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