Forráskód Böngészése

[CodeGen] Indirect fields can initialize a union

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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@238649 91177308-0d34-0410-b5e6-96231b3b80d8
David Majnemer 10 éve
szülő
commit
97b6875b65

+ 8 - 2
lib/CodeGen/CGExprConstant.cpp

@@ -1349,8 +1349,14 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
     }
     }
 
 
     // For unions, stop after the first named field.
     // 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.
   // Fill in the virtual bases, if we're working with the complete object.

+ 7 - 3
lib/CodeGen/CGRecordLayoutBuilder.cpp

@@ -314,9 +314,13 @@ void CGRecordLowering::lowerUnion() {
     // If this is the case, then we aught not to try and come up with a "better"
     // 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
     // type, it might not be very easy to come up with a Constant which
     // correctly initializes it.
     // 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;
         IsZeroInitializable = IsZeroInitializableAsBase = false;
         StorageType = FieldType;
         StorageType = FieldType;
       }
       }

+ 10 - 0
test/CodeGenCXX/pointers-to-data-members.cpp

@@ -285,4 +285,14 @@ S s;
 // CHECK-GLOBAL: @_ZN19FlexibleArrayMember1sE = global %"struct.FlexibleArrayMember::S" zeroinitializer, align 8
 // 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{{.*}} }
 // CHECK-O3: attributes [[NUW]] = { nounwind readnone{{.*}} }