21 #include "llvm/ADT/DenseMapInfo.h" 22 #include "llvm/ADT/FoldingSet.h" 23 #include "llvm/ADT/SmallString.h" 24 #include "llvm/ADT/StringMap.h" 25 #include "llvm/ADT/StringRef.h" 26 #include "llvm/Support/Allocator.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/raw_ostream.h" 34 using namespace clang;
41 TokenID = tok::identifier;
46 IsFutureCompatKeyword =
false;
48 IsCPPOperatorKeyword =
false;
49 NeedsHandleIdentifier =
false;
51 ChangedAfterLoad =
false;
52 FEChangedAfterLoad =
false;
53 RevertedTokenID =
false;
55 IsModulesImport =
false;
73 StringRef Next()
override {
return StringRef(); }
79 return new EmptyLookupIterator();
84 ExternalLookup(ExternalLookup) {}
115 KEYNOOPENCL = 0x02000,
116 WCHARSUPPORT = 0x04000,
117 HALFSUPPORT = 0x08000,
118 CHAR8SUPPORT = 0x10000,
119 KEYCONCEPTS = 0x20000,
121 KEYZVECTOR = 0x80000,
122 KEYCOROUTINES = 0x100000,
123 KEYMODULES = 0x200000,
125 KEYOPENCLCXX = 0x800000,
126 KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX2A,
127 KEYALL = (0xffffff & ~KEYNOMS18 &
145 if (Flags == KEYALL)
return KS_Enabled;
146 if (LangOpts.CPlusPlus && (Flags & KEYCXX))
return KS_Enabled;
147 if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11))
return KS_Enabled;
148 if (LangOpts.CPlusPlus2a && (Flags & KEYCXX2A))
return KS_Enabled;
149 if (LangOpts.C99 && (Flags & KEYC99))
return KS_Enabled;
150 if (LangOpts.GNUKeywords && (Flags & KEYGNU))
return KS_Extension;
151 if (LangOpts.MicrosoftExt && (Flags & KEYMS))
return KS_Extension;
152 if (LangOpts.Borland && (Flags & KEYBORLAND))
return KS_Extension;
153 if (LangOpts.Bool && (Flags & BOOLSUPPORT))
return KS_Enabled;
154 if (LangOpts.Half && (Flags & HALFSUPPORT))
return KS_Enabled;
155 if (LangOpts.WChar && (Flags & WCHARSUPPORT))
return KS_Enabled;
156 if (LangOpts.Char8 && (Flags & CHAR8SUPPORT))
return KS_Enabled;
157 if (LangOpts.AltiVec && (Flags & KEYALTIVEC))
return KS_Enabled;
158 if (LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLC))
160 if (LangOpts.OpenCLCPlusPlus && (Flags & KEYOPENCLCXX))
return KS_Enabled;
161 if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX))
return KS_Enabled;
162 if (LangOpts.C11 && (Flags & KEYC11))
return KS_Enabled;
165 if (LangOpts.ObjC2 && (Flags & KEYARC))
return KS_Enabled;
166 if (LangOpts.ObjC2 && (Flags & KEYOBJC2))
return KS_Enabled;
167 if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS))
return KS_Enabled;
168 if (LangOpts.CoroutinesTS && (Flags & KEYCOROUTINES))
return KS_Enabled;
169 if (LangOpts.ModulesTS && (Flags & KEYMODULES))
return KS_Enabled;
170 if (LangOpts.CPlusPlus && (Flags & KEYALLCXX))
return KS_Future;
183 if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
188 if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
192 if (AddResult == KS_Disabled)
return;
195 Table.
get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
221 #define KEYWORD(NAME, FLAGS) \ 222 AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \ 223 FLAGS, LangOpts, *this); 224 #define ALIAS(NAME, TOK, FLAGS) \ 225 AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \ 226 FLAGS, LangOpts, *this); 227 #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \ 228 if (LangOpts.CXXOperatorNames) \ 229 AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this); 230 #define OBJC1_AT_KEYWORD(NAME) \ 231 if (LangOpts.ObjC1) \ 232 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this); 233 #define OBJC2_AT_KEYWORD(NAME) \ 234 if (LangOpts.ObjC2) \ 235 AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this); 236 #define TESTING_KEYWORD(NAME, FLAGS) 237 #include "clang/Basic/TokenKinds.def" 239 if (LangOpts.ParseUnknownAnytype)
240 AddKeyword(
"__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
243 if (LangOpts.DeclSpecKeyword)
244 AddKeyword(
"__declspec", tok::kw___declspec, KEYALL, LangOpts, *
this);
247 get(
"import").setModulesImport(
true);
256 #define KEYWORD(NAME, FLAGS) \ 257 case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS); 258 #include "clang/Basic/TokenKinds.def" 259 default:
return KS_Disabled;
278 if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
283 LangOptsNoCPP.CPlusPlus =
false;
284 LangOptsNoCPP.CPlusPlus11 =
false;
285 LangOptsNoCPP.CPlusPlus2a =
false;
286 return !isKeyword(LangOptsNoCPP);
295 #define HASH(LEN, FIRST, THIRD) \ 296 (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31) 297 #define CASE(LEN, FIRST, THIRD, NAME) \ 298 case HASH(LEN, FIRST, THIRD): \ 299 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME 301 unsigned Len = getLength();
302 if (Len < 2)
return tok::pp_not_keyword;
303 const char *Name = getNameStart();
304 switch (
HASH(Len, Name[0], Name[2])) {
305 default:
return tok::pp_not_keyword;
306 CASE( 2,
'i',
'\0',
if);
307 CASE( 4,
'e',
'i', elif);
308 CASE( 4,
'e',
's',
else);
309 CASE( 4,
'l',
'n', line);
310 CASE( 4,
's',
'c', sccs);
311 CASE( 5,
'e',
'd', endif);
312 CASE( 5,
'e',
'r', error);
313 CASE( 5,
'i',
'e', ident);
314 CASE( 5,
'i',
'd', ifdef);
315 CASE( 5,
'u',
'd', undef);
317 CASE( 6,
'a',
's', assert);
318 CASE( 6,
'd',
'f', define);
319 CASE( 6,
'i',
'n', ifndef);
320 CASE( 6,
'i',
'p',
import);
321 CASE( 6,
'p',
'a', pragma);
323 CASE( 7,
'd',
'f', defined);
324 CASE( 7,
'i',
'c', include);
325 CASE( 7,
'w',
'r', warning);
327 CASE( 8,
'u',
'a', unassert);
328 CASE(12,
'i',
'c', include_next);
330 CASE(14,
'_',
'p', __public_macro);
332 CASE(15,
'_',
'p', __private_macro);
334 CASE(16,
'_',
'i', __include_macros);
347 unsigned NumBuckets = HashTable.getNumBuckets();
348 unsigned NumIdentifiers = HashTable.getNumItems();
349 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
350 unsigned AverageIdentifierSize = 0;
351 unsigned MaxIdentifierLength = 0;
354 for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
355 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
356 unsigned IdLen = I->getKeyLength();
357 AverageIdentifierSize += IdLen;
358 if (MaxIdentifierLength < IdLen)
359 MaxIdentifierLength = IdLen;
362 fprintf(stderr,
"\n*** Identifier Table Stats:\n");
363 fprintf(stderr,
"# Identifiers: %d\n", NumIdentifiers);
364 fprintf(stderr,
"# Empty Buckets: %d\n", NumEmptyBuckets);
365 fprintf(stderr,
"Hash density (#identifiers per bucket): %f\n",
366 NumIdentifiers/(
double)NumBuckets);
367 fprintf(stderr,
"Ave identifier length: %f\n",
368 (AverageIdentifierSize/(
double)NumIdentifiers));
369 fprintf(stderr,
"Max identifier length: %d\n", MaxIdentifierLength);
372 HashTable.getAllocator().PrintStats();
392 ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
398 assert((nKeys > 1) &&
"not a multi-keyword selector");
399 ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
403 for (
unsigned i = 0; i != nKeys; ++i)
410 unsigned getNumArgs()
const {
return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
419 return keyword_begin()+getNumArgs();
423 assert(i < getNumArgs() &&
"getIdentifierInfoForSlot(): illegal index");
424 return keyword_begin()[i];
429 ID.AddInteger(NumArgs);
430 for (
unsigned i = 0; i != NumArgs; ++i)
431 ID.AddPointer(ArgTys[i]);
435 Profile(ID, keyword_begin(), getNumArgs());
442 unsigned IIF = getIdentifierInfoFlag();
453 if (getIdentifierInfoFlag() < MultiArg) {
454 assert(argIndex == 0 &&
"illegal keyword index");
455 return getAsIdentifierInfo();
465 return II? II->
getName() : StringRef();
470 llvm::raw_svector_ostream OS(Str);
471 for (
keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
473 OS << (*I)->getName();
482 return "<null selector>";
484 if (getIdentifierInfoFlag() < MultiArg) {
487 if (getNumArgs() == 0) {
488 assert(II &&
"If the number of arguments is 0 then II is guaranteed to " 496 return II->
getName().str() +
":";
500 return getMultiKeywordSelector()->getName();
513 if (name.size() < word.size())
return false;
514 return ((name.size() == word.size() || !
isLowercase(name[word.size()])) &&
515 name.startswith(word));
522 StringRef name = first->
getName();
530 if (name ==
"self")
return OMF_self;
534 if (name ==
"performSelector" || name ==
"performSelectorInBackground" ||
535 name ==
"performSelectorOnMainThread")
539 while (!name.empty() && name.front() ==
'_')
540 name = name.substr(1);
543 switch (name.front()) {
570 StringRef name = first->
getName();
573 switch (name.front()) {
597 StringRef name = first->
getName();
599 switch (name.front()) {
609 if (name ==
"localizedStringWithFormat")
return SFF_NSString;
613 if (name ==
"stringByAppendingFormat" ||
622 struct SelectorTableImpl {
623 llvm::FoldingSet<MultiKeywordSelector> Table;
624 llvm::BumpPtrAllocator Allocator;
630 return *
static_cast<SelectorTableImpl*
>(
P);
646 &Idents.
get(constructSetterName(Name->
getName()));
652 assert(Name.startswith(
"set") &&
"invalid setter name");
653 return (Twine(
toLowercase(Name[3])) + Name.drop_front(4)).str();
658 return SelTabImpl.Allocator.getTotalMemory();
668 llvm::FoldingSetNodeID
ID;
671 void *InsertPos =
nullptr;
673 SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
683 SelTabImpl.Table.InsertNode(SI, InsertPos);
688 Impl =
new SelectorTableImpl();
701 #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \ 702 case OO_##Name: return Spelling; 703 #include "clang/Basic/OperatorKinds.def" 706 llvm_unreachable(
"Invalid OverloadedOperatorKind!");
710 bool isContextSensitive) {
713 return isContextSensitive ?
"nonnull" :
"_Nonnull";
716 return isContextSensitive ?
"nullable" :
"_Nullable";
719 return isContextSensitive ?
"null_unspecified" :
"_Null_unspecified";
721 llvm_unreachable(
"Unknown nullability kind.");
void AddKeywords(const LangOptions &LangOpts)
Populate the identifier table with info about the language keywords for the language specified by Lan...
Smart pointer class that efficiently represents Objective-C method names.
void * getAsOpaquePtr() const
bool isCompatibleWithMSVC(MSVCMajorVersion MajorVersion) const
void PrintStats() const
Print some statistics to stderr that indicate how well the hashing is doing.
NullabilityKind
Describes the nullability of a particular type.
void setIsExtensionToken(bool Val)
static SelectorTableImpl & getSelectorTableImpl(void *P)
virtual IdentifierIterator * getIdentifiers()
Retrieve an iterator into the set of all identifiers known to this identifier lookup source...
KeywordStatus
How a keyword is treated in the selected standard.
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...
IdentifierInfo * getIdentifierInfoForSlot(unsigned i) const
std::string getName(ArrayRef< StringRef > Parts) const
Get the platform-specific name separator.
Selector getUnarySelector(IdentifierInfo *ID)
One of these records is kept for each identifier that is lexed.
static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel)
This table allows us to fully hide how we implement multi-keyword caching.
ObjCMethodFamily
A family of Objective-C methods.
IdentifierInfo *const * keyword_iterator
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts, tok::TokenKind K)
Checks if the specified token kind represents a keyword in the specified language.
IdentifierTable(IdentifierInfoLookup *ExternalLookup=nullptr)
Create the identifier table.
Values of this type can be null.
bool isUnarySelector() const
void setIsFutureCompatKeyword(bool Val)
static SmallString< 64 > constructSetterName(StringRef Name)
Return the default setter name for the given identifier.
static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name)
Return the default setter selector for the given identifier.
void Profile(llvm::FoldingSetNodeID &ID)
Whether values of this type can be null is (explicitly) unspecified.
Values of this type can never be null.
static void AddCXXOperatorKeyword(StringRef Keyword, tok::TokenKind TokenCode, IdentifierTable &Table)
AddCXXOperatorKeyword - Register a C++ operator keyword alternative representations.
size_t getTotalMemory() const
Return the total amount of memory allocated for managing selectors.
bool isCPlusPlusKeyword(const LangOptions &LangOpts) const
Return true if this token is a C++ keyword in the specified language.
Provides lookups to, and iteration over, IdentiferInfo objects.
void setIsCPlusPlusOperatorKeyword(bool Val=true)
isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether this identifier is a C++ al...
MultiKeywordSelector - One of these variable length records is kept for each selector containing more...
Defines the clang::LangOptions interface.
llvm::StringRef getAsString(SyncScope S)
Implements an efficient mapping from strings to IdentifierInfo nodes.
Defines an enumeration for C++ overloaded operators.
PPKeywordKind
Provides a namespace for preprocessor keywords which start with a '#' at the beginning of the line...
StringRef getNameForSlot(unsigned argIndex) const
Retrieve the name at a given position in the selector.
#define CASE(LEN, FIRST, THIRD, NAME)
ObjCInstanceTypeFamily
A family of Objective-C methods.
static KeywordStatus getKeywordStatus(const LangOptions &LangOpts, unsigned Flags)
Translates flags as specified in TokenKinds.def into keyword status in the given language standard...
An iterator that walks over all of the known identifiers in the lookup table.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
void print(llvm::raw_ostream &OS) const
Prints the full selector name (e.g. "foo:bar:").
unsigned getNumArgs() const
ObjCKeywordKind
Provides a namespace for Objective-C keywords which start with an '@'.
void setObjCKeywordID(tok::ObjCKeywordKind ID)
bool isKeyword(const LangOptions &LangOpts) const
Return true if this token is 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...
static void Profile(llvm::FoldingSetNodeID &ID, keyword_iterator ArgTys, unsigned NumArgs)
std::string getAsString() const
Derive the full selector name (e.g.
std::string getName() const
LLVM_READONLY char toLowercase(char c)
Converts the given ASCII character to its lowercase equivalent.
IdentifierInfo * getIdentifierInfoForSlot(unsigned argIndex) const
Retrieve the identifier at a given position in the selector.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
TokenKind
Provides a simple uniform namespace for tokens from all C languages.
virtual ~IdentifierIterator()
keyword_iterator keyword_begin() const
static void AddObjCKeyword(StringRef Name, tok::ObjCKeywordKind ObjCID, IdentifierTable &Table)
AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or "property".
LLVM_READONLY bool isLowercase(unsigned char c)
Return true if this character is a lowercase ASCII letter: [a-z].
Defines various enumerations that describe declaration and type specifiers.
StringRef getName() const
Return the actual identifier string.
virtual ~IdentifierInfoLookup()
Dataflow Directional Tag Classes.
static std::string getPropertyNameFromSetterSelector(Selector Sel)
Return the property name for the given setter selector.
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
unsigned getNumArgs() const
tok::PPKeywordKind getPPKeywordID() const
Return the preprocessor keyword ID for this identifier.
Not an overloaded operator.
MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV)
Selector getSelector(unsigned NumArgs, IdentifierInfo **IIV)
Can create any sort of selector.
const char * getOperatorSpelling(OverloadedOperatorKind Operator)
Retrieve the spelling of the given overloaded operator, without the preceding "operator" keyword...
#define HASH(LEN, FIRST, THIRD)
Defines the clang::TokenKind enum and support functions.
No particular method family.
unsigned kind
All of the diagnostics that can be emitted by the frontend.
keyword_iterator keyword_end() const
LLVM_READONLY char toUppercase(char c)
Converts the given ASCII character to its uppercase equivalent.
llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive=false)
Retrieve the spelling of the given nullability kind.