[CodeGen] Indirect fields can initialize a union
authorDavid Majnemer <david.majnemer@gmail.com>
Sat, 30 May 2015 09:12:07 +0000 (09:12 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Sat, 30 May 2015 09:12:07 +0000 (09:12 +0000)
The first named data member is the field used to default initialize the
union.  An IndirectFieldDecl can introduce the first named data member
of a union.

llvm-svn: 238649

clang/lib/CodeGen/CGExprConstant.cpp
clang/lib/CodeGen/CGRecordLayoutBuilder.cpp
clang/test/CodeGenCXX/pointers-to-data-members.cpp

index 73ca0cc..b90b3ab 100644 (file)
@@ -1349,8 +1349,14 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
     }
 
     // For unions, stop after the first named field.
-    if (record->isUnion() && Field->getDeclName())
-      break;
+    if (record->isUnion()) {
+      if (Field->getIdentifier())
+        break;
+      if (const auto *FieldRD =
+              dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
+        if (FieldRD->findFirstNamedDataMember())
+          break;
+    }
   }
 
   // Fill in the virtual bases, if we're working with the complete object.
index 72ecd65..c89d5cc 100644 (file)
@@ -314,9 +314,13 @@ void CGRecordLowering::lowerUnion() {
     // If this is the case, then we aught not to try and come up with a "better"
     // type, it might not be very easy to come up with a Constant which
     // correctly initializes it.
-    if (!SeenNamedMember && Field->getDeclName()) {
-      SeenNamedMember = true;
-      if (!isZeroInitializable(Field)) {
+    if (!SeenNamedMember) {
+      SeenNamedMember = Field->getIdentifier();
+      if (!SeenNamedMember)
+        if (const auto *FieldRD =
+                dyn_cast_or_null<RecordDecl>(Field->getType()->getAsTagDecl()))
+        SeenNamedMember = FieldRD->findFirstNamedDataMember();
+      if (SeenNamedMember && !isZeroInitializable(Field)) {
         IsZeroInitializable = IsZeroInitializableAsBase = false;
         StorageType = FieldType;
       }
index 0f2ddaa..94337d9 100644 (file)
@@ -285,4 +285,14 @@ S s;
 // CHECK-GLOBAL: @_ZN19FlexibleArrayMember1sE = global %"struct.FlexibleArrayMember::S" zeroinitializer, align 8
 }
 
+namespace IndirectPDM {
+union U {
+  union {
+    int U::*m;
+  };
+};
+U u;
+// CHECK-GLOBAL: @_ZN11IndirectPDM1uE = global %"union.IndirectPDM::U" { %union.anon { i64 -1 } }, align 8
+}
+
 // CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} }