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"
16 using namespace clang
;
18 NSAPI::NSAPI(ASTContext
&ctx
)
19 : Ctx(ctx
), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
20 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
21 NSUTF8StringEncodingId(nullptr) {}
23 IdentifierInfo
*NSAPI::getNSClassId(NSClassIdKindKind K
) const {
24 static const char *ClassName
[NumClassIds
] = {
30 "NSMutableDictionary",
33 "NSMutableOrderedSet",
38 return (ClassIds
[K
] = &Ctx
.Idents
.get(ClassName
[K
]));
43 Selector
NSAPI::getNSStringSelector(NSStringMethodKind MK
) const {
44 if (NSStringSelectors
[MK
].isNull()) {
47 case NSStr_stringWithString
:
48 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("stringWithString"));
50 case NSStr_stringWithUTF8String
:
51 Sel
= Ctx
.Selectors
.getUnarySelector(
52 &Ctx
.Idents
.get("stringWithUTF8String"));
54 case NSStr_initWithUTF8String
:
55 Sel
= Ctx
.Selectors
.getUnarySelector(
56 &Ctx
.Idents
.get("initWithUTF8String"));
58 case NSStr_stringWithCStringEncoding
: {
59 IdentifierInfo
*KeyIdents
[] = {
60 &Ctx
.Idents
.get("stringWithCString"),
61 &Ctx
.Idents
.get("encoding")
63 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
66 case NSStr_stringWithCString
:
67 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("stringWithCString"));
69 case NSStr_initWithString
:
70 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithString"));
73 return (NSStringSelectors
[MK
] = Sel
);
76 return NSStringSelectors
[MK
];
79 Selector
NSAPI::getNSArraySelector(NSArrayMethodKind MK
) const {
80 if (NSArraySelectors
[MK
].isNull()) {
84 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("array"));
86 case NSArr_arrayWithArray
:
87 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithArray"));
89 case NSArr_arrayWithObject
:
90 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObject"));
92 case NSArr_arrayWithObjects
:
93 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObjects"));
95 case NSArr_arrayWithObjectsCount
: {
96 IdentifierInfo
*KeyIdents
[] = {
97 &Ctx
.Idents
.get("arrayWithObjects"),
98 &Ctx
.Idents
.get("count")
100 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
103 case NSArr_initWithArray
:
104 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithArray"));
106 case NSArr_initWithObjects
:
107 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithObjects"));
109 case NSArr_objectAtIndex
:
110 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectAtIndex"));
112 case NSMutableArr_replaceObjectAtIndex
: {
113 IdentifierInfo
*KeyIdents
[] = {
114 &Ctx
.Idents
.get("replaceObjectAtIndex"),
115 &Ctx
.Idents
.get("withObject")
117 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
120 case NSMutableArr_addObject
:
121 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("addObject"));
123 case NSMutableArr_insertObjectAtIndex
: {
124 IdentifierInfo
*KeyIdents
[] = {
125 &Ctx
.Idents
.get("insertObject"),
126 &Ctx
.Idents
.get("atIndex")
128 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
131 case NSMutableArr_setObjectAtIndexedSubscript
: {
132 IdentifierInfo
*KeyIdents
[] = {
133 &Ctx
.Idents
.get("setObject"),
134 &Ctx
.Idents
.get("atIndexedSubscript")
136 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
140 return (NSArraySelectors
[MK
] = Sel
);
143 return NSArraySelectors
[MK
];
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
))
157 Selector
NSAPI::getNSDictionarySelector(
158 NSDictionaryMethodKind MK
) const {
159 if (NSDictionarySelectors
[MK
].isNull()) {
162 case NSDict_dictionary
:
163 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("dictionary"));
165 case NSDict_dictionaryWithDictionary
:
166 Sel
= Ctx
.Selectors
.getUnarySelector(
167 &Ctx
.Idents
.get("dictionaryWithDictionary"));
169 case NSDict_dictionaryWithObjectForKey
: {
170 IdentifierInfo
*KeyIdents
[] = {
171 &Ctx
.Idents
.get("dictionaryWithObject"),
172 &Ctx
.Idents
.get("forKey")
174 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
177 case NSDict_dictionaryWithObjectsForKeys
: {
178 IdentifierInfo
*KeyIdents
[] = {
179 &Ctx
.Idents
.get("dictionaryWithObjects"),
180 &Ctx
.Idents
.get("forKeys")
182 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
185 case NSDict_dictionaryWithObjectsForKeysCount
: {
186 IdentifierInfo
*KeyIdents
[] = {
187 &Ctx
.Idents
.get("dictionaryWithObjects"),
188 &Ctx
.Idents
.get("forKeys"),
189 &Ctx
.Idents
.get("count")
191 Sel
= Ctx
.Selectors
.getSelector(3, KeyIdents
);
194 case NSDict_dictionaryWithObjectsAndKeys
:
195 Sel
= Ctx
.Selectors
.getUnarySelector(
196 &Ctx
.Idents
.get("dictionaryWithObjectsAndKeys"));
198 case NSDict_initWithDictionary
:
199 Sel
= Ctx
.Selectors
.getUnarySelector(
200 &Ctx
.Idents
.get("initWithDictionary"));
202 case NSDict_initWithObjectsAndKeys
:
203 Sel
= Ctx
.Selectors
.getUnarySelector(
204 &Ctx
.Idents
.get("initWithObjectsAndKeys"));
206 case NSDict_initWithObjectsForKeys
: {
207 IdentifierInfo
*KeyIdents
[] = {
208 &Ctx
.Idents
.get("initWithObjects"),
209 &Ctx
.Idents
.get("forKeys")
211 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
214 case NSDict_objectForKey
:
215 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectForKey"));
217 case NSMutableDict_setObjectForKey
: {
218 IdentifierInfo
*KeyIdents
[] = {
219 &Ctx
.Idents
.get("setObject"),
220 &Ctx
.Idents
.get("forKey")
222 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
225 case NSMutableDict_setObjectForKeyedSubscript
: {
226 IdentifierInfo
*KeyIdents
[] = {
227 &Ctx
.Idents
.get("setObject"),
228 &Ctx
.Idents
.get("forKeyedSubscript")
230 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
233 case NSMutableDict_setValueForKey
: {
234 IdentifierInfo
*KeyIdents
[] = {
235 &Ctx
.Idents
.get("setValue"),
236 &Ctx
.Idents
.get("forKey")
238 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
242 return (NSDictionarySelectors
[MK
] = Sel
);
245 return NSDictionarySelectors
[MK
];
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
))
259 Selector
NSAPI::getNSSetSelector(NSSetMethodKind MK
) const {
260 if (NSSetSelectors
[MK
].isNull()) {
263 case NSMutableSet_addObject
:
264 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("addObject"));
266 case NSOrderedSet_insertObjectAtIndex
: {
267 IdentifierInfo
*KeyIdents
[] = {
268 &Ctx
.Idents
.get("insertObject"),
269 &Ctx
.Idents
.get("atIndex")
271 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
274 case NSOrderedSet_setObjectAtIndex
: {
275 IdentifierInfo
*KeyIdents
[] = {
276 &Ctx
.Idents
.get("setObject"),
277 &Ctx
.Idents
.get("atIndex")
279 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
282 case NSOrderedSet_setObjectAtIndexedSubscript
: {
283 IdentifierInfo
*KeyIdents
[] = {
284 &Ctx
.Idents
.get("setObject"),
285 &Ctx
.Idents
.get("atIndexedSubscript")
287 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
290 case NSOrderedSet_replaceObjectAtIndexWithObject
: {
291 IdentifierInfo
*KeyIdents
[] = {
292 &Ctx
.Idents
.get("replaceObjectAtIndex"),
293 &Ctx
.Idents
.get("withObject")
295 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
299 return (NSSetSelectors
[MK
] = Sel
);
302 return NSSetSelectors
[MK
];
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
))
315 Selector
NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK
,
316 bool Instance
) const {
317 static const char *ClassSelectorName
[NumNSNumberLiteralMethods
] = {
319 "numberWithUnsignedChar",
321 "numberWithUnsignedShort",
323 "numberWithUnsignedInt",
325 "numberWithUnsignedLong",
326 "numberWithLongLong",
327 "numberWithUnsignedLongLong",
332 "numberWithUnsignedInteger"
334 static const char *InstanceSelectorName
[NumNSNumberLiteralMethods
] = {
336 "initWithUnsignedChar",
338 "initWithUnsignedShort",
340 "initWithUnsignedInt",
342 "initWithUnsignedLong",
344 "initWithUnsignedLongLong",
349 "initWithUnsignedInteger"
355 Sels
= NSNumberInstanceSelectors
;
356 Names
= InstanceSelectorName
;
358 Sels
= NSNumberClassSelectors
;
359 Names
= ClassSelectorName
;
362 if (Sels
[MK
].isNull())
363 Sels
[MK
] = Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get(Names
[MK
]));
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
))
378 std::optional
<NSAPI::NSNumberLiteralMethodKind
>
379 NSAPI::getNSNumberFactoryMethodKind(QualType T
) const {
380 const BuiltinType
*BT
= T
->getAs
<BuiltinType
>();
384 const TypedefType
*TDT
= T
->getAs
<TypedefType
>();
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
;
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
;
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 case BuiltinType::BoundMember
:
485 case BuiltinType::Dependent
:
486 case BuiltinType::Overload
:
487 case BuiltinType::UnknownAny
:
488 case BuiltinType::ARCUnbridgedCast
:
489 case BuiltinType::Half
:
490 case BuiltinType::PseudoObject
:
491 case BuiltinType::BuiltinFn
:
492 case BuiltinType::IncompleteMatrixIdx
:
493 case BuiltinType::OMPArraySection
:
494 case BuiltinType::OMPArrayShaping
:
495 case BuiltinType::OMPIterator
:
496 case BuiltinType::BFloat16
:
503 /// Returns true if \param T is a typedef of "BOOL" in objective-c.
504 bool NSAPI::isObjCBOOLType(QualType T
) const {
505 return isObjCTypedef(T
, "BOOL", BOOLId
);
507 /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
508 bool NSAPI::isObjCNSIntegerType(QualType T
) const {
509 return isObjCTypedef(T
, "NSInteger", NSIntegerId
);
511 /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
512 bool NSAPI::isObjCNSUIntegerType(QualType T
) const {
513 return isObjCTypedef(T
, "NSUInteger", NSUIntegerId
);
516 StringRef
NSAPI::GetNSIntegralKind(QualType T
) const {
517 if (!Ctx
.getLangOpts().ObjC
|| T
.isNull())
520 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
521 StringRef NSIntegralResust
=
522 llvm::StringSwitch
<StringRef
>(
523 TDT
->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
524 .Case("int8_t", "int8_t")
525 .Case("int16_t", "int16_t")
526 .Case("int32_t", "int32_t")
527 .Case("NSInteger", "NSInteger")
528 .Case("int64_t", "int64_t")
529 .Case("uint8_t", "uint8_t")
530 .Case("uint16_t", "uint16_t")
531 .Case("uint32_t", "uint32_t")
532 .Case("NSUInteger", "NSUInteger")
533 .Case("uint64_t", "uint64_t")
534 .Default(StringRef());
535 if (!NSIntegralResust
.empty())
536 return NSIntegralResust
;
542 bool NSAPI::isMacroDefined(StringRef Id
) const {
543 // FIXME: Check whether the relevant module macros are visible.
544 return Ctx
.Idents
.get(Id
).hasMacroDefinition();
547 bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl
*InterfaceDecl
,
548 NSClassIdKindKind NSClassKind
) const {
549 if (!InterfaceDecl
) {
553 IdentifierInfo
*NSClassID
= getNSClassId(NSClassKind
);
555 bool IsSubclass
= false;
557 IsSubclass
= NSClassID
== InterfaceDecl
->getIdentifier();
562 } while ((InterfaceDecl
= InterfaceDecl
->getSuperClass()));
567 bool NSAPI::isObjCTypedef(QualType T
,
568 StringRef name
, IdentifierInfo
*&II
) const {
569 if (!Ctx
.getLangOpts().ObjC
)
575 II
= &Ctx
.Idents
.get(name
);
577 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
578 if (TDT
->getDecl()->getDeclName().getAsIdentifierInfo() == II
)
586 bool NSAPI::isObjCEnumerator(const Expr
*E
,
587 StringRef name
, IdentifierInfo
*&II
) const {
588 if (!Ctx
.getLangOpts().ObjC
)
594 II
= &Ctx
.Idents
.get(name
);
596 if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
->IgnoreParenImpCasts()))
597 if (const EnumConstantDecl
*
598 EnumD
= dyn_cast_or_null
<EnumConstantDecl
>(DRE
->getDecl()))
599 return EnumD
->getIdentifier() == II
;
604 Selector
NSAPI::getOrInitSelector(ArrayRef
<StringRef
> Ids
,
605 Selector
&Sel
) const {
607 SmallVector
<IdentifierInfo
*, 4> Idents
;
608 for (ArrayRef
<StringRef
>::const_iterator
609 I
= Ids
.begin(), E
= Ids
.end(); I
!= E
; ++I
)
610 Idents
.push_back(&Ctx
.Idents
.get(*I
));
611 Sel
= Ctx
.Selectors
.getSelector(Idents
.size(), Idents
.data());
616 Selector
NSAPI::getOrInitNullarySelector(StringRef Id
, Selector
&Sel
) const {
618 IdentifierInfo
*Ident
= &Ctx
.Idents
.get(Id
);
619 Sel
= Ctx
.Selectors
.getSelector(0, &Ident
);