blob: 4cd32b361da51e87cd3b637408eb2e1582d0d194 [file] [log] [blame]
Eugene Zelenko711964d2018-02-20 02:16:28 +00001//===- AttributeList.cpp --------------------------------------------------===//
Steve Naroffb8371e12007-06-09 03:39:29 +00002//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner5b12ab82007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Steve Naroffb8371e12007-06-09 03:39:29 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the AttributeList class implementation
11//
12//===----------------------------------------------------------------------===//
13
John McCall8b0666c2010-08-20 18:27:03 +000014#include "clang/Sema/AttributeList.h"
Benjamin Kramer1ea8e092012-07-04 17:04:04 +000015#include "clang/AST/ASTContext.h"
Alex Lorenz9e7bf162017-04-18 14:33:39 +000016#include "clang/Basic/AttrSubjectMatchRules.h"
Chris Lattner7e0fe442009-04-11 18:48:18 +000017#include "clang/Basic/IdentifierTable.h"
Bob Wilson7c730832015-07-20 22:57:31 +000018#include "clang/Basic/TargetInfo.h"
Chandler Carruth5553d0d2014-01-07 11:51:46 +000019#include "clang/Sema/SemaInternal.h"
Richard Smith84837d52012-05-03 18:27:39 +000020#include "llvm/ADT/SmallString.h"
Eugene Zelenko711964d2018-02-20 02:16:28 +000021#include "llvm/ADT/SmallVector.h"
22#include "llvm/ADT/StringRef.h"
23#include <cassert>
24#include <cstddef>
25#include <utility>
26
Steve Naroffb8371e12007-06-09 03:39:29 +000027using namespace clang;
28
Richard Smithfeefaf52013-09-03 18:01:40 +000029IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc,
30 IdentifierInfo *Ident) {
31 IdentifierLoc *Result = new (Ctx) IdentifierLoc;
32 Result->Loc = Loc;
33 Result->Ident = Ident;
34 return Result;
35}
36
John McCall084e83d2011-03-24 11:26:52 +000037size_t AttributeList::allocated_size() const {
38 if (IsAvailability) return AttributeFactory::AvailabilityAllocSize;
Dmitri Gribenkoe4a5a902012-08-17 00:08:38 +000039 else if (IsTypeTagForDatatype)
40 return AttributeFactory::TypeTagForDatatypeAllocSize;
John McCall5e77d762013-04-16 07:28:30 +000041 else if (IsProperty)
42 return AttributeFactory::PropertyAllocSize;
Erich Keane87cfcfd2018-06-22 17:34:44 +000043 else if (HasParsedType)
44 return sizeof(AttributeList) + sizeof(void *);
Aaron Ballman00e99962013-08-31 01:11:41 +000045 return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion));
Steve Naroffb8371e12007-06-09 03:39:29 +000046}
Chris Lattnerf18c7432008-02-20 23:14:47 +000047
John McCall084e83d2011-03-24 11:26:52 +000048AttributeFactory::AttributeFactory() {
49 // Go ahead and configure all the inline capacity. This is just a memset.
50 FreeLists.resize(InlineFreeListsCapacity);
51}
Eugene Zelenko711964d2018-02-20 02:16:28 +000052AttributeFactory::~AttributeFactory() = default;
John McCall084e83d2011-03-24 11:26:52 +000053
54static size_t getFreeListIndexForSize(size_t size) {
55 assert(size >= sizeof(AttributeList));
56 assert((size % sizeof(void*)) == 0);
57 return ((size - sizeof(AttributeList)) / sizeof(void*));
58}
59
60void *AttributeFactory::allocate(size_t size) {
61 // Check for a previously reclaimed attribute.
62 size_t index = getFreeListIndexForSize(size);
63 if (index < FreeLists.size()) {
64 if (AttributeList *attr = FreeLists[index]) {
65 FreeLists[index] = attr->NextInPool;
66 return attr;
67 }
68 }
69
70 // Otherwise, allocate something new.
Benjamin Kramerc3f89252016-10-20 14:27:22 +000071 return Alloc.Allocate(size, alignof(AttributeFactory));
John McCall084e83d2011-03-24 11:26:52 +000072}
73
74void AttributeFactory::reclaimPool(AttributeList *cur) {
75 assert(cur && "reclaiming empty pool!");
76 do {
77 // Read this here, because we're going to overwrite NextInPool
78 // when we toss 'cur' into the appropriate queue.
79 AttributeList *next = cur->NextInPool;
80
81 size_t size = cur->allocated_size();
82 size_t freeListIndex = getFreeListIndexForSize(size);
83
84 // Expand FreeLists to the appropriate size, if required.
85 if (freeListIndex >= FreeLists.size())
86 FreeLists.resize(freeListIndex+1);
87
88 // Add 'cur' to the appropriate free-list.
89 cur->NextInPool = FreeLists[freeListIndex];
90 FreeLists[freeListIndex] = cur;
91
92 cur = next;
93 } while (cur);
94}
95
96void AttributePool::takePool(AttributeList *pool) {
97 assert(pool);
98
99 // Fast path: this pool is empty.
100 if (!Head) {
101 Head = pool;
102 return;
103 }
104
105 // Reverse the pool onto the current head. This optimizes for the
106 // pattern of pulling a lot of pools into a single pool.
107 do {
108 AttributeList *next = pool->NextInPool;
109 pool->NextInPool = Head;
110 Head = pool;
111 pool = next;
112 } while (pool);
113}
114
Douglas Gregor377f99b2012-05-02 17:33:51 +0000115#include "clang/Sema/AttrParsedAttrKinds.inc"
116
David Majnemera94e7b62015-08-25 16:44:38 +0000117static StringRef normalizeAttrName(StringRef AttrName, StringRef ScopeName,
118 AttributeList::Syntax SyntaxUsed) {
119 // Normalize the attribute name, __foo__ becomes foo. This is only allowable
120 // for GNU attributes.
121 bool IsGNU = SyntaxUsed == AttributeList::AS_GNU ||
Aaron Ballman606093a2017-10-15 15:01:42 +0000122 ((SyntaxUsed == AttributeList::AS_CXX11 ||
123 SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu");
David Majnemera94e7b62015-08-25 16:44:38 +0000124 if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") &&
125 AttrName.endswith("__"))
126 AttrName = AttrName.slice(2, AttrName.size() - 2);
127
128 return AttrName;
129}
130
Richard Smith84837d52012-05-03 18:27:39 +0000131AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name,
Alexis Hunta0e54d42012-06-18 16:13:52 +0000132 const IdentifierInfo *ScopeName,
133 Syntax SyntaxUsed) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000134 StringRef AttrName = Name->getName();
Chris Lattnerf18c7432008-02-20 23:14:47 +0000135
Aaron Ballmanc6988092013-12-11 22:27:44 +0000136 SmallString<64> FullName;
Richard Smith84837d52012-05-03 18:27:39 +0000137 if (ScopeName)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000138 FullName += ScopeName->getName();
139
David Majnemera94e7b62015-08-25 16:44:38 +0000140 AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed);
Aaron Ballmanc6988092013-12-11 22:27:44 +0000141
Alexis Hunta0e54d42012-06-18 16:13:52 +0000142 // Ensure that in the case of C++11 attributes, we look for '::foo' if it is
143 // unscoped.
Aaron Ballman606093a2017-10-15 15:01:42 +0000144 if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x)
Aaron Ballmanc6988092013-12-11 22:27:44 +0000145 FullName += "::";
146 FullName += AttrName;
Richard Smith84837d52012-05-03 18:27:39 +0000147
Aaron Ballman09e98ff2014-01-13 21:42:39 +0000148 return ::getAttrKind(FullName, SyntaxUsed);
Chris Lattnerf18c7432008-02-20 23:14:47 +0000149}
Michael Han99315932013-01-24 16:46:58 +0000150
151unsigned AttributeList::getAttributeSpellingListIndex() const {
152 // Both variables will be used in tablegen generated
153 // attribute spell list index matching code.
Michael Han99315932013-01-24 16:46:58 +0000154 StringRef Scope = ScopeName ? ScopeName->getName() : "";
David Majnemera94e7b62015-08-25 16:44:38 +0000155 StringRef Name = normalizeAttrName(AttrName->getName(), Scope,
156 (AttributeList::Syntax)SyntaxUsed);
Michael Han99315932013-01-24 16:46:58 +0000157
158#include "clang/Sema/AttrSpellingListIndex.inc"
159
160}
161
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000162struct ParsedAttrInfo {
163 unsigned NumArgs : 4;
164 unsigned OptArgs : 4;
165 unsigned HasCustomParsing : 1;
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000166 unsigned IsTargetSpecific : 1;
167 unsigned IsType : 1;
Richard Smith4f902c72016-03-08 00:32:55 +0000168 unsigned IsStmt : 1;
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000169 unsigned IsKnownToGCC : 1;
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000170 unsigned IsSupportedByPragmaAttribute : 1;
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000171
172 bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
173 const Decl *);
Aaron Ballman3aff6332013-12-02 19:30:36 +0000174 bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr);
Bob Wilson7c730832015-07-20 22:57:31 +0000175 bool (*ExistsInTarget)(const TargetInfo &Target);
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000176 unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000177 void (*GetPragmaAttributeMatchRules)(
178 llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
179 const LangOptions &LangOpts);
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000180};
181
182namespace {
Eugene Zelenko711964d2018-02-20 02:16:28 +0000183
184#include "clang/Sema/AttrParsedAttrImpl.inc"
185
186} // namespace
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000187
Benjamin Kramer602623f2013-09-28 15:08:41 +0000188static const ParsedAttrInfo &getInfo(const AttributeList &A) {
Aaron Ballman8ee40b72013-09-09 23:33:17 +0000189 return AttrInfoMap[A.getKind()];
190}
191
192unsigned AttributeList::getMinArgs() const {
193 return getInfo(*this).NumArgs;
194}
195
196unsigned AttributeList::getMaxArgs() const {
197 return getMinArgs() + getInfo(*this).OptArgs;
198}
199
200bool AttributeList::hasCustomParsing() const {
201 return getInfo(*this).HasCustomParsing;
202}
Aaron Ballman74eeeae2013-11-27 13:27:02 +0000203
204bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
205 return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
206}
Aaron Ballman3aff6332013-12-02 19:30:36 +0000207
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000208bool AttributeList::appliesToDecl(const Decl *D,
209 attr::SubjectMatchRule MatchRule) const {
210 return checkAttributeMatchRuleAppliesTo(D, MatchRule);
211}
212
213void AttributeList::getMatchRules(
214 const LangOptions &LangOpts,
215 SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules)
216 const {
217 return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts);
218}
219
Aaron Ballman3aff6332013-12-02 19:30:36 +0000220bool AttributeList::diagnoseLangOpts(Sema &S) const {
221 return getInfo(*this).DiagLangOpts(S, *this);
222}
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000223
224bool AttributeList::isTargetSpecificAttr() const {
225 return getInfo(*this).IsTargetSpecific;
226}
227
228bool AttributeList::isTypeAttr() const {
229 return getInfo(*this).IsType;
230}
231
Richard Smith4f902c72016-03-08 00:32:55 +0000232bool AttributeList::isStmtAttr() const {
233 return getInfo(*this).IsStmt;
234}
235
Bob Wilson7c730832015-07-20 22:57:31 +0000236bool AttributeList::existsInTarget(const TargetInfo &Target) const {
237 return getInfo(*this).ExistsInTarget(Target);
Aaron Ballmanab7691c2014-01-09 22:48:32 +0000238}
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000239
Aaron Ballmanc669cc02014-01-27 22:10:04 +0000240bool AttributeList::isKnownToGCC() const {
241 return getInfo(*this).IsKnownToGCC;
Aaron Ballman9a99e0d2014-01-20 17:18:35 +0000242}
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000243
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000244bool AttributeList::isSupportedByPragmaAttribute() const {
245 return getInfo(*this).IsSupportedByPragmaAttribute;
246}
247
Aaron Ballman81cb8cb2014-01-24 21:32:49 +0000248unsigned AttributeList::getSemanticSpelling() const {
249 return getInfo(*this).SpellingIndexToSemanticSpelling(*this);
250}
Aaron Ballman8ed8dbd2014-07-31 16:37:04 +0000251
252bool AttributeList::hasVariadicArg() const {
253 // If the attribute has the maximum number of optional arguments, we will
254 // claim that as being variadic. If we someday get an attribute that
255 // legitimately bumps up against that maximum, we can use another bit to track
256 // whether it's truly variadic or not.
257 return getInfo(*this).OptArgs == 15;
258}