]> granicus.if.org Git - clang/commitdiff
Make sure we correctly zero-initialize unions containing a pointer to data member...
authorEli Friedman <eli.friedman@gmail.com>
Wed, 7 Dec 2011 01:30:11 +0000 (01:30 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 7 Dec 2011 01:30:11 +0000 (01:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146009 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 5d436619d75b42298f881e7bebb16b58ba2a2c77..48eda17b7a81df4389c47aa4d737ae74957d6b97 100644 (file)
@@ -1243,13 +1243,17 @@ static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
   for (RecordDecl::field_iterator I = record->field_begin(),
          E = record->field_end(); I != E; ++I) {
     const FieldDecl *field = *I;
-    
-    // Ignore bit fields.
-    if (field->isBitField())
-      continue;
-    
-    unsigned fieldIndex = layout.getLLVMFieldNo(field);
-    elements[fieldIndex] = CGM.EmitNullConstant(field->getType());
+
+    // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
+    // will fill in later.)
+    if (!field->isBitField()) {
+      unsigned fieldIndex = layout.getLLVMFieldNo(field);
+      elements[fieldIndex] = CGM.EmitNullConstant(field->getType());
+    }
+
+    // For unions, stop after the first named field.
+    if (record->isUnion() && field->getDeclName())
+      break;
   }
 
   // Fill in the virtual bases, if we're working with the complete object.
index 383452c79a8a64044cd749fc669bcb6428f26238..106ce10f512a456ed903df39f5b6b0b32a10f2d1 100644 (file)
@@ -531,6 +531,7 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
   CharUnits unionAlign = CharUnits::Zero();
 
   bool hasOnlyZeroSizedBitFields = true;
+  bool checkedFirstFieldZeroInit = false;
 
   unsigned fieldNo = 0;
   for (RecordDecl::field_iterator field = D->field_begin(),
@@ -542,6 +543,11 @@ void CGRecordLayoutBuilder::LayoutUnion(const RecordDecl *D) {
     if (!fieldType)
       continue;
 
+    if (field->getDeclName() && !checkedFirstFieldZeroInit) {
+      CheckZeroInitializable(field->getType());
+      checkedFirstFieldZeroInit = true;
+    }
+
     hasOnlyZeroSizedBitFields = false;
 
     CharUnits fieldAlign = CharUnits::fromQuantity(
index f0246c89b6993affeaab4aa4a6b8e5a7e198e9a4..90024e4dfed74d27f18e2a2c2df97f750badd0be 100644 (file)
@@ -230,3 +230,13 @@ namespace test4 {
   // CHECK-GLOBAL: @_ZN5test41dE = global %"struct.test4::D" { %"struct.test4::C.base" zeroinitializer, i32* null, %"struct.test4::B.base" { i32 (...)** null, i64 -1 }, %"struct.test4::A" zeroinitializer }, align 8
   D d;
 }
+
+namespace PR11487 {
+  union U
+  {
+    int U::* mptr;
+    char x[16];
+  } x;
+  // CHECK-GLOBAL: @_ZN7PR114871xE = global %"union.PR11487::U" { i64 -1, [8 x i8] zeroinitializer }, align 8
+  
+}