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) {}
84 enum TokenKey :
unsigned {
98 WCHARSUPPORT = 0x2000,
100 CHAR8SUPPORT = 0x8000,
102 KEYZVECTOR = 0x20000,
103 KEYCOROUTINES = 0x40000,
104 KEYMODULES = 0x80000,
106 KEYOPENCLCXX = 0x200000,
107 KEYMSCOMPAT = 0x400000,
112 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
113 KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
139 assert((Flag & ~(Flag - 1)) == Flag &&
"Multiple bits set?");
145 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
149 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151 return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
153 if (LangOpts.CPlusPlus11)
155 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
157 if (LangOpts.CPlusPlus20)
159 return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
161 return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
163 return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
165 if (LangOpts.Bool)
return KS_Enabled;
166 return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
168 return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
170 return LangOpts.Borland ? KS_Extension : KS_Unknown;
172 return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
175 return LangOpts.WChar ? KS_Enabled : KS_Unknown;
177 return LangOpts.Half ? KS_Enabled : KS_Unknown;
179 if (LangOpts.Char8)
return KS_Enabled;
180 if (LangOpts.CPlusPlus20)
return KS_Unknown;
181 if (LangOpts.CPlusPlus)
return KS_Future;
186 return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
188 return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
190 return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
194 return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
196 return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
198 return LangOpts.
isSYCL() ? KS_Enabled : KS_Unknown;
200 return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
202 return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
206 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
214 llvm_unreachable(
"Unknown KeywordStatus flag");
223 if (Flags == KEYALL)
return KS_Enabled;
226 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
return KS_Disabled;
227 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
231 KeywordStatus CurStatus = KS_Unknown;
234 unsigned CurFlag = Flags & ~(Flags - 1);
235 Flags = Flags & ~CurFlag;
236 CurStatus = std::max(
241 if (CurStatus == KS_Unknown)
255 if (AddResult == KS_Disabled)
return;
258 Table.
get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
284 if (BTID != tok::not_interesting) {
294#define KEYWORD(NAME, FLAGS) \
295 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
296 FLAGS, LangOpts, *this);
297#define ALIAS(NAME, TOK, FLAGS) \
298 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
299 FLAGS, LangOpts, *this);
300#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
301 if (LangOpts.CXXOperatorNames) \
302 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
303#define OBJC_AT_KEYWORD(NAME) \
305 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
306#define INTERESTING_IDENTIFIER(NAME) \
307 AddInterestingIdentifier(StringRef(#NAME), tok::NAME, *this);
309#define TESTING_KEYWORD(NAME, FLAGS)
310#include "clang/Basic/TokenKinds.def"
312 if (LangOpts.ParseUnknownAnytype)
313 AddKeyword(
"__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
316 if (LangOpts.DeclSpecKeyword)
317 AddKeyword(
"__declspec", tok::kw___declspec, KEYALL, LangOpts, *
this);
319 if (LangOpts.IEEE128)
320 AddKeyword(
"__ieee128", tok::kw___float128, KEYALL, LangOpts, *
this);
332#define KEYWORD(NAME, FLAGS) \
333 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
334#include "clang/Basic/TokenKinds.def"
335 default:
return KS_Disabled;
354 if (!LangOpts.CPlusPlus || !
isKeyword(LangOpts))
359 LangOptsNoCPP.CPlusPlus =
false;
360 LangOptsNoCPP.CPlusPlus11 =
false;
361 LangOptsNoCPP.CPlusPlus20 =
false;
371 if (Name.size() <= 1)
375 if (Name[0] ==
'_') {
382 if (
'A' <= Name[1] && Name[1] <=
'Z')
392 if (LangOpts.CPlusPlus && Name.contains(
"__"))
405 if (Name.contains(
"__"))
413 if (Name.size() >= 2 && Name.front() ==
'_' &&
414 (Name[1] ==
'_' || (Name[1] >=
'A' && Name[1] <=
'Z')))
415 return Name.ltrim(
'_');
425#define HASH(LEN, FIRST, THIRD) \
426 (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
427#define CASE(LEN, FIRST, THIRD, NAME) \
428 case HASH(LEN, FIRST, THIRD): \
429 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
432 if (Len < 2)
return tok::pp_not_keyword;
434 switch (
HASH(Len, Name[0], Name[2])) {
435 default:
return tok::pp_not_keyword;
436 CASE( 2,
'i',
'\0',
if);
437 CASE( 4,
'e',
'i', elif);
438 CASE( 4,
'e',
's',
else);
439 CASE( 4,
'l',
'n', line);
440 CASE( 4,
's',
'c', sccs);
441 CASE( 5,
'e',
'd', endif);
442 CASE( 5,
'e',
'r', error);
443 CASE( 5,
'i',
'e', ident);
444 CASE( 5,
'i',
'd', ifdef);
445 CASE( 5,
'u',
'd', undef);
447 CASE( 6,
'a',
's', assert);
448 CASE( 6,
'd',
'f', define);
449 CASE( 6,
'i',
'n', ifndef);
450 CASE( 6,
'i',
'p',
import);
451 CASE( 6,
'p',
'a', pragma);
453 CASE( 7,
'd',
'f', defined);
454 CASE( 7,
'e',
'i', elifdef);
455 CASE( 7,
'i',
'c', include);
456 CASE( 7,
'w',
'r', warning);
458 CASE( 8,
'e',
'i', elifndef);
459 CASE( 8,
'u',
'a', unassert);
460 CASE(12,
'i',
'c', include_next);
462 CASE(14,
'_',
'p', __public_macro);
464 CASE(15,
'_',
'p', __private_macro);
466 CASE(16,
'_',
'i', __include_macros);
479 unsigned NumBuckets = HashTable.getNumBuckets();
480 unsigned NumIdentifiers = HashTable.getNumItems();
481 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
482 unsigned AverageIdentifierSize = 0;
483 unsigned MaxIdentifierLength = 0;
486 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
487 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
488 unsigned IdLen = I->getKeyLength();
489 AverageIdentifierSize += IdLen;
490 if (MaxIdentifierLength < IdLen)
491 MaxIdentifierLength = IdLen;
494 fprintf(stderr,
"\n*** Identifier Table Stats:\n");
495 fprintf(stderr,
"# Identifiers: %d\n", NumIdentifiers);
496 fprintf(stderr,
"# Empty Buckets: %d\n", NumEmptyBuckets);
497 fprintf(stderr,
"Hash density (#identifiers per bucket): %f\n",
498 NumIdentifiers/(
double)NumBuckets);
499 fprintf(stderr,
"Ave identifier length: %f\n",
500 (AverageIdentifierSize/(
double)NumIdentifiers));
501 fprintf(stderr,
"Max identifier length: %d\n", MaxIdentifierLength);
504 HashTable.getAllocator().PrintStats();
512 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
523 public llvm::FoldingSetNode {
529 : DeclarationNameExtra(nKeys) {
530 assert((nKeys > 1) &&
"not a multi-keyword selector");
534 for (
unsigned i = 0; i != nKeys; ++i)
541 using DeclarationNameExtra::getNumArgs;
550 return keyword_begin() + getNumArgs();
554 assert(i < getNumArgs() &&
"getIdentifierInfoForSlot(): illegal index");
555 return keyword_begin()[i];
560 ID.AddInteger(NumArgs);
561 for (
unsigned i = 0; i != NumArgs; ++i)
562 ID.AddPointer(ArgTys[i]);
566 Profile(
ID, keyword_begin(), getNumArgs());
573 assert(!Names.empty() &&
"must have >= 1 selector slots");
576 for (
unsigned I = 0, E = Names.size(); I != E; ++I) {
588 unsigned IIF = getIdentifierInfoFlag();
599 if (getIdentifierInfoFlag() < MultiArg) {
600 assert(argIndex == 0 &&
"illegal keyword index");
601 return getAsIdentifierInfo();
611 return II ? II->
getName() : StringRef();
616 llvm::raw_svector_ostream OS(Str);
619 OS << (*I)->getName();
623 return std::string(OS.str());
628 return "<null selector>";
630 if (getIdentifierInfoFlag() < MultiArg) {
634 assert(II &&
"If the number of arguments is 0 then II is guaranteed to "
636 return std::string(II->
getName());
642 return II->
getName().str() +
":";
646 return getMultiKeywordSelector()->
getName();
659 if (name.size() < word.size())
return false;
660 return ((name.size() == word.size() || !
isLowercase(name[word.size()])) &&
661 name.startswith(word));
676 if (name ==
"self")
return OMF_self;
680 if (name ==
"performSelector" || name ==
"performSelectorInBackground" ||
681 name ==
"performSelectorOnMainThread")
685 while (!
name.empty() &&
name.front() ==
'_')
689 switch (
name.front()) {
716 StringRef name = first->
getName();
719 switch (name.front()) {
744 StringRef name = first->
getName();
746 switch (name.front()) {
756 if (name ==
"localizedStringWithFormat")
return SFF_NSString;
760 if (name ==
"stringByAppendingFormat" ||
769struct SelectorTableImpl {
770 llvm::FoldingSet<MultiKeywordSelector> Table;
771 llvm::BumpPtrAllocator Allocator;
777 return *
static_cast<SelectorTableImpl*
>(
P);
799 assert(Name.startswith(
"set") &&
"invalid setter name");
800 return (Twine(
toLowercase(Name[3])) + Name.drop_front(4)).str();
805 return SelTabImpl.Allocator.getTotalMemory();
815 llvm::FoldingSetNodeID ID;
818 void *InsertPos =
nullptr;
820 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
830 SelTabImpl.Table.InsertNode(SI, InsertPos);
835 Impl =
new SelectorTableImpl();
848#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
849 case OO_##Name: return Spelling;
850#include "clang/Basic/OperatorKinds.def"
853 llvm_unreachable(
"Invalid OverloadedOperatorKind!");
857 bool isContextSensitive) {
860 return isContextSensitive ?
"nonnull" :
"_Nonnull";
863 return isContextSensitive ?
"nullable" :
"_Nullable";
866 assert(!isContextSensitive &&
867 "_Nullable_result isn't supported as context-sensitive keyword");
868 return "_Nullable_result";
871 return isContextSensitive ?
"null_unspecified" :
"_Null_unspecified";
873 llvm_unreachable(
"Unknown nullability kind.");
880 return OS <<
"NonNull";
882 return OS <<
"Nullable";
884 return OS <<
"NullableResult";
886 return OS <<
"Unspecified";
888 llvm_unreachable(
"Unknown nullability kind.");
896 unsigned Flags = llvm::StringSwitch<unsigned>(II.
getName())
897#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
898#include "clang/Basic/TokenKinds.def"
902 if (LangOpts.CPlusPlus) {
903 if ((Flags & KEYCXX11) == KEYCXX11)
904 return diag::warn_cxx11_keyword;
909 if (((Flags & KEYCXX20) == KEYCXX20) ||
910 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
911 return diag::warn_cxx20_keyword;
913 if ((Flags & KEYC99) == KEYC99)
914 return diag::warn_c99_keyword;
915 if ((Flags & KEYC23) == KEYC23)
916 return diag::warn_c23_keyword;
920 "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 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 AddInterestingIdentifier(StringRef Name, tok::InterestingIdentifierKind BTID, IdentifierTable &Table)
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.
static std::string getName(const CallEvent &Call)
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.
void setInterestingIdentifierID(unsigned ID)
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 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
std::string getName() const
IdentifierInfo *const * keyword_iterator
void Profile(llvm::FoldingSetNodeID &ID)
IdentifierInfo * getIdentifierInfoForSlot(unsigned i) const
static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs)
keyword_iterator keyword_begin() const
MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
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, IdentifierInfo **IIV)
Can create any sort of selector.
static SmallString< 64 > constructSetterName(StringRef Name)
Return the default setter name for the given identifier.
Selector getUnarySelector(IdentifierInfo *ID)
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.
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
unsigned getNumArgs() const
unsigned kind
All of the diagnostics that can be emitted by the frontend.
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
InterestingIdentifierKind
Provides a namespace for interesting identifers such as float_t and double_t.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
@ OO_None
Not an overloaded operator.
@ NUM_OVERLOADED_OPERATORS
static constexpr int ObjCOrBuiltinIDBits
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 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