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