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