Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/Basic/IdentifierTable.cpp
35232 views
1
//===- IdentifierTable.cpp - Hash table for identifier lookup -------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file implements the IdentifierInfo, IdentifierVisitor, and
10
// IdentifierTable interfaces.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "clang/Basic/IdentifierTable.h"
15
#include "clang/Basic/CharInfo.h"
16
#include "clang/Basic/DiagnosticLex.h"
17
#include "clang/Basic/LangOptions.h"
18
#include "clang/Basic/OperatorKinds.h"
19
#include "clang/Basic/Specifiers.h"
20
#include "clang/Basic/TargetBuiltins.h"
21
#include "clang/Basic/TokenKinds.h"
22
#include "llvm/ADT/DenseMapInfo.h"
23
#include "llvm/ADT/FoldingSet.h"
24
#include "llvm/ADT/SmallString.h"
25
#include "llvm/ADT/StringMap.h"
26
#include "llvm/ADT/StringRef.h"
27
#include "llvm/Support/Allocator.h"
28
#include "llvm/Support/raw_ostream.h"
29
#include <cassert>
30
#include <cstdio>
31
#include <cstring>
32
#include <string>
33
34
using namespace clang;
35
36
// A check to make sure the ObjCOrBuiltinID has sufficient room to store the
37
// largest possible target/aux-target combination. If we exceed this, we likely
38
// need to just change the ObjCOrBuiltinIDBits value in IdentifierTable.h.
39
static_assert(2 * LargestBuiltinID < (2 << (InterestingIdentifierBits - 1)),
40
"Insufficient ObjCOrBuiltinID Bits");
41
42
//===----------------------------------------------------------------------===//
43
// IdentifierTable Implementation
44
//===----------------------------------------------------------------------===//
45
46
IdentifierIterator::~IdentifierIterator() = default;
47
48
IdentifierInfoLookup::~IdentifierInfoLookup() = default;
49
50
namespace {
51
52
/// A simple identifier lookup iterator that represents an
53
/// empty sequence of identifiers.
54
class EmptyLookupIterator : public IdentifierIterator {
55
public:
56
StringRef Next() override { return StringRef(); }
57
};
58
59
} // namespace
60
61
IdentifierIterator *IdentifierInfoLookup::getIdentifiers() {
62
return new EmptyLookupIterator();
63
}
64
65
IdentifierTable::IdentifierTable(IdentifierInfoLookup *ExternalLookup)
66
: HashTable(8192), // Start with space for 8K identifiers.
67
ExternalLookup(ExternalLookup) {}
68
69
IdentifierTable::IdentifierTable(const LangOptions &LangOpts,
70
IdentifierInfoLookup *ExternalLookup)
71
: IdentifierTable(ExternalLookup) {
72
// Populate the identifier table with info about keywords for the current
73
// language.
74
AddKeywords(LangOpts);
75
}
76
77
//===----------------------------------------------------------------------===//
78
// Language Keyword Implementation
79
//===----------------------------------------------------------------------===//
80
81
// Constants for TokenKinds.def
82
namespace {
83
84
enum TokenKey : unsigned {
85
KEYC99 = 0x1,
86
KEYCXX = 0x2,
87
KEYCXX11 = 0x4,
88
KEYGNU = 0x8,
89
KEYMS = 0x10,
90
BOOLSUPPORT = 0x20,
91
KEYALTIVEC = 0x40,
92
KEYNOCXX = 0x80,
93
KEYBORLAND = 0x100,
94
KEYOPENCLC = 0x200,
95
KEYC23 = 0x400,
96
KEYNOMS18 = 0x800,
97
KEYNOOPENCL = 0x1000,
98
WCHARSUPPORT = 0x2000,
99
HALFSUPPORT = 0x4000,
100
CHAR8SUPPORT = 0x8000,
101
KEYOBJC = 0x10000,
102
KEYZVECTOR = 0x20000,
103
KEYCOROUTINES = 0x40000,
104
KEYMODULES = 0x80000,
105
KEYCXX20 = 0x100000,
106
KEYOPENCLCXX = 0x200000,
107
KEYMSCOMPAT = 0x400000,
108
KEYSYCL = 0x800000,
109
KEYCUDA = 0x1000000,
110
KEYHLSL = 0x2000000,
111
KEYFIXEDPOINT = 0x4000000,
112
KEYMAX = KEYFIXEDPOINT, // The maximum key
113
KEYALLCXX = KEYCXX | KEYCXX11 | KEYCXX20,
114
KEYALL = (KEYMAX | (KEYMAX-1)) & ~KEYNOMS18 &
115
~KEYNOOPENCL // KEYNOMS18 and KEYNOOPENCL are used to exclude.
116
};
117
118
/// How a keyword is treated in the selected standard. This enum is ordered
119
/// intentionally so that the value that 'wins' is the most 'permissive'.
120
enum KeywordStatus {
121
KS_Unknown, // Not yet calculated. Used when figuring out the status.
122
KS_Disabled, // Disabled
123
KS_Future, // Is a keyword in future standard
124
KS_Extension, // Is an extension
125
KS_Enabled, // Enabled
126
};
127
128
} // namespace
129
130
// This works on a single TokenKey flag and checks the LangOpts to get the
131
// KeywordStatus based exclusively on this flag, so that it can be merged in
132
// getKeywordStatus. Most should be enabled/disabled, but some might imply
133
// 'future' versions, or extensions. Returns 'unknown' unless this is KNOWN to
134
// be disabled, and the calling function makes it 'disabled' if no other flag
135
// changes it. This is necessary for the KEYNOCXX and KEYNOOPENCL flags.
136
static KeywordStatus getKeywordStatusHelper(const LangOptions &LangOpts,
137
TokenKey Flag) {
138
// Flag is a single bit version of TokenKey (that is, not
139
// KEYALL/KEYALLCXX/etc), so we can check with == throughout this function.
140
assert((Flag & ~(Flag - 1)) == Flag && "Multiple bits set?");
141
142
switch (Flag) {
143
case KEYC99:
144
if (LangOpts.C99)
145
return KS_Enabled;
146
return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
147
case KEYC23:
148
if (LangOpts.C23)
149
return KS_Enabled;
150
return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
151
case KEYCXX:
152
return LangOpts.CPlusPlus ? KS_Enabled : KS_Unknown;
153
case KEYCXX11:
154
if (LangOpts.CPlusPlus11)
155
return KS_Enabled;
156
return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
157
case KEYCXX20:
158
if (LangOpts.CPlusPlus20)
159
return KS_Enabled;
160
return LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
161
case KEYGNU:
162
return LangOpts.GNUKeywords ? KS_Extension : KS_Unknown;
163
case KEYMS:
164
return LangOpts.MicrosoftExt ? KS_Extension : KS_Unknown;
165
case BOOLSUPPORT:
166
if (LangOpts.Bool) return KS_Enabled;
167
return !LangOpts.CPlusPlus ? KS_Future : KS_Unknown;
168
case KEYALTIVEC:
169
return LangOpts.AltiVec ? KS_Enabled : KS_Unknown;
170
case KEYBORLAND:
171
return LangOpts.Borland ? KS_Extension : KS_Unknown;
172
case KEYOPENCLC:
173
return LangOpts.OpenCL && !LangOpts.OpenCLCPlusPlus ? KS_Enabled
174
: KS_Unknown;
175
case WCHARSUPPORT:
176
return LangOpts.WChar ? KS_Enabled : KS_Unknown;
177
case HALFSUPPORT:
178
return LangOpts.Half ? KS_Enabled : KS_Unknown;
179
case CHAR8SUPPORT:
180
if (LangOpts.Char8) return KS_Enabled;
181
if (LangOpts.CPlusPlus20) return KS_Unknown;
182
if (LangOpts.CPlusPlus) return KS_Future;
183
return KS_Unknown;
184
case KEYOBJC:
185
// We treat bridge casts as objective-C keywords so we can warn on them
186
// in non-arc mode.
187
return LangOpts.ObjC ? KS_Enabled : KS_Unknown;
188
case KEYZVECTOR:
189
return LangOpts.ZVector ? KS_Enabled : KS_Unknown;
190
case KEYCOROUTINES:
191
return LangOpts.Coroutines ? KS_Enabled : KS_Unknown;
192
case KEYMODULES:
193
return KS_Unknown;
194
case KEYOPENCLCXX:
195
return LangOpts.OpenCLCPlusPlus ? KS_Enabled : KS_Unknown;
196
case KEYMSCOMPAT:
197
return LangOpts.MSVCCompat ? KS_Enabled : KS_Unknown;
198
case KEYSYCL:
199
return LangOpts.isSYCL() ? KS_Enabled : KS_Unknown;
200
case KEYCUDA:
201
return LangOpts.CUDA ? KS_Enabled : KS_Unknown;
202
case KEYHLSL:
203
return LangOpts.HLSL ? KS_Enabled : KS_Unknown;
204
case KEYNOCXX:
205
// This is enabled in all non-C++ modes, but might be enabled for other
206
// reasons as well.
207
return LangOpts.CPlusPlus ? KS_Unknown : KS_Enabled;
208
case KEYNOOPENCL:
209
// The disable behavior for this is handled in getKeywordStatus.
210
return KS_Unknown;
211
case KEYNOMS18:
212
// The disable behavior for this is handled in getKeywordStatus.
213
return KS_Unknown;
214
case KEYFIXEDPOINT:
215
return LangOpts.FixedPoint ? KS_Enabled : KS_Disabled;
216
default:
217
llvm_unreachable("Unknown KeywordStatus flag");
218
}
219
}
220
221
/// Translates flags as specified in TokenKinds.def into keyword status
222
/// in the given language standard.
223
static KeywordStatus getKeywordStatus(const LangOptions &LangOpts,
224
unsigned Flags) {
225
// KEYALL means always enabled, so special case this one.
226
if (Flags == KEYALL) return KS_Enabled;
227
// These are tests that need to 'always win', as they are special in that they
228
// disable based on certain conditions.
229
if (LangOpts.OpenCL && (Flags & KEYNOOPENCL)) return KS_Disabled;
230
if (LangOpts.MSVCCompat && (Flags & KEYNOMS18) &&
231
!LangOpts.isCompatibleWithMSVC(LangOptions::MSVC2015))
232
return KS_Disabled;
233
234
KeywordStatus CurStatus = KS_Unknown;
235
236
while (Flags != 0) {
237
unsigned CurFlag = Flags & ~(Flags - 1);
238
Flags = Flags & ~CurFlag;
239
CurStatus = std::max(
240
CurStatus,
241
getKeywordStatusHelper(LangOpts, static_cast<TokenKey>(CurFlag)));
242
}
243
244
if (CurStatus == KS_Unknown)
245
return KS_Disabled;
246
return CurStatus;
247
}
248
249
/// AddKeyword - This method is used to associate a token ID with specific
250
/// identifiers because they are language keywords. This causes the lexer to
251
/// automatically map matching identifiers to specialized token codes.
252
static void AddKeyword(StringRef Keyword,
253
tok::TokenKind TokenCode, unsigned Flags,
254
const LangOptions &LangOpts, IdentifierTable &Table) {
255
KeywordStatus AddResult = getKeywordStatus(LangOpts, Flags);
256
257
// Don't add this keyword if disabled in this language.
258
if (AddResult == KS_Disabled) return;
259
260
IdentifierInfo &Info =
261
Table.get(Keyword, AddResult == KS_Future ? tok::identifier : TokenCode);
262
Info.setIsExtensionToken(AddResult == KS_Extension);
263
Info.setIsFutureCompatKeyword(AddResult == KS_Future);
264
}
265
266
/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
267
/// representations.
268
static void AddCXXOperatorKeyword(StringRef Keyword,
269
tok::TokenKind TokenCode,
270
IdentifierTable &Table) {
271
IdentifierInfo &Info = Table.get(Keyword, TokenCode);
272
Info.setIsCPlusPlusOperatorKeyword();
273
}
274
275
/// AddObjCKeyword - Register an Objective-C \@keyword like "class" "selector"
276
/// or "property".
277
static void AddObjCKeyword(StringRef Name,
278
tok::ObjCKeywordKind ObjCID,
279
IdentifierTable &Table) {
280
Table.get(Name).setObjCKeywordID(ObjCID);
281
}
282
283
static void AddNotableIdentifier(StringRef Name,
284
tok::NotableIdentifierKind BTID,
285
IdentifierTable &Table) {
286
// Don't add 'not_notable' identifier.
287
if (BTID != tok::not_notable) {
288
IdentifierInfo &Info = Table.get(Name, tok::identifier);
289
Info.setNotableIdentifierID(BTID);
290
}
291
}
292
293
/// AddKeywords - Add all keywords to the symbol table.
294
///
295
void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
296
// Add keywords and tokens for the current language.
297
#define KEYWORD(NAME, FLAGS) \
298
AddKeyword(StringRef(#NAME), tok::kw_ ## NAME, \
299
FLAGS, LangOpts, *this);
300
#define ALIAS(NAME, TOK, FLAGS) \
301
AddKeyword(StringRef(NAME), tok::kw_ ## TOK, \
302
FLAGS, LangOpts, *this);
303
#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
304
if (LangOpts.CXXOperatorNames) \
305
AddCXXOperatorKeyword(StringRef(#NAME), tok::ALIAS, *this);
306
#define OBJC_AT_KEYWORD(NAME) \
307
if (LangOpts.ObjC) \
308
AddObjCKeyword(StringRef(#NAME), tok::objc_##NAME, *this);
309
#define NOTABLE_IDENTIFIER(NAME) \
310
AddNotableIdentifier(StringRef(#NAME), tok::NAME, *this);
311
312
#define TESTING_KEYWORD(NAME, FLAGS)
313
#include "clang/Basic/TokenKinds.def"
314
315
if (LangOpts.ParseUnknownAnytype)
316
AddKeyword("__unknown_anytype", tok::kw___unknown_anytype, KEYALL,
317
LangOpts, *this);
318
319
if (LangOpts.DeclSpecKeyword)
320
AddKeyword("__declspec", tok::kw___declspec, KEYALL, LangOpts, *this);
321
322
if (LangOpts.IEEE128)
323
AddKeyword("__ieee128", tok::kw___float128, KEYALL, LangOpts, *this);
324
325
// Add the 'import' contextual keyword.
326
get("import").setModulesImport(true);
327
}
328
329
/// Checks if the specified token kind represents a keyword in the
330
/// specified language.
331
/// \returns Status of the keyword in the language.
332
static KeywordStatus getTokenKwStatus(const LangOptions &LangOpts,
333
tok::TokenKind K) {
334
switch (K) {
335
#define KEYWORD(NAME, FLAGS) \
336
case tok::kw_##NAME: return getKeywordStatus(LangOpts, FLAGS);
337
#include "clang/Basic/TokenKinds.def"
338
default: return KS_Disabled;
339
}
340
}
341
342
/// Returns true if the identifier represents a keyword in the
343
/// specified language.
344
bool IdentifierInfo::isKeyword(const LangOptions &LangOpts) const {
345
switch (getTokenKwStatus(LangOpts, getTokenID())) {
346
case KS_Enabled:
347
case KS_Extension:
348
return true;
349
default:
350
return false;
351
}
352
}
353
354
/// Returns true if the identifier represents a C++ keyword in the
355
/// specified language.
356
bool IdentifierInfo::isCPlusPlusKeyword(const LangOptions &LangOpts) const {
357
if (!LangOpts.CPlusPlus || !isKeyword(LangOpts))
358
return false;
359
// This is a C++ keyword if this identifier is not a keyword when checked
360
// using LangOptions without C++ support.
361
LangOptions LangOptsNoCPP = LangOpts;
362
LangOptsNoCPP.CPlusPlus = false;
363
LangOptsNoCPP.CPlusPlus11 = false;
364
LangOptsNoCPP.CPlusPlus20 = false;
365
return !isKeyword(LangOptsNoCPP);
366
}
367
368
ReservedIdentifierStatus
369
IdentifierInfo::isReserved(const LangOptions &LangOpts) const {
370
StringRef Name = getName();
371
372
// '_' is a reserved identifier, but its use is so common (e.g. to store
373
// ignored values) that we don't warn on it.
374
if (Name.size() <= 1)
375
return ReservedIdentifierStatus::NotReserved;
376
377
// [lex.name] p3
378
if (Name[0] == '_') {
379
380
// Each name that begins with an underscore followed by an uppercase letter
381
// or another underscore is reserved.
382
if (Name[1] == '_')
383
return ReservedIdentifierStatus::StartsWithDoubleUnderscore;
384
385
if ('A' <= Name[1] && Name[1] <= 'Z')
386
return ReservedIdentifierStatus::
387
StartsWithUnderscoreFollowedByCapitalLetter;
388
389
// This is a bit misleading: it actually means it's only reserved if we're
390
// at global scope because it starts with an underscore.
391
return ReservedIdentifierStatus::StartsWithUnderscoreAtGlobalScope;
392
}
393
394
// Each name that contains a double underscore (__) is reserved.
395
if (LangOpts.CPlusPlus && Name.contains("__"))
396
return ReservedIdentifierStatus::ContainsDoubleUnderscore;
397
398
return ReservedIdentifierStatus::NotReserved;
399
}
400
401
ReservedLiteralSuffixIdStatus
402
IdentifierInfo::isReservedLiteralSuffixId() const {
403
StringRef Name = getName();
404
405
if (Name[0] != '_')
406
return ReservedLiteralSuffixIdStatus::NotStartsWithUnderscore;
407
408
if (Name.contains("__"))
409
return ReservedLiteralSuffixIdStatus::ContainsDoubleUnderscore;
410
411
return ReservedLiteralSuffixIdStatus::NotReserved;
412
}
413
414
StringRef IdentifierInfo::deuglifiedName() const {
415
StringRef Name = getName();
416
if (Name.size() >= 2 && Name.front() == '_' &&
417
(Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')))
418
return Name.ltrim('_');
419
return Name;
420
}
421
422
tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
423
// We use a perfect hash function here involving the length of the keyword,
424
// the first and third character. For preprocessor ID's there are no
425
// collisions (if there were, the switch below would complain about duplicate
426
// case values). Note that this depends on 'if' being null terminated.
427
428
#define HASH(LEN, FIRST, THIRD) \
429
(LEN << 6) + (((FIRST - 'a') - (THIRD - 'a')) & 63)
430
#define CASE(LEN, FIRST, THIRD, NAME) \
431
case HASH(LEN, FIRST, THIRD): \
432
return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
433
434
unsigned Len = getLength();
435
if (Len < 2) return tok::pp_not_keyword;
436
const char *Name = getNameStart();
437
switch (HASH(Len, Name[0], Name[2])) {
438
default: return tok::pp_not_keyword;
439
CASE( 2, 'i', '\0', if);
440
CASE( 4, 'e', 'i', elif);
441
CASE( 4, 'e', 's', else);
442
CASE( 4, 'l', 'n', line);
443
CASE( 4, 's', 'c', sccs);
444
CASE( 5, 'e', 'b', embed);
445
CASE( 5, 'e', 'd', endif);
446
CASE( 5, 'e', 'r', error);
447
CASE( 5, 'i', 'e', ident);
448
CASE( 5, 'i', 'd', ifdef);
449
CASE( 5, 'u', 'd', undef);
450
451
CASE( 6, 'a', 's', assert);
452
CASE( 6, 'd', 'f', define);
453
CASE( 6, 'i', 'n', ifndef);
454
CASE( 6, 'i', 'p', import);
455
CASE( 6, 'p', 'a', pragma);
456
457
CASE( 7, 'd', 'f', defined);
458
CASE( 7, 'e', 'i', elifdef);
459
CASE( 7, 'i', 'c', include);
460
CASE( 7, 'w', 'r', warning);
461
462
CASE( 8, 'e', 'i', elifndef);
463
CASE( 8, 'u', 'a', unassert);
464
CASE(12, 'i', 'c', include_next);
465
466
CASE(14, '_', 'p', __public_macro);
467
468
CASE(15, '_', 'p', __private_macro);
469
470
CASE(16, '_', 'i', __include_macros);
471
#undef CASE
472
#undef HASH
473
}
474
}
475
476
//===----------------------------------------------------------------------===//
477
// Stats Implementation
478
//===----------------------------------------------------------------------===//
479
480
/// PrintStats - Print statistics about how well the identifier table is doing
481
/// at hashing identifiers.
482
void IdentifierTable::PrintStats() const {
483
unsigned NumBuckets = HashTable.getNumBuckets();
484
unsigned NumIdentifiers = HashTable.getNumItems();
485
unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
486
unsigned AverageIdentifierSize = 0;
487
unsigned MaxIdentifierLength = 0;
488
489
// TODO: Figure out maximum times an identifier had to probe for -stats.
490
for (llvm::StringMap<IdentifierInfo*, llvm::BumpPtrAllocator>::const_iterator
491
I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
492
unsigned IdLen = I->getKeyLength();
493
AverageIdentifierSize += IdLen;
494
if (MaxIdentifierLength < IdLen)
495
MaxIdentifierLength = IdLen;
496
}
497
498
fprintf(stderr, "\n*** Identifier Table Stats:\n");
499
fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
500
fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
501
fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
502
NumIdentifiers/(double)NumBuckets);
503
fprintf(stderr, "Ave identifier length: %f\n",
504
(AverageIdentifierSize/(double)NumIdentifiers));
505
fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
506
507
// Compute statistics about the memory allocated for identifiers.
508
HashTable.getAllocator().PrintStats();
509
}
510
511
//===----------------------------------------------------------------------===//
512
// SelectorTable Implementation
513
//===----------------------------------------------------------------------===//
514
515
unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
516
return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
517
}
518
519
bool Selector::isKeywordSelector(ArrayRef<StringRef> Names) const {
520
assert(!Names.empty() && "must have >= 1 selector slots");
521
if (getNumArgs() != Names.size())
522
return false;
523
for (unsigned I = 0, E = Names.size(); I != E; ++I) {
524
if (getNameForSlot(I) != Names[I])
525
return false;
526
}
527
return true;
528
}
529
530
bool Selector::isUnarySelector(StringRef Name) const {
531
return isUnarySelector() && getNameForSlot(0) == Name;
532
}
533
534
unsigned Selector::getNumArgs() const {
535
unsigned IIF = getIdentifierInfoFlag();
536
if (IIF <= ZeroArg)
537
return 0;
538
if (IIF == OneArg)
539
return 1;
540
// We point to a MultiKeywordSelector.
541
MultiKeywordSelector *SI = getMultiKeywordSelector();
542
return SI->getNumArgs();
543
}
544
545
const IdentifierInfo *
546
Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
547
if (getIdentifierInfoFlag() < MultiArg) {
548
assert(argIndex == 0 && "illegal keyword index");
549
return getAsIdentifierInfo();
550
}
551
552
// We point to a MultiKeywordSelector.
553
MultiKeywordSelector *SI = getMultiKeywordSelector();
554
return SI->getIdentifierInfoForSlot(argIndex);
555
}
556
557
StringRef Selector::getNameForSlot(unsigned int argIndex) const {
558
const IdentifierInfo *II = getIdentifierInfoForSlot(argIndex);
559
return II ? II->getName() : StringRef();
560
}
561
562
std::string MultiKeywordSelector::getName() const {
563
SmallString<256> Str;
564
llvm::raw_svector_ostream OS(Str);
565
for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
566
if (*I)
567
OS << (*I)->getName();
568
OS << ':';
569
}
570
571
return std::string(OS.str());
572
}
573
574
std::string Selector::getAsString() const {
575
if (isNull())
576
return "<null selector>";
577
578
if (getIdentifierInfoFlag() < MultiArg) {
579
const IdentifierInfo *II = getAsIdentifierInfo();
580
581
if (getNumArgs() == 0) {
582
assert(II && "If the number of arguments is 0 then II is guaranteed to "
583
"not be null.");
584
return std::string(II->getName());
585
}
586
587
if (!II)
588
return ":";
589
590
return II->getName().str() + ":";
591
}
592
593
// We have a multiple keyword selector.
594
return getMultiKeywordSelector()->getName();
595
}
596
597
void Selector::print(llvm::raw_ostream &OS) const {
598
OS << getAsString();
599
}
600
601
LLVM_DUMP_METHOD void Selector::dump() const { print(llvm::errs()); }
602
603
/// Interpreting the given string using the normal CamelCase
604
/// conventions, determine whether the given string starts with the
605
/// given "word", which is assumed to end in a lowercase letter.
606
static bool startsWithWord(StringRef name, StringRef word) {
607
if (name.size() < word.size()) return false;
608
return ((name.size() == word.size() || !isLowercase(name[word.size()])) &&
609
name.starts_with(word));
610
}
611
612
ObjCMethodFamily Selector::getMethodFamilyImpl(Selector sel) {
613
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
614
if (!first) return OMF_None;
615
616
StringRef name = first->getName();
617
if (sel.isUnarySelector()) {
618
if (name == "autorelease") return OMF_autorelease;
619
if (name == "dealloc") return OMF_dealloc;
620
if (name == "finalize") return OMF_finalize;
621
if (name == "release") return OMF_release;
622
if (name == "retain") return OMF_retain;
623
if (name == "retainCount") return OMF_retainCount;
624
if (name == "self") return OMF_self;
625
if (name == "initialize") return OMF_initialize;
626
}
627
628
if (name == "performSelector" || name == "performSelectorInBackground" ||
629
name == "performSelectorOnMainThread")
630
return OMF_performSelector;
631
632
// The other method families may begin with a prefix of underscores.
633
name = name.ltrim('_');
634
635
if (name.empty()) return OMF_None;
636
switch (name.front()) {
637
case 'a':
638
if (startsWithWord(name, "alloc")) return OMF_alloc;
639
break;
640
case 'c':
641
if (startsWithWord(name, "copy")) return OMF_copy;
642
break;
643
case 'i':
644
if (startsWithWord(name, "init")) return OMF_init;
645
break;
646
case 'm':
647
if (startsWithWord(name, "mutableCopy")) return OMF_mutableCopy;
648
break;
649
case 'n':
650
if (startsWithWord(name, "new")) return OMF_new;
651
break;
652
default:
653
break;
654
}
655
656
return OMF_None;
657
}
658
659
ObjCInstanceTypeFamily Selector::getInstTypeMethodFamily(Selector sel) {
660
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
661
if (!first) return OIT_None;
662
663
StringRef name = first->getName();
664
665
if (name.empty()) return OIT_None;
666
switch (name.front()) {
667
case 'a':
668
if (startsWithWord(name, "array")) return OIT_Array;
669
break;
670
case 'd':
671
if (startsWithWord(name, "default")) return OIT_ReturnsSelf;
672
if (startsWithWord(name, "dictionary")) return OIT_Dictionary;
673
break;
674
case 's':
675
if (startsWithWord(name, "shared")) return OIT_ReturnsSelf;
676
if (startsWithWord(name, "standard")) return OIT_Singleton;
677
break;
678
case 'i':
679
if (startsWithWord(name, "init")) return OIT_Init;
680
break;
681
default:
682
break;
683
}
684
return OIT_None;
685
}
686
687
ObjCStringFormatFamily Selector::getStringFormatFamilyImpl(Selector sel) {
688
const IdentifierInfo *first = sel.getIdentifierInfoForSlot(0);
689
if (!first) return SFF_None;
690
691
StringRef name = first->getName();
692
693
switch (name.front()) {
694
case 'a':
695
if (name == "appendFormat") return SFF_NSString;
696
break;
697
698
case 'i':
699
if (name == "initWithFormat") return SFF_NSString;
700
break;
701
702
case 'l':
703
if (name == "localizedStringWithFormat") return SFF_NSString;
704
break;
705
706
case 's':
707
if (name == "stringByAppendingFormat" ||
708
name == "stringWithFormat") return SFF_NSString;
709
break;
710
}
711
return SFF_None;
712
}
713
714
namespace {
715
716
struct SelectorTableImpl {
717
llvm::FoldingSet<MultiKeywordSelector> Table;
718
llvm::BumpPtrAllocator Allocator;
719
};
720
721
} // namespace
722
723
static SelectorTableImpl &getSelectorTableImpl(void *P) {
724
return *static_cast<SelectorTableImpl*>(P);
725
}
726
727
SmallString<64>
728
SelectorTable::constructSetterName(StringRef Name) {
729
SmallString<64> SetterName("set");
730
SetterName += Name;
731
SetterName[3] = toUppercase(SetterName[3]);
732
return SetterName;
733
}
734
735
Selector
736
SelectorTable::constructSetterSelector(IdentifierTable &Idents,
737
SelectorTable &SelTable,
738
const IdentifierInfo *Name) {
739
IdentifierInfo *SetterName =
740
&Idents.get(constructSetterName(Name->getName()));
741
return SelTable.getUnarySelector(SetterName);
742
}
743
744
std::string SelectorTable::getPropertyNameFromSetterSelector(Selector Sel) {
745
StringRef Name = Sel.getNameForSlot(0);
746
assert(Name.starts_with("set") && "invalid setter name");
747
return (Twine(toLowercase(Name[3])) + Name.drop_front(4)).str();
748
}
749
750
size_t SelectorTable::getTotalMemory() const {
751
SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
752
return SelTabImpl.Allocator.getTotalMemory();
753
}
754
755
Selector SelectorTable::getSelector(unsigned nKeys,
756
const IdentifierInfo **IIV) {
757
if (nKeys < 2)
758
return Selector(IIV[0], nKeys);
759
760
SelectorTableImpl &SelTabImpl = getSelectorTableImpl(Impl);
761
762
// Unique selector, to guarantee there is one per name.
763
llvm::FoldingSetNodeID ID;
764
MultiKeywordSelector::Profile(ID, IIV, nKeys);
765
766
void *InsertPos = nullptr;
767
if (MultiKeywordSelector *SI =
768
SelTabImpl.Table.FindNodeOrInsertPos(ID, InsertPos))
769
return Selector(SI);
770
771
// MultiKeywordSelector objects are not allocated with new because they have a
772
// variable size array (for parameter types) at the end of them.
773
unsigned Size = sizeof(MultiKeywordSelector) + nKeys*sizeof(IdentifierInfo *);
774
MultiKeywordSelector *SI =
775
(MultiKeywordSelector *)SelTabImpl.Allocator.Allocate(
776
Size, alignof(MultiKeywordSelector));
777
new (SI) MultiKeywordSelector(nKeys, IIV);
778
SelTabImpl.Table.InsertNode(SI, InsertPos);
779
return Selector(SI);
780
}
781
782
SelectorTable::SelectorTable() {
783
Impl = new SelectorTableImpl();
784
}
785
786
SelectorTable::~SelectorTable() {
787
delete &getSelectorTableImpl(Impl);
788
}
789
790
const char *clang::getOperatorSpelling(OverloadedOperatorKind Operator) {
791
switch (Operator) {
792
case OO_None:
793
case NUM_OVERLOADED_OPERATORS:
794
return nullptr;
795
796
#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
797
case OO_##Name: return Spelling;
798
#include "clang/Basic/OperatorKinds.def"
799
}
800
801
llvm_unreachable("Invalid OverloadedOperatorKind!");
802
}
803
804
StringRef clang::getNullabilitySpelling(NullabilityKind kind,
805
bool isContextSensitive) {
806
switch (kind) {
807
case NullabilityKind::NonNull:
808
return isContextSensitive ? "nonnull" : "_Nonnull";
809
810
case NullabilityKind::Nullable:
811
return isContextSensitive ? "nullable" : "_Nullable";
812
813
case NullabilityKind::NullableResult:
814
assert(!isContextSensitive &&
815
"_Nullable_result isn't supported as context-sensitive keyword");
816
return "_Nullable_result";
817
818
case NullabilityKind::Unspecified:
819
return isContextSensitive ? "null_unspecified" : "_Null_unspecified";
820
}
821
llvm_unreachable("Unknown nullability kind.");
822
}
823
824
llvm::raw_ostream &clang::operator<<(llvm::raw_ostream &OS,
825
NullabilityKind NK) {
826
switch (NK) {
827
case NullabilityKind::NonNull:
828
return OS << "NonNull";
829
case NullabilityKind::Nullable:
830
return OS << "Nullable";
831
case NullabilityKind::NullableResult:
832
return OS << "NullableResult";
833
case NullabilityKind::Unspecified:
834
return OS << "Unspecified";
835
}
836
llvm_unreachable("Unknown nullability kind.");
837
}
838
839
diag::kind
840
IdentifierTable::getFutureCompatDiagKind(const IdentifierInfo &II,
841
const LangOptions &LangOpts) {
842
assert(II.isFutureCompatKeyword() && "diagnostic should not be needed");
843
844
unsigned Flags = llvm::StringSwitch<unsigned>(II.getName())
845
#define KEYWORD(NAME, FLAGS) .Case(#NAME, FLAGS)
846
#include "clang/Basic/TokenKinds.def"
847
#undef KEYWORD
848
;
849
850
if (LangOpts.CPlusPlus) {
851
if ((Flags & KEYCXX11) == KEYCXX11)
852
return diag::warn_cxx11_keyword;
853
854
// char8_t is not modeled as a CXX20_KEYWORD because it's not
855
// unconditionally enabled in C++20 mode. (It can be disabled
856
// by -fno-char8_t.)
857
if (((Flags & KEYCXX20) == KEYCXX20) ||
858
((Flags & CHAR8SUPPORT) == CHAR8SUPPORT))
859
return diag::warn_cxx20_keyword;
860
} else {
861
if ((Flags & KEYC99) == KEYC99)
862
return diag::warn_c99_keyword;
863
if ((Flags & KEYC23) == KEYC23)
864
return diag::warn_c23_keyword;
865
}
866
867
llvm_unreachable(
868
"Keyword not known to come from a newer Standard or proposed Standard");
869
}
870
871