/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/include/clang/Basic/IdentifierTable.h
Line | Count | Source (jump to first uncovered line) |
1 | | //===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===// |
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 | | /// \file |
10 | | /// Defines the clang::IdentifierInfo, clang::IdentifierTable, and |
11 | | /// clang::Selector interfaces. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H |
16 | | #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H |
17 | | |
18 | | #include "clang/Basic/LLVM.h" |
19 | | #include "clang/Basic/TokenKinds.h" |
20 | | #include "llvm/ADT/DenseMapInfo.h" |
21 | | #include "llvm/ADT/SmallString.h" |
22 | | #include "llvm/ADT/StringMap.h" |
23 | | #include "llvm/ADT/StringRef.h" |
24 | | #include "llvm/Support/Allocator.h" |
25 | | #include "llvm/Support/PointerLikeTypeTraits.h" |
26 | | #include "llvm/Support/type_traits.h" |
27 | | #include <cassert> |
28 | | #include <cstddef> |
29 | | #include <cstdint> |
30 | | #include <cstring> |
31 | | #include <string> |
32 | | #include <utility> |
33 | | |
34 | | namespace clang { |
35 | | |
36 | | class DeclarationName; |
37 | | class DeclarationNameTable; |
38 | | class IdentifierInfo; |
39 | | class LangOptions; |
40 | | class MultiKeywordSelector; |
41 | | class SourceLocation; |
42 | | |
43 | | /// A simple pair of identifier info and location. |
44 | | using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>; |
45 | | |
46 | | /// IdentifierInfo and other related classes are aligned to |
47 | | /// 8 bytes so that DeclarationName can use the lower 3 bits |
48 | | /// of a pointer to one of these classes. |
49 | | enum { IdentifierInfoAlignment = 8 }; |
50 | | |
51 | | static constexpr int ObjCOrBuiltinIDBits = 15; |
52 | | |
53 | | /// One of these records is kept for each identifier that |
54 | | /// is lexed. This contains information about whether the token was \#define'd, |
55 | | /// is a language keyword, or if it is a front-end token of some sort (e.g. a |
56 | | /// variable or function name). The preprocessor keeps this information in a |
57 | | /// set, and all tok::identifier tokens have a pointer to one of these. |
58 | | /// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits. |
59 | | class alignas(IdentifierInfoAlignment) IdentifierInfo { |
60 | | friend class IdentifierTable; |
61 | | |
62 | | // Front-end token ID or tok::identifier. |
63 | | unsigned TokenID : 9; |
64 | | |
65 | | // ObjC keyword ('protocol' in '@protocol') or builtin (__builtin_inf). |
66 | | // First NUM_OBJC_KEYWORDS values are for Objective-C, |
67 | | // the remaining values are for builtins. |
68 | | unsigned ObjCOrBuiltinID : ObjCOrBuiltinIDBits; |
69 | | |
70 | | // True if there is a #define for this. |
71 | | unsigned HasMacro : 1; |
72 | | |
73 | | // True if there was a #define for this. |
74 | | unsigned HadMacro : 1; |
75 | | |
76 | | // True if the identifier is a language extension. |
77 | | unsigned IsExtension : 1; |
78 | | |
79 | | // True if the identifier is a keyword in a newer or proposed Standard. |
80 | | unsigned IsFutureCompatKeyword : 1; |
81 | | |
82 | | // True if the identifier is poisoned. |
83 | | unsigned IsPoisoned : 1; |
84 | | |
85 | | // True if the identifier is a C++ operator keyword. |
86 | | unsigned IsCPPOperatorKeyword : 1; |
87 | | |
88 | | // Internal bit set by the member function RecomputeNeedsHandleIdentifier. |
89 | | // See comment about RecomputeNeedsHandleIdentifier for more info. |
90 | | unsigned NeedsHandleIdentifier : 1; |
91 | | |
92 | | // True if the identifier was loaded (at least partially) from an AST file. |
93 | | unsigned IsFromAST : 1; |
94 | | |
95 | | // True if the identifier has changed from the definition |
96 | | // loaded from an AST file. |
97 | | unsigned ChangedAfterLoad : 1; |
98 | | |
99 | | // True if the identifier's frontend information has changed from the |
100 | | // definition loaded from an AST file. |
101 | | unsigned FEChangedAfterLoad : 1; |
102 | | |
103 | | // True if revertTokenIDToIdentifier was called. |
104 | | unsigned RevertedTokenID : 1; |
105 | | |
106 | | // True if there may be additional information about |
107 | | // this identifier stored externally. |
108 | | unsigned OutOfDate : 1; |
109 | | |
110 | | // True if this is the 'import' contextual keyword. |
111 | | unsigned IsModulesImport : 1; |
112 | | |
113 | | // True if this is a mangled OpenMP variant name. |
114 | | unsigned IsMangledOpenMPVariantName : 1; |
115 | | |
116 | | // 28 bits left in a 64-bit word. |
117 | | |
118 | | // Managed by the language front-end. |
119 | | void *FETokenInfo = nullptr; |
120 | | |
121 | | llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr; |
122 | | |
123 | | IdentifierInfo() |
124 | | : TokenID(tok::identifier), ObjCOrBuiltinID(0), HasMacro(false), |
125 | | HadMacro(false), IsExtension(false), IsFutureCompatKeyword(false), |
126 | | IsPoisoned(false), IsCPPOperatorKeyword(false), |
127 | | NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false), |
128 | | FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false), |
129 | 382M | IsModulesImport(false), IsMangledOpenMPVariantName(false) {} |
130 | | |
131 | | public: |
132 | | IdentifierInfo(const IdentifierInfo &) = delete; |
133 | | IdentifierInfo &operator=(const IdentifierInfo &) = delete; |
134 | | IdentifierInfo(IdentifierInfo &&) = delete; |
135 | | IdentifierInfo &operator=(IdentifierInfo &&) = delete; |
136 | | |
137 | | /// Return true if this is the identifier for the specified string. |
138 | | /// |
139 | | /// This is intended to be used for string literals only: II->isStr("foo"). |
140 | | template <std::size_t StrLen> |
141 | 164M | bool isStr(const char (&Str)[StrLen]) const { |
142 | 164M | return getLength() == StrLen-1 && |
143 | 13.5M | memcmp(getNameStart(), Str, StrLen-1) == 0; |
144 | 164M | } bool clang::IdentifierInfo::isStr<5ul>(char const (&) [5ul]) const Line | Count | Source | 141 | 76.5M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 76.5M | return getLength() == StrLen-1 && | 143 | 1.31M | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 76.5M | } |
bool clang::IdentifierInfo::isStr<20ul>(char const (&) [20ul]) const Line | Count | Source | 141 | 24.0k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 24.0k | return getLength() == StrLen-1 && | 143 | 1.16k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 24.0k | } |
bool clang::IdentifierInfo::isStr<7ul>(char const (&) [7ul]) const Line | Count | Source | 141 | 8.73M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 8.73M | return getLength() == StrLen-1 && | 143 | 444k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 8.73M | } |
bool clang::IdentifierInfo::isStr<8ul>(char const (&) [8ul]) const Line | Count | Source | 141 | 17.7M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 17.7M | return getLength() == StrLen-1 && | 143 | 2.54M | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 17.7M | } |
bool clang::IdentifierInfo::isStr<6ul>(char const (&) [6ul]) const Line | Count | Source | 141 | 11.3M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 11.3M | return getLength() == StrLen-1 && | 143 | 4.39M | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 11.3M | } |
bool clang::IdentifierInfo::isStr<4ul>(char const (&) [4ul]) const Line | Count | Source | 141 | 3.67M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 3.67M | return getLength() == StrLen-1 && | 143 | 1.96M | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 3.67M | } |
bool clang::IdentifierInfo::isStr<22ul>(char const (&) [22ul]) const Line | Count | Source | 141 | 23 | bool isStr(const char (&Str)[StrLen]) const { | 142 | 23 | return getLength() == StrLen-1 && | 143 | 23 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 23 | } |
bool clang::IdentifierInfo::isStr<13ul>(char const (&) [13ul]) const Line | Count | Source | 141 | 11.3k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 11.3k | return getLength() == StrLen-1 && | 143 | 61 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 11.3k | } |
bool clang::IdentifierInfo::isStr<14ul>(char const (&) [14ul]) const Line | Count | Source | 141 | 12.8k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 12.8k | return getLength() == StrLen-1 && | 143 | 801 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 12.8k | } |
bool clang::IdentifierInfo::isStr<15ul>(char const (&) [15ul]) const Line | Count | Source | 141 | 28.9k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 28.9k | return getLength() == StrLen-1 && | 143 | 174 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 28.9k | } |
bool clang::IdentifierInfo::isStr<10ul>(char const (&) [10ul]) const Line | Count | Source | 141 | 13.7M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 13.7M | return getLength() == StrLen-1 && | 143 | 768k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 13.7M | } |
bool clang::IdentifierInfo::isStr<12ul>(char const (&) [12ul]) const Line | Count | Source | 141 | 1.59M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 1.59M | return getLength() == StrLen-1 && | 143 | 13.7k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 1.59M | } |
bool clang::IdentifierInfo::isStr<9ul>(char const (&) [9ul]) const Line | Count | Source | 141 | 13.9M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 13.9M | return getLength() == StrLen-1 && | 143 | 1.81M | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 13.9M | } |
bool clang::IdentifierInfo::isStr<16ul>(char const (&) [16ul]) const Line | Count | Source | 141 | 104k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 104k | return getLength() == StrLen-1 && | 143 | 18.2k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 104k | } |
bool clang::IdentifierInfo::isStr<17ul>(char const (&) [17ul]) const Line | Count | Source | 141 | 104k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 104k | return getLength() == StrLen-1 && | 143 | 23 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 104k | } |
bool clang::IdentifierInfo::isStr<11ul>(char const (&) [11ul]) const Line | Count | Source | 141 | 3.67M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 3.67M | return getLength() == StrLen-1 && | 143 | 142k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 3.67M | } |
bool clang::IdentifierInfo::isStr<3ul>(char const (&) [3ul]) const Line | Count | Source | 141 | 1.46k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 1.46k | return getLength() == StrLen-1 && | 143 | 1.04k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 1.46k | } |
bool clang::IdentifierInfo::isStr<2ul>(char const (&) [2ul]) const Line | Count | Source | 141 | 242k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 242k | return getLength() == StrLen-1 && | 143 | 1.43k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 242k | } |
bool clang::IdentifierInfo::isStr<18ul>(char const (&) [18ul]) const Line | Count | Source | 141 | 564k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 564k | return getLength() == StrLen-1 && | 143 | 155 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 564k | } |
bool clang::IdentifierInfo::isStr<19ul>(char const (&) [19ul]) const Line | Count | Source | 141 | 2.12k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 2.12k | return getLength() == StrLen-1 && | 143 | 19 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 2.12k | } |
bool clang::IdentifierInfo::isStr<21ul>(char const (&) [21ul]) const Line | Count | Source | 141 | 85 | bool isStr(const char (&Str)[StrLen]) const { | 142 | 85 | return getLength() == StrLen-1 && | 143 | 10 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 85 | } |
bool clang::IdentifierInfo::isStr<29ul>(char const (&) [29ul]) const Line | Count | Source | 141 | 12.8M | bool isStr(const char (&Str)[StrLen]) const { | 142 | 12.8M | return getLength() == StrLen-1 && | 143 | 97.6k | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 12.8M | } |
bool clang::IdentifierInfo::isStr<24ul>(char const (&) [24ul]) const Line | Count | Source | 141 | 1.61k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 1.61k | return getLength() == StrLen-1 && | 143 | 16 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 1.61k | } |
bool clang::IdentifierInfo::isStr<27ul>(char const (&) [27ul]) const Line | Count | Source | 141 | 22.9k | bool isStr(const char (&Str)[StrLen]) const { | 142 | 22.9k | return getLength() == StrLen-1 && | 143 | 31 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 22.9k | } |
bool clang::IdentifierInfo::isStr<30ul>(char const (&) [30ul]) const Line | Count | Source | 141 | 73 | bool isStr(const char (&Str)[StrLen]) const { | 142 | 73 | return getLength() == StrLen-1 && | 143 | 3 | memcmp(getNameStart(), Str, StrLen-1) == 0; | 144 | 73 | } |
|
145 | | |
146 | | /// Return true if this is the identifier for the specified StringRef. |
147 | 2.83k | bool isStr(llvm::StringRef Str) const { |
148 | 2.83k | llvm::StringRef ThisStr(getNameStart(), getLength()); |
149 | 2.83k | return ThisStr == Str; |
150 | 2.83k | } |
151 | | |
152 | | /// Return the beginning of the actual null-terminated string for this |
153 | | /// identifier. |
154 | 1.58G | const char *getNameStart() const { return Entry->getKeyData(); } |
155 | | |
156 | | /// Efficiently return the length of this identifier info. |
157 | 1.73G | unsigned getLength() const { return Entry->getKeyLength(); } |
158 | | |
159 | | /// Return the actual identifier string. |
160 | 1.39G | StringRef getName() const { |
161 | 1.39G | return StringRef(getNameStart(), getLength()); |
162 | 1.39G | } |
163 | | |
164 | | /// Return true if this identifier is \#defined to some other value. |
165 | | /// \note The current definition may be in a module and not currently visible. |
166 | 1.11G | bool hasMacroDefinition() const { |
167 | 1.11G | return HasMacro; |
168 | 1.11G | } |
169 | 54.8M | void setHasMacroDefinition(bool Val) { |
170 | 54.8M | if (HasMacro == Val) return893k ; |
171 | | |
172 | 53.9M | HasMacro = Val; |
173 | 53.9M | if (Val) { |
174 | 53.8M | NeedsHandleIdentifier = true; |
175 | 53.8M | HadMacro = true; |
176 | 114k | } else { |
177 | 114k | RecomputeNeedsHandleIdentifier(); |
178 | 114k | } |
179 | 53.9M | } |
180 | | /// Returns true if this identifier was \#defined to some value at any |
181 | | /// moment. In this case there should be an entry for the identifier in the |
182 | | /// macro history table in Preprocessor. |
183 | 41.4M | bool hadMacroDefinition() const { |
184 | 41.4M | return HadMacro; |
185 | 41.4M | } |
186 | | |
187 | | /// If this is a source-language token (e.g. 'for'), this API |
188 | | /// can be used to cause the lexer to map identifiers to source-language |
189 | | /// tokens. |
190 | 829M | tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } |
191 | | |
192 | | /// True if revertTokenIDToIdentifier() was called. |
193 | 44.1M | bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; } |
194 | | |
195 | | /// Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2 |
196 | | /// compatibility. |
197 | | /// |
198 | | /// TokenID is normally read-only but there are 2 instances where we revert it |
199 | | /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens |
200 | | /// using this method so we can inform serialization about it. |
201 | 169k | void revertTokenIDToIdentifier() { |
202 | 169k | assert(TokenID != tok::identifier && "Already at tok::identifier"); |
203 | 169k | TokenID = tok::identifier; |
204 | 169k | RevertedTokenID = true; |
205 | 169k | } |
206 | 2 | void revertIdentifierToTokenID(tok::TokenKind TK) { |
207 | 2 | assert(TokenID == tok::identifier && "Should be at tok::identifier"); |
208 | 2 | TokenID = TK; |
209 | 2 | RevertedTokenID = false; |
210 | 2 | } |
211 | | |
212 | | /// Return the preprocessor keyword ID for this identifier. |
213 | | /// |
214 | | /// For example, "define" will return tok::pp_define. |
215 | | tok::PPKeywordKind getPPKeywordID() const; |
216 | | |
217 | | /// Return the Objective-C keyword ID for the this identifier. |
218 | | /// |
219 | | /// For example, 'class' will return tok::objc_class if ObjC is enabled. |
220 | 1.57M | tok::ObjCKeywordKind getObjCKeywordID() const { |
221 | 1.57M | if (ObjCOrBuiltinID < tok::NUM_OBJC_KEYWORDS) |
222 | 1.57M | return tok::ObjCKeywordKind(ObjCOrBuiltinID); |
223 | 6 | else |
224 | 6 | return tok::objc_not_keyword; |
225 | 1.57M | } |
226 | 1.78M | void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; } |
227 | | |
228 | | /// Return a value indicating whether this is a builtin function. |
229 | | /// |
230 | | /// 0 is not-built-in. 1+ are specific builtin functions. |
231 | 209M | unsigned getBuiltinID() const { |
232 | 209M | if (ObjCOrBuiltinID >= tok::NUM_OBJC_KEYWORDS) |
233 | 54.6M | return ObjCOrBuiltinID - tok::NUM_OBJC_KEYWORDS; |
234 | 154M | else |
235 | 154M | return 0; |
236 | 209M | } |
237 | 235M | void setBuiltinID(unsigned ID) { |
238 | 235M | ObjCOrBuiltinID = ID + tok::NUM_OBJC_KEYWORDS; |
239 | 235M | assert(ObjCOrBuiltinID - unsigned(tok::NUM_OBJC_KEYWORDS) == ID |
240 | 235M | && "ID too large for field!"); |
241 | 235M | } |
242 | | |
243 | 54.3M | unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; } |
244 | 502k | void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; } |
245 | | |
246 | | /// get/setExtension - Initialize information about whether or not this |
247 | | /// language token is an extension. This controls extension warnings, and is |
248 | | /// only valid if a custom token ID is set. |
249 | 141M | bool isExtensionToken() const { return IsExtension; } |
250 | 31.2M | void setIsExtensionToken(bool Val) { |
251 | 31.2M | IsExtension = Val; |
252 | 31.2M | if (Val) |
253 | 2.41M | NeedsHandleIdentifier = true; |
254 | 28.8M | else |
255 | 28.8M | RecomputeNeedsHandleIdentifier(); |
256 | 31.2M | } |
257 | | |
258 | | /// is/setIsFutureCompatKeyword - Initialize information about whether or not |
259 | | /// this language token is a keyword in a newer or proposed Standard. This |
260 | | /// controls compatibility warnings, and is only true when not parsing the |
261 | | /// corresponding Standard. Once a compatibility problem has been diagnosed |
262 | | /// with this keyword, the flag will be cleared. |
263 | 127M | bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; } |
264 | 31.2M | void setIsFutureCompatKeyword(bool Val) { |
265 | 31.2M | IsFutureCompatKeyword = Val; |
266 | 31.2M | if (Val) |
267 | 735k | NeedsHandleIdentifier = true; |
268 | 30.5M | else |
269 | 30.5M | RecomputeNeedsHandleIdentifier(); |
270 | 31.2M | } |
271 | | |
272 | | /// setIsPoisoned - Mark this identifier as poisoned. After poisoning, the |
273 | | /// Preprocessor will emit an error every time this token is used. |
274 | 58.9M | void setIsPoisoned(bool Value = true) { |
275 | 58.9M | IsPoisoned = Value; |
276 | 58.9M | if (Value) |
277 | 51.8M | NeedsHandleIdentifier = true; |
278 | 7.13M | else |
279 | 7.13M | RecomputeNeedsHandleIdentifier(); |
280 | 58.9M | } |
281 | | |
282 | | /// Return true if this token has been poisoned. |
283 | 630M | bool isPoisoned() const { return IsPoisoned; } |
284 | | |
285 | | /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether |
286 | | /// this identifier is a C++ alternate representation of an operator. |
287 | 967k | void setIsCPlusPlusOperatorKeyword(bool Val = true) { |
288 | 967k | IsCPPOperatorKeyword = Val; |
289 | 967k | } |
290 | 82.6M | bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } |
291 | | |
292 | | /// Return true if this token is a keyword in the specified language. |
293 | | bool isKeyword(const LangOptions &LangOpts) const; |
294 | | |
295 | | /// Return true if this token is a C++ keyword in the specified |
296 | | /// language. |
297 | | bool isCPlusPlusKeyword(const LangOptions &LangOpts) const; |
298 | | |
299 | | /// Get and set FETokenInfo. The language front-end is allowed to associate |
300 | | /// arbitrary metadata with this token. |
301 | 396M | void *getFETokenInfo() const { return FETokenInfo; } |
302 | 73.2M | void setFETokenInfo(void *T) { FETokenInfo = T; } |
303 | | |
304 | | /// Return true if the Preprocessor::HandleIdentifier must be called |
305 | | /// on a token of this identifier. |
306 | | /// |
307 | | /// If this returns false, we know that HandleIdentifier will not affect |
308 | | /// the token. |
309 | 805M | bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } |
310 | | |
311 | | /// Return true if the identifier in its current state was loaded |
312 | | /// from an AST file. |
313 | 161M | bool isFromAST() const { return IsFromAST; } |
314 | | |
315 | 19.3M | void setIsFromAST() { IsFromAST = true; } |
316 | | |
317 | | /// Determine whether this identifier has changed since it was loaded |
318 | | /// from an AST file. |
319 | 1.96M | bool hasChangedSinceDeserialization() const { |
320 | 1.96M | return ChangedAfterLoad; |
321 | 1.96M | } |
322 | | |
323 | | /// Note that this identifier has changed since it was loaded from |
324 | | /// an AST file. |
325 | 81.9k | void setChangedSinceDeserialization() { |
326 | 81.9k | ChangedAfterLoad = true; |
327 | 81.9k | } |
328 | | |
329 | | /// Determine whether the frontend token information for this |
330 | | /// identifier has changed since it was loaded from an AST file. |
331 | 116k | bool hasFETokenInfoChangedSinceDeserialization() const { |
332 | 116k | return FEChangedAfterLoad; |
333 | 116k | } |
334 | | |
335 | | /// Note that the frontend token information for this identifier has |
336 | | /// changed since it was loaded from an AST file. |
337 | 478k | void setFETokenInfoChangedSinceDeserialization() { |
338 | 478k | FEChangedAfterLoad = true; |
339 | 478k | } |
340 | | |
341 | | /// Determine whether the information for this identifier is out of |
342 | | /// date with respect to the external source. |
343 | 1.04G | bool isOutOfDate() const { return OutOfDate; } |
344 | | |
345 | | /// Set whether the information for this identifier is out of |
346 | | /// date with respect to the external source. |
347 | 30.5M | void setOutOfDate(bool OOD) { |
348 | 30.5M | OutOfDate = OOD; |
349 | 30.5M | if (OOD) |
350 | 24.4M | NeedsHandleIdentifier = true; |
351 | 6.03M | else |
352 | 6.03M | RecomputeNeedsHandleIdentifier(); |
353 | 30.5M | } |
354 | | |
355 | | /// Determine whether this is the contextual keyword \c import. |
356 | 70.1M | bool isModulesImport() const { return IsModulesImport; } |
357 | | |
358 | | /// Set whether this identifier is the contextual keyword \c import. |
359 | 136k | void setModulesImport(bool I) { |
360 | 136k | IsModulesImport = I; |
361 | 136k | if (I) |
362 | 136k | NeedsHandleIdentifier = true; |
363 | 0 | else |
364 | 0 | RecomputeNeedsHandleIdentifier(); |
365 | 136k | } |
366 | | |
367 | | /// Determine whether this is the mangled name of an OpenMP variant. |
368 | 2.24M | bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; } |
369 | | |
370 | | /// Set whether this is the mangled name of an OpenMP variant. |
371 | 16.7k | void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; } |
372 | | |
373 | | /// Return true if this identifier is an editor placeholder. |
374 | | /// |
375 | | /// Editor placeholders are produced by the code-completion engine and are |
376 | | /// represented as characters between '<#' and '#>' in the source code. An |
377 | | /// example of auto-completed call with a placeholder parameter is shown |
378 | | /// below: |
379 | | /// \code |
380 | | /// function(<#int x#>); |
381 | | /// \endcode |
382 | 15.3M | bool isEditorPlaceholder() const { |
383 | 15.3M | return getName().startswith("<#") && getName().endswith("#>")27 ; |
384 | 15.3M | } |
385 | | |
386 | | /// Determine whether \p this is a name reserved for the implementation (C99 |
387 | | /// 7.1.3, C++ [lib.global.names]). |
388 | 26.4k | bool isReservedName(bool doubleUnderscoreOnly = false) const { |
389 | 26.4k | if (getLength() < 2) |
390 | 2.96k | return false; |
391 | 23.5k | const char *Name = getNameStart(); |
392 | 23.5k | return Name[0] == '_' && |
393 | 5.93k | (Name[1] == '_' || |
394 | 172 | (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly8 )); |
395 | 23.5k | } |
396 | | |
397 | | /// Provide less than operator for lexicographical sorting. |
398 | 509M | bool operator<(const IdentifierInfo &RHS) const { |
399 | 509M | return getName() < RHS.getName(); |
400 | 509M | } |
401 | | |
402 | | private: |
403 | | /// The Preprocessor::HandleIdentifier does several special (but rare) |
404 | | /// things to identifiers of various sorts. For example, it changes the |
405 | | /// \c for keyword token from tok::identifier to tok::for. |
406 | | /// |
407 | | /// This method is very tied to the definition of HandleIdentifier. Any |
408 | | /// change to it should be reflected here. |
409 | 72.6M | void RecomputeNeedsHandleIdentifier() { |
410 | 72.6M | NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition()72.6M || |
411 | 72.4M | isExtensionToken() || isFutureCompatKeyword()70.0M || |
412 | 70.0M | isOutOfDate() || isModulesImport()70.0M ; |
413 | 72.6M | } |
414 | | }; |
415 | | |
416 | | /// An RAII object for [un]poisoning an identifier within a scope. |
417 | | /// |
418 | | /// \p II is allowed to be null, in which case objects of this type have |
419 | | /// no effect. |
420 | | class PoisonIdentifierRAIIObject { |
421 | | IdentifierInfo *const II; |
422 | | const bool OldValue; |
423 | | |
424 | | public: |
425 | | PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue) |
426 | 24.8M | : II(II), OldValue(II ? II->isPoisoned() : false) { |
427 | 24.8M | if(II) |
428 | 432 | II->setIsPoisoned(NewValue); |
429 | 24.8M | } |
430 | | |
431 | 24.8M | ~PoisonIdentifierRAIIObject() { |
432 | 24.8M | if(II) |
433 | 432 | II->setIsPoisoned(OldValue); |
434 | 24.8M | } |
435 | | }; |
436 | | |
437 | | /// An iterator that walks over all of the known identifiers |
438 | | /// in the lookup table. |
439 | | /// |
440 | | /// Since this iterator uses an abstract interface via virtual |
441 | | /// functions, it uses an object-oriented interface rather than the |
442 | | /// more standard C++ STL iterator interface. In this OO-style |
443 | | /// iteration, the single function \c Next() provides dereference, |
444 | | /// advance, and end-of-sequence checking in a single |
445 | | /// operation. Subclasses of this iterator type will provide the |
446 | | /// actual functionality. |
447 | | class IdentifierIterator { |
448 | | protected: |
449 | 361 | IdentifierIterator() = default; |
450 | | |
451 | | public: |
452 | | IdentifierIterator(const IdentifierIterator &) = delete; |
453 | | IdentifierIterator &operator=(const IdentifierIterator &) = delete; |
454 | | |
455 | | virtual ~IdentifierIterator(); |
456 | | |
457 | | /// Retrieve the next string in the identifier table and |
458 | | /// advances the iterator for the following string. |
459 | | /// |
460 | | /// \returns The next string in the identifier table. If there is |
461 | | /// no such string, returns an empty \c StringRef. |
462 | | virtual StringRef Next() = 0; |
463 | | }; |
464 | | |
465 | | /// Provides lookups to, and iteration over, IdentiferInfo objects. |
466 | | class IdentifierInfoLookup { |
467 | | public: |
468 | | virtual ~IdentifierInfoLookup(); |
469 | | |
470 | | /// Return the IdentifierInfo for the specified named identifier. |
471 | | /// |
472 | | /// Unlike the version in IdentifierTable, this returns a pointer instead |
473 | | /// of a reference. If the pointer is null then the IdentifierInfo cannot |
474 | | /// be found. |
475 | | virtual IdentifierInfo* get(StringRef Name) = 0; |
476 | | |
477 | | /// Retrieve an iterator into the set of all identifiers |
478 | | /// known to this identifier lookup source. |
479 | | /// |
480 | | /// This routine provides access to all of the identifiers known to |
481 | | /// the identifier lookup, allowing access to the contents of the |
482 | | /// identifiers without introducing the overhead of constructing |
483 | | /// IdentifierInfo objects for each. |
484 | | /// |
485 | | /// \returns A new iterator into the set of known identifiers. The |
486 | | /// caller is responsible for deleting this iterator. |
487 | | virtual IdentifierIterator *getIdentifiers(); |
488 | | }; |
489 | | |
490 | | /// Implements an efficient mapping from strings to IdentifierInfo nodes. |
491 | | /// |
492 | | /// This has no other purpose, but this is an extremely performance-critical |
493 | | /// piece of the code, as each occurrence of every identifier goes through |
494 | | /// here when lexed. |
495 | | class IdentifierTable { |
496 | | // Shark shows that using MallocAllocator is *much* slower than using this |
497 | | // BumpPtrAllocator! |
498 | | using HashTableTy = llvm::StringMap<IdentifierInfo *, llvm::BumpPtrAllocator>; |
499 | | HashTableTy HashTable; |
500 | | |
501 | | IdentifierInfoLookup* ExternalLookup; |
502 | | |
503 | | public: |
504 | | /// Create the identifier table. |
505 | | explicit IdentifierTable(IdentifierInfoLookup *ExternalLookup = nullptr); |
506 | | |
507 | | /// Create the identifier table, populating it with info about the |
508 | | /// language keywords for the language specified by \p LangOpts. |
509 | | explicit IdentifierTable(const LangOptions &LangOpts, |
510 | | IdentifierInfoLookup *ExternalLookup = nullptr); |
511 | | |
512 | | /// Set the external identifier lookup mechanism. |
513 | 22.8k | void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) { |
514 | 22.8k | ExternalLookup = IILookup; |
515 | 22.8k | } |
516 | | |
517 | | /// Retrieve the external identifier lookup object, if any. |
518 | 5.25M | IdentifierInfoLookup *getExternalIdentifierLookup() const { |
519 | 5.25M | return ExternalLookup; |
520 | 5.25M | } |
521 | | |
522 | 382M | llvm::BumpPtrAllocator& getAllocator() { |
523 | 382M | return HashTable.getAllocator(); |
524 | 382M | } |
525 | | |
526 | | /// Return the identifier token info for the specified named |
527 | | /// identifier. |
528 | 833M | IdentifierInfo &get(StringRef Name) { |
529 | 833M | auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first; |
530 | | |
531 | 833M | IdentifierInfo *&II = Entry.second; |
532 | 833M | if (II) return *II467M ; |
533 | | |
534 | | // No entry; if we have an external lookup, look there first. |
535 | 365M | if (ExternalLookup) { |
536 | 3.19M | II = ExternalLookup->get(Name); |
537 | 3.19M | if (II) |
538 | 609k | return *II; |
539 | 364M | } |
540 | | |
541 | | // Lookups failed, make a new IdentifierInfo. |
542 | 364M | void *Mem = getAllocator().Allocate<IdentifierInfo>(); |
543 | 364M | II = new (Mem) IdentifierInfo(); |
544 | | |
545 | | // Make sure getName() knows how to find the IdentifierInfo |
546 | | // contents. |
547 | 364M | II->Entry = &Entry; |
548 | | |
549 | 364M | return *II; |
550 | 364M | } |
551 | | |
552 | 32.2M | IdentifierInfo &get(StringRef Name, tok::TokenKind TokenCode) { |
553 | 32.2M | IdentifierInfo &II = get(Name); |
554 | 32.2M | II.TokenID = TokenCode; |
555 | 32.2M | assert(II.TokenID == (unsigned) TokenCode && "TokenCode too large"); |
556 | 32.2M | return II; |
557 | 32.2M | } |
558 | | |
559 | | /// Gets an IdentifierInfo for the given name without consulting |
560 | | /// external sources. |
561 | | /// |
562 | | /// This is a version of get() meant for external sources that want to |
563 | | /// introduce or modify an identifier. If they called get(), they would |
564 | | /// likely end up in a recursion. |
565 | 19.5M | IdentifierInfo &getOwn(StringRef Name) { |
566 | 19.5M | auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first; |
567 | | |
568 | 19.5M | IdentifierInfo *&II = Entry.second; |
569 | 19.5M | if (II) |
570 | 1.81M | return *II; |
571 | | |
572 | | // Lookups failed, make a new IdentifierInfo. |
573 | 17.7M | void *Mem = getAllocator().Allocate<IdentifierInfo>(); |
574 | 17.7M | II = new (Mem) IdentifierInfo(); |
575 | | |
576 | | // Make sure getName() knows how to find the IdentifierInfo |
577 | | // contents. |
578 | 17.7M | II->Entry = &Entry; |
579 | | |
580 | | // If this is the 'import' contextual keyword, mark it as such. |
581 | 17.7M | if (Name.equals("import")) |
582 | 0 | II->setModulesImport(true); |
583 | | |
584 | 17.7M | return *II; |
585 | 17.7M | } |
586 | | |
587 | | using iterator = HashTableTy::const_iterator; |
588 | | using const_iterator = HashTableTy::const_iterator; |
589 | | |
590 | 25.4k | iterator begin() const { return HashTable.begin(); } |
591 | 25.4k | iterator end() const { return HashTable.end(); } |
592 | 0 | unsigned size() const { return HashTable.size(); } |
593 | | |
594 | 0 | iterator find(StringRef Name) const { return HashTable.find(Name); } |
595 | | |
596 | | /// Print some statistics to stderr that indicate how well the |
597 | | /// hashing is doing. |
598 | | void PrintStats() const; |
599 | | |
600 | | /// Populate the identifier table with info about the language keywords |
601 | | /// for the language specified by \p LangOpts. |
602 | | void AddKeywords(const LangOptions &LangOpts); |
603 | | }; |
604 | | |
605 | | /// A family of Objective-C methods. |
606 | | /// |
607 | | /// These families have no inherent meaning in the language, but are |
608 | | /// nonetheless central enough in the existing implementations to |
609 | | /// merit direct AST support. While, in theory, arbitrary methods can |
610 | | /// be considered to form families, we focus here on the methods |
611 | | /// involving allocation and retain-count management, as these are the |
612 | | /// most "core" and the most likely to be useful to diverse clients |
613 | | /// without extra information. |
614 | | /// |
615 | | /// Both selectors and actual method declarations may be classified |
616 | | /// into families. Method families may impose additional restrictions |
617 | | /// beyond their selector name; for example, a method called '_init' |
618 | | /// that returns void is not considered to be in the 'init' family |
619 | | /// (but would be if it returned 'id'). It is also possible to |
620 | | /// explicitly change or remove a method's family. Therefore the |
621 | | /// method's family should be considered the single source of truth. |
622 | | enum ObjCMethodFamily { |
623 | | /// No particular method family. |
624 | | OMF_None, |
625 | | |
626 | | // Selectors in these families may have arbitrary arity, may be |
627 | | // written with arbitrary leading underscores, and may have |
628 | | // additional CamelCase "words" in their first selector chunk |
629 | | // following the family name. |
630 | | OMF_alloc, |
631 | | OMF_copy, |
632 | | OMF_init, |
633 | | OMF_mutableCopy, |
634 | | OMF_new, |
635 | | |
636 | | // These families are singletons consisting only of the nullary |
637 | | // selector with the given name. |
638 | | OMF_autorelease, |
639 | | OMF_dealloc, |
640 | | OMF_finalize, |
641 | | OMF_release, |
642 | | OMF_retain, |
643 | | OMF_retainCount, |
644 | | OMF_self, |
645 | | OMF_initialize, |
646 | | |
647 | | // performSelector families |
648 | | OMF_performSelector |
649 | | }; |
650 | | |
651 | | /// Enough bits to store any enumerator in ObjCMethodFamily or |
652 | | /// InvalidObjCMethodFamily. |
653 | | enum { ObjCMethodFamilyBitWidth = 4 }; |
654 | | |
655 | | /// An invalid value of ObjCMethodFamily. |
656 | | enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 }; |
657 | | |
658 | | /// A family of Objective-C methods. |
659 | | /// |
660 | | /// These are family of methods whose result type is initially 'id', but |
661 | | /// but are candidate for the result type to be changed to 'instancetype'. |
662 | | enum ObjCInstanceTypeFamily { |
663 | | OIT_None, |
664 | | OIT_Array, |
665 | | OIT_Dictionary, |
666 | | OIT_Singleton, |
667 | | OIT_Init, |
668 | | OIT_ReturnsSelf |
669 | | }; |
670 | | |
671 | | enum ObjCStringFormatFamily { |
672 | | SFF_None, |
673 | | SFF_NSString, |
674 | | SFF_CFString |
675 | | }; |
676 | | |
677 | | /// Smart pointer class that efficiently represents Objective-C method |
678 | | /// names. |
679 | | /// |
680 | | /// This class will either point to an IdentifierInfo or a |
681 | | /// MultiKeywordSelector (which is private). This enables us to optimize |
682 | | /// selectors that take no arguments and selectors that take 1 argument, which |
683 | | /// accounts for 78% of all selectors in Cocoa.h. |
684 | | class Selector { |
685 | | friend class Diagnostic; |
686 | | friend class SelectorTable; // only the SelectorTable can create these |
687 | | friend class DeclarationName; // and the AST's DeclarationName. |
688 | | |
689 | | enum IdentifierInfoFlag { |
690 | | // Empty selector = 0. Note that these enumeration values must |
691 | | // correspond to the enumeration values of DeclarationName::StoredNameKind |
692 | | ZeroArg = 0x01, |
693 | | OneArg = 0x02, |
694 | | MultiArg = 0x07, |
695 | | ArgFlags = 0x07 |
696 | | }; |
697 | | |
698 | | /// A pointer to the MultiKeywordSelector or IdentifierInfo. We use the low |
699 | | /// three bits of InfoPtr to store an IdentifierInfoFlag. Note that in any |
700 | | /// case IdentifierInfo and MultiKeywordSelector are already aligned to |
701 | | /// 8 bytes even on 32 bits archs because of DeclarationName. |
702 | | uintptr_t InfoPtr = 0; |
703 | | |
704 | 1.55M | Selector(IdentifierInfo *II, unsigned nArgs) { |
705 | 1.55M | InfoPtr = reinterpret_cast<uintptr_t>(II); |
706 | 1.55M | assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); |
707 | 1.55M | assert(nArgs < 2 && "nArgs not equal to 0/1"); |
708 | 1.55M | InfoPtr |= nArgs+1; |
709 | 1.55M | } |
710 | | |
711 | 401k | Selector(MultiKeywordSelector *SI) { |
712 | 401k | InfoPtr = reinterpret_cast<uintptr_t>(SI); |
713 | 401k | assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo"); |
714 | 401k | InfoPtr |= MultiArg; |
715 | 401k | } |
716 | | |
717 | 2.03M | IdentifierInfo *getAsIdentifierInfo() const { |
718 | 2.03M | if (getIdentifierInfoFlag() < MultiArg) |
719 | 2.03M | return reinterpret_cast<IdentifierInfo *>(InfoPtr & ~ArgFlags); |
720 | 0 | return nullptr; |
721 | 0 | } |
722 | | |
723 | 2.79M | MultiKeywordSelector *getMultiKeywordSelector() const { |
724 | 2.79M | return reinterpret_cast<MultiKeywordSelector *>(InfoPtr & ~ArgFlags); |
725 | 2.79M | } |
726 | | |
727 | 9.30M | unsigned getIdentifierInfoFlag() const { |
728 | 9.30M | return InfoPtr & ArgFlags; |
729 | 9.30M | } |
730 | | |
731 | | static ObjCMethodFamily getMethodFamilyImpl(Selector sel); |
732 | | |
733 | | static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel); |
734 | | |
735 | | public: |
736 | | /// The default ctor should only be used when creating data structures that |
737 | | /// will contain selectors. |
738 | 5.10M | Selector() = default; |
739 | 43.3M | explicit Selector(uintptr_t V) : InfoPtr(V) {} |
740 | | |
741 | | /// operator==/!= - Indicate whether the specified selectors are identical. |
742 | 107M | bool operator==(Selector RHS) const { |
743 | 107M | return InfoPtr == RHS.InfoPtr; |
744 | 107M | } |
745 | 68.5k | bool operator!=(Selector RHS) const { |
746 | 68.5k | return InfoPtr != RHS.InfoPtr; |
747 | 68.5k | } |
748 | | |
749 | 9.45M | void *getAsOpaquePtr() const { |
750 | 9.45M | return reinterpret_cast<void*>(InfoPtr); |
751 | 9.45M | } |
752 | | |
753 | | /// Determine whether this is the empty selector. |
754 | 66.9k | bool isNull() const { return InfoPtr == 0; } |
755 | | |
756 | | // Predicates to identify the selector type. |
757 | 917 | bool isKeywordSelector() const { |
758 | 917 | return getIdentifierInfoFlag() != ZeroArg; |
759 | 917 | } |
760 | | |
761 | 309k | bool isUnarySelector() const { |
762 | 309k | return getIdentifierInfoFlag() == ZeroArg; |
763 | 309k | } |
764 | | |
765 | | /// If this selector is the specific keyword selector described by Names. |
766 | | bool isKeywordSelector(ArrayRef<StringRef> Names) const; |
767 | | |
768 | | /// If this selector is the specific unary selector described by Name. |
769 | | bool isUnarySelector(StringRef Name) const; |
770 | | |
771 | | unsigned getNumArgs() const; |
772 | | |
773 | | /// Retrieve the identifier at a given position in the selector. |
774 | | /// |
775 | | /// Note that the identifier pointer returned may be NULL. Clients that only |
776 | | /// care about the text of the identifier string, and not the specific, |
777 | | /// uniqued identifier pointer, should use \c getNameForSlot(), which returns |
778 | | /// an empty string when the identifier pointer would be NULL. |
779 | | /// |
780 | | /// \param argIndex The index for which we want to retrieve the identifier. |
781 | | /// This index shall be less than \c getNumArgs() unless this is a keyword |
782 | | /// selector, in which case 0 is the only permissible value. |
783 | | /// |
784 | | /// \returns the uniqued identifier for this slot, or NULL if this slot has |
785 | | /// no corresponding identifier. |
786 | | IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const; |
787 | | |
788 | | /// Retrieve the name at a given position in the selector. |
789 | | /// |
790 | | /// \param argIndex The index for which we want to retrieve the name. |
791 | | /// This index shall be less than \c getNumArgs() unless this is a keyword |
792 | | /// selector, in which case 0 is the only permissible value. |
793 | | /// |
794 | | /// \returns the name for this slot, which may be the empty string if no |
795 | | /// name was supplied. |
796 | | StringRef getNameForSlot(unsigned argIndex) const; |
797 | | |
798 | | /// Derive the full selector name (e.g. "foo:bar:") and return |
799 | | /// it as an std::string. |
800 | | std::string getAsString() const; |
801 | | |
802 | | /// Prints the full selector name (e.g. "foo:bar:"). |
803 | | void print(llvm::raw_ostream &OS) const; |
804 | | |
805 | | void dump() const; |
806 | | |
807 | | /// Derive the conventional family of this method. |
808 | 284k | ObjCMethodFamily getMethodFamily() const { |
809 | 284k | return getMethodFamilyImpl(*this); |
810 | 284k | } |
811 | | |
812 | 25.9k | ObjCStringFormatFamily getStringFormatFamily() const { |
813 | 25.9k | return getStringFormatFamilyImpl(*this); |
814 | 25.9k | } |
815 | | |
816 | 11.5M | static Selector getEmptyMarker() { |
817 | 11.5M | return Selector(uintptr_t(-1)); |
818 | 11.5M | } |
819 | | |
820 | 9.12M | static Selector getTombstoneMarker() { |
821 | 9.12M | return Selector(uintptr_t(-2)); |
822 | 9.12M | } |
823 | | |
824 | | static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel); |
825 | | }; |
826 | | |
827 | | /// This table allows us to fully hide how we implement |
828 | | /// multi-keyword caching. |
829 | | class SelectorTable { |
830 | | // Actually a SelectorTableImpl |
831 | | void *Impl; |
832 | | |
833 | | public: |
834 | | SelectorTable(); |
835 | | SelectorTable(const SelectorTable &) = delete; |
836 | | SelectorTable &operator=(const SelectorTable &) = delete; |
837 | | ~SelectorTable(); |
838 | | |
839 | | /// Can create any sort of selector. |
840 | | /// |
841 | | /// \p NumArgs indicates whether this is a no argument selector "foo", a |
842 | | /// single argument selector "foo:" or multi-argument "foo:bar:". |
843 | | Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV); |
844 | | |
845 | 481k | Selector getUnarySelector(IdentifierInfo *ID) { |
846 | 481k | return Selector(ID, 1); |
847 | 481k | } |
848 | | |
849 | 620k | Selector getNullarySelector(IdentifierInfo *ID) { |
850 | 620k | return Selector(ID, 0); |
851 | 620k | } |
852 | | |
853 | | /// Return the total amount of memory allocated for managing selectors. |
854 | | size_t getTotalMemory() const; |
855 | | |
856 | | /// Return the default setter name for the given identifier. |
857 | | /// |
858 | | /// This is "set" + \p Name where the initial character of \p Name |
859 | | /// has been capitalized. |
860 | | static SmallString<64> constructSetterName(StringRef Name); |
861 | | |
862 | | /// Return the default setter selector for the given identifier. |
863 | | /// |
864 | | /// This is "set" + \p Name where the initial character of \p Name |
865 | | /// has been capitalized. |
866 | | static Selector constructSetterSelector(IdentifierTable &Idents, |
867 | | SelectorTable &SelTable, |
868 | | const IdentifierInfo *Name); |
869 | | |
870 | | /// Return the property name for the given setter selector. |
871 | | static std::string getPropertyNameFromSetterSelector(Selector Sel); |
872 | | }; |
873 | | |
874 | | namespace detail { |
875 | | |
876 | | /// DeclarationNameExtra is used as a base of various uncommon special names. |
877 | | /// This class is needed since DeclarationName has not enough space to store |
878 | | /// the kind of every possible names. Therefore the kind of common names is |
879 | | /// stored directly in DeclarationName, and the kind of uncommon names is |
880 | | /// stored in DeclarationNameExtra. It is aligned to 8 bytes because |
881 | | /// DeclarationName needs the lower 3 bits to store the kind of common names. |
882 | | /// DeclarationNameExtra is tightly coupled to DeclarationName and any change |
883 | | /// here is very likely to require changes in DeclarationName(Table). |
884 | | class alignas(IdentifierInfoAlignment) DeclarationNameExtra { |
885 | | friend class clang::DeclarationName; |
886 | | friend class clang::DeclarationNameTable; |
887 | | |
888 | | protected: |
889 | | /// The kind of "extra" information stored in the DeclarationName. See |
890 | | /// @c ExtraKindOrNumArgs for an explanation of how these enumerator values |
891 | | /// are used. Note that DeclarationName depends on the numerical values |
892 | | /// of the enumerators in this enum. See DeclarationName::StoredNameKind |
893 | | /// for more info. |
894 | | enum ExtraKind { |
895 | | CXXDeductionGuideName, |
896 | | CXXLiteralOperatorName, |
897 | | CXXUsingDirective, |
898 | | ObjCMultiArgSelector |
899 | | }; |
900 | | |
901 | | /// ExtraKindOrNumArgs has one of the following meaning: |
902 | | /// * The kind of an uncommon C++ special name. This DeclarationNameExtra |
903 | | /// is in this case in fact either a CXXDeductionGuideNameExtra or |
904 | | /// a CXXLiteralOperatorIdName. |
905 | | /// |
906 | | /// * It may be also name common to C++ using-directives (CXXUsingDirective), |
907 | | /// |
908 | | /// * Otherwise it is ObjCMultiArgSelector+NumArgs, where NumArgs is |
909 | | /// the number of arguments in the Objective-C selector, in which |
910 | | /// case the DeclarationNameExtra is also a MultiKeywordSelector. |
911 | | unsigned ExtraKindOrNumArgs; |
912 | | |
913 | 30.3k | DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {} |
914 | | DeclarationNameExtra(unsigned NumArgs) |
915 | 316k | : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {} |
916 | | |
917 | | /// Return the corresponding ExtraKind. |
918 | 9.95M | ExtraKind getKind() const { |
919 | 9.95M | return static_cast<ExtraKind>(ExtraKindOrNumArgs > |
920 | 9.95M | (unsigned)ObjCMultiArgSelector |
921 | 9.82M | ? (unsigned)ObjCMultiArgSelector |
922 | 121k | : ExtraKindOrNumArgs); |
923 | 9.95M | } |
924 | | |
925 | | /// Return the number of arguments in an ObjC selector. Only valid when this |
926 | | /// is indeed an ObjCMultiArgSelector. |
927 | 3.60M | unsigned getNumArgs() const { |
928 | 3.60M | assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector && |
929 | 3.60M | "getNumArgs called but this is not an ObjC selector!"); |
930 | 3.60M | return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector; |
931 | 3.60M | } |
932 | | }; |
933 | | |
934 | | } // namespace detail |
935 | | |
936 | | } // namespace clang |
937 | | |
938 | | namespace llvm { |
939 | | |
940 | | /// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and |
941 | | /// DenseSets. |
942 | | template <> |
943 | | struct DenseMapInfo<clang::Selector> { |
944 | 11.5M | static clang::Selector getEmptyKey() { |
945 | 11.5M | return clang::Selector::getEmptyMarker(); |
946 | 11.5M | } |
947 | | |
948 | 9.12M | static clang::Selector getTombstoneKey() { |
949 | 9.12M | return clang::Selector::getTombstoneMarker(); |
950 | 9.12M | } |
951 | | |
952 | | static unsigned getHashValue(clang::Selector S); |
953 | | |
954 | 107M | static bool isEqual(clang::Selector LHS, clang::Selector RHS) { |
955 | 107M | return LHS == RHS; |
956 | 107M | } |
957 | | }; |
958 | | |
959 | | template<> |
960 | | struct PointerLikeTypeTraits<clang::Selector> { |
961 | 192k | static const void *getAsVoidPointer(clang::Selector P) { |
962 | 192k | return P.getAsOpaquePtr(); |
963 | 192k | } |
964 | | |
965 | 0 | static clang::Selector getFromVoidPointer(const void *P) { |
966 | 0 | return clang::Selector(reinterpret_cast<uintptr_t>(P)); |
967 | 0 | } |
968 | | |
969 | | static constexpr int NumLowBitsAvailable = 0; |
970 | | }; |
971 | | |
972 | | // Provide PointerLikeTypeTraits for IdentifierInfo pointers, which |
973 | | // are not guaranteed to be 8-byte aligned. |
974 | | template<> |
975 | | struct PointerLikeTypeTraits<clang::IdentifierInfo*> { |
976 | 2.17k | static void *getAsVoidPointer(clang::IdentifierInfo* P) { |
977 | 2.17k | return P; |
978 | 2.17k | } |
979 | | |
980 | 22 | static clang::IdentifierInfo *getFromVoidPointer(void *P) { |
981 | 22 | return static_cast<clang::IdentifierInfo*>(P); |
982 | 22 | } |
983 | | |
984 | | static constexpr int NumLowBitsAvailable = 1; |
985 | | }; |
986 | | |
987 | | template<> |
988 | | struct PointerLikeTypeTraits<const clang::IdentifierInfo*> { |
989 | 371k | static const void *getAsVoidPointer(const clang::IdentifierInfo* P) { |
990 | 371k | return P; |
991 | 371k | } |
992 | | |
993 | 0 | static const clang::IdentifierInfo *getFromVoidPointer(const void *P) { |
994 | 0 | return static_cast<const clang::IdentifierInfo*>(P); |
995 | 0 | } |
996 | | |
997 | | static constexpr int NumLowBitsAvailable = 1; |
998 | | }; |
999 | | |
1000 | | } // namespace llvm |
1001 | | |
1002 | | #endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H |