1 //===--- 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 #include "llvm/ADT/StringSwitch.h"
14
15 using namespace clang;
16
NSAPI(ASTContext & ctx)17 NSAPI::NSAPI(ASTContext &ctx)
18 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20 NSUTF8StringEncodingId(nullptr) {}
21
getNSClassId(NSClassIdKindKind K) const22 IdentifierInfo *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
getNSStringSelector(NSStringMethodKind MK) const39 Selector 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;
50 case NSStr_initWithUTF8String:
51 Sel = Ctx.Selectors.getUnarySelector(
52 &Ctx.Idents.get("initWithUTF8String"));
53 break;
54 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
75 Optional<NSAPI::NSStringMethodKind>
getNSStringMethodKind(Selector Sel) const76 NSAPI::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
83 return None;
84 }
85
getNSArraySelector(NSArrayMethodKind MK) const86 Selector 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 }
127 }
128 return (NSArraySelectors[MK] = Sel);
129 }
130
131 return NSArraySelectors[MK];
132 }
133
getNSArrayMethodKind(Selector Sel)134 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
135 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
136 NSArrayMethodKind MK = NSArrayMethodKind(i);
137 if (Sel == getNSArraySelector(MK))
138 return MK;
139 }
140
141 return None;
142 }
143
getNSDictionarySelector(NSDictionaryMethodKind MK) const144 Selector NSAPI::getNSDictionarySelector(
145 NSDictionaryMethodKind MK) const {
146 if (NSDictionarySelectors[MK].isNull()) {
147 Selector Sel;
148 switch (MK) {
149 case NSDict_dictionary:
150 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
151 break;
152 case NSDict_dictionaryWithDictionary:
153 Sel = Ctx.Selectors.getUnarySelector(
154 &Ctx.Idents.get("dictionaryWithDictionary"));
155 break;
156 case NSDict_dictionaryWithObjectForKey: {
157 IdentifierInfo *KeyIdents[] = {
158 &Ctx.Idents.get("dictionaryWithObject"),
159 &Ctx.Idents.get("forKey")
160 };
161 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
162 break;
163 }
164 case NSDict_dictionaryWithObjectsForKeys: {
165 IdentifierInfo *KeyIdents[] = {
166 &Ctx.Idents.get("dictionaryWithObjects"),
167 &Ctx.Idents.get("forKeys")
168 };
169 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
170 break;
171 }
172 case NSDict_dictionaryWithObjectsForKeysCount: {
173 IdentifierInfo *KeyIdents[] = {
174 &Ctx.Idents.get("dictionaryWithObjects"),
175 &Ctx.Idents.get("forKeys"),
176 &Ctx.Idents.get("count")
177 };
178 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
179 break;
180 }
181 case NSDict_dictionaryWithObjectsAndKeys:
182 Sel = Ctx.Selectors.getUnarySelector(
183 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
184 break;
185 case NSDict_initWithDictionary:
186 Sel = Ctx.Selectors.getUnarySelector(
187 &Ctx.Idents.get("initWithDictionary"));
188 break;
189 case NSDict_initWithObjectsAndKeys:
190 Sel = Ctx.Selectors.getUnarySelector(
191 &Ctx.Idents.get("initWithObjectsAndKeys"));
192 break;
193 case NSDict_initWithObjectsForKeys: {
194 IdentifierInfo *KeyIdents[] = {
195 &Ctx.Idents.get("initWithObjects"),
196 &Ctx.Idents.get("forKeys")
197 };
198 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
199 break;
200 }
201 case NSDict_objectForKey:
202 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
203 break;
204 case NSMutableDict_setObjectForKey: {
205 IdentifierInfo *KeyIdents[] = {
206 &Ctx.Idents.get("setObject"),
207 &Ctx.Idents.get("forKey")
208 };
209 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
210 break;
211 }
212 }
213 return (NSDictionarySelectors[MK] = Sel);
214 }
215
216 return NSDictionarySelectors[MK];
217 }
218
219 Optional<NSAPI::NSDictionaryMethodKind>
getNSDictionaryMethodKind(Selector Sel)220 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
221 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
222 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
223 if (Sel == getNSDictionarySelector(MK))
224 return MK;
225 }
226
227 return None;
228 }
229
getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,bool Instance) const230 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
231 bool Instance) const {
232 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
233 "numberWithChar",
234 "numberWithUnsignedChar",
235 "numberWithShort",
236 "numberWithUnsignedShort",
237 "numberWithInt",
238 "numberWithUnsignedInt",
239 "numberWithLong",
240 "numberWithUnsignedLong",
241 "numberWithLongLong",
242 "numberWithUnsignedLongLong",
243 "numberWithFloat",
244 "numberWithDouble",
245 "numberWithBool",
246 "numberWithInteger",
247 "numberWithUnsignedInteger"
248 };
249 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
250 "initWithChar",
251 "initWithUnsignedChar",
252 "initWithShort",
253 "initWithUnsignedShort",
254 "initWithInt",
255 "initWithUnsignedInt",
256 "initWithLong",
257 "initWithUnsignedLong",
258 "initWithLongLong",
259 "initWithUnsignedLongLong",
260 "initWithFloat",
261 "initWithDouble",
262 "initWithBool",
263 "initWithInteger",
264 "initWithUnsignedInteger"
265 };
266
267 Selector *Sels;
268 const char **Names;
269 if (Instance) {
270 Sels = NSNumberInstanceSelectors;
271 Names = InstanceSelectorName;
272 } else {
273 Sels = NSNumberClassSelectors;
274 Names = ClassSelectorName;
275 }
276
277 if (Sels[MK].isNull())
278 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
279 return Sels[MK];
280 }
281
282 Optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberLiteralMethodKind(Selector Sel) const283 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
284 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
285 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
286 if (isNSNumberLiteralSelector(MK, Sel))
287 return MK;
288 }
289
290 return None;
291 }
292
293 Optional<NSAPI::NSNumberLiteralMethodKind>
getNSNumberFactoryMethodKind(QualType T) const294 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
295 const BuiltinType *BT = T->getAs<BuiltinType>();
296 if (!BT)
297 return None;
298
299 const TypedefType *TDT = T->getAs<TypedefType>();
300 if (TDT) {
301 QualType TDTTy = QualType(TDT, 0);
302 if (isObjCBOOLType(TDTTy))
303 return NSAPI::NSNumberWithBool;
304 if (isObjCNSIntegerType(TDTTy))
305 return NSAPI::NSNumberWithInteger;
306 if (isObjCNSUIntegerType(TDTTy))
307 return NSAPI::NSNumberWithUnsignedInteger;
308 }
309
310 switch (BT->getKind()) {
311 case BuiltinType::Char_S:
312 case BuiltinType::SChar:
313 return NSAPI::NSNumberWithChar;
314 case BuiltinType::Char_U:
315 case BuiltinType::UChar:
316 return NSAPI::NSNumberWithUnsignedChar;
317 case BuiltinType::Short:
318 return NSAPI::NSNumberWithShort;
319 case BuiltinType::UShort:
320 return NSAPI::NSNumberWithUnsignedShort;
321 case BuiltinType::Int:
322 return NSAPI::NSNumberWithInt;
323 case BuiltinType::UInt:
324 return NSAPI::NSNumberWithUnsignedInt;
325 case BuiltinType::Long:
326 return NSAPI::NSNumberWithLong;
327 case BuiltinType::ULong:
328 return NSAPI::NSNumberWithUnsignedLong;
329 case BuiltinType::LongLong:
330 return NSAPI::NSNumberWithLongLong;
331 case BuiltinType::ULongLong:
332 return NSAPI::NSNumberWithUnsignedLongLong;
333 case BuiltinType::Float:
334 return NSAPI::NSNumberWithFloat;
335 case BuiltinType::Double:
336 return NSAPI::NSNumberWithDouble;
337 case BuiltinType::Bool:
338 return NSAPI::NSNumberWithBool;
339
340 case BuiltinType::Void:
341 case BuiltinType::WChar_U:
342 case BuiltinType::WChar_S:
343 case BuiltinType::Char16:
344 case BuiltinType::Char32:
345 case BuiltinType::Int128:
346 case BuiltinType::LongDouble:
347 case BuiltinType::UInt128:
348 case BuiltinType::NullPtr:
349 case BuiltinType::ObjCClass:
350 case BuiltinType::ObjCId:
351 case BuiltinType::ObjCSel:
352 case BuiltinType::OCLImage1d:
353 case BuiltinType::OCLImage1dArray:
354 case BuiltinType::OCLImage1dBuffer:
355 case BuiltinType::OCLImage2d:
356 case BuiltinType::OCLImage2dArray:
357 case BuiltinType::OCLImage3d:
358 case BuiltinType::OCLSampler:
359 case BuiltinType::OCLEvent:
360 case BuiltinType::BoundMember:
361 case BuiltinType::Dependent:
362 case BuiltinType::Overload:
363 case BuiltinType::UnknownAny:
364 case BuiltinType::ARCUnbridgedCast:
365 case BuiltinType::Half:
366 case BuiltinType::PseudoObject:
367 case BuiltinType::BuiltinFn:
368 break;
369 }
370
371 return None;
372 }
373
374 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
isObjCBOOLType(QualType T) const375 bool NSAPI::isObjCBOOLType(QualType T) const {
376 return isObjCTypedef(T, "BOOL", BOOLId);
377 }
378 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
isObjCNSIntegerType(QualType T) const379 bool NSAPI::isObjCNSIntegerType(QualType T) const {
380 return isObjCTypedef(T, "NSInteger", NSIntegerId);
381 }
382 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
isObjCNSUIntegerType(QualType T) const383 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
384 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
385 }
386
GetNSIntegralKind(QualType T) const387 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
388 if (!Ctx.getLangOpts().ObjC1 || T.isNull())
389 return StringRef();
390
391 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
392 StringRef NSIntegralResust =
393 llvm::StringSwitch<StringRef>(
394 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
395 .Case("int8_t", "int8_t")
396 .Case("int16_t", "int16_t")
397 .Case("int32_t", "int32_t")
398 .Case("NSInteger", "NSInteger")
399 .Case("int64_t", "int64_t")
400 .Case("uint8_t", "uint8_t")
401 .Case("uint16_t", "uint16_t")
402 .Case("uint32_t", "uint32_t")
403 .Case("NSUInteger", "NSUInteger")
404 .Case("uint64_t", "uint64_t")
405 .Default(StringRef());
406 if (!NSIntegralResust.empty())
407 return NSIntegralResust;
408 T = TDT->desugar();
409 }
410 return StringRef();
411 }
412
isObjCTypedef(QualType T,StringRef name,IdentifierInfo * & II) const413 bool NSAPI::isObjCTypedef(QualType T,
414 StringRef name, IdentifierInfo *&II) const {
415 if (!Ctx.getLangOpts().ObjC1)
416 return false;
417 if (T.isNull())
418 return false;
419
420 if (!II)
421 II = &Ctx.Idents.get(name);
422
423 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
424 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
425 return true;
426 T = TDT->desugar();
427 }
428
429 return false;
430 }
431
isObjCEnumerator(const Expr * E,StringRef name,IdentifierInfo * & II) const432 bool NSAPI::isObjCEnumerator(const Expr *E,
433 StringRef name, IdentifierInfo *&II) const {
434 if (!Ctx.getLangOpts().ObjC1)
435 return false;
436 if (!E)
437 return false;
438
439 if (!II)
440 II = &Ctx.Idents.get(name);
441
442 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
443 if (const EnumConstantDecl *
444 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
445 return EnumD->getIdentifier() == II;
446
447 return false;
448 }
449
getOrInitSelector(ArrayRef<StringRef> Ids,Selector & Sel) const450 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
451 Selector &Sel) const {
452 if (Sel.isNull()) {
453 SmallVector<IdentifierInfo *, 4> Idents;
454 for (ArrayRef<StringRef>::const_iterator
455 I = Ids.begin(), E = Ids.end(); I != E; ++I)
456 Idents.push_back(&Ctx.Idents.get(*I));
457 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
458 }
459 return Sel;
460 }
461