From: Chris Lattner Date: Mon, 5 Jul 2010 18:03:30 +0000 (+0000) Subject: fix PR7564 a cast where the bitfield struct init code X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2bc00252d7597af32c84599076e4d14e678aaa8a;p=clang fix PR7564 a cast where the bitfield struct init code wasn't handling array padding elements right. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107621 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprConstant.cpp b/lib/CodeGen/CGExprConstant.cpp index f8e91c2272..bbd256c4f1 100644 --- a/lib/CodeGen/CGExprConstant.cpp +++ b/lib/CodeGen/CGExprConstant.cpp @@ -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(Elements.back())) + // 'or' in the bits that go into the previous byte. + llvm::Value *LastElt = Elements.back(); + if (llvm::ConstantInt *Val = dyn_cast(LastElt)) Tmp |= Val->getValue(); - else - assert(isa(Elements.back())); + else { + assert(isa(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(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(LastElt->getType()) && + "Expected array padding of undefs"); + const llvm::ArrayType *AT = cast(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(Elements.back()) && + Elements.back()->getType()->isIntegerTy(8) && + "Padding addition didn't work right"); + } + } Elements.back() = llvm::ConstantInt::get(CGM.getLLVMContext(), Tmp); diff --git a/test/CodeGen/struct-init.c b/test/CodeGen/struct-init.c index 88b57a2647..926e5a7f5d 100644 --- a/test/CodeGen/struct-init.c +++ b/test/CodeGen/struct-init.c @@ -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};