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" 225ffd83dbSDimitry Andric #include "llvm/Support/ManagedStatic.h" 230b57cec5SDimitry Andric #include <cassert> 240b57cec5SDimitry Andric #include <cstddef> 250b57cec5SDimitry Andric #include <utility> 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace clang; 280b57cec5SDimitry Andric 295ffd83dbSDimitry Andric LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry) 305ffd83dbSDimitry Andric 310b57cec5SDimitry Andric IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, 320b57cec5SDimitry Andric IdentifierInfo *Ident) { 330b57cec5SDimitry Andric IdentifierLoc *Result = new (Ctx) IdentifierLoc; 340b57cec5SDimitry Andric Result->Loc = Loc; 350b57cec5SDimitry Andric Result->Ident = Ident; 360b57cec5SDimitry Andric return Result; 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric size_t ParsedAttr::allocated_size() const { 400b57cec5SDimitry Andric if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; 410b57cec5SDimitry Andric else if (IsTypeTagForDatatype) 420b57cec5SDimitry Andric return AttributeFactory::TypeTagForDatatypeAllocSize; 430b57cec5SDimitry Andric else if (IsProperty) 440b57cec5SDimitry Andric return AttributeFactory::PropertyAllocSize; 450b57cec5SDimitry Andric else if (HasParsedType) 460b57cec5SDimitry Andric return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 470b57cec5SDimitry Andric detail::TypeTagForDatatypeData, ParsedType, 480b57cec5SDimitry Andric detail::PropertyData>(0, 0, 0, 1, 0); 490b57cec5SDimitry Andric return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, 500b57cec5SDimitry Andric detail::TypeTagForDatatypeData, ParsedType, 510b57cec5SDimitry Andric detail::PropertyData>(NumArgs, 0, 0, 0, 0); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric AttributeFactory::AttributeFactory() { 550b57cec5SDimitry Andric // Go ahead and configure all the inline capacity. This is just a memset. 560b57cec5SDimitry Andric FreeLists.resize(InlineFreeListsCapacity); 570b57cec5SDimitry Andric } 580b57cec5SDimitry Andric AttributeFactory::~AttributeFactory() = default; 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric static size_t getFreeListIndexForSize(size_t size) { 610b57cec5SDimitry Andric assert(size >= sizeof(ParsedAttr)); 620b57cec5SDimitry Andric assert((size % sizeof(void*)) == 0); 630b57cec5SDimitry Andric return ((size - sizeof(ParsedAttr)) / sizeof(void *)); 640b57cec5SDimitry Andric } 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric void *AttributeFactory::allocate(size_t size) { 670b57cec5SDimitry Andric // Check for a previously reclaimed attribute. 680b57cec5SDimitry Andric size_t index = getFreeListIndexForSize(size); 690b57cec5SDimitry Andric if (index < FreeLists.size() && !FreeLists[index].empty()) { 700b57cec5SDimitry Andric ParsedAttr *attr = FreeLists[index].back(); 710b57cec5SDimitry Andric FreeLists[index].pop_back(); 720b57cec5SDimitry Andric return attr; 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Otherwise, allocate something new. 760b57cec5SDimitry Andric return Alloc.Allocate(size, alignof(AttributeFactory)); 770b57cec5SDimitry Andric } 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric void AttributeFactory::deallocate(ParsedAttr *Attr) { 800b57cec5SDimitry Andric size_t size = Attr->allocated_size(); 810b57cec5SDimitry Andric size_t freeListIndex = getFreeListIndexForSize(size); 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric // Expand FreeLists to the appropriate size, if required. 840b57cec5SDimitry Andric if (freeListIndex >= FreeLists.size()) 850b57cec5SDimitry Andric FreeLists.resize(freeListIndex + 1); 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric #ifndef NDEBUG 880b57cec5SDimitry Andric // In debug mode, zero out the attribute to help find memory overwriting. 890b57cec5SDimitry Andric memset(Attr, 0, size); 900b57cec5SDimitry Andric #endif 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric // Add 'Attr' to the appropriate free-list. 930b57cec5SDimitry Andric FreeLists[freeListIndex].push_back(Attr); 940b57cec5SDimitry Andric } 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric void AttributeFactory::reclaimPool(AttributePool &cur) { 970b57cec5SDimitry Andric for (ParsedAttr *AL : cur.Attrs) 980b57cec5SDimitry Andric deallocate(AL); 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric void AttributePool::takePool(AttributePool &pool) { 1020b57cec5SDimitry Andric Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); 1030b57cec5SDimitry Andric pool.Attrs.clear(); 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric namespace { 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric #include "clang/Sema/AttrParsedAttrImpl.inc" 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric } // namespace 1110b57cec5SDimitry Andric 1125ffd83dbSDimitry Andric const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) { 1135ffd83dbSDimitry Andric // If we have a ParsedAttrInfo for this ParsedAttr then return that. 114*bdd1243dSDimitry Andric if ((size_t)A.getParsedKind() < std::size(AttrInfoMap)) 1155ffd83dbSDimitry Andric return *AttrInfoMap[A.getParsedKind()]; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric // If this is an ignored attribute then return an appropriate ParsedAttrInfo. 1185ffd83dbSDimitry Andric static const ParsedAttrInfo IgnoredParsedAttrInfo( 1195ffd83dbSDimitry Andric AttributeCommonInfo::IgnoredAttribute); 1205ffd83dbSDimitry Andric if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute) 1215ffd83dbSDimitry Andric return IgnoredParsedAttrInfo; 1225ffd83dbSDimitry Andric 1235ffd83dbSDimitry Andric // Otherwise this may be an attribute defined by a plugin. First instantiate 1245ffd83dbSDimitry Andric // all plugin attributes if we haven't already done so. 1255ffd83dbSDimitry Andric static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>> 1265ffd83dbSDimitry Andric PluginAttrInstances; 1275ffd83dbSDimitry Andric if (PluginAttrInstances->empty()) 1285ffd83dbSDimitry Andric for (auto It : ParsedAttrInfoRegistry::entries()) 1295ffd83dbSDimitry Andric PluginAttrInstances->emplace_back(It.instantiate()); 1305ffd83dbSDimitry Andric 1315ffd83dbSDimitry Andric // Search for a ParsedAttrInfo whose name and syntax match. 1325ffd83dbSDimitry Andric std::string FullName = A.getNormalizedFullName(); 1335ffd83dbSDimitry Andric AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax(); 1345ffd83dbSDimitry Andric if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword) 1355ffd83dbSDimitry Andric SyntaxUsed = AttributeCommonInfo::AS_Keyword; 1365ffd83dbSDimitry Andric 1375ffd83dbSDimitry Andric for (auto &Ptr : *PluginAttrInstances) 1385ffd83dbSDimitry Andric for (auto &S : Ptr->Spellings) 1395ffd83dbSDimitry Andric if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName) 1405ffd83dbSDimitry Andric return *Ptr; 1415ffd83dbSDimitry Andric 1425ffd83dbSDimitry Andric // If we failed to find a match then return a default ParsedAttrInfo. 1435ffd83dbSDimitry Andric static const ParsedAttrInfo DefaultParsedAttrInfo( 1445ffd83dbSDimitry Andric AttributeCommonInfo::UnknownAttribute); 1455ffd83dbSDimitry Andric return DefaultParsedAttrInfo; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 148349cc55cSDimitry Andric ArrayRef<const ParsedAttrInfo *> ParsedAttrInfo::getAllBuiltin() { 149*bdd1243dSDimitry Andric return llvm::ArrayRef(AttrInfoMap); 150349cc55cSDimitry Andric } 151349cc55cSDimitry Andric 1525ffd83dbSDimitry Andric unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric unsigned ParsedAttr::getMaxArgs() const { 1555ffd83dbSDimitry Andric return getMinArgs() + getInfo().OptArgs; 1560b57cec5SDimitry Andric } 1570b57cec5SDimitry Andric 15881ad6265SDimitry Andric unsigned ParsedAttr::getNumArgMembers() const { 15981ad6265SDimitry Andric return getInfo().NumArgMembers; 16081ad6265SDimitry Andric } 16181ad6265SDimitry Andric 1620b57cec5SDimitry Andric bool ParsedAttr::hasCustomParsing() const { 1635ffd83dbSDimitry Andric return getInfo().HasCustomParsing; 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { 1675ffd83dbSDimitry Andric return getInfo().diagAppertainsToDecl(S, *this, D); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 170fe6060f1SDimitry Andric bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Stmt *St) const { 171fe6060f1SDimitry Andric return getInfo().diagAppertainsToStmt(S, *this, St); 172fe6060f1SDimitry Andric } 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric bool ParsedAttr::diagnoseMutualExclusion(Sema &S, const Decl *D) const { 175fe6060f1SDimitry Andric return getInfo().diagMutualExclusion(S, *this, D); 176fe6060f1SDimitry Andric } 177fe6060f1SDimitry Andric 1780b57cec5SDimitry Andric bool ParsedAttr::appliesToDecl(const Decl *D, 1790b57cec5SDimitry Andric attr::SubjectMatchRule MatchRule) const { 1800b57cec5SDimitry Andric return checkAttributeMatchRuleAppliesTo(D, MatchRule); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric void ParsedAttr::getMatchRules( 1840b57cec5SDimitry Andric const LangOptions &LangOpts, 1850b57cec5SDimitry Andric SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) 1860b57cec5SDimitry Andric const { 1875ffd83dbSDimitry Andric return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric bool ParsedAttr::diagnoseLangOpts(Sema &S) const { 191349cc55cSDimitry Andric if (getInfo().acceptsLangOpts(S.getLangOpts())) 192349cc55cSDimitry Andric return true; 193349cc55cSDimitry Andric S.Diag(getLoc(), diag::warn_attribute_ignored) << *this; 194349cc55cSDimitry Andric return false; 1950b57cec5SDimitry Andric } 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric bool ParsedAttr::isTargetSpecificAttr() const { 1985ffd83dbSDimitry Andric return getInfo().IsTargetSpecific; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2015ffd83dbSDimitry Andric bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; } 2020b57cec5SDimitry Andric 2035ffd83dbSDimitry Andric bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; } 2040b57cec5SDimitry Andric 2050b57cec5SDimitry Andric bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { 2065ffd83dbSDimitry Andric return getInfo().existsInTarget(Target); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2095ffd83dbSDimitry Andric bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; } 2100b57cec5SDimitry Andric 2110b57cec5SDimitry Andric bool ParsedAttr::isSupportedByPragmaAttribute() const { 2125ffd83dbSDimitry Andric return getInfo().IsSupportedByPragmaAttribute; 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 21581ad6265SDimitry Andric bool ParsedAttr::slidesFromDeclToDeclSpecLegacyBehavior() const { 21681ad6265SDimitry Andric assert(isStandardAttributeSyntax()); 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric // We have historically allowed some type attributes with standard attribute 21981ad6265SDimitry Andric // syntax to slide to the decl-specifier-seq, so we have to keep supporting 22081ad6265SDimitry Andric // it. This property is consciously not defined as a flag in Attr.td because 22181ad6265SDimitry Andric // we don't want new attributes to specify it. 22281ad6265SDimitry Andric // 22381ad6265SDimitry Andric // Note: No new entries should be added to this list. Entries should be 22481ad6265SDimitry Andric // removed from this list after a suitable deprecation period, provided that 22581ad6265SDimitry Andric // there are no compatibility considerations with other compilers. If 22681ad6265SDimitry Andric // possible, we would like this list to go away entirely. 22781ad6265SDimitry Andric switch (getParsedKind()) { 22881ad6265SDimitry Andric case AT_AddressSpace: 22981ad6265SDimitry Andric case AT_OpenCLPrivateAddressSpace: 23081ad6265SDimitry Andric case AT_OpenCLGlobalAddressSpace: 23181ad6265SDimitry Andric case AT_OpenCLGlobalDeviceAddressSpace: 23281ad6265SDimitry Andric case AT_OpenCLGlobalHostAddressSpace: 23381ad6265SDimitry Andric case AT_OpenCLLocalAddressSpace: 23481ad6265SDimitry Andric case AT_OpenCLConstantAddressSpace: 23581ad6265SDimitry Andric case AT_OpenCLGenericAddressSpace: 23681ad6265SDimitry Andric case AT_NeonPolyVectorType: 23781ad6265SDimitry Andric case AT_NeonVectorType: 23881ad6265SDimitry Andric case AT_ArmMveStrictPolymorphism: 23981ad6265SDimitry Andric case AT_BTFTypeTag: 24081ad6265SDimitry Andric case AT_ObjCGC: 24181ad6265SDimitry Andric case AT_MatrixType: 24281ad6265SDimitry Andric return true; 24381ad6265SDimitry Andric default: 24481ad6265SDimitry Andric return false; 24581ad6265SDimitry Andric } 24681ad6265SDimitry Andric } 24781ad6265SDimitry Andric 24881ad6265SDimitry Andric bool ParsedAttr::acceptsExprPack() const { return getInfo().AcceptsExprPack; } 24981ad6265SDimitry Andric 2500b57cec5SDimitry Andric unsigned ParsedAttr::getSemanticSpelling() const { 2515ffd83dbSDimitry Andric return getInfo().spellingIndexToSemanticSpelling(*this); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric bool ParsedAttr::hasVariadicArg() const { 2550b57cec5SDimitry Andric // If the attribute has the maximum number of optional arguments, we will 2560b57cec5SDimitry Andric // claim that as being variadic. If we someday get an attribute that 2570b57cec5SDimitry Andric // legitimately bumps up against that maximum, we can use another bit to track 2580b57cec5SDimitry Andric // whether it's truly variadic or not. 2595ffd83dbSDimitry Andric return getInfo().OptArgs == 15; 2600b57cec5SDimitry Andric } 261fe6060f1SDimitry Andric 26281ad6265SDimitry Andric bool ParsedAttr::isParamExpr(size_t N) const { 26381ad6265SDimitry Andric return getInfo().isParamExpr(N); 26481ad6265SDimitry Andric } 26581ad6265SDimitry Andric 26681ad6265SDimitry Andric void ParsedAttr::handleAttrWithDelayedArgs(Sema &S, Decl *D) const { 26781ad6265SDimitry Andric ::handleAttrWithDelayedArgs(S, D, *this); 26881ad6265SDimitry Andric } 26981ad6265SDimitry Andric 270fe6060f1SDimitry Andric static unsigned getNumAttributeArgs(const ParsedAttr &AL) { 271fe6060f1SDimitry Andric // FIXME: Include the type in the argument list. 272fe6060f1SDimitry Andric return AL.getNumArgs() + AL.hasParsedType(); 273fe6060f1SDimitry Andric } 274fe6060f1SDimitry Andric 275fe6060f1SDimitry Andric template <typename Compare> 276fe6060f1SDimitry Andric static bool checkAttributeNumArgsImpl(Sema &S, const ParsedAttr &AL, 277fe6060f1SDimitry Andric unsigned Num, unsigned Diag, 278fe6060f1SDimitry Andric Compare Comp) { 279fe6060f1SDimitry Andric if (Comp(getNumAttributeArgs(AL), Num)) { 280fe6060f1SDimitry Andric S.Diag(AL.getLoc(), Diag) << AL << Num; 281fe6060f1SDimitry Andric return false; 282fe6060f1SDimitry Andric } 283fe6060f1SDimitry Andric return true; 284fe6060f1SDimitry Andric } 285fe6060f1SDimitry Andric 286fe6060f1SDimitry Andric bool ParsedAttr::checkExactlyNumArgs(Sema &S, unsigned Num) const { 287fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 288fe6060f1SDimitry Andric diag::err_attribute_wrong_number_arguments, 289fe6060f1SDimitry Andric std::not_equal_to<unsigned>()); 290fe6060f1SDimitry Andric } 291fe6060f1SDimitry Andric bool ParsedAttr::checkAtLeastNumArgs(Sema &S, unsigned Num) const { 292fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 293fe6060f1SDimitry Andric diag::err_attribute_too_few_arguments, 294fe6060f1SDimitry Andric std::less<unsigned>()); 295fe6060f1SDimitry Andric } 296fe6060f1SDimitry Andric bool ParsedAttr::checkAtMostNumArgs(Sema &S, unsigned Num) const { 297fe6060f1SDimitry Andric return checkAttributeNumArgsImpl(S, *this, Num, 298fe6060f1SDimitry Andric diag::err_attribute_too_many_arguments, 299fe6060f1SDimitry Andric std::greater<unsigned>()); 300fe6060f1SDimitry Andric } 30181ad6265SDimitry Andric 30281ad6265SDimitry Andric void clang::takeAndConcatenateAttrs(ParsedAttributes &First, 30381ad6265SDimitry Andric ParsedAttributes &Second, 30481ad6265SDimitry Andric ParsedAttributes &Result) { 30581ad6265SDimitry Andric // Note that takeAllFrom() puts the attributes at the beginning of the list, 30681ad6265SDimitry Andric // so to obtain the correct ordering, we add `Second`, then `First`. 30781ad6265SDimitry Andric Result.takeAllFrom(Second); 30881ad6265SDimitry Andric Result.takeAllFrom(First); 30981ad6265SDimitry Andric if (First.Range.getBegin().isValid()) 31081ad6265SDimitry Andric Result.Range.setBegin(First.Range.getBegin()); 31181ad6265SDimitry Andric else 31281ad6265SDimitry Andric Result.Range.setBegin(Second.Range.getBegin()); 31381ad6265SDimitry Andric if (Second.Range.getEnd().isValid()) 31481ad6265SDimitry Andric Result.Range.setEnd(Second.Range.getEnd()); 31581ad6265SDimitry Andric else 31681ad6265SDimitry Andric Result.Range.setEnd(First.Range.getEnd()); 31781ad6265SDimitry Andric } 318