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
84 enum 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 KEYHLSL = 0x2000000,
111 KEYFIXEDPOINT = 0x4000000,
112 KEYMAX = KEYFIXEDPOINT, // The maximum key
113 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
114 KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
115 ~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
116 };
117
118 /// How a keyword is treated in the selected standard. This enum is ordered
119 /// intentionally so that the value that 'wins' is the most 'permissive'.
120 enum KeywordStatus {
121 KS_Unknown, // Not yet calculated. Used when figuring out the status.
122 KS_Disabled, // Disabled
123 KS_Future, // Is a keyword in future standard
124 KS_Extension, // Is an extension
125 KS_Enabled, // Enabled
126 };
127
128} // namespace
129
130// This works on a single TokenKey flag and checks the LangOpts to get the
131// KeywordStatus based exclusively on this flag, so that it can be merged in
132// getKeywordStatus. Most should be enabled/disabled, but some might imply
133// 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to
134// be disabled, and the calling function makes it 'disabled' if no other flag
135// changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.
136static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
137 TokenKey Flag) {
138 // Flag is a single bit version of TokenKey (that is, not
139 // KEYALL/KEYALLCXX/etc), so we can check with == throughout this function.
140 assert((Flag & ~(Flag - 1)) == Flag && "Multiple bits set?");
141
142 switch (Flag) {
143 case KEYC99:
144 if (LangOpts.C99)
145 return KS_Enabled;
146 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
147 case KEYC23:
148 if (LangOpts.C23)
149 return KS_Enabled;
150 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151 case KEYCXX:
152 return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
153 case KEYCXX11:
154 if (LangOpts.CPlusPlus11)
155 return KS_Enabled;
156 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
157 case KEYCXX20:
158 if (LangOpts.CPlusPlus20)
159 return KS_Enabled;
160 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
161 case KEYGNU:
162 return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
163 case KEYMS:
164 return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
165 case BOOLSUPPORT:
166 if (LangOpts.Bool) return KS_Enabled;
167 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
168 case KEYALTIVEC:
169 return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
170 case KEYBORLAND:
171 return LangOpts.Borland ? KS_Extension : KS_Unknown;
172 case KEYOPENCLC:
173 return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
174 : KS_Unknown;
175 case WCHARSUPPORT:
176 return LangOpts.WChar ? KS_Enabled : KS_Unknown;
177 case HALFSUPPORT:
178 return LangOpts.Half ? KS_Enabled : KS_Unknown;
179 case CHAR8SUPPORT:
180 if (LangOpts.Char8) return KS_Enabled;
181 if (LangOpts.CPlusPlus20) return KS_Unknown;
182 if (LangOpts.CPlusPlus) return KS_Future;
183 return KS_Unknown;
184 case KEYOBJC:
185 // We treat bridge casts as objective-C keywords so we can warn on them
186 // in non-arc mode.
187 return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
188 case KEYZVECTOR:
189 return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
190 case KEYCOROUTINES:
191 return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
192 case KEYMODULES:
193 return KS_Unknown;
194 case KEYOPENCLCXX:
195 return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
196 case KEYMSCOMPAT:
197 return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
198 case KEYSYCL:
199 return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
200 case KEYCUDA:
201 return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
202 case KEYHLSL:
203 return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
204 case KEYNOCXX:
205 // This is enabled in all non-C++ modes, but might be enabled for other
206 // reasons as well.
207 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
208 case KEYNOOPENCL:
209 // The disable behavior for this is handled in getKeywordStatus.
210 return KS_Unknown;
211 case KEYNOMS18:
212 // The disable behavior for this is handled in getKeywordStatus.
213 return KS_Unknown;
214 case KEYFIXEDPOINT:
215 return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
216 default:
217 llvm_unreachable("Unknown KeywordStatus flag");
218 }
219}
220
221/// Translates flags as specified in TokenKinds.def into keyword status
222/// in the given language standard.
223static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
224 unsigned Flags) {
225 // KEYALL means always enabled, so special case this one.
226 if (Flags == KEYALL) return KS_Enabled;
227 // These are tests that need to 'always win', as they are special in that they
228 // disable based on certain conditions.
229 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;
230 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
232 return KS_Disabled;
233
234 KeywordStatus CurStatus = KS_Unknown;
235
236 while (Flags != 0) {
237 unsigned CurFlag = Flags & ~(Flags - 1);
238 Flags = Flags & ~CurFlag;
239 CurStatus = std::max(
240 CurStatus,
241 getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));
242 }
243
244 if (CurStatus == KS_Unknown)
245 return KS_Disabled;
246 return CurStatus;
247}
248
249/// AddKeyword - This method is used to associate a token ID with specific
250/// identifiers because they are language keywords. This causes the lexer to
251/// automatically map matching identifiers to specialized token codes.
252static void AddKeyword(StringRef Keyword,
253 tok::TokenKind TokenCode, unsigned Flags,
254 const LangOptions &LangOpts, IdentifierTable &Table) {
255 KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
256
257 // Don't add this keyword if disabled in this language.
258 if (AddResult == KS_Disabled) return;
259
260 IdentifierInfo &Info =
261 Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
262 Info.setIsExtensionToken(AddResult == KS_Extension);
263 Info.setIsFutureCompatKeyword(AddResult == KS_Future);
264}
265
266/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
267/// representations.
268static void AddCXXOperatorKeyword(StringRef Keyword,
269 tok::TokenKind TokenCode,
270 IdentifierTable &Table) {
271 IdentifierInfo &Info = Table.get(Keyword, TokenCode);
273}
274
275/// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
276/// or "property".
277static void AddObjCKeyword(StringRef Name,
279 IdentifierTable &Table) {
280 Table.get(Name).setObjCKeywordID(ObjCID);
281}
282
283static void AddNotableIdentifier(StringRef Name,
285 IdentifierTable &Table) {
286 // Don't add 'not_notable' identifier.
287 if (BTID != tok::not_notable) {
288 IdentifierInfo &Info = Table.get(Name, tok::identifier);
289 Info.setNotableIdentifierID(BTID);
290 }
291}
292
293/// AddKeywords - Add all keywords to the symbol table.
294///
296 // Add keywords and tokens for the current language.
297#define KEYWORD(NAME, FLAGS) \
298 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
299 FLAGS, LangOpts, *this);
300#define ALIAS(NAME, TOK, FLAGS) \
301 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
302 FLAGS, LangOpts, *this);
303#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
304 if (LangOpts.CXXOperatorNames) \
305 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
306#define OBJC_AT_KEYWORD(NAME) \
307 if (LangOpts.ObjC) \
308 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
309#define NOTABLE_IDENTIFIER(NAME) \
310 AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
311
312#define TESTING_KEYWORD(NAME, FLAGS)
313#include "clang/Basic/TokenKinds.def"
314
315 if (LangOpts.ParseUnknownAnytype)
316 AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
317 LangOpts, *this);
318
319 if (LangOpts.DeclSpecKeyword)
320 AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
321
322 if (LangOpts.IEEE128)
323 AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
324
325 // Add the 'import' contextual keyword.
326 get("import").setModulesImport(true);
327}
328
329/// Checks if the specified token kind represents a keyword in the
330/// specified language.
331/// \returns Status of the keyword in the language.
332static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
333 tok::TokenKind K) {
334 switch (K) {
335#define KEYWORD(NAME, FLAGS) \
336 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
337#include "clang/Basic/TokenKinds.def"
338 default: return KS_Disabled;
339 }
340}
341
342/// Returns true if the identifier represents a keyword in the
343/// specified language.
344bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
345 switch (getTokenKwStatus(LangOpts, getTokenID())) {
346 case KS_Enabled:
347 case KS_Extension:
348 return true;
349 default:
350 return false;
351 }
352}
353
354/// Returns true if the identifier represents a C++ keyword in the
355/// specified language.
357 if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
358 return false;
359 // This is a C++ keyword if this identifier is not a keyword when checked
360 // using LangOptions without C++ support.
361 LangOptions LangOptsNoCPP = LangOpts;
362 LangOptsNoCPP.CPlusPlus = false;
363 LangOptsNoCPP.CPlusPlus11 = false;
364 LangOptsNoCPP.CPlusPlus20 = false;
365 return !isKeyword(LangOptsNoCPP);
366}
367
370 StringRef Name = getName();
371
372 // '_' is a reserved identifier, but its use is so common (e.g. to store
373 // ignored values) that we don't warn on it.
374 if (Name.size() <= 1)
376
377 // [lex.name] p3
378 if (Name[0] == '_') {
379
380 // Each name that begins with an underscore followed by an uppercase letter
381 // or another underscore is reserved.
382 if (Name[1] == '_')
384
385 if ('A' <= Name[1] && Name[1] <= 'Z')
388
389 // This is a bit misleading: it actually means it's only reserved if we're
390 // at global scope because it starts with an underscore.
392 }
393
394 // Each name that contains a double underscore (__) is reserved.
395 if (LangOpts.CPlusPlus && Name.contains("__"))
397
399}
400
403 StringRef Name = getName();
404
405 if (Name[0] != '_')
407
408 if (Name.contains("__"))
410
412}
413
415 StringRef Name = getName();
416 if (Name.size() >= 2 && Name.front() == '_' &&
417 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
418 return Name.ltrim('_');
419 return Name;
420}
421
423 // We use a perfect hash function here involving the length of the keyword,
424 // the first and third character. For preprocessor ID's there are no
425 // collisions (if there were, the switch below would complain about duplicate
426 // case values). Note that this depends on 'if' being null terminated.
427
428#define HASH(LEN, FIRST, THIRD) \
429 (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
430#define CASE(LEN, FIRST, THIRD, NAME) \
431 case HASH(LEN, FIRST, THIRD): \
432 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
433
434 unsigned Len = getLength();
435 if (Len < 2) return tok::pp_not_keyword;
436 const char *Name = getNameStart();
437 switch (HASH(Len, Name[0], Name[2])) {
438 default: return tok::pp_not_keyword;
439 CASE( 2, 'i', '\0', if);
440 CASE( 4, 'e', 'i', elif);
441 CASE( 4, 'e', 's', else);
442 CASE( 4, 'l', 'n', line);
443 CASE( 4, 's', 'c', sccs);
444 CASE( 5, 'e', 'b', embed);
445 CASE( 5, 'e', 'd', endif);
446 CASE( 5, 'e', 'r', error);
447 CASE( 5, 'i', 'e', ident);
448 CASE( 5, 'i', 'd', ifdef);
449 CASE( 5, 'u', 'd', undef);
450
451 CASE( 6, 'a', 's', assert);
452 CASE( 6, 'd', 'f', define);
453 CASE( 6, 'i', 'n', ifndef);
454 CASE( 6, 'i', 'p', import);
455 CASE( 6, 'p', 'a', pragma);
456
457 CASE( 7, 'd', 'f', defined);
458 CASE( 7, 'e', 'i', elifdef);
459 CASE( 7, 'i', 'c', include);
460 CASE( 7, 'w', 'r', warning);
461
462 CASE( 8, 'e', 'i', elifndef);
463 CASE( 8, 'u', 'a', unassert);
464 CASE(12, 'i', 'c', include_next);
465
466 CASE(14, '_', 'p', __public_macro);
467
468 CASE(15, '_', 'p', __private_macro);
469
470 CASE(16, '_', 'i', __include_macros);
471#undef CASE
472#undef HASH
473 }
474}
475
476//===----------------------------------------------------------------------===//
477// Stats Implementation
478//===----------------------------------------------------------------------===//
479
480/// PrintStats - Print statistics about how well the identifier table is doing
481/// at hashing identifiers.
483 unsigned NumBuckets = HashTable.getNumBuckets();
484 unsigned NumIdentifiers = HashTable.getNumItems();
485 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
486 unsigned AverageIdentifierSize = 0;
487 unsigned MaxIdentifierLength = 0;
488
489 // TODO: Figure out maximum times an identifier had to probe for -stats.
490 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
491 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
492 unsigned IdLen = I->getKeyLength();
493 AverageIdentifierSize += IdLen;
494 if (MaxIdentifierLength < IdLen)
495 MaxIdentifierLength = IdLen;
496 }
497
498 fprintf(stderr, "\n*** Identifier Table Stats:\n");
499 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
500 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
501 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
502 NumIdentifiers/(double)NumBuckets);
503 fprintf(stderr, "Ave identifier length: %f\n",
504 (AverageIdentifierSize/(double)NumIdentifiers));
505 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
506
507 // Compute statistics about the memory allocated for identifiers.
508 HashTable.getAllocator().PrintStats();
509}
510
511//===----------------------------------------------------------------------===//
512// SelectorTable Implementation
513//===----------------------------------------------------------------------===//
514
515unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
516 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
517}
518
520 assert(!Names.empty() && "must have >= 1 selector slots");
521 if (getNumArgs() != Names.size())
522 return false;
523 for (unsigned I = 0, E = Names.size(); I != E; ++I) {
524 if (getNameForSlot(I) != Names[I])
525 return false;
526 }
527 return true;
528}
529
530bool Selector::isUnarySelector(StringRef Name) const {
531 return isUnarySelector() && getNameForSlot(0) == Name;
532}
533
534unsigned Selector::getNumArgs() const {
535 unsigned IIF = getIdentifierInfoFlag();
536 if (IIF <= ZeroArg)
537 return 0;
538 if (IIF == OneArg)
539 return 1;
540 // We point to a MultiKeywordSelector.
541 MultiKeywordSelector *SI = getMultiKeywordSelector();
542 return SI->getNumArgs();
543}
544
545const IdentifierInfo *
546Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
547 if (getIdentifierInfoFlag() < MultiArg) {
548 assert(argIndex == 0 && "illegal keyword index");
549 return getAsIdentifierInfo();
550 }
551
552 // We point to a MultiKeywordSelector.
553 MultiKeywordSelector *SI = getMultiKeywordSelector();
554 return SI->getIdentifierInfoForSlot(argIndex);
555}
556
557StringRef Selector::getNameForSlot(unsigned int argIndex) const {
558 const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
559 return II ? II->getName() : StringRef();
560}
561
562std::string MultiKeywordSelector::getName() const {
564 llvm::raw_svector_ostream OS(Str);
565 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
566 if (*I)
567 OS << (*I)->getName();
568 OS << ':';
569 }
570
571 return std::string(OS.str());
572}
573
574std::string Selector::getAsString() const {
575 if (isNull())
576 return "<null selector>";
577
578 if (getIdentifierInfoFlag() < MultiArg) {
579 const IdentifierInfo *II = getAsIdentifierInfo();
580
581 if (getNumArgs() == 0) {
582 assert(II && "If the number of arguments is 0 then II is guaranteed to "
583 "not be null.");
584 return std::string(II->getName());
585 }
586
587 if (!II)
588 return ":";
589
590 return II->getName().str() + ":";
591 }
592
593 // We have a multiple keyword selector.
594 return getMultiKeywordSelector()->getName();
595}
596
597void Selector::print(llvm::raw_ostream &OS) const {
598 OS << getAsString();
599}
600
601LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
602
603/// Interpreting the given string using the normal CamelCase
604/// conventions, determine whether the given string starts with the
605/// given "word", which is assumed to end in a lowercase letter.
606static bool startsWithWord(StringRef name, StringRef word) {
607 if (name.size() < word.size()) return false;
608 return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
609 name.starts_with(word));
610}
611
612ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
613 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
614 if (!first) return OMF_None;
615
616 StringRef name = first->getName();
617 if (sel.isUnarySelector()) {
618 if (name == "autorelease") return OMF_autorelease;
619 if (name == "dealloc") return OMF_dealloc;
620 if (name == "finalize") return OMF_finalize;
621 if (name == "release") return OMF_release;
622 if (name == "retain") return OMF_retain;
623 if (name == "retainCount") return OMF_retainCount;
624 if (name == "self") return OMF_self;
625 if (name == "initialize") return OMF_initialize;
626 }
627
628 if (name == "performSelector" || name == "performSelectorInBackground" ||
629 name == "performSelectorOnMainThread")
630 return OMF_performSelector;
631
632 // The other method families may begin with a prefix of underscores.
633 name = name.ltrim('_');
634
635 if (name.empty()) return OMF_None;
636 switch (name.front()) {
637 case 'a':
638 if (startsWithWord(name, "alloc")) return OMF_alloc;
639 break;
640 case 'c':
641 if (startsWithWord(name, "copy")) return OMF_copy;
642 break;
643 case 'i':
644 if (startsWithWord(name, "init")) return OMF_init;
645 break;
646 case 'm':
647 if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
648 break;
649 case 'n':
650 if (startsWithWord(name, "new")) return OMF_new;
651 break;
652 default:
653 break;
654 }
655
656 return OMF_None;
657}
658
660 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
661 if (!first) return OIT_None;
662
663 StringRef name = first->getName();
664
665 if (name.empty()) return OIT_None;
666 switch (name.front()) {
667 case 'a':
668 if (startsWithWord(name, "array")) return OIT_Array;
669 break;
670 case 'd':
671 if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
672 if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
673 break;
674 case 's':
675 if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
676 if (startsWithWord(name, "standard")) return OIT_Singleton;
677 break;
678 case 'i':
679 if (startsWithWord(name, "init")) return OIT_Init;
680 break;
681 default:
682 break;
683 }
684 return OIT_None;
685}
686
687ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
688 const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
689 if (!first) return SFF_None;
690
691 StringRef name = first->getName();
692
693 switch (name.front()) {
694 case 'a':
695 if (name == "appendFormat") return SFF_NSString;
696 break;
697
698 case 'i':
699 if (name == "initWithFormat") return SFF_NSString;
700 break;
701
702 case 'l':
703 if (name == "localizedStringWithFormat") return SFF_NSString;
704 break;
705
706 case 's':
707 if (name == "stringByAppendingFormat" ||
708 name == "stringWithFormat") return SFF_NSString;
709 break;
710 }
711 return SFF_None;
712}
713
714namespace {
715
716struct SelectorTableImpl {
717 llvm::FoldingSet<MultiKeywordSelector> Table;
718 llvm::BumpPtrAllocator Allocator;
719};
720
721} // namespace
722
723static SelectorTableImpl &getSelectorTableImpl(void *P) {
724 return *static_cast<SelectorTableImpl*>(P);
725}
726
729 SmallString<64> SetterName("set");
730 SetterName += Name;
731 SetterName[3] = toUppercase(SetterName[3]);
732 return SetterName;
733}
734
737 SelectorTable &SelTable,
738 const IdentifierInfo *Name) {
739 IdentifierInfo *SetterName =
740 &Idents.get(constructSetterName(Name->getName()));
741 return SelTable.getUnarySelector(SetterName);
742}
743
745 StringRef Name = Sel.getNameForSlot(0);
746 assert(Name.starts_with("set") && "invalid setter name");
747 return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
748}
749
751 SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
752 return SelTabImpl.Allocator.getTotalMemory();
753}
754
756 const IdentifierInfo **IIV) {
757 if (nKeys < 2)
758 return Selector(IIV[0], nKeys);
759
760 SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
761
762 // Unique selector, to guarantee there is one per name.
763 llvm::FoldingSetNodeID ID;
764 MultiKeywordSelector::Profile(ID, IIV, nKeys);
765
766 void *InsertPos = nullptr;
767 if (MultiKeywordSelector *SI =
768 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
769 return Selector(SI);
770
771 // MultiKeywordSelector objects are not allocated with new because they have a
772 // variable size array (for parameter types) at the end of them.
773 unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
775 (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
776 Size, alignof(MultiKeywordSelector));
777 new (SI) MultiKeywordSelector(nKeys, IIV);
778 SelTabImpl.Table.InsertNode(SI, InsertPos);
779 return Selector(SI);
780}
781
783 Impl = new SelectorTableImpl();
784}
785
787 delete &getSelectorTableImpl(Impl);
788}
789
791 switch (Operator) {
792 case OO_None:
794 return nullptr;
795
796#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
797 case OO_##Name: return Spelling;
798#include "clang/Basic/OperatorKinds.def"
799 }
800
801 llvm_unreachable("Invalid OverloadedOperatorKind!");
802}
803
805 bool isContextSensitive) {
806 switch (kind) {
808 return isContextSensitive ? "nonnull" : "_Nonnull";
809
811 return isContextSensitive ? "nullable" : "_Nullable";
812
814 assert(!isContextSensitive &&
815 "_Nullable_result isn't supported as context-sensitive keyword");
816 return "_Nullable_result";
817
819 return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
820 }
821 llvm_unreachable("Unknown nullability kind.");
822}
823
824llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
825 NullabilityKind NK) {
826 switch (NK) {
828 return OS << "NonNull";
830 return OS << "Nullable";
832 return OS << "NullableResult";
834 return OS << "Unspecified";
835 }
836 llvm_unreachable("Unknown nullability kind.");
837}
838
841 const LangOptions &LangOpts) {
842 assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
843
844 unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
845#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
846#include "clang/Basic/TokenKinds.def"
847#undef KEYWORD
848 ;
849
850 if (LangOpts.CPlusPlus) {
851 if ((Flags & KEYCXX11) == KEYCXX11)
852 return diag::warn_cxx11_keyword;
853
854 // char8_t is not modeled as a CXX20_KEYWORD because it's not
855 // unconditionally enabled in C++20 mode. (It can be disabled
856 // by -fno-char8_t.)
857 if (((Flags & KEYCXX20) == KEYCXX20) ||
858 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
859 return diag::warn_cxx20_keyword;
860 } else {
861 if ((Flags & KEYC99) == KEYC99)
862 return diag::warn_c99_keyword;
863 if ((Flags & KEYC23) == KEYC23)
864 return diag::warn_c23_keyword;
865 }
866
867 llvm_unreachable(
868 "Keyword not known to come from a newer Standard or proposed Standard");
869}
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:461
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
Definition: LangOptions.h:629
bool isSYCL() const
Definition: LangOptions.h:712
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:333
@ 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