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