Index: include/clang/Parse/Parser.h =================================================================== --- include/clang/Parse/Parser.h +++ include/clang/Parse/Parser.h @@ -1361,7 +1361,7 @@ }; NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, + ParsedAttributes &AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, @@ -1406,6 +1406,16 @@ SourceRange Range; }; + struct NonOwningParsedAttributesWithRange : NonOwningParsedAttributes { + NonOwningParsedAttributesWithRange() + : NonOwningParsedAttributes() {} + void clearListOnly() { + NonOwningParsedAttributes::clearListOnly(); + Range = SourceRange(); + } + + SourceRange Range; + }; DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = nullptr); @@ -1921,6 +1931,7 @@ void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); void ParseMicrosoftIfExistsExternalDeclaration(); void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, + ParsedAttributes &AccessAttrs, AccessSpecifier& CurAS); bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, bool &InitExprsOk); @@ -2310,14 +2321,21 @@ 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(NonOwningParsedAttributesWithRange &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 +2712,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 +2868,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 +2921,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* Attr); + /// 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; + AttributeList *addNew(AttributeList *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. @@ -639,29 +640,23 @@ AttributePool(const AttributePool &) = delete; ~AttributePool() { - if (Head) Factory.reclaimPool(Head); + 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 +664,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 addNew(new (memory) + AttributeList(attrName, attrRange, scopeName, scopeLoc, + args, numArgs, syntax, ellipsisLoc)); } AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, @@ -683,133 +677,145 @@ 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 addNew(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 addNew(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 addNew(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 addNew(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 addNew(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 NonOwningParsedAttributes { + 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) { assert(newAttr); - assert(newAttr->getNext() == nullptr); - newAttr->setNext(list); - list = newAttr; + AttrList.insert(AttrList.begin(), newAttr); + } + void addAtEnd(AttributeList *newAttr) { + assert(newAttr); + AttrList.push_back(newAttr); } - void addAll(AttributeList *newList) { - if (!newList) return; - - AttributeList *lastInNewList = newList; - while (AttributeList *next = lastInNewList->getNext()) - lastInNewList = next; - - lastInNewList->setNext(list); - list = newList; + 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 addAllAtEnd(AttributeList *newList) { - if (!list) { - list = newList; - return; - } + void clearListOnly() { AttrList.clear(); } - AttributeList *lastInList = list; - while (AttributeList *next = lastInList->getNext()) - lastInList = 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 NonOwningParsedAttributes; + }; + 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 NonOwningParsedAttributes; + }; - lastInList->setNext(newList); + void addAll(iterator B, iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); } - void set(AttributeList *newList) { - list = newList; + void addAllAtEnd(iterator B, iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); } + 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()); } + +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 NonOwningParsedAttributes { +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, @@ -897,10 +903,8 @@ add(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(NonOwningParsedAttributes &AL) { + Attrs.addAll(AL.begin(), AL.end()); } bool hasAttributes() const { return !Attrs.empty(); } @@ -1147,9 +1147,9 @@ return SourceRange(Loc, EndLoc); } - struct TypeInfoCommon { - AttributeList *AttrList; - }; + NonOwningParsedAttributes AttrList; + + struct TypeInfoCommon {}; struct PointerTypeInfo : TypeInfoCommon { /// The type qualifiers: const/volatile/restrict/unaligned/atomic. @@ -1522,12 +1522,11 @@ /// If there are attributes applied to this declaratorchunk, return /// them. - const AttributeList *getAttrs() const { - return Common.AttrList; + const NonOwningParsedAttributes &getAttrs() const { + return AttrList; } - - AttributeList *&getAttrListRef() { - return Common.AttrList; + NonOwningParsedAttributes &getAttrs() { + return AttrList; } /// Return a DeclaratorChunk for a pointer. @@ -1546,7 +1545,6 @@ I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding(); I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding(); - I.Ptr.AttrList = nullptr; return I; } @@ -1558,7 +1556,6 @@ I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = nullptr; return I; } @@ -1570,7 +1567,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 +1610,6 @@ I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1625,7 +1620,6 @@ I.Kind = Pipe; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1637,7 +1631,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 +1642,6 @@ I.Kind = Paren; I.Loc = LParenLoc; I.EndLoc = RParenLoc; - I.Common.AttrList = nullptr; return I; } @@ -2145,16 +2137,26 @@ /// 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, + 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 +2397,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 +2413,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 @@ -2043,7 +2043,7 @@ /// Handle a C++11 empty-declaration and attribute-declaration. Decl *ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const NonOwningParsedAttributes &AttrList, SourceLocation SemiLoc); enum class ModuleDeclKind { @@ -2181,7 +2181,7 @@ Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr, + SourceLocation NameLoc, const NonOwningParsedAttributes &Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, @@ -2193,7 +2193,7 @@ unsigned TagSpec, SourceLocation TagLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const NonOwningParsedAttributes &Attr, MultiTemplateParamsArg TempParamLists); TypeResult ActOnDependentTag(Scope *S, @@ -2219,7 +2219,7 @@ Declarator &D, Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr); + const AttributeList &MSPropertyAttr); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, @@ -2255,7 +2255,7 @@ void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, ArrayRef Fields, SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + const NonOwningParsedAttributes &AttrList); /// ActOnTagStartDefinition - Invoked when we have entered the /// scope of a tag's definition (e.g., for an enumeration, class, @@ -2320,12 +2320,11 @@ Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attrs, SourceLocation EqualLoc, - Expr *Val); + const NonOwningParsedAttributes &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 NonOwningParsedAttributes &Attr); DeclContext *getContainingDC(DeclContext *DC); @@ -3316,11 +3315,16 @@ // 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 NonOwningParsedAttributes &AttrList); + void ProcessDeclAttribute(Scope *S, Decl *D, const AttributeList &AL, + bool IncludeCXX11Attributes = true); + void ProcessDeclAttributeList(Scope *S, Decl *D, + const NonOwningParsedAttributes &AL, bool IncludeCXX11Attributes = true); - bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList); + bool + ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, + const NonOwningParsedAttributes &AttrList); void checkUnusedDeclAttributes(Declarator &D); @@ -3386,7 +3390,8 @@ bool allowArrayTypes); /// Stmt attributes - this routine is the top level dispatcher. - StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, + StmtResult ProcessStmtAttributes(Stmt *Stmt, + const NonOwningParsedAttributes &Attrs, SourceRange Range); void WarnConflictingTypedMethods(ObjCMethodDecl *Method, @@ -4540,11 +4545,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 NonOwningParsedAttributes &AttrList, + UsingDirectiveDecl *&UsingDecl); void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; @@ -4585,13 +4589,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 NonOwningParsedAttributes &AttrList); void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); @@ -4629,7 +4631,7 @@ CXXScopeSpec &SS, DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, - AttributeList *AttrList, + const NonOwningParsedAttributes &AttrList, bool IsInstantiation); NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef Expansions); @@ -4650,13 +4652,13 @@ CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList); + const NonOwningParsedAttributes &AttrList); Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, MultiTemplateParamsArg TemplateParams, SourceLocation UsingLoc, UnqualifiedId &Name, - AttributeList *AttrList, + const NonOwningParsedAttributes &AttrList, TypeResult Type, Decl *DeclFromDeclSpec); @@ -5722,7 +5724,7 @@ bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs = nullptr); + const NonOwningParsedAttributes &Attrs); NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, @@ -5861,11 +5863,9 @@ /// 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, - SourceLocation RBrac, - AttributeList *AttrList); + void ActOnFinishCXXMemberSpecification( + Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, const NonOwningParsedAttributes &AttrList); void ActOnFinishCXXMemberDecls(); void ActOnFinishCXXNonNestedClass(Decl *D); @@ -6202,7 +6202,7 @@ DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const NonOwningParsedAttributes &Attr, TemplateParameterList *TemplateParams, AccessSpecifier AS, SourceLocation ModulePrivateLoc, @@ -6283,14 +6283,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 NonOwningParsedAttributes &Attr, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody = nullptr); bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, TemplateDecl *PrimaryTemplate, @@ -6323,30 +6321,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 NonOwningParsedAttributes &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 NonOwningParsedAttributes &Attr); DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, @@ -7931,20 +7918,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 NonOwningParsedAttributes &AttrList); void ActOnSuperClassOfClassInterface(Scope *S, SourceLocation AtInterfaceLoc, @@ -7977,19 +7958,15 @@ 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); + const NonOwningParsedAttributes &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 NonOwningParsedAttributes &AttrList); Decl *ActOnStartClassImplementation( SourceLocation AtClassImplLoc, @@ -8012,9 +7989,10 @@ ArrayRef TypeParamLists, unsigned NumElts); - DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef IdentList, - AttributeList *attrList); + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef IdentList, + const NonOwningParsedAttributes &attrList); void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, ArrayRef ProtocolId, @@ -8149,22 +8127,22 @@ ObjCDeclSpec DeclSpec; /// ArgAttrs - Attribute list for this argument. - AttributeList *ArgAttrs; + const NonOwningParsedAttributes *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 NonOwningParsedAttributes &AttrList, + tok::ObjCKeywordKind MethodImplKind, bool isVariadic, + bool MethodDefinition); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, @@ -10085,7 +10063,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 NonOwningParsedAttributes &Attrs); /// Gets the CUDA target for the current context. CUDAFunctionTarget CurrentCUDATarget() { Index: lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- lib/Parse/ParseCXXInlineMethods.cpp +++ lib/Parse/ParseCXXInlineMethods.cpp @@ -23,7 +23,7 @@ /// 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, + ParsedAttributes &AccessAttrs, ParsingDeclarator &D, const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers& VS, @@ -46,7 +46,8 @@ TemplateParams, nullptr, VS, ICIS_NoInit); if (FnD) { - Actions.ProcessDeclAttributeList(getCurScope(), FnD, AccessAttrs); + Actions.ProcessDeclAttributeList(getCurScope(), FnD, + AccessAttrs); if (PureSpecLoc.isValid()) Actions.ActOnPureSpecifier(FnD, PureSpecLoc); } 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,29 @@ << 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 +1610,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 +1654,8 @@ 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. @@ -4080,7 +4051,7 @@ Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, T.getOpenLocation(), T.getCloseLocation(), - attrs.getList()); + attrs); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } @@ -4391,7 +4362,7 @@ unsigned DiagID; Decl *TagDecl = Actions.ActOnTag( getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, + attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || @@ -4534,7 +4505,7 @@ // Install the enumerator constant into EnumDecl. Decl *EnumConstDecl = Actions.ActOnEnumConstant( getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - attrs.getList(), EqualLoc, AssignedVal.get()); + attrs, EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); @@ -4589,7 +4560,7 @@ Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls, getCurScope(), - attrs.getList()); + attrs); // Now handle enum constant availability diagnostics. assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); @@ -5386,8 +5357,8 @@ // 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()); + std::move(DS.getAttributes()), + /* Don't replace range end. */ SourceLocation()); return; } } @@ -5400,7 +5371,7 @@ D.AddTypeInfo( DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), - DS.getAttributes(), SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } // Not a pointer, C++ reference, or block. @@ -5438,13 +5409,13 @@ DS.getRestrictSpecLoc(), DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), - DS.getAttributes(), + 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(), + std::move(DS.getAttributes()), SourceLocation()); } else { // Is a reference @@ -5500,7 +5471,7 @@ // Remember that we parsed a reference type. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, Kind == tok::amp), - DS.getAttributes(), + std::move(DS.getAttributes()), SourceLocation()); } } @@ -6011,7 +5982,7 @@ T.consumeClose(); D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); D.setGroupingParens(hadGroupingParens); @@ -6262,7 +6233,7 @@ DeclsInPrototype, StartLoc, LocalEndLoc, D, TrailingReturnType), - FnAttrs, EndLoc); + std::move(FnAttrs), EndLoc); } /// ParseRefQualifier - Parses a member function ref-qualifier. Returns @@ -6584,7 +6555,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)) { @@ -6601,7 +6572,7 @@ 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()); @@ -6679,7 +6650,7 @@ NumElements.get(), T.getOpenLocation(), T.getCloseLocation()), - DS.getAttributes(), T.getCloseLocation()); + std::move(DS.getAttributes()), T.getCloseLocation()); } /// Diagnose brackets before an identifier. @@ -6731,18 +6702,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 @@ -185,8 +185,8 @@ UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, - IdentLoc, Ident, T.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + IdentLoc, Ident, T.getOpenLocation(), + attrs, ImplicitUsingDirectiveDecl); PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -237,7 +237,7 @@ Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], Ident[index], Tracker.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + attrs, ImplicitUsingDirectiveDecl); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -543,7 +543,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 +711,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,7 +813,7 @@ TemplateParams ? TemplateParams->data() : nullptr, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, D.Name, Attrs.getList(), + UsingLoc, D.Name, Attrs, TypeAlias, DeclFromDeclSpec); } @@ -1764,7 +1764,7 @@ TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc, - attrs.getList()); + attrs); // Friend template-ids are treated as references unless // they have template headers, in which case they're ill-formed @@ -1825,7 +1825,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), @@ -1845,7 +1845,7 @@ TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, TagType, StartLoc, SS, Name, - NameLoc, attrs.getList()); + NameLoc, attrs); } else if (TUK == Sema::TUK_Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitAttributes(attrs); @@ -1853,7 +1853,7 @@ TagOrTempResult = Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, - Name, NameLoc, attrs.getList(), + Name, NameLoc, attrs, MultiTemplateParamsArg( TemplateParams? &(*TemplateParams)[0] : nullptr, @@ -1886,7 +1886,7 @@ // Declaration or definition of a class type TagOrTempResult = Actions.ActOnTag( getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, - attrs.getList(), AS, DS.getModulePrivateSpecLoc(), TParams, Owned, + attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, SourceLocation(), false, clang::TypeResult(), DSC == DeclSpecContext::DSC_type_specifier, DSC == DeclSpecContext::DSC_template_param || @@ -1929,7 +1929,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 +2300,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 +2422,7 @@ /// Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - AttributeList *AccessAttrs, + ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -2492,7 +2490,8 @@ return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( getCurScope(), AS, /*UsingLoc*/ SourceLocation(), /*TypenameLoc*/ SourceLocation(), SS, Name, - /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr))); + /*EllipsisLoc*/ SourceLocation(), + /*AttrList*/ NonOwningParsedAttributes{}))); } } @@ -2512,7 +2511,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 +2524,12 @@ } ParsedAttributesWithRange attrs(AttrFactory); - ParsedAttributesWithRange FnAttrs(AttrFactory); + NonOwningParsedAttributesWithRange 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 +2776,8 @@ // initialize it. ThisDecl = VT->getTemplatedDecl(); - if (ThisDecl && AccessAttrs) + // FIXME: Make ProcessDeclAttributeList take ParsedAttributes. + if (ThisDecl && !AccessAttrs.empty()) Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } @@ -3014,7 +3014,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: @@ -3081,7 +3081,7 @@ } if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, - AccessAttrs.getList())) { + AccessAttrs)) { // found another attribute than only annotations AccessAttrs.clear(); } @@ -3094,7 +3094,7 @@ TagDecl); default: - return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3284,7 +3284,7 @@ Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, T.getOpenLocation(), T.getCloseLocation(), - attrs.getList()); + attrs); // C++11 [class.mem]p2: // Within the class member-specification, the class is regarded as complete @@ -3893,25 +3893,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 +4222,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 +4254,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 +4272,8 @@ SourceLocation ASLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(), + NonOwningParsedAttributes{}); else Diag(Tok, diag::err_expected) << tok::colon; ConsumeToken(); @@ -4277,7 +4281,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,7 +2948,6 @@ ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). - ParsedAttributes attrs(AttrFactory); SourceLocation NoLoc; ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, /*IsAmbiguous=*/false, @@ -2974,7 +2973,7 @@ /*DeclsInPrototype=*/None, CaretLoc, CaretLoc, ParamInfo), - attrs, CaretLoc); + 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; @@ -1219,7 +1219,7 @@ /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, TrailingReturnType), - Attr, DeclEndLoc); + 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))) { @@ -1290,7 +1290,7 @@ /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D, TrailingReturnType), - Attr, DeclEndLoc); + std::move(Attr), DeclEndLoc); } // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using @@ -2892,7 +2892,7 @@ 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); @@ -363,7 +363,7 @@ typeArgsRAngleLoc), protocols.data(), protocols.size(), protocolLocs.data(), - EndProtoLoc, attrs.getList()); + EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); @@ -392,14 +392,11 @@ 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().add(getNullabilityAttr()); } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().addAttributes(getNullabilityAttr()); + D.getMutableDeclSpec().getAttributes().add(getNullabilityAttr()); addedToDeclSpec = true; } } @@ -1202,19 +1199,16 @@ /// 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(); +static void takeDeclAttributes(NonOwningParsedAttributes &attrs, + NonOwningParsedAttributes &from) { + llvm::SmallVector ToBeMoved; + for (AttributeList &AL : from) + if (!AL.isUsedAsTypeAttr()) + ToBeMoved.push_back(&AL); - 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); - } + for (AttributeList *AL : ToBeMoved) { + from.remove(AL); + attrs.add(AL); } } @@ -1227,11 +1221,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: @@ -1391,7 +1384,7 @@ mType, DSRet, ReturnType, selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), MethodImplKind, + methodAttrs, MethodImplKind, false, MethodDefinition); PD.complete(Result); return Result; @@ -1423,7 +1416,7 @@ if (getLangOpts().ObjC2) MaybeParseGNUAttributes(paramAttrs); MaybeParseCXX11Attributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); + ArgInfo.ArgAttrs = ¶mAttrs; // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { @@ -1518,7 +1511,7 @@ mType, DSRet, ReturnType, KeyLocs, Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), + methodAttrs, MethodImplKind, isVariadic, MethodDefinition); PD.complete(Result); @@ -1885,9 +1878,10 @@ 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); + NonOwningParsedAttributes Attrs; + Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), + Attrs); } /// objc-class-instance-variables: @@ -2038,7 +2032,7 @@ if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, - attrs.getList()); + attrs); } CheckNestedObjCContexts(AtLoc); @@ -2066,7 +2060,7 @@ return nullptr; return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, - attrs.getList()); + attrs); } // Last, and definitely not least, parse a protocol declaration. @@ -2085,7 +2079,7 @@ ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + 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()) { + if (!Attrs.begin()->isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); + << Attrs.begin()->getName(); SkipToEnd(); return; } - AttributeList &Attribute = *Attrs.getList(); + AttributeList &Attribute = *Attrs.begin(); // 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 { @@ -611,7 +611,7 @@ TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) SubStmt = Actions.ProcessStmtAttributes( - SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); + SubStmt.get(), TempAttrs, TempAttrs.Range); } else { Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } @@ -627,8 +627,8 @@ LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); - if (AttributeList *Attrs = attrs.getList()) { - Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); + if (!attrs.empty()) { + Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs); attrs.clear(); } @@ -2269,7 +2269,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."); @@ -154,7 +147,7 @@ isSpecialization, LastParamListWasEmpty), ParsingTemplateParams, - DeclEnd, AS, AccessAttrs); + DeclEnd, AccessAttrs, AS); } /// Parse a single declaration that declares a template, @@ -167,14 +160,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 +1329,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,36 @@ 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; - } + // 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; @@ -996,14 +995,11 @@ 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) { + for(const AttributeList &AL : getAttributes()) + if (AL.getKind() == AttributeList::AT_Mode) { writtenBS.ModeAttr = true; break; } - attrs = attrs->getNext(); - } } /// Finish - This does final analysis of the declspec, rejecting things like Index: lib/Sema/SemaAttr.cpp =================================================================== --- lib/Sema/SemaAttr.cpp +++ lib/Sema/SemaAttr.cpp @@ -659,9 +659,8 @@ if (!Applies) continue; Entry.IsUsed = true; - assert(!Attribute->getNext() && "Expected just one attribute"); PragmaAttributeCurrentTargetDecl = D; - ProcessDeclAttributeList(S, D, Attribute); + ProcessDeclAttribute(S, D, *Attribute); 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 NonOwningParsedAttributes &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,10 +6203,10 @@ llvm_unreachable("Unexpected context"); } -static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, +static bool hasParsedAttr(Scope *S, const NonOwningParsedAttributes &AttrList, AttributeList::Kind Kind) { - for (const AttributeList *L = AttrList; L; L = L->getNext()) - if (L->getKind() == Kind) + for (const AttributeList &AL : AttrList) + if (AL.getKind() == Kind) return true; return false; } @@ -6215,7 +6214,7 @@ 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 (hasParsedAttr(S, PD.getDeclSpec().getAttributes(), Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type @@ -11341,7 +11340,7 @@ ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), - EmptyAttrs, IdentLoc); + IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); @@ -12944,7 +12943,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()) @@ -13056,7 +13055,7 @@ /*ExceptionSpecTokens=*/nullptr, /*DeclsInPrototype=*/None, Loc, Loc, D), - DS.getAttributes(), + std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); @@ -13529,13 +13528,12 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, + const NonOwningParsedAttributes &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. @@ -13575,7 +13573,7 @@ OwnedDecl = false; DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, - SS, Name, NameLoc, Attr, + SS, Name, NameLoc, Attrs, TemplateParams, AS, ModulePrivateLoc, /*FriendLoc*/SourceLocation(), @@ -14047,7 +14045,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 +14405,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 +15224,8 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef Fields, SourceLocation LBrac, - SourceLocation RBrac, AttributeList *Attr) { + SourceLocation RBrac, + const NonOwningParsedAttributes &Attrs) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -15545,8 +15543,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 +15921,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attr, + const NonOwningParsedAttributes &Attrs, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast(theEnumDecl); EnumConstantDecl *LastEnumConst = @@ -15975,7 +15972,7 @@ } // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. @@ -16169,12 +16166,11 @@ void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, Decl *EnumDeclX, ArrayRef Elements, - Scope *S, AttributeList *Attr) { + Scope *S, const NonOwningParsedAttributes &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 @@ -5784,9 +5784,8 @@ /// ProcessDeclAttribute - Apply the specific attribute to the specified decl if /// the attribute applies to decls. If the attribute is a type attribute, just /// silently ignore it if a GNU attribute. -static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, - const AttributeList &AL, - bool IncludeCXX11Attributes) { +void Sema::ProcessDeclAttribute(Scope *scope, Decl *D, const AttributeList &AL, + bool IncludeCXX11Attributes) { if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) return; @@ -5799,15 +5798,15 @@ // which do not apply to the current target architecture are treated as // though they were unknown attributes. 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) + !AL.existsInTarget(Context.getTargetInfo())) { + Diag(AL.getLoc(), AL.isDeclspecAttribute() + ? diag::warn_unhandled_ms_attribute_ignored + : diag::warn_unknown_attribute_ignored) << AL.getName(); return; } - if (handleCommonAttributeFeatures(S, D, AL)) + if (handleCommonAttributeFeatures(*this, D, AL)) return; switch (AL.getKind()) { @@ -5817,423 +5816,423 @@ assert(AL.isTypeAttr() && "Non-type attribute not handled"); break; } - S.Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) + Diag(AL.getLoc(), diag::err_stmt_attribute_invalid_on_decl) << AL.getName() << D->getLocation(); break; case AttributeList::AT_Interrupt: - handleInterruptAttr(S, D, AL); + handleInterruptAttr(*this, D, AL); break; case AttributeList::AT_X86ForceAlignArgPointer: - handleX86ForceAlignArgPointerAttr(S, D, AL); + handleX86ForceAlignArgPointerAttr(*this, D, AL); break; case AttributeList::AT_DLLExport: case AttributeList::AT_DLLImport: - handleDLLAttr(S, D, AL); + handleDLLAttr(*this, D, AL); break; case AttributeList::AT_Mips16: handleSimpleAttributeWithExclusions(S, D, AL); + MipsInterruptAttr>(*this, D, AL); break; case AttributeList::AT_NoMips16: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_MicroMips: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions(*this, D, AL); break; case AttributeList::AT_NoMicroMips: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_MipsLongCall: handleSimpleAttributeWithExclusions( - S, D, AL); + *this, D, AL); break; case AttributeList::AT_MipsShortCall: handleSimpleAttributeWithExclusions( - S, D, AL); + *this, D, AL); break; case AttributeList::AT_AMDGPUFlatWorkGroupSize: - handleAMDGPUFlatWorkGroupSizeAttr(S, D, AL); + handleAMDGPUFlatWorkGroupSizeAttr(*this, D, AL); break; case AttributeList::AT_AMDGPUWavesPerEU: - handleAMDGPUWavesPerEUAttr(S, D, AL); + handleAMDGPUWavesPerEUAttr(*this, D, AL); break; case AttributeList::AT_AMDGPUNumSGPR: - handleAMDGPUNumSGPRAttr(S, D, AL); + handleAMDGPUNumSGPRAttr(*this, D, AL); break; case AttributeList::AT_AMDGPUNumVGPR: - handleAMDGPUNumVGPRAttr(S, D, AL); + handleAMDGPUNumVGPRAttr(*this, D, AL); break; case AttributeList::AT_AVRSignal: - handleAVRSignalAttr(S, D, AL); + handleAVRSignalAttr(*this, D, AL); break; case AttributeList::AT_IBAction: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_IBOutlet: - handleIBOutlet(S, D, AL); + handleIBOutlet(*this, D, AL); break; case AttributeList::AT_IBOutletCollection: - handleIBOutletCollection(S, D, AL); + handleIBOutletCollection(*this, D, AL); break; case AttributeList::AT_IFunc: - handleIFuncAttr(S, D, AL); + handleIFuncAttr(*this, D, AL); break; case AttributeList::AT_Alias: - handleAliasAttr(S, D, AL); + handleAliasAttr(*this, D, AL); break; case AttributeList::AT_Aligned: - handleAlignedAttr(S, D, AL); + handleAlignedAttr(*this, D, AL); break; case AttributeList::AT_AlignValue: - handleAlignValueAttr(S, D, AL); + handleAlignValueAttr(*this, D, AL); break; case AttributeList::AT_AllocSize: - handleAllocSizeAttr(S, D, AL); + handleAllocSizeAttr(*this, D, AL); break; case AttributeList::AT_AlwaysInline: - handleAlwaysInlineAttr(S, D, AL); + handleAlwaysInlineAttr(*this, D, AL); break; case AttributeList::AT_Artificial: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_AnalyzerNoReturn: - handleAnalyzerNoReturnAttr(S, D, AL); + handleAnalyzerNoReturnAttr(*this, D, AL); break; case AttributeList::AT_TLSModel: - handleTLSModelAttr(S, D, AL); + handleTLSModelAttr(*this, D, AL); break; case AttributeList::AT_Annotate: - handleAnnotateAttr(S, D, AL); + handleAnnotateAttr(*this, D, AL); break; case AttributeList::AT_Availability: - handleAvailabilityAttr(S, D, AL); + handleAvailabilityAttr(*this, D, AL); break; case AttributeList::AT_CarriesDependency: - handleDependencyAttr(S, scope, D, AL); + handleDependencyAttr(*this, scope, D, AL); break; case AttributeList::AT_Common: - handleCommonAttr(S, D, AL); + handleCommonAttr(*this, D, AL); break; case AttributeList::AT_CUDAConstant: - handleConstantAttr(S, D, AL); + handleConstantAttr(*this, D, AL); break; case AttributeList::AT_PassObjectSize: - handlePassObjectSizeAttr(S, D, AL); + handlePassObjectSizeAttr(*this, D, AL); break; case AttributeList::AT_Constructor: - handleConstructorAttr(S, D, AL); + handleConstructorAttr(*this, D, AL); break; case AttributeList::AT_CXX11NoReturn: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Deprecated: - handleDeprecatedAttr(S, D, AL); + handleDeprecatedAttr(*this, D, AL); break; case AttributeList::AT_Destructor: - handleDestructorAttr(S, D, AL); + handleDestructorAttr(*this, D, AL); break; case AttributeList::AT_EnableIf: - handleEnableIfAttr(S, D, AL); + handleEnableIfAttr(*this, D, AL); break; case AttributeList::AT_DiagnoseIf: - handleDiagnoseIfAttr(S, D, AL); + handleDiagnoseIfAttr(*this, D, AL); break; case AttributeList::AT_ExtVectorType: - handleExtVectorTypeAttr(S, D, AL); + handleExtVectorTypeAttr(*this, D, AL); break; case AttributeList::AT_ExternalSourceSymbol: - handleExternalSourceSymbolAttr(S, D, AL); + handleExternalSourceSymbolAttr(*this, D, AL); break; case AttributeList::AT_MinSize: - handleMinSizeAttr(S, D, AL); + handleMinSizeAttr(*this, D, AL); break; case AttributeList::AT_OptimizeNone: - handleOptimizeNoneAttr(S, D, AL); + handleOptimizeNoneAttr(*this, D, AL); break; case AttributeList::AT_FlagEnum: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_EnumExtensibility: - handleEnumExtensibilityAttr(S, D, AL); + handleEnumExtensibilityAttr(*this, D, AL); break; case AttributeList::AT_Flatten: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Format: - handleFormatAttr(S, D, AL); + handleFormatAttr(*this, D, AL); break; case AttributeList::AT_FormatArg: - handleFormatArgAttr(S, D, AL); + handleFormatArgAttr(*this, D, AL); break; case AttributeList::AT_CUDAGlobal: - handleGlobalAttr(S, D, AL); + handleGlobalAttr(*this, D, AL); break; case AttributeList::AT_CUDADevice: - handleSimpleAttributeWithExclusions(S, D, + handleSimpleAttributeWithExclusions(*this, D, AL); break; case AttributeList::AT_CUDAHost: - handleSimpleAttributeWithExclusions(S, D, + handleSimpleAttributeWithExclusions(*this, D, AL); break; case AttributeList::AT_GNUInline: - handleGNUInlineAttr(S, D, AL); + handleGNUInlineAttr(*this, D, AL); break; case AttributeList::AT_CUDALaunchBounds: - handleLaunchBoundsAttr(S, D, AL); + handleLaunchBoundsAttr(*this, D, AL); break; case AttributeList::AT_Restrict: - handleRestrictAttr(S, D, AL); + handleRestrictAttr(*this, D, AL); break; case AttributeList::AT_MayAlias: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Mode: - handleModeAttr(S, D, AL); + handleModeAttr(*this, D, AL); break; case AttributeList::AT_NoAlias: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoCommon: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoSplitStack: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NonNull: if (auto *PVD = dyn_cast(D)) - handleNonNullAttrParameter(S, PVD, AL); + handleNonNullAttrParameter(*this, PVD, AL); else - handleNonNullAttr(S, D, AL); + handleNonNullAttr(*this, D, AL); break; case AttributeList::AT_ReturnsNonNull: - handleReturnsNonNullAttr(S, D, AL); + handleReturnsNonNullAttr(*this, D, AL); break; case AttributeList::AT_NoEscape: - handleNoEscapeAttr(S, D, AL); + handleNoEscapeAttr(*this, D, AL); break; case AttributeList::AT_AssumeAligned: - handleAssumeAlignedAttr(S, D, AL); + handleAssumeAlignedAttr(*this, D, AL); break; case AttributeList::AT_AllocAlign: - handleAllocAlignAttr(S, D, AL); + handleAllocAlignAttr(*this, D, AL); break; case AttributeList::AT_Overloadable: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Ownership: - handleOwnershipAttr(S, D, AL); + handleOwnershipAttr(*this, D, AL); break; case AttributeList::AT_Cold: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions(*this, D, AL); break; case AttributeList::AT_Hot: - handleSimpleAttributeWithExclusions(S, D, AL); + handleSimpleAttributeWithExclusions(*this, D, AL); break; case AttributeList::AT_Naked: - handleNakedAttr(S, D, AL); + handleNakedAttr(*this, D, AL); break; case AttributeList::AT_NoReturn: - handleNoReturnAttr(S, D, AL); + handleNoReturnAttr(*this, D, AL); break; case AttributeList::AT_AnyX86NoCfCheck: - handleNoCfCheckAttr(S, D, AL); + handleNoCfCheckAttr(*this, D, AL); break; case AttributeList::AT_NoThrow: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_CUDAShared: - handleSharedAttr(S, D, AL); + handleSharedAttr(*this, D, AL); break; case AttributeList::AT_VecReturn: - handleVecReturnAttr(S, D, AL); + handleVecReturnAttr(*this, D, AL); break; case AttributeList::AT_ObjCOwnership: - handleObjCOwnershipAttr(S, D, AL); + handleObjCOwnershipAttr(*this, D, AL); break; case AttributeList::AT_ObjCPreciseLifetime: - handleObjCPreciseLifetimeAttr(S, D, AL); + handleObjCPreciseLifetimeAttr(*this, D, AL); break; case AttributeList::AT_ObjCReturnsInnerPointer: - handleObjCReturnsInnerPointerAttr(S, D, AL); + handleObjCReturnsInnerPointerAttr(*this, D, AL); break; case AttributeList::AT_ObjCRequiresSuper: - handleObjCRequiresSuperAttr(S, D, AL); + handleObjCRequiresSuperAttr(*this, D, AL); break; case AttributeList::AT_ObjCBridge: - handleObjCBridgeAttr(S, D, AL); + handleObjCBridgeAttr(*this, D, AL); break; case AttributeList::AT_ObjCBridgeMutable: - handleObjCBridgeMutableAttr(S, D, AL); + handleObjCBridgeMutableAttr(*this, D, AL); break; case AttributeList::AT_ObjCBridgeRelated: - handleObjCBridgeRelatedAttr(S, D, AL); + handleObjCBridgeRelatedAttr(*this, D, AL); break; case AttributeList::AT_ObjCDesignatedInitializer: - handleObjCDesignatedInitializer(S, D, AL); + handleObjCDesignatedInitializer(*this, D, AL); break; case AttributeList::AT_ObjCRuntimeName: - handleObjCRuntimeName(S, D, AL); + handleObjCRuntimeName(*this, D, AL); break; case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ObjCBoxable: - handleObjCBoxable(S, D, AL); + handleObjCBoxable(*this, D, AL); break; case AttributeList::AT_CFAuditedTransfer: handleSimpleAttributeWithExclusions(S, D, AL); + CFUnknownTransferAttr>(*this, D, AL); break; case AttributeList::AT_CFUnknownTransfer: handleSimpleAttributeWithExclusions(S, D, AL); + CFAuditedTransferAttr>(*this, D, AL); break; case AttributeList::AT_CFConsumed: case AttributeList::AT_NSConsumed: - handleNSConsumedAttr(S, D, AL); + handleNSConsumedAttr(*this, D, AL); break; case AttributeList::AT_NSConsumesSelf: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NSReturnsAutoreleased: case AttributeList::AT_NSReturnsNotRetained: case AttributeList::AT_CFReturnsNotRetained: case AttributeList::AT_NSReturnsRetained: case AttributeList::AT_CFReturnsRetained: - handleNSReturnsRetainedAttr(S, D, AL); + handleNSReturnsRetainedAttr(*this, D, AL); break; case AttributeList::AT_WorkGroupSizeHint: - handleWorkGroupSize(S, D, AL); + handleWorkGroupSize(*this, D, AL); break; case AttributeList::AT_ReqdWorkGroupSize: - handleWorkGroupSize(S, D, AL); + handleWorkGroupSize(*this, D, AL); break; case AttributeList::AT_OpenCLIntelReqdSubGroupSize: - handleSubGroupSize(S, D, AL); + handleSubGroupSize(*this, D, AL); break; case AttributeList::AT_VecTypeHint: - handleVecTypeHint(S, D, AL); + handleVecTypeHint(*this, D, AL); break; case AttributeList::AT_RequireConstantInit: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_InitPriority: - handleInitPriorityAttr(S, D, AL); + handleInitPriorityAttr(*this, D, AL); break; case AttributeList::AT_Packed: - handlePackedAttr(S, D, AL); + handlePackedAttr(*this, D, AL); break; case AttributeList::AT_Section: - handleSectionAttr(S, D, AL); + handleSectionAttr(*this, D, AL); break; case AttributeList::AT_Target: - handleTargetAttr(S, D, AL); + handleTargetAttr(*this, D, AL); break; case AttributeList::AT_Unavailable: - handleAttrWithMessage(S, D, AL); + handleAttrWithMessage(*this, D, AL); break; case AttributeList::AT_ArcWeakrefUnavailable: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ObjCRootClass: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ObjCSubclassingRestricted: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ObjCExplicitProtocolImpl: - handleObjCSuppresProtocolAttr(S, D, AL); + handleObjCSuppresProtocolAttr(*this, D, AL); break; case AttributeList::AT_ObjCRequiresPropertyDefs: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Unused: - handleUnusedAttr(S, D, AL); + handleUnusedAttr(*this, D, AL); break; case AttributeList::AT_ReturnsTwice: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NotTailCalled: handleSimpleAttributeWithExclusions(S, D, AL); + AlwaysInlineAttr>(*this, D, AL); break; case AttributeList::AT_DisableTailCalls: handleSimpleAttributeWithExclusions(S, D, AL); + NakedAttr>(*this, D, AL); break; case AttributeList::AT_Used: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Visibility: - handleVisibilityAttr(S, D, AL, false); + handleVisibilityAttr(*this, D, AL, false); break; case AttributeList::AT_TypeVisibility: - handleVisibilityAttr(S, D, AL, true); + handleVisibilityAttr(*this, D, AL, true); break; case AttributeList::AT_WarnUnused: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_WarnUnusedResult: - handleWarnUnusedResult(S, D, AL); + handleWarnUnusedResult(*this, D, AL); break; case AttributeList::AT_Weak: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_WeakRef: - handleWeakRefAttr(S, D, AL); + handleWeakRefAttr(*this, D, AL); break; case AttributeList::AT_WeakImport: - handleWeakImportAttr(S, D, AL); + handleWeakImportAttr(*this, D, AL); break; case AttributeList::AT_TransparentUnion: - handleTransparentUnionAttr(S, D, AL); + handleTransparentUnionAttr(*this, D, AL); break; case AttributeList::AT_ObjCException: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ObjCMethodFamily: - handleObjCMethodFamilyAttr(S, D, AL); + handleObjCMethodFamilyAttr(*this, D, AL); break; case AttributeList::AT_ObjCNSObject: - handleObjCNSObject(S, D, AL); + handleObjCNSObject(*this, D, AL); break; case AttributeList::AT_ObjCIndependentClass: - handleObjCIndependentClass(S, D, AL); + handleObjCIndependentClass(*this, D, AL); break; case AttributeList::AT_Blocks: - handleBlocksAttr(S, D, AL); + handleBlocksAttr(*this, D, AL); break; case AttributeList::AT_Sentinel: - handleSentinelAttr(S, D, AL); + handleSentinelAttr(*this, D, AL); break; case AttributeList::AT_Const: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Pure: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Cleanup: - handleCleanupAttr(S, D, AL); + handleCleanupAttr(*this, D, AL); break; case AttributeList::AT_NoDebug: - handleNoDebugAttr(S, D, AL); + handleNoDebugAttr(*this, D, AL); break; case AttributeList::AT_NoDuplicate: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Convergent: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoInline: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoInstrumentFunction: // Interacts with -pg. - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoStackProtector: // Interacts with -fstack-protector options. - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_StdCall: case AttributeList::AT_CDecl: @@ -6249,186 +6248,186 @@ case AttributeList::AT_IntelOclBicc: case AttributeList::AT_PreserveMost: case AttributeList::AT_PreserveAll: - handleCallConvAttr(S, D, AL); + handleCallConvAttr(*this, D, AL); break; case AttributeList::AT_Suppress: - handleSuppressAttr(S, D, AL); + handleSuppressAttr(*this, D, AL); break; case AttributeList::AT_OpenCLKernel: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_OpenCLAccess: - handleOpenCLAccessAttr(S, D, AL); + handleOpenCLAccessAttr(*this, D, AL); break; case AttributeList::AT_OpenCLNoSVM: - handleOpenCLNoSVMAttr(S, D, AL); + handleOpenCLNoSVMAttr(*this, D, AL); break; case AttributeList::AT_SwiftContext: - handleParameterABIAttr(S, D, AL, ParameterABI::SwiftContext); + handleParameterABIAttr(*this, D, AL, ParameterABI::SwiftContext); break; case AttributeList::AT_SwiftErrorResult: - handleParameterABIAttr(S, D, AL, ParameterABI::SwiftErrorResult); + handleParameterABIAttr(*this, D, AL, ParameterABI::SwiftErrorResult); break; case AttributeList::AT_SwiftIndirectResult: - handleParameterABIAttr(S, D, AL, ParameterABI::SwiftIndirectResult); + handleParameterABIAttr(*this, D, AL, ParameterABI::SwiftIndirectResult); break; case AttributeList::AT_InternalLinkage: - handleInternalLinkageAttr(S, D, AL); + handleInternalLinkageAttr(*this, D, AL); break; case AttributeList::AT_LTOVisibilityPublic: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; // Microsoft attributes: case AttributeList::AT_EmptyBases: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_LayoutVersion: - handleLayoutVersion(S, D, AL); + handleLayoutVersion(*this, D, AL); break; case AttributeList::AT_TrivialABI: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_MSNoVTable: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_MSStruct: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Uuid: - handleUuidAttr(S, D, AL); + handleUuidAttr(*this, D, AL); break; case AttributeList::AT_MSInheritance: - handleMSInheritanceAttr(S, D, AL); + handleMSInheritanceAttr(*this, D, AL); break; case AttributeList::AT_SelectAny: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_Thread: - handleDeclspecThreadAttr(S, D, AL); + handleDeclspecThreadAttr(*this, D, AL); break; case AttributeList::AT_AbiTag: - handleAbiTagAttr(S, D, AL); + handleAbiTagAttr(*this, D, AL); break; // Thread safety attributes: case AttributeList::AT_AssertExclusiveLock: - handleAssertExclusiveLockAttr(S, D, AL); + handleAssertExclusiveLockAttr(*this, D, AL); break; case AttributeList::AT_AssertSharedLock: - handleAssertSharedLockAttr(S, D, AL); + handleAssertSharedLockAttr(*this, D, AL); break; case AttributeList::AT_GuardedVar: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_PtGuardedVar: - handlePtGuardedVarAttr(S, D, AL); + handlePtGuardedVarAttr(*this, D, AL); break; case AttributeList::AT_ScopedLockable: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_NoSanitize: - handleNoSanitizeAttr(S, D, AL); + handleNoSanitizeAttr(*this, D, AL); break; case AttributeList::AT_NoSanitizeSpecific: - handleNoSanitizeSpecificAttr(S, D, AL); + handleNoSanitizeSpecificAttr(*this, D, AL); break; case AttributeList::AT_NoThreadSafetyAnalysis: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_GuardedBy: - handleGuardedByAttr(S, D, AL); + handleGuardedByAttr(*this, D, AL); break; case AttributeList::AT_PtGuardedBy: - handlePtGuardedByAttr(S, D, AL); + handlePtGuardedByAttr(*this, D, AL); break; case AttributeList::AT_ExclusiveTrylockFunction: - handleExclusiveTrylockFunctionAttr(S, D, AL); + handleExclusiveTrylockFunctionAttr(*this, D, AL); break; case AttributeList::AT_LockReturned: - handleLockReturnedAttr(S, D, AL); + handleLockReturnedAttr(*this, D, AL); break; case AttributeList::AT_LocksExcluded: - handleLocksExcludedAttr(S, D, AL); + handleLocksExcludedAttr(*this, D, AL); break; case AttributeList::AT_SharedTrylockFunction: - handleSharedTrylockFunctionAttr(S, D, AL); + handleSharedTrylockFunctionAttr(*this, D, AL); break; case AttributeList::AT_AcquiredBefore: - handleAcquiredBeforeAttr(S, D, AL); + handleAcquiredBeforeAttr(*this, D, AL); break; case AttributeList::AT_AcquiredAfter: - handleAcquiredAfterAttr(S, D, AL); + handleAcquiredAfterAttr(*this, D, AL); break; // Capability analysis attributes. case AttributeList::AT_Capability: case AttributeList::AT_Lockable: - handleCapabilityAttr(S, D, AL); + handleCapabilityAttr(*this, D, AL); break; case AttributeList::AT_RequiresCapability: - handleRequiresCapabilityAttr(S, D, AL); + handleRequiresCapabilityAttr(*this, D, AL); break; case AttributeList::AT_AssertCapability: - handleAssertCapabilityAttr(S, D, AL); + handleAssertCapabilityAttr(*this, D, AL); break; case AttributeList::AT_AcquireCapability: - handleAcquireCapabilityAttr(S, D, AL); + handleAcquireCapabilityAttr(*this, D, AL); break; case AttributeList::AT_ReleaseCapability: - handleReleaseCapabilityAttr(S, D, AL); + handleReleaseCapabilityAttr(*this, D, AL); break; case AttributeList::AT_TryAcquireCapability: - handleTryAcquireCapabilityAttr(S, D, AL); + handleTryAcquireCapabilityAttr(*this, D, AL); break; // Consumed analysis attributes. case AttributeList::AT_Consumable: - handleConsumableAttr(S, D, AL); + handleConsumableAttr(*this, D, AL); break; case AttributeList::AT_ConsumableAutoCast: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_ConsumableSetOnRead: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_CallableWhen: - handleCallableWhenAttr(S, D, AL); + handleCallableWhenAttr(*this, D, AL); break; case AttributeList::AT_ParamTypestate: - handleParamTypestateAttr(S, D, AL); + handleParamTypestateAttr(*this, D, AL); break; case AttributeList::AT_ReturnTypestate: - handleReturnTypestateAttr(S, D, AL); + handleReturnTypestateAttr(*this, D, AL); break; case AttributeList::AT_SetTypestate: - handleSetTypestateAttr(S, D, AL); + handleSetTypestateAttr(*this, D, AL); break; case AttributeList::AT_TestTypestate: - handleTestTypestateAttr(S, D, AL); + handleTestTypestateAttr(*this, D, AL); break; // Type safety attributes. case AttributeList::AT_ArgumentWithTypeTag: - handleArgumentWithTypeTagAttr(S, D, AL); + handleArgumentWithTypeTagAttr(*this, D, AL); break; case AttributeList::AT_TypeTagForDatatype: - handleTypeTagForDatatypeAttr(S, D, AL); + handleTypeTagForDatatypeAttr(*this, D, AL); break; case AttributeList::AT_AnyX86NoCallerSavedRegisters: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_RenderScriptKernel: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; // XRay attributes. case AttributeList::AT_XRayInstrument: - handleSimpleAttribute(S, D, AL); + handleSimpleAttribute(*this, D, AL); break; case AttributeList::AT_XRayLogArgs: - handleXRayLogArgsAttr(S, D, AL); + handleXRayLogArgsAttr(*this, D, AL); break; } } @@ -6436,17 +6435,17 @@ /// 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 NonOwningParsedAttributes &AttrList, bool IncludeCXX11Attributes) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); + for (const AttributeList &AL : AttrList) + ProcessDeclAttribute(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) + Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) << cast(D); D->dropAttr(); return; @@ -6495,44 +6494,45 @@ } // 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 NonOwningParsedAttributes &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 NonOwningParsedAttributes &AttrList) { + for (const AttributeList &AL : AttrList) { + if (AL.getKind() == AttributeList::AT_Annotate) { + ProcessDeclAttribute(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 NonOwningParsedAttributes &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 +6541,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 +6648,20 @@ /// 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); + if (!PD.getAttributes().empty()) + 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; @@ -2694,7 +2689,7 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs) { + const NonOwningParsedAttributes &Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); @@ -2822,10 +2817,13 @@ return false; } -static AttributeList *getMSPropertyAttr(AttributeList *list) { - for (AttributeList *it = list; it != nullptr; it = it->getNext()) - if (it->isDeclspecPropertyAttribute()) - return it; +static AttributeList *getMSPropertyAttr(const NonOwningParsedAttributes &list) { + NonOwningParsedAttributes::const_iterator Itr = + llvm::find_if(list, [](const AttributeList &AL) { + return AL.isDeclspecPropertyAttribute(); + }); + if (Itr != list.end()) + return &*Itr; return nullptr; } @@ -2905,7 +2903,7 @@ bool isFunc = D.isDeclarationOfFunction(); AttributeList *MSPropertyAttr = - getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); + 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 NonOwningParsedAttributes &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( @@ -8757,7 +8753,7 @@ SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, - AttributeList *AttrList, + const NonOwningParsedAttributes &AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. @@ -9273,13 +9269,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 NonOwningParsedAttributes &AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); @@ -9379,7 +9373,7 @@ CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList) { + const NonOwningParsedAttributes &AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { @@ -9836,15 +9830,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 NonOwningParsedAttributes &AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -10415,7 +10405,7 @@ MultiTemplateParamsArg TemplateParamLists, SourceLocation UsingLoc, UnqualifiedId &Name, - AttributeList *AttrList, + const NonOwningParsedAttributes &AttrList, TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. @@ -13575,13 +13565,12 @@ } Decl *Sema::ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const NonOwningParsedAttributes &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; @@ -13923,7 +13912,7 @@ CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const NonOwningParsedAttributes &Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -15411,7 +15400,7 @@ 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 +15463,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 NonOwningParsedAttributes &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 NonOwningParsedAttributes &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 '*'. @@ -1749,10 +1739,9 @@ } /// ActOnForwardProtocolDeclaration - Handle \@protocol foo; -Sema::DeclGroupPtrTy -Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, - ArrayRef IdentList, - AttributeList *attrList) { +Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration( + SourceLocation AtProtocolLoc, ArrayRef IdentList, + const NonOwningParsedAttributes &attrList) { SmallVector DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; @@ -1765,9 +1754,8 @@ PushOnScopeChains(PDecl, TUScope); CheckObjCDeclScope(PDecl); - - if (attrList) - ProcessDeclAttributeList(TUScope, PDecl, attrList); + + ProcessDeclAttributeList(TUScope, PDecl, attrList); AddPragmaAttributes(TUScope, PDecl); if (PrevDecl) @@ -1789,7 +1777,7 @@ unsigned NumProtoRefs, const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, - AttributeList *AttrList) { + const NonOwningParsedAttributes &AttrList) { ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); @@ -1858,8 +1846,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,18 +4511,16 @@ } 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, - bool isVariadic, bool MethodDefinition) { + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const NonOwningParsedAttributes &AttrList, + tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, + bool MethodDefinition) { // Make sure we can establish a context for the method. if (!CurContext->isObjCContainer()) { Diag(MethodLoc, diag::err_missing_method_context); @@ -4612,7 +4597,7 @@ CvtQTToAstBitMask(ArgInfo[i].DeclSpec.getObjCDeclQualifier())); // Apply the attributes to the parameter. - ProcessDeclAttributeList(TUScope, Param, ArgInfo[i].ArgAttrs); + ProcessDeclAttributeList(TUScope, Param, *ArgInfo[i].ArgAttrs); AddPragmaAttributes(TUScope, Param); if (Param->hasAttr()) { @@ -4642,8 +4627,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(), NonOwningParsedAttributes{}); 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(), NonOwningParsedAttributes{}); 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(), NonOwningParsedAttributes{}); 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, - SourceRange Range) { +StmtResult +Sema::ProcessStmtAttributes(Stmt *S, const NonOwningParsedAttributes &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 @@ -1267,7 +1267,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const NonOwningParsedAttributes &Attr, TemplateParameterList *TemplateParams, AccessSpecifier AS, SourceLocation ModulePrivateLoc, SourceLocation FriendLoc, @@ -1613,8 +1613,7 @@ if (TUK == TUK_Definition) NewClass->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); if (PrevClassTemplate) mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); @@ -7407,7 +7406,7 @@ SourceLocation KWLoc, SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, - AttributeList *Attr, + const NonOwningParsedAttributes &Attr, MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { @@ -7711,8 +7710,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. @@ -8576,7 +8574,7 @@ SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, SourceLocation RAngleLoc, - AttributeList *Attr) { + const NonOwningParsedAttributes &Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.get(); TemplateDecl *TD = Name.getAsTemplateDecl(); @@ -8617,11 +8615,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 +8639,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 +8752,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 @@ -8861,7 +8858,7 @@ CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr) { + const NonOwningParsedAttributes &Attr) { bool Owned = false; bool IsDependent = false; @@ -9163,8 +9160,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 +9196,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 +9243,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 +9322,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(), NonOwningParsedAttributes{}); 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 @@ -1119,7 +1119,7 @@ SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, Enumerators, - nullptr, nullptr); + nullptr, NonOwningParsedAttributes{}); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -2648,7 +2648,8 @@ NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, + NonOwningParsedAttributes{}, /*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 { + NonOwningParsedAttributes &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().add(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); + NonOwningParsedAttributes &fromList, + NonOwningParsedAttributes &toList) { + fromList.remove(&attr); + toList.add(&attr); } /// The location of a type attribute. @@ -295,7 +266,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, TypeAttrLocation TAL, - AttributeList *attrs); + NonOwningParsedAttributes &attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, AttributeList &attr, @@ -416,8 +387,8 @@ /*onlyBlockPointers=*/true); if (!destChunk) destChunk = &chunk; - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - destChunk->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + destChunk->getAttrs()); return; } @@ -432,8 +403,8 @@ if (DeclaratorChunk *dest = maybeMovePastReturnType( declarator, i, /*onlyBlockPointers=*/true)) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - dest->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + dest->getAttrs()); return; } } @@ -493,8 +464,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 +473,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 +498,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: @@ -551,7 +522,7 @@ static bool distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, AttributeList &attr, - AttributeList *&attrList, + NonOwningParsedAttributes &attrList, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); @@ -560,7 +531,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,14 +550,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(), + state.getCurrentAttributes(), declSpecType)) return; @@ -604,14 +575,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 +597,26 @@ 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 existin glist isn't possible. Instead, make a + // non-owning copy and iterate over that. + NonOwningParsedAttributes 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 +633,7 @@ default: break; } - } while ((attr = next)); + } } /// Add a synthetic '()' to a block-literal declarator if it is @@ -761,28 +733,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 +1172,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 NonOwningParsedAttributes &Attrs) { + for (const AttributeList &AL : Attrs) + if (AL.getKind() == AttributeList::AT_OpenCLAccess) + return static_cast(AL.getSemanticSpelling()); return OpenCLAccessAttr::Keyword_read_only; } @@ -1237,7 +1192,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(); @@ -1584,7 +1539,7 @@ #define GENERIC_IMAGE_TYPE(ImgType, Id) \ case DeclSpec::TST_##ImgType##_t: \ - switch (getImageAccess(DS.getAttributes().getList())) { \ + switch (getImageAccess(DS.getAttributes())) { \ case OpenCLAccessAttr::Keyword_write_only: \ Result = Context.Id##WOTy; break; \ case OpenCLAccessAttr::Keyword_read_write: \ @@ -1644,7 +1599,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 +2601,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 +2767,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 +2784,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. @@ -3316,19 +3270,20 @@ /// type or normal function type. static CallingConv getCCForDeclaratorChunk(Sema &S, Declarator &D, + const NonOwningParsedAttributes &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 +3339,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 +3391,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 NonOwningParsedAttributes &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 +3997,18 @@ // 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) + auto hasCFReturnsAttr = + [](const NonOwningParsedAttributes &AttrList) -> bool { + for(const AttributeList &AL : AttrList) + if (AL.getKind() == AttributeList::AT_CFReturnsRetained || + AL.getKind() == AttributeList::AT_CFReturnsNotRetained) return true; - NextAttr = NextAttr->getNext(); - } return false; }; 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 +4064,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, + NonOwningParsedAttributes &attrs) -> AttributeList * { // We've seen a pointer. if (NumPointersRemaining > 0) --NumPointersRemaining; @@ -4137,7 +4089,7 @@ nullptr, SourceLocation(), nullptr, 0, syntax); - spliceAttrIntoList(*nullabilityAttr, attrs); + attrs.add(nullabilityAttr); if (inferNullabilityCS) { state.getDeclarator().getMutableDeclSpec().getObjCQualifiers() @@ -4192,9 +4144,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 +4184,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 +4206,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 +4480,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 +4530,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) { @@ -4593,9 +4543,8 @@ // 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) { + for (const AttributeList &AL : D.getAttributes()) { + if (AL.getKind() == AttributeList::AT_Overloadable) { Overloadable = true; break; } @@ -4758,7 +4707,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 +4763,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 +4774,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,9 +5039,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) + for (const AttributeList &AL : chunk.getAttrs()) + if (AL.getKind() == AttributeList::AT_ObjCOwnership) return; const char *attrStr = nullptr; @@ -5117,8 +5064,7 @@ .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ nullptr, SourceLocation(), /*args*/ &Args, 1, AttributeList::AS_GNU); - spliceAttrIntoList(*attr, chunk.getAttrListRef()); - + chunk.getAttrs().add(attr); // TODO: mark whether we did this inference? } @@ -5262,39 +5208,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 +5228,26 @@ TL.setAttrOperandParensRange(SourceRange()); } +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const NonOwningParsedAttributes &attrs, + const NonOwningParsedAttributes &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 +5258,8 @@ : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + fillAttributedTypeLoc(TL, DS.getAttributes(), + NonOwningParsedAttributes{}); Visit(TL.getModifiedLoc()); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { @@ -5484,7 +5431,7 @@ } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, Chunk.getAttrs()); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), NonOwningParsedAttributes{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5617,16 +5564,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 NonOwningParsedAttributes &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 +5593,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 +5616,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 +6509,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 +6542,8 @@ " " + attr.getName()->getName().str() + " "); } - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return true; }; @@ -7239,16 +7190,18 @@ } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - TypeAttrLocation TAL, AttributeList *attrs) { + TypeAttrLocation TAL, + NonOwningParsedAttributes &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. + NonOwningParsedAttributes AttrsCopy {attrs}; + for (AttributeList &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. if (attr.isInvalid())