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",
37 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
42 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
43 if (NSStringSelectors[MK].isNull()) {
46 case NSStr_stringWithString:
47 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
49 case NSStr_stringWithUTF8String:
50 Sel = Ctx.Selectors.getUnarySelector(
51 &Ctx.Idents.get("stringWithUTF8String"));
53 case NSStr_initWithUTF8String:
54 Sel = Ctx.Selectors.getUnarySelector(
55 &Ctx.Idents.get("initWithUTF8String"));
57 case NSStr_stringWithCStringEncoding: {
58 IdentifierInfo *KeyIdents[] = {
59 &Ctx.Idents.get("stringWithCString"),
60 &Ctx.Idents.get("encoding")
62 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
65 case NSStr_stringWithCString:
66 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
68 case NSStr_initWithString:
69 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
72 return (NSStringSelectors[MK] = Sel);
75 return NSStringSelectors[MK];
78 Optional<NSAPI::NSStringMethodKind>
79 NSAPI::getNSStringMethodKind(Selector Sel) const {
80 for (unsigned i = 0; i != NumNSStringMethods; ++i) {
81 NSStringMethodKind MK = NSStringMethodKind(i);
82 if (Sel == getNSStringSelector(MK))
89 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
90 if (NSArraySelectors[MK].isNull()) {
94 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
96 case NSArr_arrayWithArray:
97 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
99 case NSArr_arrayWithObject:
100 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
102 case NSArr_arrayWithObjects:
103 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
105 case NSArr_arrayWithObjectsCount: {
106 IdentifierInfo *KeyIdents[] = {
107 &Ctx.Idents.get("arrayWithObjects"),
108 &Ctx.Idents.get("count")
110 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
113 case NSArr_initWithArray:
114 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
116 case NSArr_initWithObjects:
117 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
119 case NSArr_objectAtIndex:
120 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
122 case NSMutableArr_replaceObjectAtIndex: {
123 IdentifierInfo *KeyIdents[] = {
124 &Ctx.Idents.get("replaceObjectAtIndex"),
125 &Ctx.Idents.get("withObject")
127 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
130 case NSMutableArr_addObject:
131 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
133 case NSMutableArr_insertObjectAtIndex: {
134 IdentifierInfo *KeyIdents[] = {
135 &Ctx.Idents.get("insertObject"),
136 &Ctx.Idents.get("atIndex")
138 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
141 case NSMutableArr_setObjectAtIndexedSubscript: {
142 IdentifierInfo *KeyIdents[] = {
143 &Ctx.Idents.get("setObject"),
144 &Ctx.Idents.get("atIndexedSubscript")
146 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
150 return (NSArraySelectors[MK] = Sel);
153 return NSArraySelectors[MK];
156 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
157 for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
158 NSArrayMethodKind MK = NSArrayMethodKind(i);
159 if (Sel == getNSArraySelector(MK))
166 Selector NSAPI::getNSDictionarySelector(
167 NSDictionaryMethodKind MK) const {
168 if (NSDictionarySelectors[MK].isNull()) {
171 case NSDict_dictionary:
172 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
174 case NSDict_dictionaryWithDictionary:
175 Sel = Ctx.Selectors.getUnarySelector(
176 &Ctx.Idents.get("dictionaryWithDictionary"));
178 case NSDict_dictionaryWithObjectForKey: {
179 IdentifierInfo *KeyIdents[] = {
180 &Ctx.Idents.get("dictionaryWithObject"),
181 &Ctx.Idents.get("forKey")
183 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
186 case NSDict_dictionaryWithObjectsForKeys: {
187 IdentifierInfo *KeyIdents[] = {
188 &Ctx.Idents.get("dictionaryWithObjects"),
189 &Ctx.Idents.get("forKeys")
191 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
194 case NSDict_dictionaryWithObjectsForKeysCount: {
195 IdentifierInfo *KeyIdents[] = {
196 &Ctx.Idents.get("dictionaryWithObjects"),
197 &Ctx.Idents.get("forKeys"),
198 &Ctx.Idents.get("count")
200 Sel = Ctx.Selectors.getSelector(3, KeyIdents);
203 case NSDict_dictionaryWithObjectsAndKeys:
204 Sel = Ctx.Selectors.getUnarySelector(
205 &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
207 case NSDict_initWithDictionary:
208 Sel = Ctx.Selectors.getUnarySelector(
209 &Ctx.Idents.get("initWithDictionary"));
211 case NSDict_initWithObjectsAndKeys:
212 Sel = Ctx.Selectors.getUnarySelector(
213 &Ctx.Idents.get("initWithObjectsAndKeys"));
215 case NSDict_initWithObjectsForKeys: {
216 IdentifierInfo *KeyIdents[] = {
217 &Ctx.Idents.get("initWithObjects"),
218 &Ctx.Idents.get("forKeys")
220 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
223 case NSDict_objectForKey:
224 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
226 case NSMutableDict_setObjectForKey: {
227 IdentifierInfo *KeyIdents[] = {
228 &Ctx.Idents.get("setObject"),
229 &Ctx.Idents.get("forKey")
231 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
234 case NSMutableDict_setObjectForKeyedSubscript: {
235 IdentifierInfo *KeyIdents[] = {
236 &Ctx.Idents.get("setObject"),
237 &Ctx.Idents.get("forKeyedSubscript")
239 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
242 case NSMutableDict_setValueForKey: {
243 IdentifierInfo *KeyIdents[] = {
244 &Ctx.Idents.get("setValue"),
245 &Ctx.Idents.get("forKey")
247 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
251 return (NSDictionarySelectors[MK] = Sel);
254 return NSDictionarySelectors[MK];
257 Optional<NSAPI::NSDictionaryMethodKind>
258 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
259 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
260 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
261 if (Sel == getNSDictionarySelector(MK))
268 Selector NSAPI::getNSSetSelector(NSSetMethodKind MK) const {
269 if (NSSetSelectors[MK].isNull()) {
272 case NSMutableSet_addObject:
273 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("addObject"));
275 case NSOrderedSet_insertObjectAtIndex: {
276 IdentifierInfo *KeyIdents[] = {
277 &Ctx.Idents.get("insertObject"),
278 &Ctx.Idents.get("atIndex")
280 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
283 case NSOrderedSet_setObjectAtIndex: {
284 IdentifierInfo *KeyIdents[] = {
285 &Ctx.Idents.get("setObject"),
286 &Ctx.Idents.get("atIndex")
288 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
291 case NSOrderedSet_setObjectAtIndexedSubscript: {
292 IdentifierInfo *KeyIdents[] = {
293 &Ctx.Idents.get("setObject"),
294 &Ctx.Idents.get("atIndexedSubscript")
296 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
299 case NSOrderedSet_replaceObjectAtIndexWithObject: {
300 IdentifierInfo *KeyIdents[] = {
301 &Ctx.Idents.get("replaceObjectAtIndex"),
302 &Ctx.Idents.get("withObject")
304 Sel = Ctx.Selectors.getSelector(2, KeyIdents);
308 return (NSSetSelectors[MK] = Sel);
311 return NSSetSelectors[MK];
314 Optional<NSAPI::NSSetMethodKind>
315 NSAPI::getNSSetMethodKind(Selector Sel) {
316 for (unsigned i = 0; i != NumNSSetMethods; ++i) {
317 NSSetMethodKind MK = NSSetMethodKind(i);
318 if (Sel == getNSSetSelector(MK))
325 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
326 bool Instance) const {
327 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
329 "numberWithUnsignedChar",
331 "numberWithUnsignedShort",
333 "numberWithUnsignedInt",
335 "numberWithUnsignedLong",
336 "numberWithLongLong",
337 "numberWithUnsignedLongLong",
342 "numberWithUnsignedInteger"
344 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
346 "initWithUnsignedChar",
348 "initWithUnsignedShort",
350 "initWithUnsignedInt",
352 "initWithUnsignedLong",
354 "initWithUnsignedLongLong",
359 "initWithUnsignedInteger"
365 Sels = NSNumberInstanceSelectors;
366 Names = InstanceSelectorName;
368 Sels = NSNumberClassSelectors;
369 Names = ClassSelectorName;
372 if (Sels[MK].isNull())
373 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
377 Optional<NSAPI::NSNumberLiteralMethodKind>
378 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
379 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
380 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
381 if (isNSNumberLiteralSelector(MK, Sel))
388 Optional<NSAPI::NSNumberLiteralMethodKind>
389 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
390 const BuiltinType *BT = T->getAs<BuiltinType>();
394 const TypedefType *TDT = T->getAs<TypedefType>();
396 QualType TDTTy = QualType(TDT, 0);
397 if (isObjCBOOLType(TDTTy))
398 return NSAPI::NSNumberWithBool;
399 if (isObjCNSIntegerType(TDTTy))
400 return NSAPI::NSNumberWithInteger;
401 if (isObjCNSUIntegerType(TDTTy))
402 return NSAPI::NSNumberWithUnsignedInteger;
405 switch (BT->getKind()) {
406 case BuiltinType::Char_S:
407 case BuiltinType::SChar:
408 return NSAPI::NSNumberWithChar;
409 case BuiltinType::Char_U:
410 case BuiltinType::UChar:
411 return NSAPI::NSNumberWithUnsignedChar;
412 case BuiltinType::Short:
413 return NSAPI::NSNumberWithShort;
414 case BuiltinType::UShort:
415 return NSAPI::NSNumberWithUnsignedShort;
416 case BuiltinType::Int:
417 return NSAPI::NSNumberWithInt;
418 case BuiltinType::UInt:
419 return NSAPI::NSNumberWithUnsignedInt;
420 case BuiltinType::Long:
421 return NSAPI::NSNumberWithLong;
422 case BuiltinType::ULong:
423 return NSAPI::NSNumberWithUnsignedLong;
424 case BuiltinType::LongLong:
425 return NSAPI::NSNumberWithLongLong;
426 case BuiltinType::ULongLong:
427 return NSAPI::NSNumberWithUnsignedLongLong;
428 case BuiltinType::Float:
429 return NSAPI::NSNumberWithFloat;
430 case BuiltinType::Double:
431 return NSAPI::NSNumberWithDouble;
432 case BuiltinType::Bool:
433 return NSAPI::NSNumberWithBool;
435 case BuiltinType::Void:
436 case BuiltinType::WChar_U:
437 case BuiltinType::WChar_S:
438 case BuiltinType::Char16:
439 case BuiltinType::Char32:
440 case BuiltinType::Int128:
441 case BuiltinType::LongDouble:
442 case BuiltinType::UInt128:
443 case BuiltinType::NullPtr:
444 case BuiltinType::ObjCClass:
445 case BuiltinType::ObjCId:
446 case BuiltinType::ObjCSel:
447 case BuiltinType::OCLImage1d:
448 case BuiltinType::OCLImage1dArray:
449 case BuiltinType::OCLImage1dBuffer:
450 case BuiltinType::OCLImage2d:
451 case BuiltinType::OCLImage2dArray:
452 case BuiltinType::OCLImage3d:
453 case BuiltinType::OCLSampler:
454 case BuiltinType::OCLEvent:
455 case BuiltinType::BoundMember:
456 case BuiltinType::Dependent:
457 case BuiltinType::Overload:
458 case BuiltinType::UnknownAny:
459 case BuiltinType::ARCUnbridgedCast:
460 case BuiltinType::Half:
461 case BuiltinType::PseudoObject:
462 case BuiltinType::BuiltinFn:
469 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
470 bool NSAPI::isObjCBOOLType(QualType T) const {
471 return isObjCTypedef(T, "BOOL", BOOLId);
473 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
474 bool NSAPI::isObjCNSIntegerType(QualType T) const {
475 return isObjCTypedef(T, "NSInteger", NSIntegerId);
477 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
478 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
479 return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
482 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
483 if (!Ctx.getLangOpts().ObjC1 || T.isNull())
486 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
487 StringRef NSIntegralResust =
488 llvm::StringSwitch<StringRef>(
489 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
490 .Case("int8_t", "int8_t")
491 .Case("int16_t", "int16_t")
492 .Case("int32_t", "int32_t")
493 .Case("NSInteger", "NSInteger")
494 .Case("int64_t", "int64_t")
495 .Case("uint8_t", "uint8_t")
496 .Case("uint16_t", "uint16_t")
497 .Case("uint32_t", "uint32_t")
498 .Case("NSUInteger", "NSUInteger")
499 .Case("uint64_t", "uint64_t")
500 .Default(StringRef());
501 if (!NSIntegralResust.empty())
502 return NSIntegralResust;
508 bool NSAPI::isMacroDefined(StringRef Id) const {
509 // FIXME: Check whether the relevant module macros are visible.
510 return Ctx.Idents.get(Id).hasMacroDefinition();
513 bool NSAPI::isObjCTypedef(QualType T,
514 StringRef name, IdentifierInfo *&II) const {
515 if (!Ctx.getLangOpts().ObjC1)
521 II = &Ctx.Idents.get(name);
523 while (const TypedefType *TDT = T->getAs<TypedefType>()) {
524 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
532 bool NSAPI::isObjCEnumerator(const Expr *E,
533 StringRef name, IdentifierInfo *&II) const {
534 if (!Ctx.getLangOpts().ObjC1)
540 II = &Ctx.Idents.get(name);
542 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
543 if (const EnumConstantDecl *
544 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
545 return EnumD->getIdentifier() == II;
550 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
551 Selector &Sel) const {
553 SmallVector<IdentifierInfo *, 4> Idents;
554 for (ArrayRef<StringRef>::const_iterator
555 I = Ids.begin(), E = Ids.end(); I != E; ++I)
556 Idents.push_back(&Ctx.Idents.get(*I));
557 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());