diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 67 | ||||
-rw-r--r-- | clang/lib/Sema/DeclSpec.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaAttr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCUDA.cpp | 9 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 78 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 87 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 137 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 90 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmtAttr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 96 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaType.cpp | 429 |
15 files changed, 431 insertions, 601 deletions
diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index 4cd32b361da..6d5c6a26ef5 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -60,56 +60,41 @@ static size_t getFreeListIndexForSize(size_t size) { void *AttributeFactory::allocate(size_t size) { // Check for a previously reclaimed attribute. size_t index = getFreeListIndexForSize(size); - if (index < FreeLists.size()) { - if (AttributeList *attr = FreeLists[index]) { - FreeLists[index] = attr->NextInPool; - return attr; - } + if (index < FreeLists.size() && !FreeLists[index].empty()) { + AttributeList *attr = FreeLists[index].back(); + FreeLists[index].pop_back(); + return attr; } // Otherwise, allocate something new. return Alloc.Allocate(size, alignof(AttributeFactory)); } -void AttributeFactory::reclaimPool(AttributeList *cur) { - assert(cur && "reclaiming empty pool!"); - do { - // Read this here, because we're going to overwrite NextInPool - // when we toss 'cur' into the appropriate queue. - AttributeList *next = cur->NextInPool; - - size_t size = cur->allocated_size(); - size_t freeListIndex = getFreeListIndexForSize(size); - - // Expand FreeLists to the appropriate size, if required. - if (freeListIndex >= FreeLists.size()) - FreeLists.resize(freeListIndex+1); - - // Add 'cur' to the appropriate free-list. - cur->NextInPool = FreeLists[freeListIndex]; - FreeLists[freeListIndex] = cur; - - cur = next; - } while (cur); -} +void AttributeFactory::deallocate(AttributeList *Attr) { + size_t size = Attr->allocated_size(); + size_t freeListIndex = getFreeListIndexForSize(size); -void AttributePool::takePool(AttributeList *pool) { - assert(pool); + // Expand FreeLists to the appropriate size, if required. + if (freeListIndex >= FreeLists.size()) + FreeLists.resize(freeListIndex + 1); - // Fast path: this pool is empty. - if (!Head) { - Head = pool; - return; - } +#if !NDEBUG + // In debug mode, zero out the attribute to help find memory overwriting. + memset(Attr, 0, size); +#endif + + // Add 'Attr' to the appropriate free-list. + FreeLists[freeListIndex].push_back(Attr); +} + +void AttributeFactory::reclaimPool(AttributePool &cur) { + for (AttributeList *AL : cur.Attrs) + deallocate(AL); +} - // Reverse the pool onto the current head. This optimizes for the - // pattern of pulling a lot of pools into a single pool. - do { - AttributeList *next = pool->NextInPool; - pool->NextInPool = Head; - Head = pool; - pool = next; - } while (pool); +void AttributePool::takePool(AttributePool &pool) { + Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); + pool.Attrs.clear(); } #include "clang/Sema/AttrParsedAttrKinds.inc" diff --git a/clang/lib/Sema/DeclSpec.cpp b/clang/lib/Sema/DeclSpec.cpp index fe111a5ddea..01c9bad16f1 100644 --- a/clang/lib/Sema/DeclSpec.cpp +++ b/clang/lib/Sema/DeclSpec.cpp @@ -186,7 +186,6 @@ DeclaratorChunk DeclaratorChunk::getFunction(bool hasProto, I.Kind = Function; I.Loc = LocalRangeBegin; I.EndLoc = LocalRangeEnd; - I.Fun.AttrList = nullptr; I.Fun.hasPrototype = hasProto; I.Fun.isVariadic = EllipsisLoc.isValid(); I.Fun.isAmbiguous = isAmbiguous; @@ -995,15 +994,7 @@ void DeclSpec::SaveWrittenBuiltinSpecs() { writtenBS.Width = getTypeSpecWidth(); writtenBS.Type = getTypeSpecType(); // Search the list of attributes for the presence of a mode attribute. - writtenBS.ModeAttr = false; - AttributeList* attrs = getAttributes().getList(); - while (attrs) { - if (attrs->getKind() == AttributeList::AT_Mode) { - writtenBS.ModeAttr = true; - break; - } - attrs = attrs->getNext(); - } + writtenBS.ModeAttr = getAttributes().hasAttribute(AttributeList::AT_Mode); } /// Finish - This does final analysis of the declspec, rejecting things like diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp index 64f12f3f5e4..cc155b7ff6b 100644 --- a/clang/lib/Sema/SemaAttr.cpp +++ b/clang/lib/Sema/SemaAttr.cpp @@ -645,7 +645,7 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (PragmaAttributeStack.empty()) return; for (auto &Entry : PragmaAttributeStack) { - const AttributeList *Attribute = Entry.Attribute; + AttributeList *Attribute = Entry.Attribute; assert(Attribute && "Expected an attribute"); // Ensure that the attribute can be applied to the given declaration. @@ -659,9 +659,10 @@ void Sema::AddPragmaAttributes(Scope *S, Decl *D) { if (!Applies) continue; Entry.IsUsed = true; - assert(!Attribute->getNext() && "Expected just one attribute"); PragmaAttributeCurrentTargetDecl = D; - ProcessDeclAttributeList(S, D, Attribute); + ParsedAttributesView Attrs; + Attrs.addAtStart(Attribute); + ProcessDeclAttributeList(S, D, Attrs); PragmaAttributeCurrentTargetDecl = nullptr; } } diff --git a/clang/lib/Sema/SemaCUDA.cpp b/clang/lib/Sema/SemaCUDA.cpp index a44eeb47c13..5b81eb3a43d 100644 --- a/clang/lib/Sema/SemaCUDA.cpp +++ b/clang/lib/Sema/SemaCUDA.cpp @@ -55,13 +55,14 @@ ExprResult Sema::ActOnCUDAExecConfigExpr(Scope *S, SourceLocation LLLLoc, /*IsExecConfig=*/true); } -Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) { +Sema::CUDAFunctionTarget +Sema::IdentifyCUDATarget(const ParsedAttributesView &Attrs) { bool HasHostAttr = false; bool HasDeviceAttr = false; bool HasGlobalAttr = false; bool HasInvalidTargetAttr = false; - while (Attr) { - switch(Attr->getKind()){ + for (const AttributeList &AL : Attrs) { + switch (AL.getKind()) { case AttributeList::AT_CUDAGlobal: HasGlobalAttr = true; break; @@ -77,8 +78,8 @@ Sema::CUDAFunctionTarget Sema::IdentifyCUDATarget(const AttributeList *Attr) { default: break; } - Attr = Attr->getNext(); } + if (HasInvalidTargetAttr) return CFT_InvalidTarget; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 13ef46b5414..1e63fd3bfe0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4447,10 +4447,9 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, TypeSpecType == DeclSpec::TST_interface || TypeSpecType == DeclSpec::TST_union || TypeSpecType == DeclSpec::TST_enum) { - for (AttributeList* attrs = DS.getAttributes().getList(); attrs; - attrs = attrs->getNext()) - Diag(attrs->getLoc(), diag::warn_declspec_attribute_ignored) - << attrs->getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); + for (const AttributeList &AL : DS.getAttributes()) + Diag(AL.getLoc(), diag::warn_declspec_attribute_ignored) + << AL.getName() << GetDiagnosticTypeSpecifierID(TypeSpecType); } } @@ -6204,29 +6203,21 @@ static bool shouldConsiderLinkage(const FunctionDecl *FD) { llvm_unreachable("Unexpected context"); } -static bool hasParsedAttr(Scope *S, const AttributeList *AttrList, - AttributeList::Kind Kind) { - for (const AttributeList *L = AttrList; L; L = L->getNext()) - if (L->getKind() == Kind) - return true; - return false; -} - static bool hasParsedAttr(Scope *S, const Declarator &PD, AttributeList::Kind Kind) { // Check decl attributes on the DeclSpec. - if (hasParsedAttr(S, PD.getDeclSpec().getAttributes().getList(), Kind)) + if (PD.getDeclSpec().getAttributes().hasAttribute(Kind)) return true; // Walk the declarator structure, checking decl attributes that were in a type // position to the decl itself. for (unsigned I = 0, E = PD.getNumTypeObjects(); I != E; ++I) { - if (hasParsedAttr(S, PD.getTypeObject(I).getAttrs(), Kind)) + if (PD.getTypeObject(I).getAttrs().hasAttribute(Kind)) return true; } // Finally, check attributes on the decl itself. - return hasParsedAttr(S, PD.getAttributes(), Kind); + return PD.getAttributes().hasAttribute(Kind); } /// Adjust the \c DeclContext for a function or variable that might be a @@ -11340,8 +11331,8 @@ Sema::ActOnCXXForRangeIdentifier(Scope *S, SourceLocation IdentLoc, D.takeAttributes(Attrs, AttrEnd); ParsedAttributes EmptyAttrs(Attrs.getPool().getFactory()); - D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/false), - EmptyAttrs, IdentLoc); + D.AddTypeInfo(DeclaratorChunk::getReference(0, IdentLoc, /*lvalue*/ false), + IdentLoc); Decl *Var = ActOnDeclarator(S, D); cast<VarDecl>(Var)->setCXXForRangeDecl(true); FinalizeDeclaration(Var); @@ -12944,7 +12935,7 @@ void Sema::ActOnFinishDelayedAttribute(Scope *S, Decl *D, // Always attach attributes to the underlying decl. if (TemplateDecl *TD = dyn_cast<TemplateDecl>(D)) D = TD->getTemplatedDecl(); - ProcessDeclAttributeList(S, D, Attrs.getList()); + ProcessDeclAttributeList(S, D, Attrs); if (CXXMethodDecl *Method = dyn_cast_or_null<CXXMethodDecl>(D)) if (Method->isStatic()) @@ -13046,18 +13037,16 @@ NamedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc, /*ConstQualifierLoc=*/NoLoc, /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, + /*MutableLoc=*/NoLoc, EST_None, /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - Loc, Loc, D), - DS.getAttributes(), - SourceLocation()); + /*DeclsInPrototype=*/None, Loc, + Loc, D), + std::move(DS.getAttributes()), SourceLocation()); D.SetIdentifier(&II, Loc); // Insert this function into the enclosing block scope. @@ -13529,13 +13518,12 @@ static bool isAcceptableTagRedeclContext(Sema &S, DeclContext *OldDC, Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, AccessSpecifier AS, + const ParsedAttributesView &Attrs, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, - bool ScopedEnumUsesClassTag, - TypeResult UnderlyingType, + bool ScopedEnumUsesClassTag, TypeResult UnderlyingType, bool IsTypeSpecifier, bool IsTemplateParamOrArg, SkipBodyInfo *SkipBody) { // If this is not a definition, it must have a name. @@ -13574,14 +13562,11 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, return nullptr; OwnedDecl = false; - DeclResult Result = CheckClassTemplate(S, TagSpec, TUK, KWLoc, - SS, Name, NameLoc, Attr, - TemplateParams, AS, - ModulePrivateLoc, - /*FriendLoc*/SourceLocation(), - TemplateParameterLists.size()-1, - TemplateParameterLists.data(), - SkipBody); + DeclResult Result = CheckClassTemplate( + S, TagSpec, TUK, KWLoc, SS, Name, NameLoc, Attrs, TemplateParams, + AS, ModulePrivateLoc, + /*FriendLoc*/ SourceLocation(), TemplateParameterLists.size() - 1, + TemplateParameterLists.data(), SkipBody); return Result.get(); } else { // The "template<>" header is extraneous. @@ -14047,7 +14032,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // If this is a use, just return the declaration we found, unless // we have attributes. if (TUK == TUK_Reference || TUK == TUK_Friend) { - if (Attr) { + if (!Attrs.empty()) { // FIXME: Diagnose these attributes. For now, we create a new // declaration to hold them. } else if (TUK == TUK_Reference && @@ -14407,8 +14392,7 @@ CreateNewDecl: if (TUK == TUK_Definition) New->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // If this has an identifier, add it to the scope stack. @@ -15227,7 +15211,8 @@ void Sema::ActOnLastBitfield(SourceLocation DeclLoc, void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, ArrayRef<Decl *> Fields, SourceLocation LBrac, - SourceLocation RBrac, AttributeList *Attr) { + SourceLocation RBrac, + const ParsedAttributesView &Attrs) { assert(EnclosingDecl && "missing record or interface decl"); // If this is an Objective-C @implementation or category and we have @@ -15545,8 +15530,7 @@ void Sema::ActOnFields(Scope *S, SourceLocation RecLoc, Decl *EnclosingDecl, 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<CXXRecordDecl>(Record)) { @@ -15924,7 +15908,7 @@ Sema::SkipBodyInfo Sema::shouldSkipAnonEnumBody(Scope *S, IdentifierInfo *II, Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attr, + const ParsedAttributesView &Attrs, SourceLocation EqualLoc, Expr *Val) { EnumDecl *TheEnumDecl = cast<EnumDecl>(theEnumDecl); EnumConstantDecl *LastEnumConst = @@ -15975,7 +15959,7 @@ Decl *Sema::ActOnEnumConstant(Scope *S, Decl *theEnumDecl, Decl *lastEnumConst, } // Process attributes. - if (Attr) ProcessDeclAttributeList(S, New, Attr); + ProcessDeclAttributeList(S, New, Attrs); AddPragmaAttributes(S, New); // Register this decl in the current scope stack. @@ -16167,14 +16151,12 @@ bool Sema::IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, } void Sema::ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDeclX, - ArrayRef<Decl *> Elements, - Scope *S, AttributeList *Attr) { + Decl *EnumDeclX, ArrayRef<Decl *> Elements, Scope *S, + const ParsedAttributesView &Attrs) { EnumDecl *Enum = cast<EnumDecl>(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) { diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 022d9fe8b89..d352015a510 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -5820,8 +5820,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, if (AL.getKind() == AttributeList::UnknownAttribute || !AL.existsInTarget(S.Context.getTargetInfo())) { S.Diag(AL.getLoc(), AL.isDeclspecAttribute() - ? diag::warn_unhandled_ms_attribute_ignored - : diag::warn_unknown_attribute_ignored) + ? diag::warn_unhandled_ms_attribute_ignored + : diag::warn_unknown_attribute_ignored) << AL.getName(); return; } @@ -5992,8 +5992,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, AL); break; case AttributeList::AT_CUDAHost: - handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, - AL); + handleSimpleAttributeWithExclusions<CUDAHostAttr, CUDAGlobalAttr>(S, D, AL); break; case AttributeList::AT_GNUInline: handleGNUInlineAttr(S, D, AL); @@ -6095,8 +6094,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleObjCRuntimeName(S, D, AL); break; case AttributeList::AT_ObjCRuntimeVisible: - handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL); - break; + handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL); + break; case AttributeList::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; @@ -6177,12 +6176,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL); break; case AttributeList::AT_NotTailCalled: - handleSimpleAttributeWithExclusions<NotTailCalledAttr, - AlwaysInlineAttr>(S, D, AL); + handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>( + S, D, AL); break; case AttributeList::AT_DisableTailCalls: - handleSimpleAttributeWithExclusions<DisableTailCallsAttr, - NakedAttr>(S, D, AL); + handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D, + AL); break; case AttributeList::AT_Used: handleSimpleAttribute<UsedAttr>(S, D, AL); @@ -6458,18 +6457,21 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, /// ProcessDeclAttributeList - Apply all the decl attributes in the specified /// attribute list to the specified decl, ignoring any type attributes. void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, - const AttributeList *AttrList, + const ParsedAttributesView &AttrList, bool IncludeCXX11Attributes) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) - ProcessDeclAttribute(*this, S, D, *l, IncludeCXX11Attributes); + if (AttrList.empty()) + return; + + for (const AttributeList &AL : AttrList) + ProcessDeclAttribute(*this, S, D, AL, IncludeCXX11Attributes); // FIXME: We should be able to handle these cases in TableGen. // GCC accepts // static int a9 __attribute__((weakref)); // but that looks really pointless. We reject it. if (D->hasAttr<WeakRefAttr>() && !D->hasAttr<AliasAttr>()) { - Diag(AttrList->getLoc(), diag::err_attribute_weakref_without_alias) - << cast<NamedDecl>(D); + Diag(AttrList.begin()->getLoc(), diag::err_attribute_weakref_without_alias) + << cast<NamedDecl>(D); D->dropAttr<WeakRefAttr>(); return; } @@ -6517,44 +6519,46 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D, } // Helper for delayed processing TransparentUnion attribute. -void Sema::ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList) { - for (const AttributeList *AL = AttrList; AL; AL = AL->getNext()) - if (AL->getKind() == AttributeList::AT_TransparentUnion) { - handleTransparentUnionAttr(*this, D, *AL); +void Sema::ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) + if (AL.getKind() == AttributeList::AT_TransparentUnion) { + handleTransparentUnionAttr(*this, D, AL); break; } } // Annotation attributes are the only attributes allowed after an access // specifier. -bool Sema::ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList) { - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() == AttributeList::AT_Annotate) { - ProcessDeclAttribute(*this, nullptr, ASDecl, *l, l->isCXX11Attribute()); +bool Sema::ProcessAccessDeclAttributeList( + AccessSpecDecl *ASDecl, const ParsedAttributesView &AttrList) { + for (const AttributeList &AL : AttrList) { + if (AL.getKind() == AttributeList::AT_Annotate) { + ProcessDeclAttribute(*this, nullptr, ASDecl, AL, AL.isCXX11Attribute()); } else { - Diag(l->getLoc(), diag::err_only_annotate_after_access_spec); + Diag(AL.getLoc(), diag::err_only_annotate_after_access_spec); return true; } } - return false; } /// checkUnusedDeclAttributes - Check a list of attributes to see if it /// contains any decl attributes that we should warn about. -static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { - for ( ; A; A = A->getNext()) { +static void checkUnusedDeclAttributes(Sema &S, const ParsedAttributesView &A) { + for (const AttributeList &AL : A) { // Only warn if the attribute is an unignored, non-type attribute. - if (A->isUsedAsTypeAttr() || A->isInvalid()) continue; - if (A->getKind() == AttributeList::IgnoredAttribute) continue; + if (AL.isUsedAsTypeAttr() || AL.isInvalid()) + continue; + if (AL.getKind() == AttributeList::IgnoredAttribute) + continue; - if (A->getKind() == AttributeList::UnknownAttribute) { - S.Diag(A->getLoc(), diag::warn_unknown_attribute_ignored) - << A->getName() << A->getRange(); + if (AL.getKind() == AttributeList::UnknownAttribute) { + S.Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) + << AL.getName() << AL.getRange(); } else { - S.Diag(A->getLoc(), diag::warn_attribute_not_on_decl) - << A->getName() << A->getRange(); + S.Diag(AL.getLoc(), diag::warn_attribute_not_on_decl) + << AL.getName() << AL.getRange(); } } } @@ -6563,7 +6567,7 @@ static void checkUnusedDeclAttributes(Sema &S, const AttributeList *A) { /// 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()); @@ -6670,20 +6674,19 @@ void Sema::ProcessPragmaWeak(Scope *S, Decl *D) { /// specified in many different places, and we need to find and apply them all. void Sema::ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD) { // Apply decl attributes from the DeclSpec if present. - if (const AttributeList *Attrs = PD.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, D, Attrs); + if (!PD.getDeclSpec().getAttributes().empty()) + ProcessDeclAttributeList(S, D, PD.getDeclSpec().getAttributes()); // Walk the declarator structure, applying decl attributes that were in a type // position to the decl itself. This handles cases like: // int *__attr__(x)** D; // when X is a decl attribute. for (unsigned i = 0, e = PD.getNumTypeObjects(); i != e; ++i) - if (const AttributeList *Attrs = PD.getTypeObject(i).getAttrs()) - ProcessDeclAttributeList(S, D, Attrs, /*IncludeCXX11Attributes=*/false); + ProcessDeclAttributeList(S, D, PD.getTypeObject(i).getAttrs(), + /*IncludeCXX11Attributes=*/false); // Finally, apply any attributes on the decl itself. - if (const AttributeList *Attrs = PD.getAttributes()) - ProcessDeclAttributeList(S, D, Attrs); + ProcessDeclAttributeList(S, D, PD.getAttributes()); // Apply additional attributes specified by '#pragma clang attribute'. AddPragmaAttributes(S, D); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 822d5ef254a..6f411ca26de 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -2300,18 +2300,13 @@ Sema::ActOnBaseSpecifier(Decl *classdecl, SourceRange SpecifierRange, // We do not support any C++11 attributes on base-specifiers yet. // Diagnose any attributes we see. - if (!Attributes.empty()) { - for (AttributeList *Attr = Attributes.getList(); Attr; - Attr = Attr->getNext()) { - if (Attr->isInvalid() || - Attr->getKind() == AttributeList::IgnoredAttribute) - continue; - Diag(Attr->getLoc(), - Attr->getKind() == AttributeList::UnknownAttribute - ? diag::warn_unknown_attribute_ignored - : diag::err_base_specifier_attribute) - << Attr->getName(); - } + for (const AttributeList &AL : Attributes) { + if (AL.isInvalid() || AL.getKind() == AttributeList::IgnoredAttribute) + continue; + Diag(AL.getLoc(), AL.getKind() == AttributeList::UnknownAttribute + ? diag::warn_unknown_attribute_ignored + : diag::err_base_specifier_attribute) + << AL.getName(); } TypeSourceInfo *TInfo = nullptr; @@ -2691,10 +2686,9 @@ std::string Sema::getAmbiguousPathsDisplayString(CXXBasePaths &Paths) { //===----------------------------------------------------------------------===// /// ActOnAccessSpecifier - Parsed an access specifier followed by a colon. -bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, +bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs) { + const ParsedAttributesView &Attrs) { assert(Access != AS_none && "Invalid kind for syntactic access specifier!"); AccessSpecDecl *ASDecl = AccessSpecDecl::Create(Context, Access, CurContext, ASLoc, ColonLoc); @@ -2822,10 +2816,14 @@ static bool InitializationHasSideEffects(const FieldDecl &FD) { return false; } -static AttributeList *getMSPropertyAttr(AttributeList *list) { - for (AttributeList *it = list; it != nullptr; it = it->getNext()) - if (it->isDeclspecPropertyAttribute()) - return it; +static const AttributeList * +getMSPropertyAttr(const ParsedAttributesView &list) { + ParsedAttributesView::const_iterator Itr = + llvm::find_if(list, [](const AttributeList &AL) { + return AL.isDeclspecPropertyAttribute(); + }); + if (Itr != list.end()) + return &*Itr; return nullptr; } @@ -2904,8 +2902,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, assert(!DS.isFriendSpecified()); bool isFunc = D.isDeclarationOfFunction(); - AttributeList *MSPropertyAttr = - getMSPropertyAttr(D.getDeclSpec().getAttributes().getList()); + const AttributeList *MSPropertyAttr = + getMSPropertyAttr(D.getDeclSpec().getAttributes()); if (cast<CXXRecordDecl>(CurContext)->isInterface()) { // The Microsoft extension __interface only permits public member functions @@ -3073,7 +3071,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, if (MSPropertyAttr) { Member = HandleMSProperty(S, cast<CXXRecordDecl>(CurContext), Loc, D, - BitWidth, InitStyle, AS, MSPropertyAttr); + BitWidth, InitStyle, AS, *MSPropertyAttr); if (!Member) return nullptr; isInstField = false; @@ -7809,22 +7807,20 @@ void Sema::checkIllFormedTrivialABIStruct(CXXRecordDecl &RD) { } } -void Sema::ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, - SourceLocation RBrac, - AttributeList *AttrList) { +void Sema::ActOnFinishCXXMemberSpecification( + Scope *S, SourceLocation RLoc, Decl *TagDecl, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList) { if (!TagDecl) return; AdjustDeclIfTemplate(TagDecl); - for (const AttributeList* l = AttrList; l; l = l->getNext()) { - if (l->getKind() != AttributeList::AT_Visibility) + for (const AttributeList &AL : AttrList) { + if (AL.getKind() != AttributeList::AT_Visibility) continue; - l->setInvalid(); - Diag(l->getLoc(), diag::warn_attribute_after_definition_ignored) << - l->getName(); + AL.setInvalid(); + Diag(AL.getLoc(), diag::warn_attribute_after_definition_ignored) + << AL.getName(); } ActOnFields(S, RLoc, TagDecl, llvm::makeArrayRef( @@ -8751,14 +8747,10 @@ static void DiagnoseNamespaceInlineMismatch(Sema &S, SourceLocation KeywordLoc, /// ActOnStartNamespaceDef - This is called at the start of a namespace /// definition. -Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, - SourceLocation InlineLoc, - SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *II, - SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl *&UD) { +Decl *Sema::ActOnStartNamespaceDef( + Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc, + SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace, + const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) { SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc; // For anonymous namespace, take the location of the left brace. SourceLocation Loc = II ? IdentLoc : LBrace; @@ -9273,13 +9265,11 @@ static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, return false; } -Decl *Sema::ActOnUsingDirective(Scope *S, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, - SourceLocation IdentLoc, - IdentifierInfo *NamespcName, - AttributeList *AttrList) { +Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + const ParsedAttributesView &AttrList) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); assert(NamespcName && "Invalid NamespcName."); assert(IdentLoc.isValid() && "Invalid NamespceName location."); @@ -9371,15 +9361,12 @@ void Sema::PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir) { S->PushUsingDirective(UDir); } - -Decl *Sema::ActOnUsingDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnUsingDeclaration(Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, UnqualifiedId &Name, SourceLocation EllipsisLoc, - AttributeList *AttrList) { + const ParsedAttributesView &AttrList) { assert(S->getFlags() & Scope::DeclScope && "Invalid Scope."); if (SS.isEmpty()) { @@ -9836,15 +9823,11 @@ private: /// \param IsInstantiation - Whether this call arises from an /// instantiation of an unresolved using declaration. We treat /// the lookup differently for these declarations. -NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation) { +NamedDecl *Sema::BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation) { assert(!SS.isInvalid() && "Invalid CXXScopeSpec."); SourceLocation IdentLoc = NameInfo.getLoc(); assert(IdentLoc.isValid() && "Invalid TargetName location."); @@ -10410,14 +10393,11 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } -Decl *Sema::ActOnAliasDeclaration(Scope *S, - AccessSpecifier AS, +Decl *Sema::ActOnAliasDeclaration(Scope *S, AccessSpecifier AS, MultiTemplateParamsArg TemplateParamLists, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec) { + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec) { // Skip up to the relevant declaration scope. while (S->isTemplateParamScope()) S = S->getParent(); @@ -13575,13 +13555,12 @@ Decl *Sema::ActOnFinishLinkageSpecification(Scope *S, } Decl *Sema::ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + const ParsedAttributesView &AttrList, SourceLocation SemiLoc) { Decl *ED = EmptyDecl::Create(Context, CurContext, SemiLoc); // Attribute declarations appertain to empty declaration so we handle // them here. - if (AttrList) - ProcessDeclAttributeList(S, ED, AttrList); + ProcessDeclAttributeList(S, ED, AttrList); CurContext->addDecl(ED); return ED; @@ -13920,10 +13899,9 @@ FriendDecl *Sema::CheckFriendTypeDecl(SourceLocation LocStart, /// templated. Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists) { TagTypeKind Kind = TypeWithKeyword::getTagTypeKindForTypeSpec(TagSpec); @@ -14036,7 +14014,6 @@ Decl *Sema::ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, return Friend; } - /// Handle a friend type declaration. This works in tandem with /// ActOnTag. /// @@ -15407,11 +15384,11 @@ void Sema::actOnDelayedExceptionSpecification(Decl *MethodD, /// HandleMSProperty - Analyze a __delcspec(property) field of a C++ class. /// MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, - SourceLocation DeclStart, - Declarator &D, Expr *BitWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr) { + const AttributeList &MSPropertyAttr) { IdentifierInfo *II = D.getIdentifier(); if (!II) { Diag(DeclStart, diag::err_anonymous_property); @@ -15474,7 +15451,7 @@ MSPropertyDecl *Sema::HandleMSProperty(Scope *S, RecordDecl *Record, 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); diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 8c621dfa40c..e1b033ea828 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -948,16 +948,14 @@ static bool checkTypeParamListConsistency(Sema &S, return false; } -Decl *Sema:: -ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, SourceLocation SuperLoc, - ArrayRef<ParsedType> 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<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { assert(ClassName && "Missing class identifier"); // Check for another declaration kind with the same name. @@ -1042,9 +1040,8 @@ ActOnStartClassInterface(Scope *S, SourceLocation AtInterfaceLoc, IDecl->setInvalidDecl(); } } - - if (AttrList) - ProcessDeclAttributeList(TUScope, IDecl, AttrList); + + ProcessDeclAttributeList(TUScope, IDecl, AttrList); AddPragmaAttributes(TUScope, IDecl); PushOnScopeChains(IDecl, TUScope); @@ -1183,15 +1180,11 @@ bool Sema::CheckForwardProtocolDeclarationForCircularDependency( return res; } -Decl * -Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, - SourceLocation ProtocolLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartProtocolInterface( + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { bool err = false; // FIXME: Deal with AttrList. assert(ProtocolName && "Missing protocol identifier"); @@ -1234,9 +1227,8 @@ Sema::ActOnStartProtocolInterface(SourceLocation AtProtoInterfaceLoc, 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 @@ void Sema::actOnObjCTypeArgsOrProtocolQualifiers( // add the '*'. if (type->getAs<ObjCInterfaceType>()) { SourceLocation starLoc = getLocForEndOfToken(loc); - ParsedAttributes parsedAttrs(attrFactory); D.AddTypeInfo(DeclaratorChunk::getPointer(/*typeQuals=*/0, starLoc, SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation(), SourceLocation()), - parsedAttrs, starLoc); // Diagnose the missing '*'. @@ -1752,7 +1742,7 @@ void Sema::DiagnoseClassExtensionDupMethods(ObjCCategoryDecl *CAT, Sema::DeclGroupPtrTy Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, ArrayRef<IdentifierLocPair> IdentList, - AttributeList *attrList) { + const ParsedAttributesView &attrList) { SmallVector<Decl *, 8> DeclsInGroup; for (const IdentifierLocPair &IdentPair : IdentList) { IdentifierInfo *Ident = IdentPair.first; @@ -1765,9 +1755,8 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, PushOnScopeChains(PDecl, TUScope); CheckObjCDeclScope(PDecl); - - if (attrList) - ProcessDeclAttributeList(TUScope, PDecl, attrList); + + ProcessDeclAttributeList(TUScope, PDecl, attrList); AddPragmaAttributes(TUScope, PDecl); if (PrevDecl) @@ -1779,17 +1768,13 @@ Sema::ActOnForwardProtocolDeclaration(SourceLocation AtProtocolLoc, return BuildDeclaratorGroup(DeclsInGroup); } -Decl *Sema:: -ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList) { +Decl *Sema::ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList) { ObjCCategoryDecl *CDecl; ObjCInterfaceDecl *IDecl = getObjCInterfaceDecl(ClassName, ClassLoc, true); @@ -1858,8 +1843,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, // 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) { @@ -4516,17 +4500,14 @@ static void checkObjCMethodX86VectorTypes(Sema &SemaRef, } Decl *Sema::ActOnMethodDeclaration( - Scope *S, - SourceLocation MethodLoc, SourceLocation EndLoc, - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef<SourceLocation> SelectorLocs, - Selector Sel, + Scope *S, SourceLocation MethodLoc, SourceLocation EndLoc, + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef<SourceLocation> SelectorLocs, Selector Sel, // optional arguments. The number of types/arguments is obtained // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodDeclKind, + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodDeclKind, bool isVariadic, bool MethodDefinition) { // Make sure we can establish a context for the method. if (!CurContext->isObjCContainer()) { @@ -4634,8 +4615,7 @@ Decl *Sema::ActOnMethodDeclaration( ObjCMethod->setObjCDeclQualifier( CvtQTToAstBitMask(ReturnQT.getObjCDeclQualifier())); - if (AttrList) - ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); + ProcessDeclAttributeList(TUScope, ObjCMethod, AttrList); AddPragmaAttributes(TUScope, ObjCMethod); // Add the method now. diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 5e69feceda6..9e53beb449b 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1170,7 +1170,7 @@ void Sema::ActOnLambdaError(SourceLocation StartLoc, Scope *CurScope, Class->setInvalidDecl(); SmallVector<Decl*, 4> Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); PopFunctionScopeInfo(); @@ -1608,7 +1608,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, // Finalize the lambda class. SmallVector<Decl*, 4> Fields(Class->fields()); ActOnFields(nullptr, Class->getLocation(), Class, Fields, SourceLocation(), - SourceLocation(), nullptr); + SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Class); } diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index ccf25ee9ebe..058a2cd4f21 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -4283,7 +4283,7 @@ void Sema::ActOnCapturedRegionError() { SmallVector<Decl*, 4> Fields(Record->fields()); ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields, - SourceLocation(), SourceLocation(), /*AttributeList=*/nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); PopDeclContext(); PopFunctionScopeInfo(); diff --git a/clang/lib/Sema/SemaStmtAttr.cpp b/clang/lib/Sema/SemaStmtAttr.cpp index e55e20c2827..dbd967cc939 100644 --- a/clang/lib/Sema/SemaStmtAttr.cpp +++ b/clang/lib/Sema/SemaStmtAttr.cpp @@ -313,11 +313,12 @@ static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A, } } -StmtResult Sema::ProcessStmtAttributes(Stmt *S, AttributeList *AttrList, +StmtResult Sema::ProcessStmtAttributes(Stmt *S, + const ParsedAttributesView &AttrList, SourceRange Range) { SmallVector<const Attr*, 8> 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); } diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 68a5196f6b8..276a617d1ac 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -1263,17 +1263,13 @@ static void SetNestedNameSpecifier(TagDecl *T, const CXXScopeSpec &SS) { T->setQualifierInfo(SS.getWithLocInContext(T->getASTContext())); } -DeclResult -Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList** OuterTemplateParamLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, SkipBodyInfo *SkipBody) { assert(TemplateParams && TemplateParams->size() > 0 && "No template parameters"); assert(TUK != TUK_Reference && "Can only declare or define class templates"); @@ -1613,8 +1609,7 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, if (TUK == TUK_Definition) NewClass->startDefinition(); - if (Attr) - ProcessDeclAttributeList(S, NewClass, Attr); + ProcessDeclAttributeList(S, NewClass, Attr); if (PrevClassTemplate) mergeDeclAttributes(NewClass, PrevClassTemplate->getTemplatedDecl()); @@ -7401,16 +7396,11 @@ bool Sema::CheckTemplatePartialSpecializationArgs( return false; } -DeclResult -Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, - TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg - TemplateParameterLists, - SkipBodyInfo *SkipBody) { +DeclResult Sema::ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, SkipBodyInfo *SkipBody) { assert(TUK != TUK_Reference && "References are not specializations"); CXXScopeSpec &SS = TemplateId.SS; @@ -7711,8 +7701,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, } } - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add alignment attributes if necessary; these attributes are checked when // the ASTContext lays out the structure. @@ -8564,19 +8553,12 @@ static void dllExportImportClassTemplateSpecialization( } // Explicit instantiation of a class template specialization -DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy TemplateD, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgsIn, - SourceLocation RAngleLoc, - AttributeList *Attr) { +DeclResult Sema::ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy TemplateD, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgsIn, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr) { // Find the class template we're specializing TemplateName Name = TemplateD.get(); TemplateDecl *TD = Name.getAsTemplateDecl(); @@ -8617,11 +8599,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, if (TSK == TSK_ExplicitInstantiationDeclaration) { // Check for dllexport class template instantiation declarations. - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLExport) { + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLExport) { Diag(ExternLoc, diag::warn_attribute_dllexport_explicit_instantiation_decl); - Diag(A->getLoc(), diag::note_attribute); + Diag(AL.getLoc(), diag::note_attribute); break; } } @@ -8641,10 +8623,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Check for dllimport class template instantiation definitions. bool DLLImport = ClassTemplate->getTemplatedDecl()->getAttr<DLLImportAttr>(); - for (AttributeList *A = Attr; A; A = A->getNext()) { - if (A->getKind() == AttributeList::AT_DLLImport) + for (const AttributeList &AL : Attr) { + if (AL.getKind() == AttributeList::AT_DLLImport) DLLImport = true; - if (A->getKind() == AttributeList::AT_DLLExport) { + if (AL.getKind() == AttributeList::AT_DLLExport) { // dllexport trumps dllimport here. DLLImport = false; break; @@ -8754,8 +8736,7 @@ Sema::ActOnExplicitInstantiation(Scope *S, Specialization->setBraceRange(SourceRange()); bool PreviouslyDLLExported = Specialization->hasAttr<DLLExportAttr>(); - if (Attr) - ProcessDeclAttributeList(S, Specialization, Attr); + ProcessDeclAttributeList(S, Specialization, Attr); // Add the explicit instantiation into its lexical context. However, // since explicit instantiations are never found by name lookup, we @@ -8853,15 +8834,11 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Explicit instantiation of a member class of a class template. DeclResult -Sema::ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr) { +Sema::ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, unsigned TagSpec, + SourceLocation KWLoc, CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr) { bool Owned = false; bool IsDependent = false; @@ -9163,8 +9140,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, Prev->setTemplateSpecializationKind(TSK, D.getIdentifierLoc()); if (PrevTemplate) { // Merge attributes. - if (AttributeList *Attr = D.getDeclSpec().getAttributes().getList()) - ProcessDeclAttributeList(S, Prev, Attr); + ProcessDeclAttributeList(S, Prev, D.getDeclSpec().getAttributes()); } if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateVariableDefinition(D.getIdentifierLoc(), Prev); @@ -9200,7 +9176,6 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, // template. UnresolvedSet<8> TemplateMatches; FunctionDecl *NonTemplateMatch = nullptr; - AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); TemplateSpecCandidateSet FailedCandidates(D.getIdentifierLoc()); for (LookupResult::iterator P = Previous.begin(), PEnd = Previous.end(); P != PEnd; ++P) { @@ -9248,7 +9223,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, if (LangOpts.CUDA && IdentifyCUDATarget(Specialization, /* IgnoreImplicitHDAttributes = */ true) != - IdentifyCUDATarget(Attr)) { + IdentifyCUDATarget(D.getDeclSpec().getAttributes())) { FailedCandidates.addCandidate().set( P.getPair(), FunTmpl->getTemplatedDecl(), MakeDeductionFailureInfo(Context, TDK_CUDATargetMismatch, Info)); @@ -9327,8 +9302,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, 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. diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 2218bdd958e..5a4a6bd033c 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -2125,7 +2125,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation, // Finish checking fields. ActOnFields(nullptr, Instantiation->getLocation(), Instantiation, Fields, - SourceLocation(), SourceLocation(), nullptr); + SourceLocation(), SourceLocation(), ParsedAttributesView()); CheckCompletedCXXClass(Instantiation); // Default arguments are parsed, if not instantiated. We can go instantiate diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 68857d972b5..5109dc8290f 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1118,8 +1118,7 @@ void TemplateDeclInstantiator::InstantiateEnumDefinition( } SemaRef.ActOnEnumBody(Enum->getLocation(), Enum->getBraceRange(), Enum, - Enumerators, - nullptr, nullptr); + Enumerators, nullptr, ParsedAttributesView()); } Decl *TemplateDeclInstantiator::VisitEnumConstantDecl(EnumConstantDecl *D) { @@ -2648,7 +2647,8 @@ Decl *TemplateDeclInstantiator::instantiateUnresolvedUsingDecl( NamedDecl *UD = SemaRef.BuildUsingDeclaration( /*Scope*/ nullptr, D->getAccess(), D->getUsingLoc(), - /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, nullptr, + /*HasTypename*/ TD, TypenameLoc, SS, NameInfo, EllipsisLoc, + ParsedAttributesView(), /*IsInstantiation*/ true); if (UD) SemaRef.Context.setInstantiatedFromUsingDecl(UD, D); diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index c7e251d35b4..18c5ce75d1e 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -195,10 +195,10 @@ namespace { chunkIndex = idx; } - AttributeList *&getCurrentAttrListRef() const { + ParsedAttributesView &getCurrentAttributes() const { if (isProcessingDeclSpec()) - return getMutableDeclSpec().getAttributes().getListRef(); - return declarator.getTypeObject(chunkIndex).getAttrListRef(); + return getMutableDeclSpec().getAttributes(); + return declarator.getTypeObject(chunkIndex).getAttrs(); } /// Save the current set of attributes on the DeclSpec. @@ -207,9 +207,8 @@ namespace { 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 @@ namespace { void restoreDeclSpecAttrs() { assert(hasSavedAttrs); - if (savedAttrs.empty()) { - getMutableDeclSpec().getAttributes().set(nullptr); - return; - } - - getMutableDeclSpec().getAttributes().set(savedAttrs[0]); - for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i) - savedAttrs[i]->setNext(savedAttrs[i+1]); - savedAttrs.back()->setNext(nullptr); + getMutableDeclSpec().getAttributes().clearListOnly(); + for (AttributeList *AL : savedAttrs) + getMutableDeclSpec().getAttributes().addAtStart(AL); } }; } // end anonymous namespace -static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) { - attr.setNext(head); - head = &attr; -} - -static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) { - if (head == &attr) { - head = attr.getNext(); - return; - } - - AttributeList *cur = head; - while (true) { - assert(cur && cur->getNext() && "ran out of attrs?"); - if (cur->getNext() == &attr) { - cur->setNext(attr.getNext()); - return; - } - cur = cur->getNext(); - } -} - static void moveAttrFromListToList(AttributeList &attr, - AttributeList *&fromList, - AttributeList *&toList) { - spliceAttrOutOfList(attr, fromList); - spliceAttrIntoList(attr, toList); + ParsedAttributesView &fromList, + ParsedAttributesView &toList) { + fromList.remove(&attr); + toList.addAtStart(&attr); } /// The location of a type attribute. @@ -293,9 +264,8 @@ enum TypeAttrLocation { TAL_DeclName }; -static void processTypeAttrs(TypeProcessingState &state, - QualType &type, TypeAttrLocation TAL, - AttributeList *attrs); +static void processTypeAttrs(TypeProcessingState &state, QualType &type, + TypeAttrLocation TAL, ParsedAttributesView &attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, AttributeList &attr, @@ -416,8 +386,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, /*onlyBlockPointers=*/true); if (!destChunk) destChunk = &chunk; - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - destChunk->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + destChunk->getAttrs()); return; } @@ -432,8 +402,8 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state, if (DeclaratorChunk *dest = maybeMovePastReturnType( declarator, i, /*onlyBlockPointers=*/true)) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - dest->getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + dest->getAttrs()); return; } } @@ -493,8 +463,8 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // attribute from being applied multiple times and gives // the source-location-filler something to work with. state.saveDeclSpecAttrs(); - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getMutableDeclSpec().getAttributes().getListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getMutableDeclSpec().getAttributes()); return; } } @@ -502,13 +472,13 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state, // Otherwise, if we found an appropriate chunk, splice the attribute // into it. if (innermost != -1U) { - moveAttrFromListToList(attr, declarator.getAttrListRef(), - declarator.getTypeObject(innermost).getAttrListRef()); + moveAttrFromListToList(attr, declarator.getAttributes(), + declarator.getTypeObject(innermost).getAttrs()); return; } // Otherwise, diagnose when we're done building the type. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -527,8 +497,8 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, DeclaratorChunk &chunk = declarator.getTypeObject(i-1); switch (chunk.Kind) { case DeclaratorChunk::Function: - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return; case DeclaratorChunk::Paren: @@ -548,11 +518,9 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state, /// Try to distribute a function type attribute to the innermost /// function chunk or type. Returns true if the attribute was /// distributed, false if no location was found. -static bool -distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, - AttributeList &attr, - AttributeList *&attrList, - QualType &declSpecType) { +static bool distributeFunctionTypeAttrToInnermost( + TypeProcessingState &state, AttributeList &attr, + ParsedAttributesView &attrList, QualType &declSpecType) { Declarator &declarator = state.getDeclarator(); // Put it on the innermost function chunk, if there is one. @@ -560,7 +528,7 @@ distributeFunctionTypeAttrToInnermost(TypeProcessingState &state, DeclaratorChunk &chunk = declarator.getTypeObject(i); if (chunk.Kind != DeclaratorChunk::Function) continue; - moveAttrFromListToList(attr, attrList, chunk.getAttrListRef()); + moveAttrFromListToList(attr, attrList, chunk.getAttrs()); return true; } @@ -579,15 +547,14 @@ distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state, // the declarators. Move them straight there. We don't support the // 'put them wherever you like' semantics we allow for GNU attributes. if (attr.isCXX11Attribute()) { - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - state.getDeclarator().getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + state.getDeclarator().getAttributes()); return; } // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - state.getCurrentAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, state.getCurrentAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is @@ -604,14 +571,13 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, Declarator &declarator = state.getDeclarator(); // Try to distribute to the innermost. - if (distributeFunctionTypeAttrToInnermost(state, attr, - declarator.getAttrListRef(), - declSpecType)) + if (distributeFunctionTypeAttrToInnermost( + state, attr, declarator.getAttributes(), declSpecType)) return; // If that failed, diagnose the bad attribute when the declarator is // fully built. - spliceAttrOutOfList(attr, declarator.getAttrListRef()); + declarator.getAttributes().remove(&attr); state.addIgnoredTypeAttr(attr); } @@ -627,24 +593,25 @@ distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state, static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, QualType &declSpecType) { // Collect all the type attributes from the declarator itself. - assert(state.getDeclarator().getAttributes() && "declarator has no attrs!"); - AttributeList *attr = state.getDeclarator().getAttributes(); - AttributeList *next; - do { - next = attr->getNext(); - + assert(!state.getDeclarator().getAttributes().empty() && + "declarator has no attrs!"); + // The called functions in this loop actually remove things from the current + // list, so iterating over the existing list isn't possible. Instead, make a + // non-owning copy and iterate over that. + ParsedAttributesView AttrsCopy{state.getDeclarator().getAttributes()}; + for (AttributeList &attr : AttrsCopy) { // Do not distribute C++11 attributes. They have strict rules for what // they appertain to. - if (attr->isCXX11Attribute()) + if (attr.isCXX11Attribute()) continue; - switch (attr->getKind()) { + switch (attr.getKind()) { OBJC_POINTER_TYPE_ATTRS_CASELIST: - distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeObjCPointerTypeAttrFromDeclarator(state, attr, declSpecType); break; FUNCTION_TYPE_ATTRS_CASELIST: - distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType); + distributeFunctionTypeAttrFromDeclarator(state, attr, declSpecType); break; MS_TYPE_ATTRS_CASELIST: @@ -661,7 +628,7 @@ static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state, default: break; } - } while ((attr = next)); + } } /// Add a synthetic '()' to a block-literal declarator if it is @@ -761,28 +728,18 @@ static bool checkOmittedBlockReturnType(Sema &S, Declarator &declarator, 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<AttributeList *, 2> ToBeRemoved; + for (AttributeList &AL : declarator.getMutableDeclSpec().getAttributes()) { + if (AL.isInvalid() || !AL.isTypeAttr()) continue; - } - S.Diag(attr.getLoc(), + S.Diag(AL.getLoc(), diag::warn_block_literal_attributes_on_omitted_return_type) - << attr.getName(); - // Remove cur from the list. - if (prev) { - prev->setNext(cur->getNext()); - prev = cur; - } else { - attrs = cur->getNext(); - } + << AL.getName(); + ToBeRemoved.push_back(&AL); } + // Remove bad attributes from the list. + for (AttributeList *AL : ToBeRemoved) + declarator.getMutableDeclSpec().getAttributes().remove(AL); // Warn if we see type qualifiers for omitted return type on a block literal. const DeclSpec &DS = declarator.getDeclSpec(); @@ -1210,18 +1167,11 @@ TypeResult Sema::actOnObjCTypeArgsAndProtocolQualifiers( 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<OpenCLAccessAttr::Spelling>( - Attr.getSemanticSpelling()); - } - } while (Next); - } +static OpenCLAccessAttr::Spelling +getImageAccess(const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) + if (AL.getKind() == AttributeList::AT_OpenCLAccess) + return static_cast<OpenCLAccessAttr::Spelling>(AL.getSemanticSpelling()); return OpenCLAccessAttr::Keyword_read_only; } @@ -1237,7 +1187,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { Sema &S = state.getSema(); Declarator &declarator = state.getDeclarator(); - const DeclSpec &DS = declarator.getDeclSpec(); + DeclSpec &DS = declarator.getMutableDeclSpec(); SourceLocation DeclLoc = declarator.getIdentifierLoc(); if (DeclLoc.isInvalid()) DeclLoc = DS.getLocStart(); @@ -1582,16 +1532,19 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { } break; -#define GENERIC_IMAGE_TYPE(ImgType, Id) \ - case DeclSpec::TST_##ImgType##_t: \ - switch (getImageAccess(DS.getAttributes().getList())) { \ - case OpenCLAccessAttr::Keyword_write_only: \ - Result = Context.Id##WOTy; break; \ - case OpenCLAccessAttr::Keyword_read_write: \ - Result = Context.Id##RWTy; break; \ - case OpenCLAccessAttr::Keyword_read_only: \ - Result = Context.Id##ROTy; break; \ - } \ +#define GENERIC_IMAGE_TYPE(ImgType, Id) \ + case DeclSpec::TST_##ImgType##_t: \ + switch (getImageAccess(DS.getAttributes())) { \ + case OpenCLAccessAttr::Keyword_write_only: \ + Result = Context.Id##WOTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_write: \ + Result = Context.Id##RWTy; \ + break; \ + case OpenCLAccessAttr::Keyword_read_only: \ + Result = Context.Id##ROTy; \ + break; \ + } \ break; #include "clang/Basic/OpenCLImageTypes.def" @@ -1644,7 +1597,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // attributes are pushed around. // pipe attributes will be handled later ( at GetFullTypeForDeclarator ) if (!DS.isTypeSpecPipe()) - processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList()); + processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes()); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -2646,9 +2599,8 @@ static void inferARCWriteback(TypeProcessingState &state, if (chunk.Kind != DeclaratorChunk::Pointer && chunk.Kind != DeclaratorChunk::BlockPointer) return; - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) + for (const AttributeList &AL : chunk.getAttrs()) + if (AL.getKind() == AttributeList::AT_ObjCOwnership) return; transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing, @@ -2813,7 +2765,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // "void" instead. T = SemaRef.Context.VoidTy; processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; case UnqualifiedIdKind::IK_DeductionGuideName: @@ -2830,7 +2782,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, break; } - if (D.getAttributes()) + if (!D.getAttributes().empty()) distributeTypeAttrsFromDeclarator(state, T); // C++11 [dcl.spec.auto]p5: reject 'auto' if it is not in an allowed context. @@ -3314,21 +3266,20 @@ static void warnAboutRedundantParens(Sema &S, Declarator &D, QualType T) { /// this is the outermost chunk, then we can determine the CC from the /// declarator context. If not, then this could be either a member function /// type or normal function type. -static CallingConv -getCCForDeclaratorChunk(Sema &S, Declarator &D, - const DeclaratorChunk::FunctionTypeInfo &FTI, - unsigned ChunkIndex) { +static CallingConv getCCForDeclaratorChunk( + Sema &S, Declarator &D, const ParsedAttributesView &AttrList, + const DeclaratorChunk::FunctionTypeInfo &FTI, unsigned ChunkIndex) { assert(D.getTypeObject(ChunkIndex).Kind == DeclaratorChunk::Function); // Check for an explicit CC attribute. - for (auto Attr = FTI.AttrList; Attr; Attr = Attr->getNext()) { - switch (Attr->getKind()) { - CALLING_CONV_ATTRS_CASELIST: { + for (const AttributeList &AL : AttrList) { + switch (AL.getKind()) { + CALLING_CONV_ATTRS_CASELIST : { // Ignore attributes that don't validate or can't apply to the // function type. We'll diagnose the failure to apply them in // handleFunctionTypeAttr. CallingConv CC; - if (!S.CheckCallingConvAttr(*Attr, CC) && + if (!S.CheckCallingConvAttr(AL, CC) && (!FTI.isVariadic || supportsVariadicCall(CC))) { return CC; } @@ -3384,9 +3335,8 @@ getCCForDeclaratorChunk(Sema &S, Declarator &D, // convention attribute. This is the simplest place to infer // calling convention for OpenCL kernels. if (S.getLangOpts().OpenCL) { - for (const AttributeList *Attr = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_OpenCLKernel) { + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_OpenCLKernel) { CC = CC_OpenCLKernel; break; } @@ -3437,12 +3387,11 @@ IdentifierInfo *Sema::getNSErrorIdent() { /// Check whether there is a nullability attribute of any kind in the given /// attribute list. -static bool hasNullabilityAttr(const AttributeList *attrs) { - for (const AttributeList *attr = attrs; attr; - attr = attr->getNext()) { - if (attr->getKind() == AttributeList::AT_TypeNonNull || - attr->getKind() == AttributeList::AT_TypeNullable || - attr->getKind() == AttributeList::AT_TypeNullUnspecified) +static bool hasNullabilityAttr(const ParsedAttributesView &attrs) { + for (const AttributeList &AL : attrs) { + if (AL.getKind() == AttributeList::AT_TypeNonNull || + AL.getKind() == AttributeList::AT_TypeNullable || + AL.getKind() == AttributeList::AT_TypeNullUnspecified) return true; } @@ -4044,19 +3993,16 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // On pointer-to-pointer parameters marked cf_returns_retained or // cf_returns_not_retained, if the outer pointer is explicit then // infer the inner pointer as _Nullable. - auto hasCFReturnsAttr = [](const AttributeList *NextAttr) -> bool { - while (NextAttr) { - if (NextAttr->getKind() == AttributeList::AT_CFReturnsRetained || - NextAttr->getKind() == AttributeList::AT_CFReturnsNotRetained) - return true; - NextAttr = NextAttr->getNext(); - } - return false; + auto hasCFReturnsAttr = + [](const ParsedAttributesView &AttrList) -> bool { + return AttrList.hasAttribute(AttributeList::AT_CFReturnsRetained) || + AttrList.hasAttribute( + AttributeList::AT_CFReturnsNotRetained); }; if (const auto *InnermostChunk = D.getInnermostNonParenChunk()) { if (hasCFReturnsAttr(D.getAttributes()) || hasCFReturnsAttr(InnermostChunk->getAttrs()) || - hasCFReturnsAttr(D.getDeclSpec().getAttributes().getList())) { + hasCFReturnsAttr(D.getDeclSpec().getAttributes())) { inferNullability = NullabilityKind::Nullable; inferNullabilityInnerOnly = true; } @@ -4112,10 +4058,10 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Local function that checks the nullability for a given pointer declarator. // Returns true if _Nonnull was inferred. - auto inferPointerNullability = [&](SimplePointerKind pointerKind, - SourceLocation pointerLoc, - SourceLocation pointerEndLoc, - AttributeList *&attrs) -> AttributeList * { + auto inferPointerNullability = + [&](SimplePointerKind pointerKind, SourceLocation pointerLoc, + SourceLocation pointerEndLoc, + ParsedAttributesView &attrs) -> AttributeList * { // We've seen a pointer. if (NumPointersRemaining > 0) --NumPointersRemaining; @@ -4137,7 +4083,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, nullptr, SourceLocation(), nullptr, 0, syntax); - spliceAttrIntoList(*nullabilityAttr, attrs); + attrs.addAtStart(nullabilityAttr); if (inferNullabilityCS) { state.getDeclarator().getMutableDeclSpec().getObjCQualifiers() @@ -4192,9 +4138,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, pointerKind = SimplePointerKind::MemberPointer; if (auto *attr = inferPointerNullability( - pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), - D.getDeclSpec().getLocEnd(), - D.getMutableDeclSpec().getAttributes().getListRef())) { + pointerKind, D.getDeclSpec().getTypeSpecTypeLoc(), + D.getDeclSpec().getLocEnd(), + D.getMutableDeclSpec().getAttributes())) { T = Context.getAttributedType( AttributedType::getNullabilityAttrKind(*inferNullability),T,T); attr->setUsedAsTypeAttr(); @@ -4232,7 +4178,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability. inferPointerNullability(SimplePointerKind::BlockPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name); if (DeclType.Cls.TypeQuals || LangOpts.OpenCL) { @@ -4254,7 +4200,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability inferPointerNullability(SimplePointerKind::Pointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) { T = Context.getObjCObjectPointerType(T); @@ -4528,20 +4474,17 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, SourceLocation AttrLoc; if (chunkIndex + 1 < D.getNumTypeObjects()) { DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1); - for (const AttributeList *Attr = ReturnTypeChunk.getAttrs(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : ReturnTypeChunk.getAttrs()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } } if (AttrLoc.isInvalid()) { - for (const AttributeList *Attr - = D.getDeclSpec().getAttributes().getList(); - Attr; Attr = Attr->getNext()) { - if (Attr->getKind() == AttributeList::AT_ObjCOwnership) { - AttrLoc = Attr->getLoc(); + for (const AttributeList &AL : D.getDeclSpec().getAttributes()) { + if (AL.getKind() == AttributeList::AT_ObjCOwnership) { + AttrLoc = AL.getLoc(); break; } } @@ -4581,7 +4524,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, if (FTI.isAmbiguous) warnAboutAmbiguousFunction(S, D, DeclType, T); - FunctionType::ExtInfo EI(getCCForDeclaratorChunk(S, D, FTI, chunkIndex)); + FunctionType::ExtInfo EI( + getCCForDeclaratorChunk(S, D, DeclType.getAttrs(), FTI, chunkIndex)); if (!FTI.NumParams && !FTI.isVariadic && !LangOpts.CPlusPlus && !LangOpts.OpenCL) { @@ -4591,19 +4535,9 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // We allow a zero-parameter variadic function in C if the // function is marked with the "overloadable" attribute. Scan // for this attribute now. - if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) { - bool Overloadable = false; - for (const AttributeList *Attrs = D.getAttributes(); - Attrs; Attrs = Attrs->getNext()) { - if (Attrs->getKind() == AttributeList::AT_Overloadable) { - Overloadable = true; - break; - } - } - - if (!Overloadable) + if (!FTI.NumParams && FTI.isVariadic && !LangOpts.CPlusPlus) + if (!D.getAttributes().hasAttribute(AttributeList::AT_Overloadable)) S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_param); - } if (FTI.NumParams && FTI.Params[0].Param == nullptr) { // C99 6.7.5.3p3: Reject int(x,y,z) when it's not a function @@ -4758,7 +4692,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Handle pointer nullability. inferPointerNullability(SimplePointerKind::MemberPointer, DeclType.Loc, - DeclType.EndLoc, DeclType.getAttrListRef()); + DeclType.EndLoc, DeclType.getAttrs()); if (SS.isInvalid()) { // Avoid emitting extra errors if we already errored on the scope. @@ -4814,7 +4748,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, case DeclaratorChunk::Pipe: { T = S.BuildReadPipeType(T, DeclType.Loc); processTypeAttrs(state, T, TAL_DeclSpec, - D.getDeclSpec().getAttributes().getList()); + D.getMutableDeclSpec().getAttributes()); break; } } @@ -4825,8 +4759,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, } // See if there are any attributes on this declarator chunk. - processTypeAttrs(state, T, TAL_DeclChunk, - const_cast<AttributeList *>(DeclType.getAttrs())); + processTypeAttrs(state, T, TAL_DeclChunk, DeclType.getAttrs()); } // GNU warning -Wstrict-prototypes @@ -5091,10 +5024,8 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, // Look for an explicit lifetime attribute. DeclaratorChunk &chunk = D.getTypeObject(chunkIndex); - for (const AttributeList *attr = chunk.getAttrs(); attr; - attr = attr->getNext()) - if (attr->getKind() == AttributeList::AT_ObjCOwnership) - return; + if (chunk.getAttrs().hasAttribute(AttributeList::AT_ObjCOwnership)) + return; const char *attrStr = nullptr; switch (ownership) { @@ -5117,8 +5048,7 @@ static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state, .create(&S.Context.Idents.get("objc_ownership"), SourceLocation(), /*scope*/ nullptr, SourceLocation(), /*args*/ &Args, 1, AttributeList::AS_GNU); - spliceAttrIntoList(*attr, chunk.getAttrListRef()); - + chunk.getAttrs().addAtStart(attr); // TODO: mark whether we did this inference? } @@ -5262,39 +5192,19 @@ static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) { llvm_unreachable("unexpected attribute kind!"); } -static void fillAttributedTypeLoc(AttributedTypeLoc TL, - const AttributeList *attrs, - const AttributeList *DeclAttrs = nullptr) { - // DeclAttrs and attrs cannot be both empty. - assert((attrs || DeclAttrs) && - "no type attributes in the expected location!"); - - AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); - // Try to search for an attribute of matching kind in attrs list. - while (attrs && attrs->getKind() != parsedKind) - attrs = attrs->getNext(); - if (!attrs) { - // No matching type attribute in attrs list found. - // Try searching through C++11 attributes in the declarator attribute list. - while (DeclAttrs && (!DeclAttrs->isCXX11Attribute() || - DeclAttrs->getKind() != parsedKind)) - DeclAttrs = DeclAttrs->getNext(); - attrs = DeclAttrs; - } - - assert(attrs && "no matching type attribute in expected location!"); - - TL.setAttrNameLoc(attrs->getLoc()); +static void setAttributedTypeLoc(AttributedTypeLoc TL, + const AttributeList &attr) { + TL.setAttrNameLoc(attr.getLoc()); if (TL.hasAttrExprOperand()) { - assert(attrs->isArgExpr(0) && "mismatched attribute operand kind"); - TL.setAttrExprOperand(attrs->getArgAsExpr(0)); + assert(attr.isArgExpr(0) && "mismatched attribute operand kind"); + TL.setAttrExprOperand(attr.getArgAsExpr(0)); } else if (TL.hasAttrEnumOperand()) { - assert((attrs->isArgIdent(0) || attrs->isArgExpr(0)) && + assert((attr.isArgIdent(0) || attr.isArgExpr(0)) && "unexpected attribute operand kind"); - if (attrs->isArgIdent(0)) - TL.setAttrEnumOperandLoc(attrs->getArgAsIdent(0)->Loc); + if (attr.isArgIdent(0)) + TL.setAttrEnumOperandLoc(attr.getArgAsIdent(0)->Loc); else - TL.setAttrEnumOperandLoc(attrs->getArgAsExpr(0)->getExprLoc()); + TL.setAttrEnumOperandLoc(attr.getArgAsExpr(0)->getExprLoc()); } // FIXME: preserve this information to here. @@ -5302,6 +5212,25 @@ static void fillAttributedTypeLoc(AttributedTypeLoc TL, TL.setAttrOperandParensRange(SourceRange()); } +static void fillAttributedTypeLoc(AttributedTypeLoc TL, + const ParsedAttributesView &Attrs, + const ParsedAttributesView &DeclAttrs) { + // DeclAttrs and Attrs cannot be both empty. + assert((!Attrs.empty() || !DeclAttrs.empty()) && + "no type attributes in the expected location!"); + + AttributeList::Kind parsedKind = getAttrListKind(TL.getAttrKind()); + // Try to search for an attribute of matching kind in Attrs list. + for (const AttributeList &AL : Attrs) + if (AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + + for (const AttributeList &AL : DeclAttrs) + if (AL.isCXX11Attribute() || AL.getKind() == parsedKind) + return setAttributedTypeLoc(TL, AL); + llvm_unreachable("no matching type attribute in expected location!"); +} + namespace { class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> { ASTContext &Context; @@ -5312,7 +5241,7 @@ namespace { : Context(Context), DS(DS) {} void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, DS.getAttributes().getList()); + fillAttributedTypeLoc(TL, DS.getAttributes(), ParsedAttributesView{}); Visit(TL.getModifiedLoc()); } void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { @@ -5484,7 +5413,7 @@ namespace { } void VisitAttributedTypeLoc(AttributedTypeLoc TL) { - fillAttributedTypeLoc(TL, Chunk.getAttrs()); + fillAttributedTypeLoc(TL, Chunk.getAttrs(), ParsedAttributesView{}); } void VisitAdjustedTypeLoc(AdjustedTypeLoc TL) { // nothing @@ -5617,16 +5546,20 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) { ATL.setParensRange(SourceRange()); } -static void fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, - const AttributeList *Attrs) { - while (Attrs && Attrs->getKind() != AttributeList::AT_AddressSpace) - Attrs = Attrs->getNext(); +static void +fillDependentAddressSpaceTypeLoc(DependentAddressSpaceTypeLoc DASTL, + const ParsedAttributesView &Attrs) { + for (const AttributeList &AL : Attrs) { + if (AL.getKind() == AttributeList::AT_AddressSpace) { + DASTL.setAttrNameLoc(AL.getLoc()); + DASTL.setAttrExprOperand(AL.getArgAsExpr(0)); + DASTL.setAttrOperandParensRange(SourceRange()); + return; + } + } - assert(Attrs && "no address_space attribute found at the expected location!"); - - DASTL.setAttrNameLoc(Attrs->getLoc()); - DASTL.setAttrExprOperand(Attrs->getArgAsExpr(0)); - DASTL.setAttrOperandParensRange(SourceRange()); + llvm_unreachable( + "no address_space attribute found at the expected location!"); } /// Create and instantiate a TypeSourceInfo with type source information. @@ -5642,7 +5575,6 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, 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<PackExpansionType>(T)) { @@ -5666,7 +5598,8 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, } while (AttributedTypeLoc TL = CurrTL.getAs<AttributedTypeLoc>()) { - fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), DeclAttrs); + fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs(), + D.getAttributes()); CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc(); } @@ -6558,7 +6491,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, auto moveToChunk = [&](DeclaratorChunk &chunk, bool inFunction) -> bool { // If there is already a nullability attribute there, don't add // one. - if (hasNullabilityAttr(chunk.getAttrListRef())) + if (hasNullabilityAttr(chunk.getAttrs())) return false; // Complain about the nullability qualifier being in the wrong @@ -6591,8 +6524,8 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state, " " + attr.getName()->getName().str() + " "); } - moveAttrFromListToList(attr, state.getCurrentAttrListRef(), - chunk.getAttrListRef()); + moveAttrFromListToList(attr, state.getCurrentAttributes(), + chunk.getAttrs()); return true; }; @@ -7239,16 +7172,18 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - TypeAttrLocation TAL, AttributeList *attrs) { + TypeAttrLocation TAL, + ParsedAttributesView &attrs) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the // type, but others can be present in the type specifiers even though they // apply to the decl. Here we apply type attributes and ignore the rest. - while (attrs) { - AttributeList &attr = *attrs; - attrs = attr.getNext(); // reset to the next here due to early loop continue - // stmts + // This loop modifies the list pretty frequently, but we still need to make + // sure we visit every element once. Copy the attributes list, and iterate + // over that. + ParsedAttributesView AttrsCopy{attrs}; + for (AttributeList &attr : AttrsCopy) { // Skip attributes that were marked to be invalid. if (attr.isInvalid()) |