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/ErrorHandling.h"
29#include "llvm/Support/raw_ostream.h"
41 "Insufficient ObjCOrBuiltinID Bits");
58 StringRef
Next()
override {
return StringRef(); }
64 return new EmptyLookupIterator();
69 ExternalLookup(ExternalLookup) {}
86 enum TokenKey :
unsigned {
100 WCHARSUPPORT = 0x2000,
101 HALFSUPPORT = 0x4000,
102 CHAR8SUPPORT = 0x8000,
104 KEYZVECTOR = 0x20000,
105 KEYCOROUTINES = 0x40000,
106 KEYMODULES = 0x80000,
108 KEYOPENCLCXX = 0x200000,
109 KEYMSCOMPAT = 0x400000,
114 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
115 KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
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.HLSL ? KS_Enabled : KS_Unknown;
208 return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
216 llvm_unreachable(
"Unknown KeywordStatus flag");
225 if (Flags == KEYALL)
return KS_Enabled;
228 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
return KS_Disabled;
229 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
233 KeywordStatus CurStatus = KS_Unknown;
236 unsigned CurFlag = Flags & ~(Flags - 1);
237 Flags = Flags & ~CurFlag;
238 CurStatus = std::max(
243 if (CurStatus == KS_Unknown)
257 if (AddResult == KS_Disabled)
return;
260 Table.
get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
286#define KEYWORD(NAME, FLAGS) \
287 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
288 FLAGS, LangOpts, *this);
289#define ALIAS(NAME, TOK, FLAGS) \
290 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
291 FLAGS, LangOpts, *this);
292#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
293 if (LangOpts.CXXOperatorNames) \
294 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
295#define OBJC_AT_KEYWORD(NAME) \
297 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
298#define TESTING_KEYWORD(NAME, FLAGS)
299#include "clang/Basic/TokenKinds.def"
301 if (LangOpts.ParseUnknownAnytype)
302 AddKeyword(
"__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
305 if (LangOpts.DeclSpecKeyword)
306 AddKeyword(
"__declspec", tok::kw___declspec, KEYALL, LangOpts, *
this);
308 if (LangOpts.IEEE128)
309 AddKeyword(
"__ieee128", tok::kw___float128, KEYALL, LangOpts, *
this);
321#define KEYWORD(NAME, FLAGS) \
322 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
323#include "clang/Basic/TokenKinds.def"
324 default:
return KS_Disabled;
343 if (!LangOpts.CPlusPlus || !
isKeyword(LangOpts))
348 LangOptsNoCPP.CPlusPlus =
false;
349 LangOptsNoCPP.CPlusPlus11 =
false;
350 LangOptsNoCPP.CPlusPlus20 =
false;
360 if (Name.size() <= 1)
364 if (Name[0] ==
'_') {
371 if (
'A' <= Name[1] && Name[1] <=
'Z')
381 if (LangOpts.CPlusPlus && Name.contains(
"__"))
389 if (Name.size() >= 2 && Name.front() ==
'_' &&
390 (Name[1] ==
'_' || (Name[1] >=
'A' && Name[1] <=
'Z')))
391 return Name.ltrim(
'_');
401#define HASH(LEN, FIRST, THIRD) \
402 (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
403#define CASE(LEN, FIRST, THIRD, NAME) \
404 case HASH(LEN, FIRST, THIRD): \
405 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
408 if (Len < 2)
return tok::pp_not_keyword;
410 switch (
HASH(Len, Name[0], Name[2])) {
411 default:
return tok::pp_not_keyword;
412 CASE( 2,
'i',
'\0',
if);
413 CASE( 4,
'e',
'i', elif);
414 CASE( 4,
'e',
's',
else);
415 CASE( 4,
'l',
'n', line);
416 CASE( 4,
's',
'c', sccs);
417 CASE( 5,
'e',
'd', endif);
418 CASE( 5,
'e',
'r', error);
419 CASE( 5,
'i',
'e', ident);
420 CASE( 5,
'i',
'd', ifdef);
421 CASE( 5,
'u',
'd', undef);
423 CASE( 6,
'a',
's', assert);
424 CASE( 6,
'd',
'f', define);
425 CASE( 6,
'i',
'n', ifndef);
426 CASE( 6,
'i',
'p',
import);
427 CASE( 6,
'p',
'a', pragma);
429 CASE( 7,
'd',
'f', defined);
430 CASE( 7,
'e',
'i', elifdef);
431 CASE( 7,
'i',
'c', include);
432 CASE( 7,
'w',
'r', warning);
434 CASE( 8,
'e',
'i', elifndef);
435 CASE( 8,
'u',
'a', unassert);
436 CASE(12,
'i',
'c', include_next);
438 CASE(14,
'_',
'p', __public_macro);
440 CASE(15,
'_',
'p', __private_macro);
442 CASE(16,
'_',
'i', __include_macros);
455 unsigned NumBuckets = HashTable.getNumBuckets();
456 unsigned NumIdentifiers = HashTable.getNumItems();
457 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
458 unsigned AverageIdentifierSize = 0;
459 unsigned MaxIdentifierLength = 0;
462 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
463 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
464 unsigned IdLen = I->getKeyLength();
465 AverageIdentifierSize += IdLen;
466 if (MaxIdentifierLength < IdLen)
467 MaxIdentifierLength = IdLen;
470 fprintf(stderr,
"\n*** Identifier Table Stats:\n");
471 fprintf(stderr,
"# Identifiers: %d\n", NumIdentifiers);
472 fprintf(stderr,
"# Empty Buckets: %d\n", NumEmptyBuckets);
473 fprintf(stderr,
"Hash density (#identifiers per bucket): %f\n",
474 NumIdentifiers/(
double)NumBuckets);
475 fprintf(stderr,
"Ave identifier length: %f\n",
476 (AverageIdentifierSize/(
double)NumIdentifiers));
477 fprintf(stderr,
"Max identifier length: %d\n", MaxIdentifierLength);
480 HashTable.getAllocator().PrintStats();
488 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
499 public llvm::FoldingSetNode {
505 : DeclarationNameExtra(nKeys) {
506 assert((nKeys > 1) &&
"not a multi-keyword selector");
510 for (
unsigned i = 0; i != nKeys; ++i)
517 using DeclarationNameExtra::getNumArgs;
526 return keyword_begin() + getNumArgs();
530 assert(i < getNumArgs() &&
"getIdentifierInfoForSlot(): illegal index");
531 return keyword_begin()[i];
536 ID.AddInteger(NumArgs);
537 for (
unsigned i = 0; i != NumArgs; ++i)
538 ID.AddPointer(ArgTys[i]);
542 Profile(ID, keyword_begin(), getNumArgs());
549 assert(!Names.empty() &&
"must have >= 1 selector slots");
552 for (
unsigned I = 0, E = Names.size(); I != E; ++I) {
564 unsigned IIF = getIdentifierInfoFlag();
575 if (getIdentifierInfoFlag() < MultiArg) {
576 assert(argIndex == 0 &&
"illegal keyword index");
577 return getAsIdentifierInfo();
587 return II ? II->
getName() : StringRef();
592 llvm::raw_svector_ostream OS(Str);
595 OS << (*I)->getName();
599 return std::string(OS.str());
604 return "<null selector>";
606 if (getIdentifierInfoFlag() < MultiArg) {
610 assert(II &&
"If the number of arguments is 0 then II is guaranteed to "
612 return std::string(II->
getName());
618 return II->
getName().str() +
":";
622 return getMultiKeywordSelector()->
getName();
635 if (name.size() < word.size())
return false;
636 return ((name.size() == word.size() || !
isLowercase(name[word.size()])) &&
637 name.startswith(word));
652 if (name ==
"self")
return OMF_self;
656 if (name ==
"performSelector" || name ==
"performSelectorInBackground" ||
657 name ==
"performSelectorOnMainThread")
661 while (!
name.empty() &&
name.front() ==
'_')
665 switch (
name.front()) {
692 StringRef name = first->
getName();
695 switch (name.front()) {
720 StringRef name = first->
getName();
722 switch (name.front()) {
732 if (name ==
"localizedStringWithFormat")
return SFF_NSString;
736 if (name ==
"stringByAppendingFormat" ||
745struct SelectorTableImpl {
746 llvm::FoldingSet<MultiKeywordSelector> Table;
747 llvm::BumpPtrAllocator Allocator;
753 return *
static_cast<SelectorTableImpl*
>(
P);
775 assert(Name.startswith(
"set") &&
"invalid setter name");
776 return (Twine(
toLowercase(Name[3])) + Name.drop_front(4)).str();
781 return SelTabImpl.Allocator.getTotalMemory();
791 llvm::FoldingSetNodeID ID;
794 void *InsertPos =
nullptr;
796 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
806 SelTabImpl.Table.InsertNode(SI, InsertPos);
811 Impl =
new SelectorTableImpl();
824#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
825 case OO_##Name: return Spelling;
826#include "clang/Basic/OperatorKinds.def"
829 llvm_unreachable(
"Invalid OverloadedOperatorKind!");
833 bool isContextSensitive) {
836 return isContextSensitive ?
"nonnull" :
"_Nonnull";
839 return isContextSensitive ?
"nullable" :
"_Nullable";
842 assert(!isContextSensitive &&
843 "_Nullable_result isn't supported as context-sensitive keyword");
844 return "_Nullable_result";
847 return isContextSensitive ?
"null_unspecified" :
"_Null_unspecified";
849 llvm_unreachable(
"Unknown nullability kind.");
857 unsigned Flags = llvm::StringSwitch<unsigned>(II.
getName())
858#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
859#include "clang/Basic/TokenKinds.def"
863 if (LangOpts.CPlusPlus) {
864 if ((Flags & KEYCXX11) == KEYCXX11)
865 return diag::warn_cxx11_keyword;
870 if (((Flags & KEYCXX20) == KEYCXX20) ||
871 ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
872 return diag::warn_cxx20_keyword;
874 if ((Flags & KEYC99) == KEYC99)
875 return diag::warn_c99_keyword;
876 if ((Flags & KEYC2X) == KEYC2X)
877 return diag::warn_c2x_keyword;
881 "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 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.
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...
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.
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.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.
ObjCInstanceTypeFamily
A family of Objective-C methods.
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