File: | tools/clang/lib/Sema/ParsedAttr.cpp |
Warning: | line 31, column 3 Called C++ object pointer is null |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //======- ParsedAttr.cpp --------------------------------------------------===// | |||
2 | // | |||
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 | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file defines the ParsedAttr class implementation | |||
10 | // | |||
11 | //===----------------------------------------------------------------------===// | |||
12 | ||||
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 <cassert> | |||
23 | #include <cstddef> | |||
24 | #include <utility> | |||
25 | ||||
26 | using namespace clang; | |||
27 | ||||
28 | IdentifierLoc *IdentifierLoc::create(ASTContext &Ctx, SourceLocation Loc, | |||
29 | IdentifierInfo *Ident) { | |||
30 | IdentifierLoc *Result = new (Ctx) IdentifierLoc; | |||
| ||||
31 | Result->Loc = Loc; | |||
| ||||
32 | Result->Ident = Ident; | |||
33 | return Result; | |||
34 | } | |||
35 | ||||
36 | size_t ParsedAttr::allocated_size() const { | |||
37 | if (IsAvailability) return AttributeFactory::AvailabilityAllocSize; | |||
38 | else if (IsTypeTagForDatatype) | |||
39 | return AttributeFactory::TypeTagForDatatypeAllocSize; | |||
40 | else if (IsProperty) | |||
41 | return AttributeFactory::PropertyAllocSize; | |||
42 | else if (HasParsedType) | |||
43 | return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, | |||
44 | detail::TypeTagForDatatypeData, ParsedType, | |||
45 | detail::PropertyData>(0, 0, 0, 1, 0); | |||
46 | return totalSizeToAlloc<ArgsUnion, detail::AvailabilityData, | |||
47 | detail::TypeTagForDatatypeData, ParsedType, | |||
48 | detail::PropertyData>(NumArgs, 0, 0, 0, 0); | |||
49 | } | |||
50 | ||||
51 | AttributeFactory::AttributeFactory() { | |||
52 | // Go ahead and configure all the inline capacity. This is just a memset. | |||
53 | FreeLists.resize(InlineFreeListsCapacity); | |||
54 | } | |||
55 | AttributeFactory::~AttributeFactory() = default; | |||
56 | ||||
57 | static size_t getFreeListIndexForSize(size_t size) { | |||
58 | assert(size >= sizeof(ParsedAttr))((size >= sizeof(ParsedAttr)) ? static_cast<void> (0 ) : __assert_fail ("size >= sizeof(ParsedAttr)", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/Sema/ParsedAttr.cpp" , 58, __PRETTY_FUNCTION__)); | |||
59 | assert((size % sizeof(void*)) == 0)(((size % sizeof(void*)) == 0) ? static_cast<void> (0) : __assert_fail ("(size % sizeof(void*)) == 0", "/build/llvm-toolchain-snapshot-9~svn362543/tools/clang/lib/Sema/ParsedAttr.cpp" , 59, __PRETTY_FUNCTION__)); | |||
60 | return ((size - sizeof(ParsedAttr)) / sizeof(void *)); | |||
61 | } | |||
62 | ||||
63 | void *AttributeFactory::allocate(size_t size) { | |||
64 | // Check for a previously reclaimed attribute. | |||
65 | size_t index = getFreeListIndexForSize(size); | |||
66 | if (index < FreeLists.size() && !FreeLists[index].empty()) { | |||
67 | ParsedAttr *attr = FreeLists[index].back(); | |||
68 | FreeLists[index].pop_back(); | |||
69 | return attr; | |||
70 | } | |||
71 | ||||
72 | // Otherwise, allocate something new. | |||
73 | return Alloc.Allocate(size, alignof(AttributeFactory)); | |||
74 | } | |||
75 | ||||
76 | void AttributeFactory::deallocate(ParsedAttr *Attr) { | |||
77 | size_t size = Attr->allocated_size(); | |||
78 | size_t freeListIndex = getFreeListIndexForSize(size); | |||
79 | ||||
80 | // Expand FreeLists to the appropriate size, if required. | |||
81 | if (freeListIndex >= FreeLists.size()) | |||
82 | FreeLists.resize(freeListIndex + 1); | |||
83 | ||||
84 | #ifndef NDEBUG | |||
85 | // In debug mode, zero out the attribute to help find memory overwriting. | |||
86 | memset(Attr, 0, size); | |||
87 | #endif | |||
88 | ||||
89 | // Add 'Attr' to the appropriate free-list. | |||
90 | FreeLists[freeListIndex].push_back(Attr); | |||
91 | } | |||
92 | ||||
93 | void AttributeFactory::reclaimPool(AttributePool &cur) { | |||
94 | for (ParsedAttr *AL : cur.Attrs) | |||
95 | deallocate(AL); | |||
96 | } | |||
97 | ||||
98 | void AttributePool::takePool(AttributePool &pool) { | |||
99 | Attrs.insert(Attrs.end(), pool.Attrs.begin(), pool.Attrs.end()); | |||
100 | pool.Attrs.clear(); | |||
101 | } | |||
102 | ||||
103 | #include "clang/Sema/AttrParsedAttrKinds.inc" | |||
104 | ||||
105 | static StringRef normalizeAttrScopeName(StringRef ScopeName, | |||
106 | ParsedAttr::Syntax SyntaxUsed) { | |||
107 | // Normalize the "__gnu__" scope name to be "gnu" and the "_Clang" scope name | |||
108 | // to be "clang". | |||
109 | if (SyntaxUsed == ParsedAttr::AS_CXX11 || | |||
110 | SyntaxUsed == ParsedAttr::AS_C2x) { | |||
111 | if (ScopeName == "__gnu__") | |||
112 | ScopeName = "gnu"; | |||
113 | else if (ScopeName == "_Clang") | |||
114 | ScopeName = "clang"; | |||
115 | } | |||
116 | return ScopeName; | |||
117 | } | |||
118 | ||||
119 | static StringRef normalizeAttrName(StringRef AttrName, | |||
120 | StringRef NormalizedScopeName, | |||
121 | ParsedAttr::Syntax SyntaxUsed) { | |||
122 | // Normalize the attribute name, __foo__ becomes foo. This is only allowable | |||
123 | // for GNU attributes, and attributes using the double square bracket syntax. | |||
124 | bool ShouldNormalize = | |||
125 | SyntaxUsed == ParsedAttr::AS_GNU || | |||
126 | ((SyntaxUsed == ParsedAttr::AS_CXX11 || | |||
127 | SyntaxUsed == ParsedAttr::AS_C2x) && | |||
128 | (NormalizedScopeName == "gnu" || NormalizedScopeName == "clang")); | |||
129 | if (ShouldNormalize && AttrName.size() >= 4 && AttrName.startswith("__") && | |||
130 | AttrName.endswith("__")) | |||
131 | AttrName = AttrName.slice(2, AttrName.size() - 2); | |||
132 | ||||
133 | return AttrName; | |||
134 | } | |||
135 | ||||
136 | ParsedAttr::Kind ParsedAttr::getKind(const IdentifierInfo *Name, | |||
137 | const IdentifierInfo *ScopeName, | |||
138 | Syntax SyntaxUsed) { | |||
139 | StringRef AttrName = Name->getName(); | |||
140 | ||||
141 | SmallString<64> FullName; | |||
142 | if (ScopeName) | |||
143 | FullName += normalizeAttrScopeName(ScopeName->getName(), SyntaxUsed); | |||
144 | ||||
145 | AttrName = normalizeAttrName(AttrName, FullName, SyntaxUsed); | |||
146 | ||||
147 | // Ensure that in the case of C++11 attributes, we look for '::foo' if it is | |||
148 | // unscoped. | |||
149 | if (ScopeName || SyntaxUsed == AS_CXX11 || SyntaxUsed == AS_C2x) | |||
150 | FullName += "::"; | |||
151 | FullName += AttrName; | |||
152 | ||||
153 | return ::getAttrKind(FullName, SyntaxUsed); | |||
154 | } | |||
155 | ||||
156 | unsigned ParsedAttr::getAttributeSpellingListIndex() const { | |||
157 | // Both variables will be used in tablegen generated | |||
158 | // attribute spell list index matching code. | |||
159 | auto Syntax = static_cast<ParsedAttr::Syntax>(SyntaxUsed); | |||
160 | StringRef Scope = | |||
161 | ScopeName ? normalizeAttrScopeName(ScopeName->getName(), Syntax) : ""; | |||
162 | StringRef Name = normalizeAttrName(AttrName->getName(), Scope, Syntax); | |||
163 | ||||
164 | #include "clang/Sema/AttrSpellingListIndex.inc" | |||
165 | ||||
166 | } | |||
167 | ||||
168 | struct ParsedAttrInfo { | |||
169 | unsigned NumArgs : 4; | |||
170 | unsigned OptArgs : 4; | |||
171 | unsigned HasCustomParsing : 1; | |||
172 | unsigned IsTargetSpecific : 1; | |||
173 | unsigned IsType : 1; | |||
174 | unsigned IsStmt : 1; | |||
175 | unsigned IsKnownToGCC : 1; | |||
176 | unsigned IsSupportedByPragmaAttribute : 1; | |||
177 | ||||
178 | bool (*DiagAppertainsToDecl)(Sema &S, const ParsedAttr &Attr, const Decl *); | |||
179 | bool (*DiagLangOpts)(Sema &S, const ParsedAttr &Attr); | |||
180 | bool (*ExistsInTarget)(const TargetInfo &Target); | |||
181 | unsigned (*SpellingIndexToSemanticSpelling)(const ParsedAttr &Attr); | |||
182 | void (*GetPragmaAttributeMatchRules)( | |||
183 | llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules, | |||
184 | const LangOptions &LangOpts); | |||
185 | }; | |||
186 | ||||
187 | namespace { | |||
188 | ||||
189 | #include "clang/Sema/AttrParsedAttrImpl.inc" | |||
190 | ||||
191 | } // namespace | |||
192 | ||||
193 | static const ParsedAttrInfo &getInfo(const ParsedAttr &A) { | |||
194 | return AttrInfoMap[A.getKind()]; | |||
195 | } | |||
196 | ||||
197 | unsigned ParsedAttr::getMinArgs() const { return getInfo(*this).NumArgs; } | |||
198 | ||||
199 | unsigned ParsedAttr::getMaxArgs() const { | |||
200 | return getMinArgs() + getInfo(*this).OptArgs; | |||
201 | } | |||
202 | ||||
203 | bool ParsedAttr::hasCustomParsing() const { | |||
204 | return getInfo(*this).HasCustomParsing; | |||
205 | } | |||
206 | ||||
207 | bool ParsedAttr::diagnoseAppertainsTo(Sema &S, const Decl *D) const { | |||
208 | return getInfo(*this).DiagAppertainsToDecl(S, *this, D); | |||
209 | } | |||
210 | ||||
211 | bool ParsedAttr::appliesToDecl(const Decl *D, | |||
212 | attr::SubjectMatchRule MatchRule) const { | |||
213 | return checkAttributeMatchRuleAppliesTo(D, MatchRule); | |||
214 | } | |||
215 | ||||
216 | void ParsedAttr::getMatchRules( | |||
217 | const LangOptions &LangOpts, | |||
218 | SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &MatchRules) | |||
219 | const { | |||
220 | return getInfo(*this).GetPragmaAttributeMatchRules(MatchRules, LangOpts); | |||
221 | } | |||
222 | ||||
223 | bool ParsedAttr::diagnoseLangOpts(Sema &S) const { | |||
224 | return getInfo(*this).DiagLangOpts(S, *this); | |||
225 | } | |||
226 | ||||
227 | bool ParsedAttr::isTargetSpecificAttr() const { | |||
228 | return getInfo(*this).IsTargetSpecific; | |||
229 | } | |||
230 | ||||
231 | bool ParsedAttr::isTypeAttr() const { return getInfo(*this).IsType; } | |||
232 | ||||
233 | bool ParsedAttr::isStmtAttr() const { return getInfo(*this).IsStmt; } | |||
234 | ||||
235 | bool ParsedAttr::existsInTarget(const TargetInfo &Target) const { | |||
236 | return getInfo(*this).ExistsInTarget(Target); | |||
237 | } | |||
238 | ||||
239 | bool ParsedAttr::isKnownToGCC() const { return getInfo(*this).IsKnownToGCC; } | |||
240 | ||||
241 | bool ParsedAttr::isSupportedByPragmaAttribute() const { | |||
242 | return getInfo(*this).IsSupportedByPragmaAttribute; | |||
243 | } | |||
244 | ||||
245 | unsigned ParsedAttr::getSemanticSpelling() const { | |||
246 | return getInfo(*this).SpellingIndexToSemanticSpelling(*this); | |||
247 | } | |||
248 | ||||
249 | bool ParsedAttr::hasVariadicArg() const { | |||
250 | // If the attribute has the maximum number of optional arguments, we will | |||
251 | // claim that as being variadic. If we someday get an attribute that | |||
252 | // legitimately bumps up against that maximum, we can use another bit to track | |||
253 | // whether it's truly variadic or not. | |||
254 | return getInfo(*this).OptArgs == 15; | |||
255 | } |