22#include "llvm/ADT/DenseMapInfo.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/SmallString.h"
25#include "llvm/ADT/StringMap.h"
26#include "llvm/ADT/StringRef.h"
27#include "llvm/Support/Allocator.h"
28#include "llvm/Support/raw_ostream.h"
40 "Insufficient ObjCOrBuiltinID Bits");
56 StringRef
Next()
override {
return StringRef(); }
62 return new EmptyLookupIterator();
67 ExternalLookup(ExternalLookup) {}
84enum TokenKey :
unsigned {
98 WCHARSUPPORT = 0x2000,
100 CHAR8SUPPORT = 0x8000,
102 KEYZVECTOR = 0x20000,
103 KEYCOROUTINES = 0x40000,
104 KEYMODULES = 0x80000,
106 KEYOPENCLCXX = 0x200000,
107 KEYMSCOMPAT = 0x400000,
111 KEYNOZOS = 0x4000000,
113 KEYFIXEDPOINT = 0x10000000,
114 KEYMAX = KEYFIXEDPOINT,
115 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
116 KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
142 assert((Flag & ~(Flag - 1)) == Flag &&
"Multiple bits set?");
148 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
152 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
154 return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
156 if (LangOpts.CPlusPlus11)
158 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
160 if (LangOpts.CPlusPlus20)
162 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
164 return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
166 return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
168 if (LangOpts.Bool)
return KS_Enabled;
169 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
171 return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
173 return LangOpts.Borland ? KS_Extension : KS_Unknown;
175 return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
178 return LangOpts.WChar ? KS_Enabled : KS_Unknown;
180 return LangOpts.Half ? KS_Enabled : KS_Unknown;
182 if (LangOpts.Char8)
return KS_Enabled;
183 if (LangOpts.CPlusPlus20)
return KS_Unknown;
184 if (LangOpts.CPlusPlus)
return KS_Future;
189 return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
191 return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
193 return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
197 return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
199 return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
201 return LangOpts.
isSYCL() ? KS_Enabled : KS_Unknown;
203 return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
205 return LangOpts.ZOSExt ? KS_Enabled : KS_Unknown;
207 return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
211 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
218 return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
220 llvm_unreachable(
"Unknown KeywordStatus flag");
229 if (Flags == KEYALL)
return KS_Enabled;
232 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
return KS_Disabled;
233 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
236 if (LangOpts.ZOSExt && (Flags & KEYNOZOS))
238 KeywordStatus CurStatus = KS_Unknown;
241 unsigned CurFlag = Flags & ~(Flags - 1);
242 Flags = Flags & ~CurFlag;
243 CurStatus = std::max(
248 if (CurStatus == KS_Unknown)
262 if (AddResult == KS_Disabled)
return;
265 Table.
get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
291 if (BTID != tok::not_notable) {
301#define KEYWORD(NAME, FLAGS) \
302 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
303 FLAGS, LangOpts, *this);
304#define ALIAS(NAME, TOK, FLAGS) \
305 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
306 FLAGS, LangOpts, *this);
307#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
308 if (LangOpts.CXXOperatorNames) \
309 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
310#define OBJC_AT_KEYWORD(NAME) \
312 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
313#define NOTABLE_IDENTIFIER(NAME) \
314 AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
316#define TESTING_KEYWORD(NAME, FLAGS)
317#include "clang/Basic/TokenKinds.def"
319 if (LangOpts.ParseUnknownAnytype)
320 AddKeyword(
"__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
323 if (LangOpts.DeclSpecKeyword)
324 AddKeyword(
"__declspec", tok::kw___declspec, KEYALL, LangOpts, *
this);
326 if (LangOpts.IEEE128)
327 AddKeyword(
"__ieee128", tok::kw___float128, KEYALL, LangOpts, *
this);
339#define KEYWORD(NAME, FLAGS) \
340 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
341#include "clang/Basic/TokenKinds.def"
342 default:
return KS_Disabled;
361 if (!LangOpts.CPlusPlus || !
isKeyword(LangOpts))
366 LangOptsNoCPP.CPlusPlus =
false;
367 LangOptsNoCPP.CPlusPlus11 =
false;
368 LangOptsNoCPP.CPlusPlus20 =
false;
378 if (Name.size() <= 1)
382 if (Name[0] ==
'_') {
389 if (
'A' <= Name[1] && Name[1] <=
'Z')
399 if (LangOpts.CPlusPlus && Name.contains(
"__"))
412 if (Name.contains(
"__"))
420 if (Name.size() >= 2 && Name.front() ==
'_' &&
421 (Name[1] ==
'_' || (Name[1] >=
'A' && Name[1] <=
'Z')))
422 return Name.ltrim(
'_');
432#define HASH(LEN, FIRST, THIRD) \
433 (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
434#define CASE(LEN, FIRST, THIRD, NAME) \
435 case HASH(LEN, FIRST, THIRD): \
436 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
439 if (Len < 2)
return tok::pp_not_keyword;
441 switch (
HASH(Len, Name[0], Name[2])) {
442 default:
return tok::pp_not_keyword;
443 CASE( 2,
'i',
'\0',
if);
444 CASE( 4,
'e',
'i', elif);
445 CASE( 4,
'e',
's',
else);
446 CASE( 4,
'l',
'n', line);
447 CASE( 4,
's',
'c', sccs);
448 CASE( 5,
'e',
'b', embed);
449 CASE( 5,
'e',
'd', endif);
450 CASE( 5,
'e',
'r', error);
451 CASE( 5,
'i',
'e', ident);
452 CASE( 5,
'i',
'd', ifdef);
453 CASE( 5,
'u',
'd', undef);
455 CASE( 6,
'a',
's', assert);
456 CASE( 6,
'd',
'f', define);
457 CASE( 6,
'i',
'n', ifndef);
458 CASE( 6,
'i',
'p',
import);
459 CASE( 6,
'p',
'a', pragma);
461 CASE( 7,
'd',
'f', defined);
462 CASE( 7,
'e',
'i', elifdef);
463 CASE( 7,
'i',
'c', include);
464 CASE( 7,
'w',
'r', warning);
466 CASE( 8,
'e',
'i', elifndef);
467 CASE( 8,
'u',
'a', unassert);
468 CASE(12,
'i',
'c', include_next);
470 CASE(14,
'_',
'p', __public_macro);
472 CASE(15,
'_',
'p', __private_macro);
474 CASE(16,
'_',
'i', __include_macros);
487 unsigned NumBuckets = HashTable.getNumBuckets();
488 unsigned NumIdentifiers = HashTable.getNumItems();
489 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
490 unsigned AverageIdentifierSize = 0;
491 unsigned MaxIdentifierLength = 0;
494 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
495 I = HashTable.begin(),
E = HashTable.end(); I !=
E; ++I) {
496 unsigned IdLen = I->getKeyLength();
497 AverageIdentifierSize += IdLen;
498 if (MaxIdentifierLength < IdLen)
499 MaxIdentifierLength = IdLen;
502 fprintf(stderr,
"\n*** Identifier Table Stats:\n");
503 fprintf(stderr,
"# Identifiers: %d\n", NumIdentifiers);
504 fprintf(stderr,
"# Empty Buckets: %d\n", NumEmptyBuckets);
505 fprintf(stderr,
"Hash density (#identifiers per bucket): %f\n",
506 NumIdentifiers/(
double)NumBuckets);
507 fprintf(stderr,
"Ave identifier length: %f\n",
508 (AverageIdentifierSize/(
double)NumIdentifiers));
509 fprintf(stderr,
"Max identifier length: %d\n", MaxIdentifierLength);
512 HashTable.getAllocator().PrintStats();
520 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
524 assert(!Names.empty() &&
"must have >= 1 selector slots");
527 for (
unsigned I = 0,
E = Names.size(); I !=
E; ++I) {
539 unsigned IIF = getIdentifierInfoFlag();
551 if (getIdentifierInfoFlag() < MultiArg) {
552 assert(argIndex == 0 &&
"illegal keyword index");
553 return getAsIdentifierInfo();
563 return II ? II->
getName() : StringRef();
568 llvm::raw_svector_ostream OS(Str);
571 OS << (*I)->getName();
575 return std::string(OS.str());
580 return "<null selector>";
582 if (getIdentifierInfoFlag() < MultiArg) {
586 assert(II &&
"If the number of arguments is 0 then II is guaranteed to "
588 return std::string(II->
getName());
594 return II->
getName().str() +
":";
598 return getMultiKeywordSelector()->
getName();
611 if (name.size() < word.size())
return false;
612 return ((name.size() == word.size() || !
isLowercase(name[word.size()])) &&
613 name.starts_with(word));
628 if (name ==
"self")
return OMF_self;
632 if (name ==
"performSelector" || name ==
"performSelectorInBackground" ||
633 name ==
"performSelectorOnMainThread")
640 switch (
name.front()) {
667 StringRef name = first->
getName();
670 switch (name.front()) {
695 StringRef name = first->
getName();
697 switch (name.front()) {
707 if (name ==
"localizedStringWithFormat")
return SFF_NSString;
711 if (name ==
"stringByAppendingFormat" ||
720struct SelectorTableImpl {
721 llvm::FoldingSet<MultiKeywordSelector> Table;
722 llvm::BumpPtrAllocator Allocator;
728 return *
static_cast<SelectorTableImpl*
>(
P);
750 assert(Name.starts_with(
"set") &&
"invalid setter name");
751 return (Twine(
toLowercase(Name[3])) + Name.drop_front(4)).str();
756 return SelTabImpl.Allocator.getTotalMemory();
767 llvm::FoldingSetNodeID ID;
770 void *InsertPos =
nullptr;
772 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
782 SelTabImpl.Table.InsertNode(SI, InsertPos);
787 Impl =
new SelectorTableImpl();
800#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
801 case OO_##Name: return Spelling;
802#include "clang/Basic/OperatorKinds.def"
805 llvm_unreachable(
"Invalid OverloadedOperatorKind!");
809 bool isContextSensitive) {
812 return isContextSensitive ?
"nonnull" :
"_Nonnull";
815 return isContextSensitive ?
"nullable" :
"_Nullable";
818 assert(!isContextSensitive &&
819 "_Nullable_result isn't supported as context-sensitive keyword");
820 return "_Nullable_result";
823 return isContextSensitive ?
"null_unspecified" :
"_Null_unspecified";
825 llvm_unreachable(
"Unknown nullability kind.");
832 return OS <<
"NonNull";
834 return OS <<
"Nullable";
836 return OS <<
"NullableResult";
838 return OS <<
"Unspecified";
840 llvm_unreachable(
"Unknown nullability kind.");
848 unsigned Flags = llvm::StringSwitch<unsigned>(II.
getName())
849#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
850#include "clang/Basic/TokenKinds.def"
854 if (LangOpts.CPlusPlus) {
855 if ((Flags & KEYCXX11) == KEYCXX11)
856 return diag::warn_cxx11_keyword;
861 if (((Flags & KEYCXX20) == KEYCXX20) ||
862 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
863 return diag::warn_cxx20_keyword;
865 if ((Flags & KEYC99) == KEYC99)
866 return diag::warn_c99_keyword;
867 if ((Flags & KEYC23) == KEYC23)
868 return diag::warn_c23_keyword;
872 "Keyword not known to come from a newer Standard or proposed Standard");
static void AddObjCKeyword(StringRef Name, tok::ObjCKeywordKind ObjCID, IdentifierTable &Table)
AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or "property".
static void AddCXXOperatorKeyword(StringRef Keyword, tok::TokenKind TokenCode, IdentifierTable &Table)
AddCXXOperatorKeyword - Register a C++ operator keyword alternative representations.
static void AddNotableIdentifier(StringRef Name, tok::NotableIdentifierKind BTID, IdentifierTable &Table)
static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts, TokenKey Flag)
static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts, tok::TokenKind K)
Checks if the specified token kind represents a keyword in the specified language.
static bool startsWithWord(StringRef name, StringRef word)
Interpreting the given string using the normal CamelCase conventions, determine whether the given str...
#define CASE(LEN, FIRST, THIRD, NAME)
static void AddKeyword(StringRef Keyword, tok::TokenKind TokenCode, unsigned Flags, const LangOptions &LangOpts, IdentifierTable &Table)
AddKeyword - This method is used to associate a token ID with specific identifiers because they are l...
static SelectorTableImpl & getSelectorTableImpl(void *P)
static KeywordStatus getKeywordStatus(const LangOptions &LangOpts, unsigned Flags)
Translates flags as specified in TokenKinds.def into keyword status in the given language standard.
#define HASH(LEN, FIRST, THIRD)
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Defines the clang::LangOptions interface.
Defines an enumeration for C++ overloaded operators.
Defines various enumerations that describe declaration and type specifiers.
Enumerates target-specific builtins in their own namespaces within namespace clang.
Defines the clang::TokenKind enum and support functions.
Provides lookups to, and iteration over, IdentiferInfo objects.
virtual ~IdentifierInfoLookup()
virtual IdentifierIterator * getIdentifiers()
Retrieve an iterator into the set of all identifiers known to this identifier lookup source.
One of these records is kept for each identifier that is lexed.
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const
Return true if this token is a C++ keyword in the specified language.
unsigned getLength() const
Efficiently return the length of this identifier info.
void setModulesImport(bool I)
Set whether this identifier is the contextual keyword import.
void setNotableIdentifierID(unsigned ID)
void setIsExtensionToken(bool Val)
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
tok::TokenKind getTokenID() const
If this is a source-language token (e.g.
void setObjCKeywordID(tok::ObjCKeywordKind ID)
const char * getNameStart() const
Return the beginning of the actual null-terminated string for this identifier.
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is a keyword in the specified language.
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const
Determine whether this is a name reserved for the implementation (C99 7.1.3, C++ [lib....
void setIsCPlusPlusOperatorKeyword(bool Val=true)
isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether this identifier is a C++ al...
ReservedLiteralSuffixIdStatus isReservedLiteralSuffixId() const
Determine whether this is a name reserved for future standardization or the implementation (C++ [usrl...
void setIsFutureCompatKeyword(bool Val)
StringRef deuglifiedName() const
If the identifier is an "uglified" reserved name, return a cleaned form.
StringRef getName() const
Return the actual identifier string.
bool isFutureCompatKeyword() const
is/setIsFutureCompatKeyword - Initialize information about whether or not this language token is a ke...
An iterator that walks over all of the known identifiers in the lookup table.
virtual StringRef Next()=0
Retrieve the next string in the identifier table and advances the iterator for the following string.
virtual ~IdentifierIterator()
Implements an efficient mapping from strings to IdentifierInfo nodes.
IdentifierTable(IdentifierInfoLookup *ExternalLookup=nullptr)
Create the identifier table.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
void PrintStats() const
Print some statistics to stderr that indicate how well the hashing is doing.
void AddKeywords(const LangOptions &LangOpts)
Populate the identifier table with info about the language keywords for the language specified by Lan...
diag::kind getFutureCompatDiagKind(const IdentifierInfo &II, const LangOptions &LangOpts)
Returns the correct diagnostic to issue for a future-compat diagnostic warning.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
One of these variable length records is kept for each selector containing more than one keyword.
keyword_iterator keyword_end() const
const IdentifierInfo *const * keyword_iterator
std::string getName() const
static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs)
keyword_iterator keyword_begin() const
const IdentifierInfo * getIdentifierInfoForSlot(unsigned i) const
This table allows us to fully hide how we implement multi-keyword caching.
static std::string getPropertyNameFromSetterSelector(Selector Sel)
Return the property name for the given setter selector.
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
size_t getTotalMemory() const
Return the total amount of memory allocated for managing selectors.
Selector getSelector(unsigned NumArgs, const IdentifierInfo **IIV)
Can create any sort of selector.
Selector getUnarySelector(const IdentifierInfo *ID)
static SmallString< 64 > constructSetterName(StringRef Name)
Return the default setter name for the given identifier.
Smart pointer class that efficiently represents Objective-C method names.
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
const IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
std::string getAsString() const
Derive the full selector name (e.g.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
bool isKeywordSelector() const
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
bool isUnarySelector() const
bool isNull() const
Determine whether this is the empty selector.
unsigned getNumArgs() const
unsigned kind
All of the diagnostics that can be emitted by the frontend.
NotableIdentifierKind
Provides a namespace for notable identifers such as float_t and double_t.
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
The JSON file list parser is used to communicate input to InstallAPI.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
NullabilityKind
Describes the nullability of a particular type.
@ Nullable
Values of this type can be null.
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
@ NonNull
Values of this type can never be null.
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
ObjCMethodFamily
A family of Objective-C methods.
@ OMF_None
No particular method family.
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ASTContext::SectionInfo &Section)
Insertion operator for diagnostics.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
ObjCInstanceTypeFamily
A family of Objective-C methods.
ReservedLiteralSuffixIdStatus
@ NotStartsWithUnderscore
@ ContainsDoubleUnderscore
LLVM_READONLY bool isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.
static constexpr int InterestingIdentifierBits
static constexpr uint64_t LargestBuiltinID
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword.
@ StartsWithDoubleUnderscore
@ StartsWithUnderscoreFollowedByCapitalLetter
@ ContainsDoubleUnderscore
@ StartsWithUnderscoreAtGlobalScope