diff options
author | John McCall <rjmccall@apple.com> | 2011-03-24 11:26:52 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-03-24 11:26:52 +0000 |
commit | 0b7e678a11ece4288dc01aebb5b17e5eef8f8d2d (patch) | |
tree | 7a4b4707d5fcfeed3c2301e0c4d15647bf7f24c3 | |
parent | fa7b8ced6f3318879b39f44b5ace8346e979826e (diff) |
Insomniac refactoring: change how the parser allocates attributes so that
AttributeLists do not accumulate over the lifetime of parsing, but are
instead reused. Also make the arguments array not require a separate
allocation, and make availability attributes store their stuff in
augmented memory, too.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@128209 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Parse/Parser.h | 22 | ||||
-rw-r--r-- | include/clang/Sema/AttributeList.h | 352 | ||||
-rw-r--r-- | include/clang/Sema/DeclSpec.h | 88 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 175 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 36 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 20 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 12 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 41 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 16 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 6 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/AttributeList.cpp | 109 | ||||
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 1 |
16 files changed, 571 insertions, 328 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 45f1f2af45..83225cf265 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -157,7 +157,7 @@ class Parser : public CodeCompletionHandler { unsigned TemplateParameterDepth; /// Factory object for creating AttributeList objects. - AttributeList::Factory AttrFactory; + AttributeFactory AttrFactory; public: Parser(Preprocessor &PP, Sema &Actions); @@ -801,10 +801,9 @@ private: ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclSpec(Parser &P) : ParsingRAII(P) {} - ParsingDeclSpec(ParsingDeclRAIIObject &RAII) : ParsingRAII(RAII) {} + ParsingDeclSpec(Parser &P) : DeclSpec(P.AttrFactory), ParsingRAII(P) {} ParsingDeclSpec(Parser &P, ParsingDeclRAIIObject *RAII) - : ParsingRAII(P, RAII) {} + : DeclSpec(P.AttrFactory), ParsingRAII(P, RAII) {} void complete(Decl *D) { ParsingRAII.complete(D); @@ -943,6 +942,9 @@ private: //===--------------------------------------------------------------------===// // C99 6.9: External Definitions. struct ParsedAttributesWithRange : ParsedAttributes { + ParsedAttributesWithRange(AttributeFactory &factory) + : ParsedAttributes(factory) {} + SourceRange Range; }; @@ -1506,10 +1508,10 @@ private: void MaybeParseGNUAttributes(Declarator &D) { if (Tok.is(tok::kw___attribute)) { - ParsedAttributes attrs; + ParsedAttributes attrs(AttrFactory); SourceLocation endLoc; ParseGNUAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseGNUAttributes(ParsedAttributes &attrs, @@ -1522,18 +1524,18 @@ private: void MaybeParseCXX0XAttributes(Declarator &D) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrs; + ParsedAttributesWithRange attrs(AttrFactory); SourceLocation endLoc; ParseCXX0XAttributes(attrs, &endLoc); - D.addAttributes(attrs.getList(), endLoc); + D.takeAttributes(attrs, endLoc); } } void MaybeParseCXX0XAttributes(ParsedAttributes &attrs, SourceLocation *endLoc = 0) { if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) { - ParsedAttributesWithRange attrsWithRange; + ParsedAttributesWithRange attrsWithRange(AttrFactory); ParseCXX0XAttributes(attrsWithRange, endLoc); - attrs.append(attrsWithRange.getList()); + attrs.takeAllFrom(attrsWithRange); } } void MaybeParseCXX0XAttributes(ParsedAttributesWithRange &attrs, diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index 3657b44b02..8e05c62880 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -16,13 +16,13 @@ #define LLVM_CLANG_SEMA_ATTRLIST_H #include "llvm/Support/Allocator.h" -#include "clang/Sema/Ownership.h" +#include "llvm/ADT/SmallVector.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" -#include "clang/AST/Expr.h" #include <cassert> namespace clang { + class ASTContext; class IdentifierInfo; class Expr; @@ -51,87 +51,96 @@ struct AvailabilityChange { /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class AttributeList { -public: - class Factory; +class AttributeList { // TODO: This should really be called ParsedAttribute private: IdentifierInfo *AttrName; - SourceLocation AttrLoc; IdentifierInfo *ScopeName; - SourceLocation ScopeLoc; IdentifierInfo *ParmName; + SourceLocation AttrLoc; + SourceLocation ScopeLoc; SourceLocation ParmLoc; - Expr **Args; + + /// The number of expression arguments this attribute has. + /// The expressions themselves are stored after the object. unsigned NumArgs; - AttributeList *Next; - bool DeclspecAttribute, CXX0XAttribute; - // For the 'availability' attribute. - AvailabilityChange AvailabilityIntroduced; - AvailabilityChange AvailabilityDeprecated; - AvailabilityChange AvailabilityObsoleted; + /// True if Microsoft style: declspec(foo). + bool DeclspecAttribute; + + /// True if C++0x-style: [[foo]]. + bool CXX0XAttribute; /// True if already diagnosed as invalid. mutable bool Invalid; + /// True if this has the extra information associated with an + /// availability attribute. + bool IsAvailability; + + /// The next attribute in the current position. + AttributeList *NextInPosition; + + /// The next attribute allocated in the current Pool. + AttributeList *NextInPool; + + Expr **getArgsBuffer() { + return reinterpret_cast<Expr**>(this+1); + } + Expr * const *getArgsBuffer() const { + return reinterpret_cast<Expr* const *>(this+1); + } + + enum AvailabilitySlot { + IntroducedSlot, DeprecatedSlot, ObsoletedSlot + }; + + AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) { + return reinterpret_cast<AvailabilityChange*>(this+1)[index]; + } + const AvailabilityChange &getAvailabilitySlot(AvailabilitySlot index) const { + return reinterpret_cast<const AvailabilityChange*>(this+1)[index]; + } + AttributeList(const AttributeList &); // DO NOT IMPLEMENT void operator=(const AttributeList &); // DO NOT IMPLEMENT void operator delete(void *); // DO NOT IMPLEMENT ~AttributeList(); // DO NOT IMPLEMENT - AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, - bool declspec, bool cxx0x); - - AttributeList(llvm::BumpPtrAllocator &Alloc, - IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - const AvailabilityChange &Introduced, - const AvailabilityChange &Deprecated, - const AvailabilityChange &Obsoleted, - bool declspec, bool cxx0x); + + size_t allocated_size() const; + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(numArgs), + DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), Invalid(false), + IsAvailability(false), NextInPosition(0), NextInPool(0) { + if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(Expr*)); + } + + AttributeList(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + bool declspec, bool cxx0x) + : AttrName(attrName), ScopeName(scopeName), ParmName(parmName), + AttrLoc(attrLoc), ScopeLoc(scopeLoc), ParmLoc(parmLoc), + NumArgs(0), DeclspecAttribute(declspec), CXX0XAttribute(cxx0x), + Invalid(false), IsAvailability(true), NextInPosition(0), NextInPool(0) { + new (&getAvailabilitySlot(IntroducedSlot)) AvailabilityChange(introduced); + new (&getAvailabilitySlot(DeprecatedSlot)) AvailabilityChange(deprecated); + new (&getAvailabilitySlot(ObsoletedSlot)) AvailabilityChange(obsoleted); + } + + friend class AttributePool; + friend class AttributeFactory; + public: - class Factory { - llvm::BumpPtrAllocator Alloc; - public: - Factory() {} - ~Factory() {} - AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - Expr **args, unsigned numargs, bool declspec = false, bool cxx0x = false) { - AttributeList *Mem = Alloc.Allocate<AttributeList>(); - new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, - ParmName, ParmLoc, args, numargs, - declspec, cxx0x); - return Mem; - } - - AttributeList *Create(IdentifierInfo *AttrName, SourceLocation AttrLoc, - IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - IdentifierInfo *ParmName, SourceLocation ParmLoc, - const AvailabilityChange &Introduced, - const AvailabilityChange &Deprecated, - const AvailabilityChange &Obsoleted, - bool declspec = false, bool cxx0x = false) { - AttributeList *Mem = Alloc.Allocate<AttributeList>(); - new (Mem) AttributeList(Alloc, AttrName, AttrLoc, ScopeName, ScopeLoc, - ParmName, ParmLoc, Introduced, Deprecated, - Obsoleted, declspec, cxx0x); - return Mem; - } - - AttributeList* CreateIntegerAttribute(ASTContext &C, IdentifierInfo *Name, - SourceLocation TokLoc, int Arg) { - Expr* IArg = IntegerLiteral::Create(C, llvm::APInt(32, (uint64_t)Arg), - C.IntTy, TokLoc); - return Create( Name, TokLoc, 0, TokLoc, 0, TokLoc, &IArg, 1, 0); - } - }; - enum Kind { // Please keep this list alphabetized. AT_IBAction, // Clang-specific. AT_IBOutlet, // Clang-specific. @@ -242,8 +251,8 @@ public: Kind getKind() const { return getKind(getName()); } static Kind getKind(const IdentifierInfo *Name); - AttributeList *getNext() const { return Next; } - void setNext(AttributeList *N) { Next = N; } + AttributeList *getNext() const { return NextInPosition; } + void setNext(AttributeList *N) { NextInPosition = N; } /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } @@ -251,14 +260,14 @@ public: /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return Args[Arg]; + return getArgsBuffer()[Arg]; } class arg_iterator { - Expr** X; + Expr * const *X; unsigned Idx; public: - arg_iterator(Expr** x, unsigned idx) : X(x), Idx(idx) {} + arg_iterator(Expr * const *x, unsigned idx) : X(x), Idx(idx) {} arg_iterator& operator++() { ++Idx; @@ -285,27 +294,158 @@ public: }; arg_iterator arg_begin() const { - return arg_iterator(Args, 0); + return arg_iterator(getArgsBuffer(), 0); } arg_iterator arg_end() const { - return arg_iterator(Args, NumArgs); + return arg_iterator(getArgsBuffer(), NumArgs); } const AvailabilityChange &getAvailabilityIntroduced() const { assert(getKind() == AT_availability && "Not an availability attribute"); - return AvailabilityIntroduced; + return getAvailabilitySlot(IntroducedSlot); } const AvailabilityChange &getAvailabilityDeprecated() const { assert(getKind() == AT_availability && "Not an availability attribute"); - return AvailabilityDeprecated; + return getAvailabilitySlot(DeprecatedSlot); } const AvailabilityChange &getAvailabilityObsoleted() const { assert(getKind() == AT_availability && "Not an availability attribute"); - return AvailabilityObsoleted; + return getAvailabilitySlot(ObsoletedSlot); + } +}; + +/// A factory, from which one makes pools, from which one creates +/// individual attributes which are deallocated with the pool. +/// +/// Note that it's tolerably cheap to create and destroy one of +/// these as long as you don't actually allocate anything in it. +class AttributeFactory { +public: + enum { + /// The required allocation size of an availability attribute, + /// which we want to ensure is a multiple of sizeof(void*). + AvailabilityAllocSize = + sizeof(AttributeList) + + ((3 * sizeof(AvailabilityChange) + sizeof(void*) - 1) + / sizeof(void*) * sizeof(void*)) + }; + +private: + enum { + /// The number of free lists we want to be sure to support + /// inline. This is just enough that availability attributes + /// don't surpass it. It's actually very unlikely we'll see an + /// attribute that needs more than that; on x86-64 you'd need 10 + /// expression arguments, and on i386 you'd need 19. + InlineFreeListsCapacity = + 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) + }; + + llvm::BumpPtrAllocator Alloc; + + /// Free lists. The index is determined by the following formula: + /// (size - sizeof(AttributeList)) / sizeof(void*) + llvm::SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; + + // The following are the private interface used by AttributePool. + friend class AttributePool; + + /// Allocate an attribute of the given size. + void *allocate(size_t size); + + /// Reclaim all the attributes in the given pool chain, which is + /// non-empty. Note that the current implementation is safe + /// against reclaiming things which were not actually allocated + /// with the allocator, although of course it's important to make + /// sure that their allocator lives at least as long as this one. + void reclaimPool(AttributeList *head); + +public: + AttributeFactory(); + ~AttributeFactory(); +}; + +class AttributePool { + AttributeFactory &Factory; + AttributeList *Head; + + void *allocate(size_t size) { + return Factory.allocate(size); } + + AttributeList *add(AttributeList *attr) { + // We don't care about the order of the pool. + attr->NextInPool = Head; + Head = attr; + return attr; + } + + void takePool(AttributeList *pool); + +public: + /// Create a new pool for a factory. + AttributePool(AttributeFactory &factory) : Factory(factory), Head(0) {} + + /// Move the given pool's allocations to this pool. + AttributePool(AttributePool &pool) : Factory(pool.Factory), Head(pool.Head) { + pool.Head = 0; + } + + AttributeFactory &getFactory() const { return Factory; } + + void clear() { + if (Head) { + Factory.reclaimPool(Head); + Head = 0; + } + } + + /// Take the given pool's allocations and add them to this pool. + void takeAllFrom(AttributePool &pool) { + if (pool.Head) { + takePool(pool.Head); + pool.Head = 0; + } + } + + ~AttributePool() { + if (Head) Factory.reclaimPool(Head); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(sizeof(AttributeList) + + numArgs * sizeof(Expr*)); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + args, numArgs, + declspec, cxx0x)); + } + + AttributeList *create(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + bool declspec = false, bool cxx0x = false) { + void *memory = allocate(AttributeFactory::AvailabilityAllocSize); + return add(new (memory) AttributeList(attrName, attrLoc, + scopeName, scopeLoc, + parmName, parmLoc, + introduced, deprecated, obsoleted, + declspec, cxx0x)); + } + + AttributeList *createIntegerAttribute(ASTContext &C, IdentifierInfo *Name, + SourceLocation TokLoc, int Arg); }; /// addAttributeLists - Add two AttributeLists together @@ -350,7 +490,16 @@ struct CXX0XAttributeList { /// is that this will become significantly more serious. class ParsedAttributes { public: - ParsedAttributes() : list(0) {} + ParsedAttributes(AttributeFactory &factory) + : pool(factory), list(0) { + } + + ParsedAttributes(ParsedAttributes &attrs) + : pool(attrs.pool), list(attrs.list) { + attrs.list = 0; + } + + AttributePool &getPool() const { return pool; } bool empty() const { return list == 0; } @@ -361,7 +510,7 @@ public: list = newAttr; } - void append(AttributeList *newList) { + void addAll(AttributeList *newList) { if (!newList) return; AttributeList *lastInNewList = newList; @@ -376,14 +525,57 @@ public: list = newList; } - void clear() { list = 0; } + void takeAllFrom(ParsedAttributes &attrs) { + addAll(attrs.list); + attrs.list = 0; + pool.takeAllFrom(attrs.pool); + } + + void clear() { list = 0; pool.clear(); } AttributeList *getList() const { return list; } /// Returns a reference to the attribute list. Try not to introduce /// dependencies on this method, it may not be long-lived. AttributeList *&getListRef() { return list; } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + Expr **args, unsigned numArgs, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + args, numArgs, declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNew(IdentifierInfo *attrName, SourceLocation attrLoc, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *parmName, SourceLocation parmLoc, + const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + bool declspec = false, bool cxx0x = false) { + AttributeList *attr = + pool.create(attrName, attrLoc, scopeName, scopeLoc, parmName, parmLoc, + introduced, deprecated, obsoleted, declspec, cxx0x); + add(attr); + return attr; + } + + AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name, + SourceLocation loc, int arg) { + AttributeList *attr = + pool.createIntegerAttribute(C, name, loc, arg); + add(attr); + return attr; + } + + private: + mutable AttributePool pool; AttributeList *list; }; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 0e06330434..23a054a43c 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -271,7 +271,6 @@ public: }; private: - // storage-class-specifier /*SCS*/unsigned StorageClassSpec : 3; unsigned SCS_thread_specified : 1; @@ -358,7 +357,7 @@ private: void operator=(const DeclSpec&); // DO NOT IMPLEMENT public: - DeclSpec() + DeclSpec(AttributeFactory &attrFactory) : StorageClassSpec(SCS_unspecified), SCS_thread_specified(false), SCS_extern_in_linkage_spec(false), @@ -377,6 +376,7 @@ public: Friend_specified(false), Constexpr_specified(false), StorageClassSpecAsWritten(SCS_unspecified), + Attrs(attrFactory), ProtocolQualifiers(0), NumProtocolQualifiers(0), ProtocolLocs(0), @@ -581,6 +581,10 @@ public: bool isConstexprSpecified() const { return Constexpr_specified; } SourceLocation getConstexprSpecLoc() const { return ConstexprLoc; } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// AddAttributes - contatenates two attribute lists. /// The GCC attribute syntax allows for the following: /// @@ -594,9 +598,9 @@ public: /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// void addAttributes(AttributeList *AL) { - Attrs.append(AL); + Attrs.addAll(AL); } - void aetAttributes(AttributeList *AL) { + void setAttributes(AttributeList *AL) { Attrs.set(AL); } @@ -608,14 +612,12 @@ public: /// TakeAttributes - Return the current attribute list and remove them from /// the DeclSpec so that it doesn't own them. ParsedAttributes takeAttributes() { - ParsedAttributes saved = Attrs; - Attrs.clear(); - return saved; + // The non-const "copy" constructor clears the operand automatically. + return Attrs; } void takeAttributesFrom(ParsedAttributes &attrs) { - Attrs.append(attrs.getList()); - attrs.clear(); + Attrs.takeAllFrom(attrs); } typedef Decl * const *ProtocolQualifierListTy; @@ -1197,8 +1199,7 @@ struct DeclaratorChunk { static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, - SourceLocation RestrictQualLoc, - const ParsedAttributes &attrs) { + SourceLocation RestrictQualLoc) { DeclaratorChunk I; I.Kind = Pointer; I.Loc = Loc; @@ -1206,35 +1207,33 @@ struct DeclaratorChunk { I.Ptr.ConstQualLoc = ConstQualLoc.getRawEncoding(); I.Ptr.VolatileQualLoc = VolatileQualLoc.getRawEncoding(); I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); - I.Ptr.AttrList = attrs.getList(); + I.Ptr.AttrList = 0; return I; } /// getReference - Return a DeclaratorChunk for a reference. /// static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs, bool lvalue) { DeclaratorChunk I; I.Kind = Reference; I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = attrs.getList(); + I.Ref.AttrList = 0; return I; } /// getArray - Return a DeclaratorChunk for an array. /// static DeclaratorChunk getArray(unsigned TypeQuals, - const ParsedAttributes &attrs, bool isStatic, bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { DeclaratorChunk I; I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = attrs.getList(); + I.Arr.AttrList = 0; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1244,8 +1243,7 @@ struct DeclaratorChunk { /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. /// "TheDeclarator" is the declarator that this will be added to. - static DeclaratorChunk getFunction(const ParsedAttributes &attrs, - bool hasProto, bool isVariadic, + static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, SourceLocation EllipsisLoc, ParamInfo *ArgInfo, unsigned NumArgs, unsigned TypeQuals, @@ -1265,25 +1263,24 @@ struct DeclaratorChunk { /// getBlockPointer - Return a DeclaratorChunk for a block. /// - static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc, - const ParsedAttributes &attrs) { + static DeclaratorChunk getBlockPointer(unsigned TypeQuals, + SourceLocation Loc) { DeclaratorChunk I; I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = attrs.getList(); + I.Cls.AttrList = 0; return I; } static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, unsigned TypeQuals, - SourceLocation Loc, - const ParsedAttributes &attrs) { + SourceLocation Loc) { DeclaratorChunk I; I.Kind = MemberPointer; I.Loc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = attrs.getList(); + I.Mem.AttrList = 0; new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); return I; } @@ -1352,8 +1349,8 @@ private: /// GroupingParens - Set by Parser::ParseParenDeclarator(). bool GroupingParens : 1; - /// AttrList - Attributes. - AttributeList *AttrList; + /// Attrs - Attributes. + ParsedAttributes Attrs; /// AsmLabel - The asm label, if specified. Expr *AsmLabel; @@ -1377,8 +1374,8 @@ public: Declarator(const DeclSpec &ds, TheContext C) : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), - GroupingParens(false), AttrList(0), AsmLabel(0), - InlineParamsUsed(false), Extension(false) { + GroupingParens(false), Attrs(ds.getAttributePool().getFactory()), + AsmLabel(0), InlineParamsUsed(false), Extension(false) { } ~Declarator() { @@ -1396,6 +1393,10 @@ public: /// be shared or when in error recovery etc. DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); } + AttributePool &getAttributePool() const { + return Attrs.getPool(); + } + /// getCXXScopeSpec - Return the C++ scope specifier (global scope or /// nested-name-specifier) that is part of the declarator-id. const CXXScopeSpec &getCXXScopeSpec() const { return SS; } @@ -1445,7 +1446,7 @@ public: for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) DeclTypeInfo[i].destroy(); DeclTypeInfo.clear(); - AttrList = 0; + Attrs.clear(); AsmLabel = 0; InlineParamsUsed = false; } @@ -1552,8 +1553,13 @@ public: /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. - void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + void AddTypeInfo(const DeclaratorChunk &TI, + ParsedAttributes &attrs, + SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); + DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + getAttributePool().takeAllFrom(attrs.getPool()); + if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } @@ -1633,28 +1639,26 @@ public: return const_cast<Declarator*>(this)->getFunctionTypeInfo(); } - /// AddAttributes - simply adds the attribute list to the Declarator. + /// takeAttributes - Takes attributes from the given parsed-attributes + /// set and add them to this declarator. + /// /// These examples both add 3 attributes to "var": /// short int var __attribute__((aligned(16),common,deprecated)); /// short int x, __attribute__((aligned(16)) var /// __attribute__((common,deprecated)); /// /// Also extends the range of the declarator. - void addAttributes(AttributeList *alist, SourceLocation LastLoc) { - AttrList = addAttributeLists(AttrList, alist); - - if (!LastLoc.isInvalid()) - SetRangeEnd(LastLoc); - } + void takeAttributes(ParsedAttributes &attrs, SourceLocation lastLoc) { + Attrs.takeAllFrom(attrs); - void addAttributes(const ParsedAttributes &attrs) { - addAttributes(attrs.getList(), SourceLocation()); + if (!lastLoc.isInvalid()) + SetRangeEnd(lastLoc); } - const AttributeList *getAttributes() const { return AttrList; } - AttributeList *getAttributes() { return AttrList; } + const AttributeList *getAttributes() const { return Attrs.getList(); } + AttributeList *getAttributes() { return Attrs.getList(); } - AttributeList *&getAttrListRef() { return AttrList; } + AttributeList *&getAttrListRef() { return Attrs.getListRef(); } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6928d0d6d0..976e60f0c9 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -33,7 +33,7 @@ using namespace clang; TypeResult Parser::ParseTypeName(SourceRange *Range, Declarator::TheContext Context) { // Parse the common declaration-specifiers piece. - DeclSpec DS; + DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. @@ -126,8 +126,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, if (Tok.is(tok::r_paren)) { // __attribute__(( mode(byte) )) ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - ParmName, ParmLoc, 0, 0)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + ParmName, ParmLoc, 0, 0); } else if (Tok.is(tok::comma)) { ConsumeToken(); // __attribute__(( format(printf, 1, 2) )) @@ -150,9 +150,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, - AttrNameLoc, ParmName, ParmLoc, - ArgExprs.take(), ArgExprs.size())); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + ParmName, ParmLoc, ArgExprs.take(), ArgExprs.size()); } } } else { // not an identifier @@ -161,8 +160,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // parse a possibly empty comma separated list of expressions // __attribute__(( nonnull() )) ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0)); + attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); break; case tok::kw_char: case tok::kw_wchar_t: @@ -179,9 +178,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, case tok::kw_void: case tok::kw_typeof: { AttributeList *attr - = AttrFactory.Create(AttrName, AttrNameLoc, 0, AttrNameLoc, - 0, SourceLocation(), 0, 0); - attrs.add(attr); + = attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc, + 0, SourceLocation(), 0, 0); if (attr->getKind() == AttributeList::AT_IBOutletCollection) Diag(Tok, diag::err_iboutletcollection_builtintype); // If it's a builtin type name, eat it and expect a rparen @@ -213,16 +211,16 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, // Match the ')'. if (ArgExprsOk && Tok.is(tok::r_paren)) { ConsumeParen(); // ignore the right paren loc for now - attrs.add(AttrFactory.Create(AttrName, AttrNameLoc, 0, - AttrNameLoc, 0, SourceLocation(), - ArgExprs.take(), ArgExprs.size())); + attrs.addNew(AttrName, AttrNameLoc, 0, |