NSAPI.cpp revision 239462
1139731Simp//===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===// 21543Srgrimes// 31543Srgrimes// The LLVM Compiler Infrastructure 4247047Skib// 51543Srgrimes// This file is distributed under the University of Illinois Open Source 61543Srgrimes// License. See LICENSE.TXT for details. 71543Srgrimes// 81543Srgrimes//===----------------------------------------------------------------------===// 91543Srgrimes 101543Srgrimes#include "clang/AST/NSAPI.h" 111543Srgrimes#include "clang/AST/ASTContext.h" 121543Srgrimes#include "clang/AST/Expr.h" 131543Srgrimes 141543Srgrimesusing namespace clang; 151543Srgrimes 161543SrgrimesNSAPI::NSAPI(ASTContext &ctx) 171543Srgrimes : Ctx(ctx), ClassIds(), BOOLId(0), NSIntegerId(0), NSUIntegerId(0), 181543Srgrimes NSASCIIStringEncodingId(0), NSUTF8StringEncodingId(0) { 191543Srgrimes} 201543Srgrimes 211543SrgrimesIdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { 221543Srgrimes static const char *ClassName[NumClassIds] = { 231543Srgrimes "NSObject", 241543Srgrimes "NSString", 251543Srgrimes "NSArray", 261543Srgrimes "NSMutableArray", 271543Srgrimes "NSDictionary", 281543Srgrimes "NSMutableDictionary", 291543Srgrimes "NSNumber" 301543Srgrimes }; 3150477Speter 321543Srgrimes if (!ClassIds[K]) 331543Srgrimes return (ClassIds[K] = &Ctx.Idents.get(ClassName[K])); 34247047Skib 35247047Skib return ClassIds[K]; 362166Spaul} 371543Srgrimes 381543SrgrimesSelector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { 391543Srgrimes if (NSStringSelectors[MK].isNull()) { 401543Srgrimes Selector Sel; 41247047Skib switch (MK) { 42247047Skib case NSStr_stringWithString: 431543Srgrimes Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString")); 44105014Smike break; 451543Srgrimes case NSStr_stringWithUTF8String: 46247047Skib Sel = Ctx.Selectors.getUnarySelector( 471543Srgrimes &Ctx.Idents.get("stringWithUTF8String")); 48247047Skib break; 49247047Skib case NSStr_stringWithCStringEncoding: { 50247047Skib IdentifierInfo *KeyIdents[] = { 51247047Skib &Ctx.Idents.get("stringWithCString"), 52247047Skib &Ctx.Idents.get("encoding") 53247047Skib }; 54247047Skib Sel = Ctx.Selectors.getSelector(2, KeyIdents); 55247047Skib break; 56247047Skib } 57247047Skib case NSStr_stringWithCString: 58247047Skib Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString")); 59247047Skib break; 60247047Skib case NSStr_initWithString: 61247047Skib Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); 62247047Skib break; 63247047Skib } 64247047Skib return (NSStringSelectors[MK] = Sel); 65247047Skib } 66247047Skib 67247047Skib return NSStringSelectors[MK]; 68247047Skib} 69247047Skib 70247047Skibllvm::Optional<NSAPI::NSStringMethodKind> 71247047SkibNSAPI::getNSStringMethodKind(Selector Sel) const { 72247047Skib for (unsigned i = 0; i != NumNSStringMethods; ++i) { 73247047Skib NSStringMethodKind MK = NSStringMethodKind(i); 74247047Skib if (Sel == getNSStringSelector(MK)) 75247047Skib return MK; 76247047Skib } 77247047Skib 78247047Skib return llvm::Optional<NSStringMethodKind>(); 79247047Skib} 80247047Skib 81247047SkibSelector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { 82247047Skib if (NSArraySelectors[MK].isNull()) { 83247047Skib Selector Sel; 84247047Skib switch (MK) { 85247047Skib case NSArr_array: 86247047Skib Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array")); 87247047Skib break; 88247047Skib case NSArr_arrayWithArray: 89247047Skib Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray")); 90247047Skib break; 91247047Skib case NSArr_arrayWithObject: 92247047Skib Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject")); 93247047Skib break; 94247047Skib case NSArr_arrayWithObjects: 95247047Skib Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects")); 96247047Skib break; 97247047Skib case NSArr_arrayWithObjectsCount: { 98247047Skib IdentifierInfo *KeyIdents[] = { 99247047Skib &Ctx.Idents.get("arrayWithObjects"), 100247047Skib &Ctx.Idents.get("count") 101247047Skib }; 102247047Skib Sel = Ctx.Selectors.getSelector(2, KeyIdents); 103247047Skib break; 104247047Skib } 105247047Skib case NSArr_initWithArray: 1061543Srgrimes Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray")); 1071543Srgrimes break; 1081543Srgrimes case NSArr_initWithObjects: 1091543Srgrimes Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects")); 1101543Srgrimes break; 1111543Srgrimes case NSArr_objectAtIndex: 112227399Skib Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex")); 113227399Skib break; 114227399Skib case NSMutableArr_replaceObjectAtIndex: { 1151543Srgrimes IdentifierInfo *KeyIdents[] = { 11683047Sobrien &Ctx.Idents.get("replaceObjectAtIndex"), 117105014Smike &Ctx.Idents.get("withObject") 118114349Speter }; 119119889Speter Sel = Ctx.Selectors.getSelector(2, KeyIdents); 120114349Speter break; 121114349Speter } 122114349Speter } 123119889Speter return (NSArraySelectors[MK] = Sel); 124119889Speter } 125114349Speter 126119889Speter return NSArraySelectors[MK]; 127119889Speter} 128119889Speter 129119889Speterllvm::Optional<NSAPI::NSArrayMethodKind> 130119889SpeterNSAPI::getNSArrayMethodKind(Selector Sel) { 131119889Speter for (unsigned i = 0; i != NumNSArrayMethods; ++i) { 132119889Speter NSArrayMethodKind MK = NSArrayMethodKind(i); 133119889Speter if (Sel == getNSArraySelector(MK)) 134190623Skib return MK; 135190623Skib } 136190623Skib 137119889Speter return llvm::Optional<NSArrayMethodKind>(); 138190623Skib} 139190623Skib 140190623SkibSelector NSAPI::getNSDictionarySelector( 141114349Speter NSDictionaryMethodKind MK) const { 142114349Speter if (NSDictionarySelectors[MK].isNull()) { 143114349Speter Selector Sel; 144114349Speter switch (MK) { 145114349Speter case NSDict_dictionary: 146114349Speter Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary")); 147114349Speter break; 14853108Smarcel case NSDict_dictionaryWithDictionary: 149227399Skib Sel = Ctx.Selectors.getUnarySelector( 150227399Skib &Ctx.Idents.get("dictionaryWithDictionary")); 15153108Smarcel break; 152114349Speter case NSDict_dictionaryWithObjectForKey: { 153114349Speter IdentifierInfo *KeyIdents[] = { 154119888Speter &Ctx.Idents.get("dictionaryWithObject"), 155190623Skib &Ctx.Idents.get("forKey") 156190623Skib }; 157190623Skib Sel = Ctx.Selectors.getSelector(2, KeyIdents); 158190623Skib break; 159230765Skib } 160230765Skib case NSDict_dictionaryWithObjectsForKeys: { 161230765Skib IdentifierInfo *KeyIdents[] = { 162230765Skib &Ctx.Idents.get("dictionaryWithObjects"), 16351942Smarcel &Ctx.Idents.get("forKeys") 164105014Smike }; 165247047Skib Sel = Ctx.Selectors.getSelector(2, KeyIdents); 1669343Sbde break; 167247047Skib } 168 case NSDict_dictionaryWithObjectsForKeysCount: { 169 IdentifierInfo *KeyIdents[] = { 170 &Ctx.Idents.get("dictionaryWithObjects"), 171 &Ctx.Idents.get("forKeys"), 172 &Ctx.Idents.get("count") 173 }; 174 Sel = Ctx.Selectors.getSelector(3, KeyIdents); 175 break; 176 } 177 case NSDict_dictionaryWithObjectsAndKeys: 178 Sel = Ctx.Selectors.getUnarySelector( 179 &Ctx.Idents.get("dictionaryWithObjectsAndKeys")); 180 break; 181 case NSDict_initWithDictionary: 182 Sel = Ctx.Selectors.getUnarySelector( 183 &Ctx.Idents.get("initWithDictionary")); 184 break; 185 case NSDict_initWithObjectsAndKeys: 186 Sel = Ctx.Selectors.getUnarySelector( 187 &Ctx.Idents.get("initWithObjectsAndKeys")); 188 break; 189 case NSDict_objectForKey: 190 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); 191 break; 192 case NSMutableDict_setObjectForKey: { 193 IdentifierInfo *KeyIdents[] = { 194 &Ctx.Idents.get("setObject"), 195 &Ctx.Idents.get("forKey") 196 }; 197 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 198 break; 199 } 200 } 201 return (NSDictionarySelectors[MK] = Sel); 202 } 203 204 return NSDictionarySelectors[MK]; 205} 206 207llvm::Optional<NSAPI::NSDictionaryMethodKind> 208NSAPI::getNSDictionaryMethodKind(Selector Sel) { 209 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { 210 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); 211 if (Sel == getNSDictionarySelector(MK)) 212 return MK; 213 } 214 215 return llvm::Optional<NSDictionaryMethodKind>(); 216} 217 218Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, 219 bool Instance) const { 220 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { 221 "numberWithChar", 222 "numberWithUnsignedChar", 223 "numberWithShort", 224 "numberWithUnsignedShort", 225 "numberWithInt", 226 "numberWithUnsignedInt", 227 "numberWithLong", 228 "numberWithUnsignedLong", 229 "numberWithLongLong", 230 "numberWithUnsignedLongLong", 231 "numberWithFloat", 232 "numberWithDouble", 233 "numberWithBool", 234 "numberWithInteger", 235 "numberWithUnsignedInteger" 236 }; 237 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = { 238 "initWithChar", 239 "initWithUnsignedChar", 240 "initWithShort", 241 "initWithUnsignedShort", 242 "initWithInt", 243 "initWithUnsignedInt", 244 "initWithLong", 245 "initWithUnsignedLong", 246 "initWithLongLong", 247 "initWithUnsignedLongLong", 248 "initWithFloat", 249 "initWithDouble", 250 "initWithBool", 251 "initWithInteger", 252 "initWithUnsignedInteger" 253 }; 254 255 Selector *Sels; 256 const char **Names; 257 if (Instance) { 258 Sels = NSNumberInstanceSelectors; 259 Names = InstanceSelectorName; 260 } else { 261 Sels = NSNumberClassSelectors; 262 Names = ClassSelectorName; 263 } 264 265 if (Sels[MK].isNull()) 266 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK])); 267 return Sels[MK]; 268} 269 270llvm::Optional<NSAPI::NSNumberLiteralMethodKind> 271NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { 272 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { 273 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); 274 if (isNSNumberLiteralSelector(MK, Sel)) 275 return MK; 276 } 277 278 return llvm::Optional<NSNumberLiteralMethodKind>(); 279} 280 281llvm::Optional<NSAPI::NSNumberLiteralMethodKind> 282NSAPI::getNSNumberFactoryMethodKind(QualType T) const { 283 const BuiltinType *BT = T->getAs<BuiltinType>(); 284 if (!BT) 285 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); 286 287 const TypedefType *TDT = T->getAs<TypedefType>(); 288 if (TDT) { 289 QualType TDTTy = QualType(TDT, 0); 290 if (isObjCBOOLType(TDTTy)) 291 return NSAPI::NSNumberWithBool; 292 if (isObjCNSIntegerType(TDTTy)) 293 return NSAPI::NSNumberWithInteger; 294 if (isObjCNSUIntegerType(TDTTy)) 295 return NSAPI::NSNumberWithUnsignedInteger; 296 } 297 298 switch (BT->getKind()) { 299 case BuiltinType::Char_S: 300 case BuiltinType::SChar: 301 return NSAPI::NSNumberWithChar; 302 case BuiltinType::Char_U: 303 case BuiltinType::UChar: 304 return NSAPI::NSNumberWithUnsignedChar; 305 case BuiltinType::Short: 306 return NSAPI::NSNumberWithShort; 307 case BuiltinType::UShort: 308 return NSAPI::NSNumberWithUnsignedShort; 309 case BuiltinType::Int: 310 return NSAPI::NSNumberWithInt; 311 case BuiltinType::UInt: 312 return NSAPI::NSNumberWithUnsignedInt; 313 case BuiltinType::Long: 314 return NSAPI::NSNumberWithLong; 315 case BuiltinType::ULong: 316 return NSAPI::NSNumberWithUnsignedLong; 317 case BuiltinType::LongLong: 318 return NSAPI::NSNumberWithLongLong; 319 case BuiltinType::ULongLong: 320 return NSAPI::NSNumberWithUnsignedLongLong; 321 case BuiltinType::Float: 322 return NSAPI::NSNumberWithFloat; 323 case BuiltinType::Double: 324 return NSAPI::NSNumberWithDouble; 325 case BuiltinType::Bool: 326 return NSAPI::NSNumberWithBool; 327 328 case BuiltinType::Void: 329 case BuiltinType::WChar_U: 330 case BuiltinType::WChar_S: 331 case BuiltinType::Char16: 332 case BuiltinType::Char32: 333 case BuiltinType::Int128: 334 case BuiltinType::LongDouble: 335 case BuiltinType::UInt128: 336 case BuiltinType::NullPtr: 337 case BuiltinType::ObjCClass: 338 case BuiltinType::ObjCId: 339 case BuiltinType::ObjCSel: 340 case BuiltinType::BoundMember: 341 case BuiltinType::Dependent: 342 case BuiltinType::Overload: 343 case BuiltinType::UnknownAny: 344 case BuiltinType::ARCUnbridgedCast: 345 case BuiltinType::Half: 346 case BuiltinType::PseudoObject: 347 break; 348 } 349 350 return llvm::Optional<NSAPI::NSNumberLiteralMethodKind>(); 351} 352 353/// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. 354bool NSAPI::isObjCBOOLType(QualType T) const { 355 return isObjCTypedef(T, "BOOL", BOOLId); 356} 357/// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. 358bool NSAPI::isObjCNSIntegerType(QualType T) const { 359 return isObjCTypedef(T, "NSInteger", NSIntegerId); 360} 361/// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. 362bool NSAPI::isObjCNSUIntegerType(QualType T) const { 363 return isObjCTypedef(T, "NSUInteger", NSUIntegerId); 364} 365 366bool NSAPI::isObjCTypedef(QualType T, 367 StringRef name, IdentifierInfo *&II) const { 368 if (!Ctx.getLangOpts().ObjC1) 369 return false; 370 if (T.isNull()) 371 return false; 372 373 if (!II) 374 II = &Ctx.Idents.get(name); 375 376 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 377 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) 378 return true; 379 T = TDT->desugar(); 380 } 381 382 return false; 383} 384 385bool NSAPI::isObjCEnumerator(const Expr *E, 386 StringRef name, IdentifierInfo *&II) const { 387 if (!Ctx.getLangOpts().ObjC1) 388 return false; 389 if (!E) 390 return false; 391 392 if (!II) 393 II = &Ctx.Idents.get(name); 394 395 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) 396 if (const EnumConstantDecl * 397 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl())) 398 return EnumD->getIdentifier() == II; 399 400 return false; 401} 402 403Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, 404 Selector &Sel) const { 405 if (Sel.isNull()) { 406 SmallVector<IdentifierInfo *, 4> Idents; 407 for (ArrayRef<StringRef>::const_iterator 408 I = Ids.begin(), E = Ids.end(); I != E; ++I) 409 Idents.push_back(&Ctx.Idents.get(*I)); 410 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data()); 411 } 412 return Sel; 413} 414