xref: /src/contrib/llvm-project/clang/lib/Basic/IdentifierTable.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1461a67faSDimitry Andric //===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
2ec2b103cSEd Schouten //
322989816SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
422989816SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
522989816SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ec2b103cSEd Schouten //
7ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
8ec2b103cSEd Schouten //
9ec2b103cSEd Schouten // This file implements the IdentifierInfo, IdentifierVisitor, and
10ec2b103cSEd Schouten // IdentifierTable interfaces.
11ec2b103cSEd Schouten //
12ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
13ec2b103cSEd Schouten 
14ec2b103cSEd Schouten #include "clang/Basic/IdentifierTable.h"
15461a67faSDimitry Andric #include "clang/Basic/CharInfo.h"
16e3b55780SDimitry Andric #include "clang/Basic/DiagnosticLex.h"
17ec2b103cSEd Schouten #include "clang/Basic/LangOptions.h"
189f4dbff6SDimitry Andric #include "clang/Basic/OperatorKinds.h"
192e645aa5SDimitry Andric #include "clang/Basic/Specifiers.h"
20cfca06d7SDimitry Andric #include "clang/Basic/TargetBuiltins.h"
21461a67faSDimitry Andric #include "clang/Basic/TokenKinds.h"
22461a67faSDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
23809500fcSDimitry Andric #include "llvm/ADT/FoldingSet.h"
249f4dbff6SDimitry Andric #include "llvm/ADT/SmallString.h"
25461a67faSDimitry Andric #include "llvm/ADT/StringMap.h"
26461a67faSDimitry Andric #include "llvm/ADT/StringRef.h"
27461a67faSDimitry Andric #include "llvm/Support/Allocator.h"
28809500fcSDimitry Andric #include "llvm/Support/raw_ostream.h"
29461a67faSDimitry Andric #include <cassert>
30ec2b103cSEd Schouten #include <cstdio>
31461a67faSDimitry Andric #include <cstring>
32461a67faSDimitry Andric #include <string>
33ec2b103cSEd Schouten 
34ec2b103cSEd Schouten using namespace clang;
35ec2b103cSEd Schouten 
36cfca06d7SDimitry Andric // A check to make sure the ObjCOrBuiltinID has sufficient room to store the
37cfca06d7SDimitry Andric // largest possible target/aux-target combination. If we exceed this, we likely
38cfca06d7SDimitry Andric // need to just change the ObjCOrBuiltinIDBits value in IdentifierTable.h.
39ac9a064cSDimitry Andric static_assert(2 * LargestBuiltinID < (2 << (InterestingIdentifierBits - 1)),
40cfca06d7SDimitry Andric               "Insufficient ObjCOrBuiltinID Bits");
41cfca06d7SDimitry Andric 
42ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
43ec2b103cSEd Schouten // IdentifierTable Implementation
44ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
45ec2b103cSEd Schouten 
46461a67faSDimitry Andric IdentifierIterator::~IdentifierIterator() = default;
47bca07a45SDimitry Andric 
48461a67faSDimitry Andric IdentifierInfoLookup::~IdentifierInfoLookup() = default;
49ec2b103cSEd Schouten 
50bca07a45SDimitry Andric namespace {
51461a67faSDimitry Andric 
5248675466SDimitry Andric /// A simple identifier lookup iterator that represents an
53bca07a45SDimitry Andric /// empty sequence of identifiers.
54b1c73532SDimitry Andric class EmptyLookupIterator : public IdentifierIterator {
55bca07a45SDimitry Andric public:
Next()569f4dbff6SDimitry Andric   StringRef Next() override { return StringRef(); }
57bca07a45SDimitry Andric };
58461a67faSDimitry Andric 
59461a67faSDimitry Andric } // namespace
60bca07a45SDimitry Andric 
getIdentifiers()616a037251SDimitry Andric IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
62bca07a45SDimitry Andric   return new EmptyLookupIterator();
63bca07a45SDimitry Andric }
64bca07a45SDimitry Andric 
IdentifierTable(IdentifierInfoLookup * ExternalLookup)6548675466SDimitry Andric IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)
66ec2b103cSEd Schouten     : HashTable(8192), // Start with space for 8K identifiers.
6748675466SDimitry Andric       ExternalLookup(ExternalLookup) {}
6848675466SDimitry Andric 
IdentifierTable(const LangOptions & LangOpts,IdentifierInfoLookup * ExternalLookup)6948675466SDimitry Andric IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
7048675466SDimitry Andric                                  IdentifierInfoLookup *ExternalLookup)
7148675466SDimitry Andric     : IdentifierTable(ExternalLookup) {
72ec2b103cSEd Schouten   // Populate the identifier table with info about keywords for the current
73ec2b103cSEd Schouten   // language.
74ec2b103cSEd Schouten   AddKeywords(LangOpts);
75ec2b103cSEd Schouten }
76ec2b103cSEd Schouten 
77ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
78ec2b103cSEd Schouten // Language Keyword Implementation
79ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
80ec2b103cSEd Schouten 
81ec2b103cSEd Schouten // Constants for TokenKinds.def
82ec2b103cSEd Schouten namespace {
83461a67faSDimitry Andric 
84e3b55780SDimitry Andric   enum TokenKey : unsigned {
8501af97d3SDimitry Andric     KEYC99        = 0x1,
8601af97d3SDimitry Andric     KEYCXX        = 0x2,
87809500fcSDimitry Andric     KEYCXX11      = 0x4,
8801af97d3SDimitry Andric     KEYGNU        = 0x8,
8901af97d3SDimitry Andric     KEYMS         = 0x10,
9001af97d3SDimitry Andric     BOOLSUPPORT   = 0x20,
9101af97d3SDimitry Andric     KEYALTIVEC    = 0x40,
9201af97d3SDimitry Andric     KEYNOCXX      = 0x80,
9301af97d3SDimitry Andric     KEYBORLAND    = 0x100,
9448675466SDimitry Andric     KEYOPENCLC    = 0x200,
95b1c73532SDimitry Andric     KEYC23        = 0x400,
96676fbe81SDimitry Andric     KEYNOMS18     = 0x800,
97676fbe81SDimitry Andric     KEYNOOPENCL   = 0x1000,
98676fbe81SDimitry Andric     WCHARSUPPORT  = 0x2000,
99676fbe81SDimitry Andric     HALFSUPPORT   = 0x4000,
100676fbe81SDimitry Andric     CHAR8SUPPORT  = 0x8000,
101e3b55780SDimitry Andric     KEYOBJC       = 0x10000,
102e3b55780SDimitry Andric     KEYZVECTOR    = 0x20000,
103e3b55780SDimitry Andric     KEYCOROUTINES = 0x40000,
104e3b55780SDimitry Andric     KEYMODULES    = 0x80000,
105e3b55780SDimitry Andric     KEYCXX20      = 0x100000,
106e3b55780SDimitry Andric     KEYOPENCLCXX  = 0x200000,
107e3b55780SDimitry Andric     KEYMSCOMPAT   = 0x400000,
108e3b55780SDimitry Andric     KEYSYCL       = 0x800000,
109e3b55780SDimitry Andric     KEYCUDA       = 0x1000000,
110e3b55780SDimitry Andric     KEYHLSL       = 0x2000000,
111b1c73532SDimitry Andric     KEYFIXEDPOINT = 0x4000000,
112b1c73532SDimitry Andric     KEYMAX        = KEYFIXEDPOINT, // The maximum key
113cfca06d7SDimitry Andric     KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
114145449b1SDimitry Andric     KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
115145449b1SDimitry Andric              ~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
116ec2b103cSEd Schouten   };
11706d4ba38SDimitry Andric 
118e3b55780SDimitry Andric   /// How a keyword is treated in the selected standard. This enum is ordered
119e3b55780SDimitry Andric   /// intentionally so that the value that 'wins' is the most 'permissive'.
12006d4ba38SDimitry Andric   enum KeywordStatus {
121e3b55780SDimitry Andric     KS_Unknown,     // Not yet calculated. Used when figuring out the status.
12206d4ba38SDimitry Andric     KS_Disabled,    // Disabled
123e3b55780SDimitry Andric     KS_Future,      // Is a keyword in future standard
12406d4ba38SDimitry Andric     KS_Extension,   // Is an extension
12506d4ba38SDimitry Andric     KS_Enabled,     // Enabled
12606d4ba38SDimitry Andric   };
127461a67faSDimitry Andric 
128461a67faSDimitry Andric } // namespace
12906d4ba38SDimitry Andric 
130e3b55780SDimitry Andric // This works on a single TokenKey flag and checks the LangOpts to get the
131e3b55780SDimitry Andric // KeywordStatus based exclusively on this flag, so that it can be merged in
132e3b55780SDimitry Andric // getKeywordStatus. Most should be enabled/disabled, but some might imply
133e3b55780SDimitry Andric // 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to
134e3b55780SDimitry Andric // be disabled, and the calling function makes it 'disabled' if no other flag
135e3b55780SDimitry Andric // changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.
getKeywordStatusHelper(const LangOptions & LangOpts,TokenKey Flag)136e3b55780SDimitry Andric static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
137e3b55780SDimitry Andric                                             TokenKey Flag) {
138e3b55780SDimitry Andric   // Flag is a single bit version of TokenKey (that is, not
139e3b55780SDimitry Andric   // KEYALL/KEYALLCXX/etc), so we can check with == throughout this function.
140e3b55780SDimitry Andric   assert((Flag & ~(Flag - 1)) == Flag && "Multiple bits set?");
141e3b55780SDimitry Andric 
142e3b55780SDimitry Andric   switch (Flag) {
143e3b55780SDimitry Andric   case KEYC99:
144e3b55780SDimitry Andric     if (LangOpts.C99)
145e3b55780SDimitry Andric       return KS_Enabled;
146e3b55780SDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
147b1c73532SDimitry Andric   case KEYC23:
148b1c73532SDimitry Andric     if (LangOpts.C23)
149e3b55780SDimitry Andric       return KS_Enabled;
150e3b55780SDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151e3b55780SDimitry Andric   case KEYCXX:
152e3b55780SDimitry Andric     return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
153e3b55780SDimitry Andric   case KEYCXX11:
154e3b55780SDimitry Andric     if (LangOpts.CPlusPlus11)
155e3b55780SDimitry Andric       return KS_Enabled;
156e3b55780SDimitry Andric     return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
157e3b55780SDimitry Andric   case KEYCXX20:
158e3b55780SDimitry Andric     if (LangOpts.CPlusPlus20)
159e3b55780SDimitry Andric       return KS_Enabled;
160e3b55780SDimitry Andric     return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
161e3b55780SDimitry Andric   case KEYGNU:
162e3b55780SDimitry Andric     return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
163e3b55780SDimitry Andric   case KEYMS:
164e3b55780SDimitry Andric     return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
165e3b55780SDimitry Andric   case BOOLSUPPORT:
166e3b55780SDimitry Andric     if (LangOpts.Bool)      return KS_Enabled;
167e3b55780SDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
168e3b55780SDimitry Andric   case KEYALTIVEC:
169e3b55780SDimitry Andric     return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
170e3b55780SDimitry Andric   case KEYBORLAND:
171e3b55780SDimitry Andric     return LangOpts.Borland ? KS_Extension : KS_Unknown;
172e3b55780SDimitry Andric   case KEYOPENCLC:
173e3b55780SDimitry Andric     return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
174e3b55780SDimitry Andric                                                         : KS_Unknown;
175e3b55780SDimitry Andric   case WCHARSUPPORT:
176e3b55780SDimitry Andric     return LangOpts.WChar ? KS_Enabled : KS_Unknown;
177e3b55780SDimitry Andric   case HALFSUPPORT:
178e3b55780SDimitry Andric     return LangOpts.Half ? KS_Enabled : KS_Unknown;
179e3b55780SDimitry Andric   case CHAR8SUPPORT:
180e3b55780SDimitry Andric     if (LangOpts.Char8) return KS_Enabled;
181e3b55780SDimitry Andric     if (LangOpts.CPlusPlus20) return KS_Unknown;
182e3b55780SDimitry Andric     if (LangOpts.CPlusPlus) return KS_Future;
183e3b55780SDimitry Andric     return KS_Unknown;
184e3b55780SDimitry Andric   case KEYOBJC:
185e3b55780SDimitry Andric     // We treat bridge casts as objective-C keywords so we can warn on them
186e3b55780SDimitry Andric     // in non-arc mode.
187e3b55780SDimitry Andric     return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
188e3b55780SDimitry Andric   case KEYZVECTOR:
189e3b55780SDimitry Andric     return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
190e3b55780SDimitry Andric   case KEYCOROUTINES:
191e3b55780SDimitry Andric     return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
192e3b55780SDimitry Andric   case KEYMODULES:
1937fa27ce4SDimitry Andric     return KS_Unknown;
194e3b55780SDimitry Andric   case KEYOPENCLCXX:
195e3b55780SDimitry Andric     return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
196e3b55780SDimitry Andric   case KEYMSCOMPAT:
197e3b55780SDimitry Andric     return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
198e3b55780SDimitry Andric   case KEYSYCL:
199e3b55780SDimitry Andric     return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
200e3b55780SDimitry Andric   case KEYCUDA:
201e3b55780SDimitry Andric     return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
202e3b55780SDimitry Andric   case KEYHLSL:
203e3b55780SDimitry Andric     return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
204e3b55780SDimitry Andric   case KEYNOCXX:
205e3b55780SDimitry Andric     // This is enabled in all non-C++ modes, but might be enabled for other
206e3b55780SDimitry Andric     // reasons as well.
207e3b55780SDimitry Andric     return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
208e3b55780SDimitry Andric   case KEYNOOPENCL:
209e3b55780SDimitry Andric     // The disable behavior for this is handled in getKeywordStatus.
210e3b55780SDimitry Andric     return KS_Unknown;
211e3b55780SDimitry Andric   case KEYNOMS18:
212e3b55780SDimitry Andric     // The disable behavior for this is handled in getKeywordStatus.
213e3b55780SDimitry Andric     return KS_Unknown;
214b1c73532SDimitry Andric   case KEYFIXEDPOINT:
215b1c73532SDimitry Andric     return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
216e3b55780SDimitry Andric   default:
217e3b55780SDimitry Andric     llvm_unreachable("Unknown KeywordStatus flag");
218e3b55780SDimitry Andric   }
219e3b55780SDimitry Andric }
220e3b55780SDimitry Andric 
22148675466SDimitry Andric /// Translates flags as specified in TokenKinds.def into keyword status
22206d4ba38SDimitry Andric /// in the given language standard.
getKeywordStatus(const LangOptions & LangOpts,unsigned Flags)22306d4ba38SDimitry Andric static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
22406d4ba38SDimitry Andric                                       unsigned Flags) {
225e3b55780SDimitry Andric   // KEYALL means always enabled, so special case this one.
22606d4ba38SDimitry Andric   if (Flags == KEYALL) return KS_Enabled;
227e3b55780SDimitry Andric   // These are tests that need to 'always win', as they are special in that they
228e3b55780SDimitry Andric   // disable based on certain conditions.
229e3b55780SDimitry Andric   if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;
230e3b55780SDimitry Andric   if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
231e3b55780SDimitry Andric       !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
23206d4ba38SDimitry Andric     return KS_Disabled;
233e3b55780SDimitry Andric 
234e3b55780SDimitry Andric   KeywordStatus CurStatus = KS_Unknown;
235e3b55780SDimitry Andric 
236e3b55780SDimitry Andric   while (Flags != 0) {
237e3b55780SDimitry Andric     unsigned CurFlag = Flags & ~(Flags - 1);
238e3b55780SDimitry Andric     Flags = Flags & ~CurFlag;
239e3b55780SDimitry Andric     CurStatus = std::max(
240e3b55780SDimitry Andric         CurStatus,
241e3b55780SDimitry Andric         getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));
242e3b55780SDimitry Andric   }
243e3b55780SDimitry Andric 
244e3b55780SDimitry Andric   if (CurStatus == KS_Unknown)
245e3b55780SDimitry Andric     return KS_Disabled;
246e3b55780SDimitry Andric   return CurStatus;
247ec2b103cSEd Schouten }
248ec2b103cSEd Schouten 
249ec2b103cSEd Schouten /// AddKeyword - This method is used to associate a token ID with specific
250ec2b103cSEd Schouten /// identifiers because they are language keywords.  This causes the lexer to
251ec2b103cSEd Schouten /// automatically map matching identifiers to specialized token codes.
AddKeyword(StringRef Keyword,tok::TokenKind TokenCode,unsigned Flags,const LangOptions & LangOpts,IdentifierTable & Table)25236981b17SDimitry Andric static void AddKeyword(StringRef Keyword,
253ec2b103cSEd Schouten                        tok::TokenKind TokenCode, unsigned Flags,
254ec2b103cSEd Schouten                        const LangOptions &LangOpts, IdentifierTable &Table) {
25506d4ba38SDimitry Andric   KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
256ec2b103cSEd Schouten 
257ec2b103cSEd Schouten   // Don't add this keyword if disabled in this language.
25806d4ba38SDimitry Andric   if (AddResult == KS_Disabled) return;
259ec2b103cSEd Schouten 
26036981b17SDimitry Andric   IdentifierInfo &Info =
26106d4ba38SDimitry Andric       Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
26206d4ba38SDimitry Andric   Info.setIsExtensionToken(AddResult == KS_Extension);
2635e20cdd8SDimitry Andric   Info.setIsFutureCompatKeyword(AddResult == KS_Future);
264ec2b103cSEd Schouten }
265ec2b103cSEd Schouten 
266ec2b103cSEd Schouten /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
267ec2b103cSEd Schouten /// representations.
AddCXXOperatorKeyword(StringRef Keyword,tok::TokenKind TokenCode,IdentifierTable & Table)26836981b17SDimitry Andric static void AddCXXOperatorKeyword(StringRef Keyword,
269ec2b103cSEd Schouten                                   tok::TokenKind TokenCode,
270ec2b103cSEd Schouten                                   IdentifierTable &Table) {
2713d1dcd9bSDimitry Andric   IdentifierInfo &Info = Table.get(Keyword, TokenCode);
272ec2b103cSEd Schouten   Info.setIsCPlusPlusOperatorKeyword();
273ec2b103cSEd Schouten }
274ec2b103cSEd Schouten 
27556d91b49SDimitry Andric /// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
27656d91b49SDimitry Andric /// or "property".
AddObjCKeyword(StringRef Name,tok::ObjCKeywordKind ObjCID,IdentifierTable & Table)27736981b17SDimitry Andric static void AddObjCKeyword(StringRef Name,
2784a37f65fSRoman Divacky                            tok::ObjCKeywordKind ObjCID,
279ec2b103cSEd Schouten                            IdentifierTable &Table) {
2804a37f65fSRoman Divacky   Table.get(Name).setObjCKeywordID(ObjCID);
281ec2b103cSEd Schouten }
282ec2b103cSEd Schouten 
AddNotableIdentifier(StringRef Name,tok::NotableIdentifierKind BTID,IdentifierTable & Table)283ac9a064cSDimitry Andric static void AddNotableIdentifier(StringRef Name,
284ac9a064cSDimitry Andric                                  tok::NotableIdentifierKind BTID,
2857fa27ce4SDimitry Andric                                  IdentifierTable &Table) {
286ac9a064cSDimitry Andric   // Don't add 'not_notable' identifier.
287ac9a064cSDimitry Andric   if (BTID != tok::not_notable) {
2887fa27ce4SDimitry Andric     IdentifierInfo &Info = Table.get(Name, tok::identifier);
289ac9a064cSDimitry Andric     Info.setNotableIdentifierID(BTID);
2907fa27ce4SDimitry Andric   }
2917fa27ce4SDimitry Andric }
2927fa27ce4SDimitry Andric 
293ec2b103cSEd Schouten /// AddKeywords - Add all keywords to the symbol table.
294ec2b103cSEd Schouten ///
AddKeywords(const LangOptions & LangOpts)295ec2b103cSEd Schouten void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
296ec2b103cSEd Schouten   // Add keywords and tokens for the current language.
297ec2b103cSEd Schouten #define KEYWORD(NAME, FLAGS) \
29836981b17SDimitry Andric   AddKeyword(StringRef(#NAME), tok::kw_ ## NAME,  \
299ec2b103cSEd Schouten              FLAGS, LangOpts, *this);
300ec2b103cSEd Schouten #define ALIAS(NAME, TOK, FLAGS) \
30136981b17SDimitry Andric   AddKeyword(StringRef(NAME), tok::kw_ ## TOK,  \
302ec2b103cSEd Schouten              FLAGS, LangOpts, *this);
303ec2b103cSEd Schouten #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
304ec2b103cSEd Schouten   if (LangOpts.CXXOperatorNames)          \
30536981b17SDimitry Andric     AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
306676fbe81SDimitry Andric #define OBJC_AT_KEYWORD(NAME)  \
307676fbe81SDimitry Andric   if (LangOpts.ObjC)           \
30836981b17SDimitry Andric     AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
309ac9a064cSDimitry Andric #define NOTABLE_IDENTIFIER(NAME)                                               \
310ac9a064cSDimitry Andric   AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
3117fa27ce4SDimitry Andric 
31201af97d3SDimitry Andric #define TESTING_KEYWORD(NAME, FLAGS)
313ec2b103cSEd Schouten #include "clang/Basic/TokenKinds.def"
31401af97d3SDimitry Andric 
31501af97d3SDimitry Andric   if (LangOpts.ParseUnknownAnytype)
31601af97d3SDimitry Andric     AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
31701af97d3SDimitry Andric                LangOpts, *this);
3185e20cdd8SDimitry Andric 
31945b53394SDimitry Andric   if (LangOpts.DeclSpecKeyword)
3205e20cdd8SDimitry Andric     AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
32148675466SDimitry Andric 
322344a3780SDimitry Andric   if (LangOpts.IEEE128)
323344a3780SDimitry Andric     AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
324344a3780SDimitry Andric 
32522989816SDimitry Andric   // Add the 'import' contextual keyword.
32648675466SDimitry Andric   get("import").setModulesImport(true);
327ec2b103cSEd Schouten }
328ec2b103cSEd Schouten 
32948675466SDimitry Andric /// Checks if the specified token kind represents a keyword in the
33006d4ba38SDimitry Andric /// specified language.
33106d4ba38SDimitry Andric /// \returns Status of the keyword in the language.
getTokenKwStatus(const LangOptions & LangOpts,tok::TokenKind K)33206d4ba38SDimitry Andric static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
33306d4ba38SDimitry Andric                                       tok::TokenKind K) {
33406d4ba38SDimitry Andric   switch (K) {
33506d4ba38SDimitry Andric #define KEYWORD(NAME, FLAGS) \
33606d4ba38SDimitry Andric   case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
33706d4ba38SDimitry Andric #include "clang/Basic/TokenKinds.def"
33806d4ba38SDimitry Andric   default: return KS_Disabled;
33906d4ba38SDimitry Andric   }
34006d4ba38SDimitry Andric }
34106d4ba38SDimitry Andric 
34248675466SDimitry Andric /// Returns true if the identifier represents a keyword in the
34306d4ba38SDimitry Andric /// specified language.
isKeyword(const LangOptions & LangOpts) const3447442d6faSDimitry Andric bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
34506d4ba38SDimitry Andric   switch (getTokenKwStatus(LangOpts, getTokenID())) {
34606d4ba38SDimitry Andric   case KS_Enabled:
34706d4ba38SDimitry Andric   case KS_Extension:
34806d4ba38SDimitry Andric     return true;
34906d4ba38SDimitry Andric   default:
35006d4ba38SDimitry Andric     return false;
35106d4ba38SDimitry Andric   }
35206d4ba38SDimitry Andric }
35306d4ba38SDimitry Andric 
35448675466SDimitry Andric /// Returns true if the identifier represents a C++ keyword in the
3557442d6faSDimitry Andric /// specified language.
isCPlusPlusKeyword(const LangOptions & LangOpts) const3567442d6faSDimitry Andric bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
3577442d6faSDimitry Andric   if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
3587442d6faSDimitry Andric     return false;
3597442d6faSDimitry Andric   // This is a C++ keyword if this identifier is not a keyword when checked
3607442d6faSDimitry Andric   // using LangOptions without C++ support.
3617442d6faSDimitry Andric   LangOptions LangOptsNoCPP = LangOpts;
3627442d6faSDimitry Andric   LangOptsNoCPP.CPlusPlus = false;
3637442d6faSDimitry Andric   LangOptsNoCPP.CPlusPlus11 = false;
364cfca06d7SDimitry Andric   LangOptsNoCPP.CPlusPlus20 = false;
3657442d6faSDimitry Andric   return !isKeyword(LangOptsNoCPP);
3667442d6faSDimitry Andric }
3677442d6faSDimitry Andric 
368344a3780SDimitry Andric ReservedIdentifierStatus
isReserved(const LangOptions & LangOpts) const369344a3780SDimitry Andric IdentifierInfo::isReserved(const LangOptions &LangOpts) const {
370344a3780SDimitry Andric   StringRef Name = getName();
371344a3780SDimitry Andric 
372344a3780SDimitry Andric   // '_' is a reserved identifier, but its use is so common (e.g. to store
373344a3780SDimitry Andric   // ignored values) that we don't warn on it.
374344a3780SDimitry Andric   if (Name.size() <= 1)
375344a3780SDimitry Andric     return ReservedIdentifierStatus::NotReserved;
376344a3780SDimitry Andric 
377344a3780SDimitry Andric   // [lex.name] p3
378344a3780SDimitry Andric   if (Name[0] == '_') {
379344a3780SDimitry Andric 
380344a3780SDimitry Andric     // Each name that begins with an underscore followed by an uppercase letter
381344a3780SDimitry Andric     // or another underscore is reserved.
382344a3780SDimitry Andric     if (Name[1] == '_')
383344a3780SDimitry Andric       return ReservedIdentifierStatus::StartsWithDoubleUnderscore;
384344a3780SDimitry Andric 
385344a3780SDimitry Andric     if ('A' <= Name[1] && Name[1] <= 'Z')
386344a3780SDimitry Andric       return ReservedIdentifierStatus::
387344a3780SDimitry Andric           StartsWithUnderscoreFollowedByCapitalLetter;
388344a3780SDimitry Andric 
389344a3780SDimitry Andric     // This is a bit misleading: it actually means it's only reserved if we're
390344a3780SDimitry Andric     // at global scope because it starts with an underscore.
391344a3780SDimitry Andric     return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
392344a3780SDimitry Andric   }
393344a3780SDimitry Andric 
394344a3780SDimitry Andric   // Each name that contains a double underscore (__) is reserved.
395344a3780SDimitry Andric   if (LangOpts.CPlusPlus && Name.contains("__"))
396344a3780SDimitry Andric     return ReservedIdentifierStatus::ContainsDoubleUnderscore;
397344a3780SDimitry Andric 
398344a3780SDimitry Andric   return ReservedIdentifierStatus::NotReserved;
399344a3780SDimitry Andric }
400344a3780SDimitry Andric 
4017fa27ce4SDimitry Andric ReservedLiteralSuffixIdStatus
isReservedLiteralSuffixId() const4027fa27ce4SDimitry Andric IdentifierInfo::isReservedLiteralSuffixId() const {
4037fa27ce4SDimitry Andric   StringRef Name = getName();
4047fa27ce4SDimitry Andric 
4057fa27ce4SDimitry Andric   if (Name[0] != '_')
4067fa27ce4SDimitry Andric     return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;
4077fa27ce4SDimitry Andric 
4087fa27ce4SDimitry Andric   if (Name.contains("__"))
4097fa27ce4SDimitry Andric     return ReservedLiteralSuffixIdStatus::ContainsDoubleUnderscore;
4107fa27ce4SDimitry Andric 
4117fa27ce4SDimitry Andric   return ReservedLiteralSuffixIdStatus::NotReserved;
4127fa27ce4SDimitry Andric }
4137fa27ce4SDimitry Andric 
deuglifiedName() const4146f8fc217SDimitry Andric StringRef IdentifierInfo::deuglifiedName() const {
4156f8fc217SDimitry Andric   StringRef Name = getName();
4166f8fc217SDimitry Andric   if (Name.size() >= 2 && Name.front() == '_' &&
4176f8fc217SDimitry Andric       (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
4186f8fc217SDimitry Andric     return Name.ltrim('_');
4196f8fc217SDimitry Andric   return Name;
4206f8fc217SDimitry Andric }
4216f8fc217SDimitry Andric 
getPPKeywordID() const422ec2b103cSEd Schouten tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
423ec2b103cSEd Schouten   // We use a perfect hash function here involving the length of the keyword,
424ec2b103cSEd Schouten   // the first and third character.  For preprocessor ID's there are no
425ec2b103cSEd Schouten   // collisions (if there were, the switch below would complain about duplicate
426ec2b103cSEd Schouten   // case values).  Note that this depends on 'if' being null terminated.
427ec2b103cSEd Schouten 
428ec2b103cSEd Schouten #define HASH(LEN, FIRST, THIRD)                                                \
429ac9a064cSDimitry Andric   (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
430ec2b103cSEd Schouten #define CASE(LEN, FIRST, THIRD, NAME) \
431ec2b103cSEd Schouten   case HASH(LEN, FIRST, THIRD): \
432ec2b103cSEd Schouten     return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
433ec2b103cSEd Schouten 
434ec2b103cSEd Schouten   unsigned Len = getLength();
435ec2b103cSEd Schouten   if (Len < 2) return tok::pp_not_keyword;
43673490b89SRoman Divacky   const char *Name = getNameStart();
437ec2b103cSEd Schouten   switch (HASH(Len, Name[0], Name[2])) {
438ec2b103cSEd Schouten   default: return tok::pp_not_keyword;
439ec2b103cSEd Schouten   CASE( 2, 'i', '\0', if);
440ec2b103cSEd Schouten   CASE( 4, 'e', 'i', elif);
441ec2b103cSEd Schouten   CASE( 4, 'e', 's', else);
442ec2b103cSEd Schouten   CASE( 4, 'l', 'n', line);
443ec2b103cSEd Schouten   CASE( 4, 's', 'c', sccs);
444ac9a064cSDimitry Andric   CASE( 5, 'e', 'b', embed);
445ec2b103cSEd Schouten   CASE( 5, 'e', 'd', endif);
446ec2b103cSEd Schouten   CASE( 5, 'e', 'r', error);
447ec2b103cSEd Schouten   CASE( 5, 'i', 'e', ident);
448ec2b103cSEd Schouten   CASE( 5, 'i', 'd', ifdef);
449ec2b103cSEd Schouten   CASE( 5, 'u', 'd', undef);
450ec2b103cSEd Schouten 
451ec2b103cSEd Schouten   CASE( 6, 'a', 's', assert);
452ec2b103cSEd Schouten   CASE( 6, 'd', 'f', define);
453ec2b103cSEd Schouten   CASE( 6, 'i', 'n', ifndef);
454ec2b103cSEd Schouten   CASE( 6, 'i', 'p', import);
455ec2b103cSEd Schouten   CASE( 6, 'p', 'a', pragma);
456ec2b103cSEd Schouten 
457ec2b103cSEd Schouten   CASE( 7, 'd', 'f', defined);
458344a3780SDimitry Andric   CASE( 7, 'e', 'i', elifdef);
459ec2b103cSEd Schouten   CASE( 7, 'i', 'c', include);
460ec2b103cSEd Schouten   CASE( 7, 'w', 'r', warning);
461ec2b103cSEd Schouten 
462344a3780SDimitry Andric   CASE( 8, 'e', 'i', elifndef);
463ec2b103cSEd Schouten   CASE( 8, 'u', 'a', unassert);
464ec2b103cSEd Schouten   CASE(12, 'i', 'c', include_next);
465ec2b103cSEd Schouten 
466dbe13110SDimitry Andric   CASE(14, '_', 'p', __public_macro);
467dbe13110SDimitry Andric 
468dbe13110SDimitry Andric   CASE(15, '_', 'p', __private_macro);
469dbe13110SDimitry Andric 
470ec2b103cSEd Schouten   CASE(16, '_', 'i', __include_macros);
471ec2b103cSEd Schouten #undef CASE
472ec2b103cSEd Schouten #undef HASH
473ec2b103cSEd Schouten   }
474ec2b103cSEd Schouten }
475ec2b103cSEd Schouten 
476ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
477ec2b103cSEd Schouten // Stats Implementation
478ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
479ec2b103cSEd Schouten 
480ec2b103cSEd Schouten /// PrintStats - Print statistics about how well the identifier table is doing
481ec2b103cSEd Schouten /// at hashing identifiers.
PrintStats() const482ec2b103cSEd Schouten void IdentifierTable::PrintStats() const {
483ec2b103cSEd Schouten   unsigned NumBuckets = HashTable.getNumBuckets();
484ec2b103cSEd Schouten   unsigned NumIdentifiers = HashTable.getNumItems();
485ec2b103cSEd Schouten   unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
486ec2b103cSEd Schouten   unsigned AverageIdentifierSize = 0;
487ec2b103cSEd Schouten   unsigned MaxIdentifierLength = 0;
488ec2b103cSEd Schouten 
489ec2b103cSEd Schouten   // TODO: Figure out maximum times an identifier had to probe for -stats.
490ec2b103cSEd Schouten   for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
491ec2b103cSEd Schouten        I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
492ec2b103cSEd Schouten     unsigned IdLen = I->getKeyLength();
493ec2b103cSEd Schouten     AverageIdentifierSize += IdLen;
494ec2b103cSEd Schouten     if (MaxIdentifierLength < IdLen)
495ec2b103cSEd Schouten       MaxIdentifierLength = IdLen;
496ec2b103cSEd Schouten   }
497ec2b103cSEd Schouten 
498ec2b103cSEd Schouten   fprintf(stderr, "\n*** Identifier Table Stats:\n");
499ec2b103cSEd Schouten   fprintf(stderr, "# Identifiers:   %d\n", NumIdentifiers);
500ec2b103cSEd Schouten   fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
501ec2b103cSEd Schouten   fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
502ec2b103cSEd Schouten           NumIdentifiers/(double)NumBuckets);
503ec2b103cSEd Schouten   fprintf(stderr, "Ave identifier length: %f\n",
504ec2b103cSEd Schouten           (AverageIdentifierSize/(double)NumIdentifiers));
505ec2b103cSEd Schouten   fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
506ec2b103cSEd Schouten 
507ec2b103cSEd Schouten   // Compute statistics about the memory allocated for identifiers.
508ec2b103cSEd Schouten   HashTable.getAllocator().PrintStats();
509ec2b103cSEd Schouten }
510ec2b103cSEd Schouten 
511ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
512ec2b103cSEd Schouten // SelectorTable Implementation
513ec2b103cSEd Schouten //===----------------------------------------------------------------------===//
514ec2b103cSEd Schouten 
getHashValue(clang::Selector S)515ec2b103cSEd Schouten unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
516ec2b103cSEd Schouten   return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
517ec2b103cSEd Schouten }
518ec2b103cSEd Schouten 
isKeywordSelector(ArrayRef<StringRef> Names) const519519fc96cSDimitry Andric bool Selector::isKeywordSelector(ArrayRef<StringRef> Names) const {
520519fc96cSDimitry Andric   assert(!Names.empty() && "must have >= 1 selector slots");
521519fc96cSDimitry Andric   if (getNumArgs() != Names.size())
522519fc96cSDimitry Andric     return false;
523519fc96cSDimitry Andric   for (unsigned I = 0, E = Names.size(); I != E; ++I) {
524519fc96cSDimitry Andric     if (getNameForSlot(I) != Names[I])
525519fc96cSDimitry Andric       return false;
526519fc96cSDimitry Andric   }
527519fc96cSDimitry Andric   return true;
528519fc96cSDimitry Andric }
529519fc96cSDimitry Andric 
isUnarySelector(StringRef Name) const530519fc96cSDimitry Andric bool Selector::isUnarySelector(StringRef Name) const {
531519fc96cSDimitry Andric   return isUnarySelector() && getNameForSlot(0) == Name;
532519fc96cSDimitry Andric }
533519fc96cSDimitry Andric 
getNumArgs() const534ec2b103cSEd Schouten unsigned Selector::getNumArgs() const {
535ec2b103cSEd Schouten   unsigned IIF = getIdentifierInfoFlag();
53656d91b49SDimitry Andric   if (IIF <= ZeroArg)
537ec2b103cSEd Schouten     return 0;
538ec2b103cSEd Schouten   if (IIF == OneArg)
539ec2b103cSEd Schouten     return 1;
54056d91b49SDimitry Andric   // We point to a MultiKeywordSelector.
54156d91b49SDimitry Andric   MultiKeywordSelector *SI = getMultiKeywordSelector();
542ec2b103cSEd Schouten   return SI->getNumArgs();
543ec2b103cSEd Schouten }
544ec2b103cSEd Schouten 
545ac9a064cSDimitry Andric const IdentifierInfo *
getIdentifierInfoForSlot(unsigned argIndex) const546ac9a064cSDimitry Andric Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
54756d91b49SDimitry Andric   if (getIdentifierInfoFlag() < MultiArg) {
548ec2b103cSEd Schouten     assert(argIndex == 0 && "illegal keyword index");
549ec2b103cSEd Schouten     return getAsIdentifierInfo();
550ec2b103cSEd Schouten   }
551461a67faSDimitry Andric 
55256d91b49SDimitry Andric   // We point to a MultiKeywordSelector.
55356d91b49SDimitry Andric   MultiKeywordSelector *SI = getMultiKeywordSelector();
554ec2b103cSEd Schouten   return SI->getIdentifierInfoForSlot(argIndex);
555ec2b103cSEd Schouten }
556ec2b103cSEd Schouten 
getNameForSlot(unsigned int argIndex) const55736981b17SDimitry Andric StringRef Selector::getNameForSlot(unsigned int argIndex) const {
558ac9a064cSDimitry Andric   const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
55936981b17SDimitry Andric   return II ? II->getName() : StringRef();
560bca07a45SDimitry Andric }
561bca07a45SDimitry Andric 
getName() const562ec2b103cSEd Schouten std::string MultiKeywordSelector::getName() const {
563dbe13110SDimitry Andric   SmallString<256> Str;
56473490b89SRoman Divacky   llvm::raw_svector_ostream OS(Str);
565ec2b103cSEd Schouten   for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
566ec2b103cSEd Schouten     if (*I)
56773490b89SRoman Divacky       OS << (*I)->getName();
56873490b89SRoman Divacky     OS << ':';
569ec2b103cSEd Schouten   }
570ec2b103cSEd Schouten 
571cfca06d7SDimitry Andric   return std::string(OS.str());
572ec2b103cSEd Schouten }
573ec2b103cSEd Schouten 
getAsString() const574ec2b103cSEd Schouten std::string Selector::getAsString() const {
575b1c73532SDimitry Andric   if (isNull())
576ec2b103cSEd Schouten     return "<null selector>";
577ec2b103cSEd Schouten 
57856d91b49SDimitry Andric   if (getIdentifierInfoFlag() < MultiArg) {
579ac9a064cSDimitry Andric     const IdentifierInfo *II = getAsIdentifierInfo();
580ec2b103cSEd Schouten 
581bab175ecSDimitry Andric     if (getNumArgs() == 0) {
582bab175ecSDimitry Andric       assert(II && "If the number of arguments is 0 then II is guaranteed to "
583bab175ecSDimitry Andric                    "not be null.");
584cfca06d7SDimitry Andric       return std::string(II->getName());
585bab175ecSDimitry Andric     }
586ec2b103cSEd Schouten 
58773490b89SRoman Divacky     if (!II)
58873490b89SRoman Divacky       return ":";
58973490b89SRoman Divacky 
59073490b89SRoman Divacky     return II->getName().str() + ":";
591ec2b103cSEd Schouten   }
592ec2b103cSEd Schouten 
59356d91b49SDimitry Andric   // We have a multiple keyword selector.
59456d91b49SDimitry Andric   return getMultiKeywordSelector()->getName();
595ec2b103cSEd Schouten }
596ec2b103cSEd Schouten 
print(llvm::raw_ostream & OS) const5979f4dbff6SDimitry Andric void Selector::print(llvm::raw_ostream &OS) const {
5989f4dbff6SDimitry Andric   OS << getAsString();
5999f4dbff6SDimitry Andric }
6009f4dbff6SDimitry Andric 
dump() const60148675466SDimitry Andric LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
60248675466SDimitry Andric 
60301af97d3SDimitry Andric /// Interpreting the given string using the normal CamelCase
60401af97d3SDimitry Andric /// conventions, determine whether the given string starts with the
60501af97d3SDimitry Andric /// given "word", which is assumed to end in a lowercase letter.
startsWithWord(StringRef name,StringRef word)60636981b17SDimitry Andric static bool startsWithWord(StringRef name, StringRef word) {
60701af97d3SDimitry Andric   if (name.size() < word.size()) return false;
608809500fcSDimitry Andric   return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
609312c0ed1SDimitry Andric           name.starts_with(word));
61001af97d3SDimitry Andric }
61101af97d3SDimitry Andric 
getMethodFamilyImpl(Selector sel)61201af97d3SDimitry Andric ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
613ac9a064cSDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
61401af97d3SDimitry Andric   if (!first) return OMF_None;
61501af97d3SDimitry Andric 
61636981b17SDimitry Andric   StringRef name = first->getName();
61701af97d3SDimitry Andric   if (sel.isUnarySelector()) {
61801af97d3SDimitry Andric     if (name == "autorelease") return OMF_autorelease;
61901af97d3SDimitry Andric     if (name == "dealloc") return OMF_dealloc;
62036981b17SDimitry Andric     if (name == "finalize") return OMF_finalize;
62101af97d3SDimitry Andric     if (name == "release") return OMF_release;
62201af97d3SDimitry Andric     if (name == "retain") return OMF_retain;
62301af97d3SDimitry Andric     if (name == "retainCount") return OMF_retainCount;
62429cafa66SDimitry Andric     if (name == "self") return OMF_self;
62506d4ba38SDimitry Andric     if (name == "initialize") return OMF_initialize;
62601af97d3SDimitry Andric   }
62701af97d3SDimitry Andric 
6287442d6faSDimitry Andric   if (name == "performSelector" || name == "performSelectorInBackground" ||
6297442d6faSDimitry Andric       name == "performSelectorOnMainThread")
6307442d6faSDimitry Andric     return OMF_performSelector;
631180abc3dSDimitry Andric 
63201af97d3SDimitry Andric   // The other method families may begin with a prefix of underscores.
63377dbea07SDimitry Andric   name = name.ltrim('_');
63401af97d3SDimitry Andric 
63501af97d3SDimitry Andric   if (name.empty()) return OMF_None;
63601af97d3SDimitry Andric   switch (name.front()) {
63701af97d3SDimitry Andric   case 'a':
63801af97d3SDimitry Andric     if (startsWithWord(name, "alloc")) return OMF_alloc;
63901af97d3SDimitry Andric     break;
64001af97d3SDimitry Andric   case 'c':
64101af97d3SDimitry Andric     if (startsWithWord(name, "copy")) return OMF_copy;
64201af97d3SDimitry Andric     break;
64301af97d3SDimitry Andric   case 'i':
64401af97d3SDimitry Andric     if (startsWithWord(name, "init")) return OMF_init;
64501af97d3SDimitry Andric     break;
64601af97d3SDimitry Andric   case 'm':
64701af97d3SDimitry Andric     if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
64801af97d3SDimitry Andric     break;
64901af97d3SDimitry Andric   case 'n':
65001af97d3SDimitry Andric     if (startsWithWord(name, "new")) return OMF_new;
65101af97d3SDimitry Andric     break;
65201af97d3SDimitry Andric   default:
65301af97d3SDimitry Andric     break;
65401af97d3SDimitry Andric   }
65501af97d3SDimitry Andric 
65601af97d3SDimitry Andric   return OMF_None;
65701af97d3SDimitry Andric }
658ec2b103cSEd Schouten 
getInstTypeMethodFamily(Selector sel)659bfef3995SDimitry Andric ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
660ac9a064cSDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
661bfef3995SDimitry Andric   if (!first) return OIT_None;
662bfef3995SDimitry Andric 
663bfef3995SDimitry Andric   StringRef name = first->getName();
664bfef3995SDimitry Andric 
665bfef3995SDimitry Andric   if (name.empty()) return OIT_None;
666bfef3995SDimitry Andric   switch (name.front()) {
667bfef3995SDimitry Andric     case 'a':
668bfef3995SDimitry Andric       if (startsWithWord(name, "array")) return OIT_Array;
669bfef3995SDimitry Andric       break;
670bfef3995SDimitry Andric     case 'd':
671bfef3995SDimitry Andric       if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
672bfef3995SDimitry Andric       if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
673bfef3995SDimitry Andric       break;
674bfef3995SDimitry Andric     case 's':
675bfef3995SDimitry Andric       if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
676bfef3995SDimitry Andric       if (startsWithWord(name, "standard")) return OIT_Singleton;
677551c6985SDimitry Andric       break;
678bfef3995SDimitry Andric     case 'i':
679bfef3995SDimitry Andric       if (startsWithWord(name, "init")) return OIT_Init;
680676fbe81SDimitry Andric       break;
681bfef3995SDimitry Andric     default:
682bfef3995SDimitry Andric       break;
683bfef3995SDimitry Andric   }
684bfef3995SDimitry Andric   return OIT_None;
685bfef3995SDimitry Andric }
686bfef3995SDimitry Andric 
getStringFormatFamilyImpl(Selector sel)68706d4ba38SDimitry Andric ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
688ac9a064cSDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
68906d4ba38SDimitry Andric   if (!first) return SFF_None;
69006d4ba38SDimitry Andric 
69106d4ba38SDimitry Andric   StringRef name = first->getName();
69206d4ba38SDimitry Andric 
69306d4ba38SDimitry Andric   switch (name.front()) {
69406d4ba38SDimitry Andric     case 'a':
69506d4ba38SDimitry Andric       if (name == "appendFormat") return SFF_NSString;
69606d4ba38SDimitry Andric       break;
69706d4ba38SDimitry Andric 
69806d4ba38SDimitry Andric     case 'i':
69906d4ba38SDimitry Andric       if (name == "initWithFormat") return SFF_NSString;
70006d4ba38SDimitry Andric       break;
70106d4ba38SDimitry Andric 
70206d4ba38SDimitry Andric     case 'l':
70306d4ba38SDimitry Andric       if (name == "localizedStringWithFormat") return SFF_NSString;
70406d4ba38SDimitry Andric       break;
70506d4ba38SDimitry Andric 
70606d4ba38SDimitry Andric     case 's':
70706d4ba38SDimitry Andric       if (name == "stringByAppendingFormat" ||
70806d4ba38SDimitry Andric           name == "stringWithFormat") return SFF_NSString;
70906d4ba38SDimitry Andric       break;
71006d4ba38SDimitry Andric   }
71106d4ba38SDimitry Andric   return SFF_None;
71206d4ba38SDimitry Andric }
71306d4ba38SDimitry Andric 
714ec2b103cSEd Schouten namespace {
715461a67faSDimitry Andric 
716ec2b103cSEd Schouten struct SelectorTableImpl {
717ec2b103cSEd Schouten   llvm::FoldingSet<MultiKeywordSelector> Table;
718ec2b103cSEd Schouten   llvm::BumpPtrAllocator Allocator;
719ec2b103cSEd Schouten };
720461a67faSDimitry Andric 
721461a67faSDimitry Andric } // namespace
722ec2b103cSEd Schouten 
getSelectorTableImpl(void * P)723ec2b103cSEd Schouten static SelectorTableImpl &getSelectorTableImpl(void *P) {
724ec2b103cSEd Schouten   return *static_cast<SelectorTableImpl*>(P);
725ec2b103cSEd Schouten }
726ec2b103cSEd Schouten 
727bfef3995SDimitry Andric SmallString<64>
constructSetterName(StringRef Name)728bfef3995SDimitry Andric SelectorTable::constructSetterName(StringRef Name) {
729bfef3995SDimitry Andric   SmallString<64> SetterName("set");
730bfef3995SDimitry Andric   SetterName += Name;
731bfef3995SDimitry Andric   SetterName[3] = toUppercase(SetterName[3]);
732bfef3995SDimitry Andric   return SetterName;
733bfef3995SDimitry Andric }
734bfef3995SDimitry Andric 
735bfef3995SDimitry Andric Selector
constructSetterSelector(IdentifierTable & Idents,SelectorTable & SelTable,const IdentifierInfo * Name)736bfef3995SDimitry Andric SelectorTable::constructSetterSelector(IdentifierTable &Idents,
737dbe13110SDimitry Andric                                        SelectorTable &SelTable,
738dbe13110SDimitry Andric                                        const IdentifierInfo *Name) {
739bfef3995SDimitry Andric   IdentifierInfo *SetterName =
740bfef3995SDimitry Andric     &Idents.get(constructSetterName(Name->getName()));
741dbe13110SDimitry Andric   return SelTable.getUnarySelector(SetterName);
742dbe13110SDimitry Andric }
743dbe13110SDimitry Andric 
getPropertyNameFromSetterSelector(Selector Sel)74448675466SDimitry Andric std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {
74548675466SDimitry Andric   StringRef Name = Sel.getNameForSlot(0);
746312c0ed1SDimitry Andric   assert(Name.starts_with("set") && "invalid setter name");
74748675466SDimitry Andric   return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
74848675466SDimitry Andric }
74948675466SDimitry Andric 
getTotalMemory() const75001af97d3SDimitry Andric size_t SelectorTable::getTotalMemory() const {
75101af97d3SDimitry Andric   SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
75201af97d3SDimitry Andric   return SelTabImpl.Allocator.getTotalMemory();
75301af97d3SDimitry Andric }
754ec2b103cSEd Schouten 
getSelector(unsigned nKeys,const IdentifierInfo ** IIV)755ac9a064cSDimitry Andric Selector SelectorTable::getSelector(unsigned nKeys,
756ac9a064cSDimitry Andric                                     const IdentifierInfo **IIV) {
757ec2b103cSEd Schouten   if (nKeys < 2)
758ec2b103cSEd Schouten     return Selector(IIV[0], nKeys);
759ec2b103cSEd Schouten 
760ec2b103cSEd Schouten   SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
761ec2b103cSEd Schouten 
762ec2b103cSEd Schouten   // Unique selector, to guarantee there is one per name.
763ec2b103cSEd Schouten   llvm::FoldingSetNodeID ID;
764ec2b103cSEd Schouten   MultiKeywordSelector::Profile(ID, IIV, nKeys);
765ec2b103cSEd Schouten 
7669f4dbff6SDimitry Andric   void *InsertPos = nullptr;
767ec2b103cSEd Schouten   if (MultiKeywordSelector *SI =
768ec2b103cSEd Schouten         SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
769ec2b103cSEd Schouten     return Selector(SI);
770ec2b103cSEd Schouten 
771ec2b103cSEd Schouten   // MultiKeywordSelector objects are not allocated with new because they have a
772ec2b103cSEd Schouten   // variable size array (for parameter types) at the end of them.
773ec2b103cSEd Schouten   unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
774ec2b103cSEd Schouten   MultiKeywordSelector *SI =
775bab175ecSDimitry Andric       (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
776bab175ecSDimitry Andric           Size, alignof(MultiKeywordSelector));
777ec2b103cSEd Schouten   new (SI) MultiKeywordSelector(nKeys, IIV);
778ec2b103cSEd Schouten   SelTabImpl.Table.InsertNode(SI, InsertPos);
779ec2b103cSEd Schouten   return Selector(SI);
780ec2b103cSEd Schouten }
781ec2b103cSEd Schouten 
SelectorTable()782ec2b103cSEd Schouten SelectorTable::SelectorTable() {
783ec2b103cSEd Schouten   Impl = new SelectorTableImpl();
784ec2b103cSEd Schouten }
785ec2b103cSEd Schouten 
~SelectorTable()786ec2b103cSEd Schouten SelectorTable::~SelectorTable() {
787ec2b103cSEd Schouten   delete &getSelectorTableImpl(Impl);
788ec2b103cSEd Schouten }
789ec2b103cSEd Schouten 
getOperatorSpelling(OverloadedOperatorKind Operator)79051fb8b01SRoman Divacky const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
79151fb8b01SRoman Divacky   switch (Operator) {
79251fb8b01SRoman Divacky   case OO_None:
79351fb8b01SRoman Divacky   case NUM_OVERLOADED_OPERATORS:
7949f4dbff6SDimitry Andric     return nullptr;
79551fb8b01SRoman Divacky 
79651fb8b01SRoman Divacky #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
79751fb8b01SRoman Divacky   case OO_##Name: return Spelling;
79851fb8b01SRoman Divacky #include "clang/Basic/OperatorKinds.def"
79951fb8b01SRoman Divacky   }
80051fb8b01SRoman Divacky 
801dbe13110SDimitry Andric   llvm_unreachable("Invalid OverloadedOperatorKind!");
80251fb8b01SRoman Divacky }
8032e645aa5SDimitry Andric 
getNullabilitySpelling(NullabilityKind kind,bool isContextSensitive)804c192b3dcSDimitry Andric StringRef clang::getNullabilitySpelling(NullabilityKind kind,
805c192b3dcSDimitry Andric                                         bool isContextSensitive) {
8062e645aa5SDimitry Andric   switch (kind) {
8072e645aa5SDimitry Andric   case NullabilityKind::NonNull:
808c192b3dcSDimitry Andric     return isContextSensitive ? "nonnull" : "_Nonnull";
8092e645aa5SDimitry Andric 
8102e645aa5SDimitry Andric   case NullabilityKind::Nullable:
811c192b3dcSDimitry Andric     return isContextSensitive ? "nullable" : "_Nullable";
8122e645aa5SDimitry Andric 
813b60736ecSDimitry Andric   case NullabilityKind::NullableResult:
814b60736ecSDimitry Andric     assert(!isContextSensitive &&
815b60736ecSDimitry Andric            "_Nullable_result isn't supported as context-sensitive keyword");
816b60736ecSDimitry Andric     return "_Nullable_result";
817b60736ecSDimitry Andric 
8182e645aa5SDimitry Andric   case NullabilityKind::Unspecified:
819c192b3dcSDimitry Andric     return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
8202e645aa5SDimitry Andric   }
8212e645aa5SDimitry Andric   llvm_unreachable("Unknown nullability kind.");
8222e645aa5SDimitry Andric }
823e3b55780SDimitry Andric 
operator <<(llvm::raw_ostream & OS,NullabilityKind NK)8247fa27ce4SDimitry Andric llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
8257fa27ce4SDimitry Andric                                      NullabilityKind NK) {
8267fa27ce4SDimitry Andric   switch (NK) {
8277fa27ce4SDimitry Andric   case NullabilityKind::NonNull:
8287fa27ce4SDimitry Andric     return OS << "NonNull";
8297fa27ce4SDimitry Andric   case NullabilityKind::Nullable:
8307fa27ce4SDimitry Andric     return OS << "Nullable";
8317fa27ce4SDimitry Andric   case NullabilityKind::NullableResult:
8327fa27ce4SDimitry Andric     return OS << "NullableResult";
8337fa27ce4SDimitry Andric   case NullabilityKind::Unspecified:
8347fa27ce4SDimitry Andric     return OS << "Unspecified";
8357fa27ce4SDimitry Andric   }
8367fa27ce4SDimitry Andric   llvm_unreachable("Unknown nullability kind.");
8377fa27ce4SDimitry Andric }
8387fa27ce4SDimitry Andric 
839e3b55780SDimitry Andric diag::kind
getFutureCompatDiagKind(const IdentifierInfo & II,const LangOptions & LangOpts)840e3b55780SDimitry Andric IdentifierTable::getFutureCompatDiagKind(const IdentifierInfo &II,
841e3b55780SDimitry Andric                                          const LangOptions &LangOpts) {
842e3b55780SDimitry Andric   assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
843e3b55780SDimitry Andric 
844e3b55780SDimitry Andric   unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
845e3b55780SDimitry Andric #define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
846e3b55780SDimitry Andric #include "clang/Basic/TokenKinds.def"
847e3b55780SDimitry Andric #undef KEYWORD
848e3b55780SDimitry Andric       ;
849e3b55780SDimitry Andric 
850e3b55780SDimitry Andric   if (LangOpts.CPlusPlus) {
851e3b55780SDimitry Andric     if ((Flags & KEYCXX11) == KEYCXX11)
852e3b55780SDimitry Andric       return diag::warn_cxx11_keyword;
853e3b55780SDimitry Andric 
854e3b55780SDimitry Andric     // char8_t is not modeled as a CXX20_KEYWORD because it's not
855e3b55780SDimitry Andric     // unconditionally enabled in C++20 mode. (It can be disabled
856e3b55780SDimitry Andric     // by -fno-char8_t.)
857e3b55780SDimitry Andric     if (((Flags & KEYCXX20) == KEYCXX20) ||
858e3b55780SDimitry Andric         ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
859e3b55780SDimitry Andric       return diag::warn_cxx20_keyword;
860e3b55780SDimitry Andric   } else {
861e3b55780SDimitry Andric     if ((Flags & KEYC99) == KEYC99)
862e3b55780SDimitry Andric       return diag::warn_c99_keyword;
863b1c73532SDimitry Andric     if ((Flags & KEYC23) == KEYC23)
864b1c73532SDimitry Andric       return diag::warn_c23_keyword;
865e3b55780SDimitry Andric   }
866e3b55780SDimitry Andric 
867e3b55780SDimitry Andric   llvm_unreachable(
868e3b55780SDimitry Andric       "Keyword not known to come from a newer Standard or proposed Standard");
869e3b55780SDimitry Andric }
870