clang API Documentation

NSAPI.cpp
Go to the documentation of this file.
00001 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 
00010 #include "clang/AST/NSAPI.h"
00011 #include "clang/AST/ASTContext.h"
00012 #include "clang/AST/Expr.h"
00013 #include "llvm/ADT/StringSwitch.h"
00014 
00015 using namespace clang;
00016 
00017 NSAPI::NSAPI(ASTContext &ctx)
00018   : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr),
00019     NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr),
00020     NSUTF8StringEncodingId(nullptr) {}
00021 
00022 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const {
00023   static const char *ClassName[NumClassIds] = {
00024     "NSObject",
00025     "NSString",
00026     "NSArray",
00027     "NSMutableArray",
00028     "NSDictionary",
00029     "NSMutableDictionary",
00030     "NSNumber"
00031   };
00032 
00033   if (!ClassIds[K])
00034     return (ClassIds[K] = &Ctx.Idents.get(ClassName[K]));
00035 
00036   return ClassIds[K];
00037 }
00038 
00039 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const {
00040   if (NSStringSelectors[MK].isNull()) {
00041     Selector Sel;
00042     switch (MK) {
00043     case NSStr_stringWithString:
00044       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString"));
00045       break;
00046     case NSStr_stringWithUTF8String:
00047       Sel = Ctx.Selectors.getUnarySelector(
00048                                        &Ctx.Idents.get("stringWithUTF8String"));
00049       break;
00050     case NSStr_initWithUTF8String:
00051       Sel = Ctx.Selectors.getUnarySelector(
00052                                        &Ctx.Idents.get("initWithUTF8String"));
00053       break;
00054     case NSStr_stringWithCStringEncoding: {
00055       IdentifierInfo *KeyIdents[] = {
00056         &Ctx.Idents.get("stringWithCString"),
00057         &Ctx.Idents.get("encoding")
00058       };
00059       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00060       break;
00061     }
00062     case NSStr_stringWithCString:
00063       Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString"));
00064       break;
00065     case NSStr_initWithString:
00066       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString"));
00067       break;
00068     }
00069     return (NSStringSelectors[MK] = Sel);
00070   }
00071 
00072   return NSStringSelectors[MK];
00073 }
00074 
00075 Optional<NSAPI::NSStringMethodKind>
00076 NSAPI::getNSStringMethodKind(Selector Sel) const {
00077   for (unsigned i = 0; i != NumNSStringMethods; ++i) {
00078     NSStringMethodKind MK = NSStringMethodKind(i);
00079     if (Sel == getNSStringSelector(MK))
00080       return MK;
00081   }
00082 
00083   return None;
00084 }
00085 
00086 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const {
00087   if (NSArraySelectors[MK].isNull()) {
00088     Selector Sel;
00089     switch (MK) {
00090     case NSArr_array:
00091       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array"));
00092       break;
00093     case NSArr_arrayWithArray:
00094       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray"));
00095       break;
00096     case NSArr_arrayWithObject:
00097       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject"));
00098       break;
00099     case NSArr_arrayWithObjects:
00100       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects"));
00101       break;
00102     case NSArr_arrayWithObjectsCount: {
00103       IdentifierInfo *KeyIdents[] = {
00104         &Ctx.Idents.get("arrayWithObjects"),
00105         &Ctx.Idents.get("count")
00106       };
00107       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00108       break;
00109     }
00110     case NSArr_initWithArray:
00111       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray"));
00112       break;
00113     case NSArr_initWithObjects:
00114       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects"));
00115       break;
00116     case NSArr_objectAtIndex:
00117       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex"));
00118       break;
00119     case NSMutableArr_replaceObjectAtIndex: {
00120       IdentifierInfo *KeyIdents[] = {
00121         &Ctx.Idents.get("replaceObjectAtIndex"),
00122         &Ctx.Idents.get("withObject")
00123       };
00124       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00125       break;
00126     }
00127     }
00128     return (NSArraySelectors[MK] = Sel);
00129   }
00130 
00131   return NSArraySelectors[MK];
00132 }
00133 
00134 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) {
00135   for (unsigned i = 0; i != NumNSArrayMethods; ++i) {
00136     NSArrayMethodKind MK = NSArrayMethodKind(i);
00137     if (Sel == getNSArraySelector(MK))
00138       return MK;
00139   }
00140 
00141   return None;
00142 }
00143 
00144 Selector NSAPI::getNSDictionarySelector(
00145                                        NSDictionaryMethodKind MK) const {
00146   if (NSDictionarySelectors[MK].isNull()) {
00147     Selector Sel;
00148     switch (MK) {
00149     case NSDict_dictionary:
00150       Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary"));
00151       break;
00152     case NSDict_dictionaryWithDictionary:
00153       Sel = Ctx.Selectors.getUnarySelector(
00154                                    &Ctx.Idents.get("dictionaryWithDictionary"));
00155       break;
00156     case NSDict_dictionaryWithObjectForKey: {
00157       IdentifierInfo *KeyIdents[] = {
00158         &Ctx.Idents.get("dictionaryWithObject"),
00159         &Ctx.Idents.get("forKey")
00160       };
00161       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00162       break;
00163     }
00164     case NSDict_dictionaryWithObjectsForKeys: {
00165       IdentifierInfo *KeyIdents[] = {
00166         &Ctx.Idents.get("dictionaryWithObjects"),
00167         &Ctx.Idents.get("forKeys")
00168       };
00169       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00170       break;
00171     }
00172     case NSDict_dictionaryWithObjectsForKeysCount: {
00173       IdentifierInfo *KeyIdents[] = {
00174         &Ctx.Idents.get("dictionaryWithObjects"),
00175         &Ctx.Idents.get("forKeys"),
00176         &Ctx.Idents.get("count")
00177       };
00178       Sel = Ctx.Selectors.getSelector(3, KeyIdents);
00179       break;
00180     }
00181     case NSDict_dictionaryWithObjectsAndKeys:
00182       Sel = Ctx.Selectors.getUnarySelector(
00183                                &Ctx.Idents.get("dictionaryWithObjectsAndKeys"));
00184       break;
00185     case NSDict_initWithDictionary:
00186       Sel = Ctx.Selectors.getUnarySelector(
00187                                          &Ctx.Idents.get("initWithDictionary"));
00188       break;
00189     case NSDict_initWithObjectsAndKeys:
00190       Sel = Ctx.Selectors.getUnarySelector(
00191                                      &Ctx.Idents.get("initWithObjectsAndKeys"));
00192       break;
00193     case NSDict_initWithObjectsForKeys: {
00194       IdentifierInfo *KeyIdents[] = {
00195         &Ctx.Idents.get("initWithObjects"),
00196         &Ctx.Idents.get("forKeys")
00197       };
00198       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00199       break;
00200     }
00201     case NSDict_objectForKey:
00202       Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey"));
00203       break;
00204     case NSMutableDict_setObjectForKey: {
00205       IdentifierInfo *KeyIdents[] = {
00206         &Ctx.Idents.get("setObject"),
00207         &Ctx.Idents.get("forKey")
00208       };
00209       Sel = Ctx.Selectors.getSelector(2, KeyIdents);
00210       break;
00211     }
00212     }
00213     return (NSDictionarySelectors[MK] = Sel);
00214   }
00215 
00216   return NSDictionarySelectors[MK];
00217 }
00218 
00219 Optional<NSAPI::NSDictionaryMethodKind>
00220 NSAPI::getNSDictionaryMethodKind(Selector Sel) {
00221   for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) {
00222     NSDictionaryMethodKind MK = NSDictionaryMethodKind(i);
00223     if (Sel == getNSDictionarySelector(MK))
00224       return MK;
00225   }
00226 
00227   return None;
00228 }
00229 
00230 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK,
00231                                            bool Instance) const {
00232   static const char *ClassSelectorName[NumNSNumberLiteralMethods] = {
00233     "numberWithChar",
00234     "numberWithUnsignedChar",
00235     "numberWithShort",
00236     "numberWithUnsignedShort",
00237     "numberWithInt",
00238     "numberWithUnsignedInt",
00239     "numberWithLong",
00240     "numberWithUnsignedLong",
00241     "numberWithLongLong",
00242     "numberWithUnsignedLongLong",
00243     "numberWithFloat",
00244     "numberWithDouble",
00245     "numberWithBool",
00246     "numberWithInteger",
00247     "numberWithUnsignedInteger"
00248   };
00249   static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = {
00250     "initWithChar",
00251     "initWithUnsignedChar",
00252     "initWithShort",
00253     "initWithUnsignedShort",
00254     "initWithInt",
00255     "initWithUnsignedInt",
00256     "initWithLong",
00257     "initWithUnsignedLong",
00258     "initWithLongLong",
00259     "initWithUnsignedLongLong",
00260     "initWithFloat",
00261     "initWithDouble",
00262     "initWithBool",
00263     "initWithInteger",
00264     "initWithUnsignedInteger"
00265   };
00266 
00267   Selector *Sels;
00268   const char **Names;
00269   if (Instance) {
00270     Sels = NSNumberInstanceSelectors;
00271     Names = InstanceSelectorName;
00272   } else {
00273     Sels = NSNumberClassSelectors;
00274     Names = ClassSelectorName;
00275   }
00276 
00277   if (Sels[MK].isNull())
00278     Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK]));
00279   return Sels[MK];
00280 }
00281 
00282 Optional<NSAPI::NSNumberLiteralMethodKind>
00283 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const {
00284   for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) {
00285     NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i);
00286     if (isNSNumberLiteralSelector(MK, Sel))
00287       return MK;
00288   }
00289 
00290   return None;
00291 }
00292 
00293 Optional<NSAPI::NSNumberLiteralMethodKind>
00294 NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
00295   const BuiltinType *BT = T->getAs<BuiltinType>();
00296   if (!BT)
00297     return None;
00298 
00299   const TypedefType *TDT = T->getAs<TypedefType>();
00300   if (TDT) {
00301     QualType TDTTy = QualType(TDT, 0);
00302     if (isObjCBOOLType(TDTTy))
00303       return NSAPI::NSNumberWithBool;
00304     if (isObjCNSIntegerType(TDTTy))
00305       return NSAPI::NSNumberWithInteger;
00306     if (isObjCNSUIntegerType(TDTTy))
00307       return NSAPI::NSNumberWithUnsignedInteger;
00308   }
00309 
00310   switch (BT->getKind()) {
00311   case BuiltinType::Char_S:
00312   case BuiltinType::SChar:
00313     return NSAPI::NSNumberWithChar;
00314   case BuiltinType::Char_U:
00315   case BuiltinType::UChar:
00316     return NSAPI::NSNumberWithUnsignedChar;
00317   case BuiltinType::Short:
00318     return NSAPI::NSNumberWithShort;
00319   case BuiltinType::UShort:
00320     return NSAPI::NSNumberWithUnsignedShort;
00321   case BuiltinType::Int:
00322     return NSAPI::NSNumberWithInt;
00323   case BuiltinType::UInt:
00324     return NSAPI::NSNumberWithUnsignedInt;
00325   case BuiltinType::Long:
00326     return NSAPI::NSNumberWithLong;
00327   case BuiltinType::ULong:
00328     return NSAPI::NSNumberWithUnsignedLong;
00329   case BuiltinType::LongLong:
00330     return NSAPI::NSNumberWithLongLong;
00331   case BuiltinType::ULongLong:
00332     return NSAPI::NSNumberWithUnsignedLongLong;
00333   case BuiltinType::Float:
00334     return NSAPI::NSNumberWithFloat;
00335   case BuiltinType::Double:
00336     return NSAPI::NSNumberWithDouble;
00337   case BuiltinType::Bool:
00338     return NSAPI::NSNumberWithBool;
00339     
00340   case BuiltinType::Void:
00341   case BuiltinType::WChar_U:
00342   case BuiltinType::WChar_S:
00343   case BuiltinType::Char16:
00344   case BuiltinType::Char32:
00345   case BuiltinType::Int128:
00346   case BuiltinType::LongDouble:
00347   case BuiltinType::UInt128:
00348   case BuiltinType::NullPtr:
00349   case BuiltinType::ObjCClass:
00350   case BuiltinType::ObjCId:
00351   case BuiltinType::ObjCSel:
00352   case BuiltinType::OCLImage1d:
00353   case BuiltinType::OCLImage1dArray:
00354   case BuiltinType::OCLImage1dBuffer:
00355   case BuiltinType::OCLImage2d:
00356   case BuiltinType::OCLImage2dArray:
00357   case BuiltinType::OCLImage3d:
00358   case BuiltinType::OCLSampler:
00359   case BuiltinType::OCLEvent:
00360   case BuiltinType::BoundMember:
00361   case BuiltinType::Dependent:
00362   case BuiltinType::Overload:
00363   case BuiltinType::UnknownAny:
00364   case BuiltinType::ARCUnbridgedCast:
00365   case BuiltinType::Half:
00366   case BuiltinType::PseudoObject:
00367   case BuiltinType::BuiltinFn:
00368     break;
00369   }
00370   
00371   return None;
00372 }
00373 
00374 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c.
00375 bool NSAPI::isObjCBOOLType(QualType T) const {
00376   return isObjCTypedef(T, "BOOL", BOOLId);
00377 }
00378 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c.
00379 bool NSAPI::isObjCNSIntegerType(QualType T) const {
00380   return isObjCTypedef(T, "NSInteger", NSIntegerId);
00381 }
00382 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c.
00383 bool NSAPI::isObjCNSUIntegerType(QualType T) const {
00384   return isObjCTypedef(T, "NSUInteger", NSUIntegerId);
00385 }
00386 
00387 StringRef NSAPI::GetNSIntegralKind(QualType T) const {
00388   if (!Ctx.getLangOpts().ObjC1 || T.isNull())
00389     return StringRef();
00390   
00391   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
00392     StringRef NSIntegralResust =
00393       llvm::StringSwitch<StringRef>(
00394         TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName())
00395     .Case("int8_t", "int8_t")
00396     .Case("int16_t", "int16_t")
00397     .Case("int32_t", "int32_t")
00398     .Case("NSInteger", "NSInteger")
00399     .Case("int64_t", "int64_t")
00400     .Case("uint8_t", "uint8_t")
00401     .Case("uint16_t", "uint16_t")
00402     .Case("uint32_t", "uint32_t")
00403     .Case("NSUInteger", "NSUInteger")
00404     .Case("uint64_t", "uint64_t")
00405     .Default(StringRef());
00406     if (!NSIntegralResust.empty())
00407       return NSIntegralResust;
00408     T = TDT->desugar();
00409   }
00410   return StringRef();
00411 }
00412 
00413 bool NSAPI::isObjCTypedef(QualType T,
00414                           StringRef name, IdentifierInfo *&II) const {
00415   if (!Ctx.getLangOpts().ObjC1)
00416     return false;
00417   if (T.isNull())
00418     return false;
00419 
00420   if (!II)
00421     II = &Ctx.Idents.get(name);
00422 
00423   while (const TypedefType *TDT = T->getAs<TypedefType>()) {
00424     if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II)
00425       return true;
00426     T = TDT->desugar();
00427   }
00428 
00429   return false;
00430 }
00431 
00432 bool NSAPI::isObjCEnumerator(const Expr *E,
00433                              StringRef name, IdentifierInfo *&II) const {
00434   if (!Ctx.getLangOpts().ObjC1)
00435     return false;
00436   if (!E)
00437     return false;
00438 
00439   if (!II)
00440     II = &Ctx.Idents.get(name);
00441 
00442   if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts()))
00443     if (const EnumConstantDecl *
00444           EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl()))
00445       return EnumD->getIdentifier() == II;
00446 
00447   return false;
00448 }
00449 
00450 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids,
00451                                   Selector &Sel) const {
00452   if (Sel.isNull()) {
00453     SmallVector<IdentifierInfo *, 4> Idents;
00454     for (ArrayRef<StringRef>::const_iterator
00455            I = Ids.begin(), E = Ids.end(); I != E; ++I)
00456       Idents.push_back(&Ctx.Idents.get(*I));
00457     Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data());
00458   }
00459   return Sel;
00460 }