clang 20.0.0git
IdentifierTable.cpp
Go to the documentation of this file.
1//===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
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 implements the IdentifierInfo, IdentifierVisitor, and
10// IdentifierTable interfaces.
11//
12//===----------------------------------------------------------------------===//
13
22#include "llvm/ADT/DenseMapInfo.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/StringMap.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/Support/Allocator.h"
28#include "llvm/Support/raw_ostream.h"
29#include <cassert>
30#include <cstdio>
31#include <cstring>
32#include <string>
33
34using namespace clang;
35
36// A check to make sure the ObjCOrBuiltinID has sufficient room to store the
37// largest possible target/aux-target combination. If we exceed this, we likely
38// need to just change the ObjCOrBuiltinIDBits value in IdentifierTable.h.
39static_assert(2 * LargestBuiltinID < (2 << (InterestingIdentifierBits - 1)),
40 "Insufficient ObjCOrBuiltinID Bits");
41
42//===----------------------------------------------------------------------===//
43// IdentifierTable Implementation
44//===----------------------------------------------------------------------===//
45
47
49
50namespace {
51
52/// A simple identifier lookup iterator that represents an
53/// empty sequence of identifiers.
54class EmptyLookupIterator : public IdentifierIterator {
55public:
56 StringRef Next() override { return StringRef(); }
57};
58
59} // namespace
60
62 return new EmptyLookupIterator();
63}
64
66 : HashTable(8192), // Start with space for 8K identifiers.
67 ExternalLookup(ExternalLookup) {}
68
70 IdentifierInfoLookup *ExternalLookup)
71 : IdentifierTable(ExternalLookup) {
72 // Populate the identifier table with info about keywords for the current
73 // language.
74 AddKeywords(LangOpts);
75}
76
77//===----------------------------------------------------------------------===//
78// Language Keyword Implementation
79//===----------------------------------------------------------------------===//
80
81// Constants for TokenKinds.def
82namespace {
83
84enum TokenKey : unsigned {
85 KEYC99 = 0x1,
86 KEYCXX = 0x2,
87 KEYCXX11 = 0x4,
88 KEYGNU = 0x8,
89 KEYMS = 0x10,
90 BOOLSUPPORT = 0x20,
91 KEYALTIVEC = 0x40,
92 KEYNOCXX = 0x80,
93 KEYBORLAND = 0x100,
94 KEYOPENCLC = 0x200,
95 KEYC23 = 0x400,
96 KEYNOMS18 = 0x800,
97 KEYNOOPENCL = 0x1000,
98 WCHARSUPPORT = 0x2000,
99 HALFSUPPORT = 0x4000,
100 CHAR8SUPPORT = 0x8000,
101 KEYOBJC = 0x10000,
102 KEYZVECTOR = 0x20000,
103 KEYCOROUTINES = 0x40000,
104 KEYMODULES = 0x80000,
105 KEYCXX20 = 0x100000,
106 KEYOPENCLCXX = 0x200000,
107 KEYMSCOMPAT = 0x400000,
108 KEYSYCL = 0x800000,
109 KEYCUDA = 0x1000000,
110 KEYZOS = 0x2000000,
111 KEYNOZOS = 0x4000000,
112 KEYHLSL = 0x8000000,
113 KEYFIXEDPOINT = 0x10000000,
114 KEYMAX = KEYFIXEDPOINT, // The maximum key
115 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
116 KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
117 ~KEYNOZOS // KEYNOMS18, KEYNOOPENCL, KEYNOZOS are excluded.
118};
119
120/// How a keyword is treated in the selected standard. This enum is ordered
121/// intentionally so that the value that 'wins' is the most 'permissive'.
122enum KeywordStatus {
123 KS_Unknown, // Not yet calculated. Used when figuring out the status.
124 KS_Disabled, // Disabled
125 KS_Future, // Is a keyword in future standard
126 KS_Extension, // Is an extension
127 KS_Enabled, // Enabled
128};
129
130} // namespace
131
132// This works on a single TokenKey flag and checks the LangOpts to get the
133// KeywordStatus based exclusively on this flag, so that it can be merged in
134// getKeywordStatus. Most should be enabled/disabled, but some might imply
135// 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to
136// be disabled, and the calling function makes it 'disabled' if no other flag
137// changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.
138static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
139 TokenKey Flag) {
140 // Flag is a single bit version of TokenKey (that is, not
141 // KEYALL/KEYALLCXX/etc), so we can check with == throughout this function.
142 assert((Flag & ~(Flag - 1)) == Flag && "Multiple bits set?");
143
144 switch (Flag) {
145 case KEYC99:
146 if (LangOpts.C99)
147 return KS_Enabled;
148 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
149 case KEYC23:
150 if (LangOpts.C23)
151 return KS_Enabled;
152 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
153 case KEYCXX:
154 return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
155 case KEYCXX11:
156 if (LangOpts.CPlusPlus11)
157 return KS_Enabled;
158 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
159 case KEYCXX20:
160 if (LangOpts.CPlusPlus20)
161 return KS_Enabled;
162 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
163 case KEYGNU:
164 return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
165 case KEYMS:
166 return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
167 case BOOLSUPPORT:
168 if (LangOpts.Bool) return KS_Enabled;
169 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
170 case KEYALTIVEC:
171 return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
172 case KEYBORLAND:
173 return LangOpts.Borland ? KS_Extension : KS_Unknown;
174 case KEYOPENCLC:
175 return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
176 : KS_Unknown;
177 case WCHARSUPPORT:
178 return LangOpts.WChar ? KS_Enabled : KS_Unknown;
179 case HALFSUPPORT:
180 return LangOpts.Half ? KS_Enabled : KS_Unknown;
181 case CHAR8SUPPORT:
182 if (LangOpts.Char8) return KS_Enabled;
183 if (LangOpts.CPlusPlus20) return KS_Unknown;
184 if (LangOpts.CPlusPlus) return KS_Future;
185 return KS_Unknown;
186 case KEYOBJC:
187 // We treat bridge casts as objective-C keywords so we can warn on them
188 // in non-arc mode.
189 return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
190 case KEYZVECTOR:
191 return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
192 case KEYCOROUTINES:
193 return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
194 case KEYMODULES:
195 return KS_Unknown;
196 case KEYOPENCLCXX:
197 return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
198 case KEYMSCOMPAT:
199 return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
200 case KEYSYCL:
201 return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
202 case KEYCUDA:
203 return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
204 case KEYZOS:
205 return LangOpts.ZOSExt ? KS_Enabled : KS_Unknown;
206 case KEYHLSL:
207 return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
208 case KEYNOCXX:
209 // This is enabled in all non-C++ modes, but might be enabled for other
210 // reasons as well.
211 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
212 case KEYNOOPENCL:
213 case KEYNOMS18:
214 case KEYNOZOS:
215 // The disable behavior for this is handled in getKeywordStatus.
216 return KS_Unknown;
217 case KEYFIXEDPOINT:
218 return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
219 default:
220 llvm_unreachable("Unknown KeywordStatus flag");
221 }
222}
223
224/// Translates flags as specified in TokenKinds.def into keyword status
225/// in the given language standard.
226static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
227 unsigned Flags) {
228 // KEYALL means always enabled, so special case this one.
229 if (Flags == KEYALL) return KS_Enabled;
230 // These are tests that need to 'always win', as they are special in that they
231 // disable based on certain conditions.
232 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;
233 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
235 return KS_Disabled;
236 if (LangOpts.ZOSExt && (Flags & KEYNOZOS))
237 return KS_Disabled;
238 KeywordStatus CurStatus = KS_Unknown;
239
240 while (Flags != 0) {
241 unsigned CurFlag = Flags & ~(Flags - 1);
242 Flags = Flags & ~CurFlag;
243 CurStatus = std::max(
244 CurStatus,
245 getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));
246 }
247
248 if (CurStatus == KS_Unknown)
249 return KS_Disabled;
250 return CurStatus;
251}
252
253/// AddKeyword - This method is used to associate a token ID with specific
254/// identifiers because they are language keywords. This causes the lexer to
255/// automatically map matching identifiers to specialized token codes.
256static void AddKeyword(StringRef Keyword,
257 tok::TokenKind TokenCode, unsigned Flags,
258 const LangOptions &LangOpts, IdentifierTable &Table) {
259 KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
260
261 // Don't add this keyword if disabled in this language.
262 if (AddResult == KS_Disabled) return;
263
264 IdentifierInfo &Info =
265 Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
266 Info.setIsExtensionToken(AddResult == KS_Extension);
267 Info.setIsFutureCompatKeyword(AddResult == KS_Future);
268}
269
270/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
271/// representations.
272static void AddCXXOperatorKeyword(StringRef Keyword,
273 tok::TokenKind TokenCode,
274 IdentifierTable &Table) {
275 IdentifierInfo &Info = Table.get(Keyword, TokenCode);
277}
278
279/// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
280/// or "property".
281static void AddObjCKeyword(StringRef Name,
283 IdentifierTable &Table) {
284 Table.get(Name).setObjCKeywordID(ObjCID);
285}
286
287static void AddNotableIdentifier(StringRef Name,
289 IdentifierTable &Table) {
290 // Don't add 'not_notable' identifier.
291 if (BTID != tok::not_notable) {
292 IdentifierInfo &Info = Table.get(Name, tok::identifier);
293 Info.setNotableIdentifierID(BTID);
294 }
295}
296
297/// AddKeywords - Add all keywords to the symbol table.
298///
300 // Add keywords and tokens for the current language.
301#define KEYWORD(NAME, FLAGS) \
302 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
303 FLAGS, LangOpts, *this);
304#define ALIAS(NAME, TOK, FLAGS) \
305 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
306 FLAGS, LangOpts, *this);
307#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
308 if (LangOpts.CXXOperatorNames) \
309 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
310#define OBJC_AT_KEYWORD(NAME) \
311 if (LangOpts.ObjC) \
312 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
313#define NOTABLE_IDENTIFIER(NAME) \
314 AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
315
316#define TESTING_KEYWORD(NAME, FLAGS)
317#include "clang/Basic/TokenKinds.def"
318
319 if (LangOpts.ParseUnknownAnytype)
320 AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
321 LangOpts, *this);
322
323 if (LangOpts.DeclSpecKeyword)
324 AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
325
326 if (LangOpts.IEEE128)
327 AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
328
329 // Add the 'import' contextual keyword.
330 get("import").setModulesImport(true);
331}
332
333/// Checks if the specified token kind represents a keyword in the
334/// specified language.
335/// \returns Status of the keyword in the language.
336static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
337 tok::TokenKind K) {
338 switch (K) {
339#define KEYWORD(NAME, FLAGS) \
340 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
341#include "clang/Basic/TokenKinds.def"
342 default: return KS_Disabled;
343 }
344}
345
346/// Returns true if the identifier represents a keyword in the
347/// specified language.
348bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
349 switch (getTokenKwStatus(LangOpts, getTokenID())) {
350 case KS_Enabled:
351 case KS_Extension:
352 return true;
353 default:
354 return false;
355 }
356}
357
358/// Returns true if the identifier represents a C++ keyword in the
359/// specified language.
361 if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
362 return false;
363 // This is a C++ keyword if this identifier is not a keyword when checked
364 // using LangOptions without C++ support.
365 LangOptions LangOptsNoCPP = LangOpts;
366 LangOptsNoCPP.CPlusPlus = false;
367 LangOptsNoCPP.CPlusPlus11 = false;
368 LangOptsNoCPP.CPlusPlus20 = false;
369 return !isKeyword(LangOptsNoCPP);
370}
371
374 StringRef Name = getName();
375
376 // '_' is a reserved identifier, but its use is so common (e.g. to store
377 // ignored values) that we don't warn on it.
378 if (Name.size() <= 1)
380
381 // [lex.name] p3
382 if (Name[0] == '_') {
383
384 // Each name that begins with an underscore followed by an uppercase letter
385 // or another underscore is reserved.
386 if (Name[1] == '_')
388
389 if ('A' <= Name[1] && Name[1] <= 'Z')
392
393 // This is a bit misleading: it actually means it's only reserved if we're
394 // at global scope because it starts with an underscore.
396 }
397
398 // Each name that contains a double underscore (__) is reserved.
399 if (LangOpts.CPlusPlus && Name.contains("__"))
401
403}
404
407 StringRef Name = getName();
408
409 if (Name[0] != '_')
411
412 if (Name.contains("__"))
414
416}
417
419 StringRef Name = getName();
420 if (Name.size() >= 2 && Name.front() == '_' &&
421 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
422 return Name.ltrim('_');
423 return Name;
424}
425
427 // We use a perfect hash function here involving the length of the keyword,
428 // the first and third character. For preprocessor ID's there are no
429 // collisions (if there were, the switch below would complain about duplicate
430 // case values). Note that this depends on 'if' being null terminated.
431
432#define HASH(LEN, FIRST, THIRD) \
433 (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
434#define CASE(LEN, FIRST, THIRD, NAME) \
435 case HASH(LEN, FIRST, THIRD): \
436 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
437
438 unsigned Len = getLength();
439 if (Len < 2) return tok::pp_not_keyword;
440 const char *Name = getNameStart();
441 switch (HASH(Len, Name[0], Name[2])) {
442 default: return tok::pp_not_keyword;
443 CASE( 2, 'i', '\0', if);
444 CASE( 4, 'e', 'i', elif);
445 CASE( 4, 'e', 's', else);
446 CASE( 4, 'l', 'n', line);
447 CASE( 4, 's', 'c', sccs);
448 CASE( 5, 'e', 'b', embed);
449 CASE( 5, 'e', 'd', endif);
450 CASE( 5, 'e', 'r', error);
451 CASE( 5, 'i', 'e', ident);
452 CASE( 5, 'i', 'd', ifdef);
453 CASE( 5, 'u', 'd', undef);
454
455 CASE( 6, 'a', 's', assert);
456 CASE( 6, 'd', 'f', define);
457 CASE( 6, 'i', 'n', ifndef);
458 CASE( 6, 'i', 'p', import);
459 CASE( 6, 'p', 'a', pragma);
460
461 CASE( 7, 'd', 'f', defined);
462 CASE( 7, 'e', 'i', elifdef);
463 CASE( 7, 'i', 'c', include);
464 CASE( 7, 'w', 'r', warning);
465
466 CASE( 8, 'e', 'i', elifndef);
467 CASE( 8, 'u', 'a', unassert);
468 CASE(12, 'i', 'c', include_next);
469
470 CASE(14, '_', 'p', __public_macro);
471
472 CASE(15, '_', 'p', __private_macro);
473
474 CASE(16, '_', 'i', __include_macros);
475#undef CASE
476#undef HASH
477 }
478}
479
480//===----------------------------------------------------------------------===//
481// Stats Implementation
482//===----------------------------------------------------------------------===//
483
484/// PrintStats - Print statistics about how well the identifier table is doing
485/// at hashing identifiers.
487 unsigned NumBuckets = HashTable.getNumBuckets();
488 unsigned NumIdentifiers = HashTable.getNumItems();
489 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
490 unsigned AverageIdentifierSize = 0;
491 unsigned MaxIdentifierLength = 0;
492
493 // TODO: Figure out maximum times an identifier had to probe for -stats.
494 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
495 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
496 unsigned IdLen = I->getKeyLength();
497 AverageIdentifierSize += IdLen;
498 if (MaxIdentifierLength < IdLen)
499 MaxIdentifierLength = IdLen;
500 }
501
502 fprintf(stderr, "\n*** Identifier Table Stats:\n");
503 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
504 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
505 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
506 NumIdentifiers/(double)NumBuckets);
507 fprintf(stderr, "Ave identifier length: %f\n",
508 (AverageIdentifierSize/(double)NumIdentifiers));
509 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
510
511 // Compute statistics about the memory allocated for identifiers.
512 HashTable.getAllocator().PrintStats();
513}
514
515//===----------------------------------------------------------------------===//
516// SelectorTable Implementation
517//===----------------------------------------------------------------------===//
518
519unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
520 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
521}
522
524 assert(!Names.empty() && "must have >= 1 selector slots");
525 if (getNumArgs() != Names.size())
526 return false;
527 for (unsigned I = 0, E = Names.size(); I != E; ++I) {
528 if (getNameForSlot(I) != Names[I])
529 return false;
530 }
531 return true;
532}
533
534bool Selector::isUnarySelector(StringRef Name) const {
535 return isUnarySelector() && getNameForSlot(0) == Name;
536}
537
538unsigned Selector::getNumArgs() const {
539 unsigned IIF = getIdentifierInfoFlag();
540 if (IIF <= ZeroArg)
541 return 0;
542 if (IIF == OneArg)
543 return 1;
544 // We point to a MultiKeywordSelector.
545 MultiKeywordSelector *SI = getMultiKeywordSelector();
546 return SI->getNumArgs();
547}
548
549const IdentifierInfo *
550Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
551 if (getIdentifierInfoFlag() < MultiArg) {
552 assert(argIndex == 0 && "illegal keyword index");
553 return getAsIdentifierInfo();
554 }
555
556 // We point to a MultiKeywordSelector.
557 MultiKeywordSelector *SI = getMultiKeywordSelector();
558 return SI->getIdentifierInfoForSlot(argIndex);
559}
560
561StringRef Selector::getNameForSlot(unsigned int argIndex) const {
562 const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
563 return II ? II->getName() : StringRef();
564}
565
566std::string MultiKeywordSelector::getName() const {
568 llvm::raw_svector_ostream OS(Str);
569 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
570 if (*I)
571 OS << (*I)->getName();
572 OS << ':';
573 }
574
575 return std::string(OS.str());
576}
577
578std::string Selector::getAsString() const {
579 if (isNull())
580 return "<null selector>";
581
582 if (getIdentifierInfoFlag() < MultiArg) {
583 const IdentifierInfo *II = getAsIdentifierInfo();
584
585 if (getNumArgs() == 0) {
586 assert(II && "If the number of arguments is 0 then II is guaranteed to "
587 "not be null.");
588 return std::string(II->getName());
589 }
590
591 if (!II)
592 return ":";
593
594 return II->getName().str() + ":";
595 }
596
597 // We have a multiple keyword selector.
598 return getMultiKeywordSelector()->getName();
599}
600
601void Selector::print(llvm::raw_ostream &OS) const {
602 OS << getAsString();
603}
604
605LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
606
607/// Interpreting the given string using the normal CamelCase
608/// conventions, determine whether the given string starts with the
609/// given "word", which is assumed to end in a lowercase letter.
610static bool startsWithWord(StringRef name, StringRef word) {
611 if (name.size() < word.size()) return false;
612 return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
613 name.starts_with(word));
614}
615
616ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
617 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
618 if (!first) return OMF_None;
619
620 StringRef name = first->getName();
621 if (sel.isUnarySelector()) {
622 if (name == "autorelease") return OMF_autorelease;
623 if (name == "dealloc") return OMF_dealloc;
624 if (name == "finalize") return OMF_finalize;
625 if (name == "release") return OMF_release;
626 if (name == "retain") return OMF_retain;
627 if (name == "retainCount") return OMF_retainCount;
628 if (name == "self") return OMF_self;
629 if (name == "initialize") return OMF_initialize;
630 }
631
632 if (name == "performSelector" || name == "performSelectorInBackground" ||
633 name == "performSelectorOnMainThread")
634 return OMF_performSelector;
635
636 // The other method families may begin with a prefix of underscores.
637 name = name.ltrim('_');
638
639 if (name.empty()) return OMF_None;
640 switch (name.front()) {
641 case 'a':
642 if (startsWithWord(name, "alloc")) return OMF_alloc;
643 break;
644 case 'c':
645 if (startsWithWord(name, "copy")) return OMF_copy;
646 break;
647 case 'i':
648 if (startsWithWord(name, "init")) return OMF_init;
649 break;
650 case 'm':
651 if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
652 break;
653 case 'n':
654 if (startsWithWord(name, "new")) return OMF_new;
655 break;
656 default:
657 break;
658 }
659
660 return OMF_None;
661}
662
664 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
665 if (!first) return OIT_None;
666
667 StringRef name = first->getName();
668
669 if (name.empty()) return OIT_None;
670 switch (name.front()) {
671 case 'a':
672 if (startsWithWord(name, "array")) return OIT_Array;
673 break;
674 case 'd':
675 if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
676 if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
677 break;
678 case 's':
679 if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
680 if (startsWithWord(name, "standard")) return OIT_Singleton;
681 break;
682 case 'i':
683 if (startsWithWord(name, "init")) return OIT_Init;
684 break;
685 default:
686 break;
687 }
688 return OIT_None;
689}
690
691ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
692 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
693 if (!first) return SFF_None;
694
695 StringRef name = first->getName();
696
697 switch (name.front()) {
698 case 'a':
699 if (name == "appendFormat") return SFF_NSString;
700 break;
701
702 case 'i':
703 if (name == "initWithFormat") return SFF_NSString;
704 break;
705
706 case 'l':
707 if (name == "localizedStringWithFormat") return SFF_NSString;
708 break;
709
710 case 's':
711 if (name == "stringByAppendingFormat" ||
712 name == "stringWithFormat") return SFF_NSString;
713 break;
714 }
715 return SFF_None;
716}
717
718namespace {
719
720struct SelectorTableImpl {
721 llvm::FoldingSet<MultiKeywordSelector> Table;
722 llvm::BumpPtrAllocator Allocator;
723};
724
725} // namespace
726
727static SelectorTableImpl &getSelectorTableImpl(void *P) {
728 return *static_cast<SelectorTableImpl*>(P);
729}
730
733 SmallString<64> SetterName("set");
734 SetterName += Name;
735 SetterName[3] = toUppercase(SetterName[3]);
736 return SetterName;
737}
738
741 SelectorTable &SelTable,
742 const IdentifierInfo *Name) {
743 IdentifierInfo *SetterName =
744 &Idents.get(constructSetterName(Name->getName()));
745 return SelTable.getUnarySelector(SetterName);
746}
747
749 StringRef Name = Sel.getNameForSlot(0);
750 assert(Name.starts_with("set") && "invalid setter name");
751 return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
752}
753
755 SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
756 return SelTabImpl.Allocator.getTotalMemory();
757}
758
760 const IdentifierInfo **IIV) {
761 if (nKeys < 2)
762 return Selector(IIV[0], nKeys);
763
764 SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
765
766 // Unique selector, to guarantee there is one per name.
767 llvm::FoldingSetNodeID ID;
768 MultiKeywordSelector::Profile(ID, IIV, nKeys);
769
770 void *InsertPos = nullptr;
771 if (MultiKeywordSelector *SI =
772 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
773 return Selector(SI);
774
775 // MultiKeywordSelector objects are not allocated with new because they have a
776 // variable size array (for parameter types) at the end of them.
777 unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
779 (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
780 Size, alignof(MultiKeywordSelector));
781 new (SI) MultiKeywordSelector(nKeys, IIV);
782 SelTabImpl.Table.InsertNode(SI, InsertPos);
783 return Selector(SI);
784}
785
787 Impl = new SelectorTableImpl();
788}
789
791 delete &getSelectorTableImpl(Impl);
792}
793
795 switch (Operator) {
796 case OO_None:
798 return nullptr;
799
800#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
801 case OO_##Name: return Spelling;
802#include "clang/Basic/OperatorKinds.def"
803 }
804
805 llvm_unreachable("Invalid OverloadedOperatorKind!");
806}
807
809 bool isContextSensitive) {
810 switch (kind) {
812 return isContextSensitive ? "nonnull" : "_Nonnull";
813
815 return isContextSensitive ? "nullable" : "_Nullable";
816
818 assert(!isContextSensitive &&
819 "_Nullable_result isn't supported as context-sensitive keyword");
820 return "_Nullable_result";
821
823 return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
824 }
825 llvm_unreachable("Unknown nullability kind.");
826}
827
828llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
829 NullabilityKind NK) {
830 switch (NK) {
832 return OS << "NonNull";
834 return OS << "Nullable";
836 return OS << "NullableResult";
838 return OS << "Unspecified";
839 }
840 llvm_unreachable("Unknown nullability kind.");
841}
842
845 const LangOptions &LangOpts) {
846 assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
847
848 unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
849#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
850#include "clang/Basic/TokenKinds.def"
851#undef KEYWORD
852 ;
853
854 if (LangOpts.CPlusPlus) {
855 if ((Flags & KEYCXX11) == KEYCXX11)
856 return diag::warn_cxx11_keyword;
857
858 // char8_t is not modeled as a CXX20_KEYWORD because it's not
859 // unconditionally enabled in C++20 mode. (It can be disabled
860 // by -fno-char8_t.)
861 if (((Flags & KEYCXX20) == KEYCXX20) ||
862 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
863 return diag::warn_cxx20_keyword;
864 } else {
865 if ((Flags & KEYC99) == KEYC99)
866 return diag::warn_c99_keyword;
867 if ((Flags & KEYC23) == KEYC23)
868 return diag::warn_c23_keyword;
869 }
870
871 llvm_unreachable(
872 "Keyword not known to come from a newer Standard or proposed Standard");
873}
StringRef P
Expr * E
static void AddObjCKeyword(StringRef Name, tok::ObjCKeywordKind ObjCID, IdentifierTable &Table)
AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or "property".
static void AddCXXOperatorKeyword(StringRef Keyword, tok::TokenKind TokenCode, IdentifierTable &Table)
AddCXXOperatorKeyword - Register a C++ operator keyword alternative representations.
static void AddNotableIdentifier(StringRef Name, tok::NotableIdentifierKind BTID, IdentifierTable &Table)
static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts, TokenKey Flag)
static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts, tok::TokenKind K)
Checks if the specified token kind represents a keyword in the specified language.
static bool startsWithWord(StringRef name, StringRef word)
Interpreting the given string using the normal CamelCase conventions, determine whether the given str...
#define CASE(LEN, FIRST, THIRD, NAME)
static void AddKeyword(StringRef Keyword, tok::TokenKind TokenCode, unsigned Flags, const LangOptions &LangOpts, IdentifierTable &Table)
AddKeyword - This method is used to associate a token ID with specific identifiers because they are l...
static SelectorTableImpl & getSelectorTableImpl(void *P)
static KeywordStatus getKeywordStatus(const LangOptions &LangOpts, unsigned Flags)
Translates flags as specified in TokenKinds.def into keyword status in the given language standard.
#define HASH(LEN, FIRST, THIRD)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines an enumeration for C++ overloaded operators.
Defines various enumerations that describe declaration and type specifiers.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Defines the clang::TokenKind enum and support functions.
Provides lookups to, and iteration over, IdentiferInfo objects.
virtual IdentifierIterator * getIdentifiers()
Retrieve an iterator into the set of all identifiers known to this identifier lookup source.
One of these records is kept for each identifier that is lexed.
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const
Return true if this token is a C++ keyword in the specified language.
unsigned getLength() const
Efficiently return the length of this identifier info.
void setModulesImport(bool I)
Set whether this identifier is the contextual keyword import.
void setNotableIdentifierID(unsigned ID)
void setIsExtensionToken(bool Val)
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
void setObjCKeywordID(tok::ObjCKeywordKind ID)
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const
Determine whether this is a name reserved for the implementation (C99 7.1.3, C++ [lib....
void setIsCPlusPlusOperatorKeyword(bool Val=true)
isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether this identifier is a C++ al...
ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const
Determine whether this is a name reserved for future standardization or the implementation (C++ [usrl...
void setIsFutureCompatKeyword(bool Val)
StringRef deuglifiedName() const
If the identifier is an "uglified" reserved name, return a cleaned form.
StringRef getName() const
Return the actual identifier string.
bool isFutureCompatKeyword() const
is/setIsFutureCompatKeyword - Initialize information about whether or not this language token is a ke...
An iterator that walks over all of the known identifiers in the lookup table.
virtual StringRef Next()=0
Retrieve the next string in the identifier table and advances the iterator for the following string.
Implements an efficient mapping from strings to IdentifierInfo nodes.
IdentifierTable(IdentifierInfoLookup *ExternalLookup=nullptr)
Create the identifier table.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
void PrintStats() const
Print some statistics to stderr that indicate how well the hashing is doing.
void AddKeywords(const LangOptions &LangOpts)
Populate the identifier table with info about the language keywords for the language specified by Lan...
diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, const LangOptions &LangOpts)
Returns the correct diagnostic to issue for a future-compat diagnostic warning.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Definition: LangOptions.h:476
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
Definition: LangOptions.h:649
bool isSYCL() const
Definition: LangOptions.h:740
One of these variable length records is kept for each selector containing more than one keyword.
keyword_iterator keyword_end() const
const IdentifierInfo *const * keyword_iterator
static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs)
keyword_iterator keyword_begin() const
const IdentifierInfo * getIdentifierInfoForSlot(unsigned i) const
This table allows us to fully hide how we implement multi-keyword caching.
static std::string getPropertyNameFromSetterSelector(Selector Sel)
Return the property name for the given setter selector.
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
size_t getTotalMemory() const
Return the total amount of memory allocated for managing selectors.
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
Selector getUnarySelector(const IdentifierInfo *ID)
static SmallString< 64 > constructSetterName(StringRef Name)
Return the default setter name for the given identifier.
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
std::string getAsString() const
Derive the full selector name (e.g.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
bool isKeywordSelector() const
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
bool isUnarySelector() const
bool isNull() const
Determine whether this is the empty selector.
unsigned getNumArgs() const
unsigned getNumArgs() const
Return the number of arguments in an ObjC selector.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
Definition: DiagnosticIDs.h:68
NotableIdentifierKind
Provides a namespace for notable identifers such as float_t and double_t.
Definition: TokenKinds.h:49
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
Definition: TokenKinds.h:41
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
Definition: TokenKinds.h:25
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
Definition: TokenKinds.h:33
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr, CxxCtorInitializer, and TypeLoc) selects th...
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
Definition: OperatorKinds.h:21
@ OO_None
Not an overloaded operator.
Definition: OperatorKinds.h:22
@ NUM_OVERLOADED_OPERATORS
Definition: OperatorKinds.h:26
ObjCStringFormatFamily
NullabilityKind
Describes the nullability of a particular type.
Definition: Specifiers.h:336
@ Nullable
Values of this type can be null.
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
@ NonNull
Values of this type can never be null.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
Definition: CharInfo.h:224
ObjCMethodFamily
A family of Objective-C methods.
@ OMF_initialize
@ OMF_autorelease
@ OMF_mutableCopy
@ OMF_performSelector
@ OMF_None
No particular method family.
@ OMF_retainCount
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
ObjCInstanceTypeFamily
A family of Objective-C methods.
@ OIT_Dictionary
@ OIT_ReturnsSelf
ReservedLiteralSuffixIdStatus
LLVM_READONLY bool isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
Definition: CharInfo.h:120
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.
Definition: CharInfo.h:233
static constexpr int InterestingIdentifierBits
static constexpr uint64_t LargestBuiltinID
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
ReservedIdentifierStatus