blob: c56e6c16889d08239440612024d2f8cc151ccfef [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"
12
13using namespace clang;
14
15NSAPI::NSAPI(ASTContext &ctx)
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +000016 : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0) {
Ted Kremenekebcb57a2012-03-06 20:05:56 +000017}
18
19IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
20 static const char *ClassName[NumClassIds] = {
Patrick Beardb2f68202012-04-06 18:12:22 +000021 "NSObject",
Ted Kremenekebcb57a2012-03-06 20:05:56 +000022 "NSString",
23 "NSArray",
24 "NSMutableArray",
25 "NSDictionary",
26 "NSMutableDictionary",
27 "NSNumber"
28 };
29
30 if (!ClassIds[K])
31 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
32
33 return ClassIds[K];
34}
35
36Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
37 if (NSStringSelectors[MK].isNull()) {
38 Selector Sel;
39 switch (MK) {
40 case NSStr_stringWithString:
41 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
42 break;
43 case NSStr_initWithString:
44 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
45 break;
46 }
47 return (NSStringSelectors[MK] = Sel);
48 }
49
50 return NSStringSelectors[MK];
51}
52
53Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
54 if (NSArraySelectors[MK].isNull()) {
55 Selector Sel;
56 switch (MK) {
57 case NSArr_array:
58 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
59 break;
60 case NSArr_arrayWithArray:
61 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
62 break;
63 case NSArr_arrayWithObject:
64 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
65 break;
66 case NSArr_arrayWithObjects:
67 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
68 break;
69 case NSArr_arrayWithObjectsCount: {
70 IdentifierInfo *KeyIdents[] = {
71 &Ctx.Idents.get("arrayWithObjects"),
72 &Ctx.Idents.get("count")
73 };
74 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
75 break;
76 }
77 case NSArr_initWithArray:
78 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
79 break;
80 case NSArr_initWithObjects:
81 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
82 break;
83 case NSArr_objectAtIndex:
84 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
85 break;
86 case NSMutableArr_replaceObjectAtIndex: {
87 IdentifierInfo *KeyIdents[] = {
88 &Ctx.Idents.get("replaceObjectAtIndex"),
89 &Ctx.Idents.get("withObject")
90 };
91 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
92 break;
93 }
94 }
95 return (NSArraySelectors[MK] = Sel);
96 }
97
98 return NSArraySelectors[MK];
99}
100
101llvm::Optional<NSAPI::NSArrayMethodKind>
102NSAPI::getNSArrayMethodKind(Selector Sel) {
103 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
104 NSArrayMethodKind MK = NSArrayMethodKind(i);
105 if (Sel == getNSArraySelector(MK))
106 return MK;
107 }
108
109 return llvm::Optional<NSArrayMethodKind>();
110}
111
112Selector NSAPI::getNSDictionarySelector(
113 NSDictionaryMethodKind MK) const {
114 if (NSDictionarySelectors[MK].isNull()) {
115 Selector Sel;
116 switch (MK) {
117 case NSDict_dictionary:
118 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
119 break;
120 case NSDict_dictionaryWithDictionary:
121 Sel = Ctx.Selectors.getUnarySelector(
122 &Ctx.Idents.get("dictionaryWithDictionary"));
123 break;
124 case NSDict_dictionaryWithObjectForKey: {
125 IdentifierInfo *KeyIdents[] = {
126 &Ctx.Idents.get("dictionaryWithObject"),
127 &Ctx.Idents.get("forKey")
128 };
129 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
130 break;
131 }
132 case NSDict_dictionaryWithObjectsForKeys: {
133 IdentifierInfo *KeyIdents[] = {
134 &Ctx.Idents.get("dictionaryWithObjects"),
135 &Ctx.Idents.get("forKeys")
136 };
137 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
138 break;
139 }
140 case NSDict_dictionaryWithObjectsForKeysCount: {
141 IdentifierInfo *KeyIdents[] = {
142 &Ctx.Idents.get("dictionaryWithObjects"),
143 &Ctx.Idents.get("forKeys"),
144 &Ctx.Idents.get("count")
145 };
146 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
147 break;
148 }
149 case NSDict_dictionaryWithObjectsAndKeys:
150 Sel = Ctx.Selectors.getUnarySelector(
151 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
152 break;
153 case NSDict_initWithDictionary:
154 Sel = Ctx.Selectors.getUnarySelector(
155 &Ctx.Idents.get("initWithDictionary"));
156 break;
157 case NSDict_initWithObjectsAndKeys:
158 Sel = Ctx.Selectors.getUnarySelector(
159 &Ctx.Idents.get("initWithObjectsAndKeys"));
160 break;
161 case NSDict_objectForKey:
162 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
163 break;
164 case NSMutableDict_setObjectForKey: {
165 IdentifierInfo *KeyIdents[] = {
166 &Ctx.Idents.get("setObject"),
167 &Ctx.Idents.get("forKey")
168 };
169 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
170 break;
171 }
172 }
173 return (NSDictionarySelectors[MK] = Sel);
174 }
175
176 return NSDictionarySelectors[MK];
177}
178
179llvm::Optional<NSAPI::NSDictionaryMethodKind>
180NSAPI::getNSDictionaryMethodKind(Selector Sel) {
181 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
182 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
183 if (Sel == getNSDictionarySelector(MK))
184 return MK;
185 }
186
187 return llvm::Optional<NSDictionaryMethodKind>();
188}
189
190Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
191 bool Instance) const {
192 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
193 "numberWithChar",
194 "numberWithUnsignedChar",
195 "numberWithShort",
196 "numberWithUnsignedShort",
197 "numberWithInt",
198 "numberWithUnsignedInt",
199 "numberWithLong",
200 "numberWithUnsignedLong",
201 "numberWithLongLong",
202 "numberWithUnsignedLongLong",
203 "numberWithFloat",
204 "numberWithDouble",
205 "numberWithBool",
206 "numberWithInteger",
207 "numberWithUnsignedInteger"
208 };
209 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
210 "initWithChar",
211 "initWithUnsignedChar",
212 "initWithShort",
213 "initWithUnsignedShort",
214 "initWithInt",
215 "initWithUnsignedInt",
216 "initWithLong",
217 "initWithUnsignedLong",
218 "initWithLongLong",
219 "initWithUnsignedLongLong",
220 "initWithFloat",
221 "initWithDouble",
222 "initWithBool",
223 "initWithInteger",
224 "initWithUnsignedInteger"
225 };
226
227 Selector *Sels;
228 const char **Names;
229 if (Instance) {
230 Sels = NSNumberInstanceSelectors;
231 Names = InstanceSelectorName;
232 } else {
233 Sels = NSNumberClassSelectors;
234 Names = ClassSelectorName;
235 }
236
237 if (Sels[MK].isNull())
238 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
239 return Sels[MK];
240}
241
242llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
243NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
244 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
245 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
246 if (isNSNumberLiteralSelector(MK, Sel))
247 return MK;
248 }
249
250 return llvm::Optional<NSNumberLiteralMethodKind>();
251}
252
253llvm::Optional<NSAPI::NSNumberLiteralMethodKind>
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000254NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000255 const BuiltinType *BT = T->getAs<BuiltinType>();
256 if (!BT)
257 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000258
259 const TypedefType *TDT = T->getAs<TypedefType>();
260 if (TDT) {
261 QualType TDTTy = QualType(TDT, 0);
262 if (isObjCBOOLType(TDTTy))
263 return NSAPI::NSNumberWithBool;
264 if (isObjCNSIntegerType(TDTTy))
265 return NSAPI::NSNumberWithInteger;
266 if (isObjCNSUIntegerType(TDTTy))
267 return NSAPI::NSNumberWithUnsignedInteger;
268 }
269
Ted Kremenekebcb57a2012-03-06 20:05:56 +0000270 switch (BT->getKind()) {
271 case BuiltinType::Char_S:
272 case BuiltinType::SChar:
273 return NSAPI::NSNumberWithChar;
274 case BuiltinType::Char_U:
275 case BuiltinType::UChar:
276 return NSAPI::NSNumberWithUnsignedChar;
277 case BuiltinType::Short:
278 return NSAPI::NSNumberWithShort;
279 case BuiltinType::UShort:
280 return NSAPI::NSNumberWithUnsignedShort;
281 case BuiltinType::Int:
282 return NSAPI::NSNumberWithInt;
283 case BuiltinType::UInt:
284 return NSAPI::NSNumberWithUnsignedInt;
285 case BuiltinType::Long:
286 return NSAPI::NSNumberWithLong;
287 case BuiltinType::ULong:
288 return NSAPI::NSNumberWithUnsignedLong;
289 case BuiltinType::LongLong:
290 return NSAPI::NSNumberWithLongLong;
291 case BuiltinType::ULongLong:
292 return NSAPI::NSNumberWithUnsignedLongLong;
293 case BuiltinType::Float:
294 return NSAPI::NSNumberWithFloat;
295 case BuiltinType::Double:
296 return NSAPI::NSNumberWithDouble;
297 case BuiltinType::Bool:
298 return NSAPI::NSNumberWithBool;
299
300 case BuiltinType::Void:
301 case BuiltinType::WChar_U:
302 case BuiltinType::WChar_S:
303 case BuiltinType::Char16:
304 case BuiltinType::Char32:
305 case BuiltinType::Int128:
306 case BuiltinType::LongDouble:
307 case BuiltinType::UInt128:
308 case BuiltinType::NullPtr:
309 case BuiltinType::ObjCClass:
310 case BuiltinType::ObjCId:
311 case BuiltinType::ObjCSel:
312 case BuiltinType::BoundMember:
313 case BuiltinType::Dependent:
314 case BuiltinType::Overload:
315 case BuiltinType::UnknownAny:
316 case BuiltinType::ARCUnbridgedCast:
317 case BuiltinType::Half:
318 case BuiltinType::PseudoObject:
319 break;
320 }
321
322 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>();
323}
Argyrios Kyrtzidis2df1a582012-05-10 23:12:03 +0000324
325/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
326bool NSAPI::isObjCBOOLType(QualType T) const {
327 return isObjCTypedef(T, "BOOL", BOOLId);
328}
329/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
330bool NSAPI::isObjCNSIntegerType(QualType T) const {
331 return isObjCTypedef(T, "NSInteger", NSIntegerId);
332}
333/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
334bool NSAPI::isObjCNSUIntegerType(QualType T) const {
335 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
336}
337
338bool NSAPI::isObjCTypedef(QualType T,
339 StringRef name, IdentifierInfo *&II) const {
340 if (!Ctx.getLangOpts().ObjC1)
341 return false;
342 if (T.isNull())
343 return false;
344
345 if (!II)
346 II = &Ctx.Idents.get(name);
347
348 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
349 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
350 return true;
351 T = TDT->desugar();
352 }
353
354 return false;
355}