Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1361,11 +1361,11 @@ }; NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc); + ParsedAttributes &AccessAttrs, + ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, + const VirtSpecifiers &VS, + SourceLocation PureSpecLoc); void ParseCXXNonStaticMemberInitializer(Decl *VarD); void ParseLexedAttributes(ParsingClass &Class); void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, @@ -1406,6 +1406,15 @@ SourceRange Range; }; + struct ParsedAttributesViewWithRange : ParsedAttributesView { + ParsedAttributesViewWithRange() : ParsedAttributesView() {} + void clearListOnly() { + ParsedAttributesView::clearListOnly(); + Range = SourceRange(); + } + + SourceRange Range; + }; DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = nullptr); @@ -1921,7 +1930,8 @@ void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); void ParseMicrosoftIfExistsExternalDeclaration(); void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS); + ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS); bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, bool &InitExprsOk); bool ParseAsmOperandsOpt(SmallVectorImpl &Names, @@ -2310,14 +2320,23 @@ DeclSpec &DS, Sema::TagUseKind TUK); // FixItLoc = possible correct location for the attributes - void ProhibitAttributes(ParsedAttributesWithRange &attrs, + void ProhibitAttributes(ParsedAttributesWithRange &Attrs, SourceLocation FixItLoc = SourceLocation()) { - if (!attrs.Range.isValid()) return; - DiagnoseProhibitedAttributes(attrs, FixItLoc); - attrs.clear(); + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clear(); } - void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - SourceLocation FixItLoc); + + void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs, + SourceLocation FixItLoc = SourceLocation()) { + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clearListOnly(); + } + void DiagnoseProhibitedAttributes(const SourceRange &Range, + SourceLocation FixItLoc); // Forbid C++11 and C2x attributes that appear on certain syntactic locations // which standard permits but we don't supported yet, for example, attributes @@ -2694,7 +2713,7 @@ void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D, VirtSpecifiers &VS); DeclGroupPtrTy ParseCXXClassMemberDeclaration( - AccessSpecifier AS, AttributeList *Attr, + AccessSpecifier AS, ParsedAttributes &Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas( @@ -2850,20 +2869,17 @@ // C++ 14.1: Template Parameters [temp.param] Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none, - AttributeList *AccessAttrs = nullptr); + SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, + AccessSpecifier AS = AS_none); Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs); + ParsedAttributes &AccessAttrs, + AccessSpecifier AS); Decl *ParseSingleDeclarationAfterTemplate( - DeclaratorContext Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromParams, - SourceLocation &DeclEnd, - AccessSpecifier AS=AS_none, - AttributeList *AccessAttrs = nullptr); + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); bool ParseTemplateParameters(unsigned Depth, SmallVectorImpl &TemplateParams, SourceLocation &LAngleLoc, @@ -2906,6 +2922,7 @@ SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); //===--------------------------------------------------------------------===// Index: include/clang/Sema/AttributeList.h =================================================================== --- include/clang/Sema/AttributeList.h +++ include/clang/Sema/AttributeList.h @@ -21,6 +21,7 @@ #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/VersionTuple.h" #include @@ -181,12 +182,6 @@ const Expr *MessageExpr; - /// The next attribute in the current position. - AttributeList *NextInPosition = nullptr; - - /// The next attribute allocated in the current Pool. - AttributeList *NextInPool = nullptr; - /// Arguments, if any, are stored immediately following the object. ArgsUnion *getArgsBuffer() { return reinterpret_cast(this + 1); } ArgsUnion const *getArgsBuffer() const { @@ -433,9 +428,6 @@ static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, Syntax SyntaxUsed); - 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; } @@ -555,6 +547,7 @@ unsigned getSemanticSpelling() const; }; +class AttributePool; /// A factory, from which one makes pools, from which one creates /// individual attributes which are deallocated with the pool. /// @@ -595,7 +588,8 @@ /// Free lists. The index is determined by the following formula: /// (size - sizeof(AttributeList)) / sizeof(void*) - SmallVector FreeLists; + SmallVector, InlineFreeListsCapacity> + FreeLists; // The following are the private interface used by AttributePool. friend class AttributePool; @@ -603,12 +597,14 @@ /// Allocate an attribute of the given size. void *allocate(size_t size); + void deallocate(AttributeList *AL); + /// 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); + void reclaimPool(AttributePool &head); public: AttributeFactory(); @@ -616,21 +612,26 @@ }; class AttributePool { + friend class AttributeFactory; AttributeFactory &Factory; - AttributeList *Head = nullptr; + llvm::TinyPtrVector Attrs; 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; + Attrs.push_back(attr); return attr; } - void takePool(AttributeList *pool); + void remove(AttributeList *attr) { + assert(llvm::is_contained(Attrs, attr) && + "Can't take attribute from a pool that doesn't own it!"); + Attrs.erase(llvm::find(Attrs, attr)); + } + + void takePool(AttributePool &pool); public: /// Create a new pool for a factory. @@ -638,30 +639,22 @@ AttributePool(const AttributePool &) = delete; - ~AttributePool() { - if (Head) Factory.reclaimPool(Head); - } + ~AttributePool() { Factory.reclaimPool(*this); } /// Move the given pool's allocations to this pool. - AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) { - pool.Head = nullptr; - } + AttributePool(AttributePool &&pool) = default; AttributeFactory &getFactory() const { return Factory; } void clear() { - if (Head) { - Factory.reclaimPool(Head); - Head = nullptr; - } + Factory.reclaimPool(*this); + Attrs.clear(); } /// Take the given pool's allocations and add them to this pool. void takeAllFrom(AttributePool &pool) { - if (pool.Head) { - takePool(pool.Head); - pool.Head = nullptr; - } + takePool(pool); + pool.Attrs.clear(); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -669,12 +662,11 @@ ArgsUnion *args, unsigned numArgs, AttributeList::Syntax syntax, SourceLocation ellipsisLoc = SourceLocation()) { - void *memory = allocate(sizeof(AttributeList) - + numArgs * sizeof(ArgsUnion)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - args, numArgs, syntax, - ellipsisLoc)); + void *memory = + allocate(sizeof(AttributeList) + numArgs * sizeof(ArgsUnion)); + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, args, + numArgs, syntax, ellipsisLoc)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -683,133 +675,158 @@ const AvailabilityChange &introduced, const AvailabilityChange &deprecated, const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *MessageExpr, - AttributeList::Syntax syntax, - SourceLocation strict, const Expr *ReplacementExpr) { + SourceLocation unavailable, const Expr *MessageExpr, + AttributeList::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, - syntax, strict, ReplacementExpr)); + return add(new (memory) AttributeList( + attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, - IdentifierLoc *Param2, - IdentifierLoc *Param3, - AttributeList::Syntax syntax) { + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, AttributeList::Syntax syntax) { size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); void *memory = allocate(size); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param1, Param2, Param3, - syntax)); - } - - AttributeList *createTypeTagForDatatype( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *argumentKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, - AttributeList::Syntax syntax) { + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax)); + } + + AttributeList * + createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *argumentKind, + ParsedType matchingCType, bool layoutCompatible, + bool mustBeNull, AttributeList::Syntax syntax) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - argumentKind, matchingCType, - layoutCompatible, mustBeNull, - syntax)); + return add(new (memory) AttributeList( + attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax)); } - AttributeList *createTypeAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { + AttributeList * + createTypeAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, AttributeList::Syntax syntaxUsed) { void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - typeArg, syntaxUsed)); + return add(new (memory) AttributeList(attrName, attrRange, scopeName, + scopeLoc, typeArg, syntaxUsed)); } - AttributeList *createPropertyAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { + AttributeList * + createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + AttributeList::Syntax syntaxUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - getterId, setterId, - syntaxUsed)); + return add(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, + getterId, setterId, syntaxUsed)); } }; -/// ParsedAttributes - A collection of parsed attributes. Currently -/// we don't differentiate between the various attribute syntaxes, -/// which is basically silly. -/// -/// Right now this is a very lightweight container, but the expectation -/// is that this will become significantly more serious. -class ParsedAttributes { -public: - ParsedAttributes(AttributeFactory &factory) : pool(factory) {} - ParsedAttributes(const ParsedAttributes &) = delete; - - AttributePool &getPool() const { return pool; } +class ParsedAttributesView { + using VecTy = llvm::TinyPtrVector; + using SizeType = decltype(std::declval().size()); - bool empty() const { return list == nullptr; } +public: + bool empty() const { return AttrList.empty(); } + SizeType size() const { return AttrList.size(); } + AttributeList &operator[](SizeType pos) { return *AttrList[pos]; } + const AttributeList &operator[](SizeType pos) const { return *AttrList[pos]; } - void add(AttributeList *newAttr) { + void addAtStart(AttributeList *newAttr) { + assert(newAttr); + AttrList.insert(AttrList.begin(), newAttr); + } + void addAtEnd(AttributeList *newAttr) { assert(newAttr); - assert(newAttr->getNext() == nullptr); - newAttr->setNext(list); - list = newAttr; + AttrList.push_back(newAttr); + } + + void remove(AttributeList *ToBeRemoved) { + assert(is_contained(AttrList, ToBeRemoved) && + "Cannot remove attribute that isn't in the list"); + AttrList.erase(llvm::find(AttrList, ToBeRemoved)); } - void addAll(AttributeList *newList) { - if (!newList) return; + void clearListOnly() { AttrList.clear(); } - AttributeList *lastInNewList = newList; - while (AttributeList *next = lastInNewList->getNext()) - lastInNewList = next; + struct iterator : llvm::iterator_adaptor_base { + iterator() : iterator_adaptor_base(nullptr) {} + iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} + reference operator*() { return **I; } + friend class ParsedAttributesView; + }; + struct const_iterator + : llvm::iterator_adaptor_base { + const_iterator() : iterator_adaptor_base(nullptr) {} + const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} + + reference operator*() const { return **I; } + friend class ParsedAttributesView; + }; - lastInNewList->setNext(list); - list = newList; + void addAll(iterator B, iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); } - void addAllAtEnd(AttributeList *newList) { - if (!list) { - list = newList; - return; - } + void addAll(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); + } - AttributeList *lastInList = list; - while (AttributeList *next = lastInList->getNext()) - lastInList = next; + void addAllAtEnd(iterator B, iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); + } - lastInList->setNext(newList); + void addAllAtEnd(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); } - void set(AttributeList *newList) { - list = newList; + iterator begin() { return iterator(AttrList.begin()); } + const_iterator begin() const { return const_iterator(AttrList.begin()); } + iterator end() { return iterator(AttrList.end()); } + const_iterator end() const { return const_iterator(AttrList.end()); } + + bool hasAttribute(AttributeList::Kind K) const { + return llvm::any_of( + AttrList, [K](const AttributeList *AL) { return AL->getKind() == K; }); } +private: + VecTy AttrList; +}; + +/// ParsedAttributes - A collection of parsed attributes. Currently +/// we don't differentiate between the various attribute syntaxes, +/// which is basically silly. +/// +/// Right now this is a very lightweight container, but the expectation +/// is that this will become significantly more serious. +class ParsedAttributes : public ParsedAttributesView { +public: + ParsedAttributes(AttributeFactory &factory) : pool(factory) {} + ParsedAttributes(const ParsedAttributes &) = delete; + + AttributePool &getPool() const { return pool; } + void takeAllFrom(ParsedAttributes &attrs) { - addAll(attrs.list); - attrs.list = nullptr; + addAll(attrs.begin(), attrs.end()); + attrs.clearListOnly(); pool.takeAllFrom(attrs.pool); } - void clear() { list = nullptr; pool.clear(); } - AttributeList *getList() const { return list; } - - void clearListOnly() { list = nullptr; } - - /// 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; } + void clear() { + clearListOnly(); + pool.clear(); + } /// Add attribute with expression arguments. AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, @@ -820,7 +837,7 @@ AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, syntax, ellipsisLoc); - add(attr); + addAtStart(attr); return attr; } @@ -839,7 +856,7 @@ pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); - add(attr); + addAtStart(attr); return attr; } @@ -853,7 +870,7 @@ AttributeList *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, Param1, Param2, Param3, syntax); - add(attr); + addAtStart(attr); return attr; } @@ -869,7 +886,7 @@ scopeName, scopeLoc, argumentKind, matchingCType, layoutCompatible, mustBeNull, syntax); - add(attr); + addAtStart(attr); return attr; } @@ -881,7 +898,7 @@ AttributeList *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, typeArg, syntaxUsed); - add(attr); + addAtStart(attr); return attr; } @@ -894,13 +911,12 @@ AttributeList *attr = pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed); - add(attr); + addAtStart(attr); return attr; } private: mutable AttributePool pool; - AttributeList *list = nullptr; }; /// These constants match the enumerated choices of Index: include/clang/Sema/DeclSpec.h =================================================================== --- include/clang/Sema/DeclSpec.h +++ include/clang/Sema/DeclSpec.h @@ -739,8 +739,8 @@ /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// \endcode /// - void addAttributes(AttributeList *AL) { - Attrs.addAll(AL); + void addAttributes(ParsedAttributesView &AL) { + Attrs.addAll(AL.begin(), AL.end()); } bool hasAttributes() const { return !Attrs.empty(); } @@ -1147,11 +1147,9 @@ return SourceRange(Loc, EndLoc); } - struct TypeInfoCommon { - AttributeList *AttrList; - }; + ParsedAttributesView AttrList; - struct PointerTypeInfo : TypeInfoCommon { + struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict/unaligned/atomic. unsigned TypeQuals : 5; @@ -1174,7 +1172,7 @@ } }; - struct ReferenceTypeInfo : TypeInfoCommon { + struct ReferenceTypeInfo { /// The type qualifier: restrict. [GNU] C++ extension bool HasRestrict : 1; /// True if this is an lvalue reference, false if it's an rvalue reference. @@ -1183,7 +1181,7 @@ } }; - struct ArrayTypeInfo : TypeInfoCommon { + struct ArrayTypeInfo { /// The type qualifiers for the array: /// const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1234,7 +1232,7 @@ SourceRange Range; }; - struct FunctionTypeInfo : TypeInfoCommon { + struct FunctionTypeInfo { /// hasPrototype - This is true if the function had at least one typed /// parameter. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. @@ -1463,7 +1461,7 @@ ParsedType getTrailingReturnType() const { return TrailingReturnType; } }; - struct BlockPointerTypeInfo : TypeInfoCommon { + struct BlockPointerTypeInfo { /// For now, sema will catch these as invalid. /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1472,7 +1470,7 @@ } }; - struct MemberPointerTypeInfo : TypeInfoCommon { + struct MemberPointerTypeInfo { /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; // CXXScopeSpec has a constructor, so it can't be a direct member. @@ -1489,15 +1487,14 @@ } }; - struct PipeTypeInfo : TypeInfoCommon { - /// The access writes. - unsigned AccessWrites : 3; + struct PipeTypeInfo { + /// The access writes. + unsigned AccessWrites : 3; - void destroy() {} + void destroy() {} }; union { - TypeInfoCommon Common; PointerTypeInfo Ptr; ReferenceTypeInfo Ref; ArrayTypeInfo Arr; @@ -1522,13 +1519,8 @@ /// If there are attributes applied to this declaratorchunk, return /// them. - const AttributeList *getAttrs() const { - return Common.AttrList; - } - - AttributeList *&getAttrListRef() { - return Common.AttrList; - } + const ParsedAttributesView &getAttrs() const { return AttrList; } + ParsedAttributesView &getAttrs() { return AttrList; } /// Return a DeclaratorChunk for a pointer. static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, @@ -1546,7 +1538,6 @@ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding(); I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding(); - I.Ptr.AttrList = nullptr; return I; } @@ -1558,7 +1549,6 @@ I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = nullptr; return I; } @@ -1570,7 +1560,6 @@ I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = nullptr; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1614,7 +1603,6 @@ I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1625,7 +1613,6 @@ I.Kind = Pipe; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1637,7 +1624,6 @@ I.Loc = SS.getBeginLoc(); I.EndLoc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = nullptr; new (I.Mem.ScopeMem) CXXScopeSpec(SS); return I; } @@ -1649,7 +1635,6 @@ I.Kind = Paren; I.Loc = LParenLoc; I.EndLoc = RParenLoc; - I.Common.AttrList = nullptr; return I; } @@ -2144,17 +2129,27 @@ /// 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, - ParsedAttributes &attrs, + /// This function takes attrs by R-Value reference because it takes ownership + /// of those attributes from the parameter. + void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); - DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end()); getAttributePool().takeAllFrom(attrs.getPool()); if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } + /// 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) { + DeclTypeInfo.push_back(TI); + + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + /// Add a new innermost chunk to this declarator. void AddInnermostTypeInfo(const DeclaratorChunk &TI) { DeclTypeInfo.insert(DeclTypeInfo.begin(), TI); @@ -2395,16 +2390,15 @@ SetRangeEnd(lastLoc); } - const AttributeList *getAttributes() const { return Attrs.getList(); } - AttributeList *getAttributes() { return Attrs.getList(); } - - AttributeList *&getAttrListRef() { return Attrs.getListRef(); } + const ParsedAttributes &getAttributes() const { return Attrs; } + ParsedAttributes &getAttributes() { return Attrs; } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { - if (getAttributes() || getDeclSpec().hasAttributes()) return true; + if (!getAttributes().empty() || getDeclSpec().hasAttributes()) + return true; for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) - if (getTypeObject(i).getAttrs()) + if (!getTypeObject(i).getAttrs().empty()) return true; return false; } @@ -2412,12 +2406,9 @@ /// Return a source range list of C++11 attributes associated /// with the declarator. void getCXX11AttributeRanges(SmallVectorImpl &Ranges) { - AttributeList *AttrList = Attrs.getList(); - while (AttrList) { - if (AttrList->isCXX11Attribute()) - Ranges.push_back(AttrList->getRange()); - AttrList = AttrList->getNext(); - } + for (const AttributeList &AL : Attrs) + if (AL.isCXX11Attribute()) + Ranges.push_back(AL.getRange()); } void setAsmLabel(Expr *E) { AsmLabel = E; } Index: include/clang/Sema/Sema.h =================================================================== --- include/clang/Sema/Sema.h +++ include/clang/Sema/Sema.h @@ -2042,8 +2042,7 @@ SourceLocation RParenLoc); /// Handle a C++11 empty-declaration and attribute-declaration. - Decl *ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, SourceLocation SemiLoc); enum class ModuleDeclKind { @@ -2181,7 +2180,7 @@ Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr, + SourceLocation NameLoc, const ParsedAttributesView &Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, @@ -2191,9 +2190,9 @@ Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists); TypeResult ActOnDependentTag(Scope *S, @@ -2215,11 +2214,11 @@ InClassInitStyle InitStyle, AccessSpecifier AS); MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, - SourceLocation DeclStart, - Declarator &D, Expr *BitfieldWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr); + const AttributeList &MSPropertyAttr); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, @@ -2252,10 +2251,9 @@ tok::ObjCKeywordKind visibility); // This is used for both record definitions and ObjC interface declarations. - void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, - ArrayRef Fields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, + ArrayRef Fields, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList); /// ActOnTagStartDefinition - Invoked when we have entered the /// scope of a tag's definition (e.g., for an enumeration, class, @@ -2320,12 +2318,11 @@ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attrs, SourceLocation EqualLoc, - Expr *Val); + const ParsedAttributesView &Attrs, + SourceLocation EqualLoc, Expr *Val); void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDecl, - ArrayRef Elements, - Scope *S, AttributeList *Attr); + Decl *EnumDecl, ArrayRef Elements, Scope *S, + const ParsedAttributesView &Attr); DeclContext *getContainingDC(DeclContext *DC); @@ -3316,11 +3313,13 @@ // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); // Helper for delayed processing of attributes. - void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); - void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, + void ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList); + void ProcessDeclAttributeList(Scope *S, Decl *D, + const ParsedAttributesView &AL, bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList); + const ParsedAttributesView &AttrList); void checkUnusedDeclAttributes(Declarator &D); @@ -3386,7 +3385,8 @@ bool allowArrayTypes); /// Stmt attributes - this routine is the top level dispatcher. - StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, + StmtResult ProcessStmtAttributes(Stmt *Stmt, + const ParsedAttributesView &Attrs, SourceRange Range); void WarnConflictingTypedMethods(ObjCMethodDecl *Method, @@ -4540,11 +4540,10 @@ // Act on C++ namespaces Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *Ident, + SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl * &UsingDecl); + const ParsedAttributesView &AttrList, + UsingDirectiveDecl *&UsingDecl); void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; @@ -4585,13 +4584,11 @@ /// defined in [dcl.init.list]p2. bool isInitListConstructor(const FunctionDecl *Ctor); - Decl *ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *NamespcName, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); @@ -4622,15 +4619,11 @@ const DeclarationNameInfo &NameInfo, SourceLocation NameLoc); - NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation); + NamedDecl *BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation); NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef Expansions); @@ -4643,22 +4636,16 @@ findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, ConstructorUsingShadowDecl *DerivedShadow); - Decl *ActOnUsingDeclaration(Scope *CurScope, - AccessSpecifier AS, + Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - SourceLocation EllipsisLoc, - AttributeList *AttrList); - Decl *ActOnAliasDeclaration(Scope *CurScope, - AccessSpecifier AS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, + UnqualifiedId &Name, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList); + Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, MultiTemplateParamsArg TemplateParams, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec); + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec); /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. @@ -5719,10 +5706,9 @@ const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); - bool ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, + bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs = nullptr); + const ParsedAttributesView &Attrs); NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, @@ -5861,11 +5847,10 @@ /// conditions that are needed for the attribute to have an effect. void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); - void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, + void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, + Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void ActOnFinishCXXMemberDecls(); void ActOnFinishCXXNonNestedClass(Decl *D); @@ -6199,17 +6184,14 @@ ArrayRef ParamLists, bool IsFriend, bool &IsMemberSpecialization, bool &Invalid); - DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, - SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, + SkipBodyInfo *SkipBody = nullptr); TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, @@ -6283,14 +6265,12 @@ const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, bool AllowInjectedClassName = false); - DeclResult - ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody = nullptr); bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, TemplateDecl *PrimaryTemplate, @@ -6323,30 +6303,19 @@ bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr); DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, @@ -7931,20 +7900,14 @@ SourceLocation rAngleLoc); void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); - Decl *ActOnStartClassInterface(Scope *S, - SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + Decl *ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); void ActOnSuperClassOfClassInterface(Scope *S, SourceLocation AtInterfaceLoc, @@ -7972,24 +7935,18 @@ const ObjCList &PList); Decl *ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - Decl * const *ProtoRefNames, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); - - Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, + unsigned NumProtoRefs, const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList); + + Decl *ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); Decl *ActOnStartClassImplementation( SourceLocation AtClassImplLoc, @@ -8012,9 +7969,10 @@ ArrayRef TypeParamLists, unsigned NumElts); - DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef IdentList, - AttributeList *attrList); + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef IdentList, + const ParsedAttributesView &attrList); void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, ArrayRef ProtocolId, @@ -8149,22 +8107,21 @@ ObjCDeclSpec DeclSpec; /// ArgAttrs - Attribute list for this argument. - AttributeList *ArgAttrs; + ParsedAttributesView ArgAttrs; }; Decl *ActOnMethodDeclaration( - Scope *S, - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, Selector Sel, - // optional arguments. The number of types/arguments is obtained - // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic, bool MethodDefinition); + Scope *S, + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic, bool MethodDefinition); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, @@ -10085,7 +10042,7 @@ /// will get it wrong. Returns CFT_Host if D is null. CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr); + CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); /// Gets the CUDA target for the current context. CUDAFunctionTarget CurrentCUDATarget() { Index: lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- lib/Parse/ParseCXXInlineMethods.cpp +++ lib/Parse/ParseCXXInlineMethods.cpp @@ -22,12 +22,10 @@ /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. -NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc) { +NamedDecl *Parser::ParseCXXInlineMethodDef( + AccessSpecifier AS, ParsedAttributes &AccessAttrs, ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers &VS, + SourceLocation PureSpecLoc) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); Index: lib/Parse/ParseDecl.cpp =================================================================== --- lib/Parse/ParseDecl.cpp +++ lib/Parse/ParseDecl.cpp @@ -53,7 +53,7 @@ // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); if (Attrs) - DS.addAttributes(Attrs->getList()); + DS.addAttributes(*Attrs); ParseSpecifierQualifierList(DS, AS, DSC); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; @@ -424,7 +424,7 @@ ScopeName, ScopeLoc, Syntax); break; } - return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0; + return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; } bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, @@ -562,8 +562,7 @@ // If this attribute's args were parsed, and it was expected to have // arguments but none were provided, emit a diagnostic. - const AttributeList *Attr = Attrs.getList(); - if (Attr && Attr->getMaxArgs() && !NumArgs) { + if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) { Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; return false; } @@ -1439,9 +1438,8 @@ Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } - const AttributeList *AL = Attrs.getList(); - if (OnDefinition && AL && !AL->isCXX11Attribute() && - AL->isKnownToGCC()) + if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && + Attrs.begin()->isKnownToGCC()) Diag(Tok, diag::warn_attribute_on_function_definition) << &LA.AttrName; @@ -1572,29 +1570,27 @@ << FixItHint::CreateRemoval(AttrRange); } -void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - const SourceLocation CorrectLocation) { +void Parser::DiagnoseProhibitedAttributes( + const SourceRange &Range, const SourceLocation CorrectLocation) { if (CorrectLocation.isValid()) { - CharSourceRange AttrRange(attrs.Range, true); + CharSourceRange AttrRange(Range, true); Diag(CorrectLocation, diag::err_attributes_misplaced) << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) << FixItHint::CreateRemoval(AttrRange); } else - Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; + Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range; } void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { - for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { - if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute()) + for (const AttributeList &AL : Attrs) { + if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; - if (Attr->getKind() == AttributeList::UnknownAttribute) - Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) - << Attr->getName(); + if (AL.getKind() == AttributeList::UnknownAttribute) + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); else { - Diag(Attr->getLoc(), DiagID) - << Attr->getName(); - Attr->setInvalid(); + Diag(AL.getLoc(), DiagID) << AL.getName(); + AL.setInvalid(); } } } @@ -1612,47 +1608,19 @@ if (TUK == Sema::TUK_Reference) return; - ParsedAttributes &PA = DS.getAttributes(); - AttributeList *AL = PA.getList(); - AttributeList *Prev = nullptr; - AttributeList *TypeAttrHead = nullptr; - AttributeList *TypeAttrTail = nullptr; - while (AL) { - AttributeList *Next = AL->getNext(); - - if ((AL->getKind() == AttributeList::AT_Aligned && - AL->isDeclspecAttribute()) || - AL->isMicrosoftAttribute()) { - // Stitch the attribute into the tag's attribute list. - if (TypeAttrTail) - TypeAttrTail->setNext(AL); - else - TypeAttrHead = AL; - TypeAttrTail = AL; - TypeAttrTail->setNext(nullptr); - - // Remove the attribute from the variable's attribute list. - if (Prev) { - // Set the last variable attribute's next attribute to be the attribute - // after the current one. - Prev->setNext(Next); - } else { - // Removing the head of the list requires us to reset the head to the - // next attribute. - PA.set(Next); - } - } else { - Prev = AL; - } + llvm::SmallVector ToBeMoved; - AL = Next; + for (AttributeList &AL : DS.getAttributes()) { + if ((AL.getKind() == AttributeList::AT_Aligned && + AL.isDeclspecAttribute()) || + AL.isMicrosoftAttribute()) + ToBeMoved.push_back(&AL); } - // Find end of type attributes Attrs and add NewTypeAttributes in the same - // order they were in originally. (Remember, in AttributeList things earlier - // in source order are later in the list, since new attributes are added to - // the front of the list.) - Attrs.addAllAtEnd(TypeAttrHead); + for (AttributeList *AL : ToBeMoved) { + DS.getAttributes().remove(AL); + Attrs.addAtEnd(AL); + } } /// ParseDeclaration - Parse a full 'declaration', which consists of @@ -1684,7 +1652,7 @@ case tok::kw_template: case tok::kw_export: ProhibitAttributes(attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd); + SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. @@ -4077,10 +4045,8 @@ // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); - Actions.ActOnFields(getCurScope(), - RecordLoc, TagDecl, FieldDecls, - T.getOpenLocation(), T.getCloseLocation(), - attrs.getList()); + Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, + T.getOpenLocation(), T.getCloseLocation(), attrs); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } @@ -4391,8 +4357,8 @@ unsigned DiagID; Decl *TagDecl = Actions.ActOnTag( getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, - IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, + attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, @@ -4533,8 +4499,8 @@ // Install the enumerator constant into EnumDecl. Decl *EnumConstDecl = Actions.ActOnEnumConstant( - getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - attrs.getList(), EqualLoc, AssignedVal.get()); + getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs, + EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); @@ -4586,10 +4552,8 @@ ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - Actions.ActOnEnumBody(StartLoc, T.getRange(), - EnumDecl, EnumConstantDecls, - getCurScope(), - attrs.getList()); + Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls, + getCurScope(), attrs); // Now handle enum constant availability diagnostics. assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); @@ -5384,10 +5348,10 @@ // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. - D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - DS.getLocEnd()), - DS.getAttributes(), - /* Don't replace range end. */SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getMemberPointer( + SS, DS.getTypeQualifiers(), DS.getLocEnd()), + std::move(DS.getAttributes()), + /* Don't replace range end. */ SourceLocation()); return; } } @@ -5400,7 +5364,7 @@ D.AddTypeInfo( DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), - DS.getAttributes(), SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } // Not a pointer, C++ reference, or block. @@ -5432,20 +5396,16 @@ ParseDeclaratorInternal(D, DirectDeclParser); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, - DS.getConstSpecLoc(), - DS.getVolatileSpecLoc(), - DS.getRestrictSpecLoc(), - DS.getAtomicSpecLoc(), - DS.getUnalignedSpecLoc()), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getPointer( + DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), + DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(), + DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), + std::move(DS.getAttributes()), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo( + DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc), + std::move(DS.getAttributes()), SourceLocation()); } else { // Is a reference DeclSpec DS(AttrFactory); @@ -5500,8 +5460,7 @@ // Remember that we parsed a reference type. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, Kind == tok::amp), - DS.getAttributes(), - SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } } @@ -6009,9 +5968,9 @@ ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. T.consumeClose(); - D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(), - T.getCloseLocation()), - attrs, T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()), + std::move(attrs), T.getCloseLocation()); D.setGroupingParens(hadGroupingParens); @@ -6241,28 +6200,19 @@ } // Remember that we parsed a function type, and remember the attributes. - D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, - IsAmbiguous, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - RefQualifierIsLValueRef, - RefQualifierLoc, ConstQualifierLoc, - VolatileQualifierLoc, - RestrictQualifierLoc, - /*MutableLoc=*/SourceLocation(), - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - ExceptionSpecTokens, - DeclsInPrototype, - StartLoc, LocalEndLoc, D, - TrailingReturnType), - FnAttrs, EndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), RefQualifierIsLValueRef, + RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, + RestrictQualifierLoc, + /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange, + DynamicExceptions.data(), DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + ExceptionSpecTokens, DeclsInPrototype, StartLoc, + LocalEndLoc, D, TrailingReturnType), + std::move(FnAttrs), EndLoc); } /// ParseRefQualifier - Parses a member function ref-qualifier. Returns @@ -6584,7 +6534,7 @@ D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr, T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -6597,11 +6547,10 @@ MaybeParseCXX11Attributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, - ExprRes.get(), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(), T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::code_completion) { Actions.CodeCompleteBracketDeclarator(getCurScope()); @@ -6674,12 +6623,11 @@ MaybeParseCXX11Attributes(DS.getAttributes()); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), - StaticLoc.isValid(), isStar, - NumElements.get(), - T.getOpenLocation(), - T.getCloseLocation()), - DS.getAttributes(), T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), + isStar, NumElements.get(), T.getOpenLocation(), + T.getCloseLocation()), + std::move(DS.getAttributes()), T.getCloseLocation()); } /// Diagnose brackets before an identifier. @@ -6731,18 +6679,15 @@ if (NeedParens) { // Create a DeclaratorChunk for the inserted parens. - ParsedAttributes attrs(AttrFactory); SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); - D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs, + D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), SourceLocation()); } // Adding back the bracket info to the end of the Declarator. for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) { const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i); - ParsedAttributes attrs(AttrFactory); - attrs.set(Chunk.Common.AttrList); - D.AddTypeInfo(Chunk, attrs, SourceLocation()); + D.AddTypeInfo(Chunk, SourceLocation()); } // The missing identifier would have been diagnosed in ParseDirectDeclarator. Index: lib/Parse/ParseDeclCXX.cpp =================================================================== --- lib/Parse/ParseDeclCXX.cpp +++ lib/Parse/ParseDeclCXX.cpp @@ -183,10 +183,9 @@ ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, - IdentLoc, Ident, T.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, + T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -233,11 +232,10 @@ // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), - NamespaceLoc[index], IdentLoc[index], - Ident[index], Tracker.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], + Ident[index], Tracker.getOpenLocation(), attrs, + ImplicitUsingDirectiveDecl); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -543,7 +541,7 @@ SkipUntil(tok::semi); return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, - IdentLoc, NamespcName, attrs.getList()); + IdentLoc, NamespcName, attrs); } /// Parse a using-declarator (or the identifier in a C++11 alias-declaration). @@ -711,7 +709,7 @@ Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, D.TypenameLoc, D.SS, D.Name, - D.EllipsisLoc, Attrs.getList()); + D.EllipsisLoc, Attrs); if (UD) DeclsInGroup.push_back(UD); } @@ -813,8 +811,8 @@ TemplateParams ? TemplateParams->data() : nullptr, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, D.Name, Attrs.getList(), - TypeAlias, DeclFromDeclSpec); + UsingLoc, D.Name, Attrs, TypeAlias, + DeclFromDeclSpec); } /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration. @@ -1752,24 +1750,16 @@ // This is an explicit instantiation of a class template. ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, - StartLoc, - SS, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - attrs.getList()); - - // Friend template-ids are treated as references unless - // they have template headers, in which case they're ill-formed - // (FIXME: "template friend class A::B;"). - // We diagnose this error in ActOnClassTemplateSpecialization. + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, TemplateId->Template, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, attrs); + + // Friend template-ids are treated as references unless + // they have template headers, in which case they're ill-formed + // (FIXME: "template friend class A::B;"). + // We diagnose this error in ActOnClassTemplateSpecialization. } else if (TUK == Sema::TUK_Reference || (TUK == Sema::TUK_Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { @@ -1825,7 +1815,7 @@ // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization( getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), - *TemplateId, attrs.getList(), + *TemplateId, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0), @@ -1840,24 +1830,18 @@ // ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, StartLoc, SS, Name, - NameLoc, attrs.getList()); + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, Name, NameLoc, attrs); } else if (TUK == Sema::TUK_Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitAttributes(attrs); - TagOrTempResult = - Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(), - TagType, StartLoc, SS, - Name, NameLoc, attrs.getList(), - MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] - : nullptr, - TemplateParams? TemplateParams->size() : 0)); + TagOrTempResult = Actions.ActOnTemplatedFriendTag( + getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, + NameLoc, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, + TemplateParams ? TemplateParams->size() : 0)); } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) ProhibitAttributes(attrs); @@ -1885,9 +1869,9 @@ // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag( - getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, - IsDependent, SourceLocation(), false, clang::TypeResult(), + getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + SourceLocation(), false, clang::TypeResult(), DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || DSC == DeclSpecContext::DSC_template_type_arg, @@ -1929,7 +1913,7 @@ if (!TagOrTempResult.isInvalid()) // Delayed processing of attributes. - Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); const char *PrevSpec = nullptr; unsigned DiagID; @@ -2300,12 +2284,10 @@ if (!VS.isUnset()) { // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. - const AttributeList *Attr = DeclaratorInfo.getAttributes(); - while (Attr) { - if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute()) - Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); - Attr = Attr->getNext(); - } + for (const AttributeList &AL : DeclaratorInfo.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_gcc_attribute_location); + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); } } @@ -2424,7 +2406,7 @@ /// Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - AttributeList *AccessAttrs, + ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -2492,7 +2474,8 @@ return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( getCurScope(), AS, /*UsingLoc*/ SourceLocation(), /*TypenameLoc*/ SourceLocation(), SS, Name, - /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr))); + /*EllipsisLoc*/ SourceLocation(), + /*AttrList*/ ParsedAttributesView()))); } } @@ -2512,7 +2495,7 @@ SourceLocation DeclEnd; return DeclGroupPtrTy::make( DeclGroupRef(ParseTemplateDeclarationOrSpecialization( - DeclaratorContext::MemberContext, DeclEnd, AS, AccessAttrs))); + DeclaratorContext::MemberContext, DeclEnd, AccessAttrs, AS))); } // Handle: member-declaration ::= '__extension__' member-declaration @@ -2525,12 +2508,12 @@ } ParsedAttributesWithRange attrs(AttrFactory); - ParsedAttributesWithRange FnAttrs(AttrFactory); + ParsedAttributesViewWithRange FnAttrs; // Optional C++11 attribute-specifier MaybeParseCXX11Attributes(attrs); // We need to keep these attributes for future diagnostic // before they are taken over by declaration specifier. - FnAttrs.addAll(attrs.getList()); + FnAttrs.addAll(attrs.begin(), attrs.end()); FnAttrs.Range = attrs.Range; MaybeParseMicrosoftAttributes(attrs); @@ -2777,7 +2760,7 @@ // initialize it. ThisDecl = VT->getTemplatedDecl(); - if (ThisDecl && AccessAttrs) + if (ThisDecl) Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } @@ -3014,7 +2997,7 @@ switch (Tok.getKind()) { case tok::kw___if_exists: case tok::kw___if_not_exists: - ParseMicrosoftIfExistsClassDeclaration(TagType, AS); + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS); return nullptr; case tok::semi: @@ -3080,8 +3063,7 @@ Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected); } - if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, - AccessAttrs.getList())) { + if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) { // found another attribute than only annotations AccessAttrs.clear(); } @@ -3094,7 +3076,7 @@ TagDecl); default: - return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3282,9 +3264,8 @@ if (TagDecl) Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, - T.getOpenLocation(), - T.getCloseLocation(), - attrs.getList()); + T.getOpenLocation(), + T.getCloseLocation(), attrs); // C++11 [class.mem]p2: // Within the class member-specification, the class is regarded as complete @@ -3893,25 +3874,26 @@ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); - const AttributeList *Attr = Attrs.getList(); - if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + if (!Attrs.empty() && + IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + AttributeList &Attr = *Attrs.begin(); // If the attribute is a standard or built-in attribute and we are // parsing an argument list, we need to determine whether this attribute // was allowed to have an argument list (such as [[deprecated]]), and how // many arguments were parsed (so we can diagnose on [[deprecated()]]). - if (Attr->getMaxArgs() && !NumArgs) { + if (Attr.getMaxArgs() && !NumArgs) { // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - Attr->setInvalid(true); - } else if (!Attr->getMaxArgs()) { + Attr.setInvalid(true); + } else if (!Attr.getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the // presence of the argument list (even if empty) is diagnosed. Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - Attr->setInvalid(true); + Attr.setInvalid(true); } } return true; @@ -4221,8 +4203,9 @@ } while (Tok.is(tok::l_square)); } -void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS) { +void Parser::ParseMicrosoftIfExistsClassDeclaration( + DeclSpec::TST TagType, ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS) { IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; @@ -4252,7 +4235,8 @@ while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, + AccessAttrs, CurAS); continue; } @@ -4269,7 +4253,8 @@ SourceLocation ASLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(), + ParsedAttributesView{}); else Diag(Tok, diag::err_expected) << tok::colon; ConsumeToken(); @@ -4277,7 +4262,7 @@ } // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, nullptr); + ParseCXXClassMemberDeclaration(CurAS, AccessAttrs); } Braces.consumeClose(); Index: lib/Parse/ParseExpr.cpp =================================================================== --- lib/Parse/ParseExpr.cpp +++ lib/Parse/ParseExpr.cpp @@ -2948,33 +2948,31 @@ ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). - ParsedAttributes attrs(AttrFactory); SourceLocation NoLoc; - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, - /*IsAmbiguous=*/false, - /*RParenLoc=*/NoLoc, - /*ArgInfo=*/nullptr, - /*NumArgs=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLvalueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - CaretLoc, CaretLoc, - ParamInfo), - attrs, CaretLoc); + ParamInfo.AddTypeInfo( + DeclaratorChunk::getFunction(/*HasProto=*/true, + /*IsAmbiguous=*/false, + /*RParenLoc=*/NoLoc, + /*ArgInfo=*/nullptr, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, CaretLoc, + CaretLoc, ParamInfo), + CaretLoc); MaybeParseGNUAttributes(ParamInfo); Index: lib/Parse/ParseExprCXX.cpp =================================================================== --- lib/Parse/ParseExprCXX.cpp +++ lib/Parse/ParseExprCXX.cpp @@ -1109,12 +1109,12 @@ // after '(...)'. nvcc doesn't accept this. auto WarnIfHasCUDATargetAttr = [&] { if (getLangOpts().CUDA) - for (auto *A = Attr.getList(); A != nullptr; A = A->getNext()) - if (A->getKind() == AttributeList::AT_CUDADevice || - A->getKind() == AttributeList::AT_CUDAHost || - A->getKind() == AttributeList::AT_CUDAGlobal) - Diag(A->getLoc(), diag::warn_cuda_attr_lambda_position) - << A->getName()->getName(); + for (const AttributeList &A : Attr) + if (A.getKind() == AttributeList::AT_CUDADevice || + A.getKind() == AttributeList::AT_CUDAHost || + A.getKind() == AttributeList::AT_CUDAGlobal) + Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) + << A.getName()->getName(); }; TypeResult TrailingReturnType; @@ -1197,29 +1197,23 @@ WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - /*ExceptionSpecTokens*/nullptr, - /*DeclsInPrototype=*/None, - LParenLoc, FunLocalRangeEnd, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, + ESpecRange, DynamicExceptions.data(), + DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/ nullptr, + /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, tok::kw_constexpr) || (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { @@ -1266,31 +1260,29 @@ WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - /*LParenLoc=*/NoLoc, - /*Params=*/nullptr, - /*NumParams=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - DeclLoc, DeclEndLoc, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*Params=*/nullptr, + /*NumParams=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using @@ -2889,10 +2881,9 @@ D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.get(), - T.getOpenLocation(), + Size.get(), T.getOpenLocation(), T.getCloseLocation()), - Attrs, T.getCloseLocation()); + std::move(Attrs), T.getCloseLocation()); if (T.getCloseLocation().isInvalid()) return; Index: lib/Parse/ParseObjc.cpp =================================================================== --- lib/Parse/ParseObjc.cpp +++ lib/Parse/ParseObjc.cpp @@ -287,7 +287,7 @@ Decl *CategoryType = Actions.ActOnStartCategoryInterface( AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); @@ -353,17 +353,12 @@ if (Tok.isNot(tok::less)) Actions.ActOnTypedefedProtocols(protocols, protocolLocs, superClassId, superClassLoc); - - Decl *ClsType = - Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc, - typeParameterList, superClassId, - superClassLoc, - typeArgs, - SourceRange(typeArgsLAngleLoc, - typeArgsRAngleLoc), - protocols.data(), protocols.size(), - protocolLocs.data(), - EndProtoLoc, attrs.getList()); + + Decl *ClsType = Actions.ActOnStartClassInterface( + getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, + superClassLoc, typeArgs, + SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), + protocols.size(), protocolLocs.data(), EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); @@ -381,25 +376,21 @@ SourceLocation nullabilityLoc, bool &addedToDeclSpec) { // Create the attribute. - auto getNullabilityAttr = [&]() -> AttributeList * { - return D.getAttributePool().create( - P.getNullabilityKeyword(nullability), - SourceRange(nullabilityLoc), - nullptr, SourceLocation(), - nullptr, 0, - AttributeList::AS_ContextSensitiveKeyword); + auto getNullabilityAttr = [&](AttributePool &Pool) -> AttributeList * { + return Pool.create(P.getNullabilityKeyword(nullability), + SourceRange(nullabilityLoc), nullptr, SourceLocation(), + nullptr, 0, AttributeList::AS_ContextSensitiveKeyword); }; if (D.getNumTypeObjects() > 0) { // Add the attribute to the declarator chunk nearest the declarator. - auto nullabilityAttr = getNullabilityAttr(); - DeclaratorChunk &chunk = D.getTypeObject(0); - nullabilityAttr->setNext(chunk.getAttrListRef()); - chunk.getAttrListRef() = nullabilityAttr; + D.getTypeObject(0).getAttrs().addAtStart( + getNullabilityAttr(D.getAttributePool())); } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().addAttributes(getNullabilityAttr()); + D.getMutableDeclSpec().getAttributes().addAtStart( + getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); addedToDeclSpec = true; } } @@ -1202,18 +1193,12 @@ /// Take all the decl attributes out of the given list and add /// them to the given attribute set. -static void takeDeclAttributes(ParsedAttributes &attrs, - AttributeList *list) { - while (list) { - AttributeList *cur = list; - list = cur->getNext(); - - if (!cur->isUsedAsTypeAttr()) { - // Clear out the next pointer. We're really completely - // destroying the internal invariants of the declarator here, - // but it doesn't matter because we're done with it. - cur->setNext(nullptr); - attrs.add(cur); +static void takeDeclAttributes(ParsedAttributesView &attrs, + ParsedAttributesView &from) { + for (auto &AL : llvm::reverse(from)) { + if (!AL.isUsedAsTypeAttr()) { + from.remove(&AL); + attrs.addAtStart(&AL); } } } @@ -1227,11 +1212,10 @@ attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); // Now actually move the attributes over. - takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); + takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes()); takeDeclAttributes(attrs, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) - takeDeclAttributes(attrs, - const_cast(D.getTypeObject(i).getAttrs())); + takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs()); } /// objc-type-name: @@ -1386,13 +1370,10 @@ MaybeParseCXX11Attributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - selLoc, Sel, nullptr, - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), MethodImplKind, - false, MethodDefinition); + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, + selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, false, MethodDefinition); PD.complete(Result); return Result; } @@ -1423,7 +1404,7 @@ if (getLangOpts().ObjC2) MaybeParseGNUAttributes(paramAttrs); MaybeParseCXX11Attributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); + ArgInfo.ArgAttrs = paramAttrs; // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { @@ -1513,14 +1494,11 @@ Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - KeyLocs, Sel, &ArgInfos[0], - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), - MethodImplKind, isVariadic, MethodDefinition); - + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, + Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, isVariadic, MethodDefinition); + PD.complete(Result); return Result; } @@ -1885,9 +1863,9 @@ Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. - Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, - AllIvarDecls, - T.getOpenLocation(), T.getCloseLocation(), nullptr); + Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), + ParsedAttributesView()); } /// objc-class-instance-variables: @@ -2037,8 +2015,7 @@ if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs); } CheckNestedObjCContexts(AtLoc); @@ -2065,8 +2042,7 @@ if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return nullptr; - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs); } // Last, and definitely not least, parse a protocol declaration. @@ -2080,12 +2056,9 @@ /*consumeLastToken=*/true)) return nullptr; - Decl *ProtoType = - Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + Decl *ProtoType = Actions.ActOnStartProtocolInterface( + AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), + ProtocolLocs.data(), EndProtoLoc, attrs); ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); return Actions.ConvertDeclToDeclGroup(ProtoType); Index: lib/Parse/ParsePragma.cpp =================================================================== --- lib/Parse/ParsePragma.cpp +++ lib/Parse/ParsePragma.cpp @@ -1410,26 +1410,26 @@ return; } - if (!Attrs.getList() || Attrs.getList()->isInvalid()) { + if (Attrs.empty() || Attrs.begin()->isInvalid()) { SkipToEnd(); return; } // Ensure that we don't have more than one attribute. - if (Attrs.getList()->getNext()) { - SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); + if (Attrs.size() > 1) { + SourceLocation Loc = Attrs[1].getLoc(); Diag(Loc, diag::err_pragma_attribute_multiple_attributes); SkipToEnd(); return; } - if (!Attrs.getList()->isSupportedByPragmaAttribute()) { + AttributeList &Attribute = *Attrs.begin(); + if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); + << Attribute.getName(); SkipToEnd(); return; } - AttributeList &Attribute = *Attrs.getList(); // Parse the subject-list. if (!TryConsumeToken(tok::comma)) { Index: lib/Parse/ParseStmt.cpp =================================================================== --- lib/Parse/ParseStmt.cpp +++ lib/Parse/ParseStmt.cpp @@ -116,7 +116,7 @@ if (Attrs.empty() || Res.isInvalid()) return Res; - return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range); + return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range); } namespace { @@ -610,8 +610,8 @@ Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) - SubStmt = Actions.ProcessStmtAttributes( - SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); + SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs, + TempAttrs.Range); } else { Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } @@ -627,10 +627,8 @@ LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); - if (AttributeList *Attrs = attrs.getList()) { - Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); - attrs.clear(); - } + Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs); + attrs.clear(); return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, SubStmt.get()); @@ -2269,7 +2267,7 @@ if (Attrs.empty()) return true; - if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint) + if (Attrs.begin()->getKind() != AttributeList::AT_OpenCLUnrollHint) return true; if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { Index: lib/Parse/ParseTemplate.cpp =================================================================== --- lib/Parse/ParseTemplate.cpp +++ lib/Parse/ParseTemplate.cpp @@ -23,24 +23,19 @@ /// Parse a template declaration, explicit instantiation, or /// explicit specialization. -Decl * -Parser::ParseDeclarationStartingWithTemplate(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseDeclarationStartingWithTemplate( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { ObjCDeclContextSwitch ObjCDC(*this); if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { - return ParseExplicitInstantiation(Context, - SourceLocation(), ConsumeToken(), - DeclEnd, AS); + return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(), + DeclEnd, AccessAttrs, AS); } - return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, - AccessAttrs); + return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs, + AS); } - - /// Parse a template declaration or an explicit specialization. /// /// Template declarations include one or more template parameter lists @@ -56,11 +51,9 @@ /// /// explicit-specialization: [ C++ temp.expl.spec] /// 'template' '<' '>' declaration -Decl * -Parser::ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseTemplateDeclarationOrSpecialization( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(Tok.isOneOf(tok::kw_export, tok::kw_template) && "Token does not start a template declaration."); @@ -149,12 +142,10 @@ ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); // Parse the actual template declaration. - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(&ParamLists, - isSpecialization, - LastParamListWasEmpty), - ParsingTemplateParams, - DeclEnd, AS, AccessAttrs); + return ParseSingleDeclarationAfterTemplate( + Context, + ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } /// Parse a single declaration that declares a template, @@ -167,14 +158,10 @@ /// declaration. Will be AS_none for namespace-scope declarations. /// /// \returns the new declaration. -Decl * -Parser::ParseSingleDeclarationAfterTemplate( - DeclaratorContext Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromTParams, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseSingleDeclarationAfterTemplate( + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && "Template information required"); @@ -1340,16 +1327,15 @@ SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { // This isn't really required here. ParsingDeclRAIIObject ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent); - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(ExternLoc, - TemplateLoc), - ParsingTemplateParams, - DeclEnd, AS); + return ParseSingleDeclarationAfterTemplate( + Context, ParsedTemplateInfo(ExternLoc, TemplateLoc), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { Index: lib/Parse/Parser.cpp =================================================================== --- lib/Parse/Parser.cpp +++ lib/Parse/Parser.cpp @@ -698,9 +698,8 @@ return nullptr; case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. - SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), - attrs.getList(), - Tok.getLocation()); + SingleDecl = + Actions.ActOnEmptyDeclaration(getCurScope(), attrs, Tok.getLocation()); ConsumeExtraSemi(OutsideFunction); break; case tok::r_brace: @@ -829,8 +828,8 @@ diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; return Actions.ConvertDeclToDeclGroup( - ParseExplicitInstantiation(DeclaratorContext::FileContext, - ExternLoc, TemplateLoc, DeclEnd)); + ParseExplicitInstantiation(DeclaratorContext::FileContext, ExternLoc, + TemplateLoc, DeclEnd, attrs)); } goto dont_know; @@ -1090,15 +1089,10 @@ // Check to make sure that any normal attributes are allowed to be on // a definition. Late parsed attributes are checked at the end. if (Tok.isNot(tok::equal)) { - AttributeList *DtorAttrs = D.getAttributes(); - while (DtorAttrs) { - if (DtorAttrs->isKnownToGCC() && - !DtorAttrs->isCXX11Attribute()) { - Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName(); - } - DtorAttrs = DtorAttrs->getNext(); - } + for (const AttributeList &AL : D.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) + << AL.getName(); } // In delayed template parsing mode, for function template we consume the Index: lib/Sema/AttributeList.cpp =================================================================== --- lib/Sema/AttributeList.cpp +++ lib/Sema/AttributeList.cpp @@ -60,56 +60,41 @@ void *AttributeFactory::allocate(size_t size) { // Check for a previously reclaimed attribute. size_t index = getFreeListIndexForSize(size); - if (index < FreeLists.size()) { - if (AttributeList *attr = FreeLists[index]) { - FreeLists[index] = attr->NextInPool; - return attr; - } + if (index < FreeLists.size() && !FreeLists[index].empty()) { + AttributeList *attr = FreeLists[index].back(); + FreeLists[index].pop_back(); + return attr; } // Otherwise, allocate something new. return Alloc.Allocate(size, alignof(AttributeFactory)); } -void AttributeFactory::reclaimPool(AttributeList *cur) { - assert(cur && "reclaiming empty pool!"); - do { - // Read this here, because we're going to overwrite NextInPool - // when we toss 'cur' into the appropriate queue. - AttributeList *next = cur->NextInPool; - - size_t size = cur->allocated_size(); - size_t freeListIndex = getFreeListIndexForSize(size); - - // Expand FreeLists to the appropriate size, if required. - if (freeListIndex >= FreeLists.size()) - FreeLists.resize(freeListIndex+1); - - // Add 'cur' to the appropriate free-list. - cur->NextInPool = FreeLists[freeListIndex]; - FreeLists[freeListIndex] = cur; - - cur = next; - } while (cur); -} +void AttributeFactory::deallocate(AttributeList *Attr) { + size_t size = Attr->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); -void AttributePool::takePool(AttributeList *pool) { - assert(pool); + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex + 1); - // Fast path: this pool is empty. - if (!Head) { - Head = pool; - return; - } +#if !NDEBUG + // In debug mode, zero out the attribute to help find memory overwriting. + memset(Attr, 0, size); +#endif + + // Add 'Attr' to the appropriate free-list. + FreeLists[freeListIndex].push_back(Attr); +} + +void AttributeFactory::reclaimPool(AttributePool &cur) { + for (AttributeList *AL : cur.Attrs) + deallocate(AL); +} - // Reverse the pool onto the current head. This optimizes for the - // pattern of pulling a lot of pools into a single pool. - do { - AttributeList *next = pool->NextInPool; - pool->NextInPool = Head; - Head = pool; - pool = next; - } while (pool); +void AttributePool::takePool(AttributePool &pool) { + Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); + pool.Attrs.clear(); } #include "clang/Sema/AttrParsedAttrKinds.inc" Index: lib/Sema/DeclSpec.cpp =================================================================== --- lib/Sema/DeclSpec.cpp +++ lib/Sema/DeclSpec.cpp @@ -186,7 +186,6 @@ I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; - I.Fun.AttrList = nullptr; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; @@ -995,15 +994,7 @@ writtenBS.Width = getTypeSpecWidth(); writtenBS.Type = getTypeSpecType(); // Search the list of attributes for the presence of a mode attribute. - writtenBS.ModeAttr = false; - AttributeList* attrs = getAttributes().getList(); - while (attrs) { - if (attrs->getKind() == AttributeList::AT_Mode) { - writtenBS.ModeAttr = true; - break; - } - attrs = attrs->getNext(); - } + writtenBS.ModeAttr = getAttributes().hasAttribute(AttributeList::AT_Mode); } /// Finish - This does final analysis of the declspec, rejecting things like Index: lib/Sema/SemaAttr.cpp =================================================================== --- lib/Sema/SemaAttr.cpp +++ lib/Sema/SemaAttr.cpp @@ -645,7 +645,7 @@ if (PragmaAttributeStack.empty()) return; for (auto &Entry : PragmaAttributeStack) { - const AttributeList *Attribute = Entry.Attribute; + AttributeList *Attribute = Entry.Attribute; assert(Attribute && "Expected an attribute"); // Ensure that the attribute can be applied to the given declaration. @@ -659,9 +659,10 @@ if (!Applies) continue; Entry.IsUsed = true; - assert(!Attribute->getNext() && "Expected just one attribute"); PragmaAttributeCurrentTargetDecl = D; - ProcessDeclAttributeList(S, D, Attribute); + ParsedAttributesView Attrs; + Attrs.addAtStart(Attribute); + ProcessDeclAttributeList(S, D, Attrs); PragmaAttributeCurrentTargetDecl = nullptr; } } Index: lib/Sema/SemaCUDA.cpp =================================================================== --- lib/Sema/SemaCUDA.cpp +++ lib/Sema/SemaCUDA.cpp @@ -55,13 +55,14 @@ /*IsExecConfig=*/true); } -Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) { +Sema::CUDAFunctionTarget +Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; bool HasInvalidTargetAttr = false; - while (Attr) { - switch(Attr->getKind()){ + for (const AttributeList &AL : Attrs) { + switch (AL.getKind()) { case AttributeList::AT_CUDAGlobal: HasGlobalAttr = true; break; @@ -77,8 +78,8 @@ default: break; } - Attr = Attr->getNext(); } + if (HasInvalidTargetAttr) return CFT_InvalidTarget; Index: lib/Sema/SemaDecl.cpp =================================================================== --- lib/Sema/SemaDecl.cpp +++ lib/Sema/SemaDecl.cpp @@ -4447,10 +4447,9 @@ TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (AttributeList* attrs = DS.getAttributes().getList(); attrs; - attrs = attrs->getNext()) - Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) - << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); + for (const AttributeList &AL : DS.getAttributes()) + Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) + << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } } @@ -6204,29 +6203,21 @@ llvm_unreachable("Unexpected context"); } -static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, - AttributeList::Kind Kind) { - for (const AttributeList *L = AttrList; L; L = L->getNext()) - if (L->getKind() == Kind) - return true; - return false; -} - static bool hasParsedAttr(Scope *S, const Declarator &PD, AttributeList::Kind Kind) { // Check decl attributes on the DeclSpec. - if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) + if (PD.getDeclSpec().getAttributes().hasAttribute(Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type // position to the decl itself. for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { - if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) + if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind)) return true; } // Finally, check attributes on the decl itself. - return hasParsedAttr(S, PD.getAttributes(), Kind); + return PD.getAttributes().hasAttribute(Kind); } /// Adjust the \c DeclContext for a function or variable that might be a @@ -11340,8 +11331,8 @@ D.takeAttributes(Attrs, AttrEnd); ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); - D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), - EmptyAttrs, IdentLoc); + D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false), + IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); @@ -12944,7 +12935,7 @@ // Always attach attributes to the underlying decl. if (TemplateDecl *TD = dyn_cast(D)) D = TD->getTemplatedDecl(); - ProcessDeclAttributeList(S, D, Attrs.getList()); + ProcessDeclAttributeList(S, D, Attrs); if (CXXMethodDecl *Method = dyn_cast_or_null(D)) if (Method->isStatic()) @@ -13046,18 +13037,16 @@ /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, + /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - Loc, Loc, D), - DS.getAttributes(), - SourceLocation()); + /*DeclsInPrototype=*/None, Loc, + Loc, D), + std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. @@ -13529,13 +13518,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, + const ParsedAttributesView &Attrs, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. @@ -13574,14 +13562,11 @@ return nullptr; OwnedDecl = false; - DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, - SS, Name, NameLoc, Attr, - TemplateParams, AS, - ModulePrivateLoc, - /*FriendLoc*/SourceLocation(), - TemplateParameterLists.size()-1, - TemplateParameterLists.data(), - SkipBody); + DeclResult Result = CheckClassTemplate( + S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, + AS, ModulePrivateLoc, + /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, + TemplateParameterLists.data(), SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. @@ -14047,7 +14032,7 @@ // If this is a use, just return the declaration we found, unless // we have attributes. if (TUK == TUK_Reference || TUK == TUK_Friend) { - if (Attr) { + if (!Attrs.empty()) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. } else if (TUK == TUK_Reference && @@ -14407,8 +14392,7 @@ if (TUK == TUK_Definition) New->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. @@ -15227,7 +15211,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef Fields, SourceLocation LBrac, - SourceLocation RBrac, AttributeList *Attr) { + SourceLocation RBrac, + const ParsedAttributesView &Attrs) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -15545,8 +15530,7 @@ Record->completeDefinition(); // Handle attributes before checking the layout. - if (Attr) - ProcessDeclAttributeList(S, Record, Attr); + ProcessDeclAttributeList(S, Record, Attrs); // We may have deferred checking for a deleted destructor. Check now. if (CXXRecordDecl *CXXRecord = dyn_cast(Record)) { @@ -15924,7 +15908,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attr, + const ParsedAttributesView &Attrs, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast(theEnumDecl); EnumConstantDecl *LastEnumConst = @@ -15975,7 +15959,7 @@ } // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. @@ -16167,14 +16151,12 @@ } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDeclX, - ArrayRef Elements, - Scope *S, AttributeList *Attr) { + Decl *EnumDeclX, ArrayRef Elements, Scope *S, + const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast(EnumDeclX); QualType EnumType = Context.getTypeDeclType(Enum); - if (Attr) - ProcessDeclAttributeList(S, Enum, Attr); + ProcessDeclAttributeList(S, Enum, Attrs); if (Enum->isDependentType()) { for (unsigned i = 0, e = Elements.size(); i != e; ++i) { Index: lib/Sema/SemaDeclAttr.cpp =================================================================== --- lib/Sema/SemaDeclAttr.cpp +++ lib/Sema/SemaDeclAttr.cpp @@ -5801,8 +5801,8 @@ if (AL.getKind() == AttributeList::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { S.Diag(AL.getLoc(), AL.isDeclspecAttribute() - ? diag::warn_unhandled_ms_attribute_ignored - : diag::warn_unknown_attribute_ignored) + ? diag::warn_unhandled_ms_attribute_ignored + : diag::warn_unknown_attribute_ignored) << AL.getName(); return; } @@ -5973,8 +5973,7 @@ AL); break; case AttributeList::AT_CUDAHost: - handleSimpleAttributeWithExclusions(S, D, - AL); + handleSimpleAttributeWithExclusions(S, D, AL); break; case AttributeList::AT_GNUInline: handleGNUInlineAttr(S, D, AL); @@ -6076,8 +6075,8 @@ handleObjCRuntimeName(S, D, AL); break; case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute(S, D, AL); - break; + handleSimpleAttribute(S, D, AL); + break; case AttributeList::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; @@ -6155,12 +6154,12 @@ handleSimpleAttribute(S, D, AL); break; case AttributeList::AT_NotTailCalled: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions( + S, D, AL); break; case AttributeList::AT_DisableTailCalls: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions(S, D, + AL); break; case AttributeList::AT_Used: handleSimpleAttribute(S, D, AL); @@ -6436,18 +6435,21 @@ /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, - const AttributeList *AttrList, + const ParsedAttributesView &AttrList, bool IncludeCXX11Attributes) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); + if (AttrList.empty()) + return; + + for (const AttributeList &AL : AttrList) + ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); // FIXME: We should be able to handle these cases in TableGen. // GCC accepts // static int a9 __attribute__((weakref)); // but that looks really pointless. We reject it. if (D->hasAttr() && !D->hasAttr()) { - Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) - << cast(D); + Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) + << cast(D); D->dropAttr(); return; } @@ -6495,44 +6497,46 @@ } // Helper for delayed processing TransparentUnion attribute. -void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { - for (const AttributeList *AL = AttrList; AL; AL = AL->getNext()) - if (AL->getKind() == AttributeList::AT_TransparentUnion) { - handleTransparentUnionAttr(*this, D, *AL); +void Sema::ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) + if (AL.getKind() == AttributeList::AT_TransparentUnion) { + handleTransparentUnionAttr(*this, D, AL); break; } } // Annotation attributes are the only attributes allowed after an access // specifier. -bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() == AttributeList::AT_Annotate) { - ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute()); +bool Sema::ProcessAccessDeclAttributeList( + AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) { + if (AL.getKind() == AttributeList::AT_Annotate) { + ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); } else { - Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); + Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); return true; } } - return false; } /// checkUnusedDeclAttributes - Check a list of attributes to see if it /// contains any decl attributes that we should warn about. -static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { - for ( ; A; A = A->getNext()) { +static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { + for (const AttributeList &AL : A) { // Only warn if the attribute is an unignored, non-type attribute. - if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; - if (A->getKind() == AttributeList::IgnoredAttribute) continue; + if (AL.isUsedAsTypeAttr() || AL.isInvalid()) + continue; + if (AL.getKind() == AttributeList::IgnoredAttribute) + continue; - if (A->getKind() == AttributeList::UnknownAttribute) { - S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) - << A->getName() << A->getRange(); + if (AL.getKind() == AttributeList::UnknownAttribute) { + S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL.getName() << AL.getRange(); } else { - S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) - << A->getName() << A->getRange(); + S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) + << AL.getName() << AL.getRange(); } } } @@ -6541,7 +6545,7 @@ /// used to build a declaration, complain about any decl attributes /// which might be lying around on it. void Sema::checkUnusedDeclAttributes(Declarator &D) { - ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes().getList()); + ::checkUnusedDeclAttributes(*this, D.getDeclSpec().getAttributes()); ::checkUnusedDeclAttributes(*this, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) ::checkUnusedDeclAttributes(*this, D.getTypeObject(i).getAttrs()); @@ -6648,20 +6652,19 @@ /// specified in many different places, and we need to find and apply them all. void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. - if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, D, Attrs); + if (!PD.getDeclSpec().getAttributes().empty()) + ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes()); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: // int *__attr__(x)** D; // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) - if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); + ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), + /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. - if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(S, D, Attrs); + ProcessDeclAttributeList(S, D, PD.getAttributes()); // Apply additional attributes specified by '#pragma clang attribute'. AddPragmaAttributes(S, D); Index: lib/Sema/SemaDeclCXX.cpp =================================================================== --- lib/Sema/SemaDeclCXX.cpp +++ lib/Sema/SemaDeclCXX.cpp @@ -2300,18 +2300,13 @@ // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. - if (!Attributes.empty()) { - for (AttributeList *Attr = Attributes.getList(); Attr; - Attr = Attr->getNext()) { - if (Attr->isInvalid() || - Attr->getKind() == AttributeList::IgnoredAttribute) - continue; - Diag(Attr->getLoc(), - Attr->getKind() == AttributeList::UnknownAttribute - ? diag::warn_unknown_attribute_ignored - : diag::err_base_specifier_attribute) - << Attr->getName(); - } + for (const AttributeList &AL : Attributes) { + if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) + continue; + Diag(AL.getLoc(), AL.getKind() == AttributeList::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << AL.getName(); } TypeSourceInfo *TInfo = nullptr; @@ -2691,10 +2686,9 @@ //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. -bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, +bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs) { + const ParsedAttributesView &Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); @@ -2822,10 +2816,14 @@ return false; } -static AttributeList *getMSPropertyAttr(AttributeList *list) { - for (AttributeList *it = list; it != nullptr; it = it->getNext()) - if (it->isDeclspecPropertyAttribute()) - return it; +static const AttributeList * +getMSPropertyAttr(const ParsedAttributesView &list) { + ParsedAttributesView::const_iterator Itr = + llvm::find_if(list, [](const AttributeList &AL) { + return AL.isDeclspecPropertyAttribute(); + }); + if (Itr != list.end()) + return &*Itr; return nullptr; } @@ -2904,8 +2902,8 @@ assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); - AttributeList *MSPropertyAttr = - getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); + const AttributeList *MSPropertyAttr = + getMSPropertyAttr(D.getDeclSpec().getAttributes()); if (cast(CurContext)->isInterface()) { // The Microsoft extension __interface only permits public member functions @@ -3073,7 +3071,7 @@ if (MSPropertyAttr) { Member = HandleMSProperty(S, cast(CurContext), Loc, D, - BitWidth, InitStyle, AS, MSPropertyAttr); + BitWidth, InitStyle, AS, *MSPropertyAttr); if (!Member) return nullptr; isInstField = false; @@ -7809,22 +7807,20 @@ } } -void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList) { +void Sema::ActOnFinishCXXMemberSpecification( + Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList) { if (!TagDecl) return; AdjustDeclIfTemplate(TagDecl); - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() != AttributeList::AT_Visibility) + for (const AttributeList &AL : AttrList) { + if (AL.getKind() != AttributeList::AT_Visibility) continue; - l->setInvalid(); - Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) << - l->getName(); + AL.setInvalid(); + Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) + << AL.getName(); } ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( @@ -8751,14 +8747,10 @@ /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. -Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, - SourceLocation InlineLoc, - SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl *&UD) { +Decl *Sema::ActOnStartNamespaceDef( + Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, + SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, + const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -9273,13 +9265,11 @@ return false; } -Decl *Sema::ActOnUsingDirective(Scope *S, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList) { +Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + const ParsedAttributesView &AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); @@ -9371,15 +9361,12 @@ S->PushUsingDirective(UDir); } - -Decl *Sema::ActOnUsingDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList) { + const ParsedAttributesView &AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { @@ -9836,15 +9823,11 @@ /// \param IsInstantiation - Whether this call arises from an /// instantiation of an unresolved using declaration. We treat /// the lookup differently for these declarations. -NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation) { +NamedDecl *Sema::BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -10410,14 +10393,11 @@ return true; } -Decl *Sema::ActOnAliasDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, MultiTemplateParamsArg TemplateParamLists, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec) { + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->isTemplateParamScope()) S = S->getParent(); @@ -13575,13 +13555,12 @@ } Decl *Sema::ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const ParsedAttributesView &AttrList, SourceLocation SemiLoc) { Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); // Attribute declarations appertain to empty declaration so we handle // them here. - if (AttrList) - ProcessDeclAttributeList(S, ED, AttrList); + ProcessDeclAttributeList(S, ED, AttrList); CurContext->addDecl(ED); return ED; @@ -13920,10 +13899,9 @@ /// templated. Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -14036,7 +14014,6 @@ return Friend; } - /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// @@ -15407,11 +15384,11 @@ /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. /// MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, - SourceLocation DeclStart, - Declarator &D, Expr *BitWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr) { + const AttributeList &MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); @@ -15474,7 +15451,7 @@ PrevDecl = nullptr; SourceLocation TSSL = D.getLocStart(); - const AttributeList::PropertyData &Data = MSPropertyAttr->getPropertyData(); + const AttributeList::PropertyData &Data = MSPropertyAttr.getPropertyData(); MSPropertyDecl *NewPD = MSPropertyDecl::Create( Context, Record, Loc, II, T, TInfo, TSSL, Data.GetterId, Data.SetterId); ProcessDeclAttributes(TUScope, NewPD, D); Index: lib/Sema/SemaDeclObjC.cpp =================================================================== --- lib/Sema/SemaDeclObjC.cpp +++ lib/Sema/SemaDeclObjC.cpp @@ -948,16 +948,14 @@ return false; } -Decl *Sema:: -ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, AttributeList *AttrList) { +Decl *Sema::ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. @@ -1042,9 +1040,8 @@ IDecl->setInvalidDecl(); } } - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + ProcessDeclAttributeList(TUScope, IDecl, AttrList); AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); @@ -1183,15 +1180,11 @@ return res; } -Decl * -Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); @@ -1234,9 +1227,8 @@ PushOnScopeChains(PDecl, TUScope); PDecl->startDefinition(); } - - if (AttrList) - ProcessDeclAttributeList(TUScope, PDecl, AttrList); + + ProcessDeclAttributeList(TUScope, PDecl, AttrList); AddPragmaAttributes(TUScope, PDecl); // Merge attributes from previous declarations. @@ -1567,14 +1559,12 @@ // add the '*'. if (type->getAs()) { SourceLocation starLoc = getLocForEndOfToken(loc); - ParsedAttributes parsedAttrs(attrFactory); D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation()), - parsedAttrs, starLoc); // Diagnose the missing '*'. @@ -1752,7 +1742,7 @@ Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ArrayRef IdentList, - AttributeList *attrList) { + const ParsedAttributesView &attrList) { SmallVector DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; @@ -1765,9 +1755,8 @@ PushOnScopeChains(PDecl, TUScope); CheckObjCDeclScope(PDecl); - - if (attrList) - ProcessDeclAttributeList(TUScope, PDecl, attrList); + + ProcessDeclAttributeList(TUScope, PDecl, attrList); AddPragmaAttributes(TUScope, PDecl); if (PrevDecl) @@ -1779,17 +1768,13 @@ return BuildDeclaratorGroup(DeclsInGroup); } -Decl *Sema:: -ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); @@ -1858,8 +1843,7 @@ // Process the attributes before looking at protocols to ensure that the // availability attribute is attached to the category to provide availability // checking for protocol uses. - if (AttrList) - ProcessDeclAttributeList(TUScope, CDecl, AttrList); + ProcessDeclAttributeList(TUScope, CDecl, AttrList); AddPragmaAttributes(TUScope, CDecl); if (NumProtoRefs) { @@ -4524,17 +4508,14 @@ } Decl *Sema::ActOnMethodDeclaration( - Scope *S, - SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef SelectorLocs, - Selector Sel, + Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef SelectorLocs, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!CurContext->isObjCContainer()) { @@ -4642,8 +4623,7 @@ ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); - if (AttrList) - ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. Index: lib/Sema/SemaLambda.cpp =================================================================== --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -1170,7 +1170,7 @@ Class->setInvalidDecl(); SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); PopFunctionScopeInfo(); @@ -1597,7 +1597,7 @@ // Finalize the lambda class. SmallVector Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); } Index: lib/Sema/SemaStmt.cpp =================================================================== --- lib/Sema/SemaStmt.cpp +++ lib/Sema/SemaStmt.cpp @@ -4283,7 +4283,7 @@ SmallVector Fields(Record->fields()); ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields, - SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); PopDeclContext(); PopFunctionScopeInfo(); Index: lib/Sema/SemaStmtAttr.cpp =================================================================== --- lib/Sema/SemaStmtAttr.cpp +++ lib/Sema/SemaStmtAttr.cpp @@ -313,11 +313,12 @@ } } -StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList, +StmtResult Sema::ProcessStmtAttributes(Stmt *S, + const ParsedAttributesView &AttrList, SourceRange Range) { SmallVector Attrs; - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (Attr *a = ProcessStmtAttribute(*this, S, *l, Range)) + for (const AttributeList &AL : AttrList) { + if (Attr *a = ProcessStmtAttribute(*this, S, AL, Range)) Attrs.push_back(a); } Index: lib/Sema/SemaTemplate.cpp =================================================================== --- lib/Sema/SemaTemplate.cpp +++ lib/Sema/SemaTemplate.cpp @@ -1263,17 +1263,13 @@ T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } -DeclResult -Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList** OuterTemplateParamLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -1613,8 +1609,7 @@ if (TUK == TUK_Definition) NewClass->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); if (PrevClassTemplate) mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); @@ -7401,16 +7396,11 @@ return false; } -DeclResult -Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, - TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg - TemplateParameterLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); CXXScopeSpec &SS = TemplateId.SS; @@ -7711,8 +7701,7 @@ } } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -8564,19 +8553,12 @@ } // Explicit instantiation of a class template specialization -DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc, - AttributeList *Attr) { +DeclResult Sema::ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.get(); TemplateDecl *TD = Name.getAsTemplateDecl(); @@ -8617,11 +8599,11 @@ if (TSK == TSK_ExplicitInstantiationDeclaration) { // Check for dllexport class template instantiation declarations. - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLExport) { + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLExport) { Diag(ExternLoc, diag::warn_attribute_dllexport_explicit_instantiation_decl); - Diag(A->getLoc(), diag::note_attribute); + Diag(AL.getLoc(), diag::note_attribute); break; } } @@ -8641,10 +8623,10 @@ // Check for dllimport class template instantiation definitions. bool DLLImport = ClassTemplate->getTemplatedDecl()->getAttr(); - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLImport) + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLImport) DLLImport = true; - if (A->getKind() == AttributeList::AT_DLLExport) { + if (AL.getKind() == AttributeList::AT_DLLExport) { // dllexport trumps dllimport here. DLLImport = false; break; @@ -8754,8 +8736,7 @@ Specialization->setBraceRange(SourceRange()); bool PreviouslyDLLExported = Specialization->hasAttr(); - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add the explicit instantiation into its lexical context. However, // since explicit instantiations are never found by name lookup, we @@ -8853,15 +8834,11 @@ // Explicit instantiation of a member class of a class template. DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr) { +Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr) { bool Owned = false; bool IsDependent = false; @@ -9163,8 +9140,7 @@ Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (PrevTemplate) { // Merge attributes. - if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, Prev, Attr); + ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); } if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); @@ -9200,7 +9176,6 @@ // template. UnresolvedSet<8> TemplateMatches; FunctionDecl *NonTemplateMatch = nullptr; - AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { @@ -9248,7 +9223,7 @@ if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, /* IgnoreImplicitHDAttributes = */ true) != - IdentifyCUDATarget(Attr)) { + IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -9327,8 +9302,7 @@ return (Decl*) nullptr; } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, D.getDeclSpec().getAttributes()); // In MSVC mode, dllimported explicit instantiation definitions are treated as // instantiation declarations. Index: lib/Sema/SemaTemplateInstantiate.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiate.cpp +++ lib/Sema/SemaTemplateInstantiate.cpp @@ -2125,7 +2125,7 @@ // Finish checking fields. ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields, - SourceLocation(), SourceLocation(), nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Instantiation); // Default arguments are parsed, if not instantiated. We can go instantiate Index: lib/Sema/SemaTemplateInstantiateDecl.cpp =================================================================== --- lib/Sema/SemaTemplateInstantiateDecl.cpp +++ lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1118,8 +1118,7 @@ } SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, - Enumerators, - nullptr, nullptr); + Enumerators, nullptr, ParsedAttributesView()); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -2648,7 +2647,8 @@ NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, + ParsedAttributesView(), /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); Index: lib/Sema/SemaType.cpp =================================================================== --- lib/Sema/SemaType.cpp +++ lib/Sema/SemaType.cpp @@ -195,10 +195,10 @@ chunkIndex = idx; } - AttributeList *&getCurrentAttrListRef() const { + ParsedAttributesView &getCurrentAttributes() const { if (isProcessingDeclSpec()) - return getMutableDeclSpec().getAttributes().getListRef(); - return declarator.getTypeObject(chunkIndex).getAttrListRef(); + return getMutableDeclSpec().getAttributes(); + return declarator.getTypeObject(chunkIndex).getAttrs(); } /// Save the current set of attributes on the DeclSpec. @@ -207,9 +207,8 @@ if (hasSavedAttrs) return; DeclSpec &spec = getMutableDeclSpec(); - for (AttributeList *attr = spec.getAttributes().getList(); attr; - attr = attr->getNext()) - savedAttrs.push_back(attr); + for (AttributeList &AL : spec.getAttributes()) + savedAttrs.push_back(&AL); trivial &= savedAttrs.empty(); hasSavedAttrs = true; } @@ -241,46 +240,18 @@ void restoreDeclSpecAttrs() { assert(hasSavedAttrs); - if (savedAttrs.empty()) { - getMutableDeclSpec().getAttributes().set(nullptr); - return; - } - - getMutableDeclSpec().getAttributes().set(savedAttrs[0]); - for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) - savedAttrs[i]->setNext(savedAttrs[i+1]); - savedAttrs.back()->setNext(nullptr); + getMutableDeclSpec().getAttributes().clearListOnly(); + for (AttributeList *AL : savedAttrs) + getMutableDeclSpec().getAttributes().addAtStart(AL); } }; } // end anonymous namespace -static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { - attr.setNext(head); - head = &attr; -} - -static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) { - if (head == &attr) { - head = attr.getNext(); - return; - } - - AttributeList *cur = head; - while (true) { - assert(cur && cur->getNext() && "ran out of attrs?"); - if (cur->getNext() == &attr) { - cur->setNext(attr.getNext()); - return; - } - cur = cur->getNext(); - } -} - static void moveAttrFromListToList(AttributeList &attr, - AttributeList *&fromList, - AttributeList *&toList) { - spliceAttrOutOfList(attr, fromList); - spliceAttrIntoList(attr, toList); + ParsedAttributesView &fromList, + ParsedAttributesView &toList) { + fromList.remove(&attr); + toList.addAtStart(&attr); } /// The location of a type attribute. @@ -293,9 +264,8 @@ TAL_DeclName }; -static void processTypeAttrs(TypeProcessingState &state, - QualType &type, TypeAttrLocation TAL, - AttributeList *attrs); +static void processTypeAttrs(TypeProcessingState &state, QualType &type, + TypeAttrLocation TAL, ParsedAttributesView &attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, AttributeList &attr, @@ -416,8 +386,8 @@ /*onlyBlockPointers=*/true); if (!destChunk) destChunk = &chunk; - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - destChunk->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + destChunk->getAttrs()); return; } @@ -432,8 +402,8 @@ if (DeclaratorChunk *dest = maybeMovePastReturnType( declarator, i, /*onlyBlockPointers=*/true)) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - dest->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + dest->getAttrs()); return; } } @@ -493,8 +463,8 @@ // attribute from being applied multiple times and gives // the source-location-filler something to work with. state.saveDeclSpecAttrs(); - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getMutableDeclSpec().getAttributes().getListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getMutableDeclSpec().getAttributes()); return; } } @@ -502,13 +472,13 @@ // Otherwise, if we found an appropriate chunk, splice the attribute // into it. if (innermost != -1U) { - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getTypeObject(innermost).getAttrListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getTypeObject(innermost).getAttrs()); return; } // Otherwise, diagnose when we're done building the type. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -527,8 +497,8 @@ DeclaratorChunk &chunk = declarator.getTypeObject(i-1); switch (chunk.Kind) { case DeclaratorChunk::Function: - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return; case DeclaratorChunk::Paren: @@ -548,11 +518,9 @@ /// Try to distribute a function type attribute to the innermost /// function chunk or type. Returns true if the attribute was /// distributed, false if no location was found. -static bool -distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, - AttributeList &attr, - AttributeList *&attrList, - QualType &declSpecType) { +static bool distributeFunctionTypeAttrToInnermost( + TypeProcessingState &state, AttributeList &attr, + ParsedAttributesView &attrList, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); // Put it on the innermost function chunk, if there is one. @@ -560,7 +528,7 @@ DeclaratorChunk &chunk = declarator.getTypeObject(i); if (chunk.Kind != DeclaratorChunk::Function) continue; - moveAttrFromListToList(attr, attrList, chunk.getAttrListRef()); + moveAttrFromListToList(attr, attrList, chunk.getAttrs()); return true; } @@ -579,15 +547,14 @@ // the declarators. Move them straight there. We don't support the // 'put them wherever you like' semantics we allow for GNU attributes. if (attr.isCXX11Attribute()) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - state.getDeclarator().getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + state.getDeclarator().getAttributes()); return; } // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - state.getCurrentAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, state.getCurrentAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is @@ -604,14 +571,13 @@ Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - declarator.getAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, declarator.getAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is // fully built. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -627,24 +593,25 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, QualType &declSpecType) { // Collect all the type attributes from the declarator itself. - assert(state.getDeclarator().getAttributes() && "declarator has no attrs!"); - AttributeList *attr = state.getDeclarator().getAttributes(); - AttributeList *next; - do { - next = attr->getNext(); - + assert(!state.getDeclarator().getAttributes().empty() && + "declarator has no attrs!"); + // The called functions in this loop actually remove things from the current + // list, so iterating over the existing list isn't possible. Instead, make a + // non-owning copy and iterate over that. + ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()}; + for (AttributeList &attr : AttrsCopy) { // Do not distribute C++11 attributes. They have strict rules for what // they appertain to. - if (attr->isCXX11Attribute()) + if (attr.isCXX11Attribute()) continue; - switch (attr->getKind()) { + switch (attr.getKind()) { OBJC_POINTER_TYPE_ATTRS_CASELIST: - distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType); break; FUNCTION_TYPE_ATTRS_CASELIST: - distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType); break; MS_TYPE_ATTRS_CASELIST: @@ -661,7 +628,7 @@ default: break; } - } while ((attr = next)); + } } /// Add a synthetic '()' to a block-literal declarator if it is @@ -761,28 +728,18 @@ return false; // Warn if we see type attributes for omitted return type on a block literal. - AttributeList *&attrs = - declarator.getMutableDeclSpec().getAttributes().getListRef(); - AttributeList *prev = nullptr; - for (AttributeList *cur = attrs; cur; cur = cur->getNext()) { - AttributeList &attr = *cur; - // Skip attributes that were marked to be invalid or non-type - // attributes. - if (attr.isInvalid() || !attr.isTypeAttr()) { - prev = cur; + SmallVector ToBeRemoved; + for (AttributeList &AL : declarator.getMutableDeclSpec().getAttributes()) { + if (AL.isInvalid() || !AL.isTypeAttr()) continue; - } - S.Diag(attr.getLoc(), + S.Diag(AL.getLoc(), diag::warn_block_literal_attributes_on_omitted_return_type) - << attr.getName(); - // Remove cur from the list. - if (prev) { - prev->setNext(cur->getNext()); - prev = cur; - } else { - attrs = cur->getNext(); - } + << AL.getName(); + ToBeRemoved.push_back(&AL); } + // Remove bad attributes from the list. + for (AttributeList *AL : ToBeRemoved) + declarator.getMutableDeclSpec().getAttributes().remove(AL); // Warn if we see type qualifiers for omitted return type on a block literal. const DeclSpec &DS = declarator.getDeclSpec(); @@ -1210,18 +1167,11 @@ return CreateParsedType(Result, ResultTInfo); } -static OpenCLAccessAttr::Spelling getImageAccess(const AttributeList *Attrs) { - if (Attrs) { - const AttributeList *Next = Attrs; - do { - const AttributeList &Attr = *Next; - Next = Attr.getNext(); - if (Attr.getKind() == AttributeList::AT_OpenCLAccess) { - return static_cast( - Attr.getSemanticSpelling()); - } - } while (Next); - } +static OpenCLAccessAttr::Spelling +getImageAccess(const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) + if (AL.getKind() == AttributeList::AT_OpenCLAccess) + return static_cast(AL.getSemanticSpelling()); return OpenCLAccessAttr::Keyword_read_only; } @@ -1237,7 +1187,7 @@ Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - const DeclSpec &DS = declarator.getDeclSpec(); + DeclSpec &DS = declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getLocStart(); @@ -1582,16 +1532,19 @@ } break; -#define GENERIC_IMAGE_TYPE(ImgType, Id) \ - case DeclSpec::TST_##ImgType##_t: \ - switch (getImageAccess(DS.getAttributes().getList())) { \ - case OpenCLAccessAttr::Keyword_write_only: \ - Result = Context.Id##WOTy; break; \ - case OpenCLAccessAttr::Keyword_read_write: \ - Result = Context.Id##RWTy; break; \ - case OpenCLAccessAttr::Keyword_read_only: \ - Result = Context.Id##ROTy; break; \ - } \ +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + switch (getImageAccess(DS.getAttributes())) { \ + case OpenCLAccessAttr::Keyword_write_only: \ + Result = Context.Id##WOTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_write: \ + Result = Context.Id##RWTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_only: \ + Result = Context.Id##ROTy; \ + break; \ + } \ break; #include "clang/Basic/OpenCLImageTypes.def" @@ -1644,7 +1597,7 @@ // attributes are pushed around. // pipe attributes will be handled later ( at GetFullTypeForDeclarator ) if (!DS.isTypeSpecPipe()) - processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); + processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes()); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -2646,9 +2599,8 @@ if (chunk.Kind != DeclaratorChunk::Pointer && chunk.Kind != DeclaratorChunk::BlockPointer) return; - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) + for (const AttributeList &AL : chunk.getAttrs()) + if (AL.getKind() == AttributeList::AT_ObjCOwnership) return; transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing, @@ -2813,7 +2765,7 @@ // "void" instead. T = SemaRef.Context.VoidTy; processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; case UnqualifiedIdKind::IK_DeductionGuideName: @@ -2830,7 +2782,7 @@ break; } - if (D.getAttributes()) + if (!D.getAttributes().empty()) distributeTypeAttrsFromDeclarator(state, T); // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. @@ -3314,21 +3266,20 @@ /// this is the outermost chunk, then we can determine the CC from the /// declarator context. If not, then this could be either a member function /// type or normal function type. -static CallingConv -getCCForDeclaratorChunk(Sema &S, Declarator &D, - const DeclaratorChunk::FunctionTypeInfo &FTI, - unsigned ChunkIndex) { +static CallingConv getCCForDeclaratorChunk( + Sema &S, Declarator &D, const ParsedAttributesView &AttrList, + const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) { assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); // Check for an explicit CC attribute. - for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) { - switch (Attr->getKind()) { - CALLING_CONV_ATTRS_CASELIST: { + for (const AttributeList &AL : AttrList) { + switch (AL.getKind()) { + CALLING_CONV_ATTRS_CASELIST : { // Ignore attributes that don't validate or can't apply to the // function type. We'll diagnose the failure to apply them in // handleFunctionTypeAttr. CallingConv CC; - if (!S.CheckCallingConvAttr(*Attr, CC) && + if (!S.CheckCallingConvAttr(AL, CC) && (!FTI.isVariadic || supportsVariadicCall(CC))) { return CC; } @@ -3384,9 +3335,8 @@ // convention attribute. This is the simplest place to infer // calling convention for OpenCL kernels. if (S.getLangOpts().OpenCL) { - for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_OpenCLKernel) { CC = CC_OpenCLKernel; break; } @@ -3437,12 +3387,11 @@ /// Check whether there is a nullability attribute of any kind in the given /// attribute list. -static bool hasNullabilityAttr(const AttributeList *attrs) { - for (const AttributeList *attr = attrs; attr; - attr = attr->getNext()) { - if (attr->getKind() == AttributeList::AT_TypeNonNull || - attr->getKind() == AttributeList::AT_TypeNullable || - attr->getKind() == AttributeList::AT_TypeNullUnspecified) +static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { + for (const AttributeList &AL : attrs) { + if (AL.getKind() == AttributeList::AT_TypeNonNull || + AL.getKind() == AttributeList::AT_TypeNullable || + AL.getKind() == AttributeList::AT_TypeNullUnspecified) return true; } @@ -4044,19 +3993,16 @@ // On pointer-to-pointer parameters marked cf_returns_retained or // cf_returns_not_retained, if the outer pointer is explicit then // infer the inner pointer as _Nullable. - auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool { - while (NextAttr) { - if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained || - NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained) - return true; - NextAttr = NextAttr->getNext(); - } - return false; + auto hasCFReturnsAttr = + [](const ParsedAttributesView &AttrList) -> bool { + return AttrList.hasAttribute(AttributeList::AT_CFReturnsRetained) || + AttrList.hasAttribute( + AttributeList::AT_CFReturnsNotRetained); }; if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) { if (hasCFReturnsAttr(D.getAttributes()) || hasCFReturnsAttr(InnermostChunk->getAttrs()) || - hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) { + hasCFReturnsAttr(D.getDeclSpec().getAttributes())) { inferNullability = NullabilityKind::Nullable; inferNullabilityInnerOnly = true; } @@ -4112,10 +4058,10 @@ // Local function that checks the nullability for a given pointer declarator. // Returns true if _Nonnull was inferred. - auto inferPointerNullability = [&](SimplePointerKind pointerKind, - SourceLocation pointerLoc, - SourceLocation pointerEndLoc, - AttributeList *&attrs) -> AttributeList * { + auto inferPointerNullability = + [&](SimplePointerKind pointerKind, SourceLocation pointerLoc, + SourceLocation pointerEndLoc, + ParsedAttributesView &attrs) -> AttributeList * { // We've seen a pointer. if (NumPointersRemaining > 0) --NumPointersRemaining; @@ -4137,7 +4083,7 @@ nullptr, SourceLocation(), nullptr, 0, syntax); - spliceAttrIntoList(*nullabilityAttr, attrs); + attrs.addAtStart(nullabilityAttr); if (inferNullabilityCS) { state.getDeclarator().getMutableDeclSpec().getObjCQualifiers() @@ -4192,9 +4138,9 @@ pointerKind = SimplePointerKind::MemberPointer; if (auto *attr = inferPointerNullability( - pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), - D.getDeclSpec().getLocEnd(), - D.getMutableDeclSpec().getAttributes().getListRef())) { + pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), + D.getDeclSpec().getLocEnd(), + D.getMutableDeclSpec().getAttributes())) { T = Context.getAttributedType( AttributedType::getNullabilityAttrKind(*inferNullability),T,T); attr->setUsedAsTypeAttr(); @@ -4232,7 +4178,7 @@ // Handle pointer nullability. inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name); if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) { @@ -4254,7 +4200,7 @@ // Handle pointer nullability inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (LangOpts.ObjC1 && T->getAs()) { T = Context.getObjCObjectPointerType(T); @@ -4528,20 +4474,17 @@ SourceLocation AttrLoc; if (chunkIndex + 1 < D.getNumTypeObjects()) { DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); - for (const AttributeList *Attr = ReturnTypeChunk.getAttrs(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : ReturnTypeChunk.getAttrs()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } } if (AttrLoc.isInvalid()) { - for (const AttributeList *Attr - = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } @@ -4581,7 +4524,8 @@ if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); + FunctionType::ExtInfo EI( + getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus && !LangOpts.OpenCL) { @@ -4591,19 +4535,9 @@ // We allow a zero-parameter variadic function in C if the // function is marked with the "overloadable" attribute. Scan // for this attribute now. - if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) { - bool Overloadable = false; - for (const AttributeList *Attrs = D.getAttributes(); - Attrs; Attrs = Attrs->getNext()) { - if (Attrs->getKind() == AttributeList::AT_Overloadable) { - Overloadable = true; - break; - } - } - - if (!Overloadable) + if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) + if (!D.getAttributes().hasAttribute(AttributeList::AT_Overloadable)) S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param); - } if (FTI.NumParams && FTI.Params[0].Param == nullptr) { // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function @@ -4758,7 +4692,7 @@ // Handle pointer nullability. inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (SS.isInvalid()) { // Avoid emitting extra errors if we already errored on the scope. @@ -4814,7 +4748,7 @@ case DeclaratorChunk::Pipe: { T = S.BuildReadPipeType(T, DeclType.Loc); processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; } } @@ -4825,8 +4759,7 @@ } // See if there are any attributes on this declarator chunk. - processTypeAttrs(state, T, TAL_DeclChunk, - const_cast(DeclType.getAttrs())); + processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs()); } // GNU warning -Wstrict-prototypes @@ -5091,10 +5024,8 @@ // Look for an explicit lifetime attribute. DeclaratorChunk &chunk = D.getTypeObject(chunkIndex); - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) - return; + if (chunk.getAttrs().hasAttribute(AttributeList::AT_ObjCOwnership)) + return; const char *attrStr = nullptr; switch (ownership) { @@ -5117,8 +5048,7 @@ .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ nullptr, SourceLocation(), /*args*/ &Args, 1, AttributeList::AS_GNU); - spliceAttrIntoList(*attr, chunk.getAttrListRef()); - + chunk.getAttrs().addAtStart(attr); // TODO: mark whether we did this inference? } @@ -5262,39 +5192,19 @@ llvm_unreachable("unexpected attribute kind!"); } -static void fillAttributedTypeLoc(AttributedTypeLoc TL, - const AttributeList *attrs, - const AttributeList *DeclAttrs = nullptr) { - // DeclAttrs and attrs cannot be both empty. - assert((attrs || DeclAttrs) && - "no type attributes in the expected location!"); - - AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); - // Try to search for an attribute of matching kind in attrs list. - while (attrs && attrs->getKind() != parsedKind) - attrs = attrs->getNext(); - if (!attrs) { - // No matching type attribute in attrs list found. - // Try searching through C++11 attributes in the declarator attribute list. - while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() || - DeclAttrs->getKind() != parsedKind)) - DeclAttrs = DeclAttrs->getNext(); - attrs = DeclAttrs; - } - - assert(attrs && "no matching type attribute in expected location!"); - - TL.setAttrNameLoc(attrs->getLoc()); +static void setAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList &attr) { + TL.setAttrNameLoc(attr.getLoc()); if (TL.hasAttrExprOperand()) { - assert(attrs->isArgExpr(0) && "mismatched attribute operand kind"); - TL.setAttrExprOperand(attrs->getArgAsExpr(0)); + assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); + TL.setAttrExprOperand(attr.getArgAsExpr(0)); } else if (TL.hasAttrEnumOperand()) { - assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) && + assert((attr.isArgIdent(0) || attr.isArgExpr(0)) && "unexpected attribute operand kind"); - if (attrs->isArgIdent(0)) - TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc); + if (attr.isArgIdent(0)) + TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc); else - TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc()); + TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc()); } // FIXME: preserve this information to here. @@ -5302,6 +5212,25 @@ TL.setAttrOperandParensRange(SourceRange()); } +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const ParsedAttributesView &Attrs, + const ParsedAttributesView &DeclAttrs) { + // DeclAttrs and Attrs cannot be both empty. + assert((!Attrs.empty() || !DeclAttrs.empty()) && + "no type attributes in the expected location!"); + + AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); + // Try to search for an attribute of matching kind in Attrs list. + for (const AttributeList &AL : Attrs) + if (AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + + for (const AttributeList &AL : DeclAttrs) + if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + llvm_unreachable("no matching type attribute in expected location!"); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor { ASTContext &Context; @@ -5312,7 +5241,7 @@ : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { @@ -5484,7 +5413,7 @@ } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, Chunk.getAttrs()); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5617,16 +5546,20 @@ ATL.setParensRange(SourceRange()); } -static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, - const AttributeList *Attrs) { - while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace) - Attrs = Attrs->getNext(); +static void +fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, + const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) { + if (AL.getKind() == AttributeList::AT_AddressSpace) { + DASTL.setAttrNameLoc(AL.getLoc()); + DASTL.setAttrExprOperand(AL.getArgAsExpr(0)); + DASTL.setAttrOperandParensRange(SourceRange()); + return; + } + } - assert(Attrs && "no address_space attribute found at the expected location!"); - - DASTL.setAttrNameLoc(Attrs->getLoc()); - DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0)); - DASTL.setAttrOperandParensRange(SourceRange()); + llvm_unreachable( + "no address_space attribute found at the expected location!"); } /// Create and instantiate a TypeSourceInfo with type source information. @@ -5642,7 +5575,6 @@ TypeSourceInfo *ReturnTypeInfo) { TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T); UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc(); - const AttributeList *DeclAttrs = D.getAttributes(); // Handle parameter packs whose type is a pack expansion. if (isa(T)) { @@ -5666,7 +5598,8 @@ } while (AttributedTypeLoc TL = CurrTL.getAs()) { - fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), + D.getAttributes()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -6558,7 +6491,7 @@ auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool { // If there is already a nullability attribute there, don't add // one. - if (hasNullabilityAttr(chunk.getAttrListRef())) + if (hasNullabilityAttr(chunk.getAttrs())) return false; // Complain about the nullability qualifier being in the wrong @@ -6591,8 +6524,8 @@ " " + attr.getName()->getName().str() + " "); } - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return true; }; @@ -7239,16 +7172,18 @@ } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - TypeAttrLocation TAL, AttributeList *attrs) { + TypeAttrLocation TAL, + ParsedAttributesView &attrs) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. - while (attrs) { - AttributeList &attr = *attrs; - attrs = attr.getNext(); // reset to the next here due to early loop continue - // stmts + // This loop modifies the list pretty frequently, but we still need to make + // sure we visit every element once. Copy the attributes list, and iterate + // over that. + ParsedAttributesView AttrsCopy{attrs}; + for (AttributeList &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. if (attr.isInvalid())