File: | tools/clang/lib/Sema/AttributeList.cpp |
Warning: | line 32, column 3 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- AttributeList.cpp --------------------------------------------------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file defines the AttributeList class implementation | |||
11 | // | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "clang/Sema/AttributeList.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" | |||
23 | #include <cassert> | |||
24 | #include <cstddef> | |||
25 | #include <utility> | |||
26 | ||||
27 | using namespace clang; | |||
28 | ||||
29 | IdentifierLoc *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 | ||||
37 | size_t AttributeList::allocated_size() const { | |||
38 | if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; | |||
39 | else if (IsTypeTagForDatatype) | |||
40 | return AttributeFactory::TypeTagForDatatypeAllocSize; | |||
41 | else if (IsProperty) | |||
42 | return AttributeFactory::PropertyAllocSize; | |||
43 | else if (HasParsedType) | |||
44 | return sizeof(AttributeList) + sizeof(void *); | |||
45 | return (sizeof(AttributeList) + NumArgs * sizeof(ArgsUnion)); | |||
46 | } | |||
47 | ||||
48 | AttributeFactory::AttributeFactory() { | |||
49 | // Go ahead and configure all the inline capacity. This is just a memset. | |||
50 | FreeLists.resize(InlineFreeListsCapacity); | |||
51 | } | |||
52 | AttributeFactory::~AttributeFactory() = default; | |||
53 | ||||
54 | static size_t getFreeListIndexForSize(size_t size) { | |||
55 | assert(size >= sizeof(AttributeList))(static_cast <bool> (size >= sizeof(AttributeList)) ? void (0) : __assert_fail ("size >= sizeof(AttributeList)" , "/build/llvm-toolchain-snapshot-7~svn336939/tools/clang/lib/Sema/AttributeList.cpp" , 55, __extension__ __PRETTY_FUNCTION__)); | |||
56 | assert((size % sizeof(void*)) == 0)(static_cast <bool> ((size % sizeof(void*)) == 0) ? void (0) : __assert_fail ("(size % sizeof(void*)) == 0", "/build/llvm-toolchain-snapshot-7~svn336939/tools/clang/lib/Sema/AttributeList.cpp" , 56, __extension__ __PRETTY_FUNCTION__)); | |||
57 | return ((size - sizeof(AttributeList)) / sizeof(void*)); | |||
58 | } | |||
59 | ||||
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()) { | |||
64 | if (AttributeList *attr = FreeLists[index]) { | |||
65 | FreeLists[index] = attr->NextInPool; | |||
66 | return attr; | |||
67 | } | |||
68 | } | |||
69 | ||||
70 | // Otherwise, allocate something new. | |||
71 | return Alloc.Allocate(size, alignof(AttributeFactory)); | |||
72 | } | |||
73 | ||||
74 | void AttributeFactory::reclaimPool(AttributeList *cur) { | |||
75 | assert(cur && "reclaiming empty pool!")(static_cast <bool> (cur && "reclaiming empty pool!" ) ? void (0) : __assert_fail ("cur && \"reclaiming empty pool!\"" , "/build/llvm-toolchain-snapshot-7~svn336939/tools/clang/lib/Sema/AttributeList.cpp" , 75, __extension__ __PRETTY_FUNCTION__)); | |||
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 | ||||
96 | void AttributePool::takePool(AttributeList *pool) { | |||
97 | assert(pool)(static_cast <bool> (pool) ? void (0) : __assert_fail ( "pool", "/build/llvm-toolchain-snapshot-7~svn336939/tools/clang/lib/Sema/AttributeList.cpp" , 97, __extension__ __PRETTY_FUNCTION__)); | |||
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 | ||||
115 | #include "clang/Sema/AttrParsedAttrKinds.inc" | |||
116 | ||||
117 | static 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 || | |||
122 | ((SyntaxUsed == AttributeList::AS_CXX11 || | |||
123 | SyntaxUsed == AttributeList::AS_C2x) && ScopeName == "gnu"); | |||
124 | if (IsGNU && AttrName.size() >= 4 && AttrName.startswith("__") && | |||
125 | AttrName.endswith("__")) | |||
126 | AttrName = AttrName.slice(2, AttrName.size() - 2); | |||
127 | ||||
128 | return AttrName; | |||
129 | } | |||
130 | ||||
131 | AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name, | |||
132 | const IdentifierInfo *ScopeName, | |||
133 | Syntax SyntaxUsed) { | |||
134 | StringRef AttrName = Name->getName(); | |||
135 | ||||
136 | SmallString<64> FullName; | |||
137 | if (ScopeName) | |||
138 | FullName += ScopeName->getName(); | |||
139 | ||||
140 | AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); | |||
141 | ||||
142 | // Ensure that in the case of C++11 attributes, we look for '::foo' if it is | |||
143 | // unscoped. | |||
144 | if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x) | |||
145 | FullName += "::"; | |||
146 | FullName += AttrName; | |||
147 | ||||
148 | return ::getAttrKind(FullName, SyntaxUsed); | |||
149 | } | |||
150 | ||||
151 | unsigned AttributeList::getAttributeSpellingListIndex() const { | |||
152 | // Both variables will be used in tablegen generated | |||
153 | // attribute spell list index matching code. | |||
154 | StringRef Scope = ScopeName ? ScopeName->getName() : ""; | |||
155 | StringRef Name = normalizeAttrName(AttrName->getName(), Scope, | |||
156 | (AttributeList::Syntax)SyntaxUsed); | |||
157 | ||||
158 | #include "clang/Sema/AttrSpellingListIndex.inc" | |||
159 | ||||
160 | } | |||
161 | ||||
162 | struct ParsedAttrInfo { | |||
163 | unsigned NumArgs : 4; | |||
164 | unsigned OptArgs : 4; | |||
165 | unsigned HasCustomParsing : 1; | |||
166 | unsigned IsTargetSpecific : 1; | |||
167 | unsigned IsType : 1; | |||
168 | unsigned IsStmt : 1; | |||
169 | unsigned IsKnownToGCC : 1; | |||
170 | unsigned IsSupportedByPragmaAttribute : 1; | |||
171 | ||||
172 | bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, | |||
173 | const Decl *); | |||
174 | bool (*DiagLangOpts)(Sema &S, const AttributeList &Attr); | |||
175 | bool (*ExistsInTarget)(const TargetInfo &Target); | |||
176 | unsigned (*SpellingIndexToSemanticSpelling)(const AttributeList &Attr); | |||
177 | void (*GetPragmaAttributeMatchRules)( | |||
178 | llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, | |||
179 | const LangOptions &LangOpts); | |||
180 | }; | |||
181 | ||||
182 | namespace { | |||
183 | ||||
184 | #include "clang/Sema/AttrParsedAttrImpl.inc" | |||
185 | ||||
186 | } // namespace | |||
187 | ||||
188 | static const ParsedAttrInfo &getInfo(const AttributeList &A) { | |||
189 | return AttrInfoMap[A.getKind()]; | |||
190 | } | |||
191 | ||||
192 | unsigned AttributeList::getMinArgs() const { | |||
193 | return getInfo(*this).NumArgs; | |||
194 | } | |||
195 | ||||
196 | unsigned AttributeList::getMaxArgs() const { | |||
197 | return getMinArgs() + getInfo(*this).OptArgs; | |||
198 | } | |||
199 | ||||
200 | bool AttributeList::hasCustomParsing() const { | |||
201 | return getInfo(*this).HasCustomParsing; | |||
202 | } | |||
203 | ||||
204 | bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const { | |||
205 | return getInfo(*this).DiagAppertainsToDecl(S, *this, D); | |||
206 | } | |||
207 | ||||
208 | bool AttributeList::appliesToDecl(const Decl *D, | |||
209 | attr::SubjectMatchRule MatchRule) const { | |||
210 | return checkAttributeMatchRuleAppliesTo(D, MatchRule); | |||
211 | } | |||
212 | ||||
213 | void 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 | ||||
220 | bool AttributeList::diagnoseLangOpts(Sema &S) const { | |||
221 | return getInfo(*this).DiagLangOpts(S, *this); | |||
222 | } | |||
223 | ||||
224 | bool AttributeList::isTargetSpecificAttr() const { | |||
225 | return getInfo(*this).IsTargetSpecific; | |||
226 | } | |||
227 | ||||
228 | bool AttributeList::isTypeAttr() const { | |||
229 | return getInfo(*this).IsType; | |||
230 | } | |||
231 | ||||
232 | bool AttributeList::isStmtAttr() const { | |||
233 | return getInfo(*this).IsStmt; | |||
234 | } | |||
235 | ||||
236 | bool AttributeList::existsInTarget(const TargetInfo &Target) const { | |||
237 | return getInfo(*this).ExistsInTarget(Target); | |||
238 | } | |||
239 | ||||
240 | bool AttributeList::isKnownToGCC() const { | |||
241 | return getInfo(*this).IsKnownToGCC; | |||
242 | } | |||
243 | ||||
244 | bool AttributeList::isSupportedByPragmaAttribute() const { | |||
245 | return getInfo(*this).IsSupportedByPragmaAttribute; | |||
246 | } | |||
247 | ||||
248 | unsigned AttributeList::getSemanticSpelling() const { | |||
249 | return getInfo(*this).SpellingIndexToSemanticSpelling(*this); | |||
250 | } | |||
251 | ||||
252 | bool 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 | } |