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#define AMDGPU_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
457#include "clang/Basic/AMDGPUTypes.def"
458 case BuiltinType::BoundMember:
459 case BuiltinType::UnresolvedTemplate:
460 case BuiltinType::Dependent:
461 case BuiltinType::Overload:
462 case BuiltinType::UnknownAny:
463 case BuiltinType::ARCUnbridgedCast:
464 case BuiltinType::Half:
465 case BuiltinType::PseudoObject:
466 case BuiltinType::BuiltinFn:
467 case BuiltinType::IncompleteMatrixIdx:
468 case BuiltinType::ArraySection:
469 case BuiltinType::OMPArrayShaping:
470 case BuiltinType::OMPIterator:
471 case BuiltinType::BFloat16:
472 break;
473 }
474
475 return std::nullopt;
476}
477
478/// Returns true if \param T is a typedef of "BOOL" in objective-c.
479bool NSAPI::isObjCBOOLType(QualType T) const {
480 return isObjCTypedef(T, name: "BOOL", II&: BOOLId);
481}
482/// Returns true if \param T is a typedef of "NSInteger" in objective-c.
483bool NSAPI::isObjCNSIntegerType(QualType T) const {
484 return isObjCTypedef(T, name: "NSInteger", II&: NSIntegerId);
485}
486/// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
487bool NSAPI::isObjCNSUIntegerType(QualType T) const {
488 return isObjCTypedef(T, name: "NSUInteger", II&: NSUIntegerId);
489}
490
491StringRef NSAPI::GetNSIntegralKind(QualType T) const {
492 if (!Ctx.getLangOpts().ObjC || T.isNull())
493 return StringRef();
494
495 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
496 StringRef NSIntegralResust =
497 llvm::StringSwitch<StringRef>(
498 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
499 .Case(S: "int8_t", Value: "int8_t")
500 .Case(S: "int16_t", Value: "int16_t")
501 .Case(S: "int32_t", Value: "int32_t")
502 .Case(S: "NSInteger", Value: "NSInteger")
503 .Case(S: "int64_t", Value: "int64_t")
504 .Case(S: "uint8_t", Value: "uint8_t")
505 .Case(S: "uint16_t", Value: "uint16_t")
506 .Case(S: "uint32_t", Value: "uint32_t")
507 .Case(S: "NSUInteger", Value: "NSUInteger")
508 .Case(S: "uint64_t", Value: "uint64_t")
509 .Default(Value: StringRef());
510 if (!NSIntegralResust.empty())
511 return NSIntegralResust;
512 T = TDT->desugar();
513 }
514 return StringRef();
515}
516
517bool NSAPI::isMacroDefined(StringRef Id) const {
518 // FIXME: Check whether the relevant module macros are visible.
519 return Ctx.Idents.get(Name: Id).hasMacroDefinition();
520}
521
522bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
523 NSClassIdKindKind NSClassKind) const {
524 if (!InterfaceDecl) {
525 return false;
526 }
527
528 IdentifierInfo *NSClassID = getNSClassId(K: NSClassKind);
529
530 bool IsSubclass = false;
531 do {
532 IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
533
534 if (IsSubclass) {
535 break;
536 }
537 } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
538
539 return IsSubclass;
540}
541
542bool NSAPI::isObjCTypedef(QualType T,
543 StringRef name, IdentifierInfo *&II) const {
544 if (!Ctx.getLangOpts().ObjC)
545 return false;
546 if (T.isNull())
547 return false;
548
549 if (!II)
550 II = &Ctx.Idents.get(Name: name);
551
552 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
553 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
554 return true;
555 T = TDT->desugar();
556 }
557
558 return false;
559}
560
561bool NSAPI::isObjCEnumerator(const Expr *E,
562 StringRef name, IdentifierInfo *&II) const {
563 if (!Ctx.getLangOpts().ObjC)
564 return false;
565 if (!E)
566 return false;
567
568 if (!II)
569 II = &Ctx.Idents.get(Name: name);
570
571 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Val: E->IgnoreParenImpCasts()))
572 if (const EnumConstantDecl *
573 EnumD = dyn_cast_or_null<EnumConstantDecl>(Val: DRE->getDecl()))
574 return EnumD->getIdentifier() == II;
575
576 return false;
577}
578
579Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
580 Selector &Sel) const {
581 if (Sel.isNull()) {
582 SmallVector<const IdentifierInfo *, 4> Idents;
583 for (ArrayRef<StringRef>::const_iterator
584 I = Ids.begin(), E = Ids.end(); I != E; ++I)
585 Idents.push_back(Elt: &Ctx.Idents.get(Name: *I));
586 Sel = Ctx.Selectors.getSelector(NumArgs: Idents.size(), IIV: Idents.data());
587 }
588 return Sel;
589}
590
591Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
592 if (Sel.isNull()) {
593 const IdentifierInfo *Ident = &Ctx.Idents.get(Name: Id);
594 Sel = Ctx.Selectors.getSelector(NumArgs: 0, IIV: &Ident);
595 }
596 return Sel;
597}
598