xref: /llvm-project-15.0.7/clang/lib/AST/NSAPI.cpp (revision 6bfac7ae)
1 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "clang/AST/NSAPI.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Expr.h"
13 
14 using namespace clang;
15 
16 NSAPI::NSAPI(ASTContext &ctx)
17   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
18     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
19     NSUTF8StringEncodingId(nullptr) {}
20 
21 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
22   static const char *ClassName[NumClassIds] = {
23     "NSObject",
24     "NSString",
25     "NSArray",
26     "NSMutableArray",
27     "NSDictionary",
28     "NSMutableDictionary",
29     "NSNumber"
30   };
31 
32   if (!ClassIds[K])
33     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
34 
35   return ClassIds[K];
36 }
37 
38 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
39   if (NSStringSelectors[MK].isNull()) {
40     Selector Sel;
41     switch (MK) {
42     case NSStr_stringWithString:
43       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
44       break;
45     case NSStr_stringWithUTF8String:
46       Sel = Ctx.Selectors.getUnarySelector(
47                                        &Ctx.Idents.get("stringWithUTF8String"));
48       break;
49     case NSStr_stringWithCStringEncoding: {
50       IdentifierInfo *KeyIdents[] = {
51         &Ctx.Idents.get("stringWithCString"),
52         &Ctx.Idents.get("encoding")
53       };
54       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
55       break;
56     }
57     case NSStr_stringWithCString:
58       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
59       break;
60     case NSStr_initWithString:
61       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
62       break;
63     }
64     return (NSStringSelectors[MK] = Sel);
65   }
66 
67   return NSStringSelectors[MK];
68 }
69 
70 Optional<NSAPI::NSStringMethodKind>
71 NSAPI::getNSStringMethodKind(Selector Sel) const {
72   for (unsigned i = 0; i != NumNSStringMethods; ++i) {
73     NSStringMethodKind MK = NSStringMethodKind(i);
74     if (Sel == getNSStringSelector(MK))
75       return MK;
76   }
77 
78   return None;
79 }
80 
81 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
82   if (NSArraySelectors[MK].isNull()) {
83     Selector Sel;
84     switch (MK) {
85     case NSArr_array:
86       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
87       break;
88     case NSArr_arrayWithArray:
89       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
90       break;
91     case NSArr_arrayWithObject:
92       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
93       break;
94     case NSArr_arrayWithObjects:
95       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
96       break;
97     case NSArr_arrayWithObjectsCount: {
98       IdentifierInfo *KeyIdents[] = {
99         &Ctx.Idents.get("arrayWithObjects"),
100         &Ctx.Idents.get("count")
101       };
102       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
103       break;
104     }
105     case NSArr_initWithArray:
106       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
107       break;
108     case NSArr_initWithObjects:
109       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
110       break;
111     case NSArr_objectAtIndex:
112       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
113       break;
114     case NSMutableArr_replaceObjectAtIndex: {
115       IdentifierInfo *KeyIdents[] = {
116         &Ctx.Idents.get("replaceObjectAtIndex"),
117         &Ctx.Idents.get("withObject")
118       };
119       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
120       break;
121     }
122     case NSArr_initWithObjectsCount: {
123       IdentifierInfo *KeyIdents[] = {
124         &Ctx.Idents.get("initWithObjects"),
125         &Ctx.Idents.get("count")
126       };
127       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
128       break;
129     }
130     }
131     return (NSArraySelectors[MK] = Sel);
132   }
133 
134   return NSArraySelectors[MK];
135 }
136 
137 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
138   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
139     NSArrayMethodKind MK = NSArrayMethodKind(i);
140     if (Sel == getNSArraySelector(MK))
141       return MK;
142   }
143 
144   return None;
145 }
146 
147 Selector NSAPI::getNSDictionarySelector(
148                                        NSDictionaryMethodKind MK) const {
149   if (NSDictionarySelectors[MK].isNull()) {
150     Selector Sel;
151     switch (MK) {
152     case NSDict_dictionary:
153       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
154       break;
155     case NSDict_dictionaryWithDictionary:
156       Sel = Ctx.Selectors.getUnarySelector(
157                                    &Ctx.Idents.get("dictionaryWithDictionary"));
158       break;
159     case NSDict_dictionaryWithObjectForKey: {
160       IdentifierInfo *KeyIdents[] = {
161         &Ctx.Idents.get("dictionaryWithObject"),
162         &Ctx.Idents.get("forKey")
163       };
164       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
165       break;
166     }
167     case NSDict_dictionaryWithObjectsForKeys: {
168       IdentifierInfo *KeyIdents[] = {
169         &Ctx.Idents.get("dictionaryWithObjects"),
170         &Ctx.Idents.get("forKeys")
171       };
172       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
173       break;
174     }
175     case NSDict_dictionaryWithObjectsForKeysCount: {
176       IdentifierInfo *KeyIdents[] = {
177         &Ctx.Idents.get("dictionaryWithObjects"),
178         &Ctx.Idents.get("forKeys"),
179         &Ctx.Idents.get("count")
180       };
181       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
182       break;
183     }
184     case NSDict_dictionaryWithObjectsAndKeys:
185       Sel = Ctx.Selectors.getUnarySelector(
186                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
187       break;
188     case NSDict_initWithDictionary:
189       Sel = Ctx.Selectors.getUnarySelector(
190                                          &Ctx.Idents.get("initWithDictionary"));
191       break;
192     case NSDict_initWithObjectsAndKeys:
193       Sel = Ctx.Selectors.getUnarySelector(
194                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
195       break;
196     case NSDict_initWithObjectsForKeys: {
197       IdentifierInfo *KeyIdents[] = {
198         &Ctx.Idents.get("initWithObjects"),
199         &Ctx.Idents.get("forKeys")
200       };
201       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
202       break;
203     }
204     case NSDict_objectForKey:
205       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
206       break;
207     case NSMutableDict_setObjectForKey: {
208       IdentifierInfo *KeyIdents[] = {
209         &Ctx.Idents.get("setObject"),
210         &Ctx.Idents.get("forKey")
211       };
212       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
213       break;
214     }
215     case NSDict_initWithObjectsForKeysCount: {
216       IdentifierInfo *KeyIdents[] = {
217         &Ctx.Idents.get("initWithObjects"),
218         &Ctx.Idents.get("forKeys"),
219         &Ctx.Idents.get("count")
220       };
221       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
222       break;
223     }
224     }
225     return (NSDictionarySelectors[MK] = Sel);
226   }
227 
228   return NSDictionarySelectors[MK];
229 }
230 
231 Optional<NSAPI::NSDictionaryMethodKind>
232 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
233   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
234     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
235     if (Sel == getNSDictionarySelector(MK))
236       return MK;
237   }
238 
239   return None;
240 }
241 
242 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
243                                            bool Instance) const {
244   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
245     "numberWithChar",
246     "numberWithUnsignedChar",
247     "numberWithShort",
248     "numberWithUnsignedShort",
249     "numberWithInt",
250     "numberWithUnsignedInt",
251     "numberWithLong",
252     "numberWithUnsignedLong",
253     "numberWithLongLong",
254     "numberWithUnsignedLongLong",
255     "numberWithFloat",
256     "numberWithDouble",
257     "numberWithBool",
258     "numberWithInteger",
259     "numberWithUnsignedInteger"
260   };
261   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
262     "initWithChar",
263     "initWithUnsignedChar",
264     "initWithShort",
265     "initWithUnsignedShort",
266     "initWithInt",
267     "initWithUnsignedInt",
268     "initWithLong",
269     "initWithUnsignedLong",
270     "initWithLongLong",
271     "initWithUnsignedLongLong",
272     "initWithFloat",
273     "initWithDouble",
274     "initWithBool",
275     "initWithInteger",
276     "initWithUnsignedInteger"
277   };
278 
279   Selector *Sels;
280   const char **Names;
281   if (Instance) {
282     Sels = NSNumberInstanceSelectors;
283     Names = InstanceSelectorName;
284   } else {
285     Sels = NSNumberClassSelectors;
286     Names = ClassSelectorName;
287   }
288 
289   if (Sels[MK].isNull())
290     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
291   return Sels[MK];
292 }
293 
294 Optional<NSAPI::NSNumberLiteralMethodKind>
295 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
296   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
297     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
298     if (isNSNumberLiteralSelector(MK, Sel))
299       return MK;
300   }
301 
302   return None;
303 }
304 
305 Optional<NSAPI::NSNumberLiteralMethodKind>
306 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
307   const BuiltinType *BT = T->getAs<BuiltinType>();
308   if (!BT)
309     return None;
310 
311   const TypedefType *TDT = T->getAs<TypedefType>();
312   if (TDT) {
313     QualType TDTTy = QualType(TDT, 0);
314     if (isObjCBOOLType(TDTTy))
315       return NSAPI::NSNumberWithBool;
316     if (isObjCNSIntegerType(TDTTy))
317       return NSAPI::NSNumberWithInteger;
318     if (isObjCNSUIntegerType(TDTTy))
319       return NSAPI::NSNumberWithUnsignedInteger;
320   }
321 
322   switch (BT->getKind()) {
323   case BuiltinType::Char_S:
324   case BuiltinType::SChar:
325     return NSAPI::NSNumberWithChar;
326   case BuiltinType::Char_U:
327   case BuiltinType::UChar:
328     return NSAPI::NSNumberWithUnsignedChar;
329   case BuiltinType::Short:
330     return NSAPI::NSNumberWithShort;
331   case BuiltinType::UShort:
332     return NSAPI::NSNumberWithUnsignedShort;
333   case BuiltinType::Int:
334     return NSAPI::NSNumberWithInt;
335   case BuiltinType::UInt:
336     return NSAPI::NSNumberWithUnsignedInt;
337   case BuiltinType::Long:
338     return NSAPI::NSNumberWithLong;
339   case BuiltinType::ULong:
340     return NSAPI::NSNumberWithUnsignedLong;
341   case BuiltinType::LongLong:
342     return NSAPI::NSNumberWithLongLong;
343   case BuiltinType::ULongLong:
344     return NSAPI::NSNumberWithUnsignedLongLong;
345   case BuiltinType::Float:
346     return NSAPI::NSNumberWithFloat;
347   case BuiltinType::Double:
348     return NSAPI::NSNumberWithDouble;
349   case BuiltinType::Bool:
350     return NSAPI::NSNumberWithBool;
351 
352   case BuiltinType::Void:
353   case BuiltinType::WChar_U:
354   case BuiltinType::WChar_S:
355   case BuiltinType::Char16:
356   case BuiltinType::Char32:
357   case BuiltinType::Int128:
358   case BuiltinType::LongDouble:
359   case BuiltinType::UInt128:
360   case BuiltinType::NullPtr:
361   case BuiltinType::ObjCClass:
362   case BuiltinType::ObjCId:
363   case BuiltinType::ObjCSel:
364   case BuiltinType::OCLImage1d:
365   case BuiltinType::OCLImage1dArray:
366   case BuiltinType::OCLImage1dBuffer:
367   case BuiltinType::OCLImage2d:
368   case BuiltinType::OCLImage2dArray:
369   case BuiltinType::OCLImage3d:
370   case BuiltinType::OCLSampler:
371   case BuiltinType::OCLEvent:
372   case BuiltinType::BoundMember:
373   case BuiltinType::Dependent:
374   case BuiltinType::Overload:
375   case BuiltinType::UnknownAny:
376   case BuiltinType::ARCUnbridgedCast:
377   case BuiltinType::Half:
378   case BuiltinType::PseudoObject:
379   case BuiltinType::BuiltinFn:
380     break;
381   }
382 
383   return None;
384 }
385 
386 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
387 bool NSAPI::isObjCBOOLType(QualType T) const {
388   return isObjCTypedef(T, "BOOL", BOOLId);
389 }
390 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
391 bool NSAPI::isObjCNSIntegerType(QualType T) const {
392   return isObjCTypedef(T, "NSInteger", NSIntegerId);
393 }
394 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
395 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
396   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
397 }
398 
399 bool NSAPI::isObjCTypedef(QualType T,
400                           StringRef name, IdentifierInfo *&II) const {
401   if (!Ctx.getLangOpts().ObjC1)
402     return false;
403   if (T.isNull())
404     return false;
405 
406   if (!II)
407     II = &Ctx.Idents.get(name);
408 
409   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
410     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
411       return true;
412     T = TDT->desugar();
413   }
414 
415   return false;
416 }
417 
418 bool NSAPI::isObjCEnumerator(const Expr *E,
419                              StringRef name, IdentifierInfo *&II) const {
420   if (!Ctx.getLangOpts().ObjC1)
421     return false;
422   if (!E)
423     return false;
424 
425   if (!II)
426     II = &Ctx.Idents.get(name);
427 
428   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
429     if (const EnumConstantDecl *
430           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
431       return EnumD->getIdentifier() == II;
432 
433   return false;
434 }
435 
436 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
437                                   Selector &Sel) const {
438   if (Sel.isNull()) {
439     SmallVector<IdentifierInfo *, 4> Idents;
440     for (ArrayRef<StringRef>::const_iterator
441            I = Ids.begin(), E = Ids.end(); I != E; ++I)
442       Idents.push_back(&Ctx.Idents.get(*I));
443     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
444   }
445   return Sel;
446 }
447