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