xref: /freebsd/contrib/llvm-project/clang/lib/AST/NSAPI.cpp (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
1*0b57cec5SDimitry Andric //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "clang/AST/NSAPI.h"
10*0b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
11*0b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
12*0b57cec5SDimitry Andric #include "clang/AST/Expr.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
14*0b57cec5SDimitry Andric 
15*0b57cec5SDimitry Andric using namespace clang;
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric NSAPI::NSAPI(ASTContext &ctx)
18*0b57cec5SDimitry Andric   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19*0b57cec5SDimitry Andric     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20*0b57cec5SDimitry Andric     NSUTF8StringEncodingId(nullptr) {}
21*0b57cec5SDimitry Andric 
22*0b57cec5SDimitry Andric IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
23*0b57cec5SDimitry Andric   static const char *ClassName[NumClassIds] = {
24*0b57cec5SDimitry Andric     "NSObject",
25*0b57cec5SDimitry Andric     "NSString",
26*0b57cec5SDimitry Andric     "NSArray",
27*0b57cec5SDimitry Andric     "NSMutableArray",
28*0b57cec5SDimitry Andric     "NSDictionary",
29*0b57cec5SDimitry Andric     "NSMutableDictionary",
30*0b57cec5SDimitry Andric     "NSNumber",
31*0b57cec5SDimitry Andric     "NSMutableSet",
32*0b57cec5SDimitry Andric     "NSMutableOrderedSet",
33*0b57cec5SDimitry Andric     "NSValue"
34*0b57cec5SDimitry Andric   };
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric   if (!ClassIds[K])
37*0b57cec5SDimitry Andric     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   return ClassIds[K];
40*0b57cec5SDimitry Andric }
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
43*0b57cec5SDimitry Andric   if (NSStringSelectors[MK].isNull()) {
44*0b57cec5SDimitry Andric     Selector Sel;
45*0b57cec5SDimitry Andric     switch (MK) {
46*0b57cec5SDimitry Andric     case NSStr_stringWithString:
47*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
48*0b57cec5SDimitry Andric       break;
49*0b57cec5SDimitry Andric     case NSStr_stringWithUTF8String:
50*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
51*0b57cec5SDimitry Andric                                        &Ctx.Idents.get("stringWithUTF8String"));
52*0b57cec5SDimitry Andric       break;
53*0b57cec5SDimitry Andric     case NSStr_initWithUTF8String:
54*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
55*0b57cec5SDimitry Andric                                        &Ctx.Idents.get("initWithUTF8String"));
56*0b57cec5SDimitry Andric       break;
57*0b57cec5SDimitry Andric     case NSStr_stringWithCStringEncoding: {
58*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
59*0b57cec5SDimitry Andric         &Ctx.Idents.get("stringWithCString"),
60*0b57cec5SDimitry Andric         &Ctx.Idents.get("encoding")
61*0b57cec5SDimitry Andric       };
62*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
63*0b57cec5SDimitry Andric       break;
64*0b57cec5SDimitry Andric     }
65*0b57cec5SDimitry Andric     case NSStr_stringWithCString:
66*0b57cec5SDimitry Andric       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
67*0b57cec5SDimitry Andric       break;
68*0b57cec5SDimitry Andric     case NSStr_initWithString:
69*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
70*0b57cec5SDimitry Andric       break;
71*0b57cec5SDimitry Andric     }
72*0b57cec5SDimitry Andric     return (NSStringSelectors[MK] = Sel);
73*0b57cec5SDimitry Andric   }
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   return NSStringSelectors[MK];
76*0b57cec5SDimitry Andric }
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric Optional<NSAPI::NSStringMethodKind>
79*0b57cec5SDimitry Andric NSAPI::getNSStringMethodKind(Selector Sel) const {
80*0b57cec5SDimitry Andric   for (unsigned i = 0; i != NumNSStringMethods; ++i) {
81*0b57cec5SDimitry Andric     NSStringMethodKind MK = NSStringMethodKind(i);
82*0b57cec5SDimitry Andric     if (Sel == getNSStringSelector(MK))
83*0b57cec5SDimitry Andric       return MK;
84*0b57cec5SDimitry Andric   }
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric   return None;
87*0b57cec5SDimitry Andric }
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
90*0b57cec5SDimitry Andric   if (NSArraySelectors[MK].isNull()) {
91*0b57cec5SDimitry Andric     Selector Sel;
92*0b57cec5SDimitry Andric     switch (MK) {
93*0b57cec5SDimitry Andric     case NSArr_array:
94*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
95*0b57cec5SDimitry Andric       break;
96*0b57cec5SDimitry Andric     case NSArr_arrayWithArray:
97*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
98*0b57cec5SDimitry Andric       break;
99*0b57cec5SDimitry Andric     case NSArr_arrayWithObject:
100*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
101*0b57cec5SDimitry Andric       break;
102*0b57cec5SDimitry Andric     case NSArr_arrayWithObjects:
103*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
104*0b57cec5SDimitry Andric       break;
105*0b57cec5SDimitry Andric     case NSArr_arrayWithObjectsCount: {
106*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
107*0b57cec5SDimitry Andric         &Ctx.Idents.get("arrayWithObjects"),
108*0b57cec5SDimitry Andric         &Ctx.Idents.get("count")
109*0b57cec5SDimitry Andric       };
110*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
111*0b57cec5SDimitry Andric       break;
112*0b57cec5SDimitry Andric     }
113*0b57cec5SDimitry Andric     case NSArr_initWithArray:
114*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
115*0b57cec5SDimitry Andric       break;
116*0b57cec5SDimitry Andric     case NSArr_initWithObjects:
117*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
118*0b57cec5SDimitry Andric       break;
119*0b57cec5SDimitry Andric     case NSArr_objectAtIndex:
120*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
121*0b57cec5SDimitry Andric       break;
122*0b57cec5SDimitry Andric     case NSMutableArr_replaceObjectAtIndex: {
123*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
124*0b57cec5SDimitry Andric         &Ctx.Idents.get("replaceObjectAtIndex"),
125*0b57cec5SDimitry Andric         &Ctx.Idents.get("withObject")
126*0b57cec5SDimitry Andric       };
127*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
128*0b57cec5SDimitry Andric       break;
129*0b57cec5SDimitry Andric     }
130*0b57cec5SDimitry Andric     case NSMutableArr_addObject:
131*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
132*0b57cec5SDimitry Andric       break;
133*0b57cec5SDimitry Andric     case NSMutableArr_insertObjectAtIndex: {
134*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
135*0b57cec5SDimitry Andric         &Ctx.Idents.get("insertObject"),
136*0b57cec5SDimitry Andric         &Ctx.Idents.get("atIndex")
137*0b57cec5SDimitry Andric       };
138*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
139*0b57cec5SDimitry Andric       break;
140*0b57cec5SDimitry Andric     }
141*0b57cec5SDimitry Andric     case NSMutableArr_setObjectAtIndexedSubscript: {
142*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
143*0b57cec5SDimitry Andric         &Ctx.Idents.get("setObject"),
144*0b57cec5SDimitry Andric         &Ctx.Idents.get("atIndexedSubscript")
145*0b57cec5SDimitry Andric       };
146*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
147*0b57cec5SDimitry Andric       break;
148*0b57cec5SDimitry Andric     }
149*0b57cec5SDimitry Andric     }
150*0b57cec5SDimitry Andric     return (NSArraySelectors[MK] = Sel);
151*0b57cec5SDimitry Andric   }
152*0b57cec5SDimitry Andric 
153*0b57cec5SDimitry Andric   return NSArraySelectors[MK];
154*0b57cec5SDimitry Andric }
155*0b57cec5SDimitry Andric 
156*0b57cec5SDimitry Andric Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
157*0b57cec5SDimitry Andric   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
158*0b57cec5SDimitry Andric     NSArrayMethodKind MK = NSArrayMethodKind(i);
159*0b57cec5SDimitry Andric     if (Sel == getNSArraySelector(MK))
160*0b57cec5SDimitry Andric       return MK;
161*0b57cec5SDimitry Andric   }
162*0b57cec5SDimitry Andric 
163*0b57cec5SDimitry Andric   return None;
164*0b57cec5SDimitry Andric }
165*0b57cec5SDimitry Andric 
166*0b57cec5SDimitry Andric Selector NSAPI::getNSDictionarySelector(
167*0b57cec5SDimitry Andric                                        NSDictionaryMethodKind MK) const {
168*0b57cec5SDimitry Andric   if (NSDictionarySelectors[MK].isNull()) {
169*0b57cec5SDimitry Andric     Selector Sel;
170*0b57cec5SDimitry Andric     switch (MK) {
171*0b57cec5SDimitry Andric     case NSDict_dictionary:
172*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
173*0b57cec5SDimitry Andric       break;
174*0b57cec5SDimitry Andric     case NSDict_dictionaryWithDictionary:
175*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
176*0b57cec5SDimitry Andric                                    &Ctx.Idents.get("dictionaryWithDictionary"));
177*0b57cec5SDimitry Andric       break;
178*0b57cec5SDimitry Andric     case NSDict_dictionaryWithObjectForKey: {
179*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
180*0b57cec5SDimitry Andric         &Ctx.Idents.get("dictionaryWithObject"),
181*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKey")
182*0b57cec5SDimitry Andric       };
183*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
184*0b57cec5SDimitry Andric       break;
185*0b57cec5SDimitry Andric     }
186*0b57cec5SDimitry Andric     case NSDict_dictionaryWithObjectsForKeys: {
187*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
188*0b57cec5SDimitry Andric         &Ctx.Idents.get("dictionaryWithObjects"),
189*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKeys")
190*0b57cec5SDimitry Andric       };
191*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
192*0b57cec5SDimitry Andric       break;
193*0b57cec5SDimitry Andric     }
194*0b57cec5SDimitry Andric     case NSDict_dictionaryWithObjectsForKeysCount: {
195*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
196*0b57cec5SDimitry Andric         &Ctx.Idents.get("dictionaryWithObjects"),
197*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKeys"),
198*0b57cec5SDimitry Andric         &Ctx.Idents.get("count")
199*0b57cec5SDimitry Andric       };
200*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
201*0b57cec5SDimitry Andric       break;
202*0b57cec5SDimitry Andric     }
203*0b57cec5SDimitry Andric     case NSDict_dictionaryWithObjectsAndKeys:
204*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
205*0b57cec5SDimitry Andric                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
206*0b57cec5SDimitry Andric       break;
207*0b57cec5SDimitry Andric     case NSDict_initWithDictionary:
208*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
209*0b57cec5SDimitry Andric                                          &Ctx.Idents.get("initWithDictionary"));
210*0b57cec5SDimitry Andric       break;
211*0b57cec5SDimitry Andric     case NSDict_initWithObjectsAndKeys:
212*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(
213*0b57cec5SDimitry Andric                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
214*0b57cec5SDimitry Andric       break;
215*0b57cec5SDimitry Andric     case NSDict_initWithObjectsForKeys: {
216*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
217*0b57cec5SDimitry Andric         &Ctx.Idents.get("initWithObjects"),
218*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKeys")
219*0b57cec5SDimitry Andric       };
220*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
221*0b57cec5SDimitry Andric       break;
222*0b57cec5SDimitry Andric     }
223*0b57cec5SDimitry Andric     case NSDict_objectForKey:
224*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
225*0b57cec5SDimitry Andric       break;
226*0b57cec5SDimitry Andric     case NSMutableDict_setObjectForKey: {
227*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
228*0b57cec5SDimitry Andric         &Ctx.Idents.get("setObject"),
229*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKey")
230*0b57cec5SDimitry Andric       };
231*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
232*0b57cec5SDimitry Andric       break;
233*0b57cec5SDimitry Andric     }
234*0b57cec5SDimitry Andric     case NSMutableDict_setObjectForKeyedSubscript: {
235*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
236*0b57cec5SDimitry Andric         &Ctx.Idents.get("setObject"),
237*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKeyedSubscript")
238*0b57cec5SDimitry Andric       };
239*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
240*0b57cec5SDimitry Andric       break;
241*0b57cec5SDimitry Andric     }
242*0b57cec5SDimitry Andric     case NSMutableDict_setValueForKey: {
243*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
244*0b57cec5SDimitry Andric         &Ctx.Idents.get("setValue"),
245*0b57cec5SDimitry Andric         &Ctx.Idents.get("forKey")
246*0b57cec5SDimitry Andric       };
247*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
248*0b57cec5SDimitry Andric       break;
249*0b57cec5SDimitry Andric     }
250*0b57cec5SDimitry Andric     }
251*0b57cec5SDimitry Andric     return (NSDictionarySelectors[MK] = Sel);
252*0b57cec5SDimitry Andric   }
253*0b57cec5SDimitry Andric 
254*0b57cec5SDimitry Andric   return NSDictionarySelectors[MK];
255*0b57cec5SDimitry Andric }
256*0b57cec5SDimitry Andric 
257*0b57cec5SDimitry Andric Optional<NSAPI::NSDictionaryMethodKind>
258*0b57cec5SDimitry Andric NSAPI::getNSDictionaryMethodKind(Selector Sel) {
259*0b57cec5SDimitry Andric   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
260*0b57cec5SDimitry Andric     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
261*0b57cec5SDimitry Andric     if (Sel == getNSDictionarySelector(MK))
262*0b57cec5SDimitry Andric       return MK;
263*0b57cec5SDimitry Andric   }
264*0b57cec5SDimitry Andric 
265*0b57cec5SDimitry Andric   return None;
266*0b57cec5SDimitry Andric }
267*0b57cec5SDimitry Andric 
268*0b57cec5SDimitry Andric Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
269*0b57cec5SDimitry Andric   if (NSSetSelectors[MK].isNull()) {
270*0b57cec5SDimitry Andric     Selector Sel;
271*0b57cec5SDimitry Andric     switch (MK) {
272*0b57cec5SDimitry Andric     case NSMutableSet_addObject:
273*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
274*0b57cec5SDimitry Andric       break;
275*0b57cec5SDimitry Andric     case NSOrderedSet_insertObjectAtIndex: {
276*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
277*0b57cec5SDimitry Andric         &Ctx.Idents.get("insertObject"),
278*0b57cec5SDimitry Andric         &Ctx.Idents.get("atIndex")
279*0b57cec5SDimitry Andric       };
280*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
281*0b57cec5SDimitry Andric       break;
282*0b57cec5SDimitry Andric     }
283*0b57cec5SDimitry Andric     case NSOrderedSet_setObjectAtIndex: {
284*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
285*0b57cec5SDimitry Andric         &Ctx.Idents.get("setObject"),
286*0b57cec5SDimitry Andric         &Ctx.Idents.get("atIndex")
287*0b57cec5SDimitry Andric       };
288*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
289*0b57cec5SDimitry Andric       break;
290*0b57cec5SDimitry Andric     }
291*0b57cec5SDimitry Andric     case NSOrderedSet_setObjectAtIndexedSubscript: {
292*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
293*0b57cec5SDimitry Andric         &Ctx.Idents.get("setObject"),
294*0b57cec5SDimitry Andric         &Ctx.Idents.get("atIndexedSubscript")
295*0b57cec5SDimitry Andric       };
296*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
297*0b57cec5SDimitry Andric       break;
298*0b57cec5SDimitry Andric     }
299*0b57cec5SDimitry Andric     case NSOrderedSet_replaceObjectAtIndexWithObject: {
300*0b57cec5SDimitry Andric       IdentifierInfo *KeyIdents[] = {
301*0b57cec5SDimitry Andric         &Ctx.Idents.get("replaceObjectAtIndex"),
302*0b57cec5SDimitry Andric         &Ctx.Idents.get("withObject")
303*0b57cec5SDimitry Andric       };
304*0b57cec5SDimitry Andric       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
305*0b57cec5SDimitry Andric       break;
306*0b57cec5SDimitry Andric     }
307*0b57cec5SDimitry Andric     }
308*0b57cec5SDimitry Andric     return (NSSetSelectors[MK] = Sel);
309*0b57cec5SDimitry Andric   }
310*0b57cec5SDimitry Andric 
311*0b57cec5SDimitry Andric   return NSSetSelectors[MK];
312*0b57cec5SDimitry Andric }
313*0b57cec5SDimitry Andric 
314*0b57cec5SDimitry Andric Optional<NSAPI::NSSetMethodKind>
315*0b57cec5SDimitry Andric NSAPI::getNSSetMethodKind(Selector Sel) {
316*0b57cec5SDimitry Andric   for (unsigned i = 0; i != NumNSSetMethods; ++i) {
317*0b57cec5SDimitry Andric     NSSetMethodKind MK = NSSetMethodKind(i);
318*0b57cec5SDimitry Andric     if (Sel == getNSSetSelector(MK))
319*0b57cec5SDimitry Andric       return MK;
320*0b57cec5SDimitry Andric   }
321*0b57cec5SDimitry Andric 
322*0b57cec5SDimitry Andric   return None;
323*0b57cec5SDimitry Andric }
324*0b57cec5SDimitry Andric 
325*0b57cec5SDimitry Andric Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
326*0b57cec5SDimitry Andric                                            bool Instance) const {
327*0b57cec5SDimitry Andric   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
328*0b57cec5SDimitry Andric     "numberWithChar",
329*0b57cec5SDimitry Andric     "numberWithUnsignedChar",
330*0b57cec5SDimitry Andric     "numberWithShort",
331*0b57cec5SDimitry Andric     "numberWithUnsignedShort",
332*0b57cec5SDimitry Andric     "numberWithInt",
333*0b57cec5SDimitry Andric     "numberWithUnsignedInt",
334*0b57cec5SDimitry Andric     "numberWithLong",
335*0b57cec5SDimitry Andric     "numberWithUnsignedLong",
336*0b57cec5SDimitry Andric     "numberWithLongLong",
337*0b57cec5SDimitry Andric     "numberWithUnsignedLongLong",
338*0b57cec5SDimitry Andric     "numberWithFloat",
339*0b57cec5SDimitry Andric     "numberWithDouble",
340*0b57cec5SDimitry Andric     "numberWithBool",
341*0b57cec5SDimitry Andric     "numberWithInteger",
342*0b57cec5SDimitry Andric     "numberWithUnsignedInteger"
343*0b57cec5SDimitry Andric   };
344*0b57cec5SDimitry Andric   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
345*0b57cec5SDimitry Andric     "initWithChar",
346*0b57cec5SDimitry Andric     "initWithUnsignedChar",
347*0b57cec5SDimitry Andric     "initWithShort",
348*0b57cec5SDimitry Andric     "initWithUnsignedShort",
349*0b57cec5SDimitry Andric     "initWithInt",
350*0b57cec5SDimitry Andric     "initWithUnsignedInt",
351*0b57cec5SDimitry Andric     "initWithLong",
352*0b57cec5SDimitry Andric     "initWithUnsignedLong",
353*0b57cec5SDimitry Andric     "initWithLongLong",
354*0b57cec5SDimitry Andric     "initWithUnsignedLongLong",
355*0b57cec5SDimitry Andric     "initWithFloat",
356*0b57cec5SDimitry Andric     "initWithDouble",
357*0b57cec5SDimitry Andric     "initWithBool",
358*0b57cec5SDimitry Andric     "initWithInteger",
359*0b57cec5SDimitry Andric     "initWithUnsignedInteger"
360*0b57cec5SDimitry Andric   };
361*0b57cec5SDimitry Andric 
362*0b57cec5SDimitry Andric   Selector *Sels;
363*0b57cec5SDimitry Andric   const char **Names;
364*0b57cec5SDimitry Andric   if (Instance) {
365*0b57cec5SDimitry Andric     Sels = NSNumberInstanceSelectors;
366*0b57cec5SDimitry Andric     Names = InstanceSelectorName;
367*0b57cec5SDimitry Andric   } else {
368*0b57cec5SDimitry Andric     Sels = NSNumberClassSelectors;
369*0b57cec5SDimitry Andric     Names = ClassSelectorName;
370*0b57cec5SDimitry Andric   }
371*0b57cec5SDimitry Andric 
372*0b57cec5SDimitry Andric   if (Sels[MK].isNull())
373*0b57cec5SDimitry Andric     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
374*0b57cec5SDimitry Andric   return Sels[MK];
375*0b57cec5SDimitry Andric }
376*0b57cec5SDimitry Andric 
377*0b57cec5SDimitry Andric Optional<NSAPI::NSNumberLiteralMethodKind>
378*0b57cec5SDimitry Andric NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
379*0b57cec5SDimitry Andric   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
380*0b57cec5SDimitry Andric     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
381*0b57cec5SDimitry Andric     if (isNSNumberLiteralSelector(MK, Sel))
382*0b57cec5SDimitry Andric       return MK;
383*0b57cec5SDimitry Andric   }
384*0b57cec5SDimitry Andric 
385*0b57cec5SDimitry Andric   return None;
386*0b57cec5SDimitry Andric }
387*0b57cec5SDimitry Andric 
388*0b57cec5SDimitry Andric Optional<NSAPI::NSNumberLiteralMethodKind>
389*0b57cec5SDimitry Andric NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
390*0b57cec5SDimitry Andric   const BuiltinType *BT = T->getAs<BuiltinType>();
391*0b57cec5SDimitry Andric   if (!BT)
392*0b57cec5SDimitry Andric     return None;
393*0b57cec5SDimitry Andric 
394*0b57cec5SDimitry Andric   const TypedefType *TDT = T->getAs<TypedefType>();
395*0b57cec5SDimitry Andric   if (TDT) {
396*0b57cec5SDimitry Andric     QualType TDTTy = QualType(TDT, 0);
397*0b57cec5SDimitry Andric     if (isObjCBOOLType(TDTTy))
398*0b57cec5SDimitry Andric       return NSAPI::NSNumberWithBool;
399*0b57cec5SDimitry Andric     if (isObjCNSIntegerType(TDTTy))
400*0b57cec5SDimitry Andric       return NSAPI::NSNumberWithInteger;
401*0b57cec5SDimitry Andric     if (isObjCNSUIntegerType(TDTTy))
402*0b57cec5SDimitry Andric       return NSAPI::NSNumberWithUnsignedInteger;
403*0b57cec5SDimitry Andric   }
404*0b57cec5SDimitry Andric 
405*0b57cec5SDimitry Andric   switch (BT->getKind()) {
406*0b57cec5SDimitry Andric   case BuiltinType::Char_S:
407*0b57cec5SDimitry Andric   case BuiltinType::SChar:
408*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithChar;
409*0b57cec5SDimitry Andric   case BuiltinType::Char_U:
410*0b57cec5SDimitry Andric   case BuiltinType::UChar:
411*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithUnsignedChar;
412*0b57cec5SDimitry Andric   case BuiltinType::Short:
413*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithShort;
414*0b57cec5SDimitry Andric   case BuiltinType::UShort:
415*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithUnsignedShort;
416*0b57cec5SDimitry Andric   case BuiltinType::Int:
417*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithInt;
418*0b57cec5SDimitry Andric   case BuiltinType::UInt:
419*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithUnsignedInt;
420*0b57cec5SDimitry Andric   case BuiltinType::Long:
421*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithLong;
422*0b57cec5SDimitry Andric   case BuiltinType::ULong:
423*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithUnsignedLong;
424*0b57cec5SDimitry Andric   case BuiltinType::LongLong:
425*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithLongLong;
426*0b57cec5SDimitry Andric   case BuiltinType::ULongLong:
427*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithUnsignedLongLong;
428*0b57cec5SDimitry Andric   case BuiltinType::Float:
429*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithFloat;
430*0b57cec5SDimitry Andric   case BuiltinType::Double:
431*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithDouble;
432*0b57cec5SDimitry Andric   case BuiltinType::Bool:
433*0b57cec5SDimitry Andric     return NSAPI::NSNumberWithBool;
434*0b57cec5SDimitry Andric 
435*0b57cec5SDimitry Andric   case BuiltinType::Void:
436*0b57cec5SDimitry Andric   case BuiltinType::WChar_U:
437*0b57cec5SDimitry Andric   case BuiltinType::WChar_S:
438*0b57cec5SDimitry Andric   case BuiltinType::Char8:
439*0b57cec5SDimitry Andric   case BuiltinType::Char16:
440*0b57cec5SDimitry Andric   case BuiltinType::Char32:
441*0b57cec5SDimitry Andric   case BuiltinType::Int128:
442*0b57cec5SDimitry Andric   case BuiltinType::LongDouble:
443*0b57cec5SDimitry Andric   case BuiltinType::ShortAccum:
444*0b57cec5SDimitry Andric   case BuiltinType::Accum:
445*0b57cec5SDimitry Andric   case BuiltinType::LongAccum:
446*0b57cec5SDimitry Andric   case BuiltinType::UShortAccum:
447*0b57cec5SDimitry Andric   case BuiltinType::UAccum:
448*0b57cec5SDimitry Andric   case BuiltinType::ULongAccum:
449*0b57cec5SDimitry Andric   case BuiltinType::ShortFract:
450*0b57cec5SDimitry Andric   case BuiltinType::Fract:
451*0b57cec5SDimitry Andric   case BuiltinType::LongFract:
452*0b57cec5SDimitry Andric   case BuiltinType::UShortFract:
453*0b57cec5SDimitry Andric   case BuiltinType::UFract:
454*0b57cec5SDimitry Andric   case BuiltinType::ULongFract:
455*0b57cec5SDimitry Andric   case BuiltinType::SatShortAccum:
456*0b57cec5SDimitry Andric   case BuiltinType::SatAccum:
457*0b57cec5SDimitry Andric   case BuiltinType::SatLongAccum:
458*0b57cec5SDimitry Andric   case BuiltinType::SatUShortAccum:
459*0b57cec5SDimitry Andric   case BuiltinType::SatUAccum:
460*0b57cec5SDimitry Andric   case BuiltinType::SatULongAccum:
461*0b57cec5SDimitry Andric   case BuiltinType::SatShortFract:
462*0b57cec5SDimitry Andric   case BuiltinType::SatFract:
463*0b57cec5SDimitry Andric   case BuiltinType::SatLongFract:
464*0b57cec5SDimitry Andric   case BuiltinType::SatUShortFract:
465*0b57cec5SDimitry Andric   case BuiltinType::SatUFract:
466*0b57cec5SDimitry Andric   case BuiltinType::SatULongFract:
467*0b57cec5SDimitry Andric   case BuiltinType::UInt128:
468*0b57cec5SDimitry Andric   case BuiltinType::Float16:
469*0b57cec5SDimitry Andric   case BuiltinType::Float128:
470*0b57cec5SDimitry Andric   case BuiltinType::NullPtr:
471*0b57cec5SDimitry Andric   case BuiltinType::ObjCClass:
472*0b57cec5SDimitry Andric   case BuiltinType::ObjCId:
473*0b57cec5SDimitry Andric   case BuiltinType::ObjCSel:
474*0b57cec5SDimitry Andric #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
475*0b57cec5SDimitry Andric   case BuiltinType::Id:
476*0b57cec5SDimitry Andric #include "clang/Basic/OpenCLImageTypes.def"
477*0b57cec5SDimitry Andric #define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
478*0b57cec5SDimitry Andric   case BuiltinType::Id:
479*0b57cec5SDimitry Andric #include "clang/Basic/OpenCLExtensionTypes.def"
480*0b57cec5SDimitry Andric   case BuiltinType::OCLSampler:
481*0b57cec5SDimitry Andric   case BuiltinType::OCLEvent:
482*0b57cec5SDimitry Andric   case BuiltinType::OCLClkEvent:
483*0b57cec5SDimitry Andric   case BuiltinType::OCLQueue:
484*0b57cec5SDimitry Andric   case BuiltinType::OCLReserveID:
485*0b57cec5SDimitry Andric   case BuiltinType::BoundMember:
486*0b57cec5SDimitry Andric   case BuiltinType::Dependent:
487*0b57cec5SDimitry Andric   case BuiltinType::Overload:
488*0b57cec5SDimitry Andric   case BuiltinType::UnknownAny:
489*0b57cec5SDimitry Andric   case BuiltinType::ARCUnbridgedCast:
490*0b57cec5SDimitry Andric   case BuiltinType::Half:
491*0b57cec5SDimitry Andric   case BuiltinType::PseudoObject:
492*0b57cec5SDimitry Andric   case BuiltinType::BuiltinFn:
493*0b57cec5SDimitry Andric   case BuiltinType::OMPArraySection:
494*0b57cec5SDimitry Andric     break;
495*0b57cec5SDimitry Andric   }
496*0b57cec5SDimitry Andric 
497*0b57cec5SDimitry Andric   return None;
498*0b57cec5SDimitry Andric }
499*0b57cec5SDimitry Andric 
500*0b57cec5SDimitry Andric /// Returns true if \param T is a typedef of "BOOL" in objective-c.
501*0b57cec5SDimitry Andric bool NSAPI::isObjCBOOLType(QualType T) const {
502*0b57cec5SDimitry Andric   return isObjCTypedef(T, "BOOL", BOOLId);
503*0b57cec5SDimitry Andric }
504*0b57cec5SDimitry Andric /// Returns true if \param T is a typedef of "NSInteger" in objective-c.
505*0b57cec5SDimitry Andric bool NSAPI::isObjCNSIntegerType(QualType T) const {
506*0b57cec5SDimitry Andric   return isObjCTypedef(T, "NSInteger", NSIntegerId);
507*0b57cec5SDimitry Andric }
508*0b57cec5SDimitry Andric /// Returns true if \param T is a typedef of "NSUInteger" in objective-c.
509*0b57cec5SDimitry Andric bool NSAPI::isObjCNSUIntegerType(QualType T) const {
510*0b57cec5SDimitry Andric   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
511*0b57cec5SDimitry Andric }
512*0b57cec5SDimitry Andric 
513*0b57cec5SDimitry Andric StringRef NSAPI::GetNSIntegralKind(QualType T) const {
514*0b57cec5SDimitry Andric   if (!Ctx.getLangOpts().ObjC || T.isNull())
515*0b57cec5SDimitry Andric     return StringRef();
516*0b57cec5SDimitry Andric 
517*0b57cec5SDimitry Andric   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
518*0b57cec5SDimitry Andric     StringRef NSIntegralResust =
519*0b57cec5SDimitry Andric       llvm::StringSwitch<StringRef>(
520*0b57cec5SDimitry Andric         TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
521*0b57cec5SDimitry Andric     .Case("int8_t", "int8_t")
522*0b57cec5SDimitry Andric     .Case("int16_t", "int16_t")
523*0b57cec5SDimitry Andric     .Case("int32_t", "int32_t")
524*0b57cec5SDimitry Andric     .Case("NSInteger", "NSInteger")
525*0b57cec5SDimitry Andric     .Case("int64_t", "int64_t")
526*0b57cec5SDimitry Andric     .Case("uint8_t", "uint8_t")
527*0b57cec5SDimitry Andric     .Case("uint16_t", "uint16_t")
528*0b57cec5SDimitry Andric     .Case("uint32_t", "uint32_t")
529*0b57cec5SDimitry Andric     .Case("NSUInteger", "NSUInteger")
530*0b57cec5SDimitry Andric     .Case("uint64_t", "uint64_t")
531*0b57cec5SDimitry Andric     .Default(StringRef());
532*0b57cec5SDimitry Andric     if (!NSIntegralResust.empty())
533*0b57cec5SDimitry Andric       return NSIntegralResust;
534*0b57cec5SDimitry Andric     T = TDT->desugar();
535*0b57cec5SDimitry Andric   }
536*0b57cec5SDimitry Andric   return StringRef();
537*0b57cec5SDimitry Andric }
538*0b57cec5SDimitry Andric 
539*0b57cec5SDimitry Andric bool NSAPI::isMacroDefined(StringRef Id) const {
540*0b57cec5SDimitry Andric   // FIXME: Check whether the relevant module macros are visible.
541*0b57cec5SDimitry Andric   return Ctx.Idents.get(Id).hasMacroDefinition();
542*0b57cec5SDimitry Andric }
543*0b57cec5SDimitry Andric 
544*0b57cec5SDimitry Andric bool NSAPI::isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl,
545*0b57cec5SDimitry Andric                                 NSClassIdKindKind NSClassKind) const {
546*0b57cec5SDimitry Andric   if (!InterfaceDecl) {
547*0b57cec5SDimitry Andric     return false;
548*0b57cec5SDimitry Andric   }
549*0b57cec5SDimitry Andric 
550*0b57cec5SDimitry Andric   IdentifierInfo *NSClassID = getNSClassId(NSClassKind);
551*0b57cec5SDimitry Andric 
552*0b57cec5SDimitry Andric   bool IsSubclass = false;
553*0b57cec5SDimitry Andric   do {
554*0b57cec5SDimitry Andric     IsSubclass = NSClassID == InterfaceDecl->getIdentifier();
555*0b57cec5SDimitry Andric 
556*0b57cec5SDimitry Andric     if (IsSubclass) {
557*0b57cec5SDimitry Andric       break;
558*0b57cec5SDimitry Andric     }
559*0b57cec5SDimitry Andric   } while ((InterfaceDecl = InterfaceDecl->getSuperClass()));
560*0b57cec5SDimitry Andric 
561*0b57cec5SDimitry Andric   return IsSubclass;
562*0b57cec5SDimitry Andric }
563*0b57cec5SDimitry Andric 
564*0b57cec5SDimitry Andric bool NSAPI::isObjCTypedef(QualType T,
565*0b57cec5SDimitry Andric                           StringRef name, IdentifierInfo *&II) const {
566*0b57cec5SDimitry Andric   if (!Ctx.getLangOpts().ObjC)
567*0b57cec5SDimitry Andric     return false;
568*0b57cec5SDimitry Andric   if (T.isNull())
569*0b57cec5SDimitry Andric     return false;
570*0b57cec5SDimitry Andric 
571*0b57cec5SDimitry Andric   if (!II)
572*0b57cec5SDimitry Andric     II = &Ctx.Idents.get(name);
573*0b57cec5SDimitry Andric 
574*0b57cec5SDimitry Andric   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
575*0b57cec5SDimitry Andric     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
576*0b57cec5SDimitry Andric       return true;
577*0b57cec5SDimitry Andric     T = TDT->desugar();
578*0b57cec5SDimitry Andric   }
579*0b57cec5SDimitry Andric 
580*0b57cec5SDimitry Andric   return false;
581*0b57cec5SDimitry Andric }
582*0b57cec5SDimitry Andric 
583*0b57cec5SDimitry Andric bool NSAPI::isObjCEnumerator(const Expr *E,
584*0b57cec5SDimitry Andric                              StringRef name, IdentifierInfo *&II) const {
585*0b57cec5SDimitry Andric   if (!Ctx.getLangOpts().ObjC)
586*0b57cec5SDimitry Andric     return false;
587*0b57cec5SDimitry Andric   if (!E)
588*0b57cec5SDimitry Andric     return false;
589*0b57cec5SDimitry Andric 
590*0b57cec5SDimitry Andric   if (!II)
591*0b57cec5SDimitry Andric     II = &Ctx.Idents.get(name);
592*0b57cec5SDimitry Andric 
593*0b57cec5SDimitry Andric   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
594*0b57cec5SDimitry Andric     if (const EnumConstantDecl *
595*0b57cec5SDimitry Andric           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
596*0b57cec5SDimitry Andric       return EnumD->getIdentifier() == II;
597*0b57cec5SDimitry Andric 
598*0b57cec5SDimitry Andric   return false;
599*0b57cec5SDimitry Andric }
600*0b57cec5SDimitry Andric 
601*0b57cec5SDimitry Andric Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
602*0b57cec5SDimitry Andric                                   Selector &Sel) const {
603*0b57cec5SDimitry Andric   if (Sel.isNull()) {
604*0b57cec5SDimitry Andric     SmallVector<IdentifierInfo *, 4> Idents;
605*0b57cec5SDimitry Andric     for (ArrayRef<StringRef>::const_iterator
606*0b57cec5SDimitry Andric            I = Ids.begin(), E = Ids.end(); I != E; ++I)
607*0b57cec5SDimitry Andric       Idents.push_back(&Ctx.Idents.get(*I));
608*0b57cec5SDimitry Andric     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
609*0b57cec5SDimitry Andric   }
610*0b57cec5SDimitry Andric   return Sel;
611*0b57cec5SDimitry Andric }
612*0b57cec5SDimitry Andric 
613*0b57cec5SDimitry Andric Selector NSAPI::getOrInitNullarySelector(StringRef Id, Selector &Sel) const {
614*0b57cec5SDimitry Andric   if (Sel.isNull()) {
615*0b57cec5SDimitry Andric     IdentifierInfo *Ident = &Ctx.Idents.get(Id);
616*0b57cec5SDimitry Andric     Sel = Ctx.Selectors.getSelector(0, &Ident);
617*0b57cec5SDimitry Andric   }
618*0b57cec5SDimitry Andric   return Sel;
619*0b57cec5SDimitry Andric }
620