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