]> CyberLeo.Net >> Repos - FreeBSD/stable/9.git/blob - contrib/llvm/tools/clang/lib/AST/NSAPI.cpp
MFC r244628:
[FreeBSD/stable/9.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
14 using namespace clang;
15
16 NSAPI::NSAPI(ASTContext &ctx)
17   : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
18     NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
19 }
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 llvm::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 llvm::Optional<NSStringMethodKind>();
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     }
123     return (NSArraySelectors[MK] = Sel);
124   }
125
126   return NSArraySelectors[MK];
127 }
128
129 llvm::Optional<NSAPI::NSArrayMethodKind>
130 NSAPI::getNSArrayMethodKind(Selector Sel) {
131   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
132     NSArrayMethodKind MK = NSArrayMethodKind(i);
133     if (Sel == getNSArraySelector(MK))
134       return MK;
135   }
136
137   return llvm::Optional<NSArrayMethodKind>();
138 }
139
140 Selector NSAPI::getNSDictionarySelector(
141                                        NSDictionaryMethodKind MK) const {
142   if (NSDictionarySelectors[MK].isNull()) {
143     Selector Sel;
144     switch (MK) {
145     case NSDict_dictionary:
146       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
147       break;
148     case NSDict_dictionaryWithDictionary:
149       Sel = Ctx.Selectors.getUnarySelector(
150                                    &Ctx.Idents.get("dictionaryWithDictionary"));
151       break;
152     case NSDict_dictionaryWithObjectForKey: {
153       IdentifierInfo *KeyIdents[] = {
154         &Ctx.Idents.get("dictionaryWithObject"),
155         &Ctx.Idents.get("forKey")
156       };
157       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
158       break;
159     }
160     case NSDict_dictionaryWithObjectsForKeys: {
161       IdentifierInfo *KeyIdents[] = {
162         &Ctx.Idents.get("dictionaryWithObjects"),
163         &Ctx.Idents.get("forKeys")
164       };
165       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
166       break;
167     }
168     case NSDict_dictionaryWithObjectsForKeysCount: {
169       IdentifierInfo *KeyIdents[] = {
170         &Ctx.Idents.get("dictionaryWithObjects"),
171         &Ctx.Idents.get("forKeys"),
172         &Ctx.Idents.get("count")
173       };
174       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
175       break;
176     }
177     case NSDict_dictionaryWithObjectsAndKeys:
178       Sel = Ctx.Selectors.getUnarySelector(
179                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
180       break;
181     case NSDict_initWithDictionary:
182       Sel = Ctx.Selectors.getUnarySelector(
183                                          &Ctx.Idents.get("initWithDictionary"));
184       break;
185     case NSDict_initWithObjectsAndKeys:
186       Sel = Ctx.Selectors.getUnarySelector(
187                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
188       break;
189     case NSDict_objectForKey:
190       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
191       break;
192     case NSMutableDict_setObjectForKey: {
193       IdentifierInfo *KeyIdents[] = {
194         &Ctx.Idents.get("setObject"),
195         &Ctx.Idents.get("forKey")
196       };
197       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
198       break;
199     }
200     }
201     return (NSDictionarySelectors[MK] = Sel);
202   }
203
204   return NSDictionarySelectors[MK];
205 }
206
207 llvm::Optional<NSAPI::NSDictionaryMethodKind>
208 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
209   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
210     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
211     if (Sel == getNSDictionarySelector(MK))
212       return MK;
213   }
214
215   return llvm::Optional<NSDictionaryMethodKind>();
216 }
217
218 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
219                                            bool Instance) const {
220   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
221     "numberWithChar",
222     "numberWithUnsignedChar",
223     "numberWithShort",
224     "numberWithUnsignedShort",
225     "numberWithInt",
226     "numberWithUnsignedInt",
227     "numberWithLong",
228     "numberWithUnsignedLong",
229     "numberWithLongLong",
230     "numberWithUnsignedLongLong",
231     "numberWithFloat",
232     "numberWithDouble",
233     "numberWithBool",
234     "numberWithInteger",
235     "numberWithUnsignedInteger"
236   };
237   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
238     "initWithChar",
239     "initWithUnsignedChar",
240     "initWithShort",
241     "initWithUnsignedShort",
242     "initWithInt",
243     "initWithUnsignedInt",
244     "initWithLong",
245     "initWithUnsignedLong",
246     "initWithLongLong",
247     "initWithUnsignedLongLong",
248     "initWithFloat",
249     "initWithDouble",
250     "initWithBool",
251     "initWithInteger",
252     "initWithUnsignedInteger"
253   };
254
255   Selector *Sels;
256   const char **Names;
257   if (Instance) {
258     Sels = NSNumberInstanceSelectors;
259     Names = InstanceSelectorName;
260   } else {
261     Sels = NSNumberClassSelectors;
262     Names = ClassSelectorName;
263   }
264
265   if (Sels[MK].isNull())
266     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
267   return Sels[MK];
268 }
269
270 llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
271 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
272   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
273     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
274     if (isNSNumberLiteralSelector(MK, Sel))
275       return MK;
276   }
277
278   return llvm::Optional<NSNumberLiteralMethodKind>();
279 }
280
281 llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
282 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
283   const BuiltinType *BT = T->getAs<BuiltinType>();
284   if (!BT)
285     return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
286
287   const TypedefType *TDT = T->getAs<TypedefType>();
288   if (TDT) {
289     QualType TDTTy = QualType(TDT, 0);
290     if (isObjCBOOLType(TDTTy))
291       return NSAPI::NSNumberWithBool;
292     if (isObjCNSIntegerType(TDTTy))
293       return NSAPI::NSNumberWithInteger;
294     if (isObjCNSUIntegerType(TDTTy))
295       return NSAPI::NSNumberWithUnsignedInteger;
296   }
297
298   switch (BT->getKind()) {
299   case BuiltinType::Char_S:
300   case BuiltinType::SChar:
301     return NSAPI::NSNumberWithChar;
302   case BuiltinType::Char_U:
303   case BuiltinType::UChar:
304     return NSAPI::NSNumberWithUnsignedChar;
305   case BuiltinType::Short:
306     return NSAPI::NSNumberWithShort;
307   case BuiltinType::UShort:
308     return NSAPI::NSNumberWithUnsignedShort;
309   case BuiltinType::Int:
310     return NSAPI::NSNumberWithInt;
311   case BuiltinType::UInt:
312     return NSAPI::NSNumberWithUnsignedInt;
313   case BuiltinType::Long:
314     return NSAPI::NSNumberWithLong;
315   case BuiltinType::ULong:
316     return NSAPI::NSNumberWithUnsignedLong;
317   case BuiltinType::LongLong:
318     return NSAPI::NSNumberWithLongLong;
319   case BuiltinType::ULongLong:
320     return NSAPI::NSNumberWithUnsignedLongLong;
321   case BuiltinType::Float:
322     return NSAPI::NSNumberWithFloat;
323   case BuiltinType::Double:
324     return NSAPI::NSNumberWithDouble;
325   case BuiltinType::Bool:
326     return NSAPI::NSNumberWithBool;
327     
328   case BuiltinType::Void:
329   case BuiltinType::WChar_U:
330   case BuiltinType::WChar_S:
331   case BuiltinType::Char16:
332   case BuiltinType::Char32:
333   case BuiltinType::Int128:
334   case BuiltinType::LongDouble:
335   case BuiltinType::UInt128:
336   case BuiltinType::NullPtr:
337   case BuiltinType::ObjCClass:
338   case BuiltinType::ObjCId:
339   case BuiltinType::ObjCSel:
340   case BuiltinType::BoundMember:
341   case BuiltinType::Dependent:
342   case BuiltinType::Overload:
343   case BuiltinType::UnknownAny:
344   case BuiltinType::ARCUnbridgedCast:
345   case BuiltinType::Half:
346   case BuiltinType::PseudoObject:
347   case BuiltinType::BuiltinFn:
348     break;
349   }
350   
351   return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
352 }
353
354 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
355 bool NSAPI::isObjCBOOLType(QualType T) const {
356   return isObjCTypedef(T, "BOOL", BOOLId);
357 }
358 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
359 bool NSAPI::isObjCNSIntegerType(QualType T) const {
360   return isObjCTypedef(T, "NSInteger", NSIntegerId);
361 }
362 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
363 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
364   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
365 }
366
367 bool NSAPI::isObjCTypedef(QualType T,
368                           StringRef name, IdentifierInfo *&II) const {
369   if (!Ctx.getLangOpts().ObjC1)
370     return false;
371   if (T.isNull())
372     return false;
373
374   if (!II)
375     II = &Ctx.Idents.get(name);
376
377   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
378     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
379       return true;
380     T = TDT->desugar();
381   }
382
383   return false;
384 }
385
386 bool NSAPI::isObjCEnumerator(const Expr *E,
387                              StringRef name, IdentifierInfo *&II) const {
388   if (!Ctx.getLangOpts().ObjC1)
389     return false;
390   if (!E)
391     return false;
392
393   if (!II)
394     II = &Ctx.Idents.get(name);
395
396   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
397     if (const EnumConstantDecl *
398           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
399       return EnumD->getIdentifier() == II;
400
401   return false;
402 }
403
404 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
405                                   Selector &Sel) const {
406   if (Sel.isNull()) {
407     SmallVector<IdentifierInfo *, 4> Idents;
408     for (ArrayRef<StringRef>::const_iterator
409            I = Ids.begin(), E = Ids.end(); I != E; ++I)
410       Idents.push_back(&Ctx.Idents.get(*I));
411     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
412   }
413   return Sel;
414 }