1 //======- ParsedAttr.cpp --------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines the ParsedAttr class implementation
11 //===----------------------------------------------------------------------===//
13 #include "clang/Sema/ParsedAttr.h"
14 #include "clang/AST/ASTContext.h"
15 #include "clang/Basic/AttrSubjectMatchRules.h"
16 #include "clang/Basic/IdentifierTable.h"
17 #include "clang/Basic/TargetInfo.h"
18 #include "clang/Sema/SemaInternal.h"
19 #include "llvm/ADT/SmallString.h"
20 #include "llvm/ADT/SmallVector.h"
21 #include "llvm/ADT/StringRef.h"
22 #include "llvm/Support/ManagedStatic.h"
27 using namespace clang;
29 LLVM_INSTANTIATE_REGISTRY(ParsedAttrInfoRegistry)
31 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
32 IdentifierInfo *Ident) {
33 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
35 Result->Ident = Ident;
39 size_t ParsedAttr::allocated_size() const {
40 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
41 else if (IsTypeTagForDatatype)
42 return AttributeFactory::TypeTagForDatatypeAllocSize;
44 return AttributeFactory::PropertyAllocSize;
45 else if (HasParsedType)
46 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
47 detail::TypeTagForDatatypeData, ParsedType,
48 detail::PropertyData>(0, 0, 0, 1, 0);
49 return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData,
50 detail::TypeTagForDatatypeData, ParsedType,
51 detail::PropertyData>(NumArgs, 0, 0, 0, 0);
54 AttributeFactory::AttributeFactory() {
55 // Go ahead and configure all the inline capacity. This is just a memset.
56 FreeLists.resize(InlineFreeListsCapacity);
58 AttributeFactory::~AttributeFactory() = default;
60 static size_t getFreeListIndexForSize(size_t size) {
61 assert(size >= sizeof(ParsedAttr));
62 assert((size % sizeof(void*)) == 0);
63 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
66 void *AttributeFactory::allocate(size_t size) {
67 // Check for a previously reclaimed attribute.
68 size_t index = getFreeListIndexForSize(size);
69 if (index < FreeLists.size() && !FreeLists[index].empty()) {
70 ParsedAttr *attr = FreeLists[index].back();
71 FreeLists[index].pop_back();
75 // Otherwise, allocate something new.
76 return Alloc.Allocate(size, alignof(AttributeFactory));
79 void AttributeFactory::deallocate(ParsedAttr *Attr) {
80 size_t size = Attr->allocated_size();
81 size_t freeListIndex = getFreeListIndexForSize(size);
83 // Expand FreeLists to the appropriate size, if required.
84 if (freeListIndex >= FreeLists.size())
85 FreeLists.resize(freeListIndex + 1);
88 // In debug mode, zero out the attribute to help find memory overwriting.
89 memset(Attr, 0, size);
92 // Add 'Attr' to the appropriate free-list.
93 FreeLists[freeListIndex].push_back(Attr);
96 void AttributeFactory::reclaimPool(AttributePool &cur) {
97 for (ParsedAttr *AL : cur.Attrs)
101 void AttributePool::takePool(AttributePool &pool) {
102 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
108 #include "clang/Sema/AttrParsedAttrImpl.inc"
112 const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
113 // If we have a ParsedAttrInfo for this ParsedAttr then return that.
114 if ((size_t)A.getParsedKind() < llvm::array_lengthof(AttrInfoMap))
115 return *AttrInfoMap[A.getParsedKind()];
117 // If this is an ignored attribute then return an appropriate ParsedAttrInfo.
118 static const ParsedAttrInfo IgnoredParsedAttrInfo(
119 AttributeCommonInfo::IgnoredAttribute);
120 if (A.getParsedKind() == AttributeCommonInfo::IgnoredAttribute)
121 return IgnoredParsedAttrInfo;
123 // Otherwise this may be an attribute defined by a plugin. First instantiate
124 // all plugin attributes if we haven't already done so.
125 static llvm::ManagedStatic<std::list<std::unique_ptr<ParsedAttrInfo>>>
127 if (PluginAttrInstances->empty())
128 for (auto It : ParsedAttrInfoRegistry::entries())
129 PluginAttrInstances->emplace_back(It.instantiate());
131 // Search for a ParsedAttrInfo whose name and syntax match.
132 std::string FullName = A.getNormalizedFullName();
133 AttributeCommonInfo::Syntax SyntaxUsed = A.getSyntax();
134 if (SyntaxUsed == AttributeCommonInfo::AS_ContextSensitiveKeyword)
135 SyntaxUsed = AttributeCommonInfo::AS_Keyword;
137 for (auto &Ptr : *PluginAttrInstances)
138 for (auto &S : Ptr->Spellings)
139 if (S.Syntax == SyntaxUsed && S.NormalizedFullName == FullName)
142 // If we failed to find a match then return a default ParsedAttrInfo.
143 static const ParsedAttrInfo DefaultParsedAttrInfo(
144 AttributeCommonInfo::UnknownAttribute);
145 return DefaultParsedAttrInfo;
148 unsigned ParsedAttr::getMinArgs() const { return getInfo().NumArgs; }
150 unsigned ParsedAttr::getMaxArgs() const {
151 return getMinArgs() + getInfo().OptArgs;
154 bool ParsedAttr::hasCustomParsing() const {
155 return getInfo().HasCustomParsing;
158 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
159 return getInfo().diagAppertainsToDecl(S, *this, D);
162 bool ParsedAttr::appliesToDecl(const Decl *D,
163 attr::SubjectMatchRule MatchRule) const {
164 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
167 void ParsedAttr::getMatchRules(
168 const LangOptions &LangOpts,
169 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
171 return getInfo().getPragmaAttributeMatchRules(MatchRules, LangOpts);
174 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
175 return getInfo().diagLangOpts(S, *this);
178 bool ParsedAttr::isTargetSpecificAttr() const {
179 return getInfo().IsTargetSpecific;
182 bool ParsedAttr::isTypeAttr() const { return getInfo().IsType; }
184 bool ParsedAttr::isStmtAttr() const { return getInfo().IsStmt; }
186 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
187 return getInfo().existsInTarget(Target);
190 bool ParsedAttr::isKnownToGCC() const { return getInfo().IsKnownToGCC; }
192 bool ParsedAttr::isSupportedByPragmaAttribute() const {
193 return getInfo().IsSupportedByPragmaAttribute;
196 unsigned ParsedAttr::getSemanticSpelling() const {
197 return getInfo().spellingIndexToSemanticSpelling(*this);
200 bool ParsedAttr::hasVariadicArg() const {
201 // If the attribute has the maximum number of optional arguments, we will
202 // claim that as being variadic. If we someday get an attribute that
203 // legitimately bumps up against that maximum, we can use another bit to track
204 // whether it's truly variadic or not.
205 return getInfo().OptArgs == 15;