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