blob: a862630bbf8d793220f3e3eefa81288f94c69a88 [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
David Blaikiedc84cd52013-02-20 22:23:23 +000070Optional<NSAPI::NSStringMethodKind>
Guy Benyei7f92f2d2012-12-18 14:30:41 +000071NSAPI::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
David Blaikie66874fb2013-02-21 01:47:18 +000078 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +000079}
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
David Blaikiedc84cd52013-02-20 22:23:23 +0000129Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000130 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
131 NSArrayMethodKind MK = NSArrayMethodKind(i);
132 if (Sel == getNSArraySelector(MK))
133 return MK;
134 }
135
David Blaikie66874fb2013-02-21 01:47:18 +0000136 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000137}
138
139Selector NSAPI::getNSDictionarySelector(
140 NSDictionaryMethodKind MK) const {
141 if (NSDictionarySelectors[MK].isNull()) {
142 Selector Sel;
143 switch (MK) {
144 case NSDict_dictionary:
145 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
146 break;
147 case NSDict_dictionaryWithDictionary:
148 Sel = Ctx.Selectors.getUnarySelector(
149 &Ctx.Idents.get("dictionaryWithDictionary"));
150 break;
151 case NSDict_dictionaryWithObjectForKey: {
152 IdentifierInfo *KeyIdents[] = {
153 &Ctx.Idents.get("dictionaryWithObject"),
154 &Ctx.Idents.get("forKey")
155 };
156 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
157 break;
158 }
159 case NSDict_dictionaryWithObjectsForKeys: {
160 IdentifierInfo *KeyIdents[] = {
161 &Ctx.Idents.get("dictionaryWithObjects"),
162 &Ctx.Idents.get("forKeys")
163 };
164 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
165 break;
166 }
167 case NSDict_dictionaryWithObjectsForKeysCount: {
168 IdentifierInfo *KeyIdents[] = {
169 &Ctx.Idents.get("dictionaryWithObjects"),
170 &Ctx.Idents.get("forKeys"),
171 &Ctx.Idents.get("count")
172 };
173 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
174 break;
175 }
176 case NSDict_dictionaryWithObjectsAndKeys:
177 Sel = Ctx.Selectors.getUnarySelector(
178 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
179 break;
180 case NSDict_initWithDictionary:
181 Sel = Ctx.Selectors.getUnarySelector(
182 &Ctx.Idents.get("initWithDictionary"));
183 break;
184 case NSDict_initWithObjectsAndKeys:
185 Sel = Ctx.Selectors.getUnarySelector(
186 &Ctx.Idents.get("initWithObjectsAndKeys"));
187 break;
Argyrios Kyrtzidisa44b9702013-01-16 23:54:48 +0000188 case NSDict_initWithObjectsForKeys: {
189 IdentifierInfo *KeyIdents[] = {
190 &Ctx.Idents.get("initWithObjects"),
191 &Ctx.Idents.get("forKeys")
192 };
193 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
194 break;
195 }
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000196 case NSDict_objectForKey:
197 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
198 break;
199 case NSMutableDict_setObjectForKey: {
200 IdentifierInfo *KeyIdents[] = {
201 &Ctx.Idents.get("setObject"),
202 &Ctx.Idents.get("forKey")
203 };
204 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
205 break;
206 }
207 }
208 return (NSDictionarySelectors[MK] = Sel);
209 }
210
211 return NSDictionarySelectors[MK];
212}
213
David Blaikiedc84cd52013-02-20 22:23:23 +0000214Optional<NSAPI::NSDictionaryMethodKind>
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000215NSAPI::getNSDictionaryMethodKind(Selector Sel) {
216 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
217 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
218 if (Sel == getNSDictionarySelector(MK))
219 return MK;
220 }
221
David Blaikie66874fb2013-02-21 01:47:18 +0000222 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000223}
224
225Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
226 bool Instance) const {
227 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
228 "numberWithChar",
229 "numberWithUnsignedChar",
230 "numberWithShort",
231 "numberWithUnsignedShort",
232 "numberWithInt",
233 "numberWithUnsignedInt",
234 "numberWithLong",
235 "numberWithUnsignedLong",
236 "numberWithLongLong",
237 "numberWithUnsignedLongLong",
238 "numberWithFloat",
239 "numberWithDouble",
240 "numberWithBool",
241 "numberWithInteger",
242 "numberWithUnsignedInteger"
243 };
244 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
245 "initWithChar",
246 "initWithUnsignedChar",
247 "initWithShort",
248 "initWithUnsignedShort",
249 "initWithInt",
250 "initWithUnsignedInt",
251 "initWithLong",
252 "initWithUnsignedLong",
253 "initWithLongLong",
254 "initWithUnsignedLongLong",
255 "initWithFloat",
256 "initWithDouble",
257 "initWithBool",
258 "initWithInteger",
259 "initWithUnsignedInteger"
260 };
261
262 Selector *Sels;
263 const char **Names;
264 if (Instance) {
265 Sels = NSNumberInstanceSelectors;
266 Names = InstanceSelectorName;
267 } else {
268 Sels = NSNumberClassSelectors;
269 Names = ClassSelectorName;
270 }
271
272 if (Sels[MK].isNull())
273 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
274 return Sels[MK];
275}
276
David Blaikiedc84cd52013-02-20 22:23:23 +0000277Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000278NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
279 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
280 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
281 if (isNSNumberLiteralSelector(MK, Sel))
282 return MK;
283 }
284
David Blaikie66874fb2013-02-21 01:47:18 +0000285 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000286}
287
David Blaikiedc84cd52013-02-20 22:23:23 +0000288Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000289NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
290 const BuiltinType *BT = T->getAs<BuiltinType>();
291 if (!BT)
David Blaikie66874fb2013-02-21 01:47:18 +0000292 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000293
294 const TypedefType *TDT = T->getAs<TypedefType>();
295 if (TDT) {
296 QualType TDTTy = QualType(TDT, 0);
297 if (isObjCBOOLType(TDTTy))
298 return NSAPI::NSNumberWithBool;
299 if (isObjCNSIntegerType(TDTTy))
300 return NSAPI::NSNumberWithInteger;
301 if (isObjCNSUIntegerType(TDTTy))
302 return NSAPI::NSNumberWithUnsignedInteger;
303 }
304
305 switch (BT->getKind()) {
306 case BuiltinType::Char_S:
307 case BuiltinType::SChar:
308 return NSAPI::NSNumberWithChar;
309 case BuiltinType::Char_U:
310 case BuiltinType::UChar:
311 return NSAPI::NSNumberWithUnsignedChar;
312 case BuiltinType::Short:
313 return NSAPI::NSNumberWithShort;
314 case BuiltinType::UShort:
315 return NSAPI::NSNumberWithUnsignedShort;
316 case BuiltinType::Int:
317 return NSAPI::NSNumberWithInt;
318 case BuiltinType::UInt:
319 return NSAPI::NSNumberWithUnsignedInt;
320 case BuiltinType::Long:
321 return NSAPI::NSNumberWithLong;
322 case BuiltinType::ULong:
323 return NSAPI::NSNumberWithUnsignedLong;
324 case BuiltinType::LongLong:
325 return NSAPI::NSNumberWithLongLong;
326 case BuiltinType::ULongLong:
327 return NSAPI::NSNumberWithUnsignedLongLong;
328 case BuiltinType::Float:
329 return NSAPI::NSNumberWithFloat;
330 case BuiltinType::Double:
331 return NSAPI::NSNumberWithDouble;
332 case BuiltinType::Bool:
333 return NSAPI::NSNumberWithBool;
334
335 case BuiltinType::Void:
336 case BuiltinType::WChar_U:
337 case BuiltinType::WChar_S:
338 case BuiltinType::Char16:
339 case BuiltinType::Char32:
340 case BuiltinType::Int128:
341 case BuiltinType::LongDouble:
342 case BuiltinType::UInt128:
343 case BuiltinType::NullPtr:
344 case BuiltinType::ObjCClass:
345 case BuiltinType::ObjCId:
346 case BuiltinType::ObjCSel:
Guy Benyeib13621d2012-12-18 14:38:23 +0000347 case BuiltinType::OCLImage1d:
348 case BuiltinType::OCLImage1dArray:
349 case BuiltinType::OCLImage1dBuffer:
350 case BuiltinType::OCLImage2d:
351 case BuiltinType::OCLImage2dArray:
352 case BuiltinType::OCLImage3d:
Guy Benyei21f18c42013-02-07 10:55:47 +0000353 case BuiltinType::OCLSampler:
Guy Benyeie6b9d802013-01-20 12:31:11 +0000354 case BuiltinType::OCLEvent:
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000355 case BuiltinType::BoundMember:
356 case BuiltinType::Dependent:
357 case BuiltinType::Overload:
358 case BuiltinType::UnknownAny:
359 case BuiltinType::ARCUnbridgedCast:
360 case BuiltinType::Half:
361 case BuiltinType::PseudoObject:
362 case BuiltinType::BuiltinFn:
363 break;
364 }
365
David Blaikie66874fb2013-02-21 01:47:18 +0000366 return None;
Guy Benyei7f92f2d2012-12-18 14:30:41 +0000367}
368
369/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
370bool NSAPI::isObjCBOOLType(QualType T) const {
371 return isObjCTypedef(T, "BOOL", BOOLId);
372}
373/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
374bool NSAPI::isObjCNSIntegerType(QualType T) const {
375 return isObjCTypedef(T, "NSInteger", NSIntegerId);
376}
377/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
378bool NSAPI::isObjCNSUIntegerType(QualType T) const {
379 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
380}
381
382bool NSAPI::isObjCTypedef(QualType T,
383 StringRef name, IdentifierInfo *&II) const {
384 if (!Ctx.getLangOpts().ObjC1)
385 return false;
386 if (T.isNull())
387 return false;
388
389 if (!II)
390 II = &Ctx.Idents.get(name);
391
392 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
393 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
394 return true;
395 T = TDT->desugar();
396 }
397
398 return false;
399}
400
401bool NSAPI::isObjCEnumerator(const Expr *E,
402 StringRef name, IdentifierInfo *&II) const {
403 if (!Ctx.getLangOpts().ObjC1)
404 return false;
405 if (!E)
406 return false;
407
408 if (!II)
409 II = &Ctx.Idents.get(name);
410
411 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
412 if (const EnumConstantDecl *
413 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
414 return EnumD->getIdentifier() == II;
415
416 return false;
417}
418
419Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
420 Selector &Sel) const {
421 if (Sel.isNull()) {
422 SmallVector<IdentifierInfo *, 4> Idents;
423 for (ArrayRef<StringRef>::const_iterator
424 I = Ids.begin(), E = Ids.end(); I != E; ++I)
425 Idents.push_back(&Ctx.Idents.get(*I));
426 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
427 }
428 return Sel;
429}