diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/AST/RecordLayoutBuilder.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/AST/RecordLayoutBuilder.cpp')
-rw-r--r-- | lib/AST/RecordLayoutBuilder.cpp | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index d5df63f..4dfffc4 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -789,8 +789,8 @@ protected: void setDataSize(CharUnits NewSize) { DataSize = Context.toBits(NewSize); } void setDataSize(uint64_t NewSize) { DataSize = NewSize; } - RecordLayoutBuilder(const RecordLayoutBuilder&); // DO NOT IMPLEMENT - void operator=(const RecordLayoutBuilder&); // DO NOT IMPLEMENT + RecordLayoutBuilder(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; + void operator=(const RecordLayoutBuilder &) LLVM_DELETED_FUNCTION; public: static const CXXMethodDecl *ComputeKeyFunction(const CXXRecordDecl *RD); }; @@ -1557,6 +1557,13 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { bool Allowed = EmptySubobjects->CanPlaceBaseAtOffset(Base, Offset); (void)Allowed; assert(Allowed && "Base subobject externally placed at overlapping offset"); + + if (InferAlignment && Offset < getDataSize().RoundUpToAlignment(BaseAlign)){ + // The externally-supplied base offset is before the base offset we + // computed. Assume that the structure is packed. + Alignment = CharUnits::One(); + InferAlignment = false; + } } if (!Base->Class->isEmpty()) { @@ -1574,12 +1581,12 @@ CharUnits RecordLayoutBuilder::LayoutBase(const BaseSubobjectInfo *Base) { } void RecordLayoutBuilder::InitializeLayout(const Decl *D) { - if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) + if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) { IsUnion = RD->isUnion(); + IsMsStruct = RD->isMsStruct(Context); + } - Packed = D->hasAttr<PackedAttr>(); - - IsMsStruct = D->hasAttr<MsStructAttr>(); + Packed = D->hasAttr<PackedAttr>(); // Honor the default struct packing maximum alignment flag. if (unsigned DefaultMaxFieldAlignment = Context.getLangOpts().PackStruct) { @@ -1616,7 +1623,6 @@ void RecordLayoutBuilder::InitializeLayout(const Decl *D) { if (ExternalLayout) { if (ExternalAlign > 0) { Alignment = Context.toCharUnitsFromBits(ExternalAlign); - UnpackedAlignment = Alignment; } else { // The external source didn't have alignment information; infer it. InferAlignment = true; @@ -2085,7 +2091,7 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { ZeroLengthBitfield = 0; } - if (Context.getLangOpts().MSBitfields || IsMsStruct) { + if (IsMsStruct) { // If MS bitfield layout is required, figure out what type is being // laid out and align the field to the width of that type. @@ -2166,11 +2172,6 @@ void RecordLayoutBuilder::LayoutField(const FieldDecl *D) { } void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { - if (ExternalLayout) { - setSize(ExternalSize); - return; - } - // In C++, records cannot be of size 0. if (Context.getLangOpts().CPlusPlus && getSizeInBits() == 0) { if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { @@ -2184,20 +2185,37 @@ void RecordLayoutBuilder::FinishLayout(const NamedDecl *D) { setSize(CharUnits::One()); } + // Finally, round the size of the record up to the alignment of the + // record itself. + uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; + uint64_t UnpackedSizeInBits = + llvm::RoundUpToAlignment(getSizeInBits(), + Context.toBits(UnpackedAlignment)); + CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); + uint64_t RoundedSize + = llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment)); + + if (ExternalLayout) { + // If we're inferring alignment, and the external size is smaller than + // our size after we've rounded up to alignment, conservatively set the + // alignment to 1. + if (InferAlignment && ExternalSize < RoundedSize) { + Alignment = CharUnits::One(); + InferAlignment = false; + } + setSize(ExternalSize); + return; + } + + // MSVC doesn't round up to the alignment of the record with virtual bases. if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (isMicrosoftCXXABI() && RD->getNumVBases()) return; } - // Finally, round the size of the record up to the alignment of the - // record itself. - uint64_t UnpaddedSize = getSizeInBits() - UnfilledBitsInLastByte; - uint64_t UnpackedSizeInBits = - llvm::RoundUpToAlignment(getSizeInBits(), - Context.toBits(UnpackedAlignment)); - CharUnits UnpackedSize = Context.toCharUnitsFromBits(UnpackedSizeInBits); - setSize(llvm::RoundUpToAlignment(getSizeInBits(), Context.toBits(Alignment))); + // Set the size to the final size. + setSize(RoundedSize); unsigned CharBitNum = Context.getTargetInfo().getCharWidth(); if (const RecordDecl *RD = dyn_cast<RecordDecl>(D)) { @@ -2255,7 +2273,7 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, if (InferAlignment && ExternalFieldOffset < ComputedOffset) { // The externally-supplied field offset is before the field offset we // computed. Assume that the structure is packed. - Alignment = CharUnits::fromQuantity(1); + Alignment = CharUnits::One(); InferAlignment = false; } @@ -2263,6 +2281,20 @@ RecordLayoutBuilder::updateExternalFieldOffset(const FieldDecl *Field, return ExternalFieldOffset; } +/// \brief Get diagnostic %select index for tag kind for +/// field padding diagnostic message. +/// WARNING: Indexes apply to particular diagnostics only! +/// +/// \returns diagnostic %select index. +static unsigned getPaddingDiagFromTagKind(TagTypeKind Tag) { + switch (Tag) { + case TTK_Struct: return 0; + case TTK_Interface: return 1; + case TTK_Class: return 2; + default: llvm_unreachable("Invalid tag kind for field padding diagnostic!"); + } +} + void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, uint64_t UnpaddedOffset, uint64_t UnpackedOffset, @@ -2291,14 +2323,14 @@ void RecordLayoutBuilder::CheckFieldPadding(uint64_t Offset, } if (D->getIdentifier()) Diag(D->getLocation(), diag::warn_padded_struct_field) - << (D->getParent()->isStruct() ? 0 : 1) // struct|class + << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) << Context.getTypeDeclType(D->getParent()) << PadSize << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1) // plural or not << D->getIdentifier(); else Diag(D->getLocation(), diag::warn_padded_struct_anon_field) - << (D->getParent()->isStruct() ? 0 : 1) // struct|class + << getPaddingDiagFromTagKind(D->getParent()->getTagKind()) << Context.getTypeDeclType(D->getParent()) << PadSize << (InBits ? 1 : 0) /*(byte|bit)*/ << (PadSize > 1); // plural or not @@ -2508,8 +2540,8 @@ ASTContext::getObjCLayout(const ObjCInterfaceDecl *D, assert(D && D->isThisDeclarationADefinition() && "Invalid interface decl!"); // Look up this layout, if already laid out, return what we have. - ObjCContainerDecl *Key = - Impl ? (ObjCContainerDecl*) Impl : (ObjCContainerDecl*) D; + const ObjCContainerDecl *Key = + Impl ? (const ObjCContainerDecl*) Impl : (const ObjCContainerDecl*) D; if (const ASTRecordLayout *Entry = ObjCLayouts[Key]) return *Entry; |