diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index b21ba9a65e76..e336dd771a04 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -2059,8 +2059,7 @@ unsigned FieldDecl::getFieldIndex() const { if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are ignored. - if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD) || - getASTContext().ZeroBitfieldFollowsBitfield((*i), LastFD)) { + if (getASTContext().ZeroBitfieldFollowsNonBitfield((*i), LastFD)) { ++i; continue; } diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 0770e1f15143..810f11b6e3ae 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -582,7 +582,7 @@ protected: CharUnits NonVirtualSize; CharUnits NonVirtualAlignment; - CharUnits ZeroLengthBitfieldAlignment; + FieldDecl *ZeroLengthBitfield; /// PrimaryBase - the primary base class (if one exists) of the class /// we're laying out. @@ -621,7 +621,7 @@ protected: UnfilledBitsInLastByte(0), MaxFieldAlignment(CharUnits::Zero()), DataSize(0), NonVirtualSize(CharUnits::Zero()), NonVirtualAlignment(CharUnits::One()), - ZeroLengthBitfieldAlignment(CharUnits::Zero()), PrimaryBase(0), + ZeroLengthBitfield(0), PrimaryBase(0), PrimaryBaseIsVirtual(false), FirstNearlyEmptyVBase(0) { } void Layout(const RecordDecl *D); @@ -1258,22 +1258,16 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Layout each field, for now, just sequentially, respecting alignment. In // the future, this will need to be tweakable by targets. const FieldDecl *LastFD = 0; + ZeroLengthBitfield = 0; for (RecordDecl::field_iterator Field = D->field_begin(), FieldEnd = D->field_end(); Field != FieldEnd; ++Field) { if (IsMsStruct) { - const FieldDecl *FD = (*Field); - if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) { - // FIXME. Multiple zero bitfields may follow a bitfield. - // set ZeroLengthBitfieldAlignment to max. of its - // currrent and alignment of 'FD'. - std::pair FieldInfo = - Context.getTypeInfoInChars(FD->getType()); - ZeroLengthBitfieldAlignment = FieldInfo.second; - continue; - } + FieldDecl *FD = (*Field); + if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) + ZeroLengthBitfield = FD; // Zero-length bitfields following non-bitfield members are // ignored: - if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) + else if (Context.ZeroBitfieldFollowsNonBitfield(FD, LastFD)) continue; LastFD = FD; } @@ -1355,6 +1349,21 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { std::pair FieldInfo = Context.getTypeInfo(D->getType()); uint64_t TypeSize = FieldInfo.first; unsigned FieldAlign = FieldInfo.second; + + if (ZeroLengthBitfield) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + if (ZeroLengthBitfield != D) { + std::pair FieldInfo = + Context.getTypeInfo(ZeroLengthBitfield->getType()); + unsigned ZeroLengthBitfieldAlignment = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + ZeroLengthBitfield = 0; + } + } if (FieldSize > TypeSize) { LayoutWideBitField(FieldSize, TypeSize, FieldPacked, D); @@ -1455,9 +1464,19 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { Context.getTypeInfoInChars(D->getType()); FieldSize = FieldInfo.first; FieldAlign = FieldInfo.second; - if (ZeroLengthBitfieldAlignment > FieldAlign) - FieldAlign = ZeroLengthBitfieldAlignment; - ZeroLengthBitfieldAlignment = CharUnits::Zero(); + + if (ZeroLengthBitfield) { + // If a zero-length bitfield is inserted after a bitfield, + // and the alignment of the zero-length bitfield is + // greater than the member that follows it, `bar', `bar' + // will be aligned as the type of the zero-length bitfield. + std::pair FieldInfo = + Context.getTypeInfoInChars(ZeroLengthBitfield->getType()); + CharUnits ZeroLengthBitfieldAlignment = FieldInfo.second; + if (ZeroLengthBitfieldAlignment > FieldAlign) + FieldAlign = ZeroLengthBitfieldAlignment; + ZeroLengthBitfield = 0; + } if (Context.getLangOptions().MSBitfields) { // If MS bitfield layout is required, figure out what type is being diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 06c4d39c4c7f..38bfcf22b740 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -628,8 +628,7 @@ CollectRecordFields(const RecordDecl *record, llvm::DIFile tunit, FieldDecl *field = *I; if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are ignored - if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD) || - CGM.getContext().ZeroBitfieldFollowsBitfield((field), LastFD)) { + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((field), LastFD)) { --fieldNo; continue; } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 463b913d9285..8054d4b0372c 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -352,8 +352,7 @@ bool ConstStructBuilder::Build(InitListExpr *ILE) { if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are // ignored: - if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD) || - CGM.getContext().ZeroBitfieldFollowsBitfield((*Field), LastFD)) { + if (CGM.getContext().ZeroBitfieldFollowsNonBitfield((*Field), LastFD)) { --FieldNo; continue; } diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index a4ac390dd98c..3d9fd88613b7 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -753,8 +753,7 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Zero-length bitfields following non-bitfield members are // ignored: const FieldDecl *FD = (*Field); - if (Types.getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD) || - Types.getContext().ZeroBitfieldFollowsBitfield(FD, LastFD)) { + if (Types.getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) { --FieldNo; continue; } @@ -997,8 +996,7 @@ CGRecordLayout *CodeGenTypes::ComputeRecordLayout(const RecordDecl *D) { if (IsMsStruct) { // Zero-length bitfields following non-bitfield members are // ignored: - if (getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD) || - getContext().ZeroBitfieldFollowsBitfield(FD, LastFD)) { + if (getContext().ZeroBitfieldFollowsNonBitfield(FD, LastFD)) { --i; continue; } diff --git a/clang/test/CodeGen/ms_struct-bitfield-1.c b/clang/test/CodeGen/ms_struct-bitfield-1.c new file mode 100644 index 000000000000..10c6e2aed358 --- /dev/null +++ b/clang/test/CodeGen/ms_struct-bitfield-1.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -emit-llvm-only -triple x86_64-apple-darwin9 %s +// rdar://8823265 + +#define ATTR __attribute__((__ms_struct__)) + +struct { + unsigned int bf_1 : 12; + unsigned int : 0; + unsigned int bf_2 : 12; +} ATTR t1; +static int a1[(sizeof(t1) == 8) -1]; + +struct +{ + char foo : 4; + short : 0; + char bar; +} ATTR t2; +static int a2[(sizeof(t2) == 4) -1]; + +#pragma ms_struct on +struct +{ + char foo : 4; + short : 0; + char bar; +} t3; +#pragma ms_struct off +static int a3[(sizeof(t3) == 4) -1]; + +struct +{ + char foo : 6; + long : 0; +} ATTR t4; +static int a4[(sizeof(t4) == 8) -1]; + +struct +{ + char foo : 4; + short : 0; + char bar : 8; +} ATTR t5; +static int a5[(sizeof(t5) == 4) -1]; +