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