10b57cec5SDimitry Andric //======- ParsedAttr.cpp --------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file defines the ParsedAttr class implementation 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "clang/Sema/ParsedAttr.h" 140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h" 150b57cec5SDimitry Andric #include "clang/Basic/AttrSubjectMatchRules.h" 160b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 180b57cec5SDimitry Andric #include "clang/Sema/SemaInternal.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h" 200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 220b57cec5SDimitry Andric #include <cassert> 230b57cec5SDimitry Andric #include <cstddef> 240b57cec5SDimitry Andric #include <utility> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric using namespace clang; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 290b57cec5SDimitry Andric IdentifierInfo *Ident) { 300b57cec5SDimitry Andric IdentifierLoc *Result = new (Ctx) IdentifierLoc; 310b57cec5SDimitry Andric Result->Loc = Loc; 320b57cec5SDimitry Andric Result->Ident = Ident; 330b57cec5SDimitry Andric return Result; 340b57cec5SDimitry Andric } 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric size_t ParsedAttr::allocated_size() const { 370b57cec5SDimitry Andric if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 380b57cec5SDimitry Andric else if (IsTypeTagForDatatype) 390b57cec5SDimitry Andric return AttributeFactory::TypeTagForDatatypeAllocSize; 400b57cec5SDimitry Andric else if (IsProperty) 410b57cec5SDimitry Andric return AttributeFactory::PropertyAllocSize; 420b57cec5SDimitry Andric else if (HasParsedType) 430b57cec5SDimitry Andric return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 440b57cec5SDimitry Andric detail::TypeTagForDatatypeData, ParsedType, 450b57cec5SDimitry Andric detail::PropertyData>(0, 0, 0, 1, 0); 460b57cec5SDimitry Andric return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 470b57cec5SDimitry Andric detail::TypeTagForDatatypeData, ParsedType, 480b57cec5SDimitry Andric detail::PropertyData>(NumArgs, 0, 0, 0, 0); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric AttributeFactory::AttributeFactory() { 520b57cec5SDimitry Andric // Go ahead and configure all the inline capacity. This is just a memset. 530b57cec5SDimitry Andric FreeLists.resize(InlineFreeListsCapacity); 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric AttributeFactory::~AttributeFactory() = default; 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric static size_t getFreeListIndexForSize(size_t size) { 580b57cec5SDimitry Andric assert(size >= sizeof(ParsedAttr)); 590b57cec5SDimitry Andric assert((size % sizeof(void*)) == 0); 600b57cec5SDimitry Andric return ((size - sizeof(ParsedAttr)) / sizeof(void *)); 610b57cec5SDimitry Andric } 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric void *AttributeFactory::allocate(size_t size) { 640b57cec5SDimitry Andric // Check for a previously reclaimed attribute. 650b57cec5SDimitry Andric size_t index = getFreeListIndexForSize(size); 660b57cec5SDimitry Andric if (index < FreeLists.size() && !FreeLists[index].empty()) { 670b57cec5SDimitry Andric ParsedAttr *attr = FreeLists[index].back(); 680b57cec5SDimitry Andric FreeLists[index].pop_back(); 690b57cec5SDimitry Andric return attr; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric // Otherwise, allocate something new. 730b57cec5SDimitry Andric return Alloc.Allocate(size, alignof(AttributeFactory)); 740b57cec5SDimitry Andric } 750b57cec5SDimitry Andric 760b57cec5SDimitry Andric void AttributeFactory::deallocate(ParsedAttr *Attr) { 770b57cec5SDimitry Andric size_t size = Attr->allocated_size(); 780b57cec5SDimitry Andric size_t freeListIndex = getFreeListIndexForSize(size); 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric // Expand FreeLists to the appropriate size, if required. 810b57cec5SDimitry Andric if (freeListIndex >= FreeLists.size()) 820b57cec5SDimitry Andric FreeLists.resize(freeListIndex + 1); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric #ifndef NDEBUG 850b57cec5SDimitry Andric // In debug mode, zero out the attribute to help find memory overwriting. 860b57cec5SDimitry Andric memset(Attr, 0, size); 870b57cec5SDimitry Andric #endif 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // Add 'Attr' to the appropriate free-list. 900b57cec5SDimitry Andric FreeLists[freeListIndex].push_back(Attr); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric void AttributeFactory::reclaimPool(AttributePool &cur) { 940b57cec5SDimitry Andric for (ParsedAttr *AL : cur.Attrs) 950b57cec5SDimitry Andric deallocate(AL); 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric void AttributePool::takePool(AttributePool &pool) { 990b57cec5SDimitry Andric Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); 1000b57cec5SDimitry Andric pool.Attrs.clear(); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric namespace { 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric #include "clang/Sema/AttrParsedAttrImpl.inc" 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric } // namespace 1080b57cec5SDimitry Andric 1095ffd83dbSDimitry Andric const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) { 1105ffd83dbSDimitry Andric // If we have a ParsedAttrInfo for this ParsedAttr then return that. 111bdd1243dSDimitry Andric if ((size_t)A.getParsedKind() < std::size(AttrInfoMap)) 1125ffd83dbSDimitry Andric return *AttrInfoMap[A.getParsedKind()]; 1135ffd83dbSDimitry Andric 1145ffd83dbSDimitry Andric // If this is an ignored attribute then return an appropriate ParsedAttrInfo. 1155ffd83dbSDimitry Andric static const ParsedAttrInfo IgnoredParsedAttrInfo( 1165ffd83dbSDimitry Andric AttributeCommonInfo::IgnoredAttribute); 1175ffd83dbSDimitry Andric if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute) 1185ffd83dbSDimitry Andric return IgnoredParsedAttrInfo; 1195ffd83dbSDimitry Andric 12006c3fb27SDimitry Andric // Otherwise this may be an attribute defined by a plugin. 1215ffd83dbSDimitry Andric 1225ffd83dbSDimitry Andric // Search for a ParsedAttrInfo whose name and syntax match. 1235ffd83dbSDimitry Andric std::string FullName = A.getNormalizedFullName(); 1245ffd83dbSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax(); 1255ffd83dbSDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword) 1265ffd83dbSDimitry Andric SyntaxUsed = AttributeCommonInfo::AS_Keyword; 1275ffd83dbSDimitry Andric 12806c3fb27SDimitry Andric for (auto &Ptr : getAttributePluginInstances()) 12906c3fb27SDimitry Andric if (Ptr->hasSpelling(SyntaxUsed, FullName)) 1305ffd83dbSDimitry Andric return *Ptr; 1315ffd83dbSDimitry Andric 1325ffd83dbSDimitry Andric // If we failed to find a match then return a default ParsedAttrInfo. 1335ffd83dbSDimitry Andric static const ParsedAttrInfo DefaultParsedAttrInfo( 1345ffd83dbSDimitry Andric AttributeCommonInfo::UnknownAttribute); 1355ffd83dbSDimitry Andric return DefaultParsedAttrInfo; 1360b57cec5SDimitry Andric } 1370b57cec5SDimitry Andric 138349cc55cSDimitry Andric ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() { 139bdd1243dSDimitry Andric return llvm::ArrayRef(AttrInfoMap); 140349cc55cSDimitry Andric } 141349cc55cSDimitry Andric 1425ffd83dbSDimitry Andric unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric unsigned ParsedAttr::getMaxArgs() const { 1455ffd83dbSDimitry Andric return getMinArgs() + getInfo().OptArgs; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 14881ad6265SDimitry Andric unsigned ParsedAttr::getNumArgMembers() const { 14981ad6265SDimitry Andric return getInfo().NumArgMembers; 15081ad6265SDimitry Andric } 15181ad6265SDimitry Andric 1520b57cec5SDimitry Andric bool ParsedAttr::hasCustomParsing() const { 1535ffd83dbSDimitry Andric return getInfo().HasCustomParsing; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 1575ffd83dbSDimitry Andric return getInfo().diagAppertainsToDecl(S, *this, D); 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 160fe6060f1SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const { 161fe6060f1SDimitry Andric return getInfo().diagAppertainsToStmt(S, *this, St); 162fe6060f1SDimitry Andric } 163fe6060f1SDimitry Andric 164fe6060f1SDimitry Andric bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const { 165fe6060f1SDimitry Andric return getInfo().diagMutualExclusion(S, *this, D); 166fe6060f1SDimitry Andric } 167fe6060f1SDimitry Andric 1680b57cec5SDimitry Andric bool ParsedAttr::appliesToDecl(const Decl *D, 1690b57cec5SDimitry Andric attr::SubjectMatchRule MatchRule) const { 1700b57cec5SDimitry Andric return checkAttributeMatchRuleAppliesTo(D, MatchRule); 1710b57cec5SDimitry Andric } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric void ParsedAttr::getMatchRules( 1740b57cec5SDimitry Andric const LangOptions &LangOpts, 1750b57cec5SDimitry Andric SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) 1760b57cec5SDimitry Andric const { 1775ffd83dbSDimitry Andric return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric bool ParsedAttr::diagnoseLangOpts(Sema &S) const { 181349cc55cSDimitry Andric if (getInfo().acceptsLangOpts(S.getLangOpts())) 182349cc55cSDimitry Andric return true; 183349cc55cSDimitry Andric S.Diag(getLoc(), diag::warn_attribute_ignored) << *this; 184349cc55cSDimitry Andric return false; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric bool ParsedAttr::isTargetSpecificAttr() const { 1885ffd83dbSDimitry Andric return getInfo().IsTargetSpecific; 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1915ffd83dbSDimitry Andric bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; } 1920b57cec5SDimitry Andric 1935ffd83dbSDimitry Andric bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { 196*5f757f3fSDimitry Andric Kind K = getParsedKind(); 197*5f757f3fSDimitry Andric 198*5f757f3fSDimitry Andric // If the attribute has a target-specific spelling, check that it exists. 199*5f757f3fSDimitry Andric // Only call this if the attr is not ignored/unknown. For most targets, this 200*5f757f3fSDimitry Andric // function just returns true. 201*5f757f3fSDimitry Andric bool HasSpelling = K != IgnoredAttribute && K != UnknownAttribute && 202*5f757f3fSDimitry Andric K != NoSemaHandlerAttribute; 203*5f757f3fSDimitry Andric bool TargetSpecificSpellingExists = 204*5f757f3fSDimitry Andric !HasSpelling || 205*5f757f3fSDimitry Andric getInfo().spellingExistsInTarget(Target, getAttributeSpellingListIndex()); 206*5f757f3fSDimitry Andric 207*5f757f3fSDimitry Andric return getInfo().existsInTarget(Target) && TargetSpecificSpellingExists; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 2105ffd83dbSDimitry Andric bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric bool ParsedAttr::isSupportedByPragmaAttribute() const { 2135ffd83dbSDimitry Andric return getInfo().IsSupportedByPragmaAttribute; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 21681ad6265SDimitry Andric bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const { 21706c3fb27SDimitry Andric if (isRegularKeywordAttribute()) 21806c3fb27SDimitry Andric // The appurtenance rules are applied strictly for all regular keyword 21906c3fb27SDimitry Andric // atributes. 22006c3fb27SDimitry Andric return false; 22106c3fb27SDimitry Andric 22281ad6265SDimitry Andric assert(isStandardAttributeSyntax()); 22381ad6265SDimitry Andric 22481ad6265SDimitry Andric // We have historically allowed some type attributes with standard attribute 22581ad6265SDimitry Andric // syntax to slide to the decl-specifier-seq, so we have to keep supporting 22681ad6265SDimitry Andric // it. This property is consciously not defined as a flag in Attr.td because 22781ad6265SDimitry Andric // we don't want new attributes to specify it. 22881ad6265SDimitry Andric // 22981ad6265SDimitry Andric // Note: No new entries should be added to this list. Entries should be 23081ad6265SDimitry Andric // removed from this list after a suitable deprecation period, provided that 23181ad6265SDimitry Andric // there are no compatibility considerations with other compilers. If 23281ad6265SDimitry Andric // possible, we would like this list to go away entirely. 23381ad6265SDimitry Andric switch (getParsedKind()) { 23481ad6265SDimitry Andric case AT_AddressSpace: 23581ad6265SDimitry Andric case AT_OpenCLPrivateAddressSpace: 23681ad6265SDimitry Andric case AT_OpenCLGlobalAddressSpace: 23781ad6265SDimitry Andric case AT_OpenCLGlobalDeviceAddressSpace: 23881ad6265SDimitry Andric case AT_OpenCLGlobalHostAddressSpace: 23981ad6265SDimitry Andric case AT_OpenCLLocalAddressSpace: 24081ad6265SDimitry Andric case AT_OpenCLConstantAddressSpace: 24181ad6265SDimitry Andric case AT_OpenCLGenericAddressSpace: 24281ad6265SDimitry Andric case AT_NeonPolyVectorType: 24381ad6265SDimitry Andric case AT_NeonVectorType: 24481ad6265SDimitry Andric case AT_ArmMveStrictPolymorphism: 24581ad6265SDimitry Andric case AT_BTFTypeTag: 24681ad6265SDimitry Andric case AT_ObjCGC: 24781ad6265SDimitry Andric case AT_MatrixType: 24881ad6265SDimitry Andric return true; 24981ad6265SDimitry Andric default: 25081ad6265SDimitry Andric return false; 25181ad6265SDimitry Andric } 25281ad6265SDimitry Andric } 25381ad6265SDimitry Andric 25481ad6265SDimitry Andric bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; } 25581ad6265SDimitry Andric 2560b57cec5SDimitry Andric unsigned ParsedAttr::getSemanticSpelling() const { 2575ffd83dbSDimitry Andric return getInfo().spellingIndexToSemanticSpelling(*this); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric bool ParsedAttr::hasVariadicArg() const { 2610b57cec5SDimitry Andric // If the attribute has the maximum number of optional arguments, we will 2620b57cec5SDimitry Andric // claim that as being variadic. If we someday get an attribute that 2630b57cec5SDimitry Andric // legitimately bumps up against that maximum, we can use another bit to track 2640b57cec5SDimitry Andric // whether it's truly variadic or not. 2655ffd83dbSDimitry Andric return getInfo().OptArgs == 15; 2660b57cec5SDimitry Andric } 267fe6060f1SDimitry Andric 26881ad6265SDimitry Andric bool ParsedAttr::isParamExpr(size_t N) const { 26981ad6265SDimitry Andric return getInfo().isParamExpr(N); 27081ad6265SDimitry Andric } 27181ad6265SDimitry Andric 27281ad6265SDimitry Andric void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const { 27381ad6265SDimitry Andric ::handleAttrWithDelayedArgs(S, D, *this); 27481ad6265SDimitry Andric } 27581ad6265SDimitry Andric 276fe6060f1SDimitry Andric static unsigned getNumAttributeArgs(const ParsedAttr &AL) { 277fe6060f1SDimitry Andric // FIXME: Include the type in the argument list. 278fe6060f1SDimitry Andric return AL.getNumArgs() + AL.hasParsedType(); 279fe6060f1SDimitry Andric } 280fe6060f1SDimitry Andric 281fe6060f1SDimitry Andric template <typename Compare> 282fe6060f1SDimitry Andric static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, 283fe6060f1SDimitry Andric unsigned Num, unsigned Diag, 284fe6060f1SDimitry Andric Compare Comp) { 285fe6060f1SDimitry Andric if (Comp(getNumAttributeArgs(AL), Num)) { 286fe6060f1SDimitry Andric S.Diag(AL.getLoc(), Diag) << AL << Num; 287fe6060f1SDimitry Andric return false; 288fe6060f1SDimitry Andric } 289fe6060f1SDimitry Andric return true; 290fe6060f1SDimitry Andric } 291fe6060f1SDimitry Andric 292fe6060f1SDimitry Andric bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const { 293fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 294fe6060f1SDimitry Andric diag::err_attribute_wrong_number_arguments, 295fe6060f1SDimitry Andric std::not_equal_to<unsigned>()); 296fe6060f1SDimitry Andric } 297fe6060f1SDimitry Andric bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const { 298fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 299fe6060f1SDimitry Andric diag::err_attribute_too_few_arguments, 300fe6060f1SDimitry Andric std::less<unsigned>()); 301fe6060f1SDimitry Andric } 302fe6060f1SDimitry Andric bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const { 303fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 304fe6060f1SDimitry Andric diag::err_attribute_too_many_arguments, 305fe6060f1SDimitry Andric std::greater<unsigned>()); 306fe6060f1SDimitry Andric } 30781ad6265SDimitry Andric 30881ad6265SDimitry Andric void clang::takeAndConcatenateAttrs(ParsedAttributes &First, 30981ad6265SDimitry Andric ParsedAttributes &Second, 31081ad6265SDimitry Andric ParsedAttributes &Result) { 31181ad6265SDimitry Andric // Note that takeAllFrom() puts the attributes at the beginning of the list, 31281ad6265SDimitry Andric // so to obtain the correct ordering, we add `Second`, then `First`. 31381ad6265SDimitry Andric Result.takeAllFrom(Second); 31481ad6265SDimitry Andric Result.takeAllFrom(First); 31581ad6265SDimitry Andric if (First.Range.getBegin().isValid()) 31681ad6265SDimitry Andric Result.Range.setBegin(First.Range.getBegin()); 31781ad6265SDimitry Andric else 31881ad6265SDimitry Andric Result.Range.setBegin(Second.Range.getBegin()); 31981ad6265SDimitry Andric if (Second.Range.getEnd().isValid()) 32081ad6265SDimitry Andric Result.Range.setEnd(Second.Range.getEnd()); 32181ad6265SDimitry Andric else 32281ad6265SDimitry Andric Result.Range.setEnd(First.Range.getEnd()); 32381ad6265SDimitry Andric } 324