10b57cec5SDimitry Andric //===- IdentifierTable.h - Hash table for identifier lookup -----*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Defines the clang::IdentifierInfo, clang::IdentifierTable, and
110b57cec5SDimitry Andric /// clang::Selector interfaces.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #ifndef LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
160b57cec5SDimitry Andric #define LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
170b57cec5SDimitry Andric 
18bdd1243dSDimitry Andric #include "clang/Basic/DiagnosticIDs.h"
190b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
200b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
210b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
225f757f3fSDimitry Andric #include "llvm/ADT/FoldingSet.h"
235f757f3fSDimitry Andric #include "llvm/ADT/PointerIntPair.h"
245f757f3fSDimitry Andric #include "llvm/ADT/PointerUnion.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
270b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
280b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
290b57cec5SDimitry Andric #include "llvm/Support/PointerLikeTypeTraits.h"
300b57cec5SDimitry Andric #include "llvm/Support/type_traits.h"
310b57cec5SDimitry Andric #include <cassert>
320b57cec5SDimitry Andric #include <cstddef>
330b57cec5SDimitry Andric #include <cstdint>
340b57cec5SDimitry Andric #include <cstring>
350b57cec5SDimitry Andric #include <string>
360b57cec5SDimitry Andric #include <utility>
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric namespace clang {
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric class DeclarationName;
410b57cec5SDimitry Andric class DeclarationNameTable;
420b57cec5SDimitry Andric class IdentifierInfo;
430b57cec5SDimitry Andric class LangOptions;
440b57cec5SDimitry Andric class MultiKeywordSelector;
450b57cec5SDimitry Andric class SourceLocation;
460b57cec5SDimitry Andric 
47fe6060f1SDimitry Andric enum class ReservedIdentifierStatus {
48fe6060f1SDimitry Andric   NotReserved = 0,
49fe6060f1SDimitry Andric   StartsWithUnderscoreAtGlobalScope,
50349cc55cSDimitry Andric   StartsWithUnderscoreAndIsExternC,
51fe6060f1SDimitry Andric   StartsWithDoubleUnderscore,
52fe6060f1SDimitry Andric   StartsWithUnderscoreFollowedByCapitalLetter,
53fe6060f1SDimitry Andric   ContainsDoubleUnderscore,
54fe6060f1SDimitry Andric };
55fe6060f1SDimitry Andric 
5606c3fb27SDimitry Andric enum class ReservedLiteralSuffixIdStatus {
5706c3fb27SDimitry Andric   NotReserved = 0,
5806c3fb27SDimitry Andric   NotStartsWithUnderscore,
5906c3fb27SDimitry Andric   ContainsDoubleUnderscore,
6006c3fb27SDimitry Andric };
6106c3fb27SDimitry Andric 
62349cc55cSDimitry Andric /// Determine whether an identifier is reserved for use as a name at global
63349cc55cSDimitry Andric /// scope. Such identifiers might be implementation-specific global functions
64349cc55cSDimitry Andric /// or variables.
isReservedAtGlobalScope(ReservedIdentifierStatus Status)65349cc55cSDimitry Andric inline bool isReservedAtGlobalScope(ReservedIdentifierStatus Status) {
66349cc55cSDimitry Andric   return Status != ReservedIdentifierStatus::NotReserved;
67349cc55cSDimitry Andric }
68349cc55cSDimitry Andric 
69349cc55cSDimitry Andric /// Determine whether an identifier is reserved in all contexts. Such
70349cc55cSDimitry Andric /// identifiers might be implementation-specific keywords or macros, for
71349cc55cSDimitry Andric /// example.
isReservedInAllContexts(ReservedIdentifierStatus Status)72349cc55cSDimitry Andric inline bool isReservedInAllContexts(ReservedIdentifierStatus Status) {
73349cc55cSDimitry Andric   return Status != ReservedIdentifierStatus::NotReserved &&
74349cc55cSDimitry Andric          Status != ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope &&
75349cc55cSDimitry Andric          Status != ReservedIdentifierStatus::StartsWithUnderscoreAndIsExternC;
76349cc55cSDimitry Andric }
77349cc55cSDimitry Andric 
780b57cec5SDimitry Andric /// A simple pair of identifier info and location.
790b57cec5SDimitry Andric using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>;
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric /// IdentifierInfo and other related classes are aligned to
820b57cec5SDimitry Andric /// 8 bytes so that DeclarationName can use the lower 3 bits
830b57cec5SDimitry Andric /// of a pointer to one of these classes.
840b57cec5SDimitry Andric enum { IdentifierInfoAlignment = 8 };
850b57cec5SDimitry Andric 
86fe6060f1SDimitry Andric static constexpr int ObjCOrBuiltinIDBits = 16;
875ffd83dbSDimitry Andric 
8806c3fb27SDimitry Andric /// The "layout" of ObjCOrBuiltinID is:
8906c3fb27SDimitry Andric ///  - The first value (0) represents "not a special identifier".
9006c3fb27SDimitry Andric ///  - The next (NUM_OBJC_KEYWORDS - 1) values represent ObjCKeywordKinds (not
9106c3fb27SDimitry Andric ///    including objc_not_keyword).
9206c3fb27SDimitry Andric ///  - The next (NUM_INTERESTING_IDENTIFIERS - 1) values represent
9306c3fb27SDimitry Andric ///    InterestingIdentifierKinds (not including not_interesting).
9406c3fb27SDimitry Andric ///  - The rest of the values represent builtin IDs (not including NotBuiltin).
9506c3fb27SDimitry Andric static constexpr int FirstObjCKeywordID = 1;
9606c3fb27SDimitry Andric static constexpr int LastObjCKeywordID =
9706c3fb27SDimitry Andric     FirstObjCKeywordID + tok::NUM_OBJC_KEYWORDS - 2;
9806c3fb27SDimitry Andric static constexpr int FirstInterestingIdentifierID = LastObjCKeywordID + 1;
9906c3fb27SDimitry Andric static constexpr int LastInterestingIdentifierID =
10006c3fb27SDimitry Andric     FirstInterestingIdentifierID + tok::NUM_INTERESTING_IDENTIFIERS - 2;
10106c3fb27SDimitry Andric static constexpr int FirstBuiltinID = LastInterestingIdentifierID + 1;
10206c3fb27SDimitry Andric 
1030b57cec5SDimitry Andric /// One of these records is kept for each identifier that
1040b57cec5SDimitry Andric /// is lexed.  This contains information about whether the token was \#define'd,
1050b57cec5SDimitry Andric /// is a language keyword, or if it is a front-end token of some sort (e.g. a
1060b57cec5SDimitry Andric /// variable or function name).  The preprocessor keeps this information in a
1070b57cec5SDimitry Andric /// set, and all tok::identifier tokens have a pointer to one of these.
1080b57cec5SDimitry Andric /// It is aligned to 8 bytes because DeclarationName needs the lower 3 bits.
alignas(IdentifierInfoAlignment)1090b57cec5SDimitry Andric class alignas(IdentifierInfoAlignment) IdentifierInfo {
1100b57cec5SDimitry Andric   friend class IdentifierTable;
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   // Front-end token ID or tok::identifier.
1135f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(tok::TokenKind)
1140b57cec5SDimitry Andric   unsigned TokenID : 9;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   // ObjC keyword ('protocol' in '@protocol') or builtin (__builtin_inf).
1170b57cec5SDimitry Andric   // First NUM_OBJC_KEYWORDS values are for Objective-C,
1180b57cec5SDimitry Andric   // the remaining values are for builtins.
1195ffd83dbSDimitry Andric   unsigned ObjCOrBuiltinID : ObjCOrBuiltinIDBits;
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   // True if there is a #define for this.
1225f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1230b57cec5SDimitry Andric   unsigned HasMacro : 1;
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // True if there was a #define for this.
1265f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1270b57cec5SDimitry Andric   unsigned HadMacro : 1;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // True if the identifier is a language extension.
1305f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1310b57cec5SDimitry Andric   unsigned IsExtension : 1;
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   // True if the identifier is a keyword in a newer or proposed Standard.
1345f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1350b57cec5SDimitry Andric   unsigned IsFutureCompatKeyword : 1;
1360b57cec5SDimitry Andric 
1370b57cec5SDimitry Andric   // True if the identifier is poisoned.
1385f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1390b57cec5SDimitry Andric   unsigned IsPoisoned : 1;
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric   // True if the identifier is a C++ operator keyword.
1425f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1430b57cec5SDimitry Andric   unsigned IsCPPOperatorKeyword : 1;
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric   // Internal bit set by the member function RecomputeNeedsHandleIdentifier.
1460b57cec5SDimitry Andric   // See comment about RecomputeNeedsHandleIdentifier for more info.
1475f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1480b57cec5SDimitry Andric   unsigned NeedsHandleIdentifier : 1;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   // True if the identifier was loaded (at least partially) from an AST file.
1515f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1520b57cec5SDimitry Andric   unsigned IsFromAST : 1;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   // True if the identifier has changed from the definition
1550b57cec5SDimitry Andric   // loaded from an AST file.
1565f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1570b57cec5SDimitry Andric   unsigned ChangedAfterLoad : 1;
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric   // True if the identifier's frontend information has changed from the
1600b57cec5SDimitry Andric   // definition loaded from an AST file.
1615f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1620b57cec5SDimitry Andric   unsigned FEChangedAfterLoad : 1;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   // True if revertTokenIDToIdentifier was called.
1655f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1660b57cec5SDimitry Andric   unsigned RevertedTokenID : 1;
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   // True if there may be additional information about
1690b57cec5SDimitry Andric   // this identifier stored externally.
1705f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1710b57cec5SDimitry Andric   unsigned OutOfDate : 1;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   // True if this is the 'import' contextual keyword.
1745f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1750b57cec5SDimitry Andric   unsigned IsModulesImport : 1;
1760b57cec5SDimitry Andric 
1775ffd83dbSDimitry Andric   // True if this is a mangled OpenMP variant name.
1785f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
1795ffd83dbSDimitry Andric   unsigned IsMangledOpenMPVariantName : 1;
1805ffd83dbSDimitry Andric 
181349cc55cSDimitry Andric   // True if this is a deprecated macro.
1825f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
183349cc55cSDimitry Andric   unsigned IsDeprecatedMacro : 1;
184349cc55cSDimitry Andric 
185349cc55cSDimitry Andric   // True if this macro is unsafe in headers.
1865f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
187349cc55cSDimitry Andric   unsigned IsRestrictExpansion : 1;
188349cc55cSDimitry Andric 
189349cc55cSDimitry Andric   // True if this macro is final.
1905f757f3fSDimitry Andric   LLVM_PREFERRED_TYPE(bool)
191349cc55cSDimitry Andric   unsigned IsFinal : 1;
192349cc55cSDimitry Andric 
193349cc55cSDimitry Andric   // 22 bits left in a 64-bit word.
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   // Managed by the language front-end.
1960b57cec5SDimitry Andric   void *FETokenInfo = nullptr;
1970b57cec5SDimitry Andric 
1980b57cec5SDimitry Andric   llvm::StringMapEntry<IdentifierInfo *> *Entry = nullptr;
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   IdentifierInfo()
2010b57cec5SDimitry Andric       : TokenID(tok::identifier), ObjCOrBuiltinID(0), HasMacro(false),
2020b57cec5SDimitry Andric         HadMacro(false), IsExtension(false), IsFutureCompatKeyword(false),
2030b57cec5SDimitry Andric         IsPoisoned(false), IsCPPOperatorKeyword(false),
2040b57cec5SDimitry Andric         NeedsHandleIdentifier(false), IsFromAST(false), ChangedAfterLoad(false),
2050b57cec5SDimitry Andric         FEChangedAfterLoad(false), RevertedTokenID(false), OutOfDate(false),
206349cc55cSDimitry Andric         IsModulesImport(false), IsMangledOpenMPVariantName(false),
207349cc55cSDimitry Andric         IsDeprecatedMacro(false), IsRestrictExpansion(false), IsFinal(false) {}
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric public:
2100b57cec5SDimitry Andric   IdentifierInfo(const IdentifierInfo &) = delete;
2110b57cec5SDimitry Andric   IdentifierInfo &operator=(const IdentifierInfo &) = delete;
2120b57cec5SDimitry Andric   IdentifierInfo(IdentifierInfo &&) = delete;
2130b57cec5SDimitry Andric   IdentifierInfo &operator=(IdentifierInfo &&) = delete;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   /// Return true if this is the identifier for the specified string.
2160b57cec5SDimitry Andric   ///
2170b57cec5SDimitry Andric   /// This is intended to be used for string literals only: II->isStr("foo").
2180b57cec5SDimitry Andric   template <std::size_t StrLen>
2190b57cec5SDimitry Andric   bool isStr(const char (&Str)[StrLen]) const {
2200b57cec5SDimitry Andric     return getLength() == StrLen-1 &&
2210b57cec5SDimitry Andric            memcmp(getNameStart(), Str, StrLen-1) == 0;
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric   /// Return true if this is the identifier for the specified StringRef.
2250b57cec5SDimitry Andric   bool isStr(llvm::StringRef Str) const {
2260b57cec5SDimitry Andric     llvm::StringRef ThisStr(getNameStart(), getLength());
2270b57cec5SDimitry Andric     return ThisStr == Str;
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   /// Return the beginning of the actual null-terminated string for this
2310b57cec5SDimitry Andric   /// identifier.
2320b57cec5SDimitry Andric   const char *getNameStart() const { return Entry->getKeyData(); }
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   /// Efficiently return the length of this identifier info.
2350b57cec5SDimitry Andric   unsigned getLength() const { return Entry->getKeyLength(); }
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   /// Return the actual identifier string.
2380b57cec5SDimitry Andric   StringRef getName() const {
2390b57cec5SDimitry Andric     return StringRef(getNameStart(), getLength());
2400b57cec5SDimitry Andric   }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   /// Return true if this identifier is \#defined to some other value.
2430b57cec5SDimitry Andric   /// \note The current definition may be in a module and not currently visible.
2440b57cec5SDimitry Andric   bool hasMacroDefinition() const {
2450b57cec5SDimitry Andric     return HasMacro;
2460b57cec5SDimitry Andric   }
2470b57cec5SDimitry Andric   void setHasMacroDefinition(bool Val) {
2480b57cec5SDimitry Andric     if (HasMacro == Val) return;
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric     HasMacro = Val;
2510b57cec5SDimitry Andric     if (Val) {
2520b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
2530b57cec5SDimitry Andric       HadMacro = true;
2540b57cec5SDimitry Andric     } else {
255349cc55cSDimitry Andric       // If this is a final macro, make the deprecation and header unsafe bits
256349cc55cSDimitry Andric       // stick around after the undefinition so they apply to any redefinitions.
257349cc55cSDimitry Andric       if (!IsFinal) {
258349cc55cSDimitry Andric         // Because calling the setters of these calls recomputes, just set them
259349cc55cSDimitry Andric         // manually to avoid recomputing a bunch of times.
260349cc55cSDimitry Andric         IsDeprecatedMacro = false;
261349cc55cSDimitry Andric         IsRestrictExpansion = false;
262349cc55cSDimitry Andric       }
2630b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
2640b57cec5SDimitry Andric     }
2650b57cec5SDimitry Andric   }
2660b57cec5SDimitry Andric   /// Returns true if this identifier was \#defined to some value at any
2670b57cec5SDimitry Andric   /// moment. In this case there should be an entry for the identifier in the
2680b57cec5SDimitry Andric   /// macro history table in Preprocessor.
2690b57cec5SDimitry Andric   bool hadMacroDefinition() const {
2700b57cec5SDimitry Andric     return HadMacro;
2710b57cec5SDimitry Andric   }
2720b57cec5SDimitry Andric 
273349cc55cSDimitry Andric   bool isDeprecatedMacro() const { return IsDeprecatedMacro; }
274349cc55cSDimitry Andric 
275349cc55cSDimitry Andric   void setIsDeprecatedMacro(bool Val) {
276349cc55cSDimitry Andric     if (IsDeprecatedMacro == Val)
277349cc55cSDimitry Andric       return;
278349cc55cSDimitry Andric     IsDeprecatedMacro = Val;
279349cc55cSDimitry Andric     if (Val)
280349cc55cSDimitry Andric       NeedsHandleIdentifier = true;
281349cc55cSDimitry Andric     else
282349cc55cSDimitry Andric       RecomputeNeedsHandleIdentifier();
283349cc55cSDimitry Andric   }
284349cc55cSDimitry Andric 
285349cc55cSDimitry Andric   bool isRestrictExpansion() const { return IsRestrictExpansion; }
286349cc55cSDimitry Andric 
287349cc55cSDimitry Andric   void setIsRestrictExpansion(bool Val) {
288349cc55cSDimitry Andric     if (IsRestrictExpansion == Val)
289349cc55cSDimitry Andric       return;
290349cc55cSDimitry Andric     IsRestrictExpansion = Val;
291349cc55cSDimitry Andric     if (Val)
292349cc55cSDimitry Andric       NeedsHandleIdentifier = true;
293349cc55cSDimitry Andric     else
294349cc55cSDimitry Andric       RecomputeNeedsHandleIdentifier();
295349cc55cSDimitry Andric   }
296349cc55cSDimitry Andric 
297349cc55cSDimitry Andric   bool isFinal() const { return IsFinal; }
298349cc55cSDimitry Andric 
299349cc55cSDimitry Andric   void setIsFinal(bool Val) { IsFinal = Val; }
300349cc55cSDimitry Andric 
3010b57cec5SDimitry Andric   /// If this is a source-language token (e.g. 'for'), this API
3020b57cec5SDimitry Andric   /// can be used to cause the lexer to map identifiers to source-language
3030b57cec5SDimitry Andric   /// tokens.
3040b57cec5SDimitry Andric   tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; }
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   /// True if revertTokenIDToIdentifier() was called.
3070b57cec5SDimitry Andric   bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   /// Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2
3100b57cec5SDimitry Andric   /// compatibility.
3110b57cec5SDimitry Andric   ///
3120b57cec5SDimitry Andric   /// TokenID is normally read-only but there are 2 instances where we revert it
3130b57cec5SDimitry Andric   /// to tok::identifier for libstdc++ 4.2. Keep track of when this happens
3140b57cec5SDimitry Andric   /// using this method so we can inform serialization about it.
3150b57cec5SDimitry Andric   void revertTokenIDToIdentifier() {
3160b57cec5SDimitry Andric     assert(TokenID != tok::identifier && "Already at tok::identifier");
3170b57cec5SDimitry Andric     TokenID = tok::identifier;
3180b57cec5SDimitry Andric     RevertedTokenID = true;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric   void revertIdentifierToTokenID(tok::TokenKind TK) {
3210b57cec5SDimitry Andric     assert(TokenID == tok::identifier && "Should be at tok::identifier");
3220b57cec5SDimitry Andric     TokenID = TK;
3230b57cec5SDimitry Andric     RevertedTokenID = false;
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   /// Return the preprocessor keyword ID for this identifier.
3270b57cec5SDimitry Andric   ///
3280b57cec5SDimitry Andric   /// For example, "define" will return tok::pp_define.
3290b57cec5SDimitry Andric   tok::PPKeywordKind getPPKeywordID() const;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   /// Return the Objective-C keyword ID for the this identifier.
3320b57cec5SDimitry Andric   ///
3330b57cec5SDimitry Andric   /// For example, 'class' will return tok::objc_class if ObjC is enabled.
3340b57cec5SDimitry Andric   tok::ObjCKeywordKind getObjCKeywordID() const {
33506c3fb27SDimitry Andric     static_assert(FirstObjCKeywordID == 1,
33606c3fb27SDimitry Andric                   "hard-coding this assumption to simplify code");
33706c3fb27SDimitry Andric     if (ObjCOrBuiltinID <= LastObjCKeywordID)
3380b57cec5SDimitry Andric       return tok::ObjCKeywordKind(ObjCOrBuiltinID);
3390b57cec5SDimitry Andric     else
3400b57cec5SDimitry Andric       return tok::objc_not_keyword;
3410b57cec5SDimitry Andric   }
3420b57cec5SDimitry Andric   void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; }
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   /// Return a value indicating whether this is a builtin function.
3450b57cec5SDimitry Andric   ///
3460b57cec5SDimitry Andric   /// 0 is not-built-in. 1+ are specific builtin functions.
3470b57cec5SDimitry Andric   unsigned getBuiltinID() const {
34806c3fb27SDimitry Andric     if (ObjCOrBuiltinID >= FirstBuiltinID)
34906c3fb27SDimitry Andric       return 1 + (ObjCOrBuiltinID - FirstBuiltinID);
3500b57cec5SDimitry Andric     else
3510b57cec5SDimitry Andric       return 0;
3520b57cec5SDimitry Andric   }
3530b57cec5SDimitry Andric   void setBuiltinID(unsigned ID) {
35406c3fb27SDimitry Andric     assert(ID != 0);
35506c3fb27SDimitry Andric     ObjCOrBuiltinID = FirstBuiltinID + (ID - 1);
35606c3fb27SDimitry Andric     assert(getBuiltinID() == ID && "ID too large for field!");
35706c3fb27SDimitry Andric   }
35806c3fb27SDimitry Andric   void clearBuiltinID() { ObjCOrBuiltinID = 0; }
35906c3fb27SDimitry Andric 
36006c3fb27SDimitry Andric   tok::InterestingIdentifierKind getInterestingIdentifierID() const {
36106c3fb27SDimitry Andric     if (ObjCOrBuiltinID >= FirstInterestingIdentifierID &&
36206c3fb27SDimitry Andric         ObjCOrBuiltinID <= LastInterestingIdentifierID)
36306c3fb27SDimitry Andric       return tok::InterestingIdentifierKind(
36406c3fb27SDimitry Andric           1 + (ObjCOrBuiltinID - FirstInterestingIdentifierID));
36506c3fb27SDimitry Andric     else
36606c3fb27SDimitry Andric       return tok::not_interesting;
36706c3fb27SDimitry Andric   }
36806c3fb27SDimitry Andric   void setInterestingIdentifierID(unsigned ID) {
36906c3fb27SDimitry Andric     assert(ID != tok::not_interesting);
37006c3fb27SDimitry Andric     ObjCOrBuiltinID = FirstInterestingIdentifierID + (ID - 1);
37106c3fb27SDimitry Andric     assert(getInterestingIdentifierID() == ID && "ID too large for field!");
3720b57cec5SDimitry Andric   }
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   unsigned getObjCOrBuiltinID() const { return ObjCOrBuiltinID; }
3750b57cec5SDimitry Andric   void setObjCOrBuiltinID(unsigned ID) { ObjCOrBuiltinID = ID; }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   /// get/setExtension - Initialize information about whether or not this
3780b57cec5SDimitry Andric   /// language token is an extension.  This controls extension warnings, and is
3790b57cec5SDimitry Andric   /// only valid if a custom token ID is set.
3800b57cec5SDimitry Andric   bool isExtensionToken() const { return IsExtension; }
3810b57cec5SDimitry Andric   void setIsExtensionToken(bool Val) {
3820b57cec5SDimitry Andric     IsExtension = Val;
3830b57cec5SDimitry Andric     if (Val)
3840b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
3850b57cec5SDimitry Andric     else
3860b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
3870b57cec5SDimitry Andric   }
3880b57cec5SDimitry Andric 
3890b57cec5SDimitry Andric   /// is/setIsFutureCompatKeyword - Initialize information about whether or not
3900b57cec5SDimitry Andric   /// this language token is a keyword in a newer or proposed Standard. This
3910b57cec5SDimitry Andric   /// controls compatibility warnings, and is only true when not parsing the
3920b57cec5SDimitry Andric   /// corresponding Standard. Once a compatibility problem has been diagnosed
3930b57cec5SDimitry Andric   /// with this keyword, the flag will be cleared.
3940b57cec5SDimitry Andric   bool isFutureCompatKeyword() const { return IsFutureCompatKeyword; }
3950b57cec5SDimitry Andric   void setIsFutureCompatKeyword(bool Val) {
3960b57cec5SDimitry Andric     IsFutureCompatKeyword = Val;
3970b57cec5SDimitry Andric     if (Val)
3980b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
3990b57cec5SDimitry Andric     else
4000b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
4010b57cec5SDimitry Andric   }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   /// setIsPoisoned - Mark this identifier as poisoned.  After poisoning, the
4040b57cec5SDimitry Andric   /// Preprocessor will emit an error every time this token is used.
4050b57cec5SDimitry Andric   void setIsPoisoned(bool Value = true) {
4060b57cec5SDimitry Andric     IsPoisoned = Value;
4070b57cec5SDimitry Andric     if (Value)
4080b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
4090b57cec5SDimitry Andric     else
4100b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   /// Return true if this token has been poisoned.
4140b57cec5SDimitry Andric   bool isPoisoned() const { return IsPoisoned; }
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether
4170b57cec5SDimitry Andric   /// this identifier is a C++ alternate representation of an operator.
4180b57cec5SDimitry Andric   void setIsCPlusPlusOperatorKeyword(bool Val = true) {
4190b57cec5SDimitry Andric     IsCPPOperatorKeyword = Val;
4200b57cec5SDimitry Andric   }
4210b57cec5SDimitry Andric   bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   /// Return true if this token is a keyword in the specified language.
4240b57cec5SDimitry Andric   bool isKeyword(const LangOptions &LangOpts) const;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   /// Return true if this token is a C++ keyword in the specified
4270b57cec5SDimitry Andric   /// language.
4280b57cec5SDimitry Andric   bool isCPlusPlusKeyword(const LangOptions &LangOpts) const;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   /// Get and set FETokenInfo. The language front-end is allowed to associate
4310b57cec5SDimitry Andric   /// arbitrary metadata with this token.
4320b57cec5SDimitry Andric   void *getFETokenInfo() const { return FETokenInfo; }
4330b57cec5SDimitry Andric   void setFETokenInfo(void *T) { FETokenInfo = T; }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   /// Return true if the Preprocessor::HandleIdentifier must be called
4360b57cec5SDimitry Andric   /// on a token of this identifier.
4370b57cec5SDimitry Andric   ///
4380b57cec5SDimitry Andric   /// If this returns false, we know that HandleIdentifier will not affect
4390b57cec5SDimitry Andric   /// the token.
4400b57cec5SDimitry Andric   bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   /// Return true if the identifier in its current state was loaded
4430b57cec5SDimitry Andric   /// from an AST file.
4440b57cec5SDimitry Andric   bool isFromAST() const { return IsFromAST; }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric   void setIsFromAST() { IsFromAST = true; }
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   /// Determine whether this identifier has changed since it was loaded
4490b57cec5SDimitry Andric   /// from an AST file.
4500b57cec5SDimitry Andric   bool hasChangedSinceDeserialization() const {
4510b57cec5SDimitry Andric     return ChangedAfterLoad;
4520b57cec5SDimitry Andric   }
4530b57cec5SDimitry Andric 
4540b57cec5SDimitry Andric   /// Note that this identifier has changed since it was loaded from
4550b57cec5SDimitry Andric   /// an AST file.
4560b57cec5SDimitry Andric   void setChangedSinceDeserialization() {
4570b57cec5SDimitry Andric     ChangedAfterLoad = true;
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   /// Determine whether the frontend token information for this
4610b57cec5SDimitry Andric   /// identifier has changed since it was loaded from an AST file.
4620b57cec5SDimitry Andric   bool hasFETokenInfoChangedSinceDeserialization() const {
4630b57cec5SDimitry Andric     return FEChangedAfterLoad;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   /// Note that the frontend token information for this identifier has
4670b57cec5SDimitry Andric   /// changed since it was loaded from an AST file.
4680b57cec5SDimitry Andric   void setFETokenInfoChangedSinceDeserialization() {
4690b57cec5SDimitry Andric     FEChangedAfterLoad = true;
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric 
4720b57cec5SDimitry Andric   /// Determine whether the information for this identifier is out of
4730b57cec5SDimitry Andric   /// date with respect to the external source.
4740b57cec5SDimitry Andric   bool isOutOfDate() const { return OutOfDate; }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   /// Set whether the information for this identifier is out of
4770b57cec5SDimitry Andric   /// date with respect to the external source.
4780b57cec5SDimitry Andric   void setOutOfDate(bool OOD) {
4790b57cec5SDimitry Andric     OutOfDate = OOD;
4800b57cec5SDimitry Andric     if (OOD)
4810b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
4820b57cec5SDimitry Andric     else
4830b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
4840b57cec5SDimitry Andric   }
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   /// Determine whether this is the contextual keyword \c import.
4870b57cec5SDimitry Andric   bool isModulesImport() const { return IsModulesImport; }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   /// Set whether this identifier is the contextual keyword \c import.
4900b57cec5SDimitry Andric   void setModulesImport(bool I) {
4910b57cec5SDimitry Andric     IsModulesImport = I;
4920b57cec5SDimitry Andric     if (I)
4930b57cec5SDimitry Andric       NeedsHandleIdentifier = true;
4940b57cec5SDimitry Andric     else
4950b57cec5SDimitry Andric       RecomputeNeedsHandleIdentifier();
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric 
4985ffd83dbSDimitry Andric   /// Determine whether this is the mangled name of an OpenMP variant.
4995ffd83dbSDimitry Andric   bool isMangledOpenMPVariantName() const { return IsMangledOpenMPVariantName; }
5005ffd83dbSDimitry Andric 
5015ffd83dbSDimitry Andric   /// Set whether this is the mangled name of an OpenMP variant.
5025ffd83dbSDimitry Andric   void setMangledOpenMPVariantName(bool I) { IsMangledOpenMPVariantName = I; }
5035ffd83dbSDimitry Andric 
5040b57cec5SDimitry Andric   /// Return true if this identifier is an editor placeholder.
5050b57cec5SDimitry Andric   ///
5060b57cec5SDimitry Andric   /// Editor placeholders are produced by the code-completion engine and are
5070b57cec5SDimitry Andric   /// represented as characters between '<#' and '#>' in the source code. An
5080b57cec5SDimitry Andric   /// example of auto-completed call with a placeholder parameter is shown
5090b57cec5SDimitry Andric   /// below:
5100b57cec5SDimitry Andric   /// \code
5110b57cec5SDimitry Andric   ///   function(<#int x#>);
5120b57cec5SDimitry Andric   /// \endcode
5130b57cec5SDimitry Andric   bool isEditorPlaceholder() const {
5145f757f3fSDimitry Andric     return getName().starts_with("<#") && getName().ends_with("#>");
5150b57cec5SDimitry Andric   }
5160b57cec5SDimitry Andric 
517480093f4SDimitry Andric   /// Determine whether \p this is a name reserved for the implementation (C99
518480093f4SDimitry Andric   /// 7.1.3, C++ [lib.global.names]).
519fe6060f1SDimitry Andric   ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
520480093f4SDimitry Andric 
52106c3fb27SDimitry Andric   /// Determine whether \p this is a name reserved for future standardization or
52206c3fb27SDimitry Andric   /// the implementation (C++ [usrlit.suffix]).
52306c3fb27SDimitry Andric   ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const;
52406c3fb27SDimitry Andric 
52504eeddc0SDimitry Andric   /// If the identifier is an "uglified" reserved name, return a cleaned form.
52604eeddc0SDimitry Andric   /// e.g. _Foo => Foo. Otherwise, just returns the name.
52704eeddc0SDimitry Andric   StringRef deuglifiedName() const;
5285f757f3fSDimitry Andric   bool isPlaceholder() const {
5295f757f3fSDimitry Andric     return getLength() == 1 && getNameStart()[0] == '_';
5305f757f3fSDimitry Andric   }
53104eeddc0SDimitry Andric 
5320b57cec5SDimitry Andric   /// Provide less than operator for lexicographical sorting.
5330b57cec5SDimitry Andric   bool operator<(const IdentifierInfo &RHS) const {
5340b57cec5SDimitry Andric     return getName() < RHS.getName();
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric private:
5380b57cec5SDimitry Andric   /// The Preprocessor::HandleIdentifier does several special (but rare)
5390b57cec5SDimitry Andric   /// things to identifiers of various sorts.  For example, it changes the
5400b57cec5SDimitry Andric   /// \c for keyword token from tok::identifier to tok::for.
5410b57cec5SDimitry Andric   ///
5420b57cec5SDimitry Andric   /// This method is very tied to the definition of HandleIdentifier.  Any
5430b57cec5SDimitry Andric   /// change to it should be reflected here.
5440b57cec5SDimitry Andric   void RecomputeNeedsHandleIdentifier() {
5450b57cec5SDimitry Andric     NeedsHandleIdentifier = isPoisoned() || hasMacroDefinition() ||
5460b57cec5SDimitry Andric                             isExtensionToken() || isFutureCompatKeyword() ||
5470b57cec5SDimitry Andric                             isOutOfDate() || isModulesImport();
5480b57cec5SDimitry Andric   }
5490b57cec5SDimitry Andric };
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric /// An RAII object for [un]poisoning an identifier within a scope.
5520b57cec5SDimitry Andric ///
5530b57cec5SDimitry Andric /// \p II is allowed to be null, in which case objects of this type have
5540b57cec5SDimitry Andric /// no effect.
5550b57cec5SDimitry Andric class PoisonIdentifierRAIIObject {
5560b57cec5SDimitry Andric   IdentifierInfo *const II;
5570b57cec5SDimitry Andric   const bool OldValue;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric public:
PoisonIdentifierRAIIObject(IdentifierInfo * II,bool NewValue)5600b57cec5SDimitry Andric   PoisonIdentifierRAIIObject(IdentifierInfo *II, bool NewValue)
5610b57cec5SDimitry Andric     : II(II), OldValue(II ? II->isPoisoned() : false) {
5620b57cec5SDimitry Andric     if(II)
5630b57cec5SDimitry Andric       II->setIsPoisoned(NewValue);
5640b57cec5SDimitry Andric   }
5650b57cec5SDimitry Andric 
~PoisonIdentifierRAIIObject()5660b57cec5SDimitry Andric   ~PoisonIdentifierRAIIObject() {
5670b57cec5SDimitry Andric     if(II)
5680b57cec5SDimitry Andric       II->setIsPoisoned(OldValue);
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric };
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric /// An iterator that walks over all of the known identifiers
5730b57cec5SDimitry Andric /// in the lookup table.
5740b57cec5SDimitry Andric ///
5750b57cec5SDimitry Andric /// Since this iterator uses an abstract interface via virtual
5760b57cec5SDimitry Andric /// functions, it uses an object-oriented interface rather than the
5770b57cec5SDimitry Andric /// more standard C++ STL iterator interface. In this OO-style
5780b57cec5SDimitry Andric /// iteration, the single function \c Next() provides dereference,
5790b57cec5SDimitry Andric /// advance, and end-of-sequence checking in a single
5800b57cec5SDimitry Andric /// operation. Subclasses of this iterator type will provide the
5810b57cec5SDimitry Andric /// actual functionality.
5820b57cec5SDimitry Andric class IdentifierIterator {
5830b57cec5SDimitry Andric protected:
5840b57cec5SDimitry Andric   IdentifierIterator() = default;
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric public:
5870b57cec5SDimitry Andric   IdentifierIterator(const IdentifierIterator &) = delete;
5880b57cec5SDimitry Andric   IdentifierIterator &operator=(const IdentifierIterator &) = delete;
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   virtual ~IdentifierIterator();
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric   /// Retrieve the next string in the identifier table and
5930b57cec5SDimitry Andric   /// advances the iterator for the following string.
5940b57cec5SDimitry Andric   ///
5950b57cec5SDimitry Andric   /// \returns The next string in the identifier table. If there is
5960b57cec5SDimitry Andric   /// no such string, returns an empty \c StringRef.
5970b57cec5SDimitry Andric   virtual StringRef Next() = 0;
5980b57cec5SDimitry Andric };
5990b57cec5SDimitry Andric 
6000b57cec5SDimitry Andric /// Provides lookups to, and iteration over, IdentiferInfo objects.
6010b57cec5SDimitry Andric class IdentifierInfoLookup {
6020b57cec5SDimitry Andric public:
6030b57cec5SDimitry Andric   virtual ~IdentifierInfoLookup();
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   /// Return the IdentifierInfo for the specified named identifier.
6060b57cec5SDimitry Andric   ///
6070b57cec5SDimitry Andric   /// Unlike the version in IdentifierTable, this returns a pointer instead
6080b57cec5SDimitry Andric   /// of a reference.  If the pointer is null then the IdentifierInfo cannot
6090b57cec5SDimitry Andric   /// be found.
6100b57cec5SDimitry Andric   virtual IdentifierInfo* get(StringRef Name) = 0;
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   /// Retrieve an iterator into the set of all identifiers
6130b57cec5SDimitry Andric   /// known to this identifier lookup source.
6140b57cec5SDimitry Andric   ///
6150b57cec5SDimitry Andric   /// This routine provides access to all of the identifiers known to
6160b57cec5SDimitry Andric   /// the identifier lookup, allowing access to the contents of the
6170b57cec5SDimitry Andric   /// identifiers without introducing the overhead of constructing
6180b57cec5SDimitry Andric   /// IdentifierInfo objects for each.
6190b57cec5SDimitry Andric   ///
6200b57cec5SDimitry Andric   /// \returns A new iterator into the set of known identifiers. The
6210b57cec5SDimitry Andric   /// caller is responsible for deleting this iterator.
6220b57cec5SDimitry Andric   virtual IdentifierIterator *getIdentifiers();
6230b57cec5SDimitry Andric };
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric /// Implements an efficient mapping from strings to IdentifierInfo nodes.
6260b57cec5SDimitry Andric ///
6270b57cec5SDimitry Andric /// This has no other purpose, but this is an extremely performance-critical
6280b57cec5SDimitry Andric /// piece of the code, as each occurrence of every identifier goes through
6290b57cec5SDimitry Andric /// here when lexed.
6300b57cec5SDimitry Andric class IdentifierTable {
6310b57cec5SDimitry Andric   // Shark shows that using MallocAllocator is *much* slower than using this
6320b57cec5SDimitry Andric   // BumpPtrAllocator!
6330b57cec5SDimitry Andric   using HashTableTy = llvm::StringMap<IdentifierInfo *, llvm::BumpPtrAllocator>;
6340b57cec5SDimitry Andric   HashTableTy HashTable;
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   IdentifierInfoLookup* ExternalLookup;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric public:
6390b57cec5SDimitry Andric   /// Create the identifier table.
6400b57cec5SDimitry Andric   explicit IdentifierTable(IdentifierInfoLookup *ExternalLookup = nullptr);
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   /// Create the identifier table, populating it with info about the
6430b57cec5SDimitry Andric   /// language keywords for the language specified by \p LangOpts.
6440b57cec5SDimitry Andric   explicit IdentifierTable(const LangOptions &LangOpts,
6450b57cec5SDimitry Andric                            IdentifierInfoLookup *ExternalLookup = nullptr);
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric   /// Set the external identifier lookup mechanism.
setExternalIdentifierLookup(IdentifierInfoLookup * IILookup)6480b57cec5SDimitry Andric   void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) {
6490b57cec5SDimitry Andric     ExternalLookup = IILookup;
6500b57cec5SDimitry Andric   }
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   /// Retrieve the external identifier lookup object, if any.
getExternalIdentifierLookup()6530b57cec5SDimitry Andric   IdentifierInfoLookup *getExternalIdentifierLookup() const {
6540b57cec5SDimitry Andric     return ExternalLookup;
6550b57cec5SDimitry Andric   }
6560b57cec5SDimitry Andric 
getAllocator()6570b57cec5SDimitry Andric   llvm::BumpPtrAllocator& getAllocator() {
6580b57cec5SDimitry Andric     return HashTable.getAllocator();
6590b57cec5SDimitry Andric   }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric   /// Return the identifier token info for the specified named
6620b57cec5SDimitry Andric   /// identifier.
get(StringRef Name)6630b57cec5SDimitry Andric   IdentifierInfo &get(StringRef Name) {
664bdd1243dSDimitry Andric     auto &Entry = *HashTable.try_emplace(Name, nullptr).first;
6650b57cec5SDimitry Andric 
6660b57cec5SDimitry Andric     IdentifierInfo *&II = Entry.second;
6670b57cec5SDimitry Andric     if (II) return *II;
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric     // No entry; if we have an external lookup, look there first.
6700b57cec5SDimitry Andric     if (ExternalLookup) {
6710b57cec5SDimitry Andric       II = ExternalLookup->get(Name);
6720b57cec5SDimitry Andric       if (II)
6730b57cec5SDimitry Andric         return *II;
6740b57cec5SDimitry Andric     }
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric     // Lookups failed, make a new IdentifierInfo.
6770b57cec5SDimitry Andric     void *Mem = getAllocator().Allocate<IdentifierInfo>();
6780b57cec5SDimitry Andric     II = new (Mem) IdentifierInfo();
6790b57cec5SDimitry Andric 
6800b57cec5SDimitry Andric     // Make sure getName() knows how to find the IdentifierInfo
6810b57cec5SDimitry Andric     // contents.
6820b57cec5SDimitry Andric     II->Entry = &Entry;
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric     return *II;
6850b57cec5SDimitry Andric   }
6860b57cec5SDimitry Andric 
get(StringRef Name,tok::TokenKind TokenCode)6870b57cec5SDimitry Andric   IdentifierInfo &get(StringRef Name, tok::TokenKind TokenCode) {
6880b57cec5SDimitry Andric     IdentifierInfo &II = get(Name);
6890b57cec5SDimitry Andric     II.TokenID = TokenCode;
6900b57cec5SDimitry Andric     assert(II.TokenID == (unsigned) TokenCode && "TokenCode too large");
6910b57cec5SDimitry Andric     return II;
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   /// Gets an IdentifierInfo for the given name without consulting
6950b57cec5SDimitry Andric   ///        external sources.
6960b57cec5SDimitry Andric   ///
6970b57cec5SDimitry Andric   /// This is a version of get() meant for external sources that want to
6980b57cec5SDimitry Andric   /// introduce or modify an identifier. If they called get(), they would
6990b57cec5SDimitry Andric   /// likely end up in a recursion.
getOwn(StringRef Name)7000b57cec5SDimitry Andric   IdentifierInfo &getOwn(StringRef Name) {
7010b57cec5SDimitry Andric     auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first;
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric     IdentifierInfo *&II = Entry.second;
7040b57cec5SDimitry Andric     if (II)
7050b57cec5SDimitry Andric       return *II;
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric     // Lookups failed, make a new IdentifierInfo.
7080b57cec5SDimitry Andric     void *Mem = getAllocator().Allocate<IdentifierInfo>();
7090b57cec5SDimitry Andric     II = new (Mem) IdentifierInfo();
7100b57cec5SDimitry Andric 
7110b57cec5SDimitry Andric     // Make sure getName() knows how to find the IdentifierInfo
7120b57cec5SDimitry Andric     // contents.
7130b57cec5SDimitry Andric     II->Entry = &Entry;
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric     // If this is the 'import' contextual keyword, mark it as such.
7160b57cec5SDimitry Andric     if (Name.equals("import"))
7170b57cec5SDimitry Andric       II->setModulesImport(true);
7180b57cec5SDimitry Andric 
7190b57cec5SDimitry Andric     return *II;
7200b57cec5SDimitry Andric   }
7210b57cec5SDimitry Andric 
7220b57cec5SDimitry Andric   using iterator = HashTableTy::const_iterator;
7230b57cec5SDimitry Andric   using const_iterator = HashTableTy::const_iterator;
7240b57cec5SDimitry Andric 
begin()7250b57cec5SDimitry Andric   iterator begin() const { return HashTable.begin(); }
end()7260b57cec5SDimitry Andric   iterator end() const   { return HashTable.end(); }
size()7270b57cec5SDimitry Andric   unsigned size() const  { return HashTable.size(); }
7280b57cec5SDimitry Andric 
find(StringRef Name)729480093f4SDimitry Andric   iterator find(StringRef Name) const { return HashTable.find(Name); }
730480093f4SDimitry Andric 
7310b57cec5SDimitry Andric   /// Print some statistics to stderr that indicate how well the
7320b57cec5SDimitry Andric   /// hashing is doing.
7330b57cec5SDimitry Andric   void PrintStats() const;
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric   /// Populate the identifier table with info about the language keywords
7360b57cec5SDimitry Andric   /// for the language specified by \p LangOpts.
7370b57cec5SDimitry Andric   void AddKeywords(const LangOptions &LangOpts);
738bdd1243dSDimitry Andric 
739bdd1243dSDimitry Andric   /// Returns the correct diagnostic to issue for a future-compat diagnostic
740bdd1243dSDimitry Andric   /// warning. Note, this function assumes the identifier passed has already
741bdd1243dSDimitry Andric   /// been determined to be a future compatible keyword.
742bdd1243dSDimitry Andric   diag::kind getFutureCompatDiagKind(const IdentifierInfo &II,
743bdd1243dSDimitry Andric                                      const LangOptions &LangOpts);
7440b57cec5SDimitry Andric };
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric /// A family of Objective-C methods.
7470b57cec5SDimitry Andric ///
7480b57cec5SDimitry Andric /// These families have no inherent meaning in the language, but are
7490b57cec5SDimitry Andric /// nonetheless central enough in the existing implementations to
7500b57cec5SDimitry Andric /// merit direct AST support.  While, in theory, arbitrary methods can
7510b57cec5SDimitry Andric /// be considered to form families, we focus here on the methods
7520b57cec5SDimitry Andric /// involving allocation and retain-count management, as these are the
7530b57cec5SDimitry Andric /// most "core" and the most likely to be useful to diverse clients
7540b57cec5SDimitry Andric /// without extra information.
7550b57cec5SDimitry Andric ///
7560b57cec5SDimitry Andric /// Both selectors and actual method declarations may be classified
7570b57cec5SDimitry Andric /// into families.  Method families may impose additional restrictions
7580b57cec5SDimitry Andric /// beyond their selector name; for example, a method called '_init'
7590b57cec5SDimitry Andric /// that returns void is not considered to be in the 'init' family
7600b57cec5SDimitry Andric /// (but would be if it returned 'id').  It is also possible to
7610b57cec5SDimitry Andric /// explicitly change or remove a method's family.  Therefore the
7620b57cec5SDimitry Andric /// method's family should be considered the single source of truth.
7630b57cec5SDimitry Andric enum ObjCMethodFamily {
7640b57cec5SDimitry Andric   /// No particular method family.
7650b57cec5SDimitry Andric   OMF_None,
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric   // Selectors in these families may have arbitrary arity, may be
7680b57cec5SDimitry Andric   // written with arbitrary leading underscores, and may have
7690b57cec5SDimitry Andric   // additional CamelCase "words" in their first selector chunk
7700b57cec5SDimitry Andric   // following the family name.
7710b57cec5SDimitry Andric   OMF_alloc,
7720b57cec5SDimitry Andric   OMF_copy,
7730b57cec5SDimitry Andric   OMF_init,
7740b57cec5SDimitry Andric   OMF_mutableCopy,
7750b57cec5SDimitry Andric   OMF_new,
7760b57cec5SDimitry Andric 
7770b57cec5SDimitry Andric   // These families are singletons consisting only of the nullary
7780b57cec5SDimitry Andric   // selector with the given name.
7790b57cec5SDimitry Andric   OMF_autorelease,
7800b57cec5SDimitry Andric   OMF_dealloc,
7810b57cec5SDimitry Andric   OMF_finalize,
7820b57cec5SDimitry Andric   OMF_release,
7830b57cec5SDimitry Andric   OMF_retain,
7840b57cec5SDimitry Andric   OMF_retainCount,
7850b57cec5SDimitry Andric   OMF_self,
7860b57cec5SDimitry Andric   OMF_initialize,
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   // performSelector families
7890b57cec5SDimitry Andric   OMF_performSelector
7900b57cec5SDimitry Andric };
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric /// Enough bits to store any enumerator in ObjCMethodFamily or
7930b57cec5SDimitry Andric /// InvalidObjCMethodFamily.
7940b57cec5SDimitry Andric enum { ObjCMethodFamilyBitWidth = 4 };
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric /// An invalid value of ObjCMethodFamily.
7970b57cec5SDimitry Andric enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 };
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric /// A family of Objective-C methods.
8000b57cec5SDimitry Andric ///
8010b57cec5SDimitry Andric /// These are family of methods whose result type is initially 'id', but
8020b57cec5SDimitry Andric /// but are candidate for the result type to be changed to 'instancetype'.
8030b57cec5SDimitry Andric enum ObjCInstanceTypeFamily {
8040b57cec5SDimitry Andric   OIT_None,
8050b57cec5SDimitry Andric   OIT_Array,
8060b57cec5SDimitry Andric   OIT_Dictionary,
8070b57cec5SDimitry Andric   OIT_Singleton,
8080b57cec5SDimitry Andric   OIT_Init,
8090b57cec5SDimitry Andric   OIT_ReturnsSelf
8100b57cec5SDimitry Andric };
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric enum ObjCStringFormatFamily {
8130b57cec5SDimitry Andric   SFF_None,
8140b57cec5SDimitry Andric   SFF_NSString,
8150b57cec5SDimitry Andric   SFF_CFString
8160b57cec5SDimitry Andric };
8170b57cec5SDimitry Andric 
8185f757f3fSDimitry Andric namespace detail {
8195f757f3fSDimitry Andric 
8205f757f3fSDimitry Andric /// DeclarationNameExtra is used as a base of various uncommon special names.
8215f757f3fSDimitry Andric /// This class is needed since DeclarationName has not enough space to store
8225f757f3fSDimitry Andric /// the kind of every possible names. Therefore the kind of common names is
8235f757f3fSDimitry Andric /// stored directly in DeclarationName, and the kind of uncommon names is
8245f757f3fSDimitry Andric /// stored in DeclarationNameExtra. It is aligned to 8 bytes because
8255f757f3fSDimitry Andric /// DeclarationName needs the lower 3 bits to store the kind of common names.
8265f757f3fSDimitry Andric /// DeclarationNameExtra is tightly coupled to DeclarationName and any change
8275f757f3fSDimitry Andric /// here is very likely to require changes in DeclarationName(Table).
alignas(IdentifierInfoAlignment)8285f757f3fSDimitry Andric class alignas(IdentifierInfoAlignment) DeclarationNameExtra {
8295f757f3fSDimitry Andric   friend class clang::DeclarationName;
8305f757f3fSDimitry Andric   friend class clang::DeclarationNameTable;
8315f757f3fSDimitry Andric 
8325f757f3fSDimitry Andric protected:
8335f757f3fSDimitry Andric   /// The kind of "extra" information stored in the DeclarationName. See
8345f757f3fSDimitry Andric   /// @c ExtraKindOrNumArgs for an explanation of how these enumerator values
8355f757f3fSDimitry Andric   /// are used. Note that DeclarationName depends on the numerical values
8365f757f3fSDimitry Andric   /// of the enumerators in this enum. See DeclarationName::StoredNameKind
8375f757f3fSDimitry Andric   /// for more info.
8385f757f3fSDimitry Andric   enum ExtraKind {
8395f757f3fSDimitry Andric     CXXDeductionGuideName,
8405f757f3fSDimitry Andric     CXXLiteralOperatorName,
8415f757f3fSDimitry Andric     CXXUsingDirective,
8425f757f3fSDimitry Andric     ObjCMultiArgSelector
8435f757f3fSDimitry Andric   };
8445f757f3fSDimitry Andric 
8455f757f3fSDimitry Andric   /// ExtraKindOrNumArgs has one of the following meaning:
8465f757f3fSDimitry Andric   ///  * The kind of an uncommon C++ special name. This DeclarationNameExtra
8475f757f3fSDimitry Andric   ///    is in this case in fact either a CXXDeductionGuideNameExtra or
8485f757f3fSDimitry Andric   ///    a CXXLiteralOperatorIdName.
8495f757f3fSDimitry Andric   ///
8505f757f3fSDimitry Andric   ///  * It may be also name common to C++ using-directives (CXXUsingDirective),
8515f757f3fSDimitry Andric   ///
8525f757f3fSDimitry Andric   ///  * Otherwise it is ObjCMultiArgSelector+NumArgs, where NumArgs is
8535f757f3fSDimitry Andric   ///    the number of arguments in the Objective-C selector, in which
8545f757f3fSDimitry Andric   ///    case the DeclarationNameExtra is also a MultiKeywordSelector.
8555f757f3fSDimitry Andric   unsigned ExtraKindOrNumArgs;
8565f757f3fSDimitry Andric 
8575f757f3fSDimitry Andric   DeclarationNameExtra(ExtraKind Kind) : ExtraKindOrNumArgs(Kind) {}
8585f757f3fSDimitry Andric   DeclarationNameExtra(unsigned NumArgs)
8595f757f3fSDimitry Andric       : ExtraKindOrNumArgs(ObjCMultiArgSelector + NumArgs) {}
8605f757f3fSDimitry Andric 
8615f757f3fSDimitry Andric   /// Return the corresponding ExtraKind.
8625f757f3fSDimitry Andric   ExtraKind getKind() const {
8635f757f3fSDimitry Andric     return static_cast<ExtraKind>(ExtraKindOrNumArgs >
8645f757f3fSDimitry Andric                                           (unsigned)ObjCMultiArgSelector
8655f757f3fSDimitry Andric                                       ? (unsigned)ObjCMultiArgSelector
8665f757f3fSDimitry Andric                                       : ExtraKindOrNumArgs);
8675f757f3fSDimitry Andric   }
8685f757f3fSDimitry Andric 
8695f757f3fSDimitry Andric   /// Return the number of arguments in an ObjC selector. Only valid when this
8705f757f3fSDimitry Andric   /// is indeed an ObjCMultiArgSelector.
8715f757f3fSDimitry Andric   unsigned getNumArgs() const {
8725f757f3fSDimitry Andric     assert(ExtraKindOrNumArgs >= (unsigned)ObjCMultiArgSelector &&
8735f757f3fSDimitry Andric            "getNumArgs called but this is not an ObjC selector!");
8745f757f3fSDimitry Andric     return ExtraKindOrNumArgs - (unsigned)ObjCMultiArgSelector;
8755f757f3fSDimitry Andric   }
8765f757f3fSDimitry Andric };
8775f757f3fSDimitry Andric 
8785f757f3fSDimitry Andric } // namespace detail
8795f757f3fSDimitry Andric 
8805f757f3fSDimitry Andric /// One of these variable length records is kept for each
8815f757f3fSDimitry Andric /// selector containing more than one keyword. We use a folding set
8825f757f3fSDimitry Andric /// to unique aggregate names (keyword selectors in ObjC parlance). Access to
8835f757f3fSDimitry Andric /// this class is provided strictly through Selector.
alignas(IdentifierInfoAlignment)8845f757f3fSDimitry Andric class alignas(IdentifierInfoAlignment) MultiKeywordSelector
8855f757f3fSDimitry Andric     : public detail::DeclarationNameExtra,
8865f757f3fSDimitry Andric       public llvm::FoldingSetNode {
8875f757f3fSDimitry Andric   MultiKeywordSelector(unsigned nKeys) : DeclarationNameExtra(nKeys) {}
8885f757f3fSDimitry Andric 
8895f757f3fSDimitry Andric public:
8905f757f3fSDimitry Andric   // Constructor for keyword selectors.
8915f757f3fSDimitry Andric   MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
8925f757f3fSDimitry Andric       : DeclarationNameExtra(nKeys) {
8935f757f3fSDimitry Andric     assert((nKeys > 1) && "not a multi-keyword selector");
8945f757f3fSDimitry Andric 
8955f757f3fSDimitry Andric     // Fill in the trailing keyword array.
8965f757f3fSDimitry Andric     IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this + 1);
8975f757f3fSDimitry Andric     for (unsigned i = 0; i != nKeys; ++i)
8985f757f3fSDimitry Andric       KeyInfo[i] = IIV[i];
8995f757f3fSDimitry Andric   }
9005f757f3fSDimitry Andric 
9015f757f3fSDimitry Andric   // getName - Derive the full selector name and return it.
9025f757f3fSDimitry Andric   std::string getName() const;
9035f757f3fSDimitry Andric 
9045f757f3fSDimitry Andric   using DeclarationNameExtra::getNumArgs;
9055f757f3fSDimitry Andric 
9065f757f3fSDimitry Andric   using keyword_iterator = IdentifierInfo *const *;
9075f757f3fSDimitry Andric 
9085f757f3fSDimitry Andric   keyword_iterator keyword_begin() const {
9095f757f3fSDimitry Andric     return reinterpret_cast<keyword_iterator>(this + 1);
9105f757f3fSDimitry Andric   }
9115f757f3fSDimitry Andric 
9125f757f3fSDimitry Andric   keyword_iterator keyword_end() const {
9135f757f3fSDimitry Andric     return keyword_begin() + getNumArgs();
9145f757f3fSDimitry Andric   }
9155f757f3fSDimitry Andric 
9165f757f3fSDimitry Andric   IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
9175f757f3fSDimitry Andric     assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
9185f757f3fSDimitry Andric     return keyword_begin()[i];
9195f757f3fSDimitry Andric   }
9205f757f3fSDimitry Andric 
9215f757f3fSDimitry Andric   static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys,
9225f757f3fSDimitry Andric                       unsigned NumArgs) {
9235f757f3fSDimitry Andric     ID.AddInteger(NumArgs);
9245f757f3fSDimitry Andric     for (unsigned i = 0; i != NumArgs; ++i)
9255f757f3fSDimitry Andric       ID.AddPointer(ArgTys[i]);
9265f757f3fSDimitry Andric   }
9275f757f3fSDimitry Andric 
9285f757f3fSDimitry Andric   void Profile(llvm::FoldingSetNodeID &ID) {
9295f757f3fSDimitry Andric     Profile(ID, keyword_begin(), getNumArgs());
9305f757f3fSDimitry Andric   }
9315f757f3fSDimitry Andric };
9325f757f3fSDimitry Andric 
9330b57cec5SDimitry Andric /// Smart pointer class that efficiently represents Objective-C method
9340b57cec5SDimitry Andric /// names.
9350b57cec5SDimitry Andric ///
9360b57cec5SDimitry Andric /// This class will either point to an IdentifierInfo or a
9370b57cec5SDimitry Andric /// MultiKeywordSelector (which is private). This enables us to optimize
9380b57cec5SDimitry Andric /// selectors that take no arguments and selectors that take 1 argument, which
9390b57cec5SDimitry Andric /// accounts for 78% of all selectors in Cocoa.h.
9400b57cec5SDimitry Andric class Selector {
9410b57cec5SDimitry Andric   friend class Diagnostic;
9420b57cec5SDimitry Andric   friend class SelectorTable; // only the SelectorTable can create these
9430b57cec5SDimitry Andric   friend class DeclarationName; // and the AST's DeclarationName.
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   enum IdentifierInfoFlag {
9460b57cec5SDimitry Andric     // Empty selector = 0. Note that these enumeration values must
9470b57cec5SDimitry Andric     // correspond to the enumeration values of DeclarationName::StoredNameKind
9480b57cec5SDimitry Andric     ZeroArg = 0x01,
9490b57cec5SDimitry Andric     OneArg = 0x02,
9505f757f3fSDimitry Andric     // IMPORTANT NOTE: see comments in InfoPtr (below) about this enumerator
9515f757f3fSDimitry Andric     // value.
9520b57cec5SDimitry Andric     MultiArg = 0x07,
9530b57cec5SDimitry Andric   };
9540b57cec5SDimitry Andric 
9555f757f3fSDimitry Andric   /// IMPORTANT NOTE: the order of the types in this PointerUnion are
9565f757f3fSDimitry Andric   /// important! The DeclarationName class has bidirectional conversion
9575f757f3fSDimitry Andric   /// to/from Selector through an opaque pointer (void *) which corresponds
9585f757f3fSDimitry Andric   /// to this PointerIntPair. The discriminator bit from the PointerUnion
9595f757f3fSDimitry Andric   /// corresponds to the high bit in the MultiArg enumerator. So while this
9605f757f3fSDimitry Andric   /// PointerIntPair only has two bits for the integer (and we mask off the
9615f757f3fSDimitry Andric   /// high bit in `MultiArg` when it is used), that discrimator bit is
9625f757f3fSDimitry Andric   /// still necessary for the opaque conversion. The discriminator bit
9635f757f3fSDimitry Andric   /// from the PointerUnion and the two integer bits from the
9645f757f3fSDimitry Andric   /// PointerIntPair are also exposed via the DeclarationName::StoredNameKind
9655f757f3fSDimitry Andric   /// enumeration; see the comments in DeclarationName.h for more details.
9665f757f3fSDimitry Andric   /// Do not reorder or add any arguments to this template
9675f757f3fSDimitry Andric   /// without thoroughly understanding how tightly coupled these classes are.
9685f757f3fSDimitry Andric   llvm::PointerIntPair<
9695f757f3fSDimitry Andric       llvm::PointerUnion<IdentifierInfo *, MultiKeywordSelector *>, 2>
9705f757f3fSDimitry Andric       InfoPtr;
9710b57cec5SDimitry Andric 
Selector(IdentifierInfo * II,unsigned nArgs)9720b57cec5SDimitry Andric   Selector(IdentifierInfo *II, unsigned nArgs) {
9730b57cec5SDimitry Andric     assert(nArgs < 2 && "nArgs not equal to 0/1");
9745f757f3fSDimitry Andric     InfoPtr.setPointerAndInt(II, nArgs + 1);
9750b57cec5SDimitry Andric   }
9760b57cec5SDimitry Andric 
Selector(MultiKeywordSelector * SI)9770b57cec5SDimitry Andric   Selector(MultiKeywordSelector *SI) {
9785f757f3fSDimitry Andric     // IMPORTANT NOTE: we mask off the upper bit of this value because we only
9795f757f3fSDimitry Andric     // reserve two bits for the integer in the PointerIntPair. See the comments
9805f757f3fSDimitry Andric     // in `InfoPtr` for more details.
9815f757f3fSDimitry Andric     InfoPtr.setPointerAndInt(SI, MultiArg & 0b11);
9820b57cec5SDimitry Andric   }
9830b57cec5SDimitry Andric 
getAsIdentifierInfo()9840b57cec5SDimitry Andric   IdentifierInfo *getAsIdentifierInfo() const {
9855f757f3fSDimitry Andric     return InfoPtr.getPointer().dyn_cast<IdentifierInfo *>();
9860b57cec5SDimitry Andric   }
9870b57cec5SDimitry Andric 
getMultiKeywordSelector()9880b57cec5SDimitry Andric   MultiKeywordSelector *getMultiKeywordSelector() const {
9895f757f3fSDimitry Andric     return InfoPtr.getPointer().get<MultiKeywordSelector *>();
9900b57cec5SDimitry Andric   }
9910b57cec5SDimitry Andric 
getIdentifierInfoFlag()9920b57cec5SDimitry Andric   unsigned getIdentifierInfoFlag() const {
9935f757f3fSDimitry Andric     unsigned new_flags = InfoPtr.getInt();
9945f757f3fSDimitry Andric     // IMPORTANT NOTE: We have to reconstitute this data rather than use the
9955f757f3fSDimitry Andric     // value directly from the PointerIntPair. See the comments in `InfoPtr`
9965f757f3fSDimitry Andric     // for more details.
9975f757f3fSDimitry Andric     if (InfoPtr.getPointer().is<MultiKeywordSelector *>())
9985f757f3fSDimitry Andric       new_flags |= MultiArg;
9995f757f3fSDimitry Andric     return new_flags;
10000b57cec5SDimitry Andric   }
10010b57cec5SDimitry Andric 
10020b57cec5SDimitry Andric   static ObjCMethodFamily getMethodFamilyImpl(Selector sel);
10030b57cec5SDimitry Andric 
10040b57cec5SDimitry Andric   static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel);
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric public:
10070b57cec5SDimitry Andric   /// The default ctor should only be used when creating data structures that
10080b57cec5SDimitry Andric   ///  will contain selectors.
10090b57cec5SDimitry Andric   Selector() = default;
Selector(uintptr_t V)10105f757f3fSDimitry Andric   explicit Selector(uintptr_t V) {
10115f757f3fSDimitry Andric     InfoPtr.setFromOpaqueValue(reinterpret_cast<void *>(V));
10125f757f3fSDimitry Andric   }
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   /// operator==/!= - Indicate whether the specified selectors are identical.
10150b57cec5SDimitry Andric   bool operator==(Selector RHS) const {
10165f757f3fSDimitry Andric     return InfoPtr.getOpaqueValue() == RHS.InfoPtr.getOpaqueValue();
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric   bool operator!=(Selector RHS) const {
10195f757f3fSDimitry Andric     return InfoPtr.getOpaqueValue() != RHS.InfoPtr.getOpaqueValue();
10200b57cec5SDimitry Andric   }
10210b57cec5SDimitry Andric 
getAsOpaquePtr()10225f757f3fSDimitry Andric   void *getAsOpaquePtr() const { return InfoPtr.getOpaqueValue(); }
10230b57cec5SDimitry Andric 
10240b57cec5SDimitry Andric   /// Determine whether this is the empty selector.
isNull()10255f757f3fSDimitry Andric   bool isNull() const { return InfoPtr.getOpaqueValue() == nullptr; }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric   // Predicates to identify the selector type.
isKeywordSelector()10285f757f3fSDimitry Andric   bool isKeywordSelector() const { return InfoPtr.getInt() != ZeroArg; }
10290b57cec5SDimitry Andric 
isUnarySelector()10305f757f3fSDimitry Andric   bool isUnarySelector() const { return InfoPtr.getInt() == ZeroArg; }
10310b57cec5SDimitry Andric 
1032a7dea167SDimitry Andric   /// If this selector is the specific keyword selector described by Names.
1033a7dea167SDimitry Andric   bool isKeywordSelector(ArrayRef<StringRef> Names) const;
1034a7dea167SDimitry Andric 
1035a7dea167SDimitry Andric   /// If this selector is the specific unary selector described by Name.
1036a7dea167SDimitry Andric   bool isUnarySelector(StringRef Name) const;
1037a7dea167SDimitry Andric 
10380b57cec5SDimitry Andric   unsigned getNumArgs() const;
10390b57cec5SDimitry Andric 
10400b57cec5SDimitry Andric   /// Retrieve the identifier at a given position in the selector.
10410b57cec5SDimitry Andric   ///
10420b57cec5SDimitry Andric   /// Note that the identifier pointer returned may be NULL. Clients that only
10430b57cec5SDimitry Andric   /// care about the text of the identifier string, and not the specific,
10440b57cec5SDimitry Andric   /// uniqued identifier pointer, should use \c getNameForSlot(), which returns
10450b57cec5SDimitry Andric   /// an empty string when the identifier pointer would be NULL.
10460b57cec5SDimitry Andric   ///
10470b57cec5SDimitry Andric   /// \param argIndex The index for which we want to retrieve the identifier.
10480b57cec5SDimitry Andric   /// This index shall be less than \c getNumArgs() unless this is a keyword
10490b57cec5SDimitry Andric   /// selector, in which case 0 is the only permissible value.
10500b57cec5SDimitry Andric   ///
10510b57cec5SDimitry Andric   /// \returns the uniqued identifier for this slot, or NULL if this slot has
10520b57cec5SDimitry Andric   /// no corresponding identifier.
10530b57cec5SDimitry Andric   IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const;
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric   /// Retrieve the name at a given position in the selector.
10560b57cec5SDimitry Andric   ///
10570b57cec5SDimitry Andric   /// \param argIndex The index for which we want to retrieve the name.
10580b57cec5SDimitry Andric   /// This index shall be less than \c getNumArgs() unless this is a keyword
10590b57cec5SDimitry Andric   /// selector, in which case 0 is the only permissible value.
10600b57cec5SDimitry Andric   ///
10610b57cec5SDimitry Andric   /// \returns the name for this slot, which may be the empty string if no
10620b57cec5SDimitry Andric   /// name was supplied.
10630b57cec5SDimitry Andric   StringRef getNameForSlot(unsigned argIndex) const;
10640b57cec5SDimitry Andric 
10650b57cec5SDimitry Andric   /// Derive the full selector name (e.g. "foo:bar:") and return
10660b57cec5SDimitry Andric   /// it as an std::string.
10670b57cec5SDimitry Andric   std::string getAsString() const;
10680b57cec5SDimitry Andric 
10690b57cec5SDimitry Andric   /// Prints the full selector name (e.g. "foo:bar:").
10700b57cec5SDimitry Andric   void print(llvm::raw_ostream &OS) const;
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   void dump() const;
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric   /// Derive the conventional family of this method.
getMethodFamily()10750b57cec5SDimitry Andric   ObjCMethodFamily getMethodFamily() const {
10760b57cec5SDimitry Andric     return getMethodFamilyImpl(*this);
10770b57cec5SDimitry Andric   }
10780b57cec5SDimitry Andric 
getStringFormatFamily()10790b57cec5SDimitry Andric   ObjCStringFormatFamily getStringFormatFamily() const {
10800b57cec5SDimitry Andric     return getStringFormatFamilyImpl(*this);
10810b57cec5SDimitry Andric   }
10820b57cec5SDimitry Andric 
getEmptyMarker()10830b57cec5SDimitry Andric   static Selector getEmptyMarker() {
10840b57cec5SDimitry Andric     return Selector(uintptr_t(-1));
10850b57cec5SDimitry Andric   }
10860b57cec5SDimitry Andric 
getTombstoneMarker()10870b57cec5SDimitry Andric   static Selector getTombstoneMarker() {
10880b57cec5SDimitry Andric     return Selector(uintptr_t(-2));
10890b57cec5SDimitry Andric   }
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel);
10920b57cec5SDimitry Andric };
10930b57cec5SDimitry Andric 
10940b57cec5SDimitry Andric /// This table allows us to fully hide how we implement
10950b57cec5SDimitry Andric /// multi-keyword caching.
10960b57cec5SDimitry Andric class SelectorTable {
10970b57cec5SDimitry Andric   // Actually a SelectorTableImpl
10980b57cec5SDimitry Andric   void *Impl;
10990b57cec5SDimitry Andric 
11000b57cec5SDimitry Andric public:
11010b57cec5SDimitry Andric   SelectorTable();
11020b57cec5SDimitry Andric   SelectorTable(const SelectorTable &) = delete;
11030b57cec5SDimitry Andric   SelectorTable &operator=(const SelectorTable &) = delete;
11040b57cec5SDimitry Andric   ~SelectorTable();
11050b57cec5SDimitry Andric 
11060b57cec5SDimitry Andric   /// Can create any sort of selector.
11070b57cec5SDimitry Andric   ///
11080b57cec5SDimitry Andric   /// \p NumArgs indicates whether this is a no argument selector "foo", a
11090b57cec5SDimitry Andric   /// single argument selector "foo:" or multi-argument "foo:bar:".
11100b57cec5SDimitry Andric   Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV);
11110b57cec5SDimitry Andric 
getUnarySelector(IdentifierInfo * ID)11120b57cec5SDimitry Andric   Selector getUnarySelector(IdentifierInfo *ID) {
11130b57cec5SDimitry Andric     return Selector(ID, 1);
11140b57cec5SDimitry Andric   }
11150b57cec5SDimitry Andric 
getNullarySelector(IdentifierInfo * ID)11160b57cec5SDimitry Andric   Selector getNullarySelector(IdentifierInfo *ID) {
11170b57cec5SDimitry Andric     return Selector(ID, 0);
11180b57cec5SDimitry Andric   }
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric   /// Return the total amount of memory allocated for managing selectors.
11210b57cec5SDimitry Andric   size_t getTotalMemory() const;
11220b57cec5SDimitry Andric 
11230b57cec5SDimitry Andric   /// Return the default setter name for the given identifier.
11240b57cec5SDimitry Andric   ///
11250b57cec5SDimitry Andric   /// This is "set" + \p Name where the initial character of \p Name
11260b57cec5SDimitry Andric   /// has been capitalized.
11270b57cec5SDimitry Andric   static SmallString<64> constructSetterName(StringRef Name);
11280b57cec5SDimitry Andric 
11290b57cec5SDimitry Andric   /// Return the default setter selector for the given identifier.
11300b57cec5SDimitry Andric   ///
11310b57cec5SDimitry Andric   /// This is "set" + \p Name where the initial character of \p Name
11320b57cec5SDimitry Andric   /// has been capitalized.
11330b57cec5SDimitry Andric   static Selector constructSetterSelector(IdentifierTable &Idents,
11340b57cec5SDimitry Andric                                           SelectorTable &SelTable,
11350b57cec5SDimitry Andric                                           const IdentifierInfo *Name);
11360b57cec5SDimitry Andric 
11370b57cec5SDimitry Andric   /// Return the property name for the given setter selector.
11380b57cec5SDimitry Andric   static std::string getPropertyNameFromSetterSelector(Selector Sel);
11390b57cec5SDimitry Andric };
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric }  // namespace clang
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric namespace llvm {
11440b57cec5SDimitry Andric 
11450b57cec5SDimitry Andric /// Define DenseMapInfo so that Selectors can be used as keys in DenseMap and
11460b57cec5SDimitry Andric /// DenseSets.
11470b57cec5SDimitry Andric template <>
11480b57cec5SDimitry Andric struct DenseMapInfo<clang::Selector> {
11490b57cec5SDimitry Andric   static clang::Selector getEmptyKey() {
11500b57cec5SDimitry Andric     return clang::Selector::getEmptyMarker();
11510b57cec5SDimitry Andric   }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   static clang::Selector getTombstoneKey() {
11540b57cec5SDimitry Andric     return clang::Selector::getTombstoneMarker();
11550b57cec5SDimitry Andric   }
11560b57cec5SDimitry Andric 
11570b57cec5SDimitry Andric   static unsigned getHashValue(clang::Selector S);
11580b57cec5SDimitry Andric 
11590b57cec5SDimitry Andric   static bool isEqual(clang::Selector LHS, clang::Selector RHS) {
11600b57cec5SDimitry Andric     return LHS == RHS;
11610b57cec5SDimitry Andric   }
11620b57cec5SDimitry Andric };
11630b57cec5SDimitry Andric 
11640b57cec5SDimitry Andric template<>
11650b57cec5SDimitry Andric struct PointerLikeTypeTraits<clang::Selector> {
11660b57cec5SDimitry Andric   static const void *getAsVoidPointer(clang::Selector P) {
11670b57cec5SDimitry Andric     return P.getAsOpaquePtr();
11680b57cec5SDimitry Andric   }
11690b57cec5SDimitry Andric 
11700b57cec5SDimitry Andric   static clang::Selector getFromVoidPointer(const void *P) {
11710b57cec5SDimitry Andric     return clang::Selector(reinterpret_cast<uintptr_t>(P));
11720b57cec5SDimitry Andric   }
11730b57cec5SDimitry Andric 
11745ffd83dbSDimitry Andric   static constexpr int NumLowBitsAvailable = 0;
11750b57cec5SDimitry Andric };
11760b57cec5SDimitry Andric 
11770b57cec5SDimitry Andric } // namespace llvm
11780b57cec5SDimitry Andric 
11790b57cec5SDimitry Andric #endif // LLVM_CLANG_BASIC_IDENTIFIERTABLE_H
1180