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