blob: 579a92cacc90235ebef8de75730c8feaf479318b [file] [log] [blame]
Guy Benyei11169dd2012-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)
Craig Topper36250ad2014-05-12 05:36:57 +000017 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
18 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
19 NSUTF8StringEncodingId(nullptr) {}
Guy Benyei11169dd2012-12-18 14:30:41 +000020
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;
Fariborz Jahanianbe7bf722014-08-25 20:22:25 +000049 case NSStr_initWithUTF8String:
50 Sel = Ctx.Selectors.getUnarySelector(
51 &Ctx.Idents.get("initWithUTF8String"));
52 break;
Guy Benyei11169dd2012-12-18 14:30:41 +000053 case NSStr_stringWithCStringEncoding: {
54 IdentifierInfo *KeyIdents[] = {
55 &Ctx.Idents.get("stringWithCString"),
56 &Ctx.Idents.get("encoding")
57 };
58 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
59 break;
60 }
61 case NSStr_stringWithCString:
62 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
63 break;
64 case NSStr_initWithString:
65 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
66 break;
67 }
68 return (NSStringSelectors[MK] = Sel);
69 }
70
71 return NSStringSelectors[MK];
72}
73
David Blaikie05785d12013-02-20 22:23:23 +000074Optional<NSAPI::NSStringMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +000075NSAPI::getNSStringMethodKind(Selector Sel) const {
76 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
77 NSStringMethodKind MK = NSStringMethodKind(i);
78 if (Sel == getNSStringSelector(MK))
79 return MK;
80 }
81
David Blaikie7a30dc52013-02-21 01:47:18 +000082 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +000083}
84
85Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
86 if (NSArraySelectors[MK].isNull()) {
87 Selector Sel;
88 switch (MK) {
89 case NSArr_array:
90 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
91 break;
92 case NSArr_arrayWithArray:
93 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
94 break;
95 case NSArr_arrayWithObject:
96 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
97 break;
98 case NSArr_arrayWithObjects:
99 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
100 break;
101 case NSArr_arrayWithObjectsCount: {
102 IdentifierInfo *KeyIdents[] = {
103 &Ctx.Idents.get("arrayWithObjects"),
104 &Ctx.Idents.get("count")
105 };
106 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
107 break;
108 }
109 case NSArr_initWithArray:
110 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
111 break;
112 case NSArr_initWithObjects:
113 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
114 break;
115 case NSArr_objectAtIndex:
116 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
117 break;
118 case NSMutableArr_replaceObjectAtIndex: {
119 IdentifierInfo *KeyIdents[] = {
120 &Ctx.Idents.get("replaceObjectAtIndex"),
121 &Ctx.Idents.get("withObject")
122 };
123 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
124 break;
125 }
Fariborz Jahanian501e71c2014-08-06 20:56:21 +0000126 case NSArr_initWithObjectsCount: {
127 IdentifierInfo *KeyIdents[] = {
128 &Ctx.Idents.get("initWithObjects"),
129 &Ctx.Idents.get("count")
130 };
131 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
132 break;
133 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000134 }
135 return (NSArraySelectors[MK] = Sel);
136 }
137
138 return NSArraySelectors[MK];
139}
140
David Blaikie05785d12013-02-20 22:23:23 +0000141Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
Guy Benyei11169dd2012-12-18 14:30:41 +0000142 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
143 NSArrayMethodKind MK = NSArrayMethodKind(i);
144 if (Sel == getNSArraySelector(MK))
145 return MK;
146 }
147
David Blaikie7a30dc52013-02-21 01:47:18 +0000148 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000149}
150
151Selector NSAPI::getNSDictionarySelector(
152 NSDictionaryMethodKind MK) const {
153 if (NSDictionarySelectors[MK].isNull()) {
154 Selector Sel;
155 switch (MK) {
156 case NSDict_dictionary:
157 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
158 break;
159 case NSDict_dictionaryWithDictionary:
160 Sel = Ctx.Selectors.getUnarySelector(
161 &Ctx.Idents.get("dictionaryWithDictionary"));
162 break;
163 case NSDict_dictionaryWithObjectForKey: {
164 IdentifierInfo *KeyIdents[] = {
165 &Ctx.Idents.get("dictionaryWithObject"),
166 &Ctx.Idents.get("forKey")
167 };
168 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
169 break;
170 }
171 case NSDict_dictionaryWithObjectsForKeys: {
172 IdentifierInfo *KeyIdents[] = {
173 &Ctx.Idents.get("dictionaryWithObjects"),
174 &Ctx.Idents.get("forKeys")
175 };
176 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
177 break;
178 }
179 case NSDict_dictionaryWithObjectsForKeysCount: {
180 IdentifierInfo *KeyIdents[] = {
181 &Ctx.Idents.get("dictionaryWithObjects"),
182 &Ctx.Idents.get("forKeys"),
183 &Ctx.Idents.get("count")
184 };
185 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
186 break;
187 }
188 case NSDict_dictionaryWithObjectsAndKeys:
189 Sel = Ctx.Selectors.getUnarySelector(
190 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
191 break;
192 case NSDict_initWithDictionary:
193 Sel = Ctx.Selectors.getUnarySelector(
194 &Ctx.Idents.get("initWithDictionary"));
195 break;
196 case NSDict_initWithObjectsAndKeys:
197 Sel = Ctx.Selectors.getUnarySelector(
198 &Ctx.Idents.get("initWithObjectsAndKeys"));
199 break;
Argyrios Kyrtzidis6b4f3412013-01-16 23:54:48 +0000200 case NSDict_initWithObjectsForKeys: {
201 IdentifierInfo *KeyIdents[] = {
202 &Ctx.Idents.get("initWithObjects"),
203 &Ctx.Idents.get("forKeys")
204 };
205 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
206 break;
207 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000208 case NSDict_objectForKey:
209 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
210 break;
211 case NSMutableDict_setObjectForKey: {
212 IdentifierInfo *KeyIdents[] = {
213 &Ctx.Idents.get("setObject"),
214 &Ctx.Idents.get("forKey")
215 };
216 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
217 break;
218 }
Fariborz Jahanian501e71c2014-08-06 20:56:21 +0000219 case NSDict_initWithObjectsForKeysCount: {
220 IdentifierInfo *KeyIdents[] = {
221 &Ctx.Idents.get("initWithObjects"),
222 &Ctx.Idents.get("forKeys"),
223 &Ctx.Idents.get("count")
224 };
225 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
226 break;
227 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000228 }
229 return (NSDictionarySelectors[MK] = Sel);
230 }
231
232 return NSDictionarySelectors[MK];
233}
234
David Blaikie05785d12013-02-20 22:23:23 +0000235Optional<NSAPI::NSDictionaryMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000236NSAPI::getNSDictionaryMethodKind(Selector Sel) {
237 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
238 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
239 if (Sel == getNSDictionarySelector(MK))
240 return MK;
241 }
242
David Blaikie7a30dc52013-02-21 01:47:18 +0000243 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000244}
245
246Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
247 bool Instance) const {
248 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
249 "numberWithChar",
250 "numberWithUnsignedChar",
251 "numberWithShort",
252 "numberWithUnsignedShort",
253 "numberWithInt",
254 "numberWithUnsignedInt",
255 "numberWithLong",
256 "numberWithUnsignedLong",
257 "numberWithLongLong",
258 "numberWithUnsignedLongLong",
259 "numberWithFloat",
260 "numberWithDouble",
261 "numberWithBool",
262 "numberWithInteger",
263 "numberWithUnsignedInteger"
264 };
265 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
266 "initWithChar",
267 "initWithUnsignedChar",
268 "initWithShort",
269 "initWithUnsignedShort",
270 "initWithInt",
271 "initWithUnsignedInt",
272 "initWithLong",
273 "initWithUnsignedLong",
274 "initWithLongLong",
275 "initWithUnsignedLongLong",
276 "initWithFloat",
277 "initWithDouble",
278 "initWithBool",
279 "initWithInteger",
280 "initWithUnsignedInteger"
281 };
282
283 Selector *Sels;
284 const char **Names;
285 if (Instance) {
286 Sels = NSNumberInstanceSelectors;
287 Names = InstanceSelectorName;
288 } else {
289 Sels = NSNumberClassSelectors;
290 Names = ClassSelectorName;
291 }
292
293 if (Sels[MK].isNull())
294 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
295 return Sels[MK];
296}
297
David Blaikie05785d12013-02-20 22:23:23 +0000298Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000299NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
300 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
301 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
302 if (isNSNumberLiteralSelector(MK, Sel))
303 return MK;
304 }
305
David Blaikie7a30dc52013-02-21 01:47:18 +0000306 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000307}
308
David Blaikie05785d12013-02-20 22:23:23 +0000309Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000310NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
311 const BuiltinType *BT = T->getAs<BuiltinType>();
312 if (!BT)
David Blaikie7a30dc52013-02-21 01:47:18 +0000313 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000314
315 const TypedefType *TDT = T->getAs<TypedefType>();
316 if (TDT) {
317 QualType TDTTy = QualType(TDT, 0);
318 if (isObjCBOOLType(TDTTy))
319 return NSAPI::NSNumberWithBool;
320 if (isObjCNSIntegerType(TDTTy))
321 return NSAPI::NSNumberWithInteger;
322 if (isObjCNSUIntegerType(TDTTy))
323 return NSAPI::NSNumberWithUnsignedInteger;
324 }
325
326 switch (BT->getKind()) {
327 case BuiltinType::Char_S:
328 case BuiltinType::SChar:
329 return NSAPI::NSNumberWithChar;
330 case BuiltinType::Char_U:
331 case BuiltinType::UChar:
332 return NSAPI::NSNumberWithUnsignedChar;
333 case BuiltinType::Short:
334 return NSAPI::NSNumberWithShort;
335 case BuiltinType::UShort:
336 return NSAPI::NSNumberWithUnsignedShort;
337 case BuiltinType::Int:
338 return NSAPI::NSNumberWithInt;
339 case BuiltinType::UInt:
340 return NSAPI::NSNumberWithUnsignedInt;
341 case BuiltinType::Long:
342 return NSAPI::NSNumberWithLong;
343 case BuiltinType::ULong:
344 return NSAPI::NSNumberWithUnsignedLong;
345 case BuiltinType::LongLong:
346 return NSAPI::NSNumberWithLongLong;
347 case BuiltinType::ULongLong:
348 return NSAPI::NSNumberWithUnsignedLongLong;
349 case BuiltinType::Float:
350 return NSAPI::NSNumberWithFloat;
351 case BuiltinType::Double:
352 return NSAPI::NSNumberWithDouble;
353 case BuiltinType::Bool:
354 return NSAPI::NSNumberWithBool;
355
356 case BuiltinType::Void:
357 case BuiltinType::WChar_U:
358 case BuiltinType::WChar_S:
359 case BuiltinType::Char16:
360 case BuiltinType::Char32:
361 case BuiltinType::Int128:
362 case BuiltinType::LongDouble:
363 case BuiltinType::UInt128:
364 case BuiltinType::NullPtr:
365 case BuiltinType::ObjCClass:
366 case BuiltinType::ObjCId:
367 case BuiltinType::ObjCSel:
Guy Benyeid8a08ea2012-12-18 14:38:23 +0000368 case BuiltinType::OCLImage1d:
369 case BuiltinType::OCLImage1dArray:
370 case BuiltinType::OCLImage1dBuffer:
371 case BuiltinType::OCLImage2d:
372 case BuiltinType::OCLImage2dArray:
373 case BuiltinType::OCLImage3d:
Guy Benyei61054192013-02-07 10:55:47 +0000374 case BuiltinType::OCLSampler:
Guy Benyei1b4fb3e2013-01-20 12:31:11 +0000375 case BuiltinType::OCLEvent:
Guy Benyei11169dd2012-12-18 14:30:41 +0000376 case BuiltinType::BoundMember:
377 case BuiltinType::Dependent:
378 case BuiltinType::Overload:
379 case BuiltinType::UnknownAny:
380 case BuiltinType::ARCUnbridgedCast:
381 case BuiltinType::Half:
382 case BuiltinType::PseudoObject:
383 case BuiltinType::BuiltinFn:
384 break;
385 }
386
David Blaikie7a30dc52013-02-21 01:47:18 +0000387 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000388}
389
390/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
391bool NSAPI::isObjCBOOLType(QualType T) const {
392 return isObjCTypedef(T, "BOOL", BOOLId);
393}
394/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
395bool NSAPI::isObjCNSIntegerType(QualType T) const {
396 return isObjCTypedef(T, "NSInteger", NSIntegerId);
397}
398/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
399bool NSAPI::isObjCNSUIntegerType(QualType T) const {
400 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
401}
402
403bool NSAPI::isObjCTypedef(QualType T,
404 StringRef name, IdentifierInfo *&II) const {
405 if (!Ctx.getLangOpts().ObjC1)
406 return false;
407 if (T.isNull())
408 return false;
409
410 if (!II)
411 II = &Ctx.Idents.get(name);
412
413 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
414 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
415 return true;
416 T = TDT->desugar();
417 }
418
419 return false;
420}
421
422bool NSAPI::isObjCEnumerator(const Expr *E,
423 StringRef name, IdentifierInfo *&II) const {
424 if (!Ctx.getLangOpts().ObjC1)
425 return false;
426 if (!E)
427 return false;
428
429 if (!II)
430 II = &Ctx.Idents.get(name);
431
432 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
433 if (const EnumConstantDecl *
434 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
435 return EnumD->getIdentifier() == II;
436
437 return false;
438}
439
440Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
441 Selector &Sel) const {
442 if (Sel.isNull()) {
443 SmallVector<IdentifierInfo *, 4> Idents;
444 for (ArrayRef<StringRef>::const_iterator
445 I = Ids.begin(), E = Ids.end(); I != E; ++I)
446 Idents.push_back(&Ctx.Idents.get(*I));
447 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
448 }
449 return Sel;
450}