NSAPI.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620
  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. #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. using namespace clang;
  15. NSAPI::NSAPI(ASTContext &ctx)
  16. : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
  17. NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
  18. NSUTF8StringEncodingId(nullptr) {}
  19. IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
  20. static const char *ClassName[NumClassIds] = {
  21. "NSObject",
  22. "NSString",
  23. "NSArray",
  24. "NSMutableArray",
  25. "NSDictionary",
  26. "NSMutableDictionary",
  27. "NSNumber",
  28. "NSMutableSet",
  29. "NSMutableOrderedSet",
  30. "NSValue"
  31. };
  32. if (!ClassIds[K])
  33. return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
  34. return ClassIds[K];
  35. }
  36. Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
  37. if (NSStringSelectors[MK].isNull()) {
  38. Selector Sel;
  39. switch (MK) {
  40. case NSStr_stringWithString:
  41. Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
  42. break;
  43. case NSStr_stringWithUTF8String:
  44. Sel = Ctx.Selectors.getUnarySelector(
  45. &Ctx.Idents.get("stringWithUTF8String"));
  46. break;
  47. case NSStr_initWithUTF8String:
  48. Sel = Ctx.Selectors.getUnarySelector(
  49. &Ctx.Idents.get("initWithUTF8String"));
  50. break;
  51. case NSStr_stringWithCStringEncoding: {
  52. IdentifierInfo *KeyIdents[] = {
  53. &Ctx.Idents.get("stringWithCString"),
  54. &Ctx.Idents.get("encoding")
  55. };
  56. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  57. break;
  58. }
  59. case NSStr_stringWithCString:
  60. Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
  61. break;
  62. case NSStr_initWithString:
  63. Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
  64. break;
  65. }
  66. return (NSStringSelectors[MK] = Sel);
  67. }
  68. return NSStringSelectors[MK];
  69. }
  70. Optional<NSAPI::NSStringMethodKind>
  71. NSAPI::getNSStringMethodKind(Selector Sel) const {
  72. for (unsigned i = 0; i != NumNSStringMethods; ++i) {
  73. NSStringMethodKind MK = NSStringMethodKind(i);
  74. if (Sel == getNSStringSelector(MK))
  75. return MK;
  76. }
  77. return None;
  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. return NSArraySelectors[MK];
  143. }
  144. Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
  145. for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
  146. NSArrayMethodKind MK = NSArrayMethodKind(i);
  147. if (Sel == getNSArraySelector(MK))
  148. return MK;
  149. }
  150. return None;
  151. }
  152. Selector NSAPI::getNSDictionarySelector(
  153. NSDictionaryMethodKind MK) const {
  154. if (NSDictionarySelectors[MK].isNull()) {
  155. Selector Sel;
  156. switch (MK) {
  157. case NSDict_dictionary:
  158. Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
  159. break;
  160. case NSDict_dictionaryWithDictionary:
  161. Sel = Ctx.Selectors.getUnarySelector(
  162. &Ctx.Idents.get("dictionaryWithDictionary"));
  163. break;
  164. case NSDict_dictionaryWithObjectForKey: {
  165. IdentifierInfo *KeyIdents[] = {
  166. &Ctx.Idents.get("dictionaryWithObject"),
  167. &Ctx.Idents.get("forKey")
  168. };
  169. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  170. break;
  171. }
  172. case NSDict_dictionaryWithObjectsForKeys: {
  173. IdentifierInfo *KeyIdents[] = {
  174. &Ctx.Idents.get("dictionaryWithObjects"),
  175. &Ctx.Idents.get("forKeys")
  176. };
  177. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  178. break;
  179. }
  180. case NSDict_dictionaryWithObjectsForKeysCount: {
  181. IdentifierInfo *KeyIdents[] = {
  182. &Ctx.Idents.get("dictionaryWithObjects"),
  183. &Ctx.Idents.get("forKeys"),
  184. &Ctx.Idents.get("count")
  185. };
  186. Sel = Ctx.Selectors.getSelector(3, KeyIdents);
  187. break;
  188. }
  189. case NSDict_dictionaryWithObjectsAndKeys:
  190. Sel = Ctx.Selectors.getUnarySelector(
  191. &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
  192. break;
  193. case NSDict_initWithDictionary:
  194. Sel = Ctx.Selectors.getUnarySelector(
  195. &Ctx.Idents.get("initWithDictionary"));
  196. break;
  197. case NSDict_initWithObjectsAndKeys:
  198. Sel = Ctx.Selectors.getUnarySelector(
  199. &Ctx.Idents.get("initWithObjectsAndKeys"));
  200. break;
  201. case NSDict_initWithObjectsForKeys: {
  202. IdentifierInfo *KeyIdents[] = {
  203. &Ctx.Idents.get("initWithObjects"),
  204. &Ctx.Idents.get("forKeys")
  205. };
  206. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  207. break;
  208. }
  209. case NSDict_objectForKey:
  210. Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
  211. break;
  212. case NSMutableDict_setObjectForKey: {
  213. IdentifierInfo *KeyIdents[] = {
  214. &Ctx.Idents.get("setObject"),
  215. &Ctx.Idents.get("forKey")
  216. };
  217. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  218. break;
  219. }
  220. case NSMutableDict_setObjectForKeyedSubscript: {
  221. IdentifierInfo *KeyIdents[] = {
  222. &Ctx.Idents.get("setObject"),
  223. &Ctx.Idents.get("forKeyedSubscript")
  224. };
  225. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  226. break;
  227. }
  228. case NSMutableDict_setValueForKey: {
  229. IdentifierInfo *KeyIdents[] = {
  230. &Ctx.Idents.get("setValue"),
  231. &Ctx.Idents.get("forKey")
  232. };
  233. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  234. break;
  235. }
  236. }
  237. return (NSDictionarySelectors[MK] = Sel);
  238. }
  239. return NSDictionarySelectors[MK];
  240. }
  241. Optional<NSAPI::NSDictionaryMethodKind>
  242. NSAPI::getNSDictionaryMethodKind(Selector Sel) {
  243. for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
  244. NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
  245. if (Sel == getNSDictionarySelector(MK))
  246. return MK;
  247. }
  248. return None;
  249. }
  250. Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
  251. if (NSSetSelectors[MK].isNull()) {
  252. Selector Sel;
  253. switch (MK) {
  254. case NSMutableSet_addObject:
  255. Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
  256. break;
  257. case NSOrderedSet_insertObjectAtIndex: {
  258. IdentifierInfo *KeyIdents[] = {
  259. &Ctx.Idents.get("insertObject"),
  260. &Ctx.Idents.get("atIndex")
  261. };
  262. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  263. break;
  264. }
  265. case NSOrderedSet_setObjectAtIndex: {
  266. IdentifierInfo *KeyIdents[] = {
  267. &Ctx.Idents.get("setObject"),
  268. &Ctx.Idents.get("atIndex")
  269. };
  270. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  271. break;
  272. }
  273. case NSOrderedSet_setObjectAtIndexedSubscript: {
  274. IdentifierInfo *KeyIdents[] = {
  275. &Ctx.Idents.get("setObject"),
  276. &Ctx.Idents.get("atIndexedSubscript")
  277. };
  278. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  279. break;
  280. }
  281. case NSOrderedSet_replaceObjectAtIndexWithObject: {
  282. IdentifierInfo *KeyIdents[] = {
  283. &Ctx.Idents.get("replaceObjectAtIndex"),
  284. &Ctx.Idents.get("withObject")
  285. };
  286. Sel = Ctx.Selectors.getSelector(2, KeyIdents);
  287. break;
  288. }
  289. }
  290. return (NSSetSelectors[MK] = Sel);
  291. }
  292. return NSSetSelectors[MK];
  293. }
  294. Optional<NSAPI::NSSetMethodKind>
  295. NSAPI::getNSSetMethodKind(Selector Sel) {
  296. for (unsigned i = 0; i != NumNSSetMethods; ++i) {
  297. NSSetMethodKind MK = NSSetMethodKind(i);
  298. if (Sel == getNSSetSelector(MK))
  299. return MK;
  300. }
  301. return None;
  302. }
  303. Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
  304. bool Instance) const {
  305. static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
  306. "numberWithChar",
  307. "numberWithUnsignedChar",
  308. "numberWithShort",
  309. "numberWithUnsignedShort",
  310. "numberWithInt",
  311. "numberWithUnsignedInt",
  312. "numberWithLong",
  313. "numberWithUnsignedLong",
  314. "numberWithLongLong",
  315. "numberWithUnsignedLongLong",
  316. "numberWithFloat",
  317. "numberWithDouble",
  318. "numberWithBool",
  319. "numberWithInteger",
  320. "numberWithUnsignedInteger"
  321. };
  322. static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
  323. "initWithChar",
  324. "initWithUnsignedChar",
  325. "initWithShort",
  326. "initWithUnsignedShort",
  327. "initWithInt",
  328. "initWithUnsignedInt",
  329. "initWithLong",
  330. "initWithUnsignedLong",
  331. "initWithLongLong",
  332. "initWithUnsignedLongLong",
  333. "initWithFloat",
  334. "initWithDouble",
  335. "initWithBool",
  336. "initWithInteger",
  337. "initWithUnsignedInteger"
  338. };
  339. Selector *Sels;
  340. const char **Names;
  341. if (Instance) {
  342. Sels = NSNumberInstanceSelectors;
  343. Names = InstanceSelectorName;
  344. } else {
  345. Sels = NSNumberClassSelectors;
  346. Names = ClassSelectorName;
  347. }
  348. if (Sels[MK].isNull())
  349. Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
  350. return Sels[MK];
  351. }
  352. Optional<NSAPI::NSNumberLiteralMethodKind>
  353. NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
  354. for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
  355. NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
  356. if (isNSNumberLiteralSelector(MK, Sel))
  357. return MK;
  358. }
  359. return None;
  360. }
  361. Optional<NSAPI::NSNumberLiteralMethodKind>
  362. NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
  363. const BuiltinType *BT = T->getAs<BuiltinType>();
  364. if (!BT)
  365. return None;
  366. const TypedefType *TDT = T->getAs<TypedefType>();
  367. if (TDT) {
  368. QualType TDTTy = QualType(TDT, 0);
  369. if (isObjCBOOLType(TDTTy))
  370. return NSAPI::NSNumberWithBool;
  371. if (isObjCNSIntegerType(TDTTy))
  372. return NSAPI::NSNumberWithInteger;
  373. if (isObjCNSUIntegerType(TDTTy))
  374. return NSAPI::NSNumberWithUnsignedInteger;
  375. }
  376. switch (BT->getKind()) {
  377. case BuiltinType::Char_S:
  378. case BuiltinType::SChar:
  379. return NSAPI::NSNumberWithChar;
  380. case BuiltinType::Char_U:
  381. case BuiltinType::UChar:
  382. return NSAPI::NSNumberWithUnsignedChar;
  383. case BuiltinType::Short:
  384. return NSAPI::NSNumberWithShort;
  385. case BuiltinType::UShort:
  386. return NSAPI::NSNumberWithUnsignedShort;
  387. case BuiltinType::Int:
  388. return NSAPI::NSNumberWithInt;
  389. case BuiltinType::UInt:
  390. return NSAPI::NSNumberWithUnsignedInt;
  391. case BuiltinType::Long:
  392. return NSAPI::NSNumberWithLong;
  393. case BuiltinType::ULong:
  394. return NSAPI::NSNumberWithUnsignedLong;
  395. case BuiltinType::LongLong:
  396. return NSAPI::NSNumberWithLongLong;
  397. case BuiltinType::ULongLong:
  398. return NSAPI::NSNumberWithUnsignedLongLong;
  399. case BuiltinType::Float:
  400. return NSAPI::NSNumberWithFloat;
  401. case BuiltinType::Double:
  402. return NSAPI::NSNumberWithDouble;
  403. case BuiltinType::Bool:
  404. return NSAPI::NSNumberWithBool;
  405. case BuiltinType::Void:
  406. case BuiltinType::WChar_U:
  407. case BuiltinType::WChar_S:
  408. case BuiltinType::Char8:
  409. case BuiltinType::Char16:
  410. case BuiltinType::Char32:
  411. case BuiltinType::Int128:
  412. case BuiltinType::LongDouble:
  413. case BuiltinType::ShortAccum:
  414. case BuiltinType::Accum:
  415. case BuiltinType::LongAccum:
  416. case BuiltinType::UShortAccum:
  417. case BuiltinType::UAccum:
  418. case BuiltinType::ULongAccum:
  419. case BuiltinType::ShortFract:
  420. case BuiltinType::Fract:
  421. case BuiltinType::LongFract:
  422. case BuiltinType::UShortFract:
  423. case BuiltinType::UFract:
  424. case BuiltinType::ULongFract:
  425. case BuiltinType::SatShortAccum:
  426. case BuiltinType::SatAccum:
  427. case BuiltinType::SatLongAccum:
  428. case BuiltinType::SatUShortAccum:
  429. case BuiltinType::SatUAccum:
  430. case BuiltinType::SatULongAccum:
  431. case BuiltinType::SatShortFract:
  432. case BuiltinType::SatFract:
  433. case BuiltinType::SatLongFract:
  434. case BuiltinType::SatUShortFract:
  435. case BuiltinType::SatUFract:
  436. case BuiltinType::SatULongFract:
  437. case BuiltinType::UInt128:
  438. case BuiltinType::Float16:
  439. case BuiltinType::Float128:
  440. case BuiltinType::NullPtr:
  441. case BuiltinType::ObjCClass:
  442. case BuiltinType::ObjCId:
  443. case BuiltinType::ObjCSel:
  444. #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
  445. case BuiltinType::Id:
  446. #include "clang/Basic/OpenCLImageTypes.def"
  447. #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
  448. case BuiltinType::Id:
  449. #include "clang/Basic/OpenCLExtensionTypes.def"
  450. case BuiltinType::OCLSampler:
  451. case BuiltinType::OCLEvent:
  452. case BuiltinType::OCLClkEvent:
  453. case BuiltinType::OCLQueue:
  454. case BuiltinType::OCLReserveID:
  455. case BuiltinType::BoundMember:
  456. case BuiltinType::Dependent:
  457. case BuiltinType::Overload:
  458. case BuiltinType::UnknownAny:
  459. case BuiltinType::ARCUnbridgedCast:
  460. case BuiltinType::Half:
  461. case BuiltinType::PseudoObject:
  462. case BuiltinType::BuiltinFn:
  463. case BuiltinType::OMPArraySection:
  464. break;
  465. }
  466. return None;
  467. }
  468. /// Returns true if \param T is a typedef of "BOOL" in objective-c.
  469. bool NSAPI::isObjCBOOLType(QualType T) const {
  470. return isObjCTypedef(T, "BOOL", BOOLId);
  471. }
  472. /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
  473. bool NSAPI::isObjCNSIntegerType(QualType T) const {
  474. return isObjCTypedef(T, "NSInteger", NSIntegerId);
  475. }
  476. /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
  477. bool NSAPI::isObjCNSUIntegerType(QualType T) const {
  478. return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
  479. }
  480. StringRef NSAPI::GetNSIntegralKind(QualType T) const {
  481. if (!Ctx.getLangOpts().ObjC || T.isNull())
  482. return StringRef();
  483. while (const TypedefType *TDT = T->getAs<TypedefType>()) {
  484. StringRef NSIntegralResust =
  485. llvm::StringSwitch<StringRef>(
  486. TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
  487. .Case("int8_t", "int8_t")
  488. .Case("int16_t", "int16_t")
  489. .Case("int32_t", "int32_t")
  490. .Case("NSInteger", "NSInteger")
  491. .Case("int64_t", "int64_t")
  492. .Case("uint8_t", "uint8_t")
  493. .Case("uint16_t", "uint16_t")
  494. .Case("uint32_t", "uint32_t")
  495. .Case("NSUInteger", "NSUInteger")
  496. .Case("uint64_t", "uint64_t")
  497. .Default(StringRef());
  498. if (!NSIntegralResust.empty())
  499. return NSIntegralResust;
  500. T = TDT->desugar();
  501. }
  502. return StringRef();
  503. }
  504. bool NSAPI::isMacroDefined(StringRef Id) const {
  505. // FIXME: Check whether the relevant module macros are visible.
  506. return Ctx.Idents.get(Id).hasMacroDefinition();
  507. }
  508. bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
  509. NSClassIdKindKind NSClassKind) const {
  510. if (!InterfaceDecl) {
  511. return false;
  512. }
  513. IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
  514. bool IsSubclass = false;
  515. do {
  516. IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
  517. if (IsSubclass) {
  518. break;
  519. }
  520. } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
  521. return IsSubclass;
  522. }
  523. bool NSAPI::isObjCTypedef(QualType T,
  524. StringRef name, IdentifierInfo *&II) const {
  525. if (!Ctx.getLangOpts().ObjC)
  526. return false;
  527. if (T.isNull())
  528. return false;
  529. if (!II)
  530. II = &Ctx.Idents.get(name);
  531. while (const TypedefType *TDT = T->getAs<TypedefType>()) {
  532. if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
  533. return true;
  534. T = TDT->desugar();
  535. }
  536. return false;
  537. }
  538. bool NSAPI::isObjCEnumerator(const Expr *E,
  539. StringRef name, IdentifierInfo *&II) const {
  540. if (!Ctx.getLangOpts().ObjC)
  541. return false;
  542. if (!E)
  543. return false;
  544. if (!II)
  545. II = &Ctx.Idents.get(name);
  546. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
  547. if (const EnumConstantDecl *
  548. EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
  549. return EnumD->getIdentifier() == II;
  550. return false;
  551. }
  552. Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
  553. Selector &Sel) const {
  554. if (Sel.isNull()) {
  555. SmallVector<IdentifierInfo *, 4> Idents;
  556. for (ArrayRef<StringRef>::const_iterator
  557. I = Ids.begin(), E = Ids.end(); I != E; ++I)
  558. Idents.push_back(&Ctx.Idents.get(*I));
  559. Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
  560. }
  561. return Sel;
  562. }
  563. Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
  564. if (Sel.isNull()) {
  565. IdentifierInfo *Ident = &Ctx.Idents.get(Id);
  566. Sel = Ctx.Selectors.getSelector(0, &Ident);
  567. }
  568. return Sel;
  569. }