brintos

brintos / llvm-project-archived public Read only

0
0
Text · 28.3 KiB · d1c959b Raw
847 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the IdentifierInfo, IdentifierVisitor, and10// IdentifierTable interfaces.11//12//===----------------------------------------------------------------------===//13 14#include "clang/Basic/IdentifierTable.h"15#include "clang/Basic/CharInfo.h"16#include "clang/Basic/DiagnosticLex.h"17#include "clang/Basic/LangOptions.h"18#include "clang/Basic/OperatorKinds.h"19#include "clang/Basic/Specifiers.h"20#include "clang/Basic/TargetBuiltins.h"21#include "clang/Basic/TokenKinds.h"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 the36// largest possible target/aux-target combination. If we exceed this, we likely37// 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 Implementation43//===----------------------------------------------------------------------===//44 45IdentifierIterator::~IdentifierIterator() = default;46 47IdentifierInfoLookup::~IdentifierInfoLookup() = default;48 49namespace {50 51/// A simple identifier lookup iterator that represents an52/// empty sequence of identifiers.53class EmptyLookupIterator : public IdentifierIterator {54public:55  StringRef Next() override { return StringRef(); }56};57 58} // namespace59 60IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {61  return new EmptyLookupIterator();62}63 64IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)65    : HashTable(8192), // Start with space for 8K identifiers.66      ExternalLookup(ExternalLookup) {}67 68IdentifierTable::IdentifierTable(const LangOptions &LangOpts,69                                 IdentifierInfoLookup *ExternalLookup)70    : IdentifierTable(ExternalLookup) {71  // Populate the identifier table with info about keywords for the current72  // language.73  AddKeywords(LangOpts);74}75 76//===----------------------------------------------------------------------===//77// Language Keyword Implementation78//===----------------------------------------------------------------------===//79 80// This works on a single TokenKey flag and checks the LangOpts to get the81// KeywordStatus based exclusively on this flag, so that it can be merged in82// getKeywordStatus. Most should be enabled/disabled, but some might imply83// 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to84// be disabled, and the calling function makes it 'disabled' if no other flag85// changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.86static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,87                                            TokenKey Flag) {88  // Flag is a single bit version of TokenKey (that is, not89  // 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_Enabled124                                                        : 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 them136    // 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 other158    // 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  default:168    llvm_unreachable("Unknown KeywordStatus flag");169  }170}171 172KeywordStatus clang::getKeywordStatus(const LangOptions &LangOpts,173                                      unsigned Flags) {174  // KEYALL means always enabled, so special case this one.175  if (Flags == KEYALL) return KS_Enabled;176  // These are tests that need to 'always win', as they are special in that they177  // disable based on certain conditions.178  if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;179  if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&180      !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))181    return KS_Disabled;182  if (LangOpts.ZOSExt && (Flags & KEYNOZOS))183    return KS_Disabled;184  KeywordStatus CurStatus = KS_Unknown;185 186  while (Flags != 0) {187    unsigned CurFlag = Flags & ~(Flags - 1);188    Flags = Flags & ~CurFlag;189    CurStatus = std::max(190        CurStatus,191        getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));192  }193 194  if (CurStatus == KS_Unknown)195    return KS_Disabled;196  return CurStatus;197}198 199static bool IsKeywordInCpp(unsigned Flags) {200  return (Flags & (KEYCXX | KEYCXX11 | KEYCXX20 | BOOLSUPPORT | WCHARSUPPORT |201                   CHAR8SUPPORT)) != 0;202}203 204static void MarkIdentifierAsKeywordInCpp(IdentifierTable &Table,205                                         StringRef Name) {206  IdentifierInfo &II = Table.get(Name, tok::identifier);207  II.setIsKeywordInCPlusPlus();208  II.setHandleIdentifierCase();209}210 211/// AddKeyword - This method is used to associate a token ID with specific212/// identifiers because they are language keywords.  This causes the lexer to213/// automatically map matching identifiers to specialized token codes.214static void AddKeyword(StringRef Keyword,215                       tok::TokenKind TokenCode, unsigned Flags,216                       const LangOptions &LangOpts, IdentifierTable &Table) {217  KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);218 219  // Don't add this keyword if disabled in this language and isn't otherwise220  // special.221  if (AddResult == KS_Disabled) {222    // We do not consider any identifiers to be C++ keywords when in223    // Objective-C because @ effectively introduces a custom grammar where C++224    // keywords can be used (and similar for selectors). We could enable this225    // for Objective-C, but it would require more logic to ensure we do not226    // issue compatibility diagnostics in these cases.227    if (!LangOpts.ObjC && IsKeywordInCpp(Flags))228      MarkIdentifierAsKeywordInCpp(Table, Keyword);229    return;230  }231 232  IdentifierInfo &Info =233      Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);234  Info.setIsExtensionToken(AddResult == KS_Extension);235  Info.setIsFutureCompatKeyword(AddResult == KS_Future);236}237 238/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative239/// representations.240static void AddCXXOperatorKeyword(StringRef Keyword,241                                  tok::TokenKind TokenCode,242                                  IdentifierTable &Table) {243  IdentifierInfo &Info = Table.get(Keyword, TokenCode);244  Info.setIsCPlusPlusOperatorKeyword();245}246 247/// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"248/// or "property".249static void AddObjCKeyword(StringRef Name,250                           tok::ObjCKeywordKind ObjCID,251                           IdentifierTable &Table) {252  Table.get(Name).setObjCKeywordID(ObjCID);253}254 255static void AddNotableIdentifier(StringRef Name,256                                 tok::NotableIdentifierKind BTID,257                                 IdentifierTable &Table) {258  // Don't add 'not_notable' identifier.259  if (BTID != tok::not_notable) {260    IdentifierInfo &Info = Table.get(Name, tok::identifier);261    Info.setNotableIdentifierID(BTID);262  }263}264 265/// AddKeywords - Add all keywords to the symbol table.266///267void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {268  // Add keywords and tokens for the current language.269#define KEYWORD(NAME, FLAGS) \270  AddKeyword(StringRef(#NAME), tok::kw_ ## NAME,  \271             FLAGS, LangOpts, *this);272#define ALIAS(NAME, TOK, FLAGS) \273  AddKeyword(StringRef(NAME), tok::kw_ ## TOK,  \274             FLAGS, LangOpts, *this);275#define CXX_KEYWORD_OPERATOR(NAME, ALIAS)                                      \276  if (LangOpts.CXXOperatorNames)                                               \277    AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);                \278  else                                                                         \279    MarkIdentifierAsKeywordInCpp(*this, StringRef(#NAME));280#define OBJC_AT_KEYWORD(NAME)  \281  if (LangOpts.ObjC)           \282    AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);283#define NOTABLE_IDENTIFIER(NAME)                                               \284  AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);285 286#define TESTING_KEYWORD(NAME, FLAGS)287#include "clang/Basic/TokenKinds.def"288 289  if (LangOpts.ParseUnknownAnytype)290    AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,291               LangOpts, *this);292 293  if (LangOpts.DeclSpecKeyword)294    AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);295 296  if (LangOpts.IEEE128)297    AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);298 299  // Add the 'import' contextual keyword.300  get("import").setModulesImport(true);301}302 303/// Checks if the specified token kind represents a keyword in the304/// specified language.305/// \returns Status of the keyword in the language.306static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,307                                      tok::TokenKind K) {308  switch (K) {309#define KEYWORD(NAME, FLAGS) \310  case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);311#include "clang/Basic/TokenKinds.def"312  default: return KS_Disabled;313  }314}315 316/// Returns true if the identifier represents a keyword in the317/// specified language.318bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {319  switch (getTokenKwStatus(LangOpts, getTokenID())) {320  case KS_Enabled:321  case KS_Extension:322    return true;323  default:324    return false;325  }326}327 328/// Returns true if the identifier represents a C++ keyword in the329/// specified language.330bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {331  if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))332    return false;333  // This is a C++ keyword if this identifier is not a keyword when checked334  // using LangOptions without C++ support.335  LangOptions LangOptsNoCPP = LangOpts;336  LangOptsNoCPP.CPlusPlus = false;337  LangOptsNoCPP.CPlusPlus11 = false;338  LangOptsNoCPP.CPlusPlus20 = false;339  return !isKeyword(LangOptsNoCPP);340}341 342ReservedIdentifierStatus343IdentifierInfo::isReserved(const LangOptions &LangOpts) const {344  StringRef Name = getName();345 346  // '_' is a reserved identifier, but its use is so common (e.g. to store347  // ignored values) that we don't warn on it.348  if (Name.size() <= 1)349    return ReservedIdentifierStatus::NotReserved;350 351  // [lex.name] p3352  if (Name[0] == '_') {353 354    // Each name that begins with an underscore followed by an uppercase letter355    // or another underscore is reserved.356    if (Name[1] == '_')357      return ReservedIdentifierStatus::StartsWithDoubleUnderscore;358 359    if ('A' <= Name[1] && Name[1] <= 'Z')360      return ReservedIdentifierStatus::361          StartsWithUnderscoreFollowedByCapitalLetter;362 363    // This is a bit misleading: it actually means it's only reserved if we're364    // at global scope because it starts with an underscore.365    return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;366  }367 368  // Each name that contains a double underscore (__) is reserved.369  if (LangOpts.CPlusPlus && Name.contains("__"))370    return ReservedIdentifierStatus::ContainsDoubleUnderscore;371 372  return ReservedIdentifierStatus::NotReserved;373}374 375ReservedLiteralSuffixIdStatus376IdentifierInfo::isReservedLiteralSuffixId() const {377  StringRef Name = getName();378 379  // Note: the diag::warn_deprecated_literal_operator_id diagnostic depends on380  // this being the first check we do, so if this order changes, we have to fix381  // that as well.382  if (Name[0] != '_')383    return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;384 385  if (Name.contains("__"))386    return ReservedLiteralSuffixIdStatus::ContainsDoubleUnderscore;387 388  return ReservedLiteralSuffixIdStatus::NotReserved;389}390 391StringRef IdentifierInfo::deuglifiedName() const {392  StringRef Name = getName();393  if (Name.size() >= 2 && Name.front() == '_' &&394      (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))395    return Name.ltrim('_');396  return Name;397}398 399tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {400  // We use a perfect hash function here involving the length of the keyword,401  // the first and third character.  For preprocessor ID's there are no402  // collisions (if there were, the switch below would complain about duplicate403  // case values).  Note that this depends on 'if' being null terminated.404 405#define HASH(LEN, FIRST, THIRD)                                                \406  (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)407#define CASE(LEN, FIRST, THIRD, NAME) \408  case HASH(LEN, FIRST, THIRD): \409    return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME410 411  unsigned Len = getLength();412  if (Len < 2) return tok::pp_not_keyword;413  const char *Name = getNameStart();414  switch (HASH(Len, Name[0], Name[2])) {415  default: return tok::pp_not_keyword;416  CASE( 2, 'i', '\0', if);417  CASE( 4, 'e', 'i', elif);418  CASE( 4, 'e', 's', else);419  CASE( 4, 'l', 'n', line);420  CASE( 4, 's', 'c', sccs);421  CASE( 5, 'e', 'b', embed);422  CASE( 5, 'e', 'd', endif);423  CASE( 5, 'e', 'r', error);424  CASE( 5, 'i', 'e', ident);425  CASE( 5, 'i', 'd', ifdef);426  CASE( 5, 'u', 'd', undef);427 428  CASE( 6, 'a', 's', assert);429  CASE( 6, 'd', 'f', define);430  CASE( 6, 'i', 'n', ifndef);431  CASE( 6, 'i', 'p', import);432  CASE( 6, 'p', 'a', pragma);433 434  CASE( 7, 'd', 'f', defined);435  CASE( 7, 'e', 'i', elifdef);436  CASE( 7, 'i', 'c', include);437  CASE( 7, 'w', 'r', warning);438 439  CASE( 8, 'e', 'i', elifndef);440  CASE( 8, 'u', 'a', unassert);441  CASE(12, 'i', 'c', include_next);442 443  CASE(14, '_', 'p', __public_macro);444 445  CASE(15, '_', 'p', __private_macro);446 447  CASE(16, '_', 'i', __include_macros);448#undef CASE449#undef HASH450  }451}452 453//===----------------------------------------------------------------------===//454// Stats Implementation455//===----------------------------------------------------------------------===//456 457/// PrintStats - Print statistics about how well the identifier table is doing458/// at hashing identifiers.459void IdentifierTable::PrintStats() const {460  unsigned NumBuckets = HashTable.getNumBuckets();461  unsigned NumIdentifiers = HashTable.getNumItems();462  unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;463  unsigned AverageIdentifierSize = 0;464  unsigned MaxIdentifierLength = 0;465 466  // TODO: Figure out maximum times an identifier had to probe for -stats.467  for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator468       I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {469    unsigned IdLen = I->getKeyLength();470    AverageIdentifierSize += IdLen;471    if (MaxIdentifierLength < IdLen)472      MaxIdentifierLength = IdLen;473  }474 475  fprintf(stderr, "\n*** Identifier Table Stats:\n");476  fprintf(stderr, "# Identifiers:   %d\n", NumIdentifiers);477  fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);478  fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",479          NumIdentifiers/(double)NumBuckets);480  fprintf(stderr, "Ave identifier length: %f\n",481          (AverageIdentifierSize/(double)NumIdentifiers));482  fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);483 484  // Compute statistics about the memory allocated for identifiers.485  HashTable.getAllocator().PrintStats();486}487 488//===----------------------------------------------------------------------===//489// SelectorTable Implementation490//===----------------------------------------------------------------------===//491 492unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {493  return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());494}495 496bool Selector::isKeywordSelector(ArrayRef<StringRef> Names) const {497  assert(!Names.empty() && "must have >= 1 selector slots");498  if (getNumArgs() != Names.size())499    return false;500  for (unsigned I = 0, E = Names.size(); I != E; ++I) {501    if (getNameForSlot(I) != Names[I])502      return false;503  }504  return true;505}506 507bool Selector::isUnarySelector(StringRef Name) const {508  return isUnarySelector() && getNameForSlot(0) == Name;509}510 511unsigned Selector::getNumArgs() const {512  unsigned IIF = getIdentifierInfoFlag();513  if (IIF <= ZeroArg)514    return 0;515  if (IIF == OneArg)516    return 1;517  // We point to a MultiKeywordSelector.518  MultiKeywordSelector *SI = getMultiKeywordSelector();519  return SI->getNumArgs();520}521 522const IdentifierInfo *523Selector::getIdentifierInfoForSlot(unsigned argIndex) const {524  if (getIdentifierInfoFlag() < MultiArg) {525    assert(argIndex == 0 && "illegal keyword index");526    return getAsIdentifierInfo();527  }528 529  // We point to a MultiKeywordSelector.530  MultiKeywordSelector *SI = getMultiKeywordSelector();531  return SI->getIdentifierInfoForSlot(argIndex);532}533 534StringRef Selector::getNameForSlot(unsigned int argIndex) const {535  const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);536  return II ? II->getName() : StringRef();537}538 539std::string MultiKeywordSelector::getName() const {540  SmallString<256> Str;541  llvm::raw_svector_ostream OS(Str);542  for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {543    if (*I)544      OS << (*I)->getName();545    OS << ':';546  }547 548  return std::string(OS.str());549}550 551std::string Selector::getAsString() const {552  if (isNull())553    return "<null selector>";554 555  if (getIdentifierInfoFlag() < MultiArg) {556    const IdentifierInfo *II = getAsIdentifierInfo();557 558    if (getNumArgs() == 0) {559      assert(II && "If the number of arguments is 0 then II is guaranteed to "560                   "not be null.");561      return std::string(II->getName());562    }563 564    if (!II)565      return ":";566 567    return II->getName().str() + ":";568  }569 570  // We have a multiple keyword selector.571  return getMultiKeywordSelector()->getName();572}573 574void Selector::print(llvm::raw_ostream &OS) const {575  OS << getAsString();576}577 578LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }579 580/// Interpreting the given string using the normal CamelCase581/// conventions, determine whether the given string starts with the582/// given "word", which is assumed to end in a lowercase letter.583static bool startsWithWord(StringRef name, StringRef word) {584  if (name.size() < word.size()) return false;585  return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&586          name.starts_with(word));587}588 589ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {590  const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);591  if (!first) return OMF_None;592 593  StringRef name = first->getName();594  if (sel.isUnarySelector()) {595    if (name == "autorelease") return OMF_autorelease;596    if (name == "dealloc") return OMF_dealloc;597    if (name == "finalize") return OMF_finalize;598    if (name == "release") return OMF_release;599    if (name == "retain") return OMF_retain;600    if (name == "retainCount") return OMF_retainCount;601    if (name == "self") return OMF_self;602    if (name == "initialize") return OMF_initialize;603  }604 605  if (name == "performSelector" || name == "performSelectorInBackground" ||606      name == "performSelectorOnMainThread")607    return OMF_performSelector;608 609  // The other method families may begin with a prefix of underscores.610  name = name.ltrim('_');611 612  if (name.empty()) return OMF_None;613  switch (name.front()) {614  case 'a':615    if (startsWithWord(name, "alloc")) return OMF_alloc;616    break;617  case 'c':618    if (startsWithWord(name, "copy")) return OMF_copy;619    break;620  case 'i':621    if (startsWithWord(name, "init")) return OMF_init;622    break;623  case 'm':624    if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;625    break;626  case 'n':627    if (startsWithWord(name, "new")) return OMF_new;628    break;629  default:630    break;631  }632 633  return OMF_None;634}635 636ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {637  const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);638  if (!first) return OIT_None;639 640  StringRef name = first->getName();641 642  if (name.empty()) return OIT_None;643  switch (name.front()) {644    case 'a':645      if (startsWithWord(name, "array")) return OIT_Array;646      break;647    case 'd':648      if (startsWithWord(name, "default")) return OIT_ReturnsSelf;649      if (startsWithWord(name, "dictionary")) return OIT_Dictionary;650      break;651    case 's':652      if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;653      if (startsWithWord(name, "standard")) return OIT_Singleton;654      break;655    case 'i':656      if (startsWithWord(name, "init")) return OIT_Init;657      break;658    default:659      break;660  }661  return OIT_None;662}663 664ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {665  const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);666  if (!first) return SFF_None;667 668  StringRef name = first->getName();669 670  switch (name.front()) {671    case 'a':672      if (name == "appendFormat") return SFF_NSString;673      break;674 675    case 'i':676      if (name == "initWithFormat") return SFF_NSString;677      break;678 679    case 'l':680      if (name == "localizedStringWithFormat") return SFF_NSString;681      break;682 683    case 's':684      if (name == "stringByAppendingFormat" ||685          name == "stringWithFormat") return SFF_NSString;686      break;687  }688  return SFF_None;689}690 691namespace {692 693struct SelectorTableImpl {694  llvm::FoldingSet<MultiKeywordSelector> Table;695  llvm::BumpPtrAllocator Allocator;696};697 698} // namespace699 700static SelectorTableImpl &getSelectorTableImpl(void *P) {701  return *static_cast<SelectorTableImpl*>(P);702}703 704SmallString<64>705SelectorTable::constructSetterName(StringRef Name) {706  SmallString<64> SetterName("set");707  SetterName += Name;708  SetterName[3] = toUppercase(SetterName[3]);709  return SetterName;710}711 712Selector713SelectorTable::constructSetterSelector(IdentifierTable &Idents,714                                       SelectorTable &SelTable,715                                       const IdentifierInfo *Name) {716  IdentifierInfo *SetterName =717    &Idents.get(constructSetterName(Name->getName()));718  return SelTable.getUnarySelector(SetterName);719}720 721std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {722  StringRef Name = Sel.getNameForSlot(0);723  assert(Name.starts_with("set") && "invalid setter name");724  return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();725}726 727size_t SelectorTable::getTotalMemory() const {728  SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);729  return SelTabImpl.Allocator.getTotalMemory();730}731 732Selector SelectorTable::getSelector(unsigned nKeys,733                                    const IdentifierInfo **IIV) {734  if (nKeys < 2)735    return Selector(IIV[0], nKeys);736 737  SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);738 739  // Unique selector, to guarantee there is one per name.740  llvm::FoldingSetNodeID ID;741  MultiKeywordSelector::Profile(ID, IIV, nKeys);742 743  void *InsertPos = nullptr;744  if (MultiKeywordSelector *SI =745        SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))746    return Selector(SI);747 748  // MultiKeywordSelector objects are not allocated with new because they have a749  // variable size array (for parameter types) at the end of them.750  unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);751  MultiKeywordSelector *SI =752      (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(753          Size, alignof(MultiKeywordSelector));754  new (SI) MultiKeywordSelector(nKeys, IIV);755  SelTabImpl.Table.InsertNode(SI, InsertPos);756  return Selector(SI);757}758 759SelectorTable::SelectorTable() {760  Impl = new SelectorTableImpl();761}762 763SelectorTable::~SelectorTable() {764  delete &getSelectorTableImpl(Impl);765}766 767const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {768  switch (Operator) {769  case OO_None:770  case NUM_OVERLOADED_OPERATORS:771    return nullptr;772 773#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \774  case OO_##Name: return Spelling;775#include "clang/Basic/OperatorKinds.def"776  }777 778  llvm_unreachable("Invalid OverloadedOperatorKind!");779}780 781StringRef clang::getNullabilitySpelling(NullabilityKind kind,782                                        bool isContextSensitive) {783  switch (kind) {784  case NullabilityKind::NonNull:785    return isContextSensitive ? "nonnull" : "_Nonnull";786 787  case NullabilityKind::Nullable:788    return isContextSensitive ? "nullable" : "_Nullable";789 790  case NullabilityKind::NullableResult:791    assert(!isContextSensitive &&792           "_Nullable_result isn't supported as context-sensitive keyword");793    return "_Nullable_result";794 795  case NullabilityKind::Unspecified:796    return isContextSensitive ? "null_unspecified" : "_Null_unspecified";797  }798  llvm_unreachable("Unknown nullability kind.");799}800 801llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,802                                     NullabilityKind NK) {803  switch (NK) {804  case NullabilityKind::NonNull:805    return OS << "NonNull";806  case NullabilityKind::Nullable:807    return OS << "Nullable";808  case NullabilityKind::NullableResult:809    return OS << "NullableResult";810  case NullabilityKind::Unspecified:811    return OS << "Unspecified";812  }813  llvm_unreachable("Unknown nullability kind.");814}815 816diag::kind817IdentifierTable::getFutureCompatDiagKind(const IdentifierInfo &II,818                                         const LangOptions &LangOpts) {819  assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");820 821  unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())822#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)823#include "clang/Basic/TokenKinds.def"824#undef KEYWORD825      ;826 827  if (LangOpts.CPlusPlus) {828    if ((Flags & KEYCXX11) == KEYCXX11)829      return diag::warn_cxx11_keyword;830 831    // char8_t is not modeled as a CXX20_KEYWORD because it's not832    // unconditionally enabled in C++20 mode. (It can be disabled833    // by -fno-char8_t.)834    if (((Flags & KEYCXX20) == KEYCXX20) ||835        ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))836      return diag::warn_cxx20_keyword;837  } else {838    if ((Flags & KEYC99) == KEYC99)839      return diag::warn_c99_keyword;840    if ((Flags & KEYC23) == KEYC23)841      return diag::warn_c23_keyword;842  }843 844  llvm_unreachable(845      "Keyword not known to come from a newer Standard or proposed Standard");846}847