blob: 4c20235ed871acf63bf6cd734672e3db0d337082 [file] [log] [blame]
Guy Benyei7f92f2d2012-12-18 14:30:41 +00001//===--- 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
14using namespace clang;
15
16NSAPI::NSAPI(ASTContext &ctx)
17 : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
18 NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
19}
20
21IdentifierInfo *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
38Selector 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
70llvm::Optional<NSAPI::NSStringMethodKind>
71NSAPI::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
81Selector 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
129llvm::Optional<NSAPI::NSArrayMethodKind>
130NSAPI::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
140Selector 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;
Argyrios Kyrtzidisa44b9702013-01-16 23:54:48 +0000189 case NSDict_initWithObjectsForKeys: {
190 IdentifierInfo *KeyIdents[] = {
191 &Ctx.Idents.get("initWithObjects"),
192 &Ctx.Idents.get("forKeys")
193 };
194 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
195 break;
196 }
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000197 case NSDict_objectForKey:
198 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
199 break;
200 case NSMutableDict_setObjectForKey: {
201 IdentifierInfo *KeyIdents[] = {
202 &Ctx.Idents.get("setObject"),
203 &Ctx.Idents.get("forKey")
204 };
205 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
206 break;
207 }
208 }
209 return (NSDictionarySelectors[MK] = Sel);
210 }
211
212 return NSDictionarySelectors[MK];
213}
214
215llvm::Optional<NSAPI::NSDictionaryMethodKind>
216NSAPI::getNSDictionaryMethodKind(Selector Sel) {
217 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
218 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
219 if (Sel == getNSDictionarySelector(MK))
220 return MK;
221 }
222
223 return llvm::Optional<NSDictionaryMethodKind>();
224}
225
226Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
227 bool Instance) const {
228 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
229 "numberWithChar",
230 "numberWithUnsignedChar",
231 "numberWithShort",
232 "numberWithUnsignedShort",
233 "numberWithInt",
234 "numberWithUnsignedInt",
235 "numberWithLong",
236 "numberWithUnsignedLong",
237 "numberWithLongLong",
238 "numberWithUnsignedLongLong",
239 "numberWithFloat",
240 "numberWithDouble",
241 "numberWithBool",
242 "numberWithInteger",
243 "numberWithUnsignedInteger"
244 };
245 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
246 "initWithChar",
247 "initWithUnsignedChar",
248 "initWithShort",
249 "initWithUnsignedShort",
250 "initWithInt",
251 "initWithUnsignedInt",
252 "initWithLong",
253 "initWithUnsignedLong",
254 "initWithLongLong",
255 "initWithUnsignedLongLong",
256 "initWithFloat",
257 "initWithDouble",
258 "initWithBool",
259 "initWithInteger",
260 "initWithUnsignedInteger"
261 };
262
263 Selector *Sels;
264 const char **Names;
265 if (Instance) {
266 Sels = NSNumberInstanceSelectors;
267 Names = InstanceSelectorName;
268 } else {
269 Sels = NSNumberClassSelectors;
270 Names = ClassSelectorName;
271 }
272
273 if (Sels[MK].isNull())
274 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
275 return Sels[MK];
276}
277
278llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
279NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
280 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
281 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
282 if (isNSNumberLiteralSelector(MK, Sel))
283 return MK;
284 }
285
286 return llvm::Optional<NSNumberLiteralMethodKind>();
287}
288
289llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
290NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
291 const BuiltinType *BT = T->getAs<BuiltinType>();
292 if (!BT)
293 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
294
295 const TypedefType *TDT = T->getAs<TypedefType>();
296 if (TDT) {
297 QualType TDTTy = QualType(TDT, 0);
298 if (isObjCBOOLType(TDTTy))
299 return NSAPI::NSNumberWithBool;
300 if (isObjCNSIntegerType(TDTTy))
301 return NSAPI::NSNumberWithInteger;
302 if (isObjCNSUIntegerType(TDTTy))
303 return NSAPI::NSNumberWithUnsignedInteger;
304 }
305
306 switch (BT->getKind()) {
307 case BuiltinType::Char_S:
308 case BuiltinType::SChar:
309 return NSAPI::NSNumberWithChar;
310 case BuiltinType::Char_U:
311 case BuiltinType::UChar:
312 return NSAPI::NSNumberWithUnsignedChar;
313 case BuiltinType::Short:
314 return NSAPI::NSNumberWithShort;
315 case BuiltinType::UShort:
316 return NSAPI::NSNumberWithUnsignedShort;
317 case BuiltinType::Int:
318 return NSAPI::NSNumberWithInt;
319 case BuiltinType::UInt:
320 return NSAPI::NSNumberWithUnsignedInt;
321 case BuiltinType::Long:
322 return NSAPI::NSNumberWithLong;
323 case BuiltinType::ULong:
324 return NSAPI::NSNumberWithUnsignedLong;
325 case BuiltinType::LongLong:
326 return NSAPI::NSNumberWithLongLong;
327 case BuiltinType::ULongLong:
328 return NSAPI::NSNumberWithUnsignedLongLong;
329 case BuiltinType::Float:
330 return NSAPI::NSNumberWithFloat;
331 case BuiltinType::Double:
332 return NSAPI::NSNumberWithDouble;
333 case BuiltinType::Bool:
334 return NSAPI::NSNumberWithBool;
335
336 case BuiltinType::Void:
337 case BuiltinType::WChar_U:
338 case BuiltinType::WChar_S:
339 case BuiltinType::Char16:
340 case BuiltinType::Char32:
341 case BuiltinType::Int128:
342 case BuiltinType::LongDouble:
343 case BuiltinType::UInt128:
344 case BuiltinType::NullPtr:
345 case BuiltinType::ObjCClass:
346 case BuiltinType::ObjCId:
347 case BuiltinType::ObjCSel:
Guy Benyeib13621d2012-12-18 14:38:23 +0000348 case BuiltinType::OCLImage1d:
349 case BuiltinType::OCLImage1dArray:
350 case BuiltinType::OCLImage1dBuffer:
351 case BuiltinType::OCLImage2d:
352 case BuiltinType::OCLImage2dArray:
353 case BuiltinType::OCLImage3d:
Guy Benyei21f18c42013-02-07 10:55:47 +0000354 case BuiltinType::OCLSampler:
Guy Benyeie6b9d802013-01-20 12:31:11 +0000355 case BuiltinType::OCLEvent:
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000356 case BuiltinType::BoundMember:
357 case BuiltinType::Dependent:
358 case BuiltinType::Overload:
359 case BuiltinType::UnknownAny:
360 case BuiltinType::ARCUnbridgedCast:
361 case BuiltinType::Half:
362 case BuiltinType::PseudoObject:
363 case BuiltinType::BuiltinFn:
364 break;
365 }
366
367 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
368}
369
370/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
371bool NSAPI::isObjCBOOLType(QualType T) const {
372 return isObjCTypedef(T, "BOOL", BOOLId);
373}
374/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
375bool NSAPI::isObjCNSIntegerType(QualType T) const {
376 return isObjCTypedef(T, "NSInteger", NSIntegerId);
377}
378/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
379bool NSAPI::isObjCNSUIntegerType(QualType T) const {
380 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
381}
382
383bool NSAPI::isObjCTypedef(QualType T,
384 StringRef name, IdentifierInfo *&II) const {
385 if (!Ctx.getLangOpts().ObjC1)
386 return false;
387 if (T.isNull())
388 return false;
389
390 if (!II)
391 II = &Ctx.Idents.get(name);
392
393 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
394 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
395 return true;
396 T = TDT->desugar();
397 }
398
399 return false;
400}
401
402bool NSAPI::isObjCEnumerator(const Expr *E,
403 StringRef name, IdentifierInfo *&II) const {
404 if (!Ctx.getLangOpts().ObjC1)
405 return false;
406 if (!E)
407 return false;
408
409 if (!II)
410 II = &Ctx.Idents.get(name);
411
412 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
413 if (const EnumConstantDecl *
414 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
415 return EnumD->getIdentifier() == II;
416
417 return false;
418}
419
420Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
421 Selector &Sel) const {
422 if (Sel.isNull()) {
423 SmallVector<IdentifierInfo *, 4> Idents;
424 for (ArrayRef<StringRef>::const_iterator
425 I = Ids.begin(), E = Ids.end(); I != E; ++I)
426 Idents.push_back(&Ctx.Idents.get(*I));
427 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
428 }
429 return Sel;
430}