1//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
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#include "clang/AST/NSAPI.h"
10#include "clang/AST/ASTContext.h"
11#include "clang/AST/DeclObjC.h"
12#include "clang/AST/Expr.h"
13#include "llvm/ADT/StringSwitch.h"
14#include <optional>
15
16using namespace clang;
17
18NSAPI::NSAPI(ASTContext &ctx)
19 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
20 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
21 NSUTF8StringEncodingId(nullptr) {}
22
23IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
24 static const char *ClassName[NumClassIds] = {
25 "NSObject",
26 "NSString",
27 "NSArray",
28 "NSMutableArray",
29 "NSDictionary",
30 "NSMutableDictionary",
31 "NSNumber",
32 "NSMutableSet",
33 "NSMutableOrderedSet",
34 "NSValue"
35 };
36
37 if (!ClassIds[K])
38 return (ClassIds[K] = &Ctx.Idents.get(Name: ClassName[K]));
39
40 return ClassIds[K];
41}
42
43Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
44 if (NSStringSelectors[MK].isNull()) {
45 Selector Sel;
46 switch (MK) {
47 case NSStr_stringWithString:
48 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "stringWithString"));
49 break;
50 case NSStr_stringWithUTF8String:
51 Sel = Ctx.Selectors.getUnarySelector(
52 ID: &Ctx.Idents.get(Name: "stringWithUTF8String"));
53 break;
54 case NSStr_initWithUTF8String:
55 Sel = Ctx.Selectors.getUnarySelector(
56 ID: &Ctx.Idents.get(Name: "initWithUTF8String"));
57 break;
58 case NSStr_stringWithCStringEncoding: {
59 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "stringWithCString"),
60 &Ctx.Idents.get(Name: "encoding")};
61 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
62 break;
63 }
64 case NSStr_stringWithCString:
65 Sel= Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "stringWithCString"));
66 break;
67 case NSStr_initWithString:
68 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "initWithString"));
69 break;
70 }
71 return (NSStringSelectors[MK] = Sel);
72 }
73
74 return NSStringSelectors[MK];
75}
76
77Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
78 if (NSArraySelectors[MK].isNull()) {
79 Selector Sel;
80 switch (MK) {
81 case NSArr_array:
82 Sel = Ctx.Selectors.getNullarySelector(ID: &Ctx.Idents.get(Name: "array"));
83 break;
84 case NSArr_arrayWithArray:
85 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "arrayWithArray"));
86 break;
87 case NSArr_arrayWithObject:
88 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "arrayWithObject"));
89 break;
90 case NSArr_arrayWithObjects:
91 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "arrayWithObjects"));
92 break;
93 case NSArr_arrayWithObjectsCount: {
94 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "arrayWithObjects"),
95 &Ctx.Idents.get(Name: "count")};
96 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
97 break;
98 }
99 case NSArr_initWithArray:
100 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "initWithArray"));
101 break;
102 case NSArr_initWithObjects:
103 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "initWithObjects"));
104 break;
105 case NSArr_objectAtIndex:
106 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "objectAtIndex"));
107 break;
108 case NSMutableArr_replaceObjectAtIndex: {
109 const IdentifierInfo *KeyIdents[] = {
110 &Ctx.Idents.get(Name: "replaceObjectAtIndex"),
111 &Ctx.Idents.get(Name: "withObject")};
112 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
113 break;
114 }
115 case NSMutableArr_addObject:
116 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "addObject"));
117 break;
118 case NSMutableArr_insertObjectAtIndex: {
119 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "insertObject"),
120 &Ctx.Idents.get(Name: "atIndex")};
121 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
122 break;
123 }
124 case NSMutableArr_setObjectAtIndexedSubscript: {
125 const IdentifierInfo *KeyIdents[] = {
126 &Ctx.Idents.get(Name: "setObject"), &Ctx.Idents.get(Name: "atIndexedSubscript")};
127 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
128 break;
129 }
130 }
131 return (NSArraySelectors[MK] = Sel);
132 }
133
134 return NSArraySelectors[MK];
135}
136
137std::optional<NSAPI::NSArrayMethodKind>
138NSAPI::getNSArrayMethodKind(Selector Sel) {
139 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
140 NSArrayMethodKind MK = NSArrayMethodKind(i);
141 if (Sel == getNSArraySelector(MK))
142 return MK;
143 }
144
145 return std::nullopt;
146}
147
148Selector NSAPI::getNSDictionarySelector(
149 NSDictionaryMethodKind MK) const {
150 if (NSDictionarySelectors[MK].isNull()) {
151 Selector Sel;
152 switch (MK) {
153 case NSDict_dictionary:
154 Sel = Ctx.Selectors.getNullarySelector(ID: &Ctx.Idents.get(Name: "dictionary"));
155 break;
156 case NSDict_dictionaryWithDictionary:
157 Sel = Ctx.Selectors.getUnarySelector(
158 ID: &Ctx.Idents.get(Name: "dictionaryWithDictionary"));
159 break;
160 case NSDict_dictionaryWithObjectForKey: {
161 const IdentifierInfo *KeyIdents[] = {
162 &Ctx.Idents.get(Name: "dictionaryWithObject"), &Ctx.Idents.get(Name: "forKey")};
163 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
164 break;
165 }
166 case NSDict_dictionaryWithObjectsForKeys: {
167 const IdentifierInfo *KeyIdents[] = {
168 &Ctx.Idents.get(Name: "dictionaryWithObjects"), &Ctx.Idents.get(Name: "forKeys")};
169 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
170 break;
171 }
172 case NSDict_dictionaryWithObjectsForKeysCount: {
173 const IdentifierInfo *KeyIdents[] = {
174 &Ctx.Idents.get(Name: "dictionaryWithObjects"), &Ctx.Idents.get(Name: "forKeys"),
175 &Ctx.Idents.get(Name: "count")};
176 Sel = Ctx.Selectors.getSelector(NumArgs: 3, IIV: KeyIdents);
177 break;
178 }
179 case NSDict_dictionaryWithObjectsAndKeys:
180 Sel = Ctx.Selectors.getUnarySelector(
181 ID: &Ctx.Idents.get(Name: "dictionaryWithObjectsAndKeys"));
182 break;
183 case NSDict_initWithDictionary:
184 Sel = Ctx.Selectors.getUnarySelector(
185 ID: &Ctx.Idents.get(Name: "initWithDictionary"));
186 break;
187 case NSDict_initWithObjectsAndKeys:
188 Sel = Ctx.Selectors.getUnarySelector(
189 ID: &Ctx.Idents.get(Name: "initWithObjectsAndKeys"));
190 break;
191 case NSDict_initWithObjectsForKeys: {
192 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "initWithObjects"),
193 &Ctx.Idents.get(Name: "forKeys")};
194 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
195 break;
196 }
197 case NSDict_objectForKey:
198 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "objectForKey"));
199 break;
200 case NSMutableDict_setObjectForKey: {
201 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "setObject"),
202 &Ctx.Idents.get(Name: "forKey")};
203 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
204 break;
205 }
206 case NSMutableDict_setObjectForKeyedSubscript: {
207 const IdentifierInfo *KeyIdents[] = {
208 &Ctx.Idents.get(Name: "setObject"), &Ctx.Idents.get(Name: "forKeyedSubscript")};
209 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
210 break;
211 }
212 case NSMutableDict_setValueForKey: {
213 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "setValue"),
214 &Ctx.Idents.get(Name: "forKey")};
215 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
216 break;
217 }
218 }
219 return (NSDictionarySelectors[MK] = Sel);
220 }
221
222 return NSDictionarySelectors[MK];
223}
224
225std::optional<NSAPI::NSDictionaryMethodKind>
226NSAPI::getNSDictionaryMethodKind(Selector Sel) {
227 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
228 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
229 if (Sel == getNSDictionarySelector(MK))
230 return MK;
231 }
232
233 return std::nullopt;
234}
235
236Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
237 if (NSSetSelectors[MK].isNull()) {
238 Selector Sel;
239 switch (MK) {
240 case NSMutableSet_addObject:
241 Sel = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: "addObject"));
242 break;
243 case NSOrderedSet_insertObjectAtIndex: {
244 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "insertObject"),
245 &Ctx.Idents.get(Name: "atIndex")};
246 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
247 break;
248 }
249 case NSOrderedSet_setObjectAtIndex: {
250 const IdentifierInfo *KeyIdents[] = {&Ctx.Idents.get(Name: "setObject"),
251 &Ctx.Idents.get(Name: "atIndex")};
252 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
253 break;
254 }
255 case NSOrderedSet_setObjectAtIndexedSubscript: {
256 const IdentifierInfo *KeyIdents[] = {
257 &Ctx.Idents.get(Name: "setObject"), &Ctx.Idents.get(Name: "atIndexedSubscript")};
258 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
259 break;
260 }
261 case NSOrderedSet_replaceObjectAtIndexWithObject: {
262 const IdentifierInfo *KeyIdents[] = {
263 &Ctx.Idents.get(Name: "replaceObjectAtIndex"),
264 &Ctx.Idents.get(Name: "withObject")};
265 Sel = Ctx.Selectors.getSelector(NumArgs: 2, IIV: KeyIdents);
266 break;
267 }
268 }
269 return (NSSetSelectors[MK] = Sel);
270 }
271
272 return NSSetSelectors[MK];
273}
274
275std::optional<NSAPI::NSSetMethodKind> NSAPI::getNSSetMethodKind(Selector Sel) {
276 for (unsigned i = 0; i != NumNSSetMethods; ++i) {
277 NSSetMethodKind MK = NSSetMethodKind(i);
278 if (Sel == getNSSetSelector(MK))
279 return MK;
280 }
281
282 return std::nullopt;
283}
284
285Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
286 bool Instance) const {
287 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
288 "numberWithChar",
289 "numberWithUnsignedChar",
290 "numberWithShort",
291 "numberWithUnsignedShort",
292 "numberWithInt",
293 "numberWithUnsignedInt",
294 "numberWithLong",
295 "numberWithUnsignedLong",
296 "numberWithLongLong",
297 "numberWithUnsignedLongLong",
298 "numberWithFloat",
299 "numberWithDouble",
300 "numberWithBool",
301 "numberWithInteger",
302 "numberWithUnsignedInteger"
303 };
304 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
305 "initWithChar",
306 "initWithUnsignedChar",
307 "initWithShort",
308 "initWithUnsignedShort",
309 "initWithInt",
310 "initWithUnsignedInt",
311 "initWithLong",
312 "initWithUnsignedLong",
313 "initWithLongLong",
314 "initWithUnsignedLongLong",
315 "initWithFloat",
316 "initWithDouble",
317 "initWithBool",
318 "initWithInteger",
319 "initWithUnsignedInteger"
320 };
321
322 Selector *Sels;
323 const char **Names;
324 if (Instance) {
325 Sels = NSNumberInstanceSelectors;
326 Names = InstanceSelectorName;
327 } else {
328 Sels = NSNumberClassSelectors;
329 Names = ClassSelectorName;
330 }
331
332 if (Sels[MK].isNull())
333 Sels[MK] = Ctx.Selectors.getUnarySelector(ID: &Ctx.Idents.get(Name: Names[MK]));
334 return Sels[MK];
335}
336
337std::optional<NSAPI::NSNumberLiteralMethodKind>
338NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
339 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
340 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
341 if (isNSNumberLiteralSelector(MK, Sel))
342 return MK;
343 }
344
345 return std::nullopt;
346}
347
348std::optional<NSAPI::NSNumberLiteralMethodKind>
349NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
350 const BuiltinType *BT = T->getAs<BuiltinType>();
351 if (!BT)
352 return std::nullopt;
353
354 const TypedefType *TDT = T->getAs<TypedefType>();
355 if (TDT) {
356 QualType TDTTy = QualType(TDT, 0);
357 if (isObjCBOOLType(T: TDTTy))
358 return NSAPI::NSNumberWithBool;
359 if (isObjCNSIntegerType(T: TDTTy))
360 return NSAPI::NSNumberWithInteger;
361 if (isObjCNSUIntegerType(T: TDTTy))
362 return NSAPI::NSNumberWithUnsignedInteger;
363 }
364
365 switch (BT->getKind()) {
366 case BuiltinType::Char_S:
367 case BuiltinType::SChar:
368 return NSAPI::NSNumberWithChar;
369 case BuiltinType::Char_U:
370 case BuiltinType::UChar:
371 return NSAPI::NSNumberWithUnsignedChar;
372 case BuiltinType::Short:
373 return NSAPI::NSNumberWithShort;
374 case BuiltinType::UShort:
375 return NSAPI::NSNumberWithUnsignedShort;
376 case BuiltinType::Int:
377 return NSAPI::NSNumberWithInt;
378 case BuiltinType::UInt:
379 return NSAPI::NSNumberWithUnsignedInt;
380 case BuiltinType::Long:
381 return NSAPI::NSNumberWithLong;
382 case BuiltinType::ULong:
383 return NSAPI::NSNumberWithUnsignedLong;
384 case BuiltinType::LongLong:
385 return NSAPI::NSNumberWithLongLong;
386 case BuiltinType::ULongLong:
387 return NSAPI::NSNumberWithUnsignedLongLong;
388 case BuiltinType::Float:
389 return NSAPI::NSNumberWithFloat;
390 case BuiltinType::Double:
391 return NSAPI::NSNumberWithDouble;
392 case BuiltinType::Bool:
393 return NSAPI::NSNumberWithBool;
394
395 case BuiltinType::Void:
396 case BuiltinType::WChar_U:
397 case BuiltinType::WChar_S:
398 case BuiltinType::Char8:
399 case BuiltinType::Char16:
400 case BuiltinType::Char32:
401 case BuiltinType::Int128:
402 case BuiltinType::LongDouble:
403 case BuiltinType::ShortAccum:
404 case BuiltinType::Accum:
405 case BuiltinType::LongAccum:
406 case BuiltinType::UShortAccum:
407 case BuiltinType::UAccum:
408 case BuiltinType::ULongAccum:
409 case BuiltinType::ShortFract:
410 case BuiltinType::Fract:
411 case BuiltinType::LongFract:
412 case BuiltinType::UShortFract:
413 case BuiltinType::UFract:
414 case BuiltinType::ULongFract:
415 case BuiltinType::SatShortAccum:
416 case BuiltinType::SatAccum:
417 case BuiltinType::SatLongAccum:
418 case BuiltinType::SatUShortAccum:
419 case BuiltinType::SatUAccum:
420 case BuiltinType::SatULongAccum:
421 case BuiltinType::SatShortFract:
422 case BuiltinType::SatFract:
423 case BuiltinType::SatLongFract:
424 case BuiltinType::SatUShortFract:
425 case BuiltinType::SatUFract:
426 case BuiltinType::SatULongFract:
427 case BuiltinType::UInt128:
428 case BuiltinType::Float16:
429 case BuiltinType::Float128:
430 case BuiltinType::Ibm128:
431 case BuiltinType::NullPtr:
432 case BuiltinType::ObjCClass:
433 case BuiltinType::ObjCId:
434 case BuiltinType::ObjCSel:
435#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
436 case BuiltinType::Id:
437#include "clang/Basic/OpenCLImageTypes.def"
438#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
439 case BuiltinType::Id:
440#include "clang/Basic/OpenCLExtensionTypes.def"
441 case BuiltinType::OCLSampler:
442 case BuiltinType::OCLEvent:
443 case BuiltinType::OCLClkEvent:
444 case BuiltinType::OCLQueue:
445 case BuiltinType::OCLReserveID:
446#define SVE_TYPE(Name, Id, SingletonId) \
447 case BuiltinType::Id:
448#include "clang/Basic/AArch64SVEACLETypes.def"
449#define PPC_VECTOR_TYPE(Name, Id, Size) \
450 case BuiltinType::Id:
451#include "clang/Basic/PPCTypes.def"
452#define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
453#include "clang/Basic/RISCVVTypes.def"
454#define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
455#include "clang/Basic/WebAssemblyReferenceTypes.def"
456 case BuiltinType::BoundMember:
457 case BuiltinType::Dependent:
458 case BuiltinType::Overload:
459 case BuiltinType::UnknownAny:
460 case BuiltinType::ARCUnbridgedCast:
461 case BuiltinType::Half:
462 case BuiltinType::PseudoObject:
463 case BuiltinType::BuiltinFn:
464 case BuiltinType::IncompleteMatrixIdx:
465 case BuiltinType::OMPArraySection:
466 case BuiltinType::OMPArrayShaping:
467 case BuiltinType::OMPIterator:
468 case BuiltinType::BFloat16:
469 break;
470 }
471
472 return std::nullopt;
473}
474
475/// Returns true if \param T is a typedef of "BOOL" in objective-c.
476bool NSAPI::isObjCBOOLType(QualType T) const {
477 return isObjCTypedef(T, name: "BOOL", II&: BOOLId);
478}
479/// Returns true if \param T is a typedef of "NSInteger" in objective-c.
480bool NSAPI::isObjCNSIntegerType(QualType T) const {
481 return isObjCTypedef(T, name: "NSInteger", II&: NSIntegerId);
482}
483/// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
484bool NSAPI::isObjCNSUIntegerType(QualType T) const {
485 return isObjCTypedef(T, name: "NSUInteger", II&: NSUIntegerId);
486}
487
488StringRef NSAPI::GetNSIntegralKind(QualType T) const {
489 if (!Ctx.getLangOpts().ObjC || T.isNull())
490 return StringRef();
491
492 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
493 StringRef NSIntegralResust =
494 llvm::StringSwitch<StringRef>(
495 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
496 .Case(S: "int8_t", Value: "int8_t")
497 .Case(S: "int16_t", Value: "int16_t")
498 .Case(S: "int32_t", Value: "int32_t")
499 .Case(S: "NSInteger", Value: "NSInteger")
500 .Case(S: "int64_t", Value: "int64_t")
501 .Case(S: "uint8_t", Value: "uint8_t")
502 .Case(S: "uint16_t", Value: "uint16_t")
503 .Case(S: "uint32_t", Value: "uint32_t")
504 .Case(S: "NSUInteger", Value: "NSUInteger")
505 .Case(S: "uint64_t", Value: "uint64_t")
506 .Default(Value: StringRef());
507 if (!NSIntegralResust.empty())
508 return NSIntegralResust;
509 T = TDT->desugar();
510 }
511 return StringRef();
512}
513
514bool NSAPI::isMacroDefined(StringRef Id) const {
515 // FIXME: Check whether the relevant module macros are visible.
516 return Ctx.Idents.get(Name: Id).hasMacroDefinition();
517}
518
519bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
520 NSClassIdKindKind NSClassKind) const {
521 if (!InterfaceDecl) {
522 return false;
523 }
524
525 IdentifierInfo *NSClassID = getNSClassId(K: NSClassKind);
526
527 bool IsSubclass = false;
528 do {
529 IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
530
531 if (IsSubclass) {
532 break;
533 }
534 } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
535
536 return IsSubclass;
537}
538
539bool NSAPI::isObjCTypedef(QualType T,
540 StringRef name, IdentifierInfo *&II) const {
541 if (!Ctx.getLangOpts().ObjC)
542 return false;
543 if (T.isNull())
544 return false;
545
546 if (!II)
547 II = &Ctx.Idents.get(Name: name);
548
549 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
550 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
551 return true;
552 T = TDT->desugar();
553 }
554
555 return false;
556}
557
558bool NSAPI::isObjCEnumerator(const Expr *E,
559 StringRef name, IdentifierInfo *&II) const {
560 if (!Ctx.getLangOpts().ObjC)
561 return false;
562 if (!E)
563 return false;
564
565 if (!II)
566 II = &Ctx.Idents.get(Name: name);
567
568 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
569 if (const EnumConstantDecl *
570 EnumD = dyn_cast_or_null<EnumConstantDecl>(Val: DRE->getDecl()))
571 return EnumD->getIdentifier() == II;
572
573 return false;
574}
575
576Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
577 Selector &Sel) const {
578 if (Sel.isNull()) {
579 SmallVector<const IdentifierInfo *, 4> Idents;
580 for (ArrayRef<StringRef>::const_iterator
581 I = Ids.begin(), E = Ids.end(); I != E; ++I)
582 Idents.push_back(Elt: &Ctx.Idents.get(Name: *I));
583 Sel = Ctx.Selectors.getSelector(NumArgs: Idents.size(), IIV: Idents.data());
584 }
585 return Sel;
586}
587
588Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
589 if (Sel.isNull()) {
590 const IdentifierInfo *Ident = &Ctx.Idents.get(Name: Id);
591 Sel = Ctx.Selectors.getSelector(NumArgs: 0, IIV: &Ident);
592 }
593 return Sel;
594}
595

source code of clang/lib/AST/NSAPI.cpp