1 //======- ParsedAttr.cpp --------------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines the ParsedAttr class implementation
12 //===----------------------------------------------------------------------===//
14 #include "clang/Sema/ParsedAttr.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/Basic/AttrSubjectMatchRules.h"
17 #include "clang/Basic/IdentifierTable.h"
18 #include "clang/Basic/TargetInfo.h"
19 #include "clang/Sema/SemaInternal.h"
20 #include "llvm/ADT/SmallString.h"
21 #include "llvm/ADT/SmallVector.h"
22 #include "llvm/ADT/StringRef.h"
27 using namespace clang;
29 IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
30 IdentifierInfo *Ident) {
31 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
33 Result->Ident = Ident;
37 size_t ParsedAttr::allocated_size() const {
38 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
39 else if (IsTypeTagForDatatype)
40 return AttributeFactory::TypeTagForDatatypeAllocSize;
42 return AttributeFactory::PropertyAllocSize;
43 else if (HasParsedType)
44 return sizeof(ParsedAttr) + sizeof(void *);
45 return (sizeof(ParsedAttr) + NumArgs * sizeof(ArgsUnion));
48 AttributeFactory::AttributeFactory() {
49 // Go ahead and configure all the inline capacity. This is just a memset.
50 FreeLists.resize(InlineFreeListsCapacity);
52 AttributeFactory::~AttributeFactory() = default;
54 static size_t getFreeListIndexForSize(size_t size) {
55 assert(size >= sizeof(ParsedAttr));
56 assert((size % sizeof(void*)) == 0);
57 return ((size - sizeof(ParsedAttr)) / sizeof(void *));
60 void *AttributeFactory::allocate(size_t size) {
61 // Check for a previously reclaimed attribute.
62 size_t index = getFreeListIndexForSize(size);
63 if (index < FreeLists.size() && !FreeLists[index].empty()) {
64 ParsedAttr *attr = FreeLists[index].back();
65 FreeLists[index].pop_back();
69 // Otherwise, allocate something new.
70 return Alloc.Allocate(size, alignof(AttributeFactory));
73 void AttributeFactory::deallocate(ParsedAttr *Attr) {
74 size_t size = Attr->allocated_size();
75 size_t freeListIndex = getFreeListIndexForSize(size);
77 // Expand FreeLists to the appropriate size, if required.
78 if (freeListIndex >= FreeLists.size())
79 FreeLists.resize(freeListIndex + 1);
82 // In debug mode, zero out the attribute to help find memory overwriting.
83 memset(Attr, 0, size);
86 // Add 'Attr' to the appropriate free-list.
87 FreeLists[freeListIndex].push_back(Attr);
90 void AttributeFactory::reclaimPool(AttributePool &cur) {
91 for (ParsedAttr *AL : cur.Attrs)
95 void AttributePool::takePool(AttributePool &pool) {
96 Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end());
100 #include "clang/Sema/AttrParsedAttrKinds.inc"
102 static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
103 ParsedAttr::Syntax SyntaxUsed) {
104 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
105 // for GNU attributes.
106 bool IsGNU = SyntaxUsed == ParsedAttr::AS_GNU ||
107 ((SyntaxUsed == ParsedAttr::AS_CXX11 ||
108 SyntaxUsed == ParsedAttr::AS_C2x) &&
110 if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
111 AttrName.endswith("__"))
112 AttrName = AttrName.slice(2, AttrName.size() - 2);
117 ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name,
118 const IdentifierInfo *ScopeName,
120 StringRef AttrName = Name->getName();
122 SmallString<64> FullName;
124 FullName += ScopeName->getName();
126 AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
128 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
130 if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
132 FullName += AttrName;
134 return ::getAttrKind(FullName, SyntaxUsed);
137 unsigned ParsedAttr::getAttributeSpellingListIndex() const {
138 // Both variables will be used in tablegen generated
139 // attribute spell list index matching code.
140 StringRef Scope = ScopeName ? ScopeName->getName() : "";
141 StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
142 (ParsedAttr::Syntax)SyntaxUsed);
144 #include "clang/Sema/AttrSpellingListIndex.inc"
148 struct ParsedAttrInfo {
149 unsigned NumArgs : 4;
150 unsigned OptArgs : 4;
151 unsigned HasCustomParsing : 1;
152 unsigned IsTargetSpecific : 1;
155 unsigned IsKnownToGCC : 1;
156 unsigned IsSupportedByPragmaAttribute : 1;
158 bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *);
159 bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr);
160 bool (*ExistsInTarget)(const TargetInfo &Target);
161 unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr);
162 void (*GetPragmaAttributeMatchRules)(
163 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
164 const LangOptions &LangOpts);
169 #include "clang/Sema/AttrParsedAttrImpl.inc"
173 static const ParsedAttrInfo &getInfo(const ParsedAttr &A) {
174 return AttrInfoMap[A.getKind()];
177 unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; }
179 unsigned ParsedAttr::getMaxArgs() const {
180 return getMinArgs() + getInfo(*this).OptArgs;
183 bool ParsedAttr::hasCustomParsing() const {
184 return getInfo(*this).HasCustomParsing;
187 bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
188 return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
191 bool ParsedAttr::appliesToDecl(const Decl *D,
192 attr::SubjectMatchRule MatchRule) const {
193 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
196 void ParsedAttr::getMatchRules(
197 const LangOptions &LangOpts,
198 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
200 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
203 bool ParsedAttr::diagnoseLangOpts(Sema &S) const {
204 return getInfo(*this).DiagLangOpts(S, *this);
207 bool ParsedAttr::isTargetSpecificAttr() const {
208 return getInfo(*this).IsTargetSpecific;
211 bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; }
213 bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; }
215 bool ParsedAttr::existsInTarget(const TargetInfo &Target) const {
216 return getInfo(*this).ExistsInTarget(Target);
219 bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; }
221 bool ParsedAttr::isSupportedByPragmaAttribute() const {
222 return getInfo(*this).IsSupportedByPragmaAttribute;
225 unsigned ParsedAttr::getSemanticSpelling() const {
226 return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
229 bool ParsedAttr::hasVariadicArg() const {
230 // If the attribute has the maximum number of optional arguments, we will
231 // claim that as being variadic. If we someday get an attribute that
232 // legitimately bumps up against that maximum, we can use another bit to track
233 // whether it's truly variadic or not.
234 return getInfo(*this).OptArgs == 15;