22#include "llvm/ADT/DenseMapInfo.h"
23#include "llvm/ADT/FoldingSet.h"
24#include "llvm/ADT/StringMap.h"
25#include "llvm/ADT/StringRef.h"
26#include "llvm/Support/Allocator.h"
27#include "llvm/Support/raw_ostream.h"
39 "Insufficient ObjCOrBuiltinID Bits");
55 StringRef
Next()
override {
return StringRef(); }
61 return new EmptyLookupIterator();
66 ExternalLookup(ExternalLookup) {}
83enum TokenKey :
unsigned {
97 WCHARSUPPORT = 0x2000,
99 CHAR8SUPPORT = 0x8000,
101 KEYZVECTOR = 0x20000,
102 KEYCOROUTINES = 0x40000,
103 KEYMODULES = 0x80000,
105 KEYOPENCLCXX = 0x200000,
106 KEYMSCOMPAT = 0x400000,
110 KEYNOZOS = 0x4000000,
112 KEYFIXEDPOINT = 0x10000000,
113 KEYMAX = KEYFIXEDPOINT,
114 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
115 KEYALL = (KEYMAX | (KEYMAX - 1)) & ~KEYNOMS18 & ~KEYNOOPENCL &
141 assert((Flag & ~(Flag - 1)) == Flag &&
"Multiple bits set?");
147 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
153 return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
155 if (LangOpts.CPlusPlus11)
157 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
159 if (LangOpts.CPlusPlus20)
161 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
163 return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
165 return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
167 if (LangOpts.Bool)
return KS_Enabled;
168 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
170 return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
172 return LangOpts.Borland ? KS_Extension : KS_Unknown;
174 return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
177 return LangOpts.WChar ? KS_Enabled : KS_Unknown;
179 return LangOpts.Half ? KS_Enabled : KS_Unknown;
181 if (LangOpts.Char8)
return KS_Enabled;
182 if (LangOpts.CPlusPlus20)
return KS_Unknown;
183 if (LangOpts.CPlusPlus)
return KS_Future;
188 return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
190 return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
192 return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
196 return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
198 return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
200 return LangOpts.
isSYCL() ? KS_Enabled : KS_Unknown;
202 return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
204 return LangOpts.ZOSExt ? KS_Enabled : KS_Unknown;
206 return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
210 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
217 return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
219 llvm_unreachable(
"Unknown KeywordStatus flag");
228 if (Flags == KEYALL)
return KS_Enabled;
231 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
return KS_Disabled;
232 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
235 if (LangOpts.ZOSExt && (Flags & KEYNOZOS))
237 KeywordStatus CurStatus = KS_Unknown;
240 unsigned CurFlag = Flags & ~(Flags - 1);
241 Flags = Flags & ~CurFlag;
242 CurStatus = std::max(
247 if (CurStatus == KS_Unknown)
253 return (Flags & (KEYCXX | KEYCXX11 | KEYCXX20 | BOOLSUPPORT | WCHARSUPPORT |
274 if (AddResult == KS_Disabled) {
286 Table.
get(
Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
312 if (BTID != tok::not_notable) {
322#define KEYWORD(NAME, FLAGS) \
323 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
324 FLAGS, LangOpts, *this);
325#define ALIAS(NAME, TOK, FLAGS) \
326 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
327 FLAGS, LangOpts, *this);
328#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
329 if (LangOpts.CXXOperatorNames) \
330 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this); \
332 MarkIdentifierAsKeywordInCpp(*this, StringRef(#NAME));
333#define OBJC_AT_KEYWORD(NAME) \
335 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
336#define NOTABLE_IDENTIFIER(NAME) \
337 AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
339#define TESTING_KEYWORD(NAME, FLAGS)
340#include "clang/Basic/TokenKinds.def"
342 if (LangOpts.ParseUnknownAnytype)
343 AddKeyword(
"__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
346 if (LangOpts.DeclSpecKeyword)
347 AddKeyword(
"__declspec", tok::kw___declspec, KEYALL, LangOpts, *
this);
349 if (LangOpts.IEEE128)
350 AddKeyword(
"__ieee128", tok::kw___float128, KEYALL, LangOpts, *
this);
362#define KEYWORD(NAME, FLAGS) \
363 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
364#include "clang/Basic/TokenKinds.def"
365 default:
return KS_Disabled;
384 if (!LangOpts.CPlusPlus || !
isKeyword(LangOpts))
389 LangOptsNoCPP.CPlusPlus =
false;
390 LangOptsNoCPP.CPlusPlus11 =
false;
391 LangOptsNoCPP.CPlusPlus20 =
false;
401 if (Name.size() <= 1)
405 if (Name[0] ==
'_') {
412 if (
'A' <= Name[1] && Name[1] <=
'Z')
422 if (LangOpts.CPlusPlus && Name.contains(
"__"))
438 if (Name.contains(
"__"))
446 if (Name.size() >= 2 && Name.front() ==
'_' &&
447 (Name[1] ==
'_' || (Name[1] >=
'A' && Name[1] <=
'Z')))
448 return Name.ltrim(
'_');
458#define HASH(LEN, FIRST, THIRD) \
459 (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
460#define CASE(LEN, FIRST, THIRD, NAME) \
461 case HASH(LEN, FIRST, THIRD): \
462 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
465 if (Len < 2)
return tok::pp_not_keyword;
467 switch (
HASH(Len, Name[0], Name[2])) {
468 default:
return tok::pp_not_keyword;
469 CASE( 2,
'i',
'\0',
if);
470 CASE( 4,
'e',
'i', elif);
471 CASE( 4,
'e',
's',
else);
472 CASE( 4,
'l',
'n', line);
473 CASE( 4,
's',
'c', sccs);
474 CASE( 5,
'e',
'b', embed);
475 CASE( 5,
'e',
'd', endif);
476 CASE( 5,
'e',
'r', error);
477 CASE( 5,
'i',
'e', ident);
478 CASE( 5,
'i',
'd', ifdef);
479 CASE( 5,
'u',
'd', undef);
481 CASE( 6,
'a',
's', assert);
482 CASE( 6,
'd',
'f', define);
483 CASE( 6,
'i',
'n', ifndef);
484 CASE( 6,
'i',
'p',
import);
485 CASE( 6,
'p',
'a', pragma);
487 CASE( 7,
'd',
'f', defined);
488 CASE( 7,
'e',
'i', elifdef);
489 CASE( 7,
'i',
'c', include);
490 CASE( 7,
'w',
'r', warning);
492 CASE( 8,
'e',
'i', elifndef);
493 CASE( 8,
'u',
'a', unassert);
494 CASE(12,
'i',
'c', include_next);
496 CASE(14,
'_',
'p', __public_macro);
498 CASE(15,
'_',
'p', __private_macro);
500 CASE(16,
'_',
'i', __include_macros);
513 unsigned NumBuckets = HashTable.getNumBuckets();
514 unsigned NumIdentifiers = HashTable.getNumItems();
515 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
516 unsigned AverageIdentifierSize = 0;
517 unsigned MaxIdentifierLength = 0;
520 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
521 I = HashTable.begin(),
E = HashTable.end(); I !=
E; ++I) {
522 unsigned IdLen = I->getKeyLength();
523 AverageIdentifierSize += IdLen;
524 if (MaxIdentifierLength < IdLen)
525 MaxIdentifierLength = IdLen;
528 fprintf(stderr,
"\n*** Identifier Table Stats:\n");
529 fprintf(stderr,
"# Identifiers: %d\n", NumIdentifiers);
530 fprintf(stderr,
"# Empty Buckets: %d\n", NumEmptyBuckets);
531 fprintf(stderr,
"Hash density (#identifiers per bucket): %f\n",
532 NumIdentifiers/(
double)NumBuckets);
533 fprintf(stderr,
"Ave identifier length: %f\n",
534 (AverageIdentifierSize/(
double)NumIdentifiers));
535 fprintf(stderr,
"Max identifier length: %d\n", MaxIdentifierLength);
538 HashTable.getAllocator().PrintStats();
546 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
550 assert(!Names.empty() &&
"must have >= 1 selector slots");
553 for (
unsigned I = 0,
E = Names.size(); I !=
E; ++I) {
565 unsigned IIF = getIdentifierInfoFlag();
577 if (getIdentifierInfoFlag() < MultiArg) {
578 assert(argIndex == 0 &&
"illegal keyword index");
579 return getAsIdentifierInfo();
589 return II ? II->
getName() : StringRef();
594 llvm::raw_svector_ostream OS(Str);
597 OS << (*I)->getName();
601 return std::string(OS.str());
606 return "<null selector>";
608 if (getIdentifierInfoFlag() < MultiArg) {
612 assert(II &&
"If the number of arguments is 0 then II is guaranteed to "
614 return std::string(II->
getName());
620 return II->
getName().str() +
":";
624 return getMultiKeywordSelector()->
getName();
637 if (name.size() < word.size())
return false;
638 return ((name.size() == word.size() || !
isLowercase(name[word.size()])) &&
639 name.starts_with(word));
654 if (name ==
"self")
return OMF_self;
658 if (name ==
"performSelector" || name ==
"performSelectorInBackground" ||
659 name ==
"performSelectorOnMainThread")
666 switch (
name.front()) {
693 StringRef name = first->
getName();
696 switch (name.front()) {
721 StringRef name = first->
getName();
723 switch (name.front()) {
733 if (name ==
"localizedStringWithFormat")
return SFF_NSString;
737 if (name ==
"stringByAppendingFormat" ||
746struct SelectorTableImpl {
747 llvm::FoldingSet<MultiKeywordSelector> Table;
748 llvm::BumpPtrAllocator Allocator;
754 return *
static_cast<SelectorTableImpl*
>(
P);
776 assert(Name.starts_with(
"set") &&
"invalid setter name");
777 return (Twine(
toLowercase(Name[3])) + Name.drop_front(4)).str();
782 return SelTabImpl.Allocator.getTotalMemory();
793 llvm::FoldingSetNodeID ID;
796 void *InsertPos =
nullptr;
798 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
808 SelTabImpl.Table.InsertNode(SI, InsertPos);
813 Impl =
new SelectorTableImpl();
826#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
827 case OO_##Name: return Spelling;
828#include "clang/Basic/OperatorKinds.def"
831 llvm_unreachable(
"Invalid OverloadedOperatorKind!");
835 bool isContextSensitive) {
838 return isContextSensitive ?
"nonnull" :
"_Nonnull";
841 return isContextSensitive ?
"nullable" :
"_Nullable";
844 assert(!isContextSensitive &&
845 "_Nullable_result isn't supported as context-sensitive keyword");
846 return "_Nullable_result";
849 return isContextSensitive ?
"null_unspecified" :
"_Null_unspecified";
851 llvm_unreachable(
"Unknown nullability kind.");
858 return OS <<
"NonNull";
860 return OS <<
"Nullable";
862 return OS <<
"NullableResult";
864 return OS <<
"Unspecified";
866 llvm_unreachable(
"Unknown nullability kind.");
874 unsigned Flags = llvm::StringSwitch<unsigned>(II.
getName())
875#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
876#include "clang/Basic/TokenKinds.def"
880 if (LangOpts.CPlusPlus) {
881 if ((Flags & KEYCXX11) == KEYCXX11)
882 return diag::warn_cxx11_keyword;
887 if (((Flags & KEYCXX20) == KEYCXX20) ||
888 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
889 return diag::warn_cxx20_keyword;
891 if ((Flags & KEYC99) == KEYC99)
892 return diag::warn_c99_keyword;
893 if ((Flags & KEYC23) == KEYC23)
894 return diag::warn_c23_keyword;
898 "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 bool IsKeywordInCpp(unsigned Flags)
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 void MarkIdentifierAsKeywordInCpp(IdentifierTable &Table, StringRef Name)
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)
void setHandleIdentifierCase(bool Val=true)
void setIsKeywordInCPlusPlus(bool Val=true)
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.
@ Keyword
The name has been typo-corrected to a keyword.
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