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