1 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
15 using namespace clang;
17 NSAPI::NSAPI(ASTContext &ctx)
18 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20 NSUTF8StringEncodingId(nullptr) {}
22 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
23 static const char *ClassName[NumClassIds] = {
29 "NSMutableDictionary",
32 "NSMutableOrderedSet",
37 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
42 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
43 if (NSStringSelectors[MK].isNull()) {
46 case NSStr_stringWithString:
47 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
49 case NSStr_stringWithUTF8String:
50 Sel = Ctx.Selectors.getUnarySelector(
51 &Ctx.Idents.get("stringWithUTF8String"));
53 case NSStr_initWithUTF8String:
54 Sel = Ctx.Selectors.getUnarySelector(
55 &Ctx.Idents.get("initWithUTF8String"));
57 case NSStr_stringWithCStringEncoding: {
58 IdentifierInfo *KeyIdents[] = {
59 &Ctx.Idents.get("stringWithCString"),
60 &Ctx.Idents.get("encoding")
62 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
65 case NSStr_stringWithCString:
66 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
68 case NSStr_initWithString:
69 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
72 return (NSStringSelectors[MK] = Sel);
75 return NSStringSelectors[MK];
78 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
79 if (NSArraySelectors[MK].isNull()) {
83 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
85 case NSArr_arrayWithArray:
86 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
88 case NSArr_arrayWithObject:
89 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
91 case NSArr_arrayWithObjects:
92 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
94 case NSArr_arrayWithObjectsCount: {
95 IdentifierInfo *KeyIdents[] = {
96 &Ctx.Idents.get("arrayWithObjects"),
97 &Ctx.Idents.get("count")
99 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
102 case NSArr_initWithArray:
103 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
105 case NSArr_initWithObjects:
106 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
108 case NSArr_objectAtIndex:
109 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
111 case NSMutableArr_replaceObjectAtIndex: {
112 IdentifierInfo *KeyIdents[] = {
113 &Ctx.Idents.get("replaceObjectAtIndex"),
114 &Ctx.Idents.get("withObject")
116 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
119 case NSMutableArr_addObject:
120 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
122 case NSMutableArr_insertObjectAtIndex: {
123 IdentifierInfo *KeyIdents[] = {
124 &Ctx.Idents.get("insertObject"),
125 &Ctx.Idents.get("atIndex")
127 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
130 case NSMutableArr_setObjectAtIndexedSubscript: {
131 IdentifierInfo *KeyIdents[] = {
132 &Ctx.Idents.get("setObject"),
133 &Ctx.Idents.get("atIndexedSubscript")
135 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
139 return (NSArraySelectors[MK] = Sel);
142 return NSArraySelectors[MK];
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))
155 Selector NSAPI::getNSDictionarySelector(
156 NSDictionaryMethodKind MK) const {
157 if (NSDictionarySelectors[MK].isNull()) {
160 case NSDict_dictionary:
161 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
163 case NSDict_dictionaryWithDictionary:
164 Sel = Ctx.Selectors.getUnarySelector(
165 &Ctx.Idents.get("dictionaryWithDictionary"));
167 case NSDict_dictionaryWithObjectForKey: {
168 IdentifierInfo *KeyIdents[] = {
169 &Ctx.Idents.get("dictionaryWithObject"),
170 &Ctx.Idents.get("forKey")
172 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
175 case NSDict_dictionaryWithObjectsForKeys: {
176 IdentifierInfo *KeyIdents[] = {
177 &Ctx.Idents.get("dictionaryWithObjects"),
178 &Ctx.Idents.get("forKeys")
180 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
183 case NSDict_dictionaryWithObjectsForKeysCount: {
184 IdentifierInfo *KeyIdents[] = {
185 &Ctx.Idents.get("dictionaryWithObjects"),
186 &Ctx.Idents.get("forKeys"),
187 &Ctx.Idents.get("count")
189 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
192 case NSDict_dictionaryWithObjectsAndKeys:
193 Sel = Ctx.Selectors.getUnarySelector(
194 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
196 case NSDict_initWithDictionary:
197 Sel = Ctx.Selectors.getUnarySelector(
198 &Ctx.Idents.get("initWithDictionary"));
200 case NSDict_initWithObjectsAndKeys:
201 Sel = Ctx.Selectors.getUnarySelector(
202 &Ctx.Idents.get("initWithObjectsAndKeys"));
204 case NSDict_initWithObjectsForKeys: {
205 IdentifierInfo *KeyIdents[] = {
206 &Ctx.Idents.get("initWithObjects"),
207 &Ctx.Idents.get("forKeys")
209 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
212 case NSDict_objectForKey:
213 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
215 case NSMutableDict_setObjectForKey: {
216 IdentifierInfo *KeyIdents[] = {
217 &Ctx.Idents.get("setObject"),
218 &Ctx.Idents.get("forKey")
220 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
223 case NSMutableDict_setObjectForKeyedSubscript: {
224 IdentifierInfo *KeyIdents[] = {
225 &Ctx.Idents.get("setObject"),
226 &Ctx.Idents.get("forKeyedSubscript")
228 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
231 case NSMutableDict_setValueForKey: {
232 IdentifierInfo *KeyIdents[] = {
233 &Ctx.Idents.get("setValue"),
234 &Ctx.Idents.get("forKey")
236 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
240 return (NSDictionarySelectors[MK] = Sel);
243 return NSDictionarySelectors[MK];
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))
257 Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
258 if (NSSetSelectors[MK].isNull()) {
261 case NSMutableSet_addObject:
262 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
264 case NSOrderedSet_insertObjectAtIndex: {
265 IdentifierInfo *KeyIdents[] = {
266 &Ctx.Idents.get("insertObject"),
267 &Ctx.Idents.get("atIndex")
269 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
272 case NSOrderedSet_setObjectAtIndex: {
273 IdentifierInfo *KeyIdents[] = {
274 &Ctx.Idents.get("setObject"),
275 &Ctx.Idents.get("atIndex")
277 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
280 case NSOrderedSet_setObjectAtIndexedSubscript: {
281 IdentifierInfo *KeyIdents[] = {
282 &Ctx.Idents.get("setObject"),
283 &Ctx.Idents.get("atIndexedSubscript")
285 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
288 case NSOrderedSet_replaceObjectAtIndexWithObject: {
289 IdentifierInfo *KeyIdents[] = {
290 &Ctx.Idents.get("replaceObjectAtIndex"),
291 &Ctx.Idents.get("withObject")
293 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
297 return (NSSetSelectors[MK] = Sel);
300 return NSSetSelectors[MK];
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))
314 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
315 bool Instance) const {
316 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
318 "numberWithUnsignedChar",
320 "numberWithUnsignedShort",
322 "numberWithUnsignedInt",
324 "numberWithUnsignedLong",
325 "numberWithLongLong",
326 "numberWithUnsignedLongLong",
331 "numberWithUnsignedInteger"
333 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
335 "initWithUnsignedChar",
337 "initWithUnsignedShort",
339 "initWithUnsignedInt",
341 "initWithUnsignedLong",
343 "initWithUnsignedLongLong",
348 "initWithUnsignedInteger"
354 Sels = NSNumberInstanceSelectors;
355 Names = InstanceSelectorName;
357 Sels = NSNumberClassSelectors;
358 Names = ClassSelectorName;
361 if (Sels[MK].isNull())
362 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
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))
377 Optional<NSAPI::NSNumberLiteralMethodKind>
378 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
379 const BuiltinType *BT = T->getAs<BuiltinType>();
383 const TypedefType *TDT = T->getAs<TypedefType>();
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;
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;
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::NullPtr:
460 case BuiltinType::ObjCClass:
461 case BuiltinType::ObjCId:
462 case BuiltinType::ObjCSel:
463 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
464 case BuiltinType::Id:
465 #include "clang/Basic/OpenCLImageTypes.def"
466 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
467 case BuiltinType::Id:
468 #include "clang/Basic/OpenCLExtensionTypes.def"
469 case BuiltinType::OCLSampler:
470 case BuiltinType::OCLEvent:
471 case BuiltinType::OCLClkEvent:
472 case BuiltinType::OCLQueue:
473 case BuiltinType::OCLReserveID:
474 #define SVE_TYPE(Name, Id, SingletonId) \
475 case BuiltinType::Id:
476 #include "clang/Basic/AArch64SVEACLETypes.def"
477 case BuiltinType::BoundMember:
478 case BuiltinType::Dependent:
479 case BuiltinType::Overload:
480 case BuiltinType::UnknownAny:
481 case BuiltinType::ARCUnbridgedCast:
482 case BuiltinType::Half:
483 case BuiltinType::PseudoObject:
484 case BuiltinType::BuiltinFn:
485 case BuiltinType::OMPArraySection:
492 /// Returns true if \param T is a typedef of "BOOL" in objective-c.
493 bool NSAPI::isObjCBOOLType(QualType T) const {
494 return isObjCTypedef(T, "BOOL", BOOLId);
496 /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
497 bool NSAPI::isObjCNSIntegerType(QualType T) const {
498 return isObjCTypedef(T, "NSInteger", NSIntegerId);
500 /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
501 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
502 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
505 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
506 if (!Ctx.getLangOpts().ObjC || T.isNull())
509 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
510 StringRef NSIntegralResust =
511 llvm::StringSwitch<StringRef>(
512 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
513 .Case("int8_t", "int8_t")
514 .Case("int16_t", "int16_t")
515 .Case("int32_t", "int32_t")
516 .Case("NSInteger", "NSInteger")
517 .Case("int64_t", "int64_t")
518 .Case("uint8_t", "uint8_t")
519 .Case("uint16_t", "uint16_t")
520 .Case("uint32_t", "uint32_t")
521 .Case("NSUInteger", "NSUInteger")
522 .Case("uint64_t", "uint64_t")
523 .Default(StringRef());
524 if (!NSIntegralResust.empty())
525 return NSIntegralResust;
531 bool NSAPI::isMacroDefined(StringRef Id) const {
532 // FIXME: Check whether the relevant module macros are visible.
533 return Ctx.Idents.get(Id).hasMacroDefinition();
536 bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
537 NSClassIdKindKind NSClassKind) const {
538 if (!InterfaceDecl) {
542 IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
544 bool IsSubclass = false;
546 IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
551 } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
556 bool NSAPI::isObjCTypedef(QualType T,
557 StringRef name, IdentifierInfo *&II) const {
558 if (!Ctx.getLangOpts().ObjC)
564 II = &Ctx.Idents.get(name);
566 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
567 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
575 bool NSAPI::isObjCEnumerator(const Expr *E,
576 StringRef name, IdentifierInfo *&II) const {
577 if (!Ctx.getLangOpts().ObjC)
583 II = &Ctx.Idents.get(name);
585 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
586 if (const EnumConstantDecl *
587 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
588 return EnumD->getIdentifier() == II;
593 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
594 Selector &Sel) const {
596 SmallVector<IdentifierInfo *, 4> Idents;
597 for (ArrayRef<StringRef>::const_iterator
598 I = Ids.begin(), E = Ids.end(); I != E; ++I)
599 Idents.push_back(&Ctx.Idents.get(*I));
600 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
605 Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
607 IdentifierInfo *Ident = &Ctx.Idents.get(Id);
608 Sel = Ctx.Selectors.getSelector(0, &Ident);