diff options
author | Chad Rosier <mcrosier@apple.com> | 2011-08-05 22:38:04 +0000 |
---|---|---|
committer | Chad Rosier <mcrosier@apple.com> | 2011-08-05 22:38:04 +0000 |
commit | e1a6a0e05cb4bb42c8d71332a253263f957e7dab (patch) | |
tree | 913110ed224c990cc4d090a652d5f03775693cb1 /clang/lib/AST/RecordLayoutBuilder.cpp | |
parent | 76ea84eaf48e6647ead82c7b2835aae2f44e4b6a (diff) | |
download | bcm5719-llvm-e1a6a0e05cb4bb42c8d71332a253263f957e7dab.tar.gz bcm5719-llvm-e1a6a0e05cb4bb42c8d71332a253263f957e7dab.zip |
Add support for using anonymous bitfields (e.g., int : 0) to enforce alignment.
This fixes cases where the anonymous bitfield is followed by a bitfield member.
E.g.,
struct t4
{
char foo;
long : 0;
char bar : 1;
};
rdar://9859156
llvm-svn: 136991
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 4c561653a5a..6d149fe1465 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/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); |