]> granicus.if.org Git - clang/commitdiff
fix PR7564 a cast where the bitfield struct init code
authorChris Lattner <sabre@nondot.org>
Mon, 5 Jul 2010 18:03:30 +0000 (18:03 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 5 Jul 2010 18:03:30 +0000 (18:03 +0000)
wasn't handling array padding elements right.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107621 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExprConstant.cpp
test/CodeGen/struct-init.c

index f8e91c2272bcc62159046ef6fccf7d5b83fe40a0..bbd256c4f1fa97d95f123593eb681c2ea6e835eb 100644 (file)
@@ -190,11 +190,38 @@ void ConstStructBuilder::AppendBitField(const FieldDecl *Field,
       Tmp = Tmp.shl(8 - BitsInPreviousByte);
     }
 
-    // Or in the bits that go into the previous byte.
-    if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(Elements.back()))
+    // 'or' in the bits that go into the previous byte.
+    llvm::Value *LastElt = Elements.back();
+    if (llvm::ConstantInt *Val = dyn_cast<llvm::ConstantInt>(LastElt))
       Tmp |= Val->getValue();
-    else
-      assert(isa<llvm::UndefValue>(Elements.back()));
+    else {
+      assert(isa<llvm::UndefValue>(LastElt));
+      // If there is an undef field that we're adding to, it can either be a
+      // scalar undef (in which case, we just replace it with our field) or it
+      // is an array.  If it is an array, we have to pull one byte off the
+      // array so that the other undef bytes stay around.
+      if (!isa<llvm::IntegerType>(LastElt->getType())) {
+        // The undef padding will be a multibyte array, create a new smaller
+        // padding and then an hole for our i8 to get plopped into.
+        assert(isa<llvm::ArrayType>(LastElt->getType()) &&
+               "Expected array padding of undefs");
+        const llvm::ArrayType *AT = cast<llvm::ArrayType>(LastElt->getType());
+        assert(AT->getElementType()->isIntegerTy(8) &&
+               AT->getNumElements() != 0 &&
+               "Expected non-empty array padding of undefs");
+        
+        // Remove the padding array.
+        NextFieldOffsetInBytes -= AT->getNumElements();
+        Elements.pop_back();
+        
+        // Add the padding back in two chunks.
+        AppendPadding(AT->getNumElements()-1);
+        AppendPadding(1);
+        assert(isa<llvm::UndefValue>(Elements.back()) &&
+               Elements.back()->getType()->isIntegerTy(8) &&
+               "Padding addition didn't work right");
+      }
+    }
 
     Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp);
 
index 88b57a26478a4e59c9d12dee484c2f6e506a6e90..926e5a7f5dd9b64bd51a5043e22dc43149463977 100644 (file)
@@ -10,3 +10,11 @@ char a;
 const zend_ini_entry ini_entries[] = {
   {  ((char*)&((zend_ini_entry*)0)->mh_arg1 - (char*)(void*)0)},
 };
+
+// PR7564
+struct GLGENH {
+  int : 27;
+  int EMHJAA : 1;
+};
+
+struct GLGENH ABHFBF = {1};