diff options
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 4c561653a5..6d149fe146 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -1348,12 +1348,12 @@ void RecordLayoutBuilder::LayoutFields(const RecordDecl *D) { } LastFD = FD; } - else if (Context.Target.useZeroLengthBitfieldAlignment() && - !Context.Target.useBitFieldTypeAlignment()) { + else if (!Context.Target.useBitFieldTypeAlignment() && + Context.Target.useZeroLengthBitfieldAlignment()) { FieldDecl *FD = (*Field); - if (Context.ZeroBitfieldFollowsBitfield(FD, LastFD)) + if (FD->isBitField() && + FD->getBitWidth()->EvaluateAsInt(Context).getZExtValue() == 0) ZeroLengthBitfield = FD; - LastFD = FD; } LayoutField(*Field); } @@ -1411,8 +1411,8 @@ void RecordLayoutBuilder::LayoutWideBitField(uint64_t FieldSize, setDataSize(std::max(getDataSizeInBits(), FieldSize)); FieldOffset = 0; } else { - // The bitfield is allocated starting at the next offset aligned appropriately - // for T', with length n bits. + // The bitfield is allocated starting at the next offset aligned + // appropriately for T', with length n bits. FieldOffset = llvm::RoundUpToAlignment(getDataSizeInBits(), Context.toBits(TypeAlign)); @@ -1451,19 +1451,30 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { FieldAlign = TypeSize; 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<uint64_t, unsigned> FieldInfo = - Context.getTypeInfo(ZeroLengthBitfield->getType()); - unsigned ZeroLengthBitfieldAlignment = FieldInfo.second; - // Ignore alignment of subsequent zero-length bitfields. - if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) - FieldAlign = ZeroLengthBitfieldAlignment; - if (FieldSize) - ZeroLengthBitfield = 0; + std::pair<uint64_t, unsigned> FieldInfo; + unsigned ZeroLengthBitfieldAlignment; + if (IsMsStruct) { + // 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) { + FieldInfo = Context.getTypeInfo(ZeroLengthBitfield->getType()); + ZeroLengthBitfieldAlignment = FieldInfo.second; + // Ignore alignment of subsequent zero-length bitfields. + if ((ZeroLengthBitfieldAlignment > FieldAlign) || (FieldSize == 0)) + FieldAlign = ZeroLengthBitfieldAlignment; + if (FieldSize) + ZeroLengthBitfield = 0; + } + } else { + // The alignment of a zero-length bitfield affects the alignment + // of the next member. The alignment is the max of the zero + // length bitfield's alignment and a target specific fixed value. + unsigned ZeroLengthBitfieldBoundary = + Context.Target.getZeroLengthBitfieldBoundary(); + if (ZeroLengthBitfieldBoundary > FieldAlign) + FieldAlign = ZeroLengthBitfieldBoundary; } } @@ -1476,10 +1487,11 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { // was unnecessary (-Wpacked). unsigned UnpackedFieldAlign = FieldAlign; uint64_t UnpackedFieldOffset = FieldOffset; - if (!Context.Target.useBitFieldTypeAlignment()) + if (!Context.Target.useBitFieldTypeAlignment() && !ZeroLengthBitfield) UnpackedFieldAlign = 1; - if (FieldPacked || !Context.Target.useBitFieldTypeAlignment()) + if (FieldPacked || + (!Context.Target.useBitFieldTypeAlignment() && !ZeroLengthBitfield)) FieldAlign = 1; FieldAlign = std::max(FieldAlign, D->getMaxAlignment()); UnpackedFieldAlign = std::max(UnpackedFieldAlign, D->getMaxAlignment()); @@ -1500,10 +1512,14 @@ void RecordLayoutBuilder::LayoutBitField(const FieldDecl *D) { UnpackedFieldOffset = llvm::RoundUpToAlignment(UnpackedFieldOffset, UnpackedFieldAlign); - // Padding members don't affect overall alignment. - if (!D->getIdentifier()) + // Padding members don't affect overall alignment, unless zero length bitfield + // alignment is enabled. + if (!D->getIdentifier() && !Context.Target.useZeroLengthBitfieldAlignment()) FieldAlign = UnpackedFieldAlign = 1; + if (!IsMsStruct) + ZeroLengthBitfield = 0; + // Place this field at the current location. FieldOffsets.push_back(FieldOffset); |