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(nullptr), NSIntegerId(nullptr), 18 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr), 19 NSUTF8StringEncodingId(nullptr) {} 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_initWithUTF8String: 50 Sel = Ctx.Selectors.getUnarySelector( 51 &Ctx.Idents.get("initWithUTF8String")); 52 break; 53 case NSStr_stringWithCStringEncoding: { 54 IdentifierInfo *KeyIdents[] = { 55 &Ctx.Idents.get("stringWithCString"), 56 &Ctx.Idents.get("encoding") 57 }; 58 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 59 break; 60 } 61 case NSStr_stringWithCString: 62 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString")); 63 break; 64 case NSStr_initWithString: 65 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); 66 break; 67 } 68 return (NSStringSelectors[MK] = Sel); 69 } 70 71 return NSStringSelectors[MK]; 72 } 73 74 Optional<NSAPI::NSStringMethodKind> 75 NSAPI::getNSStringMethodKind(Selector Sel) const { 76 for (unsigned i = 0; i != NumNSStringMethods; ++i) { 77 NSStringMethodKind MK = NSStringMethodKind(i); 78 if (Sel == getNSStringSelector(MK)) 79 return MK; 80 } 81 82 return None; 83 } 84 85 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { 86 if (NSArraySelectors[MK].isNull()) { 87 Selector Sel; 88 switch (MK) { 89 case NSArr_array: 90 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array")); 91 break; 92 case NSArr_arrayWithArray: 93 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray")); 94 break; 95 case NSArr_arrayWithObject: 96 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject")); 97 break; 98 case NSArr_arrayWithObjects: 99 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects")); 100 break; 101 case NSArr_arrayWithObjectsCount: { 102 IdentifierInfo *KeyIdents[] = { 103 &Ctx.Idents.get("arrayWithObjects"), 104 &Ctx.Idents.get("count") 105 }; 106 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 107 break; 108 } 109 case NSArr_initWithArray: 110 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray")); 111 break; 112 case NSArr_initWithObjects: 113 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects")); 114 break; 115 case NSArr_objectAtIndex: 116 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex")); 117 break; 118 case NSMutableArr_replaceObjectAtIndex: { 119 IdentifierInfo *KeyIdents[] = { 120 &Ctx.Idents.get("replaceObjectAtIndex"), 121 &Ctx.Idents.get("withObject") 122 }; 123 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 124 break; 125 } 126 case NSArr_initWithObjectsCount: { 127 IdentifierInfo *KeyIdents[] = { 128 &Ctx.Idents.get("initWithObjects"), 129 &Ctx.Idents.get("count") 130 }; 131 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 132 break; 133 } 134 } 135 return (NSArraySelectors[MK] = Sel); 136 } 137 138 return NSArraySelectors[MK]; 139 } 140 141 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) { 142 for (unsigned i = 0; i != NumNSArrayMethods; ++i) { 143 NSArrayMethodKind MK = NSArrayMethodKind(i); 144 if (Sel == getNSArraySelector(MK)) 145 return MK; 146 } 147 148 return None; 149 } 150 151 Selector NSAPI::getNSDictionarySelector( 152 NSDictionaryMethodKind MK) const { 153 if (NSDictionarySelectors[MK].isNull()) { 154 Selector Sel; 155 switch (MK) { 156 case NSDict_dictionary: 157 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary")); 158 break; 159 case NSDict_dictionaryWithDictionary: 160 Sel = Ctx.Selectors.getUnarySelector( 161 &Ctx.Idents.get("dictionaryWithDictionary")); 162 break; 163 case NSDict_dictionaryWithObjectForKey: { 164 IdentifierInfo *KeyIdents[] = { 165 &Ctx.Idents.get("dictionaryWithObject"), 166 &Ctx.Idents.get("forKey") 167 }; 168 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 169 break; 170 } 171 case NSDict_dictionaryWithObjectsForKeys: { 172 IdentifierInfo *KeyIdents[] = { 173 &Ctx.Idents.get("dictionaryWithObjects"), 174 &Ctx.Idents.get("forKeys") 175 }; 176 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 177 break; 178 } 179 case NSDict_dictionaryWithObjectsForKeysCount: { 180 IdentifierInfo *KeyIdents[] = { 181 &Ctx.Idents.get("dictionaryWithObjects"), 182 &Ctx.Idents.get("forKeys"), 183 &Ctx.Idents.get("count") 184 }; 185 Sel = Ctx.Selectors.getSelector(3, KeyIdents); 186 break; 187 } 188 case NSDict_dictionaryWithObjectsAndKeys: 189 Sel = Ctx.Selectors.getUnarySelector( 190 &Ctx.Idents.get("dictionaryWithObjectsAndKeys")); 191 break; 192 case NSDict_initWithDictionary: 193 Sel = Ctx.Selectors.getUnarySelector( 194 &Ctx.Idents.get("initWithDictionary")); 195 break; 196 case NSDict_initWithObjectsAndKeys: 197 Sel = Ctx.Selectors.getUnarySelector( 198 &Ctx.Idents.get("initWithObjectsAndKeys")); 199 break; 200 case NSDict_initWithObjectsForKeys: { 201 IdentifierInfo *KeyIdents[] = { 202 &Ctx.Idents.get("initWithObjects"), 203 &Ctx.Idents.get("forKeys") 204 }; 205 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 206 break; 207 } 208 case NSDict_objectForKey: 209 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); 210 break; 211 case NSMutableDict_setObjectForKey: { 212 IdentifierInfo *KeyIdents[] = { 213 &Ctx.Idents.get("setObject"), 214 &Ctx.Idents.get("forKey") 215 }; 216 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 217 break; 218 } 219 case NSDict_initWithObjectsForKeysCount: { 220 IdentifierInfo *KeyIdents[] = { 221 &Ctx.Idents.get("initWithObjects"), 222 &Ctx.Idents.get("forKeys"), 223 &Ctx.Idents.get("count") 224 }; 225 Sel = Ctx.Selectors.getSelector(3, KeyIdents); 226 break; 227 } 228 } 229 return (NSDictionarySelectors[MK] = Sel); 230 } 231 232 return NSDictionarySelectors[MK]; 233 } 234 235 Optional<NSAPI::NSDictionaryMethodKind> 236 NSAPI::getNSDictionaryMethodKind(Selector Sel) { 237 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { 238 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); 239 if (Sel == getNSDictionarySelector(MK)) 240 return MK; 241 } 242 243 return None; 244 } 245 246 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, 247 bool Instance) const { 248 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { 249 "numberWithChar", 250 "numberWithUnsignedChar", 251 "numberWithShort", 252 "numberWithUnsignedShort", 253 "numberWithInt", 254 "numberWithUnsignedInt", 255 "numberWithLong", 256 "numberWithUnsignedLong", 257 "numberWithLongLong", 258 "numberWithUnsignedLongLong", 259 "numberWithFloat", 260 "numberWithDouble", 261 "numberWithBool", 262 "numberWithInteger", 263 "numberWithUnsignedInteger" 264 }; 265 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = { 266 "initWithChar", 267 "initWithUnsignedChar", 268 "initWithShort", 269 "initWithUnsignedShort", 270 "initWithInt", 271 "initWithUnsignedInt", 272 "initWithLong", 273 "initWithUnsignedLong", 274 "initWithLongLong", 275 "initWithUnsignedLongLong", 276 "initWithFloat", 277 "initWithDouble", 278 "initWithBool", 279 "initWithInteger", 280 "initWithUnsignedInteger" 281 }; 282 283 Selector *Sels; 284 const char **Names; 285 if (Instance) { 286 Sels = NSNumberInstanceSelectors; 287 Names = InstanceSelectorName; 288 } else { 289 Sels = NSNumberClassSelectors; 290 Names = ClassSelectorName; 291 } 292 293 if (Sels[MK].isNull()) 294 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK])); 295 return Sels[MK]; 296 } 297 298 Optional<NSAPI::NSNumberLiteralMethodKind> 299 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { 300 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { 301 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); 302 if (isNSNumberLiteralSelector(MK, Sel)) 303 return MK; 304 } 305 306 return None; 307 } 308 309 Optional<NSAPI::NSNumberLiteralMethodKind> 310 NSAPI::getNSNumberFactoryMethodKind(QualType T) const { 311 const BuiltinType *BT = T->getAs<BuiltinType>(); 312 if (!BT) 313 return None; 314 315 const TypedefType *TDT = T->getAs<TypedefType>(); 316 if (TDT) { 317 QualType TDTTy = QualType(TDT, 0); 318 if (isObjCBOOLType(TDTTy)) 319 return NSAPI::NSNumberWithBool; 320 if (isObjCNSIntegerType(TDTTy)) 321 return NSAPI::NSNumberWithInteger; 322 if (isObjCNSUIntegerType(TDTTy)) 323 return NSAPI::NSNumberWithUnsignedInteger; 324 } 325 326 switch (BT->getKind()) { 327 case BuiltinType::Char_S: 328 case BuiltinType::SChar: 329 return NSAPI::NSNumberWithChar; 330 case BuiltinType::Char_U: 331 case BuiltinType::UChar: 332 return NSAPI::NSNumberWithUnsignedChar; 333 case BuiltinType::Short: 334 return NSAPI::NSNumberWithShort; 335 case BuiltinType::UShort: 336 return NSAPI::NSNumberWithUnsignedShort; 337 case BuiltinType::Int: 338 return NSAPI::NSNumberWithInt; 339 case BuiltinType::UInt: 340 return NSAPI::NSNumberWithUnsignedInt; 341 case BuiltinType::Long: 342 return NSAPI::NSNumberWithLong; 343 case BuiltinType::ULong: 344 return NSAPI::NSNumberWithUnsignedLong; 345 case BuiltinType::LongLong: 346 return NSAPI::NSNumberWithLongLong; 347 case BuiltinType::ULongLong: 348 return NSAPI::NSNumberWithUnsignedLongLong; 349 case BuiltinType::Float: 350 return NSAPI::NSNumberWithFloat; 351 case BuiltinType::Double: 352 return NSAPI::NSNumberWithDouble; 353 case BuiltinType::Bool: 354 return NSAPI::NSNumberWithBool; 355 356 case BuiltinType::Void: 357 case BuiltinType::WChar_U: 358 case BuiltinType::WChar_S: 359 case BuiltinType::Char16: 360 case BuiltinType::Char32: 361 case BuiltinType::Int128: 362 case BuiltinType::LongDouble: 363 case BuiltinType::UInt128: 364 case BuiltinType::NullPtr: 365 case BuiltinType::ObjCClass: 366 case BuiltinType::ObjCId: 367 case BuiltinType::ObjCSel: 368 case BuiltinType::OCLImage1d: 369 case BuiltinType::OCLImage1dArray: 370 case BuiltinType::OCLImage1dBuffer: 371 case BuiltinType::OCLImage2d: 372 case BuiltinType::OCLImage2dArray: 373 case BuiltinType::OCLImage3d: 374 case BuiltinType::OCLSampler: 375 case BuiltinType::OCLEvent: 376 case BuiltinType::BoundMember: 377 case BuiltinType::Dependent: 378 case BuiltinType::Overload: 379 case BuiltinType::UnknownAny: 380 case BuiltinType::ARCUnbridgedCast: 381 case BuiltinType::Half: 382 case BuiltinType::PseudoObject: 383 case BuiltinType::BuiltinFn: 384 break; 385 } 386 387 return None; 388 } 389 390 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. 391 bool NSAPI::isObjCBOOLType(QualType T) const { 392 return isObjCTypedef(T, "BOOL", BOOLId); 393 } 394 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. 395 bool NSAPI::isObjCNSIntegerType(QualType T) const { 396 return isObjCTypedef(T, "NSInteger", NSIntegerId); 397 } 398 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. 399 bool NSAPI::isObjCNSUIntegerType(QualType T) const { 400 return isObjCTypedef(T, "NSUInteger", NSUIntegerId); 401 } 402 403 bool NSAPI::isObjCTypedef(QualType T, 404 StringRef name, IdentifierInfo *&II) const { 405 if (!Ctx.getLangOpts().ObjC1) 406 return false; 407 if (T.isNull()) 408 return false; 409 410 if (!II) 411 II = &Ctx.Idents.get(name); 412 413 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 414 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) 415 return true; 416 T = TDT->desugar(); 417 } 418 419 return false; 420 } 421 422 bool NSAPI::isObjCEnumerator(const Expr *E, 423 StringRef name, IdentifierInfo *&II) const { 424 if (!Ctx.getLangOpts().ObjC1) 425 return false; 426 if (!E) 427 return false; 428 429 if (!II) 430 II = &Ctx.Idents.get(name); 431 432 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) 433 if (const EnumConstantDecl * 434 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl())) 435 return EnumD->getIdentifier() == II; 436 437 return false; 438 } 439 440 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, 441 Selector &Sel) const { 442 if (Sel.isNull()) { 443 SmallVector<IdentifierInfo *, 4> Idents; 444 for (ArrayRef<StringRef>::const_iterator 445 I = Ids.begin(), E = Ids.end(); I != E; ++I) 446 Idents.push_back(&Ctx.Idents.get(*I)); 447 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data()); 448 } 449 return Sel; 450 } 451