[clang] Handle __declspec() attributes in using
[llvm-project.git] / clang / lib / AST / NSAPI.cpp
blob3621a2eaa57389bd2e3bb0cb7b068f0774bb3d37
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 //===----------------------------------------------------------------------===//
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 #include <optional>
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] = {
25 "NSObject",
26 "NSString",
27 "NSArray",
28 "NSMutableArray",
29 "NSDictionary",
30 "NSMutableDictionary",
31 "NSNumber",
32 "NSMutableSet",
33 "NSMutableOrderedSet",
34 "NSValue"
37 if (!ClassIds[K])
38 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
40 return ClassIds[K];
43 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
44 if (NSStringSelectors[MK].isNull()) {
45 Selector Sel;
46 switch (MK) {
47 case NSStr_stringWithString:
48 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
49 break;
50 case NSStr_stringWithUTF8String:
51 Sel = Ctx.Selectors.getUnarySelector(
52 &Ctx.Idents.get("stringWithUTF8String"));
53 break;
54 case NSStr_initWithUTF8String:
55 Sel = Ctx.Selectors.getUnarySelector(
56 &Ctx.Idents.get("initWithUTF8String"));
57 break;
58 case NSStr_stringWithCStringEncoding: {
59 IdentifierInfo *KeyIdents[] = {
60 &Ctx.Idents.get("stringWithCString"),
61 &Ctx.Idents.get("encoding")
63 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
64 break;
66 case NSStr_stringWithCString:
67 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
68 break;
69 case NSStr_initWithString:
70 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
71 break;
73 return (NSStringSelectors[MK] = Sel);
76 return NSStringSelectors[MK];
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")
100 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
101 break;
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")
117 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
118 break;
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")
128 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
129 break;
131 case NSMutableArr_setObjectAtIndexedSubscript: {
132 IdentifierInfo *KeyIdents[] = {
133 &Ctx.Idents.get("setObject"),
134 &Ctx.Idents.get("atIndexedSubscript")
136 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
137 break;
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))
151 return MK;
154 return std::nullopt;
157 Selector NSAPI::getNSDictionarySelector(
158 NSDictionaryMethodKind MK) const {
159 if (NSDictionarySelectors[MK].isNull()) {
160 Selector Sel;
161 switch (MK) {
162 case NSDict_dictionary:
163 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
164 break;
165 case NSDict_dictionaryWithDictionary:
166 Sel = Ctx.Selectors.getUnarySelector(
167 &Ctx.Idents.get("dictionaryWithDictionary"));
168 break;
169 case NSDict_dictionaryWithObjectForKey: {
170 IdentifierInfo *KeyIdents[] = {
171 &Ctx.Idents.get("dictionaryWithObject"),
172 &Ctx.Idents.get("forKey")
174 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
175 break;
177 case NSDict_dictionaryWithObjectsForKeys: {
178 IdentifierInfo *KeyIdents[] = {
179 &Ctx.Idents.get("dictionaryWithObjects"),
180 &Ctx.Idents.get("forKeys")
182 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
183 break;
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);
192 break;
194 case NSDict_dictionaryWithObjectsAndKeys:
195 Sel = Ctx.Selectors.getUnarySelector(
196 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
197 break;
198 case NSDict_initWithDictionary:
199 Sel = Ctx.Selectors.getUnarySelector(
200 &Ctx.Idents.get("initWithDictionary"));
201 break;
202 case NSDict_initWithObjectsAndKeys:
203 Sel = Ctx.Selectors.getUnarySelector(
204 &Ctx.Idents.get("initWithObjectsAndKeys"));
205 break;
206 case NSDict_initWithObjectsForKeys: {
207 IdentifierInfo *KeyIdents[] = {
208 &Ctx.Idents.get("initWithObjects"),
209 &Ctx.Idents.get("forKeys")
211 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
212 break;
214 case NSDict_objectForKey:
215 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
216 break;
217 case NSMutableDict_setObjectForKey: {
218 IdentifierInfo *KeyIdents[] = {
219 &Ctx.Idents.get("setObject"),
220 &Ctx.Idents.get("forKey")
222 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
223 break;
225 case NSMutableDict_setObjectForKeyedSubscript: {
226 IdentifierInfo *KeyIdents[] = {
227 &Ctx.Idents.get("setObject"),
228 &Ctx.Idents.get("forKeyedSubscript")
230 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
231 break;
233 case NSMutableDict_setValueForKey: {
234 IdentifierInfo *KeyIdents[] = {
235 &Ctx.Idents.get("setValue"),
236 &Ctx.Idents.get("forKey")
238 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
239 break;
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))
253 return MK;
256 return std::nullopt;
259 Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
260 if (NSSetSelectors[MK].isNull()) {
261 Selector Sel;
262 switch (MK) {
263 case NSMutableSet_addObject:
264 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
265 break;
266 case NSOrderedSet_insertObjectAtIndex: {
267 IdentifierInfo *KeyIdents[] = {
268 &Ctx.Idents.get("insertObject"),
269 &Ctx.Idents.get("atIndex")
271 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
272 break;
274 case NSOrderedSet_setObjectAtIndex: {
275 IdentifierInfo *KeyIdents[] = {
276 &Ctx.Idents.get("setObject"),
277 &Ctx.Idents.get("atIndex")
279 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
280 break;
282 case NSOrderedSet_setObjectAtIndexedSubscript: {
283 IdentifierInfo *KeyIdents[] = {
284 &Ctx.Idents.get("setObject"),
285 &Ctx.Idents.get("atIndexedSubscript")
287 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
288 break;
290 case NSOrderedSet_replaceObjectAtIndexWithObject: {
291 IdentifierInfo *KeyIdents[] = {
292 &Ctx.Idents.get("replaceObjectAtIndex"),
293 &Ctx.Idents.get("withObject")
295 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
296 break;
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))
309 return MK;
312 return std::nullopt;
315 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
316 bool Instance) const {
317 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
318 "numberWithChar",
319 "numberWithUnsignedChar",
320 "numberWithShort",
321 "numberWithUnsignedShort",
322 "numberWithInt",
323 "numberWithUnsignedInt",
324 "numberWithLong",
325 "numberWithUnsignedLong",
326 "numberWithLongLong",
327 "numberWithUnsignedLongLong",
328 "numberWithFloat",
329 "numberWithDouble",
330 "numberWithBool",
331 "numberWithInteger",
332 "numberWithUnsignedInteger"
334 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
335 "initWithChar",
336 "initWithUnsignedChar",
337 "initWithShort",
338 "initWithUnsignedShort",
339 "initWithInt",
340 "initWithUnsignedInt",
341 "initWithLong",
342 "initWithUnsignedLong",
343 "initWithLongLong",
344 "initWithUnsignedLongLong",
345 "initWithFloat",
346 "initWithDouble",
347 "initWithBool",
348 "initWithInteger",
349 "initWithUnsignedInteger"
352 Selector *Sels;
353 const char **Names;
354 if (Instance) {
355 Sels = NSNumberInstanceSelectors;
356 Names = InstanceSelectorName;
357 } else {
358 Sels = NSNumberClassSelectors;
359 Names = ClassSelectorName;
362 if (Sels[MK].isNull())
363 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
364 return Sels[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))
372 return MK;
375 return std::nullopt;
378 std::optional<NSAPI::NSNumberLiteralMethodKind>
379 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
380 const BuiltinType *BT = T->getAs<BuiltinType>();
381 if (!BT)
382 return std::nullopt;
384 const TypedefType *TDT = T->getAs<TypedefType>();
385 if (TDT) {
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:
497 break;
500 return std::nullopt;
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())
518 return StringRef();
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;
537 T = TDT->desugar();
539 return StringRef();
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) {
550 return false;
553 IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
555 bool IsSubclass = false;
556 do {
557 IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
559 if (IsSubclass) {
560 break;
562 } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
564 return IsSubclass;
567 bool NSAPI::isObjCTypedef(QualType T,
568 StringRef name, IdentifierInfo *&II) const {
569 if (!Ctx.getLangOpts().ObjC)
570 return false;
571 if (T.isNull())
572 return false;
574 if (!II)
575 II = &Ctx.Idents.get(name);
577 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
578 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
579 return true;
580 T = TDT->desugar();
583 return false;
586 bool NSAPI::isObjCEnumerator(const Expr *E,
587 StringRef name, IdentifierInfo *&II) const {
588 if (!Ctx.getLangOpts().ObjC)
589 return false;
590 if (!E)
591 return false;
593 if (!II)
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;
601 return false;
604 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
605 Selector &Sel) const {
606 if (Sel.isNull()) {
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());
613 return Sel;
616 Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
617 if (Sel.isNull()) {
618 IdentifierInfo *Ident = &Ctx.Idents.get(Id);
619 Sel = Ctx.Selectors.getSelector(0, &Ident);
621 return Sel;