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