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