1 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/AST/NSAPI.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/Expr.h"
13 #include "llvm/ADT/StringSwitch.h"
15 using namespace clang;
17 NSAPI::NSAPI(ASTContext &ctx)
18 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
19 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
20 NSUTF8StringEncodingId(nullptr) {}
22 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
23 static const char *ClassName[NumClassIds] = {
29 "NSMutableDictionary",
34 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
39 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
40 if (NSStringSelectors[MK].isNull()) {
43 case NSStr_stringWithString:
44 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
46 case NSStr_stringWithUTF8String:
47 Sel = Ctx.Selectors.getUnarySelector(
48 &Ctx.Idents.get("stringWithUTF8String"));
50 case NSStr_initWithUTF8String:
51 Sel = Ctx.Selectors.getUnarySelector(
52 &Ctx.Idents.get("initWithUTF8String"));
54 case NSStr_stringWithCStringEncoding: {
55 IdentifierInfo *KeyIdents[] = {
56 &Ctx.Idents.get("stringWithCString"),
57 &Ctx.Idents.get("encoding")
59 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
62 case NSStr_stringWithCString:
63 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
65 case NSStr_initWithString:
66 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
69 return (NSStringSelectors[MK] = Sel);
72 return NSStringSelectors[MK];
75 Optional<NSAPI::NSStringMethodKind>
76 NSAPI::getNSStringMethodKind(Selector Sel) const {
77 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
78 NSStringMethodKind MK = NSStringMethodKind(i);
79 if (Sel == getNSStringSelector(MK))
86 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
87 if (NSArraySelectors[MK].isNull()) {
91 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
93 case NSArr_arrayWithArray:
94 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
96 case NSArr_arrayWithObject:
97 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
99 case NSArr_arrayWithObjects:
100 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
102 case NSArr_arrayWithObjectsCount: {
103 IdentifierInfo *KeyIdents[] = {
104 &Ctx.Idents.get("arrayWithObjects"),
105 &Ctx.Idents.get("count")
107 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
110 case NSArr_initWithArray:
111 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
113 case NSArr_initWithObjects:
114 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
116 case NSArr_objectAtIndex:
117 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
119 case NSMutableArr_replaceObjectAtIndex: {
120 IdentifierInfo *KeyIdents[] = {
121 &Ctx.Idents.get("replaceObjectAtIndex"),
122 &Ctx.Idents.get("withObject")
124 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
128 return (NSArraySelectors[MK] = Sel);
131 return NSArraySelectors[MK];
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))
144 Selector NSAPI::getNSDictionarySelector(
145 NSDictionaryMethodKind MK) const {
146 if (NSDictionarySelectors[MK].isNull()) {
149 case NSDict_dictionary:
150 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
152 case NSDict_dictionaryWithDictionary:
153 Sel = Ctx.Selectors.getUnarySelector(
154 &Ctx.Idents.get("dictionaryWithDictionary"));
156 case NSDict_dictionaryWithObjectForKey: {
157 IdentifierInfo *KeyIdents[] = {
158 &Ctx.Idents.get("dictionaryWithObject"),
159 &Ctx.Idents.get("forKey")
161 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
164 case NSDict_dictionaryWithObjectsForKeys: {
165 IdentifierInfo *KeyIdents[] = {
166 &Ctx.Idents.get("dictionaryWithObjects"),
167 &Ctx.Idents.get("forKeys")
169 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
172 case NSDict_dictionaryWithObjectsForKeysCount: {
173 IdentifierInfo *KeyIdents[] = {
174 &Ctx.Idents.get("dictionaryWithObjects"),
175 &Ctx.Idents.get("forKeys"),
176 &Ctx.Idents.get("count")
178 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
181 case NSDict_dictionaryWithObjectsAndKeys:
182 Sel = Ctx.Selectors.getUnarySelector(
183 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
185 case NSDict_initWithDictionary:
186 Sel = Ctx.Selectors.getUnarySelector(
187 &Ctx.Idents.get("initWithDictionary"));
189 case NSDict_initWithObjectsAndKeys:
190 Sel = Ctx.Selectors.getUnarySelector(
191 &Ctx.Idents.get("initWithObjectsAndKeys"));
193 case NSDict_initWithObjectsForKeys: {
194 IdentifierInfo *KeyIdents[] = {
195 &Ctx.Idents.get("initWithObjects"),
196 &Ctx.Idents.get("forKeys")
198 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
201 case NSDict_objectForKey:
202 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
204 case NSMutableDict_setObjectForKey: {
205 IdentifierInfo *KeyIdents[] = {
206 &Ctx.Idents.get("setObject"),
207 &Ctx.Idents.get("forKey")
209 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
213 return (NSDictionarySelectors[MK] = Sel);
216 return NSDictionarySelectors[MK];
219 Optional<NSAPI::NSDictionaryMethodKind>
220 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
221 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
222 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
223 if (Sel == getNSDictionarySelector(MK))
230 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
231 bool Instance) const {
232 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
234 "numberWithUnsignedChar",
236 "numberWithUnsignedShort",
238 "numberWithUnsignedInt",
240 "numberWithUnsignedLong",
241 "numberWithLongLong",
242 "numberWithUnsignedLongLong",
247 "numberWithUnsignedInteger"
249 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
251 "initWithUnsignedChar",
253 "initWithUnsignedShort",
255 "initWithUnsignedInt",
257 "initWithUnsignedLong",
259 "initWithUnsignedLongLong",
264 "initWithUnsignedInteger"
270 Sels = NSNumberInstanceSelectors;
271 Names = InstanceSelectorName;
273 Sels = NSNumberClassSelectors;
274 Names = ClassSelectorName;
277 if (Sels[MK].isNull())
278 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
282 Optional<NSAPI::NSNumberLiteralMethodKind>
283 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
284 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
285 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
286 if (isNSNumberLiteralSelector(MK, Sel))
293 Optional<NSAPI::NSNumberLiteralMethodKind>
294 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
295 const BuiltinType *BT = T->getAs<BuiltinType>();
299 const TypedefType *TDT = T->getAs<TypedefType>();
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;
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;
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:
374 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
375 bool NSAPI::isObjCBOOLType(QualType T) const {
376 return isObjCTypedef(T, "BOOL", BOOLId);
378 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
379 bool NSAPI::isObjCNSIntegerType(QualType T) const {
380 return isObjCTypedef(T, "NSInteger", NSIntegerId);
382 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
383 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
384 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
387 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
388 if (!Ctx.getLangOpts().ObjC1 || T.isNull())
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;
413 bool NSAPI::isObjCTypedef(QualType T,
414 StringRef name, IdentifierInfo *&II) const {
415 if (!Ctx.getLangOpts().ObjC1)
421 II = &Ctx.Idents.get(name);
423 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
424 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
432 bool NSAPI::isObjCEnumerator(const Expr *E,
433 StringRef name, IdentifierInfo *&II) const {
434 if (!Ctx.getLangOpts().ObjC1)
440 II = &Ctx.Idents.get(name);
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;
450 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
451 Selector &Sel) const {
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());