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 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("stringWithCString"),
60 &Ctx
.Idents
.get("encoding")};
61 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
64 case NSStr_stringWithCString
:
65 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("stringWithCString"));
67 case NSStr_initWithString
:
68 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithString"));
71 return (NSStringSelectors
[MK
] = Sel
);
74 return NSStringSelectors
[MK
];
77 Selector
NSAPI::getNSArraySelector(NSArrayMethodKind MK
) const {
78 if (NSArraySelectors
[MK
].isNull()) {
82 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("array"));
84 case NSArr_arrayWithArray
:
85 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithArray"));
87 case NSArr_arrayWithObject
:
88 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObject"));
90 case NSArr_arrayWithObjects
:
91 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("arrayWithObjects"));
93 case NSArr_arrayWithObjectsCount
: {
94 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("arrayWithObjects"),
95 &Ctx
.Idents
.get("count")};
96 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
99 case NSArr_initWithArray
:
100 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithArray"));
102 case NSArr_initWithObjects
:
103 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("initWithObjects"));
105 case NSArr_objectAtIndex
:
106 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectAtIndex"));
108 case NSMutableArr_replaceObjectAtIndex
: {
109 const IdentifierInfo
*KeyIdents
[] = {
110 &Ctx
.Idents
.get("replaceObjectAtIndex"),
111 &Ctx
.Idents
.get("withObject")};
112 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
115 case NSMutableArr_addObject
:
116 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("addObject"));
118 case NSMutableArr_insertObjectAtIndex
: {
119 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("insertObject"),
120 &Ctx
.Idents
.get("atIndex")};
121 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
124 case NSMutableArr_setObjectAtIndexedSubscript
: {
125 const IdentifierInfo
*KeyIdents
[] = {
126 &Ctx
.Idents
.get("setObject"), &Ctx
.Idents
.get("atIndexedSubscript")};
127 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
131 return (NSArraySelectors
[MK
] = Sel
);
134 return NSArraySelectors
[MK
];
137 std::optional
<NSAPI::NSArrayMethodKind
>
138 NSAPI::getNSArrayMethodKind(Selector Sel
) {
139 for (unsigned i
= 0; i
!= NumNSArrayMethods
; ++i
) {
140 NSArrayMethodKind MK
= NSArrayMethodKind(i
);
141 if (Sel
== getNSArraySelector(MK
))
148 Selector
NSAPI::getNSDictionarySelector(
149 NSDictionaryMethodKind MK
) const {
150 if (NSDictionarySelectors
[MK
].isNull()) {
153 case NSDict_dictionary
:
154 Sel
= Ctx
.Selectors
.getNullarySelector(&Ctx
.Idents
.get("dictionary"));
156 case NSDict_dictionaryWithDictionary
:
157 Sel
= Ctx
.Selectors
.getUnarySelector(
158 &Ctx
.Idents
.get("dictionaryWithDictionary"));
160 case NSDict_dictionaryWithObjectForKey
: {
161 const IdentifierInfo
*KeyIdents
[] = {
162 &Ctx
.Idents
.get("dictionaryWithObject"), &Ctx
.Idents
.get("forKey")};
163 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
166 case NSDict_dictionaryWithObjectsForKeys
: {
167 const IdentifierInfo
*KeyIdents
[] = {
168 &Ctx
.Idents
.get("dictionaryWithObjects"), &Ctx
.Idents
.get("forKeys")};
169 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
172 case NSDict_dictionaryWithObjectsForKeysCount
: {
173 const IdentifierInfo
*KeyIdents
[] = {
174 &Ctx
.Idents
.get("dictionaryWithObjects"), &Ctx
.Idents
.get("forKeys"),
175 &Ctx
.Idents
.get("count")};
176 Sel
= Ctx
.Selectors
.getSelector(3, KeyIdents
);
179 case NSDict_dictionaryWithObjectsAndKeys
:
180 Sel
= Ctx
.Selectors
.getUnarySelector(
181 &Ctx
.Idents
.get("dictionaryWithObjectsAndKeys"));
183 case NSDict_initWithDictionary
:
184 Sel
= Ctx
.Selectors
.getUnarySelector(
185 &Ctx
.Idents
.get("initWithDictionary"));
187 case NSDict_initWithObjectsAndKeys
:
188 Sel
= Ctx
.Selectors
.getUnarySelector(
189 &Ctx
.Idents
.get("initWithObjectsAndKeys"));
191 case NSDict_initWithObjectsForKeys
: {
192 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("initWithObjects"),
193 &Ctx
.Idents
.get("forKeys")};
194 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
197 case NSDict_objectForKey
:
198 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("objectForKey"));
200 case NSMutableDict_setObjectForKey
: {
201 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("setObject"),
202 &Ctx
.Idents
.get("forKey")};
203 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
206 case NSMutableDict_setObjectForKeyedSubscript
: {
207 const IdentifierInfo
*KeyIdents
[] = {
208 &Ctx
.Idents
.get("setObject"), &Ctx
.Idents
.get("forKeyedSubscript")};
209 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
212 case NSMutableDict_setValueForKey
: {
213 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("setValue"),
214 &Ctx
.Idents
.get("forKey")};
215 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
219 return (NSDictionarySelectors
[MK
] = Sel
);
222 return NSDictionarySelectors
[MK
];
225 std::optional
<NSAPI::NSDictionaryMethodKind
>
226 NSAPI::getNSDictionaryMethodKind(Selector Sel
) {
227 for (unsigned i
= 0; i
!= NumNSDictionaryMethods
; ++i
) {
228 NSDictionaryMethodKind MK
= NSDictionaryMethodKind(i
);
229 if (Sel
== getNSDictionarySelector(MK
))
236 Selector
NSAPI::getNSSetSelector(NSSetMethodKind MK
) const {
237 if (NSSetSelectors
[MK
].isNull()) {
240 case NSMutableSet_addObject
:
241 Sel
= Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get("addObject"));
243 case NSOrderedSet_insertObjectAtIndex
: {
244 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("insertObject"),
245 &Ctx
.Idents
.get("atIndex")};
246 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
249 case NSOrderedSet_setObjectAtIndex
: {
250 const IdentifierInfo
*KeyIdents
[] = {&Ctx
.Idents
.get("setObject"),
251 &Ctx
.Idents
.get("atIndex")};
252 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
255 case NSOrderedSet_setObjectAtIndexedSubscript
: {
256 const IdentifierInfo
*KeyIdents
[] = {
257 &Ctx
.Idents
.get("setObject"), &Ctx
.Idents
.get("atIndexedSubscript")};
258 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
261 case NSOrderedSet_replaceObjectAtIndexWithObject
: {
262 const IdentifierInfo
*KeyIdents
[] = {
263 &Ctx
.Idents
.get("replaceObjectAtIndex"),
264 &Ctx
.Idents
.get("withObject")};
265 Sel
= Ctx
.Selectors
.getSelector(2, KeyIdents
);
269 return (NSSetSelectors
[MK
] = Sel
);
272 return NSSetSelectors
[MK
];
275 std::optional
<NSAPI::NSSetMethodKind
> NSAPI::getNSSetMethodKind(Selector Sel
) {
276 for (unsigned i
= 0; i
!= NumNSSetMethods
; ++i
) {
277 NSSetMethodKind MK
= NSSetMethodKind(i
);
278 if (Sel
== getNSSetSelector(MK
))
285 Selector
NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK
,
286 bool Instance
) const {
287 static const char *ClassSelectorName
[NumNSNumberLiteralMethods
] = {
289 "numberWithUnsignedChar",
291 "numberWithUnsignedShort",
293 "numberWithUnsignedInt",
295 "numberWithUnsignedLong",
296 "numberWithLongLong",
297 "numberWithUnsignedLongLong",
302 "numberWithUnsignedInteger"
304 static const char *InstanceSelectorName
[NumNSNumberLiteralMethods
] = {
306 "initWithUnsignedChar",
308 "initWithUnsignedShort",
310 "initWithUnsignedInt",
312 "initWithUnsignedLong",
314 "initWithUnsignedLongLong",
319 "initWithUnsignedInteger"
325 Sels
= NSNumberInstanceSelectors
;
326 Names
= InstanceSelectorName
;
328 Sels
= NSNumberClassSelectors
;
329 Names
= ClassSelectorName
;
332 if (Sels
[MK
].isNull())
333 Sels
[MK
] = Ctx
.Selectors
.getUnarySelector(&Ctx
.Idents
.get(Names
[MK
]));
337 std::optional
<NSAPI::NSNumberLiteralMethodKind
>
338 NSAPI::getNSNumberLiteralMethodKind(Selector Sel
) const {
339 for (unsigned i
= 0; i
!= NumNSNumberLiteralMethods
; ++i
) {
340 NSNumberLiteralMethodKind MK
= NSNumberLiteralMethodKind(i
);
341 if (isNSNumberLiteralSelector(MK
, Sel
))
348 std::optional
<NSAPI::NSNumberLiteralMethodKind
>
349 NSAPI::getNSNumberFactoryMethodKind(QualType T
) const {
350 const BuiltinType
*BT
= T
->getAs
<BuiltinType
>();
354 const TypedefType
*TDT
= T
->getAs
<TypedefType
>();
356 QualType TDTTy
= QualType(TDT
, 0);
357 if (isObjCBOOLType(TDTTy
))
358 return NSAPI::NSNumberWithBool
;
359 if (isObjCNSIntegerType(TDTTy
))
360 return NSAPI::NSNumberWithInteger
;
361 if (isObjCNSUIntegerType(TDTTy
))
362 return NSAPI::NSNumberWithUnsignedInteger
;
365 switch (BT
->getKind()) {
366 case BuiltinType::Char_S
:
367 case BuiltinType::SChar
:
368 return NSAPI::NSNumberWithChar
;
369 case BuiltinType::Char_U
:
370 case BuiltinType::UChar
:
371 return NSAPI::NSNumberWithUnsignedChar
;
372 case BuiltinType::Short
:
373 return NSAPI::NSNumberWithShort
;
374 case BuiltinType::UShort
:
375 return NSAPI::NSNumberWithUnsignedShort
;
376 case BuiltinType::Int
:
377 return NSAPI::NSNumberWithInt
;
378 case BuiltinType::UInt
:
379 return NSAPI::NSNumberWithUnsignedInt
;
380 case BuiltinType::Long
:
381 return NSAPI::NSNumberWithLong
;
382 case BuiltinType::ULong
:
383 return NSAPI::NSNumberWithUnsignedLong
;
384 case BuiltinType::LongLong
:
385 return NSAPI::NSNumberWithLongLong
;
386 case BuiltinType::ULongLong
:
387 return NSAPI::NSNumberWithUnsignedLongLong
;
388 case BuiltinType::Float
:
389 return NSAPI::NSNumberWithFloat
;
390 case BuiltinType::Double
:
391 return NSAPI::NSNumberWithDouble
;
392 case BuiltinType::Bool
:
393 return NSAPI::NSNumberWithBool
;
395 case BuiltinType::Void
:
396 case BuiltinType::WChar_U
:
397 case BuiltinType::WChar_S
:
398 case BuiltinType::Char8
:
399 case BuiltinType::Char16
:
400 case BuiltinType::Char32
:
401 case BuiltinType::Int128
:
402 case BuiltinType::LongDouble
:
403 case BuiltinType::ShortAccum
:
404 case BuiltinType::Accum
:
405 case BuiltinType::LongAccum
:
406 case BuiltinType::UShortAccum
:
407 case BuiltinType::UAccum
:
408 case BuiltinType::ULongAccum
:
409 case BuiltinType::ShortFract
:
410 case BuiltinType::Fract
:
411 case BuiltinType::LongFract
:
412 case BuiltinType::UShortFract
:
413 case BuiltinType::UFract
:
414 case BuiltinType::ULongFract
:
415 case BuiltinType::SatShortAccum
:
416 case BuiltinType::SatAccum
:
417 case BuiltinType::SatLongAccum
:
418 case BuiltinType::SatUShortAccum
:
419 case BuiltinType::SatUAccum
:
420 case BuiltinType::SatULongAccum
:
421 case BuiltinType::SatShortFract
:
422 case BuiltinType::SatFract
:
423 case BuiltinType::SatLongFract
:
424 case BuiltinType::SatUShortFract
:
425 case BuiltinType::SatUFract
:
426 case BuiltinType::SatULongFract
:
427 case BuiltinType::UInt128
:
428 case BuiltinType::Float16
:
429 case BuiltinType::Float128
:
430 case BuiltinType::Ibm128
:
431 case BuiltinType::NullPtr
:
432 case BuiltinType::ObjCClass
:
433 case BuiltinType::ObjCId
:
434 case BuiltinType::ObjCSel
:
435 #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
436 case BuiltinType::Id:
437 #include "clang/Basic/OpenCLImageTypes.def"
438 #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
439 case BuiltinType::Id:
440 #include "clang/Basic/OpenCLExtensionTypes.def"
441 case BuiltinType::OCLSampler
:
442 case BuiltinType::OCLEvent
:
443 case BuiltinType::OCLClkEvent
:
444 case BuiltinType::OCLQueue
:
445 case BuiltinType::OCLReserveID
:
446 #define SVE_TYPE(Name, Id, SingletonId) \
447 case BuiltinType::Id:
448 #include "clang/Basic/AArch64SVEACLETypes.def"
449 #define PPC_VECTOR_TYPE(Name, Id, Size) \
450 case BuiltinType::Id:
451 #include "clang/Basic/PPCTypes.def"
452 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
453 #include "clang/Basic/RISCVVTypes.def"
454 #define WASM_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
455 #include "clang/Basic/WebAssemblyReferenceTypes.def"
456 #define AMDGPU_TYPE(Name, Id, SingletonId, Width, Align) case BuiltinType::Id:
457 #include "clang/Basic/AMDGPUTypes.def"
458 #define HLSL_INTANGIBLE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
459 #include "clang/Basic/HLSLIntangibleTypes.def"
460 case BuiltinType::BoundMember
:
461 case BuiltinType::UnresolvedTemplate
:
462 case BuiltinType::Dependent
:
463 case BuiltinType::Overload
:
464 case BuiltinType::UnknownAny
:
465 case BuiltinType::ARCUnbridgedCast
:
466 case BuiltinType::Half
:
467 case BuiltinType::PseudoObject
:
468 case BuiltinType::BuiltinFn
:
469 case BuiltinType::IncompleteMatrixIdx
:
470 case BuiltinType::ArraySection
:
471 case BuiltinType::OMPArrayShaping
:
472 case BuiltinType::OMPIterator
:
473 case BuiltinType::BFloat16
:
480 /// Returns true if \param T is a typedef of "BOOL" in objective-c.
481 bool NSAPI::isObjCBOOLType(QualType T
) const {
482 return isObjCTypedef(T
, "BOOL", BOOLId
);
484 /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
485 bool NSAPI::isObjCNSIntegerType(QualType T
) const {
486 return isObjCTypedef(T
, "NSInteger", NSIntegerId
);
488 /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
489 bool NSAPI::isObjCNSUIntegerType(QualType T
) const {
490 return isObjCTypedef(T
, "NSUInteger", NSUIntegerId
);
493 StringRef
NSAPI::GetNSIntegralKind(QualType T
) const {
494 if (!Ctx
.getLangOpts().ObjC
|| T
.isNull())
497 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
498 StringRef NSIntegralResust
=
499 llvm::StringSwitch
<StringRef
>(
500 TDT
->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
501 .Case("int8_t", "int8_t")
502 .Case("int16_t", "int16_t")
503 .Case("int32_t", "int32_t")
504 .Case("NSInteger", "NSInteger")
505 .Case("int64_t", "int64_t")
506 .Case("uint8_t", "uint8_t")
507 .Case("uint16_t", "uint16_t")
508 .Case("uint32_t", "uint32_t")
509 .Case("NSUInteger", "NSUInteger")
510 .Case("uint64_t", "uint64_t")
511 .Default(StringRef());
512 if (!NSIntegralResust
.empty())
513 return NSIntegralResust
;
519 bool NSAPI::isMacroDefined(StringRef Id
) const {
520 // FIXME: Check whether the relevant module macros are visible.
521 return Ctx
.Idents
.get(Id
).hasMacroDefinition();
524 bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl
*InterfaceDecl
,
525 NSClassIdKindKind NSClassKind
) const {
526 if (!InterfaceDecl
) {
530 IdentifierInfo
*NSClassID
= getNSClassId(NSClassKind
);
532 bool IsSubclass
= false;
534 IsSubclass
= NSClassID
== InterfaceDecl
->getIdentifier();
539 } while ((InterfaceDecl
= InterfaceDecl
->getSuperClass()));
544 bool NSAPI::isObjCTypedef(QualType T
,
545 StringRef name
, IdentifierInfo
*&II
) const {
546 if (!Ctx
.getLangOpts().ObjC
)
552 II
= &Ctx
.Idents
.get(name
);
554 while (const TypedefType
*TDT
= T
->getAs
<TypedefType
>()) {
555 if (TDT
->getDecl()->getDeclName().getAsIdentifierInfo() == II
)
563 bool NSAPI::isObjCEnumerator(const Expr
*E
,
564 StringRef name
, IdentifierInfo
*&II
) const {
565 if (!Ctx
.getLangOpts().ObjC
)
571 II
= &Ctx
.Idents
.get(name
);
573 if (const DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
->IgnoreParenImpCasts()))
574 if (const EnumConstantDecl
*
575 EnumD
= dyn_cast_or_null
<EnumConstantDecl
>(DRE
->getDecl()))
576 return EnumD
->getIdentifier() == II
;
581 Selector
NSAPI::getOrInitSelector(ArrayRef
<StringRef
> Ids
,
582 Selector
&Sel
) const {
584 SmallVector
<const IdentifierInfo
*, 4> Idents
;
585 for (ArrayRef
<StringRef
>::const_iterator
586 I
= Ids
.begin(), E
= Ids
.end(); I
!= E
; ++I
)
587 Idents
.push_back(&Ctx
.Idents
.get(*I
));
588 Sel
= Ctx
.Selectors
.getSelector(Idents
.size(), Idents
.data());
593 Selector
NSAPI::getOrInitNullarySelector(StringRef Id
, Selector
&Sel
) const {
595 const IdentifierInfo
*Ident
= &Ctx
.Idents
.get(Id
);
596 Sel
= Ctx
.Selectors
.getSelector(0, &Ident
);