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