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