blob: c6afc8e38195d4feec4f7c2fa9b9f518b76ebd60 [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;
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 Blaikie05785d12013-02-20 22:23:23 +000070Optional<NSAPI::NSStringMethodKind>
Guy Benyei11169dd2012-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 Blaikie7a30dc52013-02-21 01:47:18 +000078 return None;
Guy Benyei11169dd2012-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 }
Fariborz Jahanian501e71c2014-08-06 20:56:21 +0000122 case NSArr_initWithObjectsCount: {
123 IdentifierInfo *KeyIdents[] = {
124 &Ctx.Idents.get("initWithObjects"),
125 &Ctx.Idents.get("count")
126 };
127 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
128 break;
129 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000130 }
131 return (NSArraySelectors[MK] = Sel);
132 }
133
134 return NSArraySelectors[MK];
135}
136
David Blaikie05785d12013-02-20 22:23:23 +0000137Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
Guy Benyei11169dd2012-12-18 14:30:41 +0000138 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
139 NSArrayMethodKind MK = NSArrayMethodKind(i);
140 if (Sel == getNSArraySelector(MK))
141 return MK;
142 }
143
David Blaikie7a30dc52013-02-21 01:47:18 +0000144 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000145}
146
147Selector NSAPI::getNSDictionarySelector(
148 NSDictionaryMethodKind MK) const {
149 if (NSDictionarySelectors[MK].isNull()) {
150 Selector Sel;
151 switch (MK) {
152 case NSDict_dictionary:
153 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
154 break;
155 case NSDict_dictionaryWithDictionary:
156 Sel = Ctx.Selectors.getUnarySelector(
157 &Ctx.Idents.get("dictionaryWithDictionary"));
158 break;
159 case NSDict_dictionaryWithObjectForKey: {
160 IdentifierInfo *KeyIdents[] = {
161 &Ctx.Idents.get("dictionaryWithObject"),
162 &Ctx.Idents.get("forKey")
163 };
164 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
165 break;
166 }
167 case NSDict_dictionaryWithObjectsForKeys: {
168 IdentifierInfo *KeyIdents[] = {
169 &Ctx.Idents.get("dictionaryWithObjects"),
170 &Ctx.Idents.get("forKeys")
171 };
172 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
173 break;
174 }
175 case NSDict_dictionaryWithObjectsForKeysCount: {
176 IdentifierInfo *KeyIdents[] = {
177 &Ctx.Idents.get("dictionaryWithObjects"),
178 &Ctx.Idents.get("forKeys"),
179 &Ctx.Idents.get("count")
180 };
181 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
182 break;
183 }
184 case NSDict_dictionaryWithObjectsAndKeys:
185 Sel = Ctx.Selectors.getUnarySelector(
186 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
187 break;
188 case NSDict_initWithDictionary:
189 Sel = Ctx.Selectors.getUnarySelector(
190 &Ctx.Idents.get("initWithDictionary"));
191 break;
192 case NSDict_initWithObjectsAndKeys:
193 Sel = Ctx.Selectors.getUnarySelector(
194 &Ctx.Idents.get("initWithObjectsAndKeys"));
195 break;
Argyrios Kyrtzidis6b4f3412013-01-16 23:54:48 +0000196 case NSDict_initWithObjectsForKeys: {
197 IdentifierInfo *KeyIdents[] = {
198 &Ctx.Idents.get("initWithObjects"),
199 &Ctx.Idents.get("forKeys")
200 };
201 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
202 break;
203 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000204 case NSDict_objectForKey:
205 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
206 break;
207 case NSMutableDict_setObjectForKey: {
208 IdentifierInfo *KeyIdents[] = {
209 &Ctx.Idents.get("setObject"),
210 &Ctx.Idents.get("forKey")
211 };
212 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
213 break;
214 }
Fariborz Jahanian501e71c2014-08-06 20:56:21 +0000215 case NSDict_initWithObjectsForKeysCount: {
216 IdentifierInfo *KeyIdents[] = {
217 &Ctx.Idents.get("initWithObjects"),
218 &Ctx.Idents.get("forKeys"),
219 &Ctx.Idents.get("count")
220 };
221 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
222 break;
223 }
Guy Benyei11169dd2012-12-18 14:30:41 +0000224 }
225 return (NSDictionarySelectors[MK] = Sel);
226 }
227
228 return NSDictionarySelectors[MK];
229}
230
David Blaikie05785d12013-02-20 22:23:23 +0000231Optional<NSAPI::NSDictionaryMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000232NSAPI::getNSDictionaryMethodKind(Selector Sel) {
233 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
234 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
235 if (Sel == getNSDictionarySelector(MK))
236 return MK;
237 }
238
David Blaikie7a30dc52013-02-21 01:47:18 +0000239 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000240}
241
242Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
243 bool Instance) const {
244 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
245 "numberWithChar",
246 "numberWithUnsignedChar",
247 "numberWithShort",
248 "numberWithUnsignedShort",
249 "numberWithInt",
250 "numberWithUnsignedInt",
251 "numberWithLong",
252 "numberWithUnsignedLong",
253 "numberWithLongLong",
254 "numberWithUnsignedLongLong",
255 "numberWithFloat",
256 "numberWithDouble",
257 "numberWithBool",
258 "numberWithInteger",
259 "numberWithUnsignedInteger"
260 };
261 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
262 "initWithChar",
263 "initWithUnsignedChar",
264 "initWithShort",
265 "initWithUnsignedShort",
266 "initWithInt",
267 "initWithUnsignedInt",
268 "initWithLong",
269 "initWithUnsignedLong",
270 "initWithLongLong",
271 "initWithUnsignedLongLong",
272 "initWithFloat",
273 "initWithDouble",
274 "initWithBool",
275 "initWithInteger",
276 "initWithUnsignedInteger"
277 };
278
279 Selector *Sels;
280 const char **Names;
281 if (Instance) {
282 Sels = NSNumberInstanceSelectors;
283 Names = InstanceSelectorName;
284 } else {
285 Sels = NSNumberClassSelectors;
286 Names = ClassSelectorName;
287 }
288
289 if (Sels[MK].isNull())
290 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
291 return Sels[MK];
292}
293
David Blaikie05785d12013-02-20 22:23:23 +0000294Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000295NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
296 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
297 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
298 if (isNSNumberLiteralSelector(MK, Sel))
299 return MK;
300 }
301
David Blaikie7a30dc52013-02-21 01:47:18 +0000302 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000303}
304
David Blaikie05785d12013-02-20 22:23:23 +0000305Optional<NSAPI::NSNumberLiteralMethodKind>
Guy Benyei11169dd2012-12-18 14:30:41 +0000306NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
307 const BuiltinType *BT = T->getAs<BuiltinType>();
308 if (!BT)
David Blaikie7a30dc52013-02-21 01:47:18 +0000309 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000310
311 const TypedefType *TDT = T->getAs<TypedefType>();
312 if (TDT) {
313 QualType TDTTy = QualType(TDT, 0);
314 if (isObjCBOOLType(TDTTy))
315 return NSAPI::NSNumberWithBool;
316 if (isObjCNSIntegerType(TDTTy))
317 return NSAPI::NSNumberWithInteger;
318 if (isObjCNSUIntegerType(TDTTy))
319 return NSAPI::NSNumberWithUnsignedInteger;
320 }
321
322 switch (BT->getKind()) {
323 case BuiltinType::Char_S:
324 case BuiltinType::SChar:
325 return NSAPI::NSNumberWithChar;
326 case BuiltinType::Char_U:
327 case BuiltinType::UChar:
328 return NSAPI::NSNumberWithUnsignedChar;
329 case BuiltinType::Short:
330 return NSAPI::NSNumberWithShort;
331 case BuiltinType::UShort:
332 return NSAPI::NSNumberWithUnsignedShort;
333 case BuiltinType::Int:
334 return NSAPI::NSNumberWithInt;
335 case BuiltinType::UInt:
336 return NSAPI::NSNumberWithUnsignedInt;
337 case BuiltinType::Long:
338 return NSAPI::NSNumberWithLong;
339 case BuiltinType::ULong:
340 return NSAPI::NSNumberWithUnsignedLong;
341 case BuiltinType::LongLong:
342 return NSAPI::NSNumberWithLongLong;
343 case BuiltinType::ULongLong:
344 return NSAPI::NSNumberWithUnsignedLongLong;
345 case BuiltinType::Float:
346 return NSAPI::NSNumberWithFloat;
347 case BuiltinType::Double:
348 return NSAPI::NSNumberWithDouble;
349 case BuiltinType::Bool:
350 return NSAPI::NSNumberWithBool;
351
352 case BuiltinType::Void:
353 case BuiltinType::WChar_U:
354 case BuiltinType::WChar_S:
355 case BuiltinType::Char16:
356 case BuiltinType::Char32:
357 case BuiltinType::Int128:
358 case BuiltinType::LongDouble:
359 case BuiltinType::UInt128:
360 case BuiltinType::NullPtr:
361 case BuiltinType::ObjCClass:
362 case BuiltinType::ObjCId:
363 case BuiltinType::ObjCSel:
Guy Benyeid8a08ea2012-12-18 14:38:23 +0000364 case BuiltinType::OCLImage1d:
365 case BuiltinType::OCLImage1dArray:
366 case BuiltinType::OCLImage1dBuffer:
367 case BuiltinType::OCLImage2d:
368 case BuiltinType::OCLImage2dArray:
369 case BuiltinType::OCLImage3d:
Guy Benyei61054192013-02-07 10:55:47 +0000370 case BuiltinType::OCLSampler:
Guy Benyei1b4fb3e2013-01-20 12:31:11 +0000371 case BuiltinType::OCLEvent:
Guy Benyei11169dd2012-12-18 14:30:41 +0000372 case BuiltinType::BoundMember:
373 case BuiltinType::Dependent:
374 case BuiltinType::Overload:
375 case BuiltinType::UnknownAny:
376 case BuiltinType::ARCUnbridgedCast:
377 case BuiltinType::Half:
378 case BuiltinType::PseudoObject:
379 case BuiltinType::BuiltinFn:
380 break;
381 }
382
David Blaikie7a30dc52013-02-21 01:47:18 +0000383 return None;
Guy Benyei11169dd2012-12-18 14:30:41 +0000384}
385
386/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
387bool NSAPI::isObjCBOOLType(QualType T) const {
388 return isObjCTypedef(T, "BOOL", BOOLId);
389}
390/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
391bool NSAPI::isObjCNSIntegerType(QualType T) const {
392 return isObjCTypedef(T, "NSInteger", NSIntegerId);
393}
394/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
395bool NSAPI::isObjCNSUIntegerType(QualType T) const {
396 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
397}
398
399bool NSAPI::isObjCTypedef(QualType T,
400 StringRef name, IdentifierInfo *&II) const {
401 if (!Ctx.getLangOpts().ObjC1)
402 return false;
403 if (T.isNull())
404 return false;
405
406 if (!II)
407 II = &Ctx.Idents.get(name);
408
409 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
410 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
411 return true;
412 T = TDT->desugar();
413 }
414
415 return false;
416}
417
418bool NSAPI::isObjCEnumerator(const Expr *E,
419 StringRef name, IdentifierInfo *&II) const {
420 if (!Ctx.getLangOpts().ObjC1)
421 return false;
422 if (!E)
423 return false;
424
425 if (!II)
426 II = &Ctx.Idents.get(name);
427
428 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
429 if (const EnumConstantDecl *
430 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
431 return EnumD->getIdentifier() == II;
432
433 return false;
434}
435
436Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
437 Selector &Sel) const {
438 if (Sel.isNull()) {
439 SmallVector<IdentifierInfo *, 4> Idents;
440 for (ArrayRef<StringRef>::const_iterator
441 I = Ids.begin(), E = Ids.end(); I != E; ++I)
442 Idents.push_back(&Ctx.Idents.get(*I));
443 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
444 }
445 return Sel;
446}