1 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
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"
16 using namespace clang;
18 NSAPI::NSAPI(ASTContext &ctx)
19 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
20 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
21 NSUTF8StringEncodingId(nullptr) {}
23 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
24 static const char *ClassName[NumClassIds] = {
30 "NSMutableDictionary",
33 "NSMutableOrderedSet",
38 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
43 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
44 if (NSStringSelectors[MK].isNull()) {
47 case NSStr_stringWithString:
48 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
50 case NSStr_stringWithUTF8String:
51 Sel = Ctx.Selectors.getUnarySelector(
52 &Ctx.Idents.get("stringWithUTF8String"));
54 case NSStr_initWithUTF8String:
55 Sel = Ctx.Selectors.getUnarySelector(
56 &Ctx.Idents.get("initWithUTF8String"));
58 case NSStr_stringWithCStringEncoding: {
59 IdentifierInfo *KeyIdents[] = {
60 &Ctx.Idents.get("stringWithCString"),
61 &Ctx.Idents.get("encoding")
63 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
66 case NSStr_stringWithCString:
67 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
69 case NSStr_initWithString:
70 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
73 return (NSStringSelectors[MK] = Sel);
76 return NSStringSelectors[MK];
79 Optional<NSAPI::NSStringMethodKind>
80 NSAPI::getNSStringMethodKind(Selector Sel) const {
81 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
82 NSStringMethodKind MK = NSStringMethodKind(i);
83 if (Sel == getNSStringSelector(MK))
90 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
91 if (NSArraySelectors[MK].isNull()) {
95 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
97 case NSArr_arrayWithArray:
98 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
100 case NSArr_arrayWithObject:
101 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
103 case NSArr_arrayWithObjects:
104 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
106 case NSArr_arrayWithObjectsCount: {
107 IdentifierInfo *KeyIdents[] = {
108 &Ctx.Idents.get("arrayWithObjects"),
109 &Ctx.Idents.get("count")
111 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
114 case NSArr_initWithArray:
115 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
117 case NSArr_initWithObjects:
118 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
120 case NSArr_objectAtIndex:
121 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
123 case NSMutableArr_replaceObjectAtIndex: {
124 IdentifierInfo *KeyIdents[] = {
125 &Ctx.Idents.get("replaceObjectAtIndex"),
126 &Ctx.Idents.get("withObject")
128 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
131 case NSMutableArr_addObject:
132 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
134 case NSMutableArr_insertObjectAtIndex: {
135 IdentifierInfo *KeyIdents[] = {
136 &Ctx.Idents.get("insertObject"),
137 &Ctx.Idents.get("atIndex")
139 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
142 case NSMutableArr_setObjectAtIndexedSubscript: {
143 IdentifierInfo *KeyIdents[] = {
144 &Ctx.Idents.get("setObject"),
145 &Ctx.Idents.get("atIndexedSubscript")
147 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
151 return (NSArraySelectors[MK] = Sel);
154 return NSArraySelectors[MK];
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))
167 Selector NSAPI::getNSDictionarySelector(
168 NSDictionaryMethodKind MK) const {
169 if (NSDictionarySelectors[MK].isNull()) {
172 case NSDict_dictionary:
173 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
175 case NSDict_dictionaryWithDictionary:
176 Sel = Ctx.Selectors.getUnarySelector(
177 &Ctx.Idents.get("dictionaryWithDictionary"));
179 case NSDict_dictionaryWithObjectForKey: {
180 IdentifierInfo *KeyIdents[] = {
181 &Ctx.Idents.get("dictionaryWithObject"),
182 &Ctx.Idents.get("forKey")
184 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
187 case NSDict_dictionaryWithObjectsForKeys: {
188 IdentifierInfo *KeyIdents[] = {
189 &Ctx.Idents.get("dictionaryWithObjects"),
190 &Ctx.Idents.get("forKeys")
192 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
195 case NSDict_dictionaryWithObjectsForKeysCount: {
196 IdentifierInfo *KeyIdents[] = {
197 &Ctx.Idents.get("dictionaryWithObjects"),
198 &Ctx.Idents.get("forKeys"),
199 &Ctx.Idents.get("count")
201 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
204 case NSDict_dictionaryWithObjectsAndKeys:
205 Sel = Ctx.Selectors.getUnarySelector(
206 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
208 case NSDict_initWithDictionary:
209 Sel = Ctx.Selectors.getUnarySelector(
210 &Ctx.Idents.get("initWithDictionary"));
212 case NSDict_initWithObjectsAndKeys:
213 Sel = Ctx.Selectors.getUnarySelector(
214 &Ctx.Idents.get("initWithObjectsAndKeys"));
216 case NSDict_initWithObjectsForKeys: {
217 IdentifierInfo *KeyIdents[] = {
218 &Ctx.Idents.get("initWithObjects"),
219 &Ctx.Idents.get("forKeys")
221 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
224 case NSDict_objectForKey:
225 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
227 case NSMutableDict_setObjectForKey: {
228 IdentifierInfo *KeyIdents[] = {
229 &Ctx.Idents.get("setObject"),
230 &Ctx.Idents.get("forKey")
232 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
235 case NSMutableDict_setObjectForKeyedSubscript: {
236 IdentifierInfo *KeyIdents[] = {
237 &Ctx.Idents.get("setObject"),
238 &Ctx.Idents.get("forKeyedSubscript")
240 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
243 case NSMutableDict_setValueForKey: {
244 IdentifierInfo *KeyIdents[] = {
245 &Ctx.Idents.get("setValue"),
246 &Ctx.Idents.get("forKey")
248 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
252 return (NSDictionarySelectors[MK] = Sel);
255 return NSDictionarySelectors[MK];
258 Optional<NSAPI::NSDictionaryMethodKind>
259 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
260 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
261 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
262 if (Sel == getNSDictionarySelector(MK))
269 Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
270 if (NSSetSelectors[MK].isNull()) {
273 case NSMutableSet_addObject:
274 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
276 case NSOrderedSet_insertObjectAtIndex: {
277 IdentifierInfo *KeyIdents[] = {
278 &Ctx.Idents.get("insertObject"),
279 &Ctx.Idents.get("atIndex")
281 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
284 case NSOrderedSet_setObjectAtIndex: {
285 IdentifierInfo *KeyIdents[] = {
286 &Ctx.Idents.get("setObject"),
287 &Ctx.Idents.get("atIndex")
289 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
292 case NSOrderedSet_setObjectAtIndexedSubscript: {
293 IdentifierInfo *KeyIdents[] = {
294 &Ctx.Idents.get("setObject"),
295 &Ctx.Idents.get("atIndexedSubscript")
297 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
300 case NSOrderedSet_replaceObjectAtIndexWithObject: {
301 IdentifierInfo *KeyIdents[] = {
302 &Ctx.Idents.get("replaceObjectAtIndex"),
303 &Ctx.Idents.get("withObject")
305 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
309 return (NSSetSelectors[MK] = Sel);
312 return NSSetSelectors[MK];
315 Optional<NSAPI::NSSetMethodKind>
316 NSAPI::getNSSetMethodKind(Selector Sel) {
317 for (unsigned i = 0; i != NumNSSetMethods; ++i) {
318 NSSetMethodKind MK = NSSetMethodKind(i);
319 if (Sel == getNSSetSelector(MK))
326 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
327 bool Instance) const {
328 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
330 "numberWithUnsignedChar",
332 "numberWithUnsignedShort",
334 "numberWithUnsignedInt",
336 "numberWithUnsignedLong",
337 "numberWithLongLong",
338 "numberWithUnsignedLongLong",
343 "numberWithUnsignedInteger"
345 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
347 "initWithUnsignedChar",
349 "initWithUnsignedShort",
351 "initWithUnsignedInt",
353 "initWithUnsignedLong",
355 "initWithUnsignedLongLong",
360 "initWithUnsignedInteger"
366 Sels = NSNumberInstanceSelectors;
367 Names = InstanceSelectorName;
369 Sels = NSNumberClassSelectors;
370 Names = ClassSelectorName;
373 if (Sels[MK].isNull())
374 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
378 Optional<NSAPI::NSNumberLiteralMethodKind>
379 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
380 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
381 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
382 if (isNSNumberLiteralSelector(MK, Sel))
389 Optional<NSAPI::NSNumberLiteralMethodKind>
390 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
391 const BuiltinType *BT = T->getAs<BuiltinType>();
395 const TypedefType *TDT = T->getAs<TypedefType>();
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;
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;
436 case BuiltinType::Void:
437 case BuiltinType::WChar_U:
438 case BuiltinType::WChar_S:
439 case BuiltinType::Char16:
440 case BuiltinType::Char32:
441 case BuiltinType::Int128:
442 case BuiltinType::LongDouble:
443 case BuiltinType::UInt128:
444 case BuiltinType::Float16:
445 case BuiltinType::Float128:
446 case BuiltinType::NullPtr:
447 case BuiltinType::ObjCClass:
448 case BuiltinType::ObjCId:
449 case BuiltinType::ObjCSel:
450 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
451 case BuiltinType::Id:
452 #include "clang/Basic/OpenCLImageTypes.def"
453 case BuiltinType::OCLSampler:
454 case BuiltinType::OCLEvent:
455 case BuiltinType::OCLClkEvent:
456 case BuiltinType::OCLQueue:
457 case BuiltinType::OCLReserveID:
458 case BuiltinType::BoundMember:
459 case BuiltinType::Dependent:
460 case BuiltinType::Overload:
461 case BuiltinType::UnknownAny:
462 case BuiltinType::ARCUnbridgedCast:
463 case BuiltinType::Half:
464 case BuiltinType::PseudoObject:
465 case BuiltinType::BuiltinFn:
466 case BuiltinType::OMPArraySection:
473 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
474 bool NSAPI::isObjCBOOLType(QualType T) const {
475 return isObjCTypedef(T, "BOOL", BOOLId);
477 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
478 bool NSAPI::isObjCNSIntegerType(QualType T) const {
479 return isObjCTypedef(T, "NSInteger", NSIntegerId);
481 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
482 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
483 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
486 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
487 if (!Ctx.getLangOpts().ObjC1 || T.isNull())
490 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
491 StringRef NSIntegralResust =
492 llvm::StringSwitch<StringRef>(
493 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
494 .Case("int8_t", "int8_t")
495 .Case("int16_t", "int16_t")
496 .Case("int32_t", "int32_t")
497 .Case("NSInteger", "NSInteger")
498 .Case("int64_t", "int64_t")
499 .Case("uint8_t", "uint8_t")
500 .Case("uint16_t", "uint16_t")
501 .Case("uint32_t", "uint32_t")
502 .Case("NSUInteger", "NSUInteger")
503 .Case("uint64_t", "uint64_t")
504 .Default(StringRef());
505 if (!NSIntegralResust.empty())
506 return NSIntegralResust;
512 bool NSAPI::isMacroDefined(StringRef Id) const {
513 // FIXME: Check whether the relevant module macros are visible.
514 return Ctx.Idents.get(Id).hasMacroDefinition();
517 bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
518 NSClassIdKindKind NSClassKind) const {
519 if (!InterfaceDecl) {
523 IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
525 bool IsSubclass = false;
527 IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
532 } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
537 bool NSAPI::isObjCTypedef(QualType T,
538 StringRef name, IdentifierInfo *&II) const {
539 if (!Ctx.getLangOpts().ObjC1)
545 II = &Ctx.Idents.get(name);
547 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
548 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
556 bool NSAPI::isObjCEnumerator(const Expr *E,
557 StringRef name, IdentifierInfo *&II) const {
558 if (!Ctx.getLangOpts().ObjC1)
564 II = &Ctx.Idents.get(name);
566 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
567 if (const EnumConstantDecl *
568 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
569 return EnumD->getIdentifier() == II;
574 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
575 Selector &Sel) const {
577 SmallVector<IdentifierInfo *, 4> Idents;
578 for (ArrayRef<StringRef>::const_iterator
579 I = Ids.begin(), E = Ids.end(); I != E; ++I)
580 Idents.push_back(&Ctx.Idents.get(*I));
581 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());