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