File indexing completed on 2026-05-10 08:36:49
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
0016 #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
0017
0018 #include "clang/Basic/Builtins.h"
0019 #include "clang/Basic/DiagnosticIDs.h"
0020 #include "clang/Basic/LLVM.h"
0021 #include "clang/Basic/TokenKinds.h"
0022 #include "llvm/ADT/DenseMapInfo.h"
0023 #include "llvm/ADT/FoldingSet.h"
0024 #include "llvm/ADT/PointerIntPair.h"
0025 #include "llvm/ADT/PointerUnion.h"
0026 #include "llvm/ADT/SmallString.h"
0027 #include "llvm/ADT/StringMap.h"
0028 #include "llvm/ADT/StringRef.h"
0029 #include "llvm/Support/Allocator.h"
0030 #include "llvm/Support/PointerLikeTypeTraits.h"
0031 #include "llvm/Support/type_traits.h"
0032 #include <cassert>
0033 #include <cstddef>
0034 #include <cstdint>
0035 #include <cstring>
0036 #include <string>
0037 #include <utility>
0038
0039 namespace clang {
0040
0041 class DeclarationName;
0042 class DeclarationNameTable;
0043 class IdentifierInfo;
0044 class LangOptions;
0045 class MultiKeywordSelector;
0046 class SourceLocation;
0047
0048 enum class ReservedIdentifierStatus {
0049 NotReserved = 0,
0050 StartsWithUnderscoreAtGlobalScope,
0051 StartsWithUnderscoreAndIsExternC,
0052 StartsWithDoubleUnderscore,
0053 StartsWithUnderscoreFollowedByCapitalLetter,
0054 ContainsDoubleUnderscore,
0055 };
0056
0057 enum class ReservedLiteralSuffixIdStatus {
0058 NotReserved = 0,
0059 NotStartsWithUnderscore,
0060 ContainsDoubleUnderscore,
0061 };
0062
0063
0064
0065
0066 inline bool isReservedAtGlobalScope(ReservedIdentifierStatus Status) {
0067 return Status != ReservedIdentifierStatus::NotReserved;
0068 }
0069
0070
0071
0072
0073 inline bool isReservedInAllContexts(ReservedIdentifierStatus Status) {
0074 return Status != ReservedIdentifierStatus::NotReserved &&
0075 Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope &&
0076 Status != ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
0077 }
0078
0079
0080 using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
0081
0082
0083
0084
0085 enum { IdentifierInfoAlignment = 8 };
0086
0087 static constexpr int InterestingIdentifierBits = 16;
0088
0089
0090
0091
0092
0093
0094 enum class InterestingIdentifier {
0095 #define OBJC_AT_KEYWORD(X) objc_##X,
0096 #include "clang/Basic/TokenKinds.def"
0097 NUM_OBJC_KEYWORDS,
0098
0099 #define NOTABLE_IDENTIFIER(X) X,
0100 #include "clang/Basic/TokenKinds.def"
0101 NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS,
0102
0103 NotBuiltin,
0104 #define BUILTIN(ID, TYPE, ATTRS) BI##ID,
0105 #include "clang/Basic/Builtins.inc"
0106 FirstTSBuiltin,
0107
0108 NotInterestingIdentifier = 65534
0109 };
0110
0111
0112
0113
0114
0115
0116
0117 class alignas(IdentifierInfoAlignment) IdentifierInfo {
0118 friend class IdentifierTable;
0119
0120
0121 LLVM_PREFERRED_TYPE(tok::TokenKind)
0122 unsigned TokenID : 9;
0123
0124 LLVM_PREFERRED_TYPE(InterestingIdentifier)
0125 unsigned InterestingIdentifierID : InterestingIdentifierBits;
0126
0127
0128 LLVM_PREFERRED_TYPE(bool)
0129 unsigned HasMacro : 1;
0130
0131
0132 LLVM_PREFERRED_TYPE(bool)
0133 unsigned HadMacro : 1;
0134
0135
0136 LLVM_PREFERRED_TYPE(bool)
0137 unsigned IsExtension : 1;
0138
0139
0140 LLVM_PREFERRED_TYPE(bool)
0141 unsigned IsFutureCompatKeyword : 1;
0142
0143
0144 LLVM_PREFERRED_TYPE(bool)
0145 unsigned IsPoisoned : 1;
0146
0147
0148 LLVM_PREFERRED_TYPE(bool)
0149 unsigned IsCPPOperatorKeyword : 1;
0150
0151
0152
0153 LLVM_PREFERRED_TYPE(bool)
0154 unsigned NeedsHandleIdentifier : 1;
0155
0156
0157 LLVM_PREFERRED_TYPE(bool)
0158 unsigned IsFromAST : 1;
0159
0160
0161
0162 LLVM_PREFERRED_TYPE(bool)
0163 unsigned ChangedAfterLoad : 1;
0164
0165
0166
0167 LLVM_PREFERRED_TYPE(bool)
0168 unsigned FEChangedAfterLoad : 1;
0169
0170
0171 LLVM_PREFERRED_TYPE(bool)
0172 unsigned RevertedTokenID : 1;
0173
0174
0175
0176 LLVM_PREFERRED_TYPE(bool)
0177 unsigned OutOfDate : 1;
0178
0179
0180 LLVM_PREFERRED_TYPE(bool)
0181 unsigned IsModulesImport : 1;
0182
0183
0184 LLVM_PREFERRED_TYPE(bool)
0185 unsigned IsMangledOpenMPVariantName : 1;
0186
0187
0188 LLVM_PREFERRED_TYPE(bool)
0189 unsigned IsDeprecatedMacro : 1;
0190
0191
0192 LLVM_PREFERRED_TYPE(bool)
0193 unsigned IsRestrictExpansion : 1;
0194
0195
0196 LLVM_PREFERRED_TYPE(bool)
0197 unsigned IsFinal : 1;
0198
0199
0200
0201
0202 void *FETokenInfo = nullptr;
0203
0204 llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr;
0205
0206 IdentifierInfo()
0207 : TokenID(tok::identifier),
0208 InterestingIdentifierID(llvm::to_underlying(
0209 InterestingIdentifier::NotInterestingIdentifier)),
0210 HasMacro(false), HadMacro(false), IsExtension(false),
0211 IsFutureCompatKeyword(false), IsPoisoned(false),
0212 IsCPPOperatorKeyword(false), NeedsHandleIdentifier(false),
0213 IsFromAST(false), ChangedAfterLoad(false), FEChangedAfterLoad(false),
0214 RevertedTokenID(false), OutOfDate(false), IsModulesImport(false),
0215 IsMangledOpenMPVariantName(false), IsDeprecatedMacro(false),
0216 IsRestrictExpansion(false), IsFinal(false) {}
0217
0218 public:
0219 IdentifierInfo(const IdentifierInfo &) = delete;
0220 IdentifierInfo &operator=(const IdentifierInfo &) = delete;
0221 IdentifierInfo(IdentifierInfo &&) = delete;
0222 IdentifierInfo &operator=(IdentifierInfo &&) = delete;
0223
0224
0225
0226
0227 template <std::size_t StrLen>
0228 bool isStr(const char (&Str)[StrLen]) const {
0229 return getLength() == StrLen-1 &&
0230 memcmp(getNameStart(), Str, StrLen-1) == 0;
0231 }
0232
0233
0234 bool isStr(llvm::StringRef Str) const {
0235 llvm::StringRef ThisStr(getNameStart(), getLength());
0236 return ThisStr == Str;
0237 }
0238
0239
0240
0241 const char *getNameStart() const { return Entry->getKeyData(); }
0242
0243
0244 unsigned getLength() const { return Entry->getKeyLength(); }
0245
0246
0247 StringRef getName() const {
0248 return StringRef(getNameStart(), getLength());
0249 }
0250
0251
0252
0253 bool hasMacroDefinition() const {
0254 return HasMacro;
0255 }
0256 void setHasMacroDefinition(bool Val) {
0257 if (HasMacro == Val) return;
0258
0259 HasMacro = Val;
0260 if (Val) {
0261 NeedsHandleIdentifier = true;
0262 HadMacro = true;
0263 } else {
0264
0265
0266 if (!IsFinal) {
0267
0268
0269 IsDeprecatedMacro = false;
0270 IsRestrictExpansion = false;
0271 }
0272 RecomputeNeedsHandleIdentifier();
0273 }
0274 }
0275
0276
0277
0278 bool hadMacroDefinition() const {
0279 return HadMacro;
0280 }
0281
0282 bool isDeprecatedMacro() const { return IsDeprecatedMacro; }
0283
0284 void setIsDeprecatedMacro(bool Val) {
0285 if (IsDeprecatedMacro == Val)
0286 return;
0287 IsDeprecatedMacro = Val;
0288 if (Val)
0289 NeedsHandleIdentifier = true;
0290 else
0291 RecomputeNeedsHandleIdentifier();
0292 }
0293
0294 bool isRestrictExpansion() const { return IsRestrictExpansion; }
0295
0296 void setIsRestrictExpansion(bool Val) {
0297 if (IsRestrictExpansion == Val)
0298 return;
0299 IsRestrictExpansion = Val;
0300 if (Val)
0301 NeedsHandleIdentifier = true;
0302 else
0303 RecomputeNeedsHandleIdentifier();
0304 }
0305
0306 bool isFinal() const { return IsFinal; }
0307
0308 void setIsFinal(bool Val) { IsFinal = Val; }
0309
0310
0311
0312
0313 tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
0314
0315
0316 bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
0317
0318
0319
0320
0321
0322
0323
0324 void revertTokenIDToIdentifier() {
0325 assert(TokenID != tok::identifier && "Already at tok::identifier");
0326 TokenID = tok::identifier;
0327 RevertedTokenID = true;
0328 }
0329 void revertIdentifierToTokenID(tok::TokenKind TK) {
0330 assert(TokenID == tok::identifier && "Should be at tok::identifier");
0331 TokenID = TK;
0332 RevertedTokenID = false;
0333 }
0334
0335
0336
0337
0338 tok::PPKeywordKind getPPKeywordID() const;
0339
0340
0341
0342
0343 tok::ObjCKeywordKind getObjCKeywordID() const {
0344 assert(0 == llvm::to_underlying(InterestingIdentifier::objc_not_keyword));
0345 auto Value = static_cast<InterestingIdentifier>(InterestingIdentifierID);
0346 if (Value < InterestingIdentifier::NUM_OBJC_KEYWORDS)
0347 return static_cast<tok::ObjCKeywordKind>(InterestingIdentifierID);
0348 return tok::objc_not_keyword;
0349 }
0350 void setObjCKeywordID(tok::ObjCKeywordKind ID) {
0351 assert(0 == llvm::to_underlying(InterestingIdentifier::objc_not_keyword));
0352 InterestingIdentifierID = ID;
0353 assert(getObjCKeywordID() == ID && "ID too large for field!");
0354 }
0355
0356
0357 unsigned getBuiltinID() const {
0358 auto Value = static_cast<InterestingIdentifier>(InterestingIdentifierID);
0359 if (Value >
0360 InterestingIdentifier::NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS &&
0361 Value != InterestingIdentifier::NotInterestingIdentifier) {
0362 auto FirstBuiltin =
0363 llvm::to_underlying(InterestingIdentifier::NotBuiltin);
0364 return static_cast<Builtin::ID>(InterestingIdentifierID - FirstBuiltin);
0365 }
0366 return Builtin::ID::NotBuiltin;
0367 }
0368 void setBuiltinID(unsigned ID) {
0369 assert(ID != Builtin::ID::NotBuiltin);
0370 auto FirstBuiltin = llvm::to_underlying(InterestingIdentifier::NotBuiltin);
0371 InterestingIdentifierID = ID + FirstBuiltin;
0372 assert(getBuiltinID() == ID && "ID too large for field!");
0373 }
0374 void clearBuiltinID() {
0375 InterestingIdentifierID =
0376 llvm::to_underlying(InterestingIdentifier::NotInterestingIdentifier);
0377 }
0378
0379 tok::NotableIdentifierKind getNotableIdentifierID() const {
0380 auto Value = static_cast<InterestingIdentifier>(InterestingIdentifierID);
0381 if (Value > InterestingIdentifier::NUM_OBJC_KEYWORDS &&
0382 Value <
0383 InterestingIdentifier::NUM_OBJC_KEYWORDS_AND_NOTABLE_IDENTIFIERS) {
0384 auto FirstNotableIdentifier =
0385 1 + llvm::to_underlying(InterestingIdentifier::NUM_OBJC_KEYWORDS);
0386 return static_cast<tok::NotableIdentifierKind>(InterestingIdentifierID -
0387 FirstNotableIdentifier);
0388 }
0389 return tok::not_notable;
0390 }
0391 void setNotableIdentifierID(unsigned ID) {
0392 assert(ID != tok::not_notable);
0393 auto FirstNotableIdentifier =
0394 1 + llvm::to_underlying(InterestingIdentifier::NUM_OBJC_KEYWORDS);
0395 InterestingIdentifierID = ID + FirstNotableIdentifier;
0396 assert(getNotableIdentifierID() == ID && "ID too large for field!");
0397 }
0398
0399 unsigned getObjCOrBuiltinID() const { return InterestingIdentifierID; }
0400 void setObjCOrBuiltinID(unsigned ID) { InterestingIdentifierID = ID; }
0401
0402
0403
0404
0405 bool isExtensionToken() const { return IsExtension; }
0406 void setIsExtensionToken(bool Val) {
0407 IsExtension = Val;
0408 if (Val)
0409 NeedsHandleIdentifier = true;
0410 else
0411 RecomputeNeedsHandleIdentifier();
0412 }
0413
0414
0415
0416
0417
0418
0419 bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; }
0420 void setIsFutureCompatKeyword(bool Val) {
0421 IsFutureCompatKeyword = Val;
0422 if (Val)
0423 NeedsHandleIdentifier = true;
0424 else
0425 RecomputeNeedsHandleIdentifier();
0426 }
0427
0428
0429
0430 void setIsPoisoned(bool Value = true) {
0431 IsPoisoned = Value;
0432 if (Value)
0433 NeedsHandleIdentifier = true;
0434 else
0435 RecomputeNeedsHandleIdentifier();
0436 }
0437
0438
0439 bool isPoisoned() const { return IsPoisoned; }
0440
0441
0442
0443 void setIsCPlusPlusOperatorKeyword(bool Val = true) {
0444 IsCPPOperatorKeyword = Val;
0445 }
0446 bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
0447
0448
0449 bool isKeyword(const LangOptions &LangOpts) const;
0450
0451
0452
0453 bool isCPlusPlusKeyword(const LangOptions &LangOpts) const;
0454
0455
0456
0457 void *getFETokenInfo() const { return FETokenInfo; }
0458 void setFETokenInfo(void *T) { FETokenInfo = T; }
0459
0460
0461
0462
0463
0464
0465 bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
0466
0467
0468
0469 bool isFromAST() const { return IsFromAST; }
0470
0471 void setIsFromAST() { IsFromAST = true; }
0472
0473
0474
0475 bool hasChangedSinceDeserialization() const {
0476 return ChangedAfterLoad;
0477 }
0478
0479
0480
0481 void setChangedSinceDeserialization() {
0482 ChangedAfterLoad = true;
0483 }
0484
0485
0486
0487 bool hasFETokenInfoChangedSinceDeserialization() const {
0488 return FEChangedAfterLoad;
0489 }
0490
0491
0492
0493 void setFETokenInfoChangedSinceDeserialization() {
0494 FEChangedAfterLoad = true;
0495 }
0496
0497
0498
0499 bool isOutOfDate() const { return OutOfDate; }
0500
0501
0502
0503 void setOutOfDate(bool OOD) {
0504 OutOfDate = OOD;
0505 if (OOD)
0506 NeedsHandleIdentifier = true;
0507 else
0508 RecomputeNeedsHandleIdentifier();
0509 }
0510
0511
0512 bool isModulesImport() const { return IsModulesImport; }
0513
0514
0515 void setModulesImport(bool I) {
0516 IsModulesImport = I;
0517 if (I)
0518 NeedsHandleIdentifier = true;
0519 else
0520 RecomputeNeedsHandleIdentifier();
0521 }
0522
0523
0524 bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; }
0525
0526
0527 void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; }
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538 bool isEditorPlaceholder() const {
0539 return getName().starts_with("<#") && getName().ends_with("#>");
0540 }
0541
0542
0543
0544 ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
0545
0546
0547
0548 ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const;
0549
0550
0551
0552 StringRef deuglifiedName() const;
0553 bool isPlaceholder() const {
0554 return getLength() == 1 && getNameStart()[0] == '_';
0555 }
0556
0557
0558 bool operator<(const IdentifierInfo &RHS) const {
0559 return getName() < RHS.getName();
0560 }
0561
0562 private:
0563
0564
0565
0566
0567
0568
0569 void RecomputeNeedsHandleIdentifier() {
0570 NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
0571 isExtensionToken() || isFutureCompatKeyword() ||
0572 isOutOfDate() || isModulesImport();
0573 }
0574 };
0575
0576
0577
0578
0579
0580 class PoisonIdentifierRAIIObject {
0581 IdentifierInfo *const II;
0582 const bool OldValue;
0583
0584 public:
0585 PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue)
0586 : II(II), OldValue(II ? II->isPoisoned() : false) {
0587 if(II)
0588 II->setIsPoisoned(NewValue);
0589 }
0590
0591 ~PoisonIdentifierRAIIObject() {
0592 if(II)
0593 II->setIsPoisoned(OldValue);
0594 }
0595 };
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607 class IdentifierIterator {
0608 protected:
0609 IdentifierIterator() = default;
0610
0611 public:
0612 IdentifierIterator(const IdentifierIterator &) = delete;
0613 IdentifierIterator &operator=(const IdentifierIterator &) = delete;
0614
0615 virtual ~IdentifierIterator();
0616
0617
0618
0619
0620
0621
0622 virtual StringRef Next() = 0;
0623 };
0624
0625
0626 class IdentifierInfoLookup {
0627 public:
0628 virtual ~IdentifierInfoLookup();
0629
0630
0631
0632
0633
0634
0635 virtual IdentifierInfo* get(StringRef Name) = 0;
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647 virtual IdentifierIterator *getIdentifiers();
0648 };
0649
0650
0651
0652
0653
0654
0655 class IdentifierTable {
0656
0657
0658 using HashTableTy = llvm::StringMap<IdentifierInfo *, llvm::BumpPtrAllocator>;
0659 HashTableTy HashTable;
0660
0661 IdentifierInfoLookup* ExternalLookup;
0662
0663 public:
0664
0665 explicit IdentifierTable(IdentifierInfoLookup *ExternalLookup = nullptr);
0666
0667
0668
0669 explicit IdentifierTable(const LangOptions &LangOpts,
0670 IdentifierInfoLookup *ExternalLookup = nullptr);
0671
0672
0673 void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
0674 ExternalLookup = IILookup;
0675 }
0676
0677
0678 IdentifierInfoLookup *getExternalIdentifierLookup() const {
0679 return ExternalLookup;
0680 }
0681
0682 llvm::BumpPtrAllocator& getAllocator() {
0683 return HashTable.getAllocator();
0684 }
0685
0686
0687
0688 IdentifierInfo &get(StringRef Name) {
0689 auto &Entry = *HashTable.try_emplace(Name, nullptr).first;
0690
0691 IdentifierInfo *&II = Entry.second;
0692 if (II) return *II;
0693
0694
0695 if (ExternalLookup) {
0696 II = ExternalLookup->get(Name);
0697 if (II)
0698 return *II;
0699 }
0700
0701
0702 void *Mem = getAllocator().Allocate<IdentifierInfo>();
0703 II = new (Mem) IdentifierInfo();
0704
0705
0706
0707 II->Entry = &Entry;
0708
0709 return *II;
0710 }
0711
0712 IdentifierInfo &get(StringRef Name, tok::TokenKind TokenCode) {
0713 IdentifierInfo &II = get(Name);
0714 II.TokenID = TokenCode;
0715 assert(II.TokenID == (unsigned) TokenCode && "TokenCode too large");
0716 return II;
0717 }
0718
0719
0720
0721
0722
0723
0724
0725 IdentifierInfo &getOwn(StringRef Name) {
0726 auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first;
0727
0728 IdentifierInfo *&II = Entry.second;
0729 if (II)
0730 return *II;
0731
0732
0733 void *Mem = getAllocator().Allocate<IdentifierInfo>();
0734 II = new (Mem) IdentifierInfo();
0735
0736
0737
0738 II->Entry = &Entry;
0739
0740
0741 if (Name == "import")
0742 II->setModulesImport(true);
0743
0744 return *II;
0745 }
0746
0747 using iterator = HashTableTy::const_iterator;
0748 using const_iterator = HashTableTy::const_iterator;
0749
0750 iterator begin() const { return HashTable.begin(); }
0751 iterator end() const { return HashTable.end(); }
0752 unsigned size() const { return HashTable.size(); }
0753
0754 iterator find(StringRef Name) const { return HashTable.find(Name); }
0755
0756
0757
0758 void PrintStats() const;
0759
0760
0761
0762 void AddKeywords(const LangOptions &LangOpts);
0763
0764
0765
0766
0767 diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
0768 const LangOptions &LangOpts);
0769 };
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788 enum ObjCMethodFamily {
0789
0790 OMF_None,
0791
0792
0793
0794
0795
0796 OMF_alloc,
0797 OMF_copy,
0798 OMF_init,
0799 OMF_mutableCopy,
0800 OMF_new,
0801
0802
0803
0804 OMF_autorelease,
0805 OMF_dealloc,
0806 OMF_finalize,
0807 OMF_release,
0808 OMF_retain,
0809 OMF_retainCount,
0810 OMF_self,
0811 OMF_initialize,
0812
0813
0814 OMF_performSelector
0815 };
0816
0817
0818
0819 enum { ObjCMethodFamilyBitWidth = 4 };
0820
0821
0822 enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
0823
0824
0825
0826
0827
0828 enum ObjCInstanceTypeFamily {
0829 OIT_None,
0830 OIT_Array,
0831 OIT_Dictionary,
0832 OIT_Singleton,
0833 OIT_Init,
0834 OIT_ReturnsSelf
0835 };
0836
0837 enum ObjCStringFormatFamily {
0838 SFF_None,
0839 SFF_NSString,
0840 SFF_CFString
0841 };
0842
0843 namespace detail {
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853 class alignas(IdentifierInfoAlignment) DeclarationNameExtra {
0854 friend class clang::DeclarationName;
0855 friend class clang::DeclarationNameTable;
0856
0857 protected:
0858
0859
0860
0861
0862
0863 enum ExtraKind {
0864 CXXDeductionGuideName,
0865 CXXLiteralOperatorName,
0866 CXXUsingDirective,
0867 ObjCMultiArgSelector
0868 };
0869
0870
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880 unsigned ExtraKindOrNumArgs;
0881
0882 DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {}
0883 DeclarationNameExtra(unsigned NumArgs)
0884 : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {}
0885
0886
0887 ExtraKind getKind() const {
0888 return static_cast<ExtraKind>(ExtraKindOrNumArgs >
0889 (unsigned)ObjCMultiArgSelector
0890 ? (unsigned)ObjCMultiArgSelector
0891 : ExtraKindOrNumArgs);
0892 }
0893
0894
0895
0896 unsigned getNumArgs() const {
0897 assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector &&
0898 "getNumArgs called but this is not an ObjC selector!");
0899 return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector;
0900 }
0901 };
0902
0903 }
0904
0905
0906
0907
0908
0909 class alignas(IdentifierInfoAlignment) MultiKeywordSelector
0910 : public detail::DeclarationNameExtra,
0911 public llvm::FoldingSetNode {
0912 MultiKeywordSelector(unsigned nKeys) : DeclarationNameExtra(nKeys) {}
0913
0914 public:
0915
0916 MultiKeywordSelector(unsigned nKeys, const IdentifierInfo **IIV)
0917 : DeclarationNameExtra(nKeys) {
0918 assert((nKeys > 1) && "not a multi-keyword selector");
0919
0920
0921 const IdentifierInfo **KeyInfo =
0922 reinterpret_cast<const IdentifierInfo **>(this + 1);
0923 for (unsigned i = 0; i != nKeys; ++i)
0924 KeyInfo[i] = IIV[i];
0925 }
0926
0927
0928 std::string getName() const;
0929
0930 using DeclarationNameExtra::getNumArgs;
0931
0932 using keyword_iterator = const IdentifierInfo *const *;
0933
0934 keyword_iterator keyword_begin() const {
0935 return reinterpret_cast<keyword_iterator>(this + 1);
0936 }
0937
0938 keyword_iterator keyword_end() const {
0939 return keyword_begin() + getNumArgs();
0940 }
0941
0942 const IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
0943 assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
0944 return keyword_begin()[i];
0945 }
0946
0947 static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys,
0948 unsigned NumArgs) {
0949 ID.AddInteger(NumArgs);
0950 for (unsigned i = 0; i != NumArgs; ++i)
0951 ID.AddPointer(ArgTys[i]);
0952 }
0953
0954 void Profile(llvm::FoldingSetNodeID &ID) {
0955 Profile(ID, keyword_begin(), getNumArgs());
0956 }
0957 };
0958
0959
0960
0961
0962
0963
0964
0965
0966 class Selector {
0967 friend class Diagnostic;
0968 friend class SelectorTable;
0969 friend class DeclarationName;
0970
0971 enum IdentifierInfoFlag {
0972
0973
0974 ZeroArg = 0x01,
0975 OneArg = 0x02,
0976
0977
0978 MultiArg = 0x07,
0979 };
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994 llvm::PointerIntPair<
0995 llvm::PointerUnion<const IdentifierInfo *, MultiKeywordSelector *>, 2>
0996 InfoPtr;
0997
0998 Selector(const IdentifierInfo *II, unsigned nArgs) {
0999 assert(nArgs < 2 && "nArgs not equal to 0/1");
1000 InfoPtr.setPointerAndInt(II, nArgs + 1);
1001 }
1002
1003 Selector(MultiKeywordSelector *SI) {
1004
1005
1006
1007 InfoPtr.setPointerAndInt(SI, MultiArg & 0b11);
1008 }
1009
1010 const IdentifierInfo *getAsIdentifierInfo() const {
1011 return dyn_cast_if_present<const IdentifierInfo *>(InfoPtr.getPointer());
1012 }
1013
1014 MultiKeywordSelector *getMultiKeywordSelector() const {
1015 return cast<MultiKeywordSelector *>(InfoPtr.getPointer());
1016 }
1017
1018 unsigned getIdentifierInfoFlag() const {
1019 unsigned new_flags = InfoPtr.getInt();
1020
1021
1022
1023 if (isa<MultiKeywordSelector *>(InfoPtr.getPointer()))
1024 new_flags |= MultiArg;
1025 return new_flags;
1026 }
1027
1028 static ObjCMethodFamily getMethodFamilyImpl(Selector sel);
1029
1030 static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel);
1031
1032 public:
1033
1034
1035 Selector() = default;
1036 explicit Selector(uintptr_t V) {
1037 InfoPtr.setFromOpaqueValue(reinterpret_cast<void *>(V));
1038 }
1039
1040
1041 bool operator==(Selector RHS) const {
1042 return InfoPtr.getOpaqueValue() == RHS.InfoPtr.getOpaqueValue();
1043 }
1044 bool operator!=(Selector RHS) const {
1045 return InfoPtr.getOpaqueValue() != RHS.InfoPtr.getOpaqueValue();
1046 }
1047
1048 void *getAsOpaquePtr() const { return InfoPtr.getOpaqueValue(); }
1049
1050
1051 bool isNull() const { return InfoPtr.getOpaqueValue() == nullptr; }
1052
1053
1054 bool isKeywordSelector() const { return InfoPtr.getInt() != ZeroArg; }
1055
1056 bool isUnarySelector() const { return InfoPtr.getInt() == ZeroArg; }
1057
1058
1059 bool isKeywordSelector(ArrayRef<StringRef> Names) const;
1060
1061
1062 bool isUnarySelector(StringRef Name) const;
1063
1064 unsigned getNumArgs() const;
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079 const IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 StringRef getNameForSlot(unsigned argIndex) const;
1090
1091
1092
1093 std::string getAsString() const;
1094
1095
1096 void print(llvm::raw_ostream &OS) const;
1097
1098 void dump() const;
1099
1100
1101 ObjCMethodFamily getMethodFamily() const {
1102 return getMethodFamilyImpl(*this);
1103 }
1104
1105 ObjCStringFormatFamily getStringFormatFamily() const {
1106 return getStringFormatFamilyImpl(*this);
1107 }
1108
1109 static Selector getEmptyMarker() {
1110 return Selector(uintptr_t(-1));
1111 }
1112
1113 static Selector getTombstoneMarker() {
1114 return Selector(uintptr_t(-2));
1115 }
1116
1117 static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel);
1118 };
1119
1120
1121
1122 class SelectorTable {
1123
1124 void *Impl;
1125
1126 public:
1127 SelectorTable();
1128 SelectorTable(const SelectorTable &) = delete;
1129 SelectorTable &operator=(const SelectorTable &) = delete;
1130 ~SelectorTable();
1131
1132
1133
1134
1135
1136 Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV);
1137
1138 Selector getUnarySelector(const IdentifierInfo *ID) {
1139 return Selector(ID, 1);
1140 }
1141
1142 Selector getNullarySelector(const IdentifierInfo *ID) {
1143 return Selector(ID, 0);
1144 }
1145
1146
1147 size_t getTotalMemory() const;
1148
1149
1150
1151
1152
1153 static SmallString<64> constructSetterName(StringRef Name);
1154
1155
1156
1157
1158
1159 static Selector constructSetterSelector(IdentifierTable &Idents,
1160 SelectorTable &SelTable,
1161 const IdentifierInfo *Name);
1162
1163
1164 static std::string getPropertyNameFromSetterSelector(Selector Sel);
1165 };
1166
1167 }
1168
1169 namespace llvm {
1170
1171
1172
1173 template <>
1174 struct DenseMapInfo<clang::Selector> {
1175 static clang::Selector getEmptyKey() {
1176 return clang::Selector::getEmptyMarker();
1177 }
1178
1179 static clang::Selector getTombstoneKey() {
1180 return clang::Selector::getTombstoneMarker();
1181 }
1182
1183 static unsigned getHashValue(clang::Selector S);
1184
1185 static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
1186 return LHS == RHS;
1187 }
1188 };
1189
1190 template<>
1191 struct PointerLikeTypeTraits<clang::Selector> {
1192 static const void *getAsVoidPointer(clang::Selector P) {
1193 return P.getAsOpaquePtr();
1194 }
1195
1196 static clang::Selector getFromVoidPointer(const void *P) {
1197 return clang::Selector(reinterpret_cast<uintptr_t>(P));
1198 }
1199
1200 static constexpr int NumLowBitsAvailable = 0;
1201 };
1202
1203 }
1204
1205 #endif