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