xref: /freebsd-src/contrib/llvm-project/clang/lib/Basic/IdentifierTable.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the IdentifierInfo, IdentifierVisitor, and
100b57cec5SDimitry Andric // IdentifierTable interfaces.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
150b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
16bdd1243dSDimitry Andric #include "clang/Basic/DiagnosticLex.h"
170b57cec5SDimitry Andric #include "clang/Basic/LangOptions.h"
180b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.h"
190b57cec5SDimitry Andric #include "clang/Basic/Specifiers.h"
205ffd83dbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
210b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.h"
220b57cec5SDimitry Andric #include "llvm/ADT/DenseMapInfo.h"
230b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
240b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
250b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
260b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
270b57cec5SDimitry Andric #include "llvm/Support/Allocator.h"
280b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
290b57cec5SDimitry Andric #include <cassert>
300b57cec5SDimitry Andric #include <cstdio>
310b57cec5SDimitry Andric #include <cstring>
320b57cec5SDimitry Andric #include <string>
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric using namespace clang;
350b57cec5SDimitry Andric 
365ffd83dbSDimitry Andric // A check to make sure the ObjCOrBuiltinID has sufficient room to store the
375ffd83dbSDimitry Andric // largest possible target/aux-target combination. If we exceed this, we likely
385ffd83dbSDimitry Andric // need to just change the ObjCOrBuiltinIDBits value in IdentifierTable.h.
39*0fca6ea1SDimitry Andric static_assert(2 * LargestBuiltinID < (2 << (InterestingIdentifierBits - 1)),
405ffd83dbSDimitry Andric               "Insufficient ObjCOrBuiltinID Bits");
415ffd83dbSDimitry Andric 
420b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
430b57cec5SDimitry Andric // IdentifierTable Implementation
440b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric IdentifierIterator::~IdentifierIterator() = default;
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric IdentifierInfoLookup::~IdentifierInfoLookup() = default;
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric namespace {
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric /// A simple identifier lookup iterator that represents an
530b57cec5SDimitry Andric /// empty sequence of identifiers.
545f757f3fSDimitry Andric class EmptyLookupIterator : public IdentifierIterator {
550b57cec5SDimitry Andric public:
560b57cec5SDimitry Andric   StringRef Next() override { return StringRef(); }
570b57cec5SDimitry Andric };
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric } // namespace
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
620b57cec5SDimitry Andric   return new EmptyLookupIterator();
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)
660b57cec5SDimitry Andric     : HashTable(8192), // Start with space for 8K identifiers.
670b57cec5SDimitry Andric       ExternalLookup(ExternalLookup) {}
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
700b57cec5SDimitry Andric                                  IdentifierInfoLookup *ExternalLookup)
710b57cec5SDimitry Andric     : IdentifierTable(ExternalLookup) {
720b57cec5SDimitry Andric   // Populate the identifier table with info about keywords for the current
730b57cec5SDimitry Andric   // language.
740b57cec5SDimitry Andric   AddKeywords(LangOpts);
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
780b57cec5SDimitry Andric // Language Keyword Implementation
790b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric // Constants for TokenKinds.def
820b57cec5SDimitry Andric namespace {
830b57cec5SDimitry Andric 
84bdd1243dSDimitry Andric   enum TokenKey : unsigned {
850b57cec5SDimitry Andric     KEYC99        = 0x1,
860b57cec5SDimitry Andric     KEYCXX        = 0x2,
870b57cec5SDimitry Andric     KEYCXX11      = 0x4,
880b57cec5SDimitry Andric     KEYGNU        = 0x8,
890b57cec5SDimitry Andric     KEYMS         = 0x10,
900b57cec5SDimitry Andric     BOOLSUPPORT   = 0x20,
910b57cec5SDimitry Andric     KEYALTIVEC    = 0x40,
920b57cec5SDimitry Andric     KEYNOCXX      = 0x80,
930b57cec5SDimitry Andric     KEYBORLAND    = 0x100,
940b57cec5SDimitry Andric     KEYOPENCLC    = 0x200,
955f757f3fSDimitry Andric     KEYC23        = 0x400,
960b57cec5SDimitry Andric     KEYNOMS18     = 0x800,
970b57cec5SDimitry Andric     KEYNOOPENCL   = 0x1000,
980b57cec5SDimitry Andric     WCHARSUPPORT  = 0x2000,
990b57cec5SDimitry Andric     HALFSUPPORT   = 0x4000,
1000b57cec5SDimitry Andric     CHAR8SUPPORT  = 0x8000,
101bdd1243dSDimitry Andric     KEYOBJC       = 0x10000,
102bdd1243dSDimitry Andric     KEYZVECTOR    = 0x20000,
103bdd1243dSDimitry Andric     KEYCOROUTINES = 0x40000,
104bdd1243dSDimitry Andric     KEYMODULES    = 0x80000,
105bdd1243dSDimitry Andric     KEYCXX20      = 0x100000,
106bdd1243dSDimitry Andric     KEYOPENCLCXX  = 0x200000,
107bdd1243dSDimitry Andric     KEYMSCOMPAT   = 0x400000,
108bdd1243dSDimitry Andric     KEYSYCL       = 0x800000,
109bdd1243dSDimitry Andric     KEYCUDA       = 0x1000000,
110bdd1243dSDimitry Andric     KEYHLSL       = 0x2000000,
1115f757f3fSDimitry Andric     KEYFIXEDPOINT = 0x4000000,
1125f757f3fSDimitry Andric     KEYMAX        = KEYFIXEDPOINT, // The maximum key
1135ffd83dbSDimitry Andric     KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
11481ad6265SDimitry Andric     KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
11581ad6265SDimitry Andric              ~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
1160b57cec5SDimitry Andric   };
1170b57cec5SDimitry Andric 
118bdd1243dSDimitry Andric   /// How a keyword is treated in the selected standard. This enum is ordered
119bdd1243dSDimitry Andric   /// intentionally so that the value that 'wins' is the most 'permissive'.
1200b57cec5SDimitry Andric   enum KeywordStatus {
121bdd1243dSDimitry Andric     KS_Unknown,     // Not yet calculated. Used when figuring out the status.
1220b57cec5SDimitry Andric     KS_Disabled,    // Disabled
123bdd1243dSDimitry Andric     KS_Future,      // Is a keyword in future standard
1240b57cec5SDimitry Andric     KS_Extension,   // Is an extension
1250b57cec5SDimitry Andric     KS_Enabled,     // Enabled
1260b57cec5SDimitry Andric   };
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric } // namespace
1290b57cec5SDimitry Andric 
130bdd1243dSDimitry Andric // This works on a single TokenKey flag and checks the LangOpts to get the
131bdd1243dSDimitry Andric // KeywordStatus based exclusively on this flag, so that it can be merged in
132bdd1243dSDimitry Andric // getKeywordStatus. Most should be enabled/disabled, but some might imply
133bdd1243dSDimitry Andric // 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to
134bdd1243dSDimitry Andric // be disabled, and the calling function makes it 'disabled' if no other flag
135bdd1243dSDimitry Andric // changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.
136bdd1243dSDimitry Andric static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
137bdd1243dSDimitry Andric                                             TokenKey Flag) {
138bdd1243dSDimitry Andric   // Flag is a single bit version of TokenKey (that is, not
139bdd1243dSDimitry Andric   // KEYALL/KEYALLCXX/etc), so we can check with == throughout this function.
140bdd1243dSDimitry Andric   assert((Flag & ~(Flag - 1)) == Flag && "Multiple bits set?");
141bdd1243dSDimitry Andric 
142bdd1243dSDimitry Andric   switch (Flag) {
143bdd1243dSDimitry Andric   case KEYC99:
144bdd1243dSDimitry Andric     if (LangOpts.C99)
145bdd1243dSDimitry Andric       return KS_Enabled;
146bdd1243dSDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
1475f757f3fSDimitry Andric   case KEYC23:
1485f757f3fSDimitry Andric     if (LangOpts.C23)
149bdd1243dSDimitry Andric       return KS_Enabled;
150bdd1243dSDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151bdd1243dSDimitry Andric   case KEYCXX:
152bdd1243dSDimitry Andric     return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
153bdd1243dSDimitry Andric   case KEYCXX11:
154bdd1243dSDimitry Andric     if (LangOpts.CPlusPlus11)
155bdd1243dSDimitry Andric       return KS_Enabled;
156bdd1243dSDimitry Andric     return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
157bdd1243dSDimitry Andric   case KEYCXX20:
158bdd1243dSDimitry Andric     if (LangOpts.CPlusPlus20)
159bdd1243dSDimitry Andric       return KS_Enabled;
160bdd1243dSDimitry Andric     return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
161bdd1243dSDimitry Andric   case KEYGNU:
162bdd1243dSDimitry Andric     return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
163bdd1243dSDimitry Andric   case KEYMS:
164bdd1243dSDimitry Andric     return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
165bdd1243dSDimitry Andric   case BOOLSUPPORT:
166bdd1243dSDimitry Andric     if (LangOpts.Bool)      return KS_Enabled;
167bdd1243dSDimitry Andric     return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
168bdd1243dSDimitry Andric   case KEYALTIVEC:
169bdd1243dSDimitry Andric     return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
170bdd1243dSDimitry Andric   case KEYBORLAND:
171bdd1243dSDimitry Andric     return LangOpts.Borland ? KS_Extension : KS_Unknown;
172bdd1243dSDimitry Andric   case KEYOPENCLC:
173bdd1243dSDimitry Andric     return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
174bdd1243dSDimitry Andric                                                         : KS_Unknown;
175bdd1243dSDimitry Andric   case WCHARSUPPORT:
176bdd1243dSDimitry Andric     return LangOpts.WChar ? KS_Enabled : KS_Unknown;
177bdd1243dSDimitry Andric   case HALFSUPPORT:
178bdd1243dSDimitry Andric     return LangOpts.Half ? KS_Enabled : KS_Unknown;
179bdd1243dSDimitry Andric   case CHAR8SUPPORT:
180bdd1243dSDimitry Andric     if (LangOpts.Char8) return KS_Enabled;
181bdd1243dSDimitry Andric     if (LangOpts.CPlusPlus20) return KS_Unknown;
182bdd1243dSDimitry Andric     if (LangOpts.CPlusPlus) return KS_Future;
183bdd1243dSDimitry Andric     return KS_Unknown;
184bdd1243dSDimitry Andric   case KEYOBJC:
185bdd1243dSDimitry Andric     // We treat bridge casts as objective-C keywords so we can warn on them
186bdd1243dSDimitry Andric     // in non-arc mode.
187bdd1243dSDimitry Andric     return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
188bdd1243dSDimitry Andric   case KEYZVECTOR:
189bdd1243dSDimitry Andric     return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
190bdd1243dSDimitry Andric   case KEYCOROUTINES:
191bdd1243dSDimitry Andric     return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
192bdd1243dSDimitry Andric   case KEYMODULES:
19306c3fb27SDimitry Andric     return KS_Unknown;
194bdd1243dSDimitry Andric   case KEYOPENCLCXX:
195bdd1243dSDimitry Andric     return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
196bdd1243dSDimitry Andric   case KEYMSCOMPAT:
197bdd1243dSDimitry Andric     return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
198bdd1243dSDimitry Andric   case KEYSYCL:
199bdd1243dSDimitry Andric     return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
200bdd1243dSDimitry Andric   case KEYCUDA:
201bdd1243dSDimitry Andric     return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
202bdd1243dSDimitry Andric   case KEYHLSL:
203bdd1243dSDimitry Andric     return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
204bdd1243dSDimitry Andric   case KEYNOCXX:
205bdd1243dSDimitry Andric     // This is enabled in all non-C++ modes, but might be enabled for other
206bdd1243dSDimitry Andric     // reasons as well.
207bdd1243dSDimitry Andric     return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
208bdd1243dSDimitry Andric   case KEYNOOPENCL:
209bdd1243dSDimitry Andric     // The disable behavior for this is handled in getKeywordStatus.
210bdd1243dSDimitry Andric     return KS_Unknown;
211bdd1243dSDimitry Andric   case KEYNOMS18:
212bdd1243dSDimitry Andric     // The disable behavior for this is handled in getKeywordStatus.
213bdd1243dSDimitry Andric     return KS_Unknown;
2145f757f3fSDimitry Andric   case KEYFIXEDPOINT:
2155f757f3fSDimitry Andric     return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
216bdd1243dSDimitry Andric   default:
217bdd1243dSDimitry Andric     llvm_unreachable("Unknown KeywordStatus flag");
218bdd1243dSDimitry Andric   }
219bdd1243dSDimitry Andric }
220bdd1243dSDimitry Andric 
2210b57cec5SDimitry Andric /// Translates flags as specified in TokenKinds.def into keyword status
2220b57cec5SDimitry Andric /// in the given language standard.
2230b57cec5SDimitry Andric static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
2240b57cec5SDimitry Andric                                       unsigned Flags) {
225bdd1243dSDimitry Andric   // KEYALL means always enabled, so special case this one.
2260b57cec5SDimitry Andric   if (Flags == KEYALL) return KS_Enabled;
227bdd1243dSDimitry Andric   // These are tests that need to 'always win', as they are special in that they
228bdd1243dSDimitry Andric   // disable based on certain conditions.
229bdd1243dSDimitry Andric   if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;
230bdd1243dSDimitry Andric   if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
231bdd1243dSDimitry Andric       !LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
2320b57cec5SDimitry Andric     return KS_Disabled;
233bdd1243dSDimitry Andric 
234bdd1243dSDimitry Andric   KeywordStatus CurStatus = KS_Unknown;
235bdd1243dSDimitry Andric 
236bdd1243dSDimitry Andric   while (Flags != 0) {
237bdd1243dSDimitry Andric     unsigned CurFlag = Flags & ~(Flags - 1);
238bdd1243dSDimitry Andric     Flags = Flags & ~CurFlag;
239bdd1243dSDimitry Andric     CurStatus = std::max(
240bdd1243dSDimitry Andric         CurStatus,
241bdd1243dSDimitry Andric         getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));
242bdd1243dSDimitry Andric   }
243bdd1243dSDimitry Andric 
244bdd1243dSDimitry Andric   if (CurStatus == KS_Unknown)
245bdd1243dSDimitry Andric     return KS_Disabled;
246bdd1243dSDimitry Andric   return CurStatus;
2470b57cec5SDimitry Andric }
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric /// AddKeyword - This method is used to associate a token ID with specific
2500b57cec5SDimitry Andric /// identifiers because they are language keywords.  This causes the lexer to
2510b57cec5SDimitry Andric /// automatically map matching identifiers to specialized token codes.
2520b57cec5SDimitry Andric static void AddKeyword(StringRef Keyword,
2530b57cec5SDimitry Andric                        tok::TokenKind TokenCode, unsigned Flags,
2540b57cec5SDimitry Andric                        const LangOptions &LangOpts, IdentifierTable &Table) {
2550b57cec5SDimitry Andric   KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   // Don't add this keyword if disabled in this language.
2580b57cec5SDimitry Andric   if (AddResult == KS_Disabled) return;
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   IdentifierInfo &Info =
2610b57cec5SDimitry Andric       Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
2620b57cec5SDimitry Andric   Info.setIsExtensionToken(AddResult == KS_Extension);
2630b57cec5SDimitry Andric   Info.setIsFutureCompatKeyword(AddResult == KS_Future);
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
2670b57cec5SDimitry Andric /// representations.
2680b57cec5SDimitry Andric static void AddCXXOperatorKeyword(StringRef Keyword,
2690b57cec5SDimitry Andric                                   tok::TokenKind TokenCode,
2700b57cec5SDimitry Andric                                   IdentifierTable &Table) {
2710b57cec5SDimitry Andric   IdentifierInfo &Info = Table.get(Keyword, TokenCode);
2720b57cec5SDimitry Andric   Info.setIsCPlusPlusOperatorKeyword();
2730b57cec5SDimitry Andric }
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric /// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
2760b57cec5SDimitry Andric /// or "property".
2770b57cec5SDimitry Andric static void AddObjCKeyword(StringRef Name,
2780b57cec5SDimitry Andric                            tok::ObjCKeywordKind ObjCID,
2790b57cec5SDimitry Andric                            IdentifierTable &Table) {
2800b57cec5SDimitry Andric   Table.get(Name).setObjCKeywordID(ObjCID);
2810b57cec5SDimitry Andric }
2820b57cec5SDimitry Andric 
283*0fca6ea1SDimitry Andric static void AddNotableIdentifier(StringRef Name,
284*0fca6ea1SDimitry Andric                                  tok::NotableIdentifierKind BTID,
28506c3fb27SDimitry Andric                                  IdentifierTable &Table) {
286*0fca6ea1SDimitry Andric   // Don't add 'not_notable' identifier.
287*0fca6ea1SDimitry Andric   if (BTID != tok::not_notable) {
28806c3fb27SDimitry Andric     IdentifierInfo &Info = Table.get(Name, tok::identifier);
289*0fca6ea1SDimitry Andric     Info.setNotableIdentifierID(BTID);
29006c3fb27SDimitry Andric   }
29106c3fb27SDimitry Andric }
29206c3fb27SDimitry Andric 
2930b57cec5SDimitry Andric /// AddKeywords - Add all keywords to the symbol table.
2940b57cec5SDimitry Andric ///
2950b57cec5SDimitry Andric void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
2960b57cec5SDimitry Andric   // Add keywords and tokens for the current language.
2970b57cec5SDimitry Andric #define KEYWORD(NAME, FLAGS) \
2980b57cec5SDimitry Andric   AddKeyword(StringRef(#NAME), tok::kw_ ## NAME,  \
2990b57cec5SDimitry Andric              FLAGS, LangOpts, *this);
3000b57cec5SDimitry Andric #define ALIAS(NAME, TOK, FLAGS) \
3010b57cec5SDimitry Andric   AddKeyword(StringRef(NAME), tok::kw_ ## TOK,  \
3020b57cec5SDimitry Andric              FLAGS, LangOpts, *this);
3030b57cec5SDimitry Andric #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
3040b57cec5SDimitry Andric   if (LangOpts.CXXOperatorNames)          \
3050b57cec5SDimitry Andric     AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
3060b57cec5SDimitry Andric #define OBJC_AT_KEYWORD(NAME)  \
3070b57cec5SDimitry Andric   if (LangOpts.ObjC)           \
3080b57cec5SDimitry Andric     AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
309*0fca6ea1SDimitry Andric #define NOTABLE_IDENTIFIER(NAME)                                               \
310*0fca6ea1SDimitry Andric   AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
31106c3fb27SDimitry Andric 
3120b57cec5SDimitry Andric #define TESTING_KEYWORD(NAME, FLAGS)
3130b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric   if (LangOpts.ParseUnknownAnytype)
3160b57cec5SDimitry Andric     AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
3170b57cec5SDimitry Andric                LangOpts, *this);
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric   if (LangOpts.DeclSpecKeyword)
3200b57cec5SDimitry Andric     AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
3210b57cec5SDimitry Andric 
322fe6060f1SDimitry Andric   if (LangOpts.IEEE128)
323fe6060f1SDimitry Andric     AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
324fe6060f1SDimitry Andric 
3250b57cec5SDimitry Andric   // Add the 'import' contextual keyword.
3260b57cec5SDimitry Andric   get("import").setModulesImport(true);
3270b57cec5SDimitry Andric }
3280b57cec5SDimitry Andric 
3290b57cec5SDimitry Andric /// Checks if the specified token kind represents a keyword in the
3300b57cec5SDimitry Andric /// specified language.
3310b57cec5SDimitry Andric /// \returns Status of the keyword in the language.
3320b57cec5SDimitry Andric static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
3330b57cec5SDimitry Andric                                       tok::TokenKind K) {
3340b57cec5SDimitry Andric   switch (K) {
3350b57cec5SDimitry Andric #define KEYWORD(NAME, FLAGS) \
3360b57cec5SDimitry Andric   case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
3370b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
3380b57cec5SDimitry Andric   default: return KS_Disabled;
3390b57cec5SDimitry Andric   }
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric /// Returns true if the identifier represents a keyword in the
3430b57cec5SDimitry Andric /// specified language.
3440b57cec5SDimitry Andric bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
3450b57cec5SDimitry Andric   switch (getTokenKwStatus(LangOpts, getTokenID())) {
3460b57cec5SDimitry Andric   case KS_Enabled:
3470b57cec5SDimitry Andric   case KS_Extension:
3480b57cec5SDimitry Andric     return true;
3490b57cec5SDimitry Andric   default:
3500b57cec5SDimitry Andric     return false;
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric }
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric /// Returns true if the identifier represents a C++ keyword in the
3550b57cec5SDimitry Andric /// specified language.
3560b57cec5SDimitry Andric bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
3570b57cec5SDimitry Andric   if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
3580b57cec5SDimitry Andric     return false;
3590b57cec5SDimitry Andric   // This is a C++ keyword if this identifier is not a keyword when checked
3600b57cec5SDimitry Andric   // using LangOptions without C++ support.
3610b57cec5SDimitry Andric   LangOptions LangOptsNoCPP = LangOpts;
3620b57cec5SDimitry Andric   LangOptsNoCPP.CPlusPlus = false;
3630b57cec5SDimitry Andric   LangOptsNoCPP.CPlusPlus11 = false;
3645ffd83dbSDimitry Andric   LangOptsNoCPP.CPlusPlus20 = false;
3650b57cec5SDimitry Andric   return !isKeyword(LangOptsNoCPP);
3660b57cec5SDimitry Andric }
3670b57cec5SDimitry Andric 
368fe6060f1SDimitry Andric ReservedIdentifierStatus
369fe6060f1SDimitry Andric IdentifierInfo::isReserved(const LangOptions &LangOpts) const {
370fe6060f1SDimitry Andric   StringRef Name = getName();
371fe6060f1SDimitry Andric 
372fe6060f1SDimitry Andric   // '_' is a reserved identifier, but its use is so common (e.g. to store
373fe6060f1SDimitry Andric   // ignored values) that we don't warn on it.
374fe6060f1SDimitry Andric   if (Name.size() <= 1)
375fe6060f1SDimitry Andric     return ReservedIdentifierStatus::NotReserved;
376fe6060f1SDimitry Andric 
377fe6060f1SDimitry Andric   // [lex.name] p3
378fe6060f1SDimitry Andric   if (Name[0] == '_') {
379fe6060f1SDimitry Andric 
380fe6060f1SDimitry Andric     // Each name that begins with an underscore followed by an uppercase letter
381fe6060f1SDimitry Andric     // or another underscore is reserved.
382fe6060f1SDimitry Andric     if (Name[1] == '_')
383fe6060f1SDimitry Andric       return ReservedIdentifierStatus::StartsWithDoubleUnderscore;
384fe6060f1SDimitry Andric 
385fe6060f1SDimitry Andric     if ('A' <= Name[1] && Name[1] <= 'Z')
386fe6060f1SDimitry Andric       return ReservedIdentifierStatus::
387fe6060f1SDimitry Andric           StartsWithUnderscoreFollowedByCapitalLetter;
388fe6060f1SDimitry Andric 
389fe6060f1SDimitry Andric     // This is a bit misleading: it actually means it's only reserved if we're
390fe6060f1SDimitry Andric     // at global scope because it starts with an underscore.
391fe6060f1SDimitry Andric     return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
392fe6060f1SDimitry Andric   }
393fe6060f1SDimitry Andric 
394fe6060f1SDimitry Andric   // Each name that contains a double underscore (__) is reserved.
395fe6060f1SDimitry Andric   if (LangOpts.CPlusPlus && Name.contains("__"))
396fe6060f1SDimitry Andric     return ReservedIdentifierStatus::ContainsDoubleUnderscore;
397fe6060f1SDimitry Andric 
398fe6060f1SDimitry Andric   return ReservedIdentifierStatus::NotReserved;
399fe6060f1SDimitry Andric }
400fe6060f1SDimitry Andric 
40106c3fb27SDimitry Andric ReservedLiteralSuffixIdStatus
40206c3fb27SDimitry Andric IdentifierInfo::isReservedLiteralSuffixId() const {
40306c3fb27SDimitry Andric   StringRef Name = getName();
40406c3fb27SDimitry Andric 
40506c3fb27SDimitry Andric   if (Name[0] != '_')
40606c3fb27SDimitry Andric     return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;
40706c3fb27SDimitry Andric 
40806c3fb27SDimitry Andric   if (Name.contains("__"))
40906c3fb27SDimitry Andric     return ReservedLiteralSuffixIdStatus::ContainsDoubleUnderscore;
41006c3fb27SDimitry Andric 
41106c3fb27SDimitry Andric   return ReservedLiteralSuffixIdStatus::NotReserved;
41206c3fb27SDimitry Andric }
41306c3fb27SDimitry Andric 
41404eeddc0SDimitry Andric StringRef IdentifierInfo::deuglifiedName() const {
41504eeddc0SDimitry Andric   StringRef Name = getName();
41604eeddc0SDimitry Andric   if (Name.size() >= 2 && Name.front() == '_' &&
41704eeddc0SDimitry Andric       (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
41804eeddc0SDimitry Andric     return Name.ltrim('_');
41904eeddc0SDimitry Andric   return Name;
42004eeddc0SDimitry Andric }
42104eeddc0SDimitry Andric 
4220b57cec5SDimitry Andric tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
4230b57cec5SDimitry Andric   // We use a perfect hash function here involving the length of the keyword,
4240b57cec5SDimitry Andric   // the first and third character.  For preprocessor ID's there are no
4250b57cec5SDimitry Andric   // collisions (if there were, the switch below would complain about duplicate
4260b57cec5SDimitry Andric   // case values).  Note that this depends on 'if' being null terminated.
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric #define HASH(LEN, FIRST, THIRD)                                                \
429*0fca6ea1SDimitry Andric   (LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
4300b57cec5SDimitry Andric #define CASE(LEN, FIRST, THIRD, NAME) \
4310b57cec5SDimitry Andric   case HASH(LEN, FIRST, THIRD): \
4320b57cec5SDimitry Andric     return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   unsigned Len = getLength();
4350b57cec5SDimitry Andric   if (Len < 2) return tok::pp_not_keyword;
4360b57cec5SDimitry Andric   const char *Name = getNameStart();
4370b57cec5SDimitry Andric   switch (HASH(Len, Name[0], Name[2])) {
4380b57cec5SDimitry Andric   default: return tok::pp_not_keyword;
4390b57cec5SDimitry Andric   CASE( 2, 'i', '\0', if);
4400b57cec5SDimitry Andric   CASE( 4, 'e', 'i', elif);
4410b57cec5SDimitry Andric   CASE( 4, 'e', 's', else);
4420b57cec5SDimitry Andric   CASE( 4, 'l', 'n', line);
4430b57cec5SDimitry Andric   CASE( 4, 's', 'c', sccs);
444*0fca6ea1SDimitry Andric   CASE( 5, 'e', 'b', embed);
4450b57cec5SDimitry Andric   CASE( 5, 'e', 'd', endif);
4460b57cec5SDimitry Andric   CASE( 5, 'e', 'r', error);
4470b57cec5SDimitry Andric   CASE( 5, 'i', 'e', ident);
4480b57cec5SDimitry Andric   CASE( 5, 'i', 'd', ifdef);
4490b57cec5SDimitry Andric   CASE( 5, 'u', 'd', undef);
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   CASE( 6, 'a', 's', assert);
4520b57cec5SDimitry Andric   CASE( 6, 'd', 'f', define);
4530b57cec5SDimitry Andric   CASE( 6, 'i', 'n', ifndef);
4540b57cec5SDimitry Andric   CASE( 6, 'i', 'p', import);
4550b57cec5SDimitry Andric   CASE( 6, 'p', 'a', pragma);
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   CASE( 7, 'd', 'f', defined);
458fe6060f1SDimitry Andric   CASE( 7, 'e', 'i', elifdef);
4590b57cec5SDimitry Andric   CASE( 7, 'i', 'c', include);
4600b57cec5SDimitry Andric   CASE( 7, 'w', 'r', warning);
4610b57cec5SDimitry Andric 
462fe6060f1SDimitry Andric   CASE( 8, 'e', 'i', elifndef);
4630b57cec5SDimitry Andric   CASE( 8, 'u', 'a', unassert);
4640b57cec5SDimitry Andric   CASE(12, 'i', 'c', include_next);
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   CASE(14, '_', 'p', __public_macro);
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   CASE(15, '_', 'p', __private_macro);
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   CASE(16, '_', 'i', __include_macros);
4710b57cec5SDimitry Andric #undef CASE
4720b57cec5SDimitry Andric #undef HASH
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4770b57cec5SDimitry Andric // Stats Implementation
4780b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric /// PrintStats - Print statistics about how well the identifier table is doing
4810b57cec5SDimitry Andric /// at hashing identifiers.
4820b57cec5SDimitry Andric void IdentifierTable::PrintStats() const {
4830b57cec5SDimitry Andric   unsigned NumBuckets = HashTable.getNumBuckets();
4840b57cec5SDimitry Andric   unsigned NumIdentifiers = HashTable.getNumItems();
4850b57cec5SDimitry Andric   unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
4860b57cec5SDimitry Andric   unsigned AverageIdentifierSize = 0;
4870b57cec5SDimitry Andric   unsigned MaxIdentifierLength = 0;
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   // TODO: Figure out maximum times an identifier had to probe for -stats.
4900b57cec5SDimitry Andric   for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
4910b57cec5SDimitry Andric        I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
4920b57cec5SDimitry Andric     unsigned IdLen = I->getKeyLength();
4930b57cec5SDimitry Andric     AverageIdentifierSize += IdLen;
4940b57cec5SDimitry Andric     if (MaxIdentifierLength < IdLen)
4950b57cec5SDimitry Andric       MaxIdentifierLength = IdLen;
4960b57cec5SDimitry Andric   }
4970b57cec5SDimitry Andric 
4980b57cec5SDimitry Andric   fprintf(stderr, "\n*** Identifier Table Stats:\n");
4990b57cec5SDimitry Andric   fprintf(stderr, "# Identifiers:   %d\n", NumIdentifiers);
5000b57cec5SDimitry Andric   fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
5010b57cec5SDimitry Andric   fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
5020b57cec5SDimitry Andric           NumIdentifiers/(double)NumBuckets);
5030b57cec5SDimitry Andric   fprintf(stderr, "Ave identifier length: %f\n",
5040b57cec5SDimitry Andric           (AverageIdentifierSize/(double)NumIdentifiers));
5050b57cec5SDimitry Andric   fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   // Compute statistics about the memory allocated for identifiers.
5080b57cec5SDimitry Andric   HashTable.getAllocator().PrintStats();
5090b57cec5SDimitry Andric }
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5120b57cec5SDimitry Andric // SelectorTable Implementation
5130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
5160b57cec5SDimitry Andric   return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
519a7dea167SDimitry Andric bool Selector::isKeywordSelector(ArrayRef<StringRef> Names) const {
520a7dea167SDimitry Andric   assert(!Names.empty() && "must have >= 1 selector slots");
521a7dea167SDimitry Andric   if (getNumArgs() != Names.size())
522a7dea167SDimitry Andric     return false;
523a7dea167SDimitry Andric   for (unsigned I = 0, E = Names.size(); I != E; ++I) {
524a7dea167SDimitry Andric     if (getNameForSlot(I) != Names[I])
525a7dea167SDimitry Andric       return false;
526a7dea167SDimitry Andric   }
527a7dea167SDimitry Andric   return true;
528a7dea167SDimitry Andric }
529a7dea167SDimitry Andric 
530a7dea167SDimitry Andric bool Selector::isUnarySelector(StringRef Name) const {
531a7dea167SDimitry Andric   return isUnarySelector() && getNameForSlot(0) == Name;
532a7dea167SDimitry Andric }
533a7dea167SDimitry Andric 
5340b57cec5SDimitry Andric unsigned Selector::getNumArgs() const {
5350b57cec5SDimitry Andric   unsigned IIF = getIdentifierInfoFlag();
5360b57cec5SDimitry Andric   if (IIF <= ZeroArg)
5370b57cec5SDimitry Andric     return 0;
5380b57cec5SDimitry Andric   if (IIF == OneArg)
5390b57cec5SDimitry Andric     return 1;
5400b57cec5SDimitry Andric   // We point to a MultiKeywordSelector.
5410b57cec5SDimitry Andric   MultiKeywordSelector *SI = getMultiKeywordSelector();
5420b57cec5SDimitry Andric   return SI->getNumArgs();
5430b57cec5SDimitry Andric }
5440b57cec5SDimitry Andric 
545*0fca6ea1SDimitry Andric const IdentifierInfo *
546*0fca6ea1SDimitry Andric Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
5470b57cec5SDimitry Andric   if (getIdentifierInfoFlag() < MultiArg) {
5480b57cec5SDimitry Andric     assert(argIndex == 0 && "illegal keyword index");
5490b57cec5SDimitry Andric     return getAsIdentifierInfo();
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   // We point to a MultiKeywordSelector.
5530b57cec5SDimitry Andric   MultiKeywordSelector *SI = getMultiKeywordSelector();
5540b57cec5SDimitry Andric   return SI->getIdentifierInfoForSlot(argIndex);
5550b57cec5SDimitry Andric }
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric StringRef Selector::getNameForSlot(unsigned int argIndex) const {
558*0fca6ea1SDimitry Andric   const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
5590b57cec5SDimitry Andric   return II ? II->getName() : StringRef();
5600b57cec5SDimitry Andric }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric std::string MultiKeywordSelector::getName() const {
5630b57cec5SDimitry Andric   SmallString<256> Str;
5640b57cec5SDimitry Andric   llvm::raw_svector_ostream OS(Str);
5650b57cec5SDimitry Andric   for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
5660b57cec5SDimitry Andric     if (*I)
5670b57cec5SDimitry Andric       OS << (*I)->getName();
5680b57cec5SDimitry Andric     OS << ':';
5690b57cec5SDimitry Andric   }
5700b57cec5SDimitry Andric 
5715ffd83dbSDimitry Andric   return std::string(OS.str());
5720b57cec5SDimitry Andric }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric std::string Selector::getAsString() const {
5755f757f3fSDimitry Andric   if (isNull())
5760b57cec5SDimitry Andric     return "<null selector>";
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   if (getIdentifierInfoFlag() < MultiArg) {
579*0fca6ea1SDimitry Andric     const IdentifierInfo *II = getAsIdentifierInfo();
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric     if (getNumArgs() == 0) {
5820b57cec5SDimitry Andric       assert(II && "If the number of arguments is 0 then II is guaranteed to "
5830b57cec5SDimitry Andric                    "not be null.");
5845ffd83dbSDimitry Andric       return std::string(II->getName());
5850b57cec5SDimitry Andric     }
5860b57cec5SDimitry Andric 
5870b57cec5SDimitry Andric     if (!II)
5880b57cec5SDimitry Andric       return ":";
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric     return II->getName().str() + ":";
5910b57cec5SDimitry Andric   }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric   // We have a multiple keyword selector.
5940b57cec5SDimitry Andric   return getMultiKeywordSelector()->getName();
5950b57cec5SDimitry Andric }
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric void Selector::print(llvm::raw_ostream &OS) const {
5980b57cec5SDimitry Andric   OS << getAsString();
5990b57cec5SDimitry Andric }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric /// Interpreting the given string using the normal CamelCase
6040b57cec5SDimitry Andric /// conventions, determine whether the given string starts with the
6050b57cec5SDimitry Andric /// given "word", which is assumed to end in a lowercase letter.
6060b57cec5SDimitry Andric static bool startsWithWord(StringRef name, StringRef word) {
6070b57cec5SDimitry Andric   if (name.size() < word.size()) return false;
6080b57cec5SDimitry Andric   return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
6095f757f3fSDimitry Andric           name.starts_with(word));
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
613*0fca6ea1SDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
6140b57cec5SDimitry Andric   if (!first) return OMF_None;
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   StringRef name = first->getName();
6170b57cec5SDimitry Andric   if (sel.isUnarySelector()) {
6180b57cec5SDimitry Andric     if (name == "autorelease") return OMF_autorelease;
6190b57cec5SDimitry Andric     if (name == "dealloc") return OMF_dealloc;
6200b57cec5SDimitry Andric     if (name == "finalize") return OMF_finalize;
6210b57cec5SDimitry Andric     if (name == "release") return OMF_release;
6220b57cec5SDimitry Andric     if (name == "retain") return OMF_retain;
6230b57cec5SDimitry Andric     if (name == "retainCount") return OMF_retainCount;
6240b57cec5SDimitry Andric     if (name == "self") return OMF_self;
6250b57cec5SDimitry Andric     if (name == "initialize") return OMF_initialize;
6260b57cec5SDimitry Andric   }
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric   if (name == "performSelector" || name == "performSelectorInBackground" ||
6290b57cec5SDimitry Andric       name == "performSelectorOnMainThread")
6300b57cec5SDimitry Andric     return OMF_performSelector;
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   // The other method families may begin with a prefix of underscores.
633647cbc5dSDimitry Andric   name = name.ltrim('_');
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   if (name.empty()) return OMF_None;
6360b57cec5SDimitry Andric   switch (name.front()) {
6370b57cec5SDimitry Andric   case 'a':
6380b57cec5SDimitry Andric     if (startsWithWord(name, "alloc")) return OMF_alloc;
6390b57cec5SDimitry Andric     break;
6400b57cec5SDimitry Andric   case 'c':
6410b57cec5SDimitry Andric     if (startsWithWord(name, "copy")) return OMF_copy;
6420b57cec5SDimitry Andric     break;
6430b57cec5SDimitry Andric   case 'i':
6440b57cec5SDimitry Andric     if (startsWithWord(name, "init")) return OMF_init;
6450b57cec5SDimitry Andric     break;
6460b57cec5SDimitry Andric   case 'm':
6470b57cec5SDimitry Andric     if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
6480b57cec5SDimitry Andric     break;
6490b57cec5SDimitry Andric   case 'n':
6500b57cec5SDimitry Andric     if (startsWithWord(name, "new")) return OMF_new;
6510b57cec5SDimitry Andric     break;
6520b57cec5SDimitry Andric   default:
6530b57cec5SDimitry Andric     break;
6540b57cec5SDimitry Andric   }
6550b57cec5SDimitry Andric 
6560b57cec5SDimitry Andric   return OMF_None;
6570b57cec5SDimitry Andric }
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
660*0fca6ea1SDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
6610b57cec5SDimitry Andric   if (!first) return OIT_None;
6620b57cec5SDimitry Andric 
6630b57cec5SDimitry Andric   StringRef name = first->getName();
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   if (name.empty()) return OIT_None;
6660b57cec5SDimitry Andric   switch (name.front()) {
6670b57cec5SDimitry Andric     case 'a':
6680b57cec5SDimitry Andric       if (startsWithWord(name, "array")) return OIT_Array;
6690b57cec5SDimitry Andric       break;
6700b57cec5SDimitry Andric     case 'd':
6710b57cec5SDimitry Andric       if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
6720b57cec5SDimitry Andric       if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
6730b57cec5SDimitry Andric       break;
6740b57cec5SDimitry Andric     case 's':
6750b57cec5SDimitry Andric       if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
6760b57cec5SDimitry Andric       if (startsWithWord(name, "standard")) return OIT_Singleton;
6770b57cec5SDimitry Andric       break;
6780b57cec5SDimitry Andric     case 'i':
6790b57cec5SDimitry Andric       if (startsWithWord(name, "init")) return OIT_Init;
6800b57cec5SDimitry Andric       break;
6810b57cec5SDimitry Andric     default:
6820b57cec5SDimitry Andric       break;
6830b57cec5SDimitry Andric   }
6840b57cec5SDimitry Andric   return OIT_None;
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
688*0fca6ea1SDimitry Andric   const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
6890b57cec5SDimitry Andric   if (!first) return SFF_None;
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   StringRef name = first->getName();
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric   switch (name.front()) {
6940b57cec5SDimitry Andric     case 'a':
6950b57cec5SDimitry Andric       if (name == "appendFormat") return SFF_NSString;
6960b57cec5SDimitry Andric       break;
6970b57cec5SDimitry Andric 
6980b57cec5SDimitry Andric     case 'i':
6990b57cec5SDimitry Andric       if (name == "initWithFormat") return SFF_NSString;
7000b57cec5SDimitry Andric       break;
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric     case 'l':
7030b57cec5SDimitry Andric       if (name == "localizedStringWithFormat") return SFF_NSString;
7040b57cec5SDimitry Andric       break;
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric     case 's':
7070b57cec5SDimitry Andric       if (name == "stringByAppendingFormat" ||
7080b57cec5SDimitry Andric           name == "stringWithFormat") return SFF_NSString;
7090b57cec5SDimitry Andric       break;
7100b57cec5SDimitry Andric   }
7110b57cec5SDimitry Andric   return SFF_None;
7120b57cec5SDimitry Andric }
7130b57cec5SDimitry Andric 
7140b57cec5SDimitry Andric namespace {
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric struct SelectorTableImpl {
7170b57cec5SDimitry Andric   llvm::FoldingSet<MultiKeywordSelector> Table;
7180b57cec5SDimitry Andric   llvm::BumpPtrAllocator Allocator;
7190b57cec5SDimitry Andric };
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric } // namespace
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric static SelectorTableImpl &getSelectorTableImpl(void *P) {
7240b57cec5SDimitry Andric   return *static_cast<SelectorTableImpl*>(P);
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric SmallString<64>
7280b57cec5SDimitry Andric SelectorTable::constructSetterName(StringRef Name) {
7290b57cec5SDimitry Andric   SmallString<64> SetterName("set");
7300b57cec5SDimitry Andric   SetterName += Name;
7310b57cec5SDimitry Andric   SetterName[3] = toUppercase(SetterName[3]);
7320b57cec5SDimitry Andric   return SetterName;
7330b57cec5SDimitry Andric }
7340b57cec5SDimitry Andric 
7350b57cec5SDimitry Andric Selector
7360b57cec5SDimitry Andric SelectorTable::constructSetterSelector(IdentifierTable &Idents,
7370b57cec5SDimitry Andric                                        SelectorTable &SelTable,
7380b57cec5SDimitry Andric                                        const IdentifierInfo *Name) {
7390b57cec5SDimitry Andric   IdentifierInfo *SetterName =
7400b57cec5SDimitry Andric     &Idents.get(constructSetterName(Name->getName()));
7410b57cec5SDimitry Andric   return SelTable.getUnarySelector(SetterName);
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {
7450b57cec5SDimitry Andric   StringRef Name = Sel.getNameForSlot(0);
7465f757f3fSDimitry Andric   assert(Name.starts_with("set") && "invalid setter name");
7470b57cec5SDimitry Andric   return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
7480b57cec5SDimitry Andric }
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric size_t SelectorTable::getTotalMemory() const {
7510b57cec5SDimitry Andric   SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
7520b57cec5SDimitry Andric   return SelTabImpl.Allocator.getTotalMemory();
7530b57cec5SDimitry Andric }
7540b57cec5SDimitry Andric 
755*0fca6ea1SDimitry Andric Selector SelectorTable::getSelector(unsigned nKeys,
756*0fca6ea1SDimitry Andric                                     const IdentifierInfo **IIV) {
7570b57cec5SDimitry Andric   if (nKeys < 2)
7580b57cec5SDimitry Andric     return Selector(IIV[0], nKeys);
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric   SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // Unique selector, to guarantee there is one per name.
7630b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
7640b57cec5SDimitry Andric   MultiKeywordSelector::Profile(ID, IIV, nKeys);
7650b57cec5SDimitry Andric 
7660b57cec5SDimitry Andric   void *InsertPos = nullptr;
7670b57cec5SDimitry Andric   if (MultiKeywordSelector *SI =
7680b57cec5SDimitry Andric         SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
7690b57cec5SDimitry Andric     return Selector(SI);
7700b57cec5SDimitry Andric 
7710b57cec5SDimitry Andric   // MultiKeywordSelector objects are not allocated with new because they have a
7720b57cec5SDimitry Andric   // variable size array (for parameter types) at the end of them.
7730b57cec5SDimitry Andric   unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
7740b57cec5SDimitry Andric   MultiKeywordSelector *SI =
7750b57cec5SDimitry Andric       (MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
7760b57cec5SDimitry Andric           Size, alignof(MultiKeywordSelector));
7770b57cec5SDimitry Andric   new (SI) MultiKeywordSelector(nKeys, IIV);
7780b57cec5SDimitry Andric   SelTabImpl.Table.InsertNode(SI, InsertPos);
7790b57cec5SDimitry Andric   return Selector(SI);
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric SelectorTable::SelectorTable() {
7830b57cec5SDimitry Andric   Impl = new SelectorTableImpl();
7840b57cec5SDimitry Andric }
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric SelectorTable::~SelectorTable() {
7870b57cec5SDimitry Andric   delete &getSelectorTableImpl(Impl);
7880b57cec5SDimitry Andric }
7890b57cec5SDimitry Andric 
7900b57cec5SDimitry Andric const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
7910b57cec5SDimitry Andric   switch (Operator) {
7920b57cec5SDimitry Andric   case OO_None:
7930b57cec5SDimitry Andric   case NUM_OVERLOADED_OPERATORS:
7940b57cec5SDimitry Andric     return nullptr;
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric #define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
7970b57cec5SDimitry Andric   case OO_##Name: return Spelling;
7980b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.def"
7990b57cec5SDimitry Andric   }
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric   llvm_unreachable("Invalid OverloadedOperatorKind!");
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric StringRef clang::getNullabilitySpelling(NullabilityKind kind,
8050b57cec5SDimitry Andric                                         bool isContextSensitive) {
8060b57cec5SDimitry Andric   switch (kind) {
8070b57cec5SDimitry Andric   case NullabilityKind::NonNull:
8080b57cec5SDimitry Andric     return isContextSensitive ? "nonnull" : "_Nonnull";
8090b57cec5SDimitry Andric 
8100b57cec5SDimitry Andric   case NullabilityKind::Nullable:
8110b57cec5SDimitry Andric     return isContextSensitive ? "nullable" : "_Nullable";
8120b57cec5SDimitry Andric 
813e8d8bef9SDimitry Andric   case NullabilityKind::NullableResult:
814e8d8bef9SDimitry Andric     assert(!isContextSensitive &&
815e8d8bef9SDimitry Andric            "_Nullable_result isn't supported as context-sensitive keyword");
816e8d8bef9SDimitry Andric     return "_Nullable_result";
817e8d8bef9SDimitry Andric 
8180b57cec5SDimitry Andric   case NullabilityKind::Unspecified:
8190b57cec5SDimitry Andric     return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
8200b57cec5SDimitry Andric   }
8210b57cec5SDimitry Andric   llvm_unreachable("Unknown nullability kind.");
8220b57cec5SDimitry Andric }
823bdd1243dSDimitry Andric 
82406c3fb27SDimitry Andric llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
82506c3fb27SDimitry Andric                                      NullabilityKind NK) {
82606c3fb27SDimitry Andric   switch (NK) {
82706c3fb27SDimitry Andric   case NullabilityKind::NonNull:
82806c3fb27SDimitry Andric     return OS << "NonNull";
82906c3fb27SDimitry Andric   case NullabilityKind::Nullable:
83006c3fb27SDimitry Andric     return OS << "Nullable";
83106c3fb27SDimitry Andric   case NullabilityKind::NullableResult:
83206c3fb27SDimitry Andric     return OS << "NullableResult";
83306c3fb27SDimitry Andric   case NullabilityKind::Unspecified:
83406c3fb27SDimitry Andric     return OS << "Unspecified";
83506c3fb27SDimitry Andric   }
83606c3fb27SDimitry Andric   llvm_unreachable("Unknown nullability kind.");
83706c3fb27SDimitry Andric }
83806c3fb27SDimitry Andric 
839bdd1243dSDimitry Andric diag::kind
840bdd1243dSDimitry Andric IdentifierTable::getFutureCompatDiagKind(const IdentifierInfo &II,
841bdd1243dSDimitry Andric                                          const LangOptions &LangOpts) {
842bdd1243dSDimitry Andric   assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
843bdd1243dSDimitry Andric 
844bdd1243dSDimitry Andric   unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
845bdd1243dSDimitry Andric #define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
846bdd1243dSDimitry Andric #include "clang/Basic/TokenKinds.def"
847bdd1243dSDimitry Andric #undef KEYWORD
848bdd1243dSDimitry Andric       ;
849bdd1243dSDimitry Andric 
850bdd1243dSDimitry Andric   if (LangOpts.CPlusPlus) {
851bdd1243dSDimitry Andric     if ((Flags & KEYCXX11) == KEYCXX11)
852bdd1243dSDimitry Andric       return diag::warn_cxx11_keyword;
853bdd1243dSDimitry Andric 
854bdd1243dSDimitry Andric     // char8_t is not modeled as a CXX20_KEYWORD because it's not
855bdd1243dSDimitry Andric     // unconditionally enabled in C++20 mode. (It can be disabled
856bdd1243dSDimitry Andric     // by -fno-char8_t.)
857bdd1243dSDimitry Andric     if (((Flags & KEYCXX20) == KEYCXX20) ||
858bdd1243dSDimitry Andric         ((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
859bdd1243dSDimitry Andric       return diag::warn_cxx20_keyword;
860bdd1243dSDimitry Andric   } else {
861bdd1243dSDimitry Andric     if ((Flags & KEYC99) == KEYC99)
862bdd1243dSDimitry Andric       return diag::warn_c99_keyword;
8635f757f3fSDimitry Andric     if ((Flags & KEYC23) == KEYC23)
8645f757f3fSDimitry Andric       return diag::warn_c23_keyword;
865bdd1243dSDimitry Andric   }
866bdd1243dSDimitry Andric 
867bdd1243dSDimitry Andric   llvm_unreachable(
868bdd1243dSDimitry Andric       "Keyword not known to come from a newer Standard or proposed Standard");
869bdd1243dSDimitry Andric }
870