1e891aa97SErich Keane //======- ParsedAttr.cpp --------------------------------------------------===// 2e891aa97SErich Keane // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e891aa97SErich Keane // 7e891aa97SErich Keane //===----------------------------------------------------------------------===// 8e891aa97SErich Keane // 9e891aa97SErich Keane // This file defines the ParsedAttr class implementation 10e891aa97SErich Keane // 11e891aa97SErich Keane //===----------------------------------------------------------------------===// 12e891aa97SErich Keane 13e891aa97SErich Keane #include "clang/Sema/ParsedAttr.h" 14e891aa97SErich Keane #include "clang/AST/ASTContext.h" 15e891aa97SErich Keane #include "clang/Basic/AttrSubjectMatchRules.h" 16e891aa97SErich Keane #include "clang/Basic/IdentifierTable.h" 17e891aa97SErich Keane #include "clang/Basic/TargetInfo.h" 18e891aa97SErich Keane #include "clang/Sema/SemaInternal.h" 19e891aa97SErich Keane #include "llvm/ADT/SmallVector.h" 20e891aa97SErich Keane #include <cassert> 21e891aa97SErich Keane #include <cstddef> 22e891aa97SErich Keane #include <utility> 23e891aa97SErich Keane 24e891aa97SErich Keane using namespace clang; 25e891aa97SErich Keane 26e891aa97SErich Keane IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 27e891aa97SErich Keane IdentifierInfo *Ident) { 28e891aa97SErich Keane IdentifierLoc *Result = new (Ctx) IdentifierLoc; 29e891aa97SErich Keane Result->Loc = Loc; 30e891aa97SErich Keane Result->Ident = Ident; 31e891aa97SErich Keane return Result; 32e891aa97SErich Keane } 33e891aa97SErich Keane 34e891aa97SErich Keane size_t ParsedAttr::allocated_size() const { 35e891aa97SErich Keane if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 36e891aa97SErich Keane else if (IsTypeTagForDatatype) 37e891aa97SErich Keane return AttributeFactory::TypeTagForDatatypeAllocSize; 38e891aa97SErich Keane else if (IsProperty) 39e891aa97SErich Keane return AttributeFactory::PropertyAllocSize; 40e891aa97SErich Keane else if (HasParsedType) 4103406c50SErich Keane return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 4203406c50SErich Keane detail::TypeTagForDatatypeData, ParsedType, 4303406c50SErich Keane detail::PropertyData>(0, 0, 0, 1, 0); 4403406c50SErich Keane return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 4503406c50SErich Keane detail::TypeTagForDatatypeData, ParsedType, 4603406c50SErich Keane detail::PropertyData>(NumArgs, 0, 0, 0, 0); 47e891aa97SErich Keane } 48e891aa97SErich Keane 49e891aa97SErich Keane AttributeFactory::AttributeFactory() { 50e891aa97SErich Keane // Go ahead and configure all the inline capacity. This is just a memset. 51e891aa97SErich Keane FreeLists.resize(InlineFreeListsCapacity); 52e891aa97SErich Keane } 53e891aa97SErich Keane AttributeFactory::~AttributeFactory() = default; 54e891aa97SErich Keane 55e891aa97SErich Keane static size_t getFreeListIndexForSize(size_t size) { 56e891aa97SErich Keane assert(size >= sizeof(ParsedAttr)); 57e891aa97SErich Keane assert((size % sizeof(void*)) == 0); 58e891aa97SErich Keane return ((size - sizeof(ParsedAttr)) / sizeof(void *)); 59e891aa97SErich Keane } 60e891aa97SErich Keane 61e891aa97SErich Keane void *AttributeFactory::allocate(size_t size) { 62e891aa97SErich Keane // Check for a previously reclaimed attribute. 63e891aa97SErich Keane size_t index = getFreeListIndexForSize(size); 64e891aa97SErich Keane if (index < FreeLists.size() && !FreeLists[index].empty()) { 65e891aa97SErich Keane ParsedAttr *attr = FreeLists[index].back(); 66e891aa97SErich Keane FreeLists[index].pop_back(); 67e891aa97SErich Keane return attr; 68e891aa97SErich Keane } 69e891aa97SErich Keane 70e891aa97SErich Keane // Otherwise, allocate something new. 71e891aa97SErich Keane return Alloc.Allocate(size, alignof(AttributeFactory)); 72e891aa97SErich Keane } 73e891aa97SErich Keane 74e891aa97SErich Keane void AttributeFactory::deallocate(ParsedAttr *Attr) { 75e891aa97SErich Keane size_t size = Attr->allocated_size(); 76e891aa97SErich Keane size_t freeListIndex = getFreeListIndexForSize(size); 77e891aa97SErich Keane 78e891aa97SErich Keane // Expand FreeLists to the appropriate size, if required. 79e891aa97SErich Keane if (freeListIndex >= FreeLists.size()) 80e891aa97SErich Keane FreeLists.resize(freeListIndex + 1); 81e891aa97SErich Keane 827b39a085SSven van Haastregt #ifndef NDEBUG 83e891aa97SErich Keane // In debug mode, zero out the attribute to help find memory overwriting. 84e891aa97SErich Keane memset(Attr, 0, size); 85e891aa97SErich Keane #endif 86e891aa97SErich Keane 87e891aa97SErich Keane // Add 'Attr' to the appropriate free-list. 88e891aa97SErich Keane FreeLists[freeListIndex].push_back(Attr); 89e891aa97SErich Keane } 90e891aa97SErich Keane 91e891aa97SErich Keane void AttributeFactory::reclaimPool(AttributePool &cur) { 92e891aa97SErich Keane for (ParsedAttr *AL : cur.Attrs) 93e891aa97SErich Keane deallocate(AL); 94e891aa97SErich Keane } 95e891aa97SErich Keane 96e891aa97SErich Keane void AttributePool::takePool(AttributePool &pool) { 97e891aa97SErich Keane Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); 98e891aa97SErich Keane pool.Attrs.clear(); 99e891aa97SErich Keane } 100e891aa97SErich Keane 101bd7bce2cSErich Keane void AttributePool::takeFrom(ParsedAttributesView &List, AttributePool &Pool) { 102bd7bce2cSErich Keane assert(&Pool != this && "AttributePool can't take attributes from itself"); 103bd7bce2cSErich Keane llvm::for_each(List.AttrList, [&Pool](ParsedAttr *A) { Pool.remove(A); }); 104bd7bce2cSErich Keane Attrs.insert(Attrs.end(), List.AttrList.begin(), List.AttrList.end()); 105bd7bce2cSErich Keane } 106bd7bce2cSErich Keane 107e891aa97SErich Keane namespace { 108e891aa97SErich Keane 109e891aa97SErich Keane #include "clang/Sema/AttrParsedAttrImpl.inc" 110e891aa97SErich Keane 111e891aa97SErich Keane } // namespace 112e891aa97SErich Keane 11375d4d4bdSJohn Brawn const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) { 11475d4d4bdSJohn Brawn // If we have a ParsedAttrInfo for this ParsedAttr then return that. 1151b3a78d1SJoe Loser if ((size_t)A.getParsedKind() < std::size(AttrInfoMap)) 11675d4d4bdSJohn Brawn return *AttrInfoMap[A.getParsedKind()]; 117590dc8d0SJohn Brawn 11875d4d4bdSJohn Brawn // If this is an ignored attribute then return an appropriate ParsedAttrInfo. 119e8743c0fSBenjamin Kramer static const ParsedAttrInfo IgnoredParsedAttrInfo( 12075d4d4bdSJohn Brawn AttributeCommonInfo::IgnoredAttribute); 12175d4d4bdSJohn Brawn if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute) 12275d4d4bdSJohn Brawn return IgnoredParsedAttrInfo; 12375d4d4bdSJohn Brawn 124f5f1813dSAnders Waldenborg // Otherwise this may be an attribute defined by a plugin. 12575d4d4bdSJohn Brawn 12675d4d4bdSJohn Brawn // Search for a ParsedAttrInfo whose name and syntax match. 12775d4d4bdSJohn Brawn std::string FullName = A.getNormalizedFullName(); 12875d4d4bdSJohn Brawn AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax(); 12975d4d4bdSJohn Brawn if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword) 13075d4d4bdSJohn Brawn SyntaxUsed = AttributeCommonInfo::AS_Keyword; 13175d4d4bdSJohn Brawn 132f5f1813dSAnders Waldenborg for (auto &Ptr : getAttributePluginInstances()) 133446f7809SAnders Waldenborg if (Ptr->hasSpelling(SyntaxUsed, FullName)) 13475d4d4bdSJohn Brawn return *Ptr; 13575d4d4bdSJohn Brawn 13675d4d4bdSJohn Brawn // If we failed to find a match then return a default ParsedAttrInfo. 137e8743c0fSBenjamin Kramer static const ParsedAttrInfo DefaultParsedAttrInfo( 138fa0320ddSJohn Brawn AttributeCommonInfo::UnknownAttribute); 139590dc8d0SJohn Brawn return DefaultParsedAttrInfo; 140e891aa97SErich Keane } 141e891aa97SErich Keane 142ece4e920SSam McCall ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() { 143a3c248dbSserge-sans-paille return llvm::ArrayRef(AttrInfoMap); 144ece4e920SSam McCall } 145ece4e920SSam McCall 14675d4d4bdSJohn Brawn unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; } 147e891aa97SErich Keane 148e891aa97SErich Keane unsigned ParsedAttr::getMaxArgs() const { 14975d4d4bdSJohn Brawn return getMinArgs() + getInfo().OptArgs; 150e891aa97SErich Keane } 151e891aa97SErich Keane 152ead1690dSSteffen Larsen unsigned ParsedAttr::getNumArgMembers() const { 153ead1690dSSteffen Larsen return getInfo().NumArgMembers; 154ead1690dSSteffen Larsen } 155ead1690dSSteffen Larsen 156e891aa97SErich Keane bool ParsedAttr::hasCustomParsing() const { 15775d4d4bdSJohn Brawn return getInfo().HasCustomParsing; 158e891aa97SErich Keane } 159e891aa97SErich Keane 160e891aa97SErich Keane bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 16175d4d4bdSJohn Brawn return getInfo().diagAppertainsToDecl(S, *this, D); 162e891aa97SErich Keane } 163e891aa97SErich Keane 164fa4e7297SAaron Ballman bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const { 165fa4e7297SAaron Ballman return getInfo().diagAppertainsToStmt(S, *this, St); 166fa4e7297SAaron Ballman } 167fa4e7297SAaron Ballman 1684be8a269SAaron Ballman bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const { 1694be8a269SAaron Ballman return getInfo().diagMutualExclusion(S, *this, D); 1704be8a269SAaron Ballman } 1714be8a269SAaron Ballman 172e891aa97SErich Keane bool ParsedAttr::appliesToDecl(const Decl *D, 173e891aa97SErich Keane attr::SubjectMatchRule MatchRule) const { 174e891aa97SErich Keane return checkAttributeMatchRuleAppliesTo(D, MatchRule); 175e891aa97SErich Keane } 176e891aa97SErich Keane 177e891aa97SErich Keane void ParsedAttr::getMatchRules( 178e891aa97SErich Keane const LangOptions &LangOpts, 179e891aa97SErich Keane SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) 180e891aa97SErich Keane const { 18175d4d4bdSJohn Brawn return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts); 182e891aa97SErich Keane } 183e891aa97SErich Keane 184e891aa97SErich Keane bool ParsedAttr::diagnoseLangOpts(Sema &S) const { 1853b99acbfSSam McCall if (getInfo().acceptsLangOpts(S.getLangOpts())) 1863b99acbfSSam McCall return true; 1873b99acbfSSam McCall S.Diag(getLoc(), diag::warn_attribute_ignored) << *this; 1883b99acbfSSam McCall return false; 189e891aa97SErich Keane } 190e891aa97SErich Keane 191e891aa97SErich Keane bool ParsedAttr::isTargetSpecificAttr() const { 19275d4d4bdSJohn Brawn return getInfo().IsTargetSpecific; 193e891aa97SErich Keane } 194e891aa97SErich Keane 19575d4d4bdSJohn Brawn bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; } 196e891aa97SErich Keane 19775d4d4bdSJohn Brawn bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; } 198e891aa97SErich Keane 199e891aa97SErich Keane bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { 2000ba5f6e6SAmy Huang Kind K = getParsedKind(); 2010ba5f6e6SAmy Huang 2020ba5f6e6SAmy Huang // If the attribute has a target-specific spelling, check that it exists. 2030ba5f6e6SAmy Huang // Only call this if the attr is not ignored/unknown. For most targets, this 2040ba5f6e6SAmy Huang // function just returns true. 2050ba5f6e6SAmy Huang bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute && 2060ba5f6e6SAmy Huang K != NoSemaHandlerAttribute; 2070ba5f6e6SAmy Huang bool TargetSpecificSpellingExists = 2080ba5f6e6SAmy Huang !HasSpelling || 2090ba5f6e6SAmy Huang getInfo().spellingExistsInTarget(Target, getAttributeSpellingListIndex()); 2100ba5f6e6SAmy Huang 2110ba5f6e6SAmy Huang return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists; 212e891aa97SErich Keane } 213e891aa97SErich Keane 21475d4d4bdSJohn Brawn bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; } 215e891aa97SErich Keane 216e891aa97SErich Keane bool ParsedAttr::isSupportedByPragmaAttribute() const { 21775d4d4bdSJohn Brawn return getInfo().IsSupportedByPragmaAttribute; 218e891aa97SErich Keane } 219e891aa97SErich Keane 2208c7b64b5SMartin Boehme bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const { 22133ee5c46SRichard Sandiford if (isRegularKeywordAttribute()) 22233ee5c46SRichard Sandiford // The appurtenance rules are applied strictly for all regular keyword 22333ee5c46SRichard Sandiford // atributes. 22433ee5c46SRichard Sandiford return false; 22533ee5c46SRichard Sandiford 226*bf02f417SAaron Ballman assert(isStandardAttributeSyntax() || isAlignas()); 2278c7b64b5SMartin Boehme 2288c7b64b5SMartin Boehme // We have historically allowed some type attributes with standard attribute 2298c7b64b5SMartin Boehme // syntax to slide to the decl-specifier-seq, so we have to keep supporting 2308c7b64b5SMartin Boehme // it. This property is consciously not defined as a flag in Attr.td because 2318c7b64b5SMartin Boehme // we don't want new attributes to specify it. 2328c7b64b5SMartin Boehme // 2338c7b64b5SMartin Boehme // Note: No new entries should be added to this list. Entries should be 2348c7b64b5SMartin Boehme // removed from this list after a suitable deprecation period, provided that 2358c7b64b5SMartin Boehme // there are no compatibility considerations with other compilers. If 2368c7b64b5SMartin Boehme // possible, we would like this list to go away entirely. 2378c7b64b5SMartin Boehme switch (getParsedKind()) { 2388c7b64b5SMartin Boehme case AT_AddressSpace: 2398c7b64b5SMartin Boehme case AT_OpenCLPrivateAddressSpace: 2408c7b64b5SMartin Boehme case AT_OpenCLGlobalAddressSpace: 2418c7b64b5SMartin Boehme case AT_OpenCLGlobalDeviceAddressSpace: 2428c7b64b5SMartin Boehme case AT_OpenCLGlobalHostAddressSpace: 2438c7b64b5SMartin Boehme case AT_OpenCLLocalAddressSpace: 2448c7b64b5SMartin Boehme case AT_OpenCLConstantAddressSpace: 2458c7b64b5SMartin Boehme case AT_OpenCLGenericAddressSpace: 2468c7b64b5SMartin Boehme case AT_NeonPolyVectorType: 2478c7b64b5SMartin Boehme case AT_NeonVectorType: 2488c7b64b5SMartin Boehme case AT_ArmMveStrictPolymorphism: 2498c7b64b5SMartin Boehme case AT_BTFTypeTag: 2508c7b64b5SMartin Boehme case AT_ObjCGC: 2518c7b64b5SMartin Boehme case AT_MatrixType: 2528c7b64b5SMartin Boehme return true; 2538c7b64b5SMartin Boehme default: 2548c7b64b5SMartin Boehme return false; 2558c7b64b5SMartin Boehme } 2568c7b64b5SMartin Boehme } 2578c7b64b5SMartin Boehme 258ead1690dSSteffen Larsen bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; } 259ead1690dSSteffen Larsen 260e891aa97SErich Keane unsigned ParsedAttr::getSemanticSpelling() const { 26175d4d4bdSJohn Brawn return getInfo().spellingIndexToSemanticSpelling(*this); 262e891aa97SErich Keane } 263e891aa97SErich Keane 264e891aa97SErich Keane bool ParsedAttr::hasVariadicArg() const { 265e891aa97SErich Keane // If the attribute has the maximum number of optional arguments, we will 266e891aa97SErich Keane // claim that as being variadic. If we someday get an attribute that 267e891aa97SErich Keane // legitimately bumps up against that maximum, we can use another bit to track 268e891aa97SErich Keane // whether it's truly variadic or not. 26975d4d4bdSJohn Brawn return getInfo().OptArgs == 15; 270e891aa97SErich Keane } 2718bb8d65eSAaron Ballman 272ead1690dSSteffen Larsen bool ParsedAttr::isParamExpr(size_t N) const { 273ead1690dSSteffen Larsen return getInfo().isParamExpr(N); 274ead1690dSSteffen Larsen } 275ead1690dSSteffen Larsen 276ead1690dSSteffen Larsen void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const { 277ead1690dSSteffen Larsen ::handleAttrWithDelayedArgs(S, D, *this); 278ead1690dSSteffen Larsen } 279ead1690dSSteffen Larsen 2808bb8d65eSAaron Ballman static unsigned getNumAttributeArgs(const ParsedAttr &AL) { 2818bb8d65eSAaron Ballman // FIXME: Include the type in the argument list. 2828bb8d65eSAaron Ballman return AL.getNumArgs() + AL.hasParsedType(); 2838bb8d65eSAaron Ballman } 2848bb8d65eSAaron Ballman 2858bb8d65eSAaron Ballman template <typename Compare> 2868bb8d65eSAaron Ballman static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, 2878bb8d65eSAaron Ballman unsigned Num, unsigned Diag, 2888bb8d65eSAaron Ballman Compare Comp) { 2898bb8d65eSAaron Ballman if (Comp(getNumAttributeArgs(AL), Num)) { 2908bb8d65eSAaron Ballman S.Diag(AL.getLoc(), Diag) << AL << Num; 2918bb8d65eSAaron Ballman return false; 2928bb8d65eSAaron Ballman } 2938bb8d65eSAaron Ballman return true; 2948bb8d65eSAaron Ballman } 2958bb8d65eSAaron Ballman 2968bb8d65eSAaron Ballman bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const { 2978bb8d65eSAaron Ballman return checkAttributeNumArgsImpl(S, *this, Num, 2988bb8d65eSAaron Ballman diag::err_attribute_wrong_number_arguments, 2998bb8d65eSAaron Ballman std::not_equal_to<unsigned>()); 3008bb8d65eSAaron Ballman } 3018bb8d65eSAaron Ballman bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const { 3028bb8d65eSAaron Ballman return checkAttributeNumArgsImpl(S, *this, Num, 3038bb8d65eSAaron Ballman diag::err_attribute_too_few_arguments, 3048bb8d65eSAaron Ballman std::less<unsigned>()); 3058bb8d65eSAaron Ballman } 3068bb8d65eSAaron Ballman bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const { 3078bb8d65eSAaron Ballman return checkAttributeNumArgsImpl(S, *this, Num, 3088bb8d65eSAaron Ballman diag::err_attribute_too_many_arguments, 3098bb8d65eSAaron Ballman std::greater<unsigned>()); 3108bb8d65eSAaron Ballman } 3118c7b64b5SMartin Boehme 3128c7b64b5SMartin Boehme void clang::takeAndConcatenateAttrs(ParsedAttributes &First, 3138c7b64b5SMartin Boehme ParsedAttributes &Second, 3148c7b64b5SMartin Boehme ParsedAttributes &Result) { 3158c7b64b5SMartin Boehme // Note that takeAllFrom() puts the attributes at the beginning of the list, 3168c7b64b5SMartin Boehme // so to obtain the correct ordering, we add `Second`, then `First`. 3178c7b64b5SMartin Boehme Result.takeAllFrom(Second); 3188c7b64b5SMartin Boehme Result.takeAllFrom(First); 3198c7b64b5SMartin Boehme if (First.Range.getBegin().isValid()) 3208c7b64b5SMartin Boehme Result.Range.setBegin(First.Range.getBegin()); 3218c7b64b5SMartin Boehme else 3228c7b64b5SMartin Boehme Result.Range.setBegin(Second.Range.getBegin()); 3238c7b64b5SMartin Boehme if (Second.Range.getEnd().isValid()) 3248c7b64b5SMartin Boehme Result.Range.setEnd(Second.Range.getEnd()); 3258c7b64b5SMartin Boehme else 3268c7b64b5SMartin Boehme Result.Range.setEnd(First.Range.getEnd()); 3278c7b64b5SMartin Boehme } 328