diff options
author | Warren Hunt <whunt@google.com> | 2014-04-10 22:15:18 +0000 |
---|---|---|
committer | Warren Hunt <whunt@google.com> | 2014-04-10 22:15:18 +0000 |
commit | 5d9eebfec6a02d1747e4cc1537e21814508d00e6 (patch) | |
tree | e43038c81ef552ae2b0c29b5daefed4efb761ee6 /clang/lib/AST/RecordLayoutBuilder.cpp | |
parent | 1ecafa880816cb17ee7c85ae98df9051ec4a8168 (diff) | |
download | bcm5719-llvm-5d9eebfec6a02d1747e4cc1537e21814508d00e6.tar.gz bcm5719-llvm-5d9eebfec6a02d1747e4cc1537e21814508d00e6.zip |
[MS-ABI] Fixed __declspec(align()) on bitfields under #pragma pack.
When __declspec(align()) is applied to a bitfield it affects the
alignment rather than the required alignment of the struct. The major
feature that this patch adds is that the alignment of the structure
obeys the alignment of __declspec(align()) from the bitfield over the
value specified in pragma pack.
Test cases are included.
The patch also includes some small cleanups in recordlayoutbuilder and
some cleanups to some lit tests, including line endings (but no
functionality change to lit tests)
llvm-svn: 205994
Diffstat (limited to 'clang/lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | clang/lib/AST/RecordLayoutBuilder.cpp | 65 |
1 files changed, 31 insertions, 34 deletions
diff --git a/clang/lib/AST/RecordLayoutBuilder.cpp b/clang/lib/AST/RecordLayoutBuilder.cpp index 8427eb5604d..623d164d221 100644 --- a/clang/lib/AST/RecordLayoutBuilder.cpp +++ b/clang/lib/AST/RecordLayoutBuilder.cpp @@ -2151,8 +2151,7 @@ public: void finalizeLayout(const RecordDecl *RD); /// \brief Gets the size and alignment of a base taking pragma pack and /// __declspec(align) into account. - ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout, - bool AsBase = true); + ElementInfo getAdjustedElementInfo(const ASTRecordLayout &Layout); /// \brief Gets the size and alignment of a field taking pragma pack and /// __declspec(align) into account. It also updates RequiredAlignment as a /// side effect because it is most convenient to do so here. @@ -2226,7 +2225,7 @@ public: MicrosoftRecordLayoutBuilder::ElementInfo MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( - const ASTRecordLayout &Layout, bool AsBase) { + const ASTRecordLayout &Layout) { ElementInfo Info; Info.Alignment = Layout.getAlignment(); // Respect pragma pack. @@ -2238,8 +2237,9 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( // the alignment in the case of pragam pack. Note that the required alignment // doesn't actually apply to the struct alignment at this point. Alignment = std::max(Alignment, Info.Alignment); + RequiredAlignment = std::max(RequiredAlignment, Layout.getRequiredAlignment()); Info.Alignment = std::max(Info.Alignment, Layout.getRequiredAlignment()); - Info.Size = AsBase ? Layout.getNonVirtualSize() : Layout.getSize(); + Info.Size = Layout.getNonVirtualSize(); return Info; } @@ -2253,37 +2253,30 @@ MicrosoftRecordLayoutBuilder::getAdjustedElementInfo( CharUnits FieldRequiredAlignment = Context.toCharUnitsFromBits(FD->getMaxAlignment()); // Respect attributes applied to subobjects of the field. - if (const RecordType *RT = - FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { - const ASTRecordLayout &Layout = Context.getASTRecordLayout(RT->getDecl()); - // Get the element info for a layout, respecting pack. - Info.Alignment = getAdjustedElementInfo(Layout, false).Alignment; - // Capture required alignment as a side-effect. - RequiredAlignment = std::max(RequiredAlignment, - Layout.getRequiredAlignment()); - } else { - if (FD->isBitField() && FD->getMaxAlignment() != 0) - Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); - // Respect pragma pack. - if (!MaxFieldAlignment.isZero()) - Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment); - } - // Respect packed field attribute. - if (FD->hasAttr<PackedAttr>()) - Info.Alignment = CharUnits::One(); - // Take required alignment into account. __declspec(align) on bitfields - // impacts the alignment rather than the required alignment. - if (!FD->isBitField()) { + if (FD->isBitField()) + // For some reason __declspec align impacts alignment rather than required + // alignment when it is applied to bitfields. Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); + else { + if (auto RT = + FD->getType()->getBaseElementTypeUnsafe()->getAs<RecordType>()) { + auto const &Layout = Context.getASTRecordLayout(RT->getDecl()); + EndsWithZeroSizedObject = Layout.hasZeroSizedSubObject(); + FieldRequiredAlignment = std::max(FieldRequiredAlignment, + Layout.getRequiredAlignment()); + } // Capture required alignment as a side-effect. RequiredAlignment = std::max(RequiredAlignment, FieldRequiredAlignment); } + // Respect pragma pack, attribute pack and declspec align + if (!MaxFieldAlignment.isZero()) + Info.Alignment = std::min(Info.Alignment, MaxFieldAlignment); + if (FD->hasAttr<PackedAttr>()) + Info.Alignment = CharUnits::One(); + Info.Alignment = std::max(Info.Alignment, FieldRequiredAlignment); // TODO: Add a Sema warning that MS ignores bitfield alignment in unions. - if (!(FD->isBitField() && IsUnion)) { + if (!(FD->isBitField() && IsUnion)) Alignment = std::max(Alignment, Info.Alignment); - if (!MaxFieldAlignment.isZero()) - Alignment = std::min(Alignment, MaxFieldAlignment); - } return Info; } @@ -2305,7 +2298,10 @@ void MicrosoftRecordLayoutBuilder::cxxLayout(const CXXRecordDecl *RD) { injectVFPtr(RD); if (HasOwnVFPtr || (HasVBPtr && !SharedVBPtrBase)) Alignment = std::max(Alignment, PointerInfo.Alignment); - NonVirtualSize = Size = Size.RoundUpToAlignment(Alignment); + auto RoundingAlignment = Alignment; + if (!MaxFieldAlignment.isZero()) + RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); + NonVirtualSize = Size = Size.RoundUpToAlignment(RoundingAlignment); RequiredAlignment = std::max( RequiredAlignment, Context.toCharUnitsFromBits(RD->getMaxAlignment())); layoutVirtualBases(RD); @@ -2374,9 +2370,6 @@ MicrosoftRecordLayoutBuilder::layoutNonVirtualBases(const CXXRecordDecl *RD) { HasVBPtr = true; continue; } - // Track RequiredAlignment for all bases in this pass. - RequiredAlignment = std::max(RequiredAlignment, - BaseLayout.getRequiredAlignment()); // Check fo a base to share a VBPtr with. if (!SharedVBPtrBase && BaseLayout.hasVBPtr()) { SharedVBPtrBase = BaseDecl; @@ -2633,7 +2626,11 @@ void MicrosoftRecordLayoutBuilder::finalizeLayout(const RecordDecl *RD) { DataSize = Size; if (!RequiredAlignment.isZero()) { Alignment = std::max(Alignment, RequiredAlignment); - Size = Size.RoundUpToAlignment(Alignment); + auto RoundingAlignment = Alignment; + if (!MaxFieldAlignment.isZero()) + RoundingAlignment = std::min(RoundingAlignment, MaxFieldAlignment); + RoundingAlignment = std::max(RoundingAlignment, RequiredAlignment); + Size = Size.RoundUpToAlignment(RoundingAlignment); } // Zero-sized structures have size equal to their alignment. if (Size.isZero()) { |