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

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