blob: 0837509194bc6b90696abdf28fab1a3c9d374c95 [file] [log] [blame]
Ted Kremenekebcb57a2012-03-06 20:05:56 +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"
Argyrios Kyrtzidis7fe103c2012-05-15 22:22:10 +000012#include "clang/AST/Expr.h"
Ted Kremenekebcb57a2012-03-06 20:05:56 +000013
14using namespace clang;
15
16NSAPI::NSAPI(ASTContext &ctx)
Argyrios Kyrtzidis7fe103c2012-05-15 22:22:10 +000017 : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0),
18 NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +000019}
20
21IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
22 static const char *ClassName[NumClassIds] = {
Patrick Beardb2f68202012-04-06 18:12:22 +000023 "NSObject",
Ted Kremenekebcb57a2012-03-06 20:05:56 +000024 "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;
Argyrios Kyrtzidis7fe103c2012-05-15 22:22:10 +000045 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;
Ted Kremenekebcb57a2012-03-06 20:05:56 +000060 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
Argyrios Kyrtzidis7fe103c2012-05-15 22:22:10 +000070llvm::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
Ted Kremenekebcb57a2012-03-06 20:05:56 +000081Selector 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;
189 case NSDict_objectForKey:
190 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
191 break;
192 case NSMutableDict_setObjectForKey: {
193 IdentifierInfo *KeyIdents[] = {
194 &Ctx.Idents.get("setObject"),
195 &Ctx.Idents.get("forKey")
196 };
197 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
198 break;
199 }
200 }
201 return (NSDictionarySelectors[MK] = Sel);
202 }
203
204 return NSDictionarySelectors[MK];
205}
206
207llvm::Optional<NSAPI::NSDictionaryMethodKind>
208NSAPI::getNSDictionaryMethodKind(Selector Sel) {
209 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
210 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
211 if (Sel == getNSDictionarySelector(MK))
212 return MK;
213 }
214
215 return llvm::Optional<NSDictionaryMethodKind>();
216}
217
218Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
219 bool Instance) const {
220 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
221 "numberWithChar",
222 "numberWithUnsignedChar",
223 "numberWithShort",
224 "numberWithUnsignedShort",
225 "numberWithInt",
226 "numberWithUnsignedInt",
227 "numberWithLong",
228 "numberWithUnsignedLong",
229 "numberWithLongLong",
230 "numberWithUnsignedLongLong",
231 "numberWithFloat",
232 "numberWithDouble",
233 "numberWithBool",
234 "numberWithInteger",
235 "numberWithUnsignedInteger"
236 };
237 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
238 "initWithChar",
239 "initWithUnsignedChar",
240 "initWithShort",
241 "initWithUnsignedShort",
242 "initWithInt",
243 "initWithUnsignedInt",
244 "initWithLong",
245 "initWithUnsignedLong",
246 "initWithLongLong",
247 "initWithUnsignedLongLong",
248 "initWithFloat",
249 "initWithDouble",
250 "initWithBool",
251 "initWithInteger",
252 "initWithUnsignedInteger"
253 };
254
255 Selector *Sels;
256 const char **Names;
257 if (Instance) {
258 Sels = NSNumberInstanceSelectors;
259 Names = InstanceSelectorName;
260 } else {
261 Sels = NSNumberClassSelectors;
262 Names = ClassSelectorName;
263 }
264
265 if (Sels[MK].isNull())
266 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
267 return Sels[MK];
268}
269
270llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
271NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
272 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
273 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
274 if (isNSNumberLiteralSelector(MK, Sel))
275 return MK;
276 }
277
278 return llvm::Optional<NSNumberLiteralMethodKind>();
279}
280
281llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000282NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000283 const BuiltinType *BT = T->getAs<BuiltinType>();
284 if (!BT)
285 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000286
287 const TypedefType *TDT = T->getAs<TypedefType>();
288 if (TDT) {
289 QualType TDTTy = QualType(TDT, 0);
290 if (isObjCBOOLType(TDTTy))
291 return NSAPI::NSNumberWithBool;
292 if (isObjCNSIntegerType(TDTTy))
293 return NSAPI::NSNumberWithInteger;
294 if (isObjCNSUIntegerType(TDTTy))
295 return NSAPI::NSNumberWithUnsignedInteger;
296 }
297
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000298 switch (BT->getKind()) {
299 case BuiltinType::Char_S:
300 case BuiltinType::SChar:
301 return NSAPI::NSNumberWithChar;
302 case BuiltinType::Char_U:
303 case BuiltinType::UChar:
304 return NSAPI::NSNumberWithUnsignedChar;
305 case BuiltinType::Short:
306 return NSAPI::NSNumberWithShort;
307 case BuiltinType::UShort:
308 return NSAPI::NSNumberWithUnsignedShort;
309 case BuiltinType::Int:
310 return NSAPI::NSNumberWithInt;
311 case BuiltinType::UInt:
312 return NSAPI::NSNumberWithUnsignedInt;
313 case BuiltinType::Long:
314 return NSAPI::NSNumberWithLong;
315 case BuiltinType::ULong:
316 return NSAPI::NSNumberWithUnsignedLong;
317 case BuiltinType::LongLong:
318 return NSAPI::NSNumberWithLongLong;
319 case BuiltinType::ULongLong:
320 return NSAPI::NSNumberWithUnsignedLongLong;
321 case BuiltinType::Float:
322 return NSAPI::NSNumberWithFloat;
323 case BuiltinType::Double:
324 return NSAPI::NSNumberWithDouble;
325 case BuiltinType::Bool:
326 return NSAPI::NSNumberWithBool;
327
328 case BuiltinType::Void:
329 case BuiltinType::WChar_U:
330 case BuiltinType::WChar_S:
331 case BuiltinType::Char16:
332 case BuiltinType::Char32:
333 case BuiltinType::Int128:
334 case BuiltinType::LongDouble:
335 case BuiltinType::UInt128:
336 case BuiltinType::NullPtr:
337 case BuiltinType::ObjCClass:
338 case BuiltinType::ObjCId:
339 case BuiltinType::ObjCSel:
340 case BuiltinType::BoundMember:
341 case BuiltinType::Dependent:
342 case BuiltinType::Overload:
343 case BuiltinType::UnknownAny:
344 case BuiltinType::ARCUnbridgedCast:
345 case BuiltinType::Half:
346 case BuiltinType::PseudoObject:
Eli Friedmana6c66ce2012-08-31 00:14:07 +0000347 case BuiltinType::BuiltinFn:
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000348 break;
349 }
350
351 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
352}
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000353
354/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
355bool NSAPI::isObjCBOOLType(QualType T) const {
356 return isObjCTypedef(T, "BOOL", BOOLId);
357}
358/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
359bool NSAPI::isObjCNSIntegerType(QualType T) const {
360 return isObjCTypedef(T, "NSInteger", NSIntegerId);
361}
362/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
363bool NSAPI::isObjCNSUIntegerType(QualType T) const {
364 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
365}
366
367bool NSAPI::isObjCTypedef(QualType T,
368 StringRef name, IdentifierInfo *&II) const {
369 if (!Ctx.getLangOpts().ObjC1)
370 return false;
371 if (T.isNull())
372 return false;
373
374 if (!II)
375 II = &Ctx.Idents.get(name);
376
377 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
378 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
379 return true;
380 T = TDT->desugar();
381 }
382
383 return false;
384}
Argyrios Kyrtzidis7fe103c2012-05-15 22:22:10 +0000385
386bool NSAPI::isObjCEnumerator(const Expr *E,
387 StringRef name, IdentifierInfo *&II) const {
388 if (!Ctx.getLangOpts().ObjC1)
389 return false;
390 if (!E)
391 return false;
392
393 if (!II)
394 II = &Ctx.Idents.get(name);
395
396 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
397 if (const EnumConstantDecl *
398 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
399 return EnumD->getIdentifier() == II;
400
401 return false;
402}
Argyrios Kyrtzidiscacf7182012-06-04 21:23:26 +0000403
404Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
405 Selector &Sel) const {
406 if (Sel.isNull()) {
407 SmallVector<IdentifierInfo *, 4> Idents;
408 for (ArrayRef<StringRef>::const_iterator
409 I = Ids.begin(), E = Ids.end(); I != E; ++I)
410 Idents.push_back(&Ctx.Idents.get(*I));
411 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
412 }
413 return Sel;
414}