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