1234287Sdim//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===// 2234287Sdim// 3234287Sdim// The LLVM Compiler Infrastructure 4234287Sdim// 5234287Sdim// This file is distributed under the University of Illinois Open Source 6234287Sdim// License. See LICENSE.TXT for details. 7234287Sdim// 8234287Sdim//===----------------------------------------------------------------------===// 9234287Sdim 10234287Sdim#include "clang/AST/NSAPI.h" 11234287Sdim#include "clang/AST/ASTContext.h" 12239462Sdim#include "clang/AST/Expr.h" 13234287Sdim 14234287Sdimusing namespace clang; 15234287Sdim 16234287SdimNSAPI::NSAPI(ASTContext &ctx) 17239462Sdim : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0), 18239462Sdim NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) { 19234287Sdim} 20234287Sdim 21234287SdimIdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { 22234287Sdim static const char *ClassName[NumClassIds] = { 23234287Sdim "NSObject", 24234287Sdim "NSString", 25234287Sdim "NSArray", 26234287Sdim "NSMutableArray", 27234287Sdim "NSDictionary", 28234287Sdim "NSMutableDictionary", 29234287Sdim "NSNumber" 30234287Sdim }; 31234287Sdim 32234287Sdim if (!ClassIds[K]) 33234287Sdim return (ClassIds[K] = &Ctx.Idents.get(ClassName[K])); 34234287Sdim 35234287Sdim return ClassIds[K]; 36234287Sdim} 37234287Sdim 38234287SdimSelector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { 39234287Sdim if (NSStringSelectors[MK].isNull()) { 40234287Sdim Selector Sel; 41234287Sdim switch (MK) { 42234287Sdim case NSStr_stringWithString: 43234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString")); 44234287Sdim break; 45239462Sdim case NSStr_stringWithUTF8String: 46239462Sdim Sel = Ctx.Selectors.getUnarySelector( 47239462Sdim &Ctx.Idents.get("stringWithUTF8String")); 48239462Sdim break; 49239462Sdim case NSStr_stringWithCStringEncoding: { 50239462Sdim IdentifierInfo *KeyIdents[] = { 51239462Sdim &Ctx.Idents.get("stringWithCString"), 52239462Sdim &Ctx.Idents.get("encoding") 53239462Sdim }; 54239462Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 55239462Sdim break; 56239462Sdim } 57239462Sdim case NSStr_stringWithCString: 58239462Sdim Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString")); 59239462Sdim break; 60234287Sdim case NSStr_initWithString: 61234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); 62234287Sdim break; 63234287Sdim } 64234287Sdim return (NSStringSelectors[MK] = Sel); 65234287Sdim } 66234287Sdim 67234287Sdim return NSStringSelectors[MK]; 68234287Sdim} 69234287Sdim 70249423SdimOptional<NSAPI::NSStringMethodKind> 71239462SdimNSAPI::getNSStringMethodKind(Selector Sel) const { 72239462Sdim for (unsigned i = 0; i != NumNSStringMethods; ++i) { 73239462Sdim NSStringMethodKind MK = NSStringMethodKind(i); 74239462Sdim if (Sel == getNSStringSelector(MK)) 75239462Sdim return MK; 76239462Sdim } 77239462Sdim 78249423Sdim return None; 79239462Sdim} 80239462Sdim 81234287SdimSelector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { 82234287Sdim if (NSArraySelectors[MK].isNull()) { 83234287Sdim Selector Sel; 84234287Sdim switch (MK) { 85234287Sdim case NSArr_array: 86234287Sdim Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array")); 87234287Sdim break; 88234287Sdim case NSArr_arrayWithArray: 89234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray")); 90234287Sdim break; 91234287Sdim case NSArr_arrayWithObject: 92234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject")); 93234287Sdim break; 94234287Sdim case NSArr_arrayWithObjects: 95234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects")); 96234287Sdim break; 97234287Sdim case NSArr_arrayWithObjectsCount: { 98234287Sdim IdentifierInfo *KeyIdents[] = { 99234287Sdim &Ctx.Idents.get("arrayWithObjects"), 100234287Sdim &Ctx.Idents.get("count") 101234287Sdim }; 102234287Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 103234287Sdim break; 104234287Sdim } 105234287Sdim case NSArr_initWithArray: 106234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray")); 107234287Sdim break; 108234287Sdim case NSArr_initWithObjects: 109234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects")); 110234287Sdim break; 111234287Sdim case NSArr_objectAtIndex: 112234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex")); 113234287Sdim break; 114234287Sdim case NSMutableArr_replaceObjectAtIndex: { 115234287Sdim IdentifierInfo *KeyIdents[] = { 116234287Sdim &Ctx.Idents.get("replaceObjectAtIndex"), 117234287Sdim &Ctx.Idents.get("withObject") 118234287Sdim }; 119234287Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 120234287Sdim break; 121234287Sdim } 122234287Sdim } 123234287Sdim return (NSArraySelectors[MK] = Sel); 124234287Sdim } 125234287Sdim 126234287Sdim return NSArraySelectors[MK]; 127234287Sdim} 128234287Sdim 129249423SdimOptional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) { 130234287Sdim for (unsigned i = 0; i != NumNSArrayMethods; ++i) { 131234287Sdim NSArrayMethodKind MK = NSArrayMethodKind(i); 132234287Sdim if (Sel == getNSArraySelector(MK)) 133234287Sdim return MK; 134234287Sdim } 135234287Sdim 136249423Sdim return None; 137234287Sdim} 138234287Sdim 139234287SdimSelector NSAPI::getNSDictionarySelector( 140234287Sdim NSDictionaryMethodKind MK) const { 141234287Sdim if (NSDictionarySelectors[MK].isNull()) { 142234287Sdim Selector Sel; 143234287Sdim switch (MK) { 144234287Sdim case NSDict_dictionary: 145234287Sdim Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary")); 146234287Sdim break; 147234287Sdim case NSDict_dictionaryWithDictionary: 148234287Sdim Sel = Ctx.Selectors.getUnarySelector( 149234287Sdim &Ctx.Idents.get("dictionaryWithDictionary")); 150234287Sdim break; 151234287Sdim case NSDict_dictionaryWithObjectForKey: { 152234287Sdim IdentifierInfo *KeyIdents[] = { 153234287Sdim &Ctx.Idents.get("dictionaryWithObject"), 154234287Sdim &Ctx.Idents.get("forKey") 155234287Sdim }; 156234287Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 157234287Sdim break; 158234287Sdim } 159234287Sdim case NSDict_dictionaryWithObjectsForKeys: { 160234287Sdim IdentifierInfo *KeyIdents[] = { 161234287Sdim &Ctx.Idents.get("dictionaryWithObjects"), 162234287Sdim &Ctx.Idents.get("forKeys") 163234287Sdim }; 164234287Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 165234287Sdim break; 166234287Sdim } 167234287Sdim case NSDict_dictionaryWithObjectsForKeysCount: { 168234287Sdim IdentifierInfo *KeyIdents[] = { 169234287Sdim &Ctx.Idents.get("dictionaryWithObjects"), 170234287Sdim &Ctx.Idents.get("forKeys"), 171234287Sdim &Ctx.Idents.get("count") 172234287Sdim }; 173234287Sdim Sel = Ctx.Selectors.getSelector(3, KeyIdents); 174234287Sdim break; 175234287Sdim } 176234287Sdim case NSDict_dictionaryWithObjectsAndKeys: 177234287Sdim Sel = Ctx.Selectors.getUnarySelector( 178234287Sdim &Ctx.Idents.get("dictionaryWithObjectsAndKeys")); 179234287Sdim break; 180234287Sdim case NSDict_initWithDictionary: 181234287Sdim Sel = Ctx.Selectors.getUnarySelector( 182234287Sdim &Ctx.Idents.get("initWithDictionary")); 183234287Sdim break; 184234287Sdim case NSDict_initWithObjectsAndKeys: 185234287Sdim Sel = Ctx.Selectors.getUnarySelector( 186234287Sdim &Ctx.Idents.get("initWithObjectsAndKeys")); 187234287Sdim break; 188249423Sdim case NSDict_initWithObjectsForKeys: { 189249423Sdim IdentifierInfo *KeyIdents[] = { 190249423Sdim &Ctx.Idents.get("initWithObjects"), 191249423Sdim &Ctx.Idents.get("forKeys") 192249423Sdim }; 193249423Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 194249423Sdim break; 195249423Sdim } 196234287Sdim case NSDict_objectForKey: 197234287Sdim Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); 198234287Sdim break; 199234287Sdim case NSMutableDict_setObjectForKey: { 200234287Sdim IdentifierInfo *KeyIdents[] = { 201234287Sdim &Ctx.Idents.get("setObject"), 202234287Sdim &Ctx.Idents.get("forKey") 203234287Sdim }; 204234287Sdim Sel = Ctx.Selectors.getSelector(2, KeyIdents); 205234287Sdim break; 206234287Sdim } 207234287Sdim } 208234287Sdim return (NSDictionarySelectors[MK] = Sel); 209234287Sdim } 210234287Sdim 211234287Sdim return NSDictionarySelectors[MK]; 212234287Sdim} 213234287Sdim 214249423SdimOptional<NSAPI::NSDictionaryMethodKind> 215234287SdimNSAPI::getNSDictionaryMethodKind(Selector Sel) { 216234287Sdim for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { 217234287Sdim NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); 218234287Sdim if (Sel == getNSDictionarySelector(MK)) 219234287Sdim return MK; 220234287Sdim } 221234287Sdim 222249423Sdim return None; 223234287Sdim} 224234287Sdim 225234287SdimSelector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, 226234287Sdim bool Instance) const { 227234287Sdim static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { 228234287Sdim "numberWithChar", 229234287Sdim "numberWithUnsignedChar", 230234287Sdim "numberWithShort", 231234287Sdim "numberWithUnsignedShort", 232234287Sdim "numberWithInt", 233234287Sdim "numberWithUnsignedInt", 234234287Sdim "numberWithLong", 235234287Sdim "numberWithUnsignedLong", 236234287Sdim "numberWithLongLong", 237234287Sdim "numberWithUnsignedLongLong", 238234287Sdim "numberWithFloat", 239234287Sdim "numberWithDouble", 240234287Sdim "numberWithBool", 241234287Sdim "numberWithInteger", 242234287Sdim "numberWithUnsignedInteger" 243234287Sdim }; 244234287Sdim static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = { 245234287Sdim "initWithChar", 246234287Sdim "initWithUnsignedChar", 247234287Sdim "initWithShort", 248234287Sdim "initWithUnsignedShort", 249234287Sdim "initWithInt", 250234287Sdim "initWithUnsignedInt", 251234287Sdim "initWithLong", 252234287Sdim "initWithUnsignedLong", 253234287Sdim "initWithLongLong", 254234287Sdim "initWithUnsignedLongLong", 255234287Sdim "initWithFloat", 256234287Sdim "initWithDouble", 257234287Sdim "initWithBool", 258234287Sdim "initWithInteger", 259234287Sdim "initWithUnsignedInteger" 260234287Sdim }; 261234287Sdim 262234287Sdim Selector *Sels; 263234287Sdim const char **Names; 264234287Sdim if (Instance) { 265234287Sdim Sels = NSNumberInstanceSelectors; 266234287Sdim Names = InstanceSelectorName; 267234287Sdim } else { 268234287Sdim Sels = NSNumberClassSelectors; 269234287Sdim Names = ClassSelectorName; 270234287Sdim } 271234287Sdim 272234287Sdim if (Sels[MK].isNull()) 273234287Sdim Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK])); 274234287Sdim return Sels[MK]; 275234287Sdim} 276234287Sdim 277249423SdimOptional<NSAPI::NSNumberLiteralMethodKind> 278234287SdimNSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { 279234287Sdim for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { 280234287Sdim NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); 281234287Sdim if (isNSNumberLiteralSelector(MK, Sel)) 282234287Sdim return MK; 283234287Sdim } 284234287Sdim 285249423Sdim return None; 286234287Sdim} 287234287Sdim 288249423SdimOptional<NSAPI::NSNumberLiteralMethodKind> 289239462SdimNSAPI::getNSNumberFactoryMethodKind(QualType T) const { 290234287Sdim const BuiltinType *BT = T->getAs<BuiltinType>(); 291234287Sdim if (!BT) 292249423Sdim return None; 293239462Sdim 294239462Sdim const TypedefType *TDT = T->getAs<TypedefType>(); 295239462Sdim if (TDT) { 296239462Sdim QualType TDTTy = QualType(TDT, 0); 297239462Sdim if (isObjCBOOLType(TDTTy)) 298239462Sdim return NSAPI::NSNumberWithBool; 299239462Sdim if (isObjCNSIntegerType(TDTTy)) 300239462Sdim return NSAPI::NSNumberWithInteger; 301239462Sdim if (isObjCNSUIntegerType(TDTTy)) 302239462Sdim return NSAPI::NSNumberWithUnsignedInteger; 303239462Sdim } 304239462Sdim 305234287Sdim switch (BT->getKind()) { 306234287Sdim case BuiltinType::Char_S: 307234287Sdim case BuiltinType::SChar: 308234287Sdim return NSAPI::NSNumberWithChar; 309234287Sdim case BuiltinType::Char_U: 310234287Sdim case BuiltinType::UChar: 311234287Sdim return NSAPI::NSNumberWithUnsignedChar; 312234287Sdim case BuiltinType::Short: 313234287Sdim return NSAPI::NSNumberWithShort; 314234287Sdim case BuiltinType::UShort: 315234287Sdim return NSAPI::NSNumberWithUnsignedShort; 316234287Sdim case BuiltinType::Int: 317234287Sdim return NSAPI::NSNumberWithInt; 318234287Sdim case BuiltinType::UInt: 319234287Sdim return NSAPI::NSNumberWithUnsignedInt; 320234287Sdim case BuiltinType::Long: 321234287Sdim return NSAPI::NSNumberWithLong; 322234287Sdim case BuiltinType::ULong: 323234287Sdim return NSAPI::NSNumberWithUnsignedLong; 324234287Sdim case BuiltinType::LongLong: 325234287Sdim return NSAPI::NSNumberWithLongLong; 326234287Sdim case BuiltinType::ULongLong: 327234287Sdim return NSAPI::NSNumberWithUnsignedLongLong; 328234287Sdim case BuiltinType::Float: 329234287Sdim return NSAPI::NSNumberWithFloat; 330234287Sdim case BuiltinType::Double: 331234287Sdim return NSAPI::NSNumberWithDouble; 332234287Sdim case BuiltinType::Bool: 333234287Sdim return NSAPI::NSNumberWithBool; 334234287Sdim 335234287Sdim case BuiltinType::Void: 336234287Sdim case BuiltinType::WChar_U: 337234287Sdim case BuiltinType::WChar_S: 338234287Sdim case BuiltinType::Char16: 339234287Sdim case BuiltinType::Char32: 340234287Sdim case BuiltinType::Int128: 341234287Sdim case BuiltinType::LongDouble: 342234287Sdim case BuiltinType::UInt128: 343234287Sdim case BuiltinType::NullPtr: 344234287Sdim case BuiltinType::ObjCClass: 345234287Sdim case BuiltinType::ObjCId: 346234287Sdim case BuiltinType::ObjCSel: 347249423Sdim case BuiltinType::OCLImage1d: 348249423Sdim case BuiltinType::OCLImage1dArray: 349249423Sdim case BuiltinType::OCLImage1dBuffer: 350249423Sdim case BuiltinType::OCLImage2d: 351249423Sdim case BuiltinType::OCLImage2dArray: 352249423Sdim case BuiltinType::OCLImage3d: 353249423Sdim case BuiltinType::OCLSampler: 354249423Sdim case BuiltinType::OCLEvent: 355234287Sdim case BuiltinType::BoundMember: 356234287Sdim case BuiltinType::Dependent: 357234287Sdim case BuiltinType::Overload: 358234287Sdim case BuiltinType::UnknownAny: 359234287Sdim case BuiltinType::ARCUnbridgedCast: 360234287Sdim case BuiltinType::Half: 361234287Sdim case BuiltinType::PseudoObject: 362243830Sdim case BuiltinType::BuiltinFn: 363234287Sdim break; 364234287Sdim } 365234287Sdim 366249423Sdim return None; 367234287Sdim} 368239462Sdim 369239462Sdim/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. 370239462Sdimbool NSAPI::isObjCBOOLType(QualType T) const { 371239462Sdim return isObjCTypedef(T, "BOOL", BOOLId); 372239462Sdim} 373239462Sdim/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. 374239462Sdimbool NSAPI::isObjCNSIntegerType(QualType T) const { 375239462Sdim return isObjCTypedef(T, "NSInteger", NSIntegerId); 376239462Sdim} 377239462Sdim/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. 378239462Sdimbool NSAPI::isObjCNSUIntegerType(QualType T) const { 379239462Sdim return isObjCTypedef(T, "NSUInteger", NSUIntegerId); 380239462Sdim} 381239462Sdim 382239462Sdimbool NSAPI::isObjCTypedef(QualType T, 383239462Sdim StringRef name, IdentifierInfo *&II) const { 384239462Sdim if (!Ctx.getLangOpts().ObjC1) 385239462Sdim return false; 386239462Sdim if (T.isNull()) 387239462Sdim return false; 388239462Sdim 389239462Sdim if (!II) 390239462Sdim II = &Ctx.Idents.get(name); 391239462Sdim 392239462Sdim while (const TypedefType *TDT = T->getAs<TypedefType>()) { 393239462Sdim if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) 394239462Sdim return true; 395239462Sdim T = TDT->desugar(); 396239462Sdim } 397239462Sdim 398239462Sdim return false; 399239462Sdim} 400239462Sdim 401239462Sdimbool NSAPI::isObjCEnumerator(const Expr *E, 402239462Sdim StringRef name, IdentifierInfo *&II) const { 403239462Sdim if (!Ctx.getLangOpts().ObjC1) 404239462Sdim return false; 405239462Sdim if (!E) 406239462Sdim return false; 407239462Sdim 408239462Sdim if (!II) 409239462Sdim II = &Ctx.Idents.get(name); 410239462Sdim 411239462Sdim if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) 412239462Sdim if (const EnumConstantDecl * 413239462Sdim EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl())) 414239462Sdim return EnumD->getIdentifier() == II; 415239462Sdim 416239462Sdim return false; 417239462Sdim} 418239462Sdim 419239462SdimSelector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, 420239462Sdim Selector &Sel) const { 421239462Sdim if (Sel.isNull()) { 422239462Sdim SmallVector<IdentifierInfo *, 4> Idents; 423239462Sdim for (ArrayRef<StringRef>::const_iterator 424239462Sdim I = Ids.begin(), E = Ids.end(); I != E; ++I) 425239462Sdim Idents.push_back(&Ctx.Idents.get(*I)); 426239462Sdim Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data()); 427239462Sdim } 428239462Sdim return Sel; 429239462Sdim} 430