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 18 NSAPI::NSAPI(ASTContext &ctx) 19 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr), 20 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr), 21 NSUTF8StringEncodingId(nullptr) {} 22 23 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 43 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> 80 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 90 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 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 167 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> 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 269 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> 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 326 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> 379 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> 390 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::UInt128: 451 case BuiltinType::Float16: 452 case BuiltinType::Float128: 453 case BuiltinType::NullPtr: 454 case BuiltinType::ObjCClass: 455 case BuiltinType::ObjCId: 456 case BuiltinType::ObjCSel: 457 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ 458 case BuiltinType::Id: 459 #include "clang/Basic/OpenCLImageTypes.def" 460 case BuiltinType::OCLSampler: 461 case BuiltinType::OCLEvent: 462 case BuiltinType::OCLClkEvent: 463 case BuiltinType::OCLQueue: 464 case BuiltinType::OCLReserveID: 465 case BuiltinType::BoundMember: 466 case BuiltinType::Dependent: 467 case BuiltinType::Overload: 468 case BuiltinType::UnknownAny: 469 case BuiltinType::ARCUnbridgedCast: 470 case BuiltinType::Half: 471 case BuiltinType::PseudoObject: 472 case BuiltinType::BuiltinFn: 473 case BuiltinType::OMPArraySection: 474 break; 475 } 476 477 return None; 478 } 479 480 /// Returns true if \param T is a typedef of "BOOL" in objective-c. 481 bool NSAPI::isObjCBOOLType(QualType T) const { 482 return isObjCTypedef(T, "BOOL", BOOLId); 483 } 484 /// Returns true if \param T is a typedef of "NSInteger" in objective-c. 485 bool NSAPI::isObjCNSIntegerType(QualType T) const { 486 return isObjCTypedef(T, "NSInteger", NSIntegerId); 487 } 488 /// Returns true if \param T is a typedef of "NSUInteger" in objective-c. 489 bool NSAPI::isObjCNSUIntegerType(QualType T) const { 490 return isObjCTypedef(T, "NSUInteger", NSUIntegerId); 491 } 492 493 StringRef NSAPI::GetNSIntegralKind(QualType T) const { 494 if (!Ctx.getLangOpts().ObjC1 || T.isNull()) 495 return StringRef(); 496 497 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 498 StringRef NSIntegralResust = 499 llvm::StringSwitch<StringRef>( 500 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName()) 501 .Case("int8_t", "int8_t") 502 .Case("int16_t", "int16_t") 503 .Case("int32_t", "int32_t") 504 .Case("NSInteger", "NSInteger") 505 .Case("int64_t", "int64_t") 506 .Case("uint8_t", "uint8_t") 507 .Case("uint16_t", "uint16_t") 508 .Case("uint32_t", "uint32_t") 509 .Case("NSUInteger", "NSUInteger") 510 .Case("uint64_t", "uint64_t") 511 .Default(StringRef()); 512 if (!NSIntegralResust.empty()) 513 return NSIntegralResust; 514 T = TDT->desugar(); 515 } 516 return StringRef(); 517 } 518 519 bool NSAPI::isMacroDefined(StringRef Id) const { 520 // FIXME: Check whether the relevant module macros are visible. 521 return Ctx.Idents.get(Id).hasMacroDefinition(); 522 } 523 524 bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl, 525 NSClassIdKindKind NSClassKind) const { 526 if (!InterfaceDecl) { 527 return false; 528 } 529 530 IdentifierInfo *NSClassID = getNSClassId(NSClassKind); 531 532 bool IsSubclass = false; 533 do { 534 IsSubclass = NSClassID == InterfaceDecl->getIdentifier(); 535 536 if (IsSubclass) { 537 break; 538 } 539 } while ((InterfaceDecl = InterfaceDecl->getSuperClass())); 540 541 return IsSubclass; 542 } 543 544 bool NSAPI::isObjCTypedef(QualType T, 545 StringRef name, IdentifierInfo *&II) const { 546 if (!Ctx.getLangOpts().ObjC1) 547 return false; 548 if (T.isNull()) 549 return false; 550 551 if (!II) 552 II = &Ctx.Idents.get(name); 553 554 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 555 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) 556 return true; 557 T = TDT->desugar(); 558 } 559 560 return false; 561 } 562 563 bool NSAPI::isObjCEnumerator(const Expr *E, 564 StringRef name, IdentifierInfo *&II) const { 565 if (!Ctx.getLangOpts().ObjC1) 566 return false; 567 if (!E) 568 return false; 569 570 if (!II) 571 II = &Ctx.Idents.get(name); 572 573 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) 574 if (const EnumConstantDecl * 575 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl())) 576 return EnumD->getIdentifier() == II; 577 578 return false; 579 } 580 581 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, 582 Selector &Sel) const { 583 if (Sel.isNull()) { 584 SmallVector<IdentifierInfo *, 4> Idents; 585 for (ArrayRef<StringRef>::const_iterator 586 I = Ids.begin(), E = Ids.end(); I != E; ++I) 587 Idents.push_back(&Ctx.Idents.get(*I)); 588 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data()); 589 } 590 return Sel; 591 } 592