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