xref: /aosp_15_r20/external/clang/lib/Sema/AttributeList.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- AttributeList.cpp --------------------------------------*- C++ -*-===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file defines the AttributeList class implementation
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #include "clang/Sema/AttributeList.h"
15*67e74705SXin Li #include "clang/AST/ASTContext.h"
16*67e74705SXin Li #include "clang/AST/DeclCXX.h"
17*67e74705SXin Li #include "clang/AST/DeclTemplate.h"
18*67e74705SXin Li #include "clang/AST/Expr.h"
19*67e74705SXin Li #include "clang/Basic/IdentifierTable.h"
20*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
21*67e74705SXin Li #include "clang/Sema/SemaInternal.h"
22*67e74705SXin Li #include "llvm/ADT/SmallString.h"
23*67e74705SXin Li #include "llvm/ADT/StringSwitch.h"
24*67e74705SXin Li using namespace clang;
25*67e74705SXin Li 
create(ASTContext & Ctx,SourceLocation Loc,IdentifierInfo * Ident)26*67e74705SXin Li IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
27*67e74705SXin Li                                      IdentifierInfo *Ident) {
28*67e74705SXin Li   IdentifierLoc *Result = new (Ctx) IdentifierLoc;
29*67e74705SXin Li   Result->Loc = Loc;
30*67e74705SXin Li   Result->Ident = Ident;
31*67e74705SXin Li   return Result;
32*67e74705SXin Li }
33*67e74705SXin Li 
allocated_size() const34*67e74705SXin Li size_t AttributeList::allocated_size() const {
35*67e74705SXin Li   if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
36*67e74705SXin Li   else if (IsTypeTagForDatatype)
37*67e74705SXin Li     return AttributeFactory::TypeTagForDatatypeAllocSize;
38*67e74705SXin Li   else if (IsProperty)
39*67e74705SXin Li     return AttributeFactory::PropertyAllocSize;
40*67e74705SXin Li   return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
41*67e74705SXin Li }
42*67e74705SXin Li 
AttributeFactory()43*67e74705SXin Li AttributeFactory::AttributeFactory() {
44*67e74705SXin Li   // Go ahead and configure all the inline capacity.  This is just a memset.
45*67e74705SXin Li   FreeLists.resize(InlineFreeListsCapacity);
46*67e74705SXin Li }
~AttributeFactory()47*67e74705SXin Li AttributeFactory::~AttributeFactory() {}
48*67e74705SXin Li 
getFreeListIndexForSize(size_t size)49*67e74705SXin Li static size_t getFreeListIndexForSize(size_t size) {
50*67e74705SXin Li   assert(size >= sizeof(AttributeList));
51*67e74705SXin Li   assert((size % sizeof(void*)) == 0);
52*67e74705SXin Li   return ((size - sizeof(AttributeList)) / sizeof(void*));
53*67e74705SXin Li }
54*67e74705SXin Li 
allocate(size_t size)55*67e74705SXin Li void *AttributeFactory::allocate(size_t size) {
56*67e74705SXin Li   // Check for a previously reclaimed attribute.
57*67e74705SXin Li   size_t index = getFreeListIndexForSize(size);
58*67e74705SXin Li   if (index < FreeLists.size()) {
59*67e74705SXin Li     if (AttributeList *attr = FreeLists[index]) {
60*67e74705SXin Li       FreeLists[index] = attr->NextInPool;
61*67e74705SXin Li       return attr;
62*67e74705SXin Li     }
63*67e74705SXin Li   }
64*67e74705SXin Li 
65*67e74705SXin Li   // Otherwise, allocate something new.
66*67e74705SXin Li   return Alloc.Allocate(size, llvm::AlignOf<AttributeFactory>::Alignment);
67*67e74705SXin Li }
68*67e74705SXin Li 
reclaimPool(AttributeList * cur)69*67e74705SXin Li void AttributeFactory::reclaimPool(AttributeList *cur) {
70*67e74705SXin Li   assert(cur && "reclaiming empty pool!");
71*67e74705SXin Li   do {
72*67e74705SXin Li     // Read this here, because we're going to overwrite NextInPool
73*67e74705SXin Li     // when we toss 'cur' into the appropriate queue.
74*67e74705SXin Li     AttributeList *next = cur->NextInPool;
75*67e74705SXin Li 
76*67e74705SXin Li     size_t size = cur->allocated_size();
77*67e74705SXin Li     size_t freeListIndex = getFreeListIndexForSize(size);
78*67e74705SXin Li 
79*67e74705SXin Li     // Expand FreeLists to the appropriate size, if required.
80*67e74705SXin Li     if (freeListIndex >= FreeLists.size())
81*67e74705SXin Li       FreeLists.resize(freeListIndex+1);
82*67e74705SXin Li 
83*67e74705SXin Li     // Add 'cur' to the appropriate free-list.
84*67e74705SXin Li     cur->NextInPool = FreeLists[freeListIndex];
85*67e74705SXin Li     FreeLists[freeListIndex] = cur;
86*67e74705SXin Li 
87*67e74705SXin Li     cur = next;
88*67e74705SXin Li   } while (cur);
89*67e74705SXin Li }
90*67e74705SXin Li 
takePool(AttributeList * pool)91*67e74705SXin Li void AttributePool::takePool(AttributeList *pool) {
92*67e74705SXin Li   assert(pool);
93*67e74705SXin Li 
94*67e74705SXin Li   // Fast path:  this pool is empty.
95*67e74705SXin Li   if (!Head) {
96*67e74705SXin Li     Head = pool;
97*67e74705SXin Li     return;
98*67e74705SXin Li   }
99*67e74705SXin Li 
100*67e74705SXin Li   // Reverse the pool onto the current head.  This optimizes for the
101*67e74705SXin Li   // pattern of pulling a lot of pools into a single pool.
102*67e74705SXin Li   do {
103*67e74705SXin Li     AttributeList *next = pool->NextInPool;
104*67e74705SXin Li     pool->NextInPool = Head;
105*67e74705SXin Li     Head = pool;
106*67e74705SXin Li     pool = next;
107*67e74705SXin Li   } while (pool);
108*67e74705SXin Li }
109*67e74705SXin Li 
110*67e74705SXin Li #include "clang/Sema/AttrParsedAttrKinds.inc"
111*67e74705SXin Li 
normalizeAttrName(StringRef AttrName,StringRef ScopeName,AttributeList::Syntax SyntaxUsed)112*67e74705SXin Li static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
113*67e74705SXin Li                                    AttributeList::Syntax SyntaxUsed) {
114*67e74705SXin Li   // Normalize the attribute name, __foo__ becomes foo. This is only allowable
115*67e74705SXin Li   // for GNU attributes.
116*67e74705SXin Li   bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
117*67e74705SXin Li                (SyntaxUsed == AttributeList::AS_CXX11 && ScopeName == "gnu");
118*67e74705SXin Li   if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
119*67e74705SXin Li       AttrName.endswith("__"))
120*67e74705SXin Li     AttrName = AttrName.slice(2, AttrName.size() - 2);
121*67e74705SXin Li 
122*67e74705SXin Li   return AttrName;
123*67e74705SXin Li }
124*67e74705SXin Li 
getKind(const IdentifierInfo * Name,const IdentifierInfo * ScopeName,Syntax SyntaxUsed)125*67e74705SXin Li AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
126*67e74705SXin Li                                            const IdentifierInfo *ScopeName,
127*67e74705SXin Li                                            Syntax SyntaxUsed) {
128*67e74705SXin Li   StringRef AttrName = Name->getName();
129*67e74705SXin Li 
130*67e74705SXin Li   SmallString<64> FullName;
131*67e74705SXin Li   if (ScopeName)
132*67e74705SXin Li     FullName += ScopeName->getName();
133*67e74705SXin Li 
134*67e74705SXin Li   AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
135*67e74705SXin Li 
136*67e74705SXin Li   // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
137*67e74705SXin Li   // unscoped.
138*67e74705SXin Li   if (ScopeName || SyntaxUsed == AS_CXX11)
139*67e74705SXin Li     FullName += "::";
140*67e74705SXin Li   FullName += AttrName;
141*67e74705SXin Li 
142*67e74705SXin Li   return ::getAttrKind(FullName, SyntaxUsed);
143*67e74705SXin Li }
144*67e74705SXin Li 
getAttributeSpellingListIndex() const145*67e74705SXin Li unsigned AttributeList::getAttributeSpellingListIndex() const {
146*67e74705SXin Li   // Both variables will be used in tablegen generated
147*67e74705SXin Li   // attribute spell list index matching code.
148*67e74705SXin Li   StringRef Scope = ScopeName ? ScopeName->getName() : "";
149*67e74705SXin Li   StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
150*67e74705SXin Li                                      (AttributeList::Syntax)SyntaxUsed);
151*67e74705SXin Li 
152*67e74705SXin Li #include "clang/Sema/AttrSpellingListIndex.inc"
153*67e74705SXin Li 
154*67e74705SXin Li }
155*67e74705SXin Li 
156*67e74705SXin Li struct ParsedAttrInfo {
157*67e74705SXin Li   unsigned NumArgs : 4;
158*67e74705SXin Li   unsigned OptArgs : 4;
159*67e74705SXin Li   unsigned HasCustomParsing : 1;
160*67e74705SXin Li   unsigned IsTargetSpecific : 1;
161*67e74705SXin Li   unsigned IsType : 1;
162*67e74705SXin Li   unsigned IsStmt : 1;
163*67e74705SXin Li   unsigned IsKnownToGCC : 1;
164*67e74705SXin Li 
165*67e74705SXin Li   bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
166*67e74705SXin Li                                const Decl *);
167*67e74705SXin Li   bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
168*67e74705SXin Li   bool (*ExistsInTarget)(const TargetInfo &Target);
169*67e74705SXin Li   unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
170*67e74705SXin Li };
171*67e74705SXin Li 
172*67e74705SXin Li namespace {
173*67e74705SXin Li   #include "clang/Sema/AttrParsedAttrImpl.inc"
174*67e74705SXin Li }
175*67e74705SXin Li 
getInfo(const AttributeList & A)176*67e74705SXin Li static const ParsedAttrInfo &getInfo(const AttributeList &A) {
177*67e74705SXin Li   return AttrInfoMap[A.getKind()];
178*67e74705SXin Li }
179*67e74705SXin Li 
getMinArgs() const180*67e74705SXin Li unsigned AttributeList::getMinArgs() const {
181*67e74705SXin Li   return getInfo(*this).NumArgs;
182*67e74705SXin Li }
183*67e74705SXin Li 
getMaxArgs() const184*67e74705SXin Li unsigned AttributeList::getMaxArgs() const {
185*67e74705SXin Li   return getMinArgs() + getInfo(*this).OptArgs;
186*67e74705SXin Li }
187*67e74705SXin Li 
hasCustomParsing() const188*67e74705SXin Li bool AttributeList::hasCustomParsing() const {
189*67e74705SXin Li   return getInfo(*this).HasCustomParsing;
190*67e74705SXin Li }
191*67e74705SXin Li 
diagnoseAppertainsTo(Sema & S,const Decl * D) const192*67e74705SXin Li bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
193*67e74705SXin Li   return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
194*67e74705SXin Li }
195*67e74705SXin Li 
diagnoseLangOpts(Sema & S) const196*67e74705SXin Li bool AttributeList::diagnoseLangOpts(Sema &S) const {
197*67e74705SXin Li   return getInfo(*this).DiagLangOpts(S, *this);
198*67e74705SXin Li }
199*67e74705SXin Li 
isTargetSpecificAttr() const200*67e74705SXin Li bool AttributeList::isTargetSpecificAttr() const {
201*67e74705SXin Li   return getInfo(*this).IsTargetSpecific;
202*67e74705SXin Li }
203*67e74705SXin Li 
isTypeAttr() const204*67e74705SXin Li bool AttributeList::isTypeAttr() const {
205*67e74705SXin Li   return getInfo(*this).IsType;
206*67e74705SXin Li }
207*67e74705SXin Li 
isStmtAttr() const208*67e74705SXin Li bool AttributeList::isStmtAttr() const {
209*67e74705SXin Li   return getInfo(*this).IsStmt;
210*67e74705SXin Li }
211*67e74705SXin Li 
existsInTarget(const TargetInfo & Target) const212*67e74705SXin Li bool AttributeList::existsInTarget(const TargetInfo &Target) const {
213*67e74705SXin Li   return getInfo(*this).ExistsInTarget(Target);
214*67e74705SXin Li }
215*67e74705SXin Li 
isKnownToGCC() const216*67e74705SXin Li bool AttributeList::isKnownToGCC() const {
217*67e74705SXin Li   return getInfo(*this).IsKnownToGCC;
218*67e74705SXin Li }
219*67e74705SXin Li 
getSemanticSpelling() const220*67e74705SXin Li unsigned AttributeList::getSemanticSpelling() const {
221*67e74705SXin Li   return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
222*67e74705SXin Li }
223*67e74705SXin Li 
hasVariadicArg() const224*67e74705SXin Li bool AttributeList::hasVariadicArg() const {
225*67e74705SXin Li   // If the attribute has the maximum number of optional arguments, we will
226*67e74705SXin Li   // claim that as being variadic. If we someday get an attribute that
227*67e74705SXin Li   // legitimately bumps up against that maximum, we can use another bit to track
228*67e74705SXin Li   // whether it's truly variadic or not.
229*67e74705SXin Li   return getInfo(*this).OptArgs == 15;
230*67e74705SXin Li }
231