106f32e7eSjoerg //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg 
906f32e7eSjoerg #include "clang/AST/NSAPI.h"
1006f32e7eSjoerg #include "clang/AST/ASTContext.h"
1106f32e7eSjoerg #include "clang/AST/DeclObjC.h"
1206f32e7eSjoerg #include "clang/AST/Expr.h"
1306f32e7eSjoerg #include "llvm/ADT/StringSwitch.h"
1406f32e7eSjoerg 
1506f32e7eSjoerg using namespace clang;
1606f32e7eSjoerg 
NSAPI(ASTContext & ctx)1706f32e7eSjoerg NSAPI::NSAPI(ASTContext &ctx)
1806f32e7eSjoerg   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
1906f32e7eSjoerg     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
2006f32e7eSjoerg     NSUTF8StringEncodingId(nullptr) {}
2106f32e7eSjoerg 
getNSClassId(NSClassIdKindKind K) const2206f32e7eSjoerg IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
2306f32e7eSjoerg   static const char *ClassName[NumClassIds] = {
2406f32e7eSjoerg     "NSObject",
2506f32e7eSjoerg     "NSString",
2606f32e7eSjoerg     "NSArray",
2706f32e7eSjoerg     "NSMutableArray",
2806f32e7eSjoerg     "NSDictionary",
2906f32e7eSjoerg     "NSMutableDictionary",
3006f32e7eSjoerg     "NSNumber",
3106f32e7eSjoerg     "NSMutableSet",
3206f32e7eSjoerg     "NSMutableOrderedSet",
3306f32e7eSjoerg     "NSValue"
3406f32e7eSjoerg   };
3506f32e7eSjoerg 
3606f32e7eSjoerg   if (!ClassIds[K])
3706f32e7eSjoerg     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
3806f32e7eSjoerg 
3906f32e7eSjoerg   return ClassIds[K];
4006f32e7eSjoerg }
4106f32e7eSjoerg 
getNSStringSelector(NSStringMethodKind MK) const4206f32e7eSjoerg Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
4306f32e7eSjoerg   if (NSStringSelectors[MK].isNull()) {
4406f32e7eSjoerg     Selector Sel;
4506f32e7eSjoerg     switch (MK) {
4606f32e7eSjoerg     case NSStr_stringWithString:
4706f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
4806f32e7eSjoerg       break;
4906f32e7eSjoerg     case NSStr_stringWithUTF8String:
5006f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
5106f32e7eSjoerg                                        &Ctx.Idents.get("stringWithUTF8String"));
5206f32e7eSjoerg       break;
5306f32e7eSjoerg     case NSStr_initWithUTF8String:
5406f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
5506f32e7eSjoerg                                        &Ctx.Idents.get("initWithUTF8String"));
5606f32e7eSjoerg       break;
5706f32e7eSjoerg     case NSStr_stringWithCStringEncoding: {
5806f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
5906f32e7eSjoerg         &Ctx.Idents.get("stringWithCString"),
6006f32e7eSjoerg         &Ctx.Idents.get("encoding")
6106f32e7eSjoerg       };
6206f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
6306f32e7eSjoerg       break;
6406f32e7eSjoerg     }
6506f32e7eSjoerg     case NSStr_stringWithCString:
6606f32e7eSjoerg       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
6706f32e7eSjoerg       break;
6806f32e7eSjoerg     case NSStr_initWithString:
6906f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
7006f32e7eSjoerg       break;
7106f32e7eSjoerg     }
7206f32e7eSjoerg     return (NSStringSelectors[MK] = Sel);
7306f32e7eSjoerg   }
7406f32e7eSjoerg 
7506f32e7eSjoerg   return NSStringSelectors[MK];
7606f32e7eSjoerg }
7706f32e7eSjoerg 
getNSArraySelector(NSArrayMethodKind MK) const7806f32e7eSjoerg Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
7906f32e7eSjoerg   if (NSArraySelectors[MK].isNull()) {
8006f32e7eSjoerg     Selector Sel;
8106f32e7eSjoerg     switch (MK) {
8206f32e7eSjoerg     case NSArr_array:
8306f32e7eSjoerg       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
8406f32e7eSjoerg       break;
8506f32e7eSjoerg     case NSArr_arrayWithArray:
8606f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
8706f32e7eSjoerg       break;
8806f32e7eSjoerg     case NSArr_arrayWithObject:
8906f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
9006f32e7eSjoerg       break;
9106f32e7eSjoerg     case NSArr_arrayWithObjects:
9206f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
9306f32e7eSjoerg       break;
9406f32e7eSjoerg     case NSArr_arrayWithObjectsCount: {
9506f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
9606f32e7eSjoerg         &Ctx.Idents.get("arrayWithObjects"),
9706f32e7eSjoerg         &Ctx.Idents.get("count")
9806f32e7eSjoerg       };
9906f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
10006f32e7eSjoerg       break;
10106f32e7eSjoerg     }
10206f32e7eSjoerg     case NSArr_initWithArray:
10306f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
10406f32e7eSjoerg       break;
10506f32e7eSjoerg     case NSArr_initWithObjects:
10606f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
10706f32e7eSjoerg       break;
10806f32e7eSjoerg     case NSArr_objectAtIndex:
10906f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
11006f32e7eSjoerg       break;
11106f32e7eSjoerg     case NSMutableArr_replaceObjectAtIndex: {
11206f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
11306f32e7eSjoerg         &Ctx.Idents.get("replaceObjectAtIndex"),
11406f32e7eSjoerg         &Ctx.Idents.get("withObject")
11506f32e7eSjoerg       };
11606f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
11706f32e7eSjoerg       break;
11806f32e7eSjoerg     }
11906f32e7eSjoerg     case NSMutableArr_addObject:
12006f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
12106f32e7eSjoerg       break;
12206f32e7eSjoerg     case NSMutableArr_insertObjectAtIndex: {
12306f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
12406f32e7eSjoerg         &Ctx.Idents.get("insertObject"),
12506f32e7eSjoerg         &Ctx.Idents.get("atIndex")
12606f32e7eSjoerg       };
12706f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
12806f32e7eSjoerg       break;
12906f32e7eSjoerg     }
13006f32e7eSjoerg     case NSMutableArr_setObjectAtIndexedSubscript: {
13106f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
13206f32e7eSjoerg         &Ctx.Idents.get("setObject"),
13306f32e7eSjoerg         &Ctx.Idents.get("atIndexedSubscript")
13406f32e7eSjoerg       };
13506f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
13606f32e7eSjoerg       break;
13706f32e7eSjoerg     }
13806f32e7eSjoerg     }
13906f32e7eSjoerg     return (NSArraySelectors[MK] = Sel);
14006f32e7eSjoerg   }
14106f32e7eSjoerg 
14206f32e7eSjoerg   return NSArraySelectors[MK];
14306f32e7eSjoerg }
14406f32e7eSjoerg 
getNSArrayMethodKind(Selector Sel)14506f32e7eSjoerg Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
14606f32e7eSjoerg   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
14706f32e7eSjoerg     NSArrayMethodKind MK = NSArrayMethodKind(i);
14806f32e7eSjoerg     if (Sel == getNSArraySelector(MK))
14906f32e7eSjoerg       return MK;
15006f32e7eSjoerg   }
15106f32e7eSjoerg 
15206f32e7eSjoerg   return None;
15306f32e7eSjoerg }
15406f32e7eSjoerg 
getNSDictionarySelector(NSDictionaryMethodKind MK) const15506f32e7eSjoerg Selector NSAPI::getNSDictionarySelector(
15606f32e7eSjoerg                                        NSDictionaryMethodKind MK) const {
15706f32e7eSjoerg   if (NSDictionarySelectors[MK].isNull()) {
15806f32e7eSjoerg     Selector Sel;
15906f32e7eSjoerg     switch (MK) {
16006f32e7eSjoerg     case NSDict_dictionary:
16106f32e7eSjoerg       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
16206f32e7eSjoerg       break;
16306f32e7eSjoerg     case NSDict_dictionaryWithDictionary:
16406f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
16506f32e7eSjoerg                                    &Ctx.Idents.get("dictionaryWithDictionary"));
16606f32e7eSjoerg       break;
16706f32e7eSjoerg     case NSDict_dictionaryWithObjectForKey: {
16806f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
16906f32e7eSjoerg         &Ctx.Idents.get("dictionaryWithObject"),
17006f32e7eSjoerg         &Ctx.Idents.get("forKey")
17106f32e7eSjoerg       };
17206f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
17306f32e7eSjoerg       break;
17406f32e7eSjoerg     }
17506f32e7eSjoerg     case NSDict_dictionaryWithObjectsForKeys: {
17606f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
17706f32e7eSjoerg         &Ctx.Idents.get("dictionaryWithObjects"),
17806f32e7eSjoerg         &Ctx.Idents.get("forKeys")
17906f32e7eSjoerg       };
18006f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
18106f32e7eSjoerg       break;
18206f32e7eSjoerg     }
18306f32e7eSjoerg     case NSDict_dictionaryWithObjectsForKeysCount: {
18406f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
18506f32e7eSjoerg         &Ctx.Idents.get("dictionaryWithObjects"),
18606f32e7eSjoerg         &Ctx.Idents.get("forKeys"),
18706f32e7eSjoerg         &Ctx.Idents.get("count")
18806f32e7eSjoerg       };
18906f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
19006f32e7eSjoerg       break;
19106f32e7eSjoerg     }
19206f32e7eSjoerg     case NSDict_dictionaryWithObjectsAndKeys:
19306f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
19406f32e7eSjoerg                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
19506f32e7eSjoerg       break;
19606f32e7eSjoerg     case NSDict_initWithDictionary:
19706f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
19806f32e7eSjoerg                                          &Ctx.Idents.get("initWithDictionary"));
19906f32e7eSjoerg       break;
20006f32e7eSjoerg     case NSDict_initWithObjectsAndKeys:
20106f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(
20206f32e7eSjoerg                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
20306f32e7eSjoerg       break;
20406f32e7eSjoerg     case NSDict_initWithObjectsForKeys: {
20506f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
20606f32e7eSjoerg         &Ctx.Idents.get("initWithObjects"),
20706f32e7eSjoerg         &Ctx.Idents.get("forKeys")
20806f32e7eSjoerg       };
20906f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
21006f32e7eSjoerg       break;
21106f32e7eSjoerg     }
21206f32e7eSjoerg     case NSDict_objectForKey:
21306f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
21406f32e7eSjoerg       break;
21506f32e7eSjoerg     case NSMutableDict_setObjectForKey: {
21606f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
21706f32e7eSjoerg         &Ctx.Idents.get("setObject"),
21806f32e7eSjoerg         &Ctx.Idents.get("forKey")
21906f32e7eSjoerg       };
22006f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
22106f32e7eSjoerg       break;
22206f32e7eSjoerg     }
22306f32e7eSjoerg     case NSMutableDict_setObjectForKeyedSubscript: {
22406f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
22506f32e7eSjoerg         &Ctx.Idents.get("setObject"),
22606f32e7eSjoerg         &Ctx.Idents.get("forKeyedSubscript")
22706f32e7eSjoerg       };
22806f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
22906f32e7eSjoerg       break;
23006f32e7eSjoerg     }
23106f32e7eSjoerg     case NSMutableDict_setValueForKey: {
23206f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
23306f32e7eSjoerg         &Ctx.Idents.get("setValue"),
23406f32e7eSjoerg         &Ctx.Idents.get("forKey")
23506f32e7eSjoerg       };
23606f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
23706f32e7eSjoerg       break;
23806f32e7eSjoerg     }
23906f32e7eSjoerg     }
24006f32e7eSjoerg     return (NSDictionarySelectors[MK] = Sel);
24106f32e7eSjoerg   }
24206f32e7eSjoerg 
24306f32e7eSjoerg   return NSDictionarySelectors[MK];
24406f32e7eSjoerg }
24506f32e7eSjoerg 
24606f32e7eSjoerg Optional<NSAPI::NSDictionaryMethodKind>
getNSDictionaryMethodKind(Selector Sel)24706f32e7eSjoerg NSAPI::getNSDictionaryMethodKind(Selector Sel) {
24806f32e7eSjoerg   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
24906f32e7eSjoerg     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
25006f32e7eSjoerg     if (Sel == getNSDictionarySelector(MK))
25106f32e7eSjoerg       return MK;
25206f32e7eSjoerg   }
25306f32e7eSjoerg 
25406f32e7eSjoerg   return None;
25506f32e7eSjoerg }
25606f32e7eSjoerg 
getNSSetSelector(NSSetMethodKind MK) const25706f32e7eSjoerg Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
25806f32e7eSjoerg   if (NSSetSelectors[MK].isNull()) {
25906f32e7eSjoerg     Selector Sel;
26006f32e7eSjoerg     switch (MK) {
26106f32e7eSjoerg     case NSMutableSet_addObject:
26206f32e7eSjoerg       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
26306f32e7eSjoerg       break;
26406f32e7eSjoerg     case NSOrderedSet_insertObjectAtIndex: {
26506f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
26606f32e7eSjoerg         &Ctx.Idents.get("insertObject"),
26706f32e7eSjoerg         &Ctx.Idents.get("atIndex")
26806f32e7eSjoerg       };
26906f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
27006f32e7eSjoerg       break;
27106f32e7eSjoerg     }
27206f32e7eSjoerg     case NSOrderedSet_setObjectAtIndex: {
27306f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
27406f32e7eSjoerg         &Ctx.Idents.get("setObject"),
27506f32e7eSjoerg         &Ctx.Idents.get("atIndex")
27606f32e7eSjoerg       };
27706f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
27806f32e7eSjoerg       break;
27906f32e7eSjoerg     }
28006f32e7eSjoerg     case NSOrderedSet_setObjectAtIndexedSubscript: {
28106f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
28206f32e7eSjoerg         &Ctx.Idents.get("setObject"),
28306f32e7eSjoerg         &Ctx.Idents.get("atIndexedSubscript")
28406f32e7eSjoerg       };
28506f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
28606f32e7eSjoerg       break;
28706f32e7eSjoerg     }
28806f32e7eSjoerg     case NSOrderedSet_replaceObjectAtIndexWithObject: {
28906f32e7eSjoerg       IdentifierInfo *KeyIdents[] = {
29006f32e7eSjoerg         &Ctx.Idents.get("replaceObjectAtIndex"),
29106f32e7eSjoerg         &Ctx.Idents.get("withObject")
29206f32e7eSjoerg       };
29306f32e7eSjoerg       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
29406f32e7eSjoerg       break;
29506f32e7eSjoerg     }
29606f32e7eSjoerg     }
29706f32e7eSjoerg     return (NSSetSelectors[MK] = Sel);
29806f32e7eSjoerg   }
29906f32e7eSjoerg 
30006f32e7eSjoerg   return NSSetSelectors[MK];
30106f32e7eSjoerg }
30206f32e7eSjoerg 
30306f32e7eSjoerg Optional<NSAPI::NSSetMethodKind>
getNSSetMethodKind(Selector Sel)30406f32e7eSjoerg NSAPI::getNSSetMethodKind(Selector Sel) {
30506f32e7eSjoerg   for (unsigned i = 0; i != NumNSSetMethods; ++i) {
30606f32e7eSjoerg     NSSetMethodKind MK = NSSetMethodKind(i);
30706f32e7eSjoerg     if (Sel == getNSSetSelector(MK))
30806f32e7eSjoerg       return MK;
30906f32e7eSjoerg   }
31006f32e7eSjoerg 
31106f32e7eSjoerg   return None;
31206f32e7eSjoerg }
31306f32e7eSjoerg 
getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,bool Instance) const31406f32e7eSjoerg Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
31506f32e7eSjoerg                                            bool Instance) const {
31606f32e7eSjoerg   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
31706f32e7eSjoerg     "numberWithChar",
31806f32e7eSjoerg     "numberWithUnsignedChar",
31906f32e7eSjoerg     "numberWithShort",
32006f32e7eSjoerg     "numberWithUnsignedShort",
32106f32e7eSjoerg     "numberWithInt",
32206f32e7eSjoerg     "numberWithUnsignedInt",
32306f32e7eSjoerg     "numberWithLong",
32406f32e7eSjoerg     "numberWithUnsignedLong",
32506f32e7eSjoerg     "numberWithLongLong",
32606f32e7eSjoerg     "numberWithUnsignedLongLong",
32706f32e7eSjoerg     "numberWithFloat",
32806f32e7eSjoerg     "numberWithDouble",
32906f32e7eSjoerg     "numberWithBool",
33006f32e7eSjoerg     "numberWithInteger",
33106f32e7eSjoerg     "numberWithUnsignedInteger"
33206f32e7eSjoerg   };
33306f32e7eSjoerg   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
33406f32e7eSjoerg     "initWithChar",
33506f32e7eSjoerg     "initWithUnsignedChar",
33606f32e7eSjoerg     "initWithShort",
33706f32e7eSjoerg     "initWithUnsignedShort",
33806f32e7eSjoerg     "initWithInt",
33906f32e7eSjoerg     "initWithUnsignedInt",
34006f32e7eSjoerg     "initWithLong",
34106f32e7eSjoerg     "initWithUnsignedLong",
34206f32e7eSjoerg     "initWithLongLong",
34306f32e7eSjoerg     "initWithUnsignedLongLong",
34406f32e7eSjoerg     "initWithFloat",
34506f32e7eSjoerg     "initWithDouble",
34606f32e7eSjoerg     "initWithBool",
34706f32e7eSjoerg     "initWithInteger",
34806f32e7eSjoerg     "initWithUnsignedInteger"
34906f32e7eSjoerg   };
35006f32e7eSjoerg 
35106f32e7eSjoerg   Selector *Sels;
35206f32e7eSjoerg   const char **Names;
35306f32e7eSjoerg   if (Instance) {
35406f32e7eSjoerg     Sels = NSNumberInstanceSelectors;
35506f32e7eSjoerg     Names = InstanceSelectorName;
35606f32e7eSjoerg   } else {
35706f32e7eSjoerg     Sels = NSNumberClassSelectors;
35806f32e7eSjoerg     Names = ClassSelectorName;
35906f32e7eSjoerg   }
36006f32e7eSjoerg 
36106f32e7eSjoerg   if (Sels[MK].isNull())
36206f32e7eSjoerg     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
36306f32e7eSjoerg   return Sels[MK];
36406f32e7eSjoerg }
36506f32e7eSjoerg 
36606f32e7eSjoerg Optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const36706f32e7eSjoerg NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
36806f32e7eSjoerg   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
36906f32e7eSjoerg     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
37006f32e7eSjoerg     if (isNSNumberLiteralSelector(MK, Sel))
37106f32e7eSjoerg       return MK;
37206f32e7eSjoerg   }
37306f32e7eSjoerg 
37406f32e7eSjoerg   return None;
37506f32e7eSjoerg }
37606f32e7eSjoerg 
37706f32e7eSjoerg Optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const37806f32e7eSjoerg NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
37906f32e7eSjoerg   const BuiltinType *BT = T->getAs<BuiltinType>();
38006f32e7eSjoerg   if (!BT)
38106f32e7eSjoerg     return None;
38206f32e7eSjoerg 
38306f32e7eSjoerg   const TypedefType *TDT = T->getAs<TypedefType>();
38406f32e7eSjoerg   if (TDT) {
38506f32e7eSjoerg     QualType TDTTy = QualType(TDT, 0);
38606f32e7eSjoerg     if (isObjCBOOLType(TDTTy))
38706f32e7eSjoerg       return NSAPI::NSNumberWithBool;
38806f32e7eSjoerg     if (isObjCNSIntegerType(TDTTy))
38906f32e7eSjoerg       return NSAPI::NSNumberWithInteger;
39006f32e7eSjoerg     if (isObjCNSUIntegerType(TDTTy))
39106f32e7eSjoerg       return NSAPI::NSNumberWithUnsignedInteger;
39206f32e7eSjoerg   }
39306f32e7eSjoerg 
39406f32e7eSjoerg   switch (BT->getKind()) {
39506f32e7eSjoerg   case BuiltinType::Char_S:
39606f32e7eSjoerg   case BuiltinType::SChar:
39706f32e7eSjoerg     return NSAPI::NSNumberWithChar;
39806f32e7eSjoerg   case BuiltinType::Char_U:
39906f32e7eSjoerg   case BuiltinType::UChar:
40006f32e7eSjoerg     return NSAPI::NSNumberWithUnsignedChar;
40106f32e7eSjoerg   case BuiltinType::Short:
40206f32e7eSjoerg     return NSAPI::NSNumberWithShort;
40306f32e7eSjoerg   case BuiltinType::UShort:
40406f32e7eSjoerg     return NSAPI::NSNumberWithUnsignedShort;
40506f32e7eSjoerg   case BuiltinType::Int:
40606f32e7eSjoerg     return NSAPI::NSNumberWithInt;
40706f32e7eSjoerg   case BuiltinType::UInt:
40806f32e7eSjoerg     return NSAPI::NSNumberWithUnsignedInt;
40906f32e7eSjoerg   case BuiltinType::Long:
41006f32e7eSjoerg     return NSAPI::NSNumberWithLong;
41106f32e7eSjoerg   case BuiltinType::ULong:
41206f32e7eSjoerg     return NSAPI::NSNumberWithUnsignedLong;
41306f32e7eSjoerg   case BuiltinType::LongLong:
41406f32e7eSjoerg     return NSAPI::NSNumberWithLongLong;
41506f32e7eSjoerg   case BuiltinType::ULongLong:
41606f32e7eSjoerg     return NSAPI::NSNumberWithUnsignedLongLong;
41706f32e7eSjoerg   case BuiltinType::Float:
41806f32e7eSjoerg     return NSAPI::NSNumberWithFloat;
41906f32e7eSjoerg   case BuiltinType::Double:
42006f32e7eSjoerg     return NSAPI::NSNumberWithDouble;
42106f32e7eSjoerg   case BuiltinType::Bool:
42206f32e7eSjoerg     return NSAPI::NSNumberWithBool;
42306f32e7eSjoerg 
42406f32e7eSjoerg   case BuiltinType::Void:
42506f32e7eSjoerg   case BuiltinType::WChar_U:
42606f32e7eSjoerg   case BuiltinType::WChar_S:
42706f32e7eSjoerg   case BuiltinType::Char8:
42806f32e7eSjoerg   case BuiltinType::Char16:
42906f32e7eSjoerg   case BuiltinType::Char32:
43006f32e7eSjoerg   case BuiltinType::Int128:
43106f32e7eSjoerg   case BuiltinType::LongDouble:
43206f32e7eSjoerg   case BuiltinType::ShortAccum:
43306f32e7eSjoerg   case BuiltinType::Accum:
43406f32e7eSjoerg   case BuiltinType::LongAccum:
43506f32e7eSjoerg   case BuiltinType::UShortAccum:
43606f32e7eSjoerg   case BuiltinType::UAccum:
43706f32e7eSjoerg   case BuiltinType::ULongAccum:
43806f32e7eSjoerg   case BuiltinType::ShortFract:
43906f32e7eSjoerg   case BuiltinType::Fract:
44006f32e7eSjoerg   case BuiltinType::LongFract:
44106f32e7eSjoerg   case BuiltinType::UShortFract:
44206f32e7eSjoerg   case BuiltinType::UFract:
44306f32e7eSjoerg   case BuiltinType::ULongFract:
44406f32e7eSjoerg   case BuiltinType::SatShortAccum:
44506f32e7eSjoerg   case BuiltinType::SatAccum:
44606f32e7eSjoerg   case BuiltinType::SatLongAccum:
44706f32e7eSjoerg   case BuiltinType::SatUShortAccum:
44806f32e7eSjoerg   case BuiltinType::SatUAccum:
44906f32e7eSjoerg   case BuiltinType::SatULongAccum:
45006f32e7eSjoerg   case BuiltinType::SatShortFract:
45106f32e7eSjoerg   case BuiltinType::SatFract:
45206f32e7eSjoerg   case BuiltinType::SatLongFract:
45306f32e7eSjoerg   case BuiltinType::SatUShortFract:
45406f32e7eSjoerg   case BuiltinType::SatUFract:
45506f32e7eSjoerg   case BuiltinType::SatULongFract:
45606f32e7eSjoerg   case BuiltinType::UInt128:
45706f32e7eSjoerg   case BuiltinType::Float16:
45806f32e7eSjoerg   case BuiltinType::Float128:
45906f32e7eSjoerg   case BuiltinType::NullPtr:
46006f32e7eSjoerg   case BuiltinType::ObjCClass:
46106f32e7eSjoerg   case BuiltinType::ObjCId:
46206f32e7eSjoerg   case BuiltinType::ObjCSel:
46306f32e7eSjoerg #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
46406f32e7eSjoerg   case BuiltinType::Id:
46506f32e7eSjoerg #include "clang/Basic/OpenCLImageTypes.def"
46606f32e7eSjoerg #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
46706f32e7eSjoerg   case BuiltinType::Id:
46806f32e7eSjoerg #include "clang/Basic/OpenCLExtensionTypes.def"
46906f32e7eSjoerg   case BuiltinType::OCLSampler:
47006f32e7eSjoerg   case BuiltinType::OCLEvent:
47106f32e7eSjoerg   case BuiltinType::OCLClkEvent:
47206f32e7eSjoerg   case BuiltinType::OCLQueue:
47306f32e7eSjoerg   case BuiltinType::OCLReserveID:
47406f32e7eSjoerg #define SVE_TYPE(Name, Id, SingletonId) \
47506f32e7eSjoerg   case BuiltinType::Id:
47606f32e7eSjoerg #include "clang/Basic/AArch64SVEACLETypes.def"
477*13fbcb42Sjoerg #define PPC_VECTOR_TYPE(Name, Id, Size) \
478*13fbcb42Sjoerg   case BuiltinType::Id:
479*13fbcb42Sjoerg #include "clang/Basic/PPCTypes.def"
480*13fbcb42Sjoerg #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
481*13fbcb42Sjoerg #include "clang/Basic/RISCVVTypes.def"
48206f32e7eSjoerg   case BuiltinType::BoundMember:
48306f32e7eSjoerg   case BuiltinType::Dependent:
48406f32e7eSjoerg   case BuiltinType::Overload:
48506f32e7eSjoerg   case BuiltinType::UnknownAny:
48606f32e7eSjoerg   case BuiltinType::ARCUnbridgedCast:
48706f32e7eSjoerg   case BuiltinType::Half:
48806f32e7eSjoerg   case BuiltinType::PseudoObject:
48906f32e7eSjoerg   case BuiltinType::BuiltinFn:
490*13fbcb42Sjoerg   case BuiltinType::IncompleteMatrixIdx:
49106f32e7eSjoerg   case BuiltinType::OMPArraySection:
492*13fbcb42Sjoerg   case BuiltinType::OMPArrayShaping:
493*13fbcb42Sjoerg   case BuiltinType::OMPIterator:
494*13fbcb42Sjoerg   case BuiltinType::BFloat16:
49506f32e7eSjoerg     break;
49606f32e7eSjoerg   }
49706f32e7eSjoerg 
49806f32e7eSjoerg   return None;
49906f32e7eSjoerg }
50006f32e7eSjoerg 
50106f32e7eSjoerg /// Returns true if \param T is a typedef of "BOOL" in objective-c.
isObjCBOOLType(QualType T) const50206f32e7eSjoerg bool NSAPI::isObjCBOOLType(QualType T) const {
50306f32e7eSjoerg   return isObjCTypedef(T, "BOOL", BOOLId);
50406f32e7eSjoerg }
50506f32e7eSjoerg /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
isObjCNSIntegerType(QualType T) const50606f32e7eSjoerg bool NSAPI::isObjCNSIntegerType(QualType T) const {
50706f32e7eSjoerg   return isObjCTypedef(T, "NSInteger", NSIntegerId);
50806f32e7eSjoerg }
50906f32e7eSjoerg /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
isObjCNSUIntegerType(QualType T) const51006f32e7eSjoerg bool NSAPI::isObjCNSUIntegerType(QualType T) const {
51106f32e7eSjoerg   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
51206f32e7eSjoerg }
51306f32e7eSjoerg 
GetNSIntegralKind(QualType T) const51406f32e7eSjoerg StringRef NSAPI::GetNSIntegralKind(QualType T) const {
51506f32e7eSjoerg   if (!Ctx.getLangOpts().ObjC || T.isNull())
51606f32e7eSjoerg     return StringRef();
51706f32e7eSjoerg 
51806f32e7eSjoerg   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
51906f32e7eSjoerg     StringRef NSIntegralResust =
52006f32e7eSjoerg       llvm::StringSwitch<StringRef>(
52106f32e7eSjoerg         TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
52206f32e7eSjoerg     .Case("int8_t", "int8_t")
52306f32e7eSjoerg     .Case("int16_t", "int16_t")
52406f32e7eSjoerg     .Case("int32_t", "int32_t")
52506f32e7eSjoerg     .Case("NSInteger", "NSInteger")
52606f32e7eSjoerg     .Case("int64_t", "int64_t")
52706f32e7eSjoerg     .Case("uint8_t", "uint8_t")
52806f32e7eSjoerg     .Case("uint16_t", "uint16_t")
52906f32e7eSjoerg     .Case("uint32_t", "uint32_t")
53006f32e7eSjoerg     .Case("NSUInteger", "NSUInteger")
53106f32e7eSjoerg     .Case("uint64_t", "uint64_t")
53206f32e7eSjoerg     .Default(StringRef());
53306f32e7eSjoerg     if (!NSIntegralResust.empty())
53406f32e7eSjoerg       return NSIntegralResust;
53506f32e7eSjoerg     T = TDT->desugar();
53606f32e7eSjoerg   }
53706f32e7eSjoerg   return StringRef();
53806f32e7eSjoerg }
53906f32e7eSjoerg 
isMacroDefined(StringRef Id) const54006f32e7eSjoerg bool NSAPI::isMacroDefined(StringRef Id) const {
54106f32e7eSjoerg   // FIXME: Check whether the relevant module macros are visible.
54206f32e7eSjoerg   return Ctx.Idents.get(Id).hasMacroDefinition();
54306f32e7eSjoerg }
54406f32e7eSjoerg 
isSubclassOfNSClass(ObjCInterfaceDecl * InterfaceDecl,NSClassIdKindKind NSClassKind) const54506f32e7eSjoerg bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
54606f32e7eSjoerg                                 NSClassIdKindKind NSClassKind) const {
54706f32e7eSjoerg   if (!InterfaceDecl) {
54806f32e7eSjoerg     return false;
54906f32e7eSjoerg   }
55006f32e7eSjoerg 
55106f32e7eSjoerg   IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
55206f32e7eSjoerg 
55306f32e7eSjoerg   bool IsSubclass = false;
55406f32e7eSjoerg   do {
55506f32e7eSjoerg     IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
55606f32e7eSjoerg 
55706f32e7eSjoerg     if (IsSubclass) {
55806f32e7eSjoerg       break;
55906f32e7eSjoerg     }
56006f32e7eSjoerg   } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
56106f32e7eSjoerg 
56206f32e7eSjoerg   return IsSubclass;
56306f32e7eSjoerg }
56406f32e7eSjoerg 
isObjCTypedef(QualType T,StringRef name,IdentifierInfo * & II) const56506f32e7eSjoerg bool NSAPI::isObjCTypedef(QualType T,
56606f32e7eSjoerg                           StringRef name, IdentifierInfo *&II) const {
56706f32e7eSjoerg   if (!Ctx.getLangOpts().ObjC)
56806f32e7eSjoerg     return false;
56906f32e7eSjoerg   if (T.isNull())
57006f32e7eSjoerg     return false;
57106f32e7eSjoerg 
57206f32e7eSjoerg   if (!II)
57306f32e7eSjoerg     II = &Ctx.Idents.get(name);
57406f32e7eSjoerg 
57506f32e7eSjoerg   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
57606f32e7eSjoerg     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
57706f32e7eSjoerg       return true;
57806f32e7eSjoerg     T = TDT->desugar();
57906f32e7eSjoerg   }
58006f32e7eSjoerg 
58106f32e7eSjoerg   return false;
58206f32e7eSjoerg }
58306f32e7eSjoerg 
isObjCEnumerator(const Expr * E,StringRef name,IdentifierInfo * & II) const58406f32e7eSjoerg bool NSAPI::isObjCEnumerator(const Expr *E,
58506f32e7eSjoerg                              StringRef name, IdentifierInfo *&II) const {
58606f32e7eSjoerg   if (!Ctx.getLangOpts().ObjC)
58706f32e7eSjoerg     return false;
58806f32e7eSjoerg   if (!E)
58906f32e7eSjoerg     return false;
59006f32e7eSjoerg 
59106f32e7eSjoerg   if (!II)
59206f32e7eSjoerg     II = &Ctx.Idents.get(name);
59306f32e7eSjoerg 
59406f32e7eSjoerg   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
59506f32e7eSjoerg     if (const EnumConstantDecl *
59606f32e7eSjoerg           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
59706f32e7eSjoerg       return EnumD->getIdentifier() == II;
59806f32e7eSjoerg 
59906f32e7eSjoerg   return false;
60006f32e7eSjoerg }
60106f32e7eSjoerg 
getOrInitSelector(ArrayRef<StringRef> Ids,Selector & Sel) const60206f32e7eSjoerg Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
60306f32e7eSjoerg                                   Selector &Sel) const {
60406f32e7eSjoerg   if (Sel.isNull()) {
60506f32e7eSjoerg     SmallVector<IdentifierInfo *, 4> Idents;
60606f32e7eSjoerg     for (ArrayRef<StringRef>::const_iterator
60706f32e7eSjoerg            I = Ids.begin(), E = Ids.end(); I != E; ++I)
60806f32e7eSjoerg       Idents.push_back(&Ctx.Idents.get(*I));
60906f32e7eSjoerg     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
61006f32e7eSjoerg   }
61106f32e7eSjoerg   return Sel;
61206f32e7eSjoerg }
61306f32e7eSjoerg 
getOrInitNullarySelector(StringRef Id,Selector & Sel) const61406f32e7eSjoerg Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
61506f32e7eSjoerg   if (Sel.isNull()) {
61606f32e7eSjoerg     IdentifierInfo *Ident = &Ctx.Idents.get(Id);
61706f32e7eSjoerg     Sel = Ctx.Selectors.getSelector(0, &Ident);
61806f32e7eSjoerg   }
61906f32e7eSjoerg   return Sel;
62006f32e7eSjoerg }
621