1*67e74705SXin Li //===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
2*67e74705SXin Li //
3*67e74705SXin Li // The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li // This file implements the IdentifierInfo, IdentifierVisitor, and
11*67e74705SXin Li // IdentifierTable interfaces.
12*67e74705SXin Li //
13*67e74705SXin Li //===----------------------------------------------------------------------===//
14*67e74705SXin Li
15*67e74705SXin Li #include "clang/Basic/CharInfo.h"
16*67e74705SXin Li #include "clang/Basic/IdentifierTable.h"
17*67e74705SXin Li #include "clang/Basic/LangOptions.h"
18*67e74705SXin Li #include "clang/Basic/OperatorKinds.h"
19*67e74705SXin Li #include "clang/Basic/Specifiers.h"
20*67e74705SXin Li #include "llvm/ADT/DenseMap.h"
21*67e74705SXin Li #include "llvm/ADT/FoldingSet.h"
22*67e74705SXin Li #include "llvm/ADT/SmallString.h"
23*67e74705SXin Li #include "llvm/Support/ErrorHandling.h"
24*67e74705SXin Li #include "llvm/Support/raw_ostream.h"
25*67e74705SXin Li #include <cstdio>
26*67e74705SXin Li
27*67e74705SXin Li using namespace clang;
28*67e74705SXin Li
29*67e74705SXin Li //===----------------------------------------------------------------------===//
30*67e74705SXin Li // IdentifierInfo Implementation
31*67e74705SXin Li //===----------------------------------------------------------------------===//
32*67e74705SXin Li
IdentifierInfo()33*67e74705SXin Li IdentifierInfo::IdentifierInfo() {
34*67e74705SXin Li TokenID = tok::identifier;
35*67e74705SXin Li ObjCOrBuiltinID = 0;
36*67e74705SXin Li HasMacro = false;
37*67e74705SXin Li HadMacro = false;
38*67e74705SXin Li IsExtension = false;
39*67e74705SXin Li IsFutureCompatKeyword = false;
40*67e74705SXin Li IsPoisoned = false;
41*67e74705SXin Li IsCPPOperatorKeyword = false;
42*67e74705SXin Li NeedsHandleIdentifier = false;
43*67e74705SXin Li IsFromAST = false;
44*67e74705SXin Li ChangedAfterLoad = false;
45*67e74705SXin Li FEChangedAfterLoad = false;
46*67e74705SXin Li RevertedTokenID = false;
47*67e74705SXin Li OutOfDate = false;
48*67e74705SXin Li IsModulesImport = false;
49*67e74705SXin Li FETokenInfo = nullptr;
50*67e74705SXin Li Entry = nullptr;
51*67e74705SXin Li }
52*67e74705SXin Li
53*67e74705SXin Li //===----------------------------------------------------------------------===//
54*67e74705SXin Li // IdentifierTable Implementation
55*67e74705SXin Li //===----------------------------------------------------------------------===//
56*67e74705SXin Li
~IdentifierIterator()57*67e74705SXin Li IdentifierIterator::~IdentifierIterator() { }
58*67e74705SXin Li
~IdentifierInfoLookup()59*67e74705SXin Li IdentifierInfoLookup::~IdentifierInfoLookup() {}
60*67e74705SXin Li
61*67e74705SXin Li namespace {
62*67e74705SXin Li /// \brief A simple identifier lookup iterator that represents an
63*67e74705SXin Li /// empty sequence of identifiers.
64*67e74705SXin Li class EmptyLookupIterator : public IdentifierIterator
65*67e74705SXin Li {
66*67e74705SXin Li public:
Next()67*67e74705SXin Li StringRef Next() override { return StringRef(); }
68*67e74705SXin Li };
69*67e74705SXin Li }
70*67e74705SXin Li
getIdentifiers()71*67e74705SXin Li IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
72*67e74705SXin Li return new EmptyLookupIterator();
73*67e74705SXin Li }
74*67e74705SXin Li
IdentifierTable(const LangOptions & LangOpts,IdentifierInfoLookup * externalLookup)75*67e74705SXin Li IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
76*67e74705SXin Li IdentifierInfoLookup* externalLookup)
77*67e74705SXin Li : HashTable(8192), // Start with space for 8K identifiers.
78*67e74705SXin Li ExternalLookup(externalLookup) {
79*67e74705SXin Li
80*67e74705SXin Li // Populate the identifier table with info about keywords for the current
81*67e74705SXin Li // language.
82*67e74705SXin Li AddKeywords(LangOpts);
83*67e74705SXin Li
84*67e74705SXin Li
85*67e74705SXin Li // Add the '_experimental_modules_import' contextual keyword.
86*67e74705SXin Li get("import").setModulesImport(true);
87*67e74705SXin Li }
88*67e74705SXin Li
89*67e74705SXin Li //===----------------------------------------------------------------------===//
90*67e74705SXin Li // Language Keyword Implementation
91*67e74705SXin Li //===----------------------------------------------------------------------===//
92*67e74705SXin Li
93*67e74705SXin Li // Constants for TokenKinds.def
94*67e74705SXin Li namespace {
95*67e74705SXin Li enum {
96*67e74705SXin Li KEYC99 = 0x1,
97*67e74705SXin Li KEYCXX = 0x2,
98*67e74705SXin Li KEYCXX11 = 0x4,
99*67e74705SXin Li KEYGNU = 0x8,
100*67e74705SXin Li KEYMS = 0x10,
101*67e74705SXin Li BOOLSUPPORT = 0x20,
102*67e74705SXin Li KEYALTIVEC = 0x40,
103*67e74705SXin Li KEYNOCXX = 0x80,
104*67e74705SXin Li KEYBORLAND = 0x100,
105*67e74705SXin Li KEYOPENCL = 0x200,
106*67e74705SXin Li KEYC11 = 0x400,
107*67e74705SXin Li KEYARC = 0x800,
108*67e74705SXin Li KEYNOMS18 = 0x01000,
109*67e74705SXin Li KEYNOOPENCL = 0x02000,
110*67e74705SXin Li WCHARSUPPORT = 0x04000,
111*67e74705SXin Li HALFSUPPORT = 0x08000,
112*67e74705SXin Li KEYCONCEPTS = 0x10000,
113*67e74705SXin Li KEYOBJC2 = 0x20000,
114*67e74705SXin Li KEYZVECTOR = 0x40000,
115*67e74705SXin Li KEYCOROUTINES = 0x80000,
116*67e74705SXin Li KEYALL = (0xfffff & ~KEYNOMS18 &
117*67e74705SXin Li ~KEYNOOPENCL) // KEYNOMS18 and KEYNOOPENCL are used to exclude.
118*67e74705SXin Li };
119*67e74705SXin Li
120*67e74705SXin Li /// \brief How a keyword is treated in the selected standard.
121*67e74705SXin Li enum KeywordStatus {
122*67e74705SXin Li KS_Disabled, // Disabled
123*67e74705SXin Li KS_Extension, // Is an extension
124*67e74705SXin Li KS_Enabled, // Enabled
125*67e74705SXin Li KS_Future // Is a keyword in future standard
126*67e74705SXin Li };
127*67e74705SXin Li }
128*67e74705SXin Li
129*67e74705SXin Li /// \brief Translates flags as specified in TokenKinds.def into keyword status
130*67e74705SXin Li /// in the given language standard.
getKeywordStatus(const LangOptions & LangOpts,unsigned Flags)131*67e74705SXin Li static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
132*67e74705SXin Li unsigned Flags) {
133*67e74705SXin Li if (Flags == KEYALL) return KS_Enabled;
134*67e74705SXin Li if (LangOpts.CPlusPlus && (Flags & KEYCXX)) return KS_Enabled;
135*67e74705SXin Li if (LangOpts.CPlusPlus11 && (Flags & KEYCXX11)) return KS_Enabled;
136*67e74705SXin Li if (LangOpts.C99 && (Flags & KEYC99)) return KS_Enabled;
137*67e74705SXin Li if (LangOpts.GNUKeywords && (Flags & KEYGNU)) return KS_Extension;
138*67e74705SXin Li if (LangOpts.MicrosoftExt && (Flags & KEYMS)) return KS_Extension;
139*67e74705SXin Li if (LangOpts.Borland && (Flags & KEYBORLAND)) return KS_Extension;
140*67e74705SXin Li if (LangOpts.Bool && (Flags & BOOLSUPPORT)) return KS_Enabled;
141*67e74705SXin Li if (LangOpts.Half && (Flags & HALFSUPPORT)) return KS_Enabled;
142*67e74705SXin Li if (LangOpts.WChar && (Flags & WCHARSUPPORT)) return KS_Enabled;
143*67e74705SXin Li if (LangOpts.AltiVec && (Flags & KEYALTIVEC)) return KS_Enabled;
144*67e74705SXin Li if (LangOpts.OpenCL && (Flags & KEYOPENCL)) return KS_Enabled;
145*67e74705SXin Li if (!LangOpts.CPlusPlus && (Flags & KEYNOCXX)) return KS_Enabled;
146*67e74705SXin Li if (LangOpts.C11 && (Flags & KEYC11)) return KS_Enabled;
147*67e74705SXin Li // We treat bridge casts as objective-C keywords so we can warn on them
148*67e74705SXin Li // in non-arc mode.
149*67e74705SXin Li if (LangOpts.ObjC2 && (Flags & KEYARC)) return KS_Enabled;
150*67e74705SXin Li if (LangOpts.ConceptsTS && (Flags & KEYCONCEPTS)) return KS_Enabled;
151*67e74705SXin Li if (LangOpts.ObjC2 && (Flags & KEYOBJC2)) return KS_Enabled;
152*67e74705SXin Li if (LangOpts.Coroutines && (Flags & KEYCOROUTINES)) return KS_Enabled;
153*67e74705SXin Li if (LangOpts.CPlusPlus && (Flags & KEYCXX11)) return KS_Future;
154*67e74705SXin Li return KS_Disabled;
155*67e74705SXin Li }
156*67e74705SXin Li
157*67e74705SXin Li /// AddKeyword - This method is used to associate a token ID with specific
158*67e74705SXin Li /// identifiers because they are language keywords. This causes the lexer to
159*67e74705SXin Li /// automatically map matching identifiers to specialized token codes.
AddKeyword(StringRef Keyword,tok::TokenKind TokenCode,unsigned Flags,const LangOptions & LangOpts,IdentifierTable & Table)160*67e74705SXin Li static void AddKeyword(StringRef Keyword,
161*67e74705SXin Li tok::TokenKind TokenCode, unsigned Flags,
162*67e74705SXin Li const LangOptions &LangOpts, IdentifierTable &Table) {
163*67e74705SXin Li KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
164*67e74705SXin Li
165*67e74705SXin Li // Don't add this keyword under MSVCCompat.
166*67e74705SXin Li if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
167*67e74705SXin Li !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
168*67e74705SXin Li return;
169*67e74705SXin Li
170*67e74705SXin Li // Don't add this keyword under OpenCL.
171*67e74705SXin Li if (LangOpts.OpenCL && (Flags & KEYNOOPENCL))
172*67e74705SXin Li return;
173*67e74705SXin Li
174*67e74705SXin Li // Don't add this keyword if disabled in this language.
175*67e74705SXin Li if (AddResult == KS_Disabled) return;
176*67e74705SXin Li
177*67e74705SXin Li IdentifierInfo &Info =
178*67e74705SXin Li Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
179*67e74705SXin Li Info.setIsExtensionToken(AddResult == KS_Extension);
180*67e74705SXin Li Info.setIsFutureCompatKeyword(AddResult == KS_Future);
181*67e74705SXin Li }
182*67e74705SXin Li
183*67e74705SXin Li /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
184*67e74705SXin Li /// representations.
AddCXXOperatorKeyword(StringRef Keyword,tok::TokenKind TokenCode,IdentifierTable & Table)185*67e74705SXin Li static void AddCXXOperatorKeyword(StringRef Keyword,
186*67e74705SXin Li tok::TokenKind TokenCode,
187*67e74705SXin Li IdentifierTable &Table) {
188*67e74705SXin Li IdentifierInfo &Info = Table.get(Keyword, TokenCode);
189*67e74705SXin Li Info.setIsCPlusPlusOperatorKeyword();
190*67e74705SXin Li }
191*67e74705SXin Li
192*67e74705SXin Li /// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
193*67e74705SXin Li /// or "property".
AddObjCKeyword(StringRef Name,tok::ObjCKeywordKind ObjCID,IdentifierTable & Table)194*67e74705SXin Li static void AddObjCKeyword(StringRef Name,
195*67e74705SXin Li tok::ObjCKeywordKind ObjCID,
196*67e74705SXin Li IdentifierTable &Table) {
197*67e74705SXin Li Table.get(Name).setObjCKeywordID(ObjCID);
198*67e74705SXin Li }
199*67e74705SXin Li
200*67e74705SXin Li /// AddKeywords - Add all keywords to the symbol table.
201*67e74705SXin Li ///
AddKeywords(const LangOptions & LangOpts)202*67e74705SXin Li void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
203*67e74705SXin Li // Add keywords and tokens for the current language.
204*67e74705SXin Li #define KEYWORD(NAME, FLAGS) \
205*67e74705SXin Li AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
206*67e74705SXin Li FLAGS, LangOpts, *this);
207*67e74705SXin Li #define ALIAS(NAME, TOK, FLAGS) \
208*67e74705SXin Li AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
209*67e74705SXin Li FLAGS, LangOpts, *this);
210*67e74705SXin Li #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
211*67e74705SXin Li if (LangOpts.CXXOperatorNames) \
212*67e74705SXin Li AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
213*67e74705SXin Li #define OBJC1_AT_KEYWORD(NAME) \
214*67e74705SXin Li if (LangOpts.ObjC1) \
215*67e74705SXin Li AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
216*67e74705SXin Li #define OBJC2_AT_KEYWORD(NAME) \
217*67e74705SXin Li if (LangOpts.ObjC2) \
218*67e74705SXin Li AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
219*67e74705SXin Li #define TESTING_KEYWORD(NAME, FLAGS)
220*67e74705SXin Li #include "clang/Basic/TokenKinds.def"
221*67e74705SXin Li
222*67e74705SXin Li if (LangOpts.ParseUnknownAnytype)
223*67e74705SXin Li AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
224*67e74705SXin Li LangOpts, *this);
225*67e74705SXin Li
226*67e74705SXin Li if (LangOpts.DeclSpecKeyword)
227*67e74705SXin Li AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
228*67e74705SXin Li }
229*67e74705SXin Li
230*67e74705SXin Li /// \brief Checks if the specified token kind represents a keyword in the
231*67e74705SXin Li /// specified language.
232*67e74705SXin Li /// \returns Status of the keyword in the language.
getTokenKwStatus(const LangOptions & LangOpts,tok::TokenKind K)233*67e74705SXin Li static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
234*67e74705SXin Li tok::TokenKind K) {
235*67e74705SXin Li switch (K) {
236*67e74705SXin Li #define KEYWORD(NAME, FLAGS) \
237*67e74705SXin Li case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
238*67e74705SXin Li #include "clang/Basic/TokenKinds.def"
239*67e74705SXin Li default: return KS_Disabled;
240*67e74705SXin Li }
241*67e74705SXin Li }
242*67e74705SXin Li
243*67e74705SXin Li /// \brief Returns true if the identifier represents a keyword in the
244*67e74705SXin Li /// specified language.
isKeyword(const LangOptions & LangOpts)245*67e74705SXin Li bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) {
246*67e74705SXin Li switch (getTokenKwStatus(LangOpts, getTokenID())) {
247*67e74705SXin Li case KS_Enabled:
248*67e74705SXin Li case KS_Extension:
249*67e74705SXin Li return true;
250*67e74705SXin Li default:
251*67e74705SXin Li return false;
252*67e74705SXin Li }
253*67e74705SXin Li }
254*67e74705SXin Li
getPPKeywordID() const255*67e74705SXin Li tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
256*67e74705SXin Li // We use a perfect hash function here involving the length of the keyword,
257*67e74705SXin Li // the first and third character. For preprocessor ID's there are no
258*67e74705SXin Li // collisions (if there were, the switch below would complain about duplicate
259*67e74705SXin Li // case values). Note that this depends on 'if' being null terminated.
260*67e74705SXin Li
261*67e74705SXin Li #define HASH(LEN, FIRST, THIRD) \
262*67e74705SXin Li (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
263*67e74705SXin Li #define CASE(LEN, FIRST, THIRD, NAME) \
264*67e74705SXin Li case HASH(LEN, FIRST, THIRD): \
265*67e74705SXin Li return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
266*67e74705SXin Li
267*67e74705SXin Li unsigned Len = getLength();
268*67e74705SXin Li if (Len < 2) return tok::pp_not_keyword;
269*67e74705SXin Li const char *Name = getNameStart();
270*67e74705SXin Li switch (HASH(Len, Name[0], Name[2])) {
271*67e74705SXin Li default: return tok::pp_not_keyword;
272*67e74705SXin Li CASE( 2, 'i', '\0', if);
273*67e74705SXin Li CASE( 4, 'e', 'i', elif);
274*67e74705SXin Li CASE( 4, 'e', 's', else);
275*67e74705SXin Li CASE( 4, 'l', 'n', line);
276*67e74705SXin Li CASE( 4, 's', 'c', sccs);
277*67e74705SXin Li CASE( 5, 'e', 'd', endif);
278*67e74705SXin Li CASE( 5, 'e', 'r', error);
279*67e74705SXin Li CASE( 5, 'i', 'e', ident);
280*67e74705SXin Li CASE( 5, 'i', 'd', ifdef);
281*67e74705SXin Li CASE( 5, 'u', 'd', undef);
282*67e74705SXin Li
283*67e74705SXin Li CASE( 6, 'a', 's', assert);
284*67e74705SXin Li CASE( 6, 'd', 'f', define);
285*67e74705SXin Li CASE( 6, 'i', 'n', ifndef);
286*67e74705SXin Li CASE( 6, 'i', 'p', import);
287*67e74705SXin Li CASE( 6, 'p', 'a', pragma);
288*67e74705SXin Li
289*67e74705SXin Li CASE( 7, 'd', 'f', defined);
290*67e74705SXin Li CASE( 7, 'i', 'c', include);
291*67e74705SXin Li CASE( 7, 'w', 'r', warning);
292*67e74705SXin Li
293*67e74705SXin Li CASE( 8, 'u', 'a', unassert);
294*67e74705SXin Li CASE(12, 'i', 'c', include_next);
295*67e74705SXin Li
296*67e74705SXin Li CASE(14, '_', 'p', __public_macro);
297*67e74705SXin Li
298*67e74705SXin Li CASE(15, '_', 'p', __private_macro);
299*67e74705SXin Li
300*67e74705SXin Li CASE(16, '_', 'i', __include_macros);
301*67e74705SXin Li #undef CASE
302*67e74705SXin Li #undef HASH
303*67e74705SXin Li }
304*67e74705SXin Li }
305*67e74705SXin Li
306*67e74705SXin Li //===----------------------------------------------------------------------===//
307*67e74705SXin Li // Stats Implementation
308*67e74705SXin Li //===----------------------------------------------------------------------===//
309*67e74705SXin Li
310*67e74705SXin Li /// PrintStats - Print statistics about how well the identifier table is doing
311*67e74705SXin Li /// at hashing identifiers.
PrintStats() const312*67e74705SXin Li void IdentifierTable::PrintStats() const {
313*67e74705SXin Li unsigned NumBuckets = HashTable.getNumBuckets();
314*67e74705SXin Li unsigned NumIdentifiers = HashTable.getNumItems();
315*67e74705SXin Li unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
316*67e74705SXin Li unsigned AverageIdentifierSize = 0;
317*67e74705SXin Li unsigned MaxIdentifierLength = 0;
318*67e74705SXin Li
319*67e74705SXin Li // TODO: Figure out maximum times an identifier had to probe for -stats.
320*67e74705SXin Li for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
321*67e74705SXin Li I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
322*67e74705SXin Li unsigned IdLen = I->getKeyLength();
323*67e74705SXin Li AverageIdentifierSize += IdLen;
324*67e74705SXin Li if (MaxIdentifierLength < IdLen)
325*67e74705SXin Li MaxIdentifierLength = IdLen;
326*67e74705SXin Li }
327*67e74705SXin Li
328*67e74705SXin Li fprintf(stderr, "\n*** Identifier Table Stats:\n");
329*67e74705SXin Li fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
330*67e74705SXin Li fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
331*67e74705SXin Li fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
332*67e74705SXin Li NumIdentifiers/(double)NumBuckets);
333*67e74705SXin Li fprintf(stderr, "Ave identifier length: %f\n",
334*67e74705SXin Li (AverageIdentifierSize/(double)NumIdentifiers));
335*67e74705SXin Li fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
336*67e74705SXin Li
337*67e74705SXin Li // Compute statistics about the memory allocated for identifiers.
338*67e74705SXin Li HashTable.getAllocator().PrintStats();
339*67e74705SXin Li }
340*67e74705SXin Li
341*67e74705SXin Li //===----------------------------------------------------------------------===//
342*67e74705SXin Li // SelectorTable Implementation
343*67e74705SXin Li //===----------------------------------------------------------------------===//
344*67e74705SXin Li
getHashValue(clang::Selector S)345*67e74705SXin Li unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
346*67e74705SXin Li return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
347*67e74705SXin Li }
348*67e74705SXin Li
349*67e74705SXin Li namespace clang {
350*67e74705SXin Li /// MultiKeywordSelector - One of these variable length records is kept for each
351*67e74705SXin Li /// selector containing more than one keyword. We use a folding set
352*67e74705SXin Li /// to unique aggregate names (keyword selectors in ObjC parlance). Access to
353*67e74705SXin Li /// this class is provided strictly through Selector.
354*67e74705SXin Li class MultiKeywordSelector
355*67e74705SXin Li : public DeclarationNameExtra, public llvm::FoldingSetNode {
MultiKeywordSelector(unsigned nKeys)356*67e74705SXin Li MultiKeywordSelector(unsigned nKeys) {
357*67e74705SXin Li ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
358*67e74705SXin Li }
359*67e74705SXin Li public:
360*67e74705SXin Li // Constructor for keyword selectors.
MultiKeywordSelector(unsigned nKeys,IdentifierInfo ** IIV)361*67e74705SXin Li MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
362*67e74705SXin Li assert((nKeys > 1) && "not a multi-keyword selector");
363*67e74705SXin Li ExtraKindOrNumArgs = NUM_EXTRA_KINDS + nKeys;
364*67e74705SXin Li
365*67e74705SXin Li // Fill in the trailing keyword array.
366*67e74705SXin Li IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
367*67e74705SXin Li for (unsigned i = 0; i != nKeys; ++i)
368*67e74705SXin Li KeyInfo[i] = IIV[i];
369*67e74705SXin Li }
370*67e74705SXin Li
371*67e74705SXin Li // getName - Derive the full selector name and return it.
372*67e74705SXin Li std::string getName() const;
373*67e74705SXin Li
getNumArgs() const374*67e74705SXin Li unsigned getNumArgs() const { return ExtraKindOrNumArgs - NUM_EXTRA_KINDS; }
375*67e74705SXin Li
376*67e74705SXin Li typedef IdentifierInfo *const *keyword_iterator;
keyword_begin() const377*67e74705SXin Li keyword_iterator keyword_begin() const {
378*67e74705SXin Li return reinterpret_cast<keyword_iterator>(this+1);
379*67e74705SXin Li }
keyword_end() const380*67e74705SXin Li keyword_iterator keyword_end() const {
381*67e74705SXin Li return keyword_begin()+getNumArgs();
382*67e74705SXin Li }
getIdentifierInfoForSlot(unsigned i) const383*67e74705SXin Li IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
384*67e74705SXin Li assert(i < getNumArgs() && "getIdentifierInfoForSlot(): illegal index");
385*67e74705SXin Li return keyword_begin()[i];
386*67e74705SXin Li }
Profile(llvm::FoldingSetNodeID & ID,keyword_iterator ArgTys,unsigned NumArgs)387*67e74705SXin Li static void Profile(llvm::FoldingSetNodeID &ID,
388*67e74705SXin Li keyword_iterator ArgTys, unsigned NumArgs) {
389*67e74705SXin Li ID.AddInteger(NumArgs);
390*67e74705SXin Li for (unsigned i = 0; i != NumArgs; ++i)
391*67e74705SXin Li ID.AddPointer(ArgTys[i]);
392*67e74705SXin Li }
Profile(llvm::FoldingSetNodeID & ID)393*67e74705SXin Li void Profile(llvm::FoldingSetNodeID &ID) {
394*67e74705SXin Li Profile(ID, keyword_begin(), getNumArgs());
395*67e74705SXin Li }
396*67e74705SXin Li };
397*67e74705SXin Li } // end namespace clang.
398*67e74705SXin Li
getNumArgs() const399*67e74705SXin Li unsigned Selector::getNumArgs() const {
400*67e74705SXin Li unsigned IIF = getIdentifierInfoFlag();
401*67e74705SXin Li if (IIF <= ZeroArg)
402*67e74705SXin Li return 0;
403*67e74705SXin Li if (IIF == OneArg)
404*67e74705SXin Li return 1;
405*67e74705SXin Li // We point to a MultiKeywordSelector.
406*67e74705SXin Li MultiKeywordSelector *SI = getMultiKeywordSelector();
407*67e74705SXin Li return SI->getNumArgs();
408*67e74705SXin Li }
409*67e74705SXin Li
getIdentifierInfoForSlot(unsigned argIndex) const410*67e74705SXin Li IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
411*67e74705SXin Li if (getIdentifierInfoFlag() < MultiArg) {
412*67e74705SXin Li assert(argIndex == 0 && "illegal keyword index");
413*67e74705SXin Li return getAsIdentifierInfo();
414*67e74705SXin Li }
415*67e74705SXin Li // We point to a MultiKeywordSelector.
416*67e74705SXin Li MultiKeywordSelector *SI = getMultiKeywordSelector();
417*67e74705SXin Li return SI->getIdentifierInfoForSlot(argIndex);
418*67e74705SXin Li }
419*67e74705SXin Li
getNameForSlot(unsigned int argIndex) const420*67e74705SXin Li StringRef Selector::getNameForSlot(unsigned int argIndex) const {
421*67e74705SXin Li IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
422*67e74705SXin Li return II? II->getName() : StringRef();
423*67e74705SXin Li }
424*67e74705SXin Li
getName() const425*67e74705SXin Li std::string MultiKeywordSelector::getName() const {
426*67e74705SXin Li SmallString<256> Str;
427*67e74705SXin Li llvm::raw_svector_ostream OS(Str);
428*67e74705SXin Li for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
429*67e74705SXin Li if (*I)
430*67e74705SXin Li OS << (*I)->getName();
431*67e74705SXin Li OS << ':';
432*67e74705SXin Li }
433*67e74705SXin Li
434*67e74705SXin Li return OS.str();
435*67e74705SXin Li }
436*67e74705SXin Li
getAsString() const437*67e74705SXin Li std::string Selector::getAsString() const {
438*67e74705SXin Li if (InfoPtr == 0)
439*67e74705SXin Li return "<null selector>";
440*67e74705SXin Li
441*67e74705SXin Li if (getIdentifierInfoFlag() < MultiArg) {
442*67e74705SXin Li IdentifierInfo *II = getAsIdentifierInfo();
443*67e74705SXin Li
444*67e74705SXin Li // If the number of arguments is 0 then II is guaranteed to not be null.
445*67e74705SXin Li if (getNumArgs() == 0)
446*67e74705SXin Li return II->getName();
447*67e74705SXin Li
448*67e74705SXin Li if (!II)
449*67e74705SXin Li return ":";
450*67e74705SXin Li
451*67e74705SXin Li return II->getName().str() + ":";
452*67e74705SXin Li }
453*67e74705SXin Li
454*67e74705SXin Li // We have a multiple keyword selector.
455*67e74705SXin Li return getMultiKeywordSelector()->getName();
456*67e74705SXin Li }
457*67e74705SXin Li
print(llvm::raw_ostream & OS) const458*67e74705SXin Li void Selector::print(llvm::raw_ostream &OS) const {
459*67e74705SXin Li OS << getAsString();
460*67e74705SXin Li }
461*67e74705SXin Li
462*67e74705SXin Li /// Interpreting the given string using the normal CamelCase
463*67e74705SXin Li /// conventions, determine whether the given string starts with the
464*67e74705SXin Li /// given "word", which is assumed to end in a lowercase letter.
startsWithWord(StringRef name,StringRef word)465*67e74705SXin Li static bool startsWithWord(StringRef name, StringRef word) {
466*67e74705SXin Li if (name.size() < word.size()) return false;
467*67e74705SXin Li return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
468*67e74705SXin Li name.startswith(word));
469*67e74705SXin Li }
470*67e74705SXin Li
getMethodFamilyImpl(Selector sel)471*67e74705SXin Li ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
472*67e74705SXin Li IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
473*67e74705SXin Li if (!first) return OMF_None;
474*67e74705SXin Li
475*67e74705SXin Li StringRef name = first->getName();
476*67e74705SXin Li if (sel.isUnarySelector()) {
477*67e74705SXin Li if (name == "autorelease") return OMF_autorelease;
478*67e74705SXin Li if (name == "dealloc") return OMF_dealloc;
479*67e74705SXin Li if (name == "finalize") return OMF_finalize;
480*67e74705SXin Li if (name == "release") return OMF_release;
481*67e74705SXin Li if (name == "retain") return OMF_retain;
482*67e74705SXin Li if (name == "retainCount") return OMF_retainCount;
483*67e74705SXin Li if (name == "self") return OMF_self;
484*67e74705SXin Li if (name == "initialize") return OMF_initialize;
485*67e74705SXin Li }
486*67e74705SXin Li
487*67e74705SXin Li if (name == "performSelector") return OMF_performSelector;
488*67e74705SXin Li
489*67e74705SXin Li // The other method families may begin with a prefix of underscores.
490*67e74705SXin Li while (!name.empty() && name.front() == '_')
491*67e74705SXin Li name = name.substr(1);
492*67e74705SXin Li
493*67e74705SXin Li if (name.empty()) return OMF_None;
494*67e74705SXin Li switch (name.front()) {
495*67e74705SXin Li case 'a':
496*67e74705SXin Li if (startsWithWord(name, "alloc")) return OMF_alloc;
497*67e74705SXin Li break;
498*67e74705SXin Li case 'c':
499*67e74705SXin Li if (startsWithWord(name, "copy")) return OMF_copy;
500*67e74705SXin Li break;
501*67e74705SXin Li case 'i':
502*67e74705SXin Li if (startsWithWord(name, "init")) return OMF_init;
503*67e74705SXin Li break;
504*67e74705SXin Li case 'm':
505*67e74705SXin Li if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
506*67e74705SXin Li break;
507*67e74705SXin Li case 'n':
508*67e74705SXin Li if (startsWithWord(name, "new")) return OMF_new;
509*67e74705SXin Li break;
510*67e74705SXin Li default:
511*67e74705SXin Li break;
512*67e74705SXin Li }
513*67e74705SXin Li
514*67e74705SXin Li return OMF_None;
515*67e74705SXin Li }
516*67e74705SXin Li
getInstTypeMethodFamily(Selector sel)517*67e74705SXin Li ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
518*67e74705SXin Li IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
519*67e74705SXin Li if (!first) return OIT_None;
520*67e74705SXin Li
521*67e74705SXin Li StringRef name = first->getName();
522*67e74705SXin Li
523*67e74705SXin Li if (name.empty()) return OIT_None;
524*67e74705SXin Li switch (name.front()) {
525*67e74705SXin Li case 'a':
526*67e74705SXin Li if (startsWithWord(name, "array")) return OIT_Array;
527*67e74705SXin Li break;
528*67e74705SXin Li case 'd':
529*67e74705SXin Li if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
530*67e74705SXin Li if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
531*67e74705SXin Li break;
532*67e74705SXin Li case 's':
533*67e74705SXin Li if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
534*67e74705SXin Li if (startsWithWord(name, "standard")) return OIT_Singleton;
535*67e74705SXin Li case 'i':
536*67e74705SXin Li if (startsWithWord(name, "init")) return OIT_Init;
537*67e74705SXin Li default:
538*67e74705SXin Li break;
539*67e74705SXin Li }
540*67e74705SXin Li return OIT_None;
541*67e74705SXin Li }
542*67e74705SXin Li
getStringFormatFamilyImpl(Selector sel)543*67e74705SXin Li ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
544*67e74705SXin Li IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
545*67e74705SXin Li if (!first) return SFF_None;
546*67e74705SXin Li
547*67e74705SXin Li StringRef name = first->getName();
548*67e74705SXin Li
549*67e74705SXin Li switch (name.front()) {
550*67e74705SXin Li case 'a':
551*67e74705SXin Li if (name == "appendFormat") return SFF_NSString;
552*67e74705SXin Li break;
553*67e74705SXin Li
554*67e74705SXin Li case 'i':
555*67e74705SXin Li if (name == "initWithFormat") return SFF_NSString;
556*67e74705SXin Li break;
557*67e74705SXin Li
558*67e74705SXin Li case 'l':
559*67e74705SXin Li if (name == "localizedStringWithFormat") return SFF_NSString;
560*67e74705SXin Li break;
561*67e74705SXin Li
562*67e74705SXin Li case 's':
563*67e74705SXin Li if (name == "stringByAppendingFormat" ||
564*67e74705SXin Li name == "stringWithFormat") return SFF_NSString;
565*67e74705SXin Li break;
566*67e74705SXin Li }
567*67e74705SXin Li return SFF_None;
568*67e74705SXin Li }
569*67e74705SXin Li
570*67e74705SXin Li namespace {
571*67e74705SXin Li struct SelectorTableImpl {
572*67e74705SXin Li llvm::FoldingSet<MultiKeywordSelector> Table;
573*67e74705SXin Li llvm::BumpPtrAllocator Allocator;
574*67e74705SXin Li };
575*67e74705SXin Li } // end anonymous namespace.
576*67e74705SXin Li
getSelectorTableImpl(void * P)577*67e74705SXin Li static SelectorTableImpl &getSelectorTableImpl(void *P) {
578*67e74705SXin Li return *static_cast<SelectorTableImpl*>(P);
579*67e74705SXin Li }
580*67e74705SXin Li
581*67e74705SXin Li SmallString<64>
constructSetterName(StringRef Name)582*67e74705SXin Li SelectorTable::constructSetterName(StringRef Name) {
583*67e74705SXin Li SmallString<64> SetterName("set");
584*67e74705SXin Li SetterName += Name;
585*67e74705SXin Li SetterName[3] = toUppercase(SetterName[3]);
586*67e74705SXin Li return SetterName;
587*67e74705SXin Li }
588*67e74705SXin Li
589*67e74705SXin Li Selector
constructSetterSelector(IdentifierTable & Idents,SelectorTable & SelTable,const IdentifierInfo * Name)590*67e74705SXin Li SelectorTable::constructSetterSelector(IdentifierTable &Idents,
591*67e74705SXin Li SelectorTable &SelTable,
592*67e74705SXin Li const IdentifierInfo *Name) {
593*67e74705SXin Li IdentifierInfo *SetterName =
594*67e74705SXin Li &Idents.get(constructSetterName(Name->getName()));
595*67e74705SXin Li return SelTable.getUnarySelector(SetterName);
596*67e74705SXin Li }
597*67e74705SXin Li
getTotalMemory() const598*67e74705SXin Li size_t SelectorTable::getTotalMemory() const {
599*67e74705SXin Li SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
600*67e74705SXin Li return SelTabImpl.Allocator.getTotalMemory();
601*67e74705SXin Li }
602*67e74705SXin Li
getSelector(unsigned nKeys,IdentifierInfo ** IIV)603*67e74705SXin Li Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
604*67e74705SXin Li if (nKeys < 2)
605*67e74705SXin Li return Selector(IIV[0], nKeys);
606*67e74705SXin Li
607*67e74705SXin Li SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
608*67e74705SXin Li
609*67e74705SXin Li // Unique selector, to guarantee there is one per name.
610*67e74705SXin Li llvm::FoldingSetNodeID ID;
611*67e74705SXin Li MultiKeywordSelector::Profile(ID, IIV, nKeys);
612*67e74705SXin Li
613*67e74705SXin Li void *InsertPos = nullptr;
614*67e74705SXin Li if (MultiKeywordSelector *SI =
615*67e74705SXin Li SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
616*67e74705SXin Li return Selector(SI);
617*67e74705SXin Li
618*67e74705SXin Li // MultiKeywordSelector objects are not allocated with new because they have a
619*67e74705SXin Li // variable size array (for parameter types) at the end of them.
620*67e74705SXin Li unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
621*67e74705SXin Li MultiKeywordSelector *SI =
622*67e74705SXin Li (MultiKeywordSelector*)SelTabImpl.Allocator.Allocate(Size,
623*67e74705SXin Li llvm::alignOf<MultiKeywordSelector>());
624*67e74705SXin Li new (SI) MultiKeywordSelector(nKeys, IIV);
625*67e74705SXin Li SelTabImpl.Table.InsertNode(SI, InsertPos);
626*67e74705SXin Li return Selector(SI);
627*67e74705SXin Li }
628*67e74705SXin Li
SelectorTable()629*67e74705SXin Li SelectorTable::SelectorTable() {
630*67e74705SXin Li Impl = new SelectorTableImpl();
631*67e74705SXin Li }
632*67e74705SXin Li
~SelectorTable()633*67e74705SXin Li SelectorTable::~SelectorTable() {
634*67e74705SXin Li delete &getSelectorTableImpl(Impl);
635*67e74705SXin Li }
636*67e74705SXin Li
getOperatorSpelling(OverloadedOperatorKind Operator)637*67e74705SXin Li const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
638*67e74705SXin Li switch (Operator) {
639*67e74705SXin Li case OO_None:
640*67e74705SXin Li case NUM_OVERLOADED_OPERATORS:
641*67e74705SXin Li return nullptr;
642*67e74705SXin Li
643*67e74705SXin Li #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
644*67e74705SXin Li case OO_##Name: return Spelling;
645*67e74705SXin Li #include "clang/Basic/OperatorKinds.def"
646*67e74705SXin Li }
647*67e74705SXin Li
648*67e74705SXin Li llvm_unreachable("Invalid OverloadedOperatorKind!");
649*67e74705SXin Li }
650*67e74705SXin Li
getNullabilitySpelling(NullabilityKind kind,bool isContextSensitive)651*67e74705SXin Li StringRef clang::getNullabilitySpelling(NullabilityKind kind,
652*67e74705SXin Li bool isContextSensitive) {
653*67e74705SXin Li switch (kind) {
654*67e74705SXin Li case NullabilityKind::NonNull:
655*67e74705SXin Li return isContextSensitive ? "nonnull" : "_Nonnull";
656*67e74705SXin Li
657*67e74705SXin Li case NullabilityKind::Nullable:
658*67e74705SXin Li return isContextSensitive ? "nullable" : "_Nullable";
659*67e74705SXin Li
660*67e74705SXin Li case NullabilityKind::Unspecified:
661*67e74705SXin Li return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
662*67e74705SXin Li }
663*67e74705SXin Li llvm_unreachable("Unknown nullability kind.");
664*67e74705SXin Li }
665