From: Anders Carlsson Date: Sat, 8 Aug 2009 18:23:56 +0000 (+0000) Subject: Introduce a new PragmaPack attribute, and use it for #pragma pack. The PackedAttr... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a860e755f1f9f071b6a6a2f96128a6a258f5c331;p=clang Introduce a new PragmaPack attribute, and use it for #pragma pack. The PackedAttr now only represents __attribute__((packed)). This is necessary because #pragma pack and __attribute__((packed)) have different semantics. No functionality change yet, but this lays the groundwork for fixing a record layout bug. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@78483 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 7d3009b011..581f8af263 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -70,6 +70,7 @@ public: NSReturnsRetained, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, + PragmaPack, Pure, Regparm, ReqdWorkGroupSize, // OpenCL-specific @@ -146,24 +147,26 @@ public: \ static bool classof(const ATTR##Attr *A) { return true; } \ } -class PackedAttr : public Attr { +DEF_SIMPLE_ATTR(Packed); + +class PragmaPackAttr : public Attr { unsigned Alignment; public: - PackedAttr(unsigned alignment) : Attr(Packed), Alignment(alignment) {} + PragmaPackAttr(unsigned alignment) : Attr(PragmaPack), Alignment(alignment) {} /// getAlignment - The specified alignment in bits. unsigned getAlignment() const { return Alignment; } virtual Attr* clone(ASTContext &C) const { - return ::new (C) PackedAttr(Alignment); + return ::new (C) PragmaPackAttr(Alignment); } // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() == Packed; + return A->getKind() == PragmaPack; } - static bool classof(const PackedAttr *A) { return true; } + static bool classof(const PragmaPackAttr *A) { return true; } }; class AlignedAttr : public Attr { diff --git a/lib/AST/RecordLayoutBuilder.cpp b/lib/AST/RecordLayoutBuilder.cpp index 1d96c1a20b..8a18197a56 100644 --- a/lib/AST/RecordLayoutBuilder.cpp +++ b/lib/AST/RecordLayoutBuilder.cpp @@ -197,9 +197,11 @@ void ASTRecordLayoutBuilder::LayoutBaseNonVirtually(const CXXRecordDecl *RD) { void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) { IsUnion = D->isUnion(); - - if (const PackedAttr* PA = D->getAttr()) - StructPacking = PA->getAlignment(); + + if (D->hasAttr()) + StructPacking = 1; + if (const PragmaPackAttr *PPA = D->getAttr()) + StructPacking = PPA->getAlignment(); if (const AlignedAttr *AA = D->getAttr()) UpdateAlignment(AA->getAlignment()); @@ -240,8 +242,8 @@ void ASTRecordLayoutBuilder::Layout(const ObjCInterfaceDecl *D, NextOffset = Size; } - if (const PackedAttr *PA = D->getAttr()) - StructPacking = PA->getAlignment(); + if (D->hasAttr()) + StructPacking = 1; if (const AlignedAttr *AA = D->getAttr()) UpdateAlignment(AA->getAlignment()); @@ -273,8 +275,8 @@ void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) { // FIXME: Should this override struct packing? Probably we want to // take the minimum? - if (const PackedAttr *PA = D->getAttr()) - FieldPacking = PA->getAlignment(); + if (D->hasAttr()) + FieldPacking = 1; if (const Expr *BitWidthExpr = D->getBitWidth()) { // TODO: Need to check this algorithm on other targets! diff --git a/lib/CodeGen/CGRecordLayoutBuilder.cpp b/lib/CodeGen/CGRecordLayoutBuilder.cpp index a119d4f3a4..d3699bb992 100644 --- a/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -31,9 +31,8 @@ void CGRecordLayoutBuilder::Layout(const RecordDecl *D) { LayoutUnion(D); return; } - - if (const PackedAttr* PA = D->getAttr()) - Packed = PA->getAlignment(); + + Packed = D->hasAttr(); if (LayoutFields(D)) return; @@ -96,15 +95,8 @@ void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D, bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D, uint64_t FieldOffset) { - bool FieldPacked = Packed; - - // FIXME: Should this override struct packing? Probably we want to - // take the minimum? - if (const PackedAttr *PA = D->getAttr()) - FieldPacked = PA->getAlignment(); - // If the field is packed, then we need a packed struct. - if (!Packed && FieldPacked) + if (!Packed && D->hasAttr()) return false; if (D->isBitField()) { diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 65da7dc451..95163af111 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -507,7 +507,8 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(CFReturnsRetained); SIMPLE_ATTR(NSReturnsRetained); SIMPLE_ATTR(Overloadable); - UNSIGNED_ATTR(Packed); + SIMPLE_ATTR(Packed); + UNSIGNED_ATTR(PragmaPack); SIMPLE_ATTR(Pure); UNSIGNED_ATTR(Regparm); STRING_ATTR(Section); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 69247d3e85..0e570a61ab 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1698,10 +1698,13 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::Overloadable: break; - case Attr::Packed: - Record.push_back(cast(Attr)->getAlignment()); + case Attr::PragmaPack: + Record.push_back(cast(Attr)->getAlignment()); break; + case Attr::Packed: + break; + case Attr::Pure: break; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index ed78ec0972..44e8b44d7a 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4200,7 +4200,7 @@ CreateNewDecl: // the #pragma tokens are effectively skipped over during the // parsing of the struct). if (unsigned Alignment = getPragmaPackAlignment()) - New->addAttr(::new (Context) PackedAttr(Alignment * 8)); + New->addAttr(::new (Context) PragmaPackAttr(Alignment * 8)); } if (getLangOptions().CPlusPlus && SS.isEmpty() && Name && !Invalid) { diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 3523000590..6df8120786 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -283,7 +283,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { } if (TagDecl *TD = dyn_cast(d)) - TD->addAttr(::new (S.Context) PackedAttr(1)); + TD->addAttr(::new (S.Context) PackedAttr); else if (FieldDecl *FD = dyn_cast(d)) { // If the alignment is less than or equal to 8 bits, the packed attribute // has no effect. @@ -292,7 +292,7 @@ static void HandlePackedAttr(Decl *d, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::warn_attribute_ignored_for_field_of_type) << Attr.getName() << FD->getType(); else - FD->addAttr(::new (S.Context) PackedAttr(1)); + FD->addAttr(::new (S.Context) PackedAttr); } else S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName(); }