clang API Documentation
00001 //===--- NSAPI.cpp - NSFoundation APIs ------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "clang/AST/NSAPI.h" 00011 #include "clang/AST/ASTContext.h" 00012 #include "clang/AST/Expr.h" 00013 #include "llvm/ADT/StringSwitch.h" 00014 00015 using namespace clang; 00016 00017 NSAPI::NSAPI(ASTContext &ctx) 00018 : Ctx(ctx), ClassIds(), BOOLId(nullptr), NSIntegerId(nullptr), 00019 NSUIntegerId(nullptr), NSASCIIStringEncodingId(nullptr), 00020 NSUTF8StringEncodingId(nullptr) {} 00021 00022 IdentifierInfo *NSAPI::getNSClassId(NSClassIdKindKind K) const { 00023 static const char *ClassName[NumClassIds] = { 00024 "NSObject", 00025 "NSString", 00026 "NSArray", 00027 "NSMutableArray", 00028 "NSDictionary", 00029 "NSMutableDictionary", 00030 "NSNumber" 00031 }; 00032 00033 if (!ClassIds[K]) 00034 return (ClassIds[K] = &Ctx.Idents.get(ClassName[K])); 00035 00036 return ClassIds[K]; 00037 } 00038 00039 Selector NSAPI::getNSStringSelector(NSStringMethodKind MK) const { 00040 if (NSStringSelectors[MK].isNull()) { 00041 Selector Sel; 00042 switch (MK) { 00043 case NSStr_stringWithString: 00044 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithString")); 00045 break; 00046 case NSStr_stringWithUTF8String: 00047 Sel = Ctx.Selectors.getUnarySelector( 00048 &Ctx.Idents.get("stringWithUTF8String")); 00049 break; 00050 case NSStr_initWithUTF8String: 00051 Sel = Ctx.Selectors.getUnarySelector( 00052 &Ctx.Idents.get("initWithUTF8String")); 00053 break; 00054 case NSStr_stringWithCStringEncoding: { 00055 IdentifierInfo *KeyIdents[] = { 00056 &Ctx.Idents.get("stringWithCString"), 00057 &Ctx.Idents.get("encoding") 00058 }; 00059 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00060 break; 00061 } 00062 case NSStr_stringWithCString: 00063 Sel= Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("stringWithCString")); 00064 break; 00065 case NSStr_initWithString: 00066 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithString")); 00067 break; 00068 } 00069 return (NSStringSelectors[MK] = Sel); 00070 } 00071 00072 return NSStringSelectors[MK]; 00073 } 00074 00075 Optional<NSAPI::NSStringMethodKind> 00076 NSAPI::getNSStringMethodKind(Selector Sel) const { 00077 for (unsigned i = 0; i != NumNSStringMethods; ++i) { 00078 NSStringMethodKind MK = NSStringMethodKind(i); 00079 if (Sel == getNSStringSelector(MK)) 00080 return MK; 00081 } 00082 00083 return None; 00084 } 00085 00086 Selector NSAPI::getNSArraySelector(NSArrayMethodKind MK) const { 00087 if (NSArraySelectors[MK].isNull()) { 00088 Selector Sel; 00089 switch (MK) { 00090 case NSArr_array: 00091 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("array")); 00092 break; 00093 case NSArr_arrayWithArray: 00094 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithArray")); 00095 break; 00096 case NSArr_arrayWithObject: 00097 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObject")); 00098 break; 00099 case NSArr_arrayWithObjects: 00100 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("arrayWithObjects")); 00101 break; 00102 case NSArr_arrayWithObjectsCount: { 00103 IdentifierInfo *KeyIdents[] = { 00104 &Ctx.Idents.get("arrayWithObjects"), 00105 &Ctx.Idents.get("count") 00106 }; 00107 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00108 break; 00109 } 00110 case NSArr_initWithArray: 00111 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithArray")); 00112 break; 00113 case NSArr_initWithObjects: 00114 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("initWithObjects")); 00115 break; 00116 case NSArr_objectAtIndex: 00117 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectAtIndex")); 00118 break; 00119 case NSMutableArr_replaceObjectAtIndex: { 00120 IdentifierInfo *KeyIdents[] = { 00121 &Ctx.Idents.get("replaceObjectAtIndex"), 00122 &Ctx.Idents.get("withObject") 00123 }; 00124 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00125 break; 00126 } 00127 } 00128 return (NSArraySelectors[MK] = Sel); 00129 } 00130 00131 return NSArraySelectors[MK]; 00132 } 00133 00134 Optional<NSAPI::NSArrayMethodKind> NSAPI::getNSArrayMethodKind(Selector Sel) { 00135 for (unsigned i = 0; i != NumNSArrayMethods; ++i) { 00136 NSArrayMethodKind MK = NSArrayMethodKind(i); 00137 if (Sel == getNSArraySelector(MK)) 00138 return MK; 00139 } 00140 00141 return None; 00142 } 00143 00144 Selector NSAPI::getNSDictionarySelector( 00145 NSDictionaryMethodKind MK) const { 00146 if (NSDictionarySelectors[MK].isNull()) { 00147 Selector Sel; 00148 switch (MK) { 00149 case NSDict_dictionary: 00150 Sel = Ctx.Selectors.getNullarySelector(&Ctx.Idents.get("dictionary")); 00151 break; 00152 case NSDict_dictionaryWithDictionary: 00153 Sel = Ctx.Selectors.getUnarySelector( 00154 &Ctx.Idents.get("dictionaryWithDictionary")); 00155 break; 00156 case NSDict_dictionaryWithObjectForKey: { 00157 IdentifierInfo *KeyIdents[] = { 00158 &Ctx.Idents.get("dictionaryWithObject"), 00159 &Ctx.Idents.get("forKey") 00160 }; 00161 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00162 break; 00163 } 00164 case NSDict_dictionaryWithObjectsForKeys: { 00165 IdentifierInfo *KeyIdents[] = { 00166 &Ctx.Idents.get("dictionaryWithObjects"), 00167 &Ctx.Idents.get("forKeys") 00168 }; 00169 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00170 break; 00171 } 00172 case NSDict_dictionaryWithObjectsForKeysCount: { 00173 IdentifierInfo *KeyIdents[] = { 00174 &Ctx.Idents.get("dictionaryWithObjects"), 00175 &Ctx.Idents.get("forKeys"), 00176 &Ctx.Idents.get("count") 00177 }; 00178 Sel = Ctx.Selectors.getSelector(3, KeyIdents); 00179 break; 00180 } 00181 case NSDict_dictionaryWithObjectsAndKeys: 00182 Sel = Ctx.Selectors.getUnarySelector( 00183 &Ctx.Idents.get("dictionaryWithObjectsAndKeys")); 00184 break; 00185 case NSDict_initWithDictionary: 00186 Sel = Ctx.Selectors.getUnarySelector( 00187 &Ctx.Idents.get("initWithDictionary")); 00188 break; 00189 case NSDict_initWithObjectsAndKeys: 00190 Sel = Ctx.Selectors.getUnarySelector( 00191 &Ctx.Idents.get("initWithObjectsAndKeys")); 00192 break; 00193 case NSDict_initWithObjectsForKeys: { 00194 IdentifierInfo *KeyIdents[] = { 00195 &Ctx.Idents.get("initWithObjects"), 00196 &Ctx.Idents.get("forKeys") 00197 }; 00198 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00199 break; 00200 } 00201 case NSDict_objectForKey: 00202 Sel = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get("objectForKey")); 00203 break; 00204 case NSMutableDict_setObjectForKey: { 00205 IdentifierInfo *KeyIdents[] = { 00206 &Ctx.Idents.get("setObject"), 00207 &Ctx.Idents.get("forKey") 00208 }; 00209 Sel = Ctx.Selectors.getSelector(2, KeyIdents); 00210 break; 00211 } 00212 } 00213 return (NSDictionarySelectors[MK] = Sel); 00214 } 00215 00216 return NSDictionarySelectors[MK]; 00217 } 00218 00219 Optional<NSAPI::NSDictionaryMethodKind> 00220 NSAPI::getNSDictionaryMethodKind(Selector Sel) { 00221 for (unsigned i = 0; i != NumNSDictionaryMethods; ++i) { 00222 NSDictionaryMethodKind MK = NSDictionaryMethodKind(i); 00223 if (Sel == getNSDictionarySelector(MK)) 00224 return MK; 00225 } 00226 00227 return None; 00228 } 00229 00230 Selector NSAPI::getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, 00231 bool Instance) const { 00232 static const char *ClassSelectorName[NumNSNumberLiteralMethods] = { 00233 "numberWithChar", 00234 "numberWithUnsignedChar", 00235 "numberWithShort", 00236 "numberWithUnsignedShort", 00237 "numberWithInt", 00238 "numberWithUnsignedInt", 00239 "numberWithLong", 00240 "numberWithUnsignedLong", 00241 "numberWithLongLong", 00242 "numberWithUnsignedLongLong", 00243 "numberWithFloat", 00244 "numberWithDouble", 00245 "numberWithBool", 00246 "numberWithInteger", 00247 "numberWithUnsignedInteger" 00248 }; 00249 static const char *InstanceSelectorName[NumNSNumberLiteralMethods] = { 00250 "initWithChar", 00251 "initWithUnsignedChar", 00252 "initWithShort", 00253 "initWithUnsignedShort", 00254 "initWithInt", 00255 "initWithUnsignedInt", 00256 "initWithLong", 00257 "initWithUnsignedLong", 00258 "initWithLongLong", 00259 "initWithUnsignedLongLong", 00260 "initWithFloat", 00261 "initWithDouble", 00262 "initWithBool", 00263 "initWithInteger", 00264 "initWithUnsignedInteger" 00265 }; 00266 00267 Selector *Sels; 00268 const char **Names; 00269 if (Instance) { 00270 Sels = NSNumberInstanceSelectors; 00271 Names = InstanceSelectorName; 00272 } else { 00273 Sels = NSNumberClassSelectors; 00274 Names = ClassSelectorName; 00275 } 00276 00277 if (Sels[MK].isNull()) 00278 Sels[MK] = Ctx.Selectors.getUnarySelector(&Ctx.Idents.get(Names[MK])); 00279 return Sels[MK]; 00280 } 00281 00282 Optional<NSAPI::NSNumberLiteralMethodKind> 00283 NSAPI::getNSNumberLiteralMethodKind(Selector Sel) const { 00284 for (unsigned i = 0; i != NumNSNumberLiteralMethods; ++i) { 00285 NSNumberLiteralMethodKind MK = NSNumberLiteralMethodKind(i); 00286 if (isNSNumberLiteralSelector(MK, Sel)) 00287 return MK; 00288 } 00289 00290 return None; 00291 } 00292 00293 Optional<NSAPI::NSNumberLiteralMethodKind> 00294 NSAPI::getNSNumberFactoryMethodKind(QualType T) const { 00295 const BuiltinType *BT = T->getAs<BuiltinType>(); 00296 if (!BT) 00297 return None; 00298 00299 const TypedefType *TDT = T->getAs<TypedefType>(); 00300 if (TDT) { 00301 QualType TDTTy = QualType(TDT, 0); 00302 if (isObjCBOOLType(TDTTy)) 00303 return NSAPI::NSNumberWithBool; 00304 if (isObjCNSIntegerType(TDTTy)) 00305 return NSAPI::NSNumberWithInteger; 00306 if (isObjCNSUIntegerType(TDTTy)) 00307 return NSAPI::NSNumberWithUnsignedInteger; 00308 } 00309 00310 switch (BT->getKind()) { 00311 case BuiltinType::Char_S: 00312 case BuiltinType::SChar: 00313 return NSAPI::NSNumberWithChar; 00314 case BuiltinType::Char_U: 00315 case BuiltinType::UChar: 00316 return NSAPI::NSNumberWithUnsignedChar; 00317 case BuiltinType::Short: 00318 return NSAPI::NSNumberWithShort; 00319 case BuiltinType::UShort: 00320 return NSAPI::NSNumberWithUnsignedShort; 00321 case BuiltinType::Int: 00322 return NSAPI::NSNumberWithInt; 00323 case BuiltinType::UInt: 00324 return NSAPI::NSNumberWithUnsignedInt; 00325 case BuiltinType::Long: 00326 return NSAPI::NSNumberWithLong; 00327 case BuiltinType::ULong: 00328 return NSAPI::NSNumberWithUnsignedLong; 00329 case BuiltinType::LongLong: 00330 return NSAPI::NSNumberWithLongLong; 00331 case BuiltinType::ULongLong: 00332 return NSAPI::NSNumberWithUnsignedLongLong; 00333 case BuiltinType::Float: 00334 return NSAPI::NSNumberWithFloat; 00335 case BuiltinType::Double: 00336 return NSAPI::NSNumberWithDouble; 00337 case BuiltinType::Bool: 00338 return NSAPI::NSNumberWithBool; 00339 00340 case BuiltinType::Void: 00341 case BuiltinType::WChar_U: 00342 case BuiltinType::WChar_S: 00343 case BuiltinType::Char16: 00344 case BuiltinType::Char32: 00345 case BuiltinType::Int128: 00346 case BuiltinType::LongDouble: 00347 case BuiltinType::UInt128: 00348 case BuiltinType::NullPtr: 00349 case BuiltinType::ObjCClass: 00350 case BuiltinType::ObjCId: 00351 case BuiltinType::ObjCSel: 00352 case BuiltinType::OCLImage1d: 00353 case BuiltinType::OCLImage1dArray: 00354 case BuiltinType::OCLImage1dBuffer: 00355 case BuiltinType::OCLImage2d: 00356 case BuiltinType::OCLImage2dArray: 00357 case BuiltinType::OCLImage3d: 00358 case BuiltinType::OCLSampler: 00359 case BuiltinType::OCLEvent: 00360 case BuiltinType::BoundMember: 00361 case BuiltinType::Dependent: 00362 case BuiltinType::Overload: 00363 case BuiltinType::UnknownAny: 00364 case BuiltinType::ARCUnbridgedCast: 00365 case BuiltinType::Half: 00366 case BuiltinType::PseudoObject: 00367 case BuiltinType::BuiltinFn: 00368 break; 00369 } 00370 00371 return None; 00372 } 00373 00374 /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. 00375 bool NSAPI::isObjCBOOLType(QualType T) const { 00376 return isObjCTypedef(T, "BOOL", BOOLId); 00377 } 00378 /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. 00379 bool NSAPI::isObjCNSIntegerType(QualType T) const { 00380 return isObjCTypedef(T, "NSInteger", NSIntegerId); 00381 } 00382 /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. 00383 bool NSAPI::isObjCNSUIntegerType(QualType T) const { 00384 return isObjCTypedef(T, "NSUInteger", NSUIntegerId); 00385 } 00386 00387 StringRef NSAPI::GetNSIntegralKind(QualType T) const { 00388 if (!Ctx.getLangOpts().ObjC1 || T.isNull()) 00389 return StringRef(); 00390 00391 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 00392 StringRef NSIntegralResust = 00393 llvm::StringSwitch<StringRef>( 00394 TDT->getDecl()->getDeclName().getAsIdentifierInfo()->getName()) 00395 .Case("int8_t", "int8_t") 00396 .Case("int16_t", "int16_t") 00397 .Case("int32_t", "int32_t") 00398 .Case("NSInteger", "NSInteger") 00399 .Case("int64_t", "int64_t") 00400 .Case("uint8_t", "uint8_t") 00401 .Case("uint16_t", "uint16_t") 00402 .Case("uint32_t", "uint32_t") 00403 .Case("NSUInteger", "NSUInteger") 00404 .Case("uint64_t", "uint64_t") 00405 .Default(StringRef()); 00406 if (!NSIntegralResust.empty()) 00407 return NSIntegralResust; 00408 T = TDT->desugar(); 00409 } 00410 return StringRef(); 00411 } 00412 00413 bool NSAPI::isObjCTypedef(QualType T, 00414 StringRef name, IdentifierInfo *&II) const { 00415 if (!Ctx.getLangOpts().ObjC1) 00416 return false; 00417 if (T.isNull()) 00418 return false; 00419 00420 if (!II) 00421 II = &Ctx.Idents.get(name); 00422 00423 while (const TypedefType *TDT = T->getAs<TypedefType>()) { 00424 if (TDT->getDecl()->getDeclName().getAsIdentifierInfo() == II) 00425 return true; 00426 T = TDT->desugar(); 00427 } 00428 00429 return false; 00430 } 00431 00432 bool NSAPI::isObjCEnumerator(const Expr *E, 00433 StringRef name, IdentifierInfo *&II) const { 00434 if (!Ctx.getLangOpts().ObjC1) 00435 return false; 00436 if (!E) 00437 return false; 00438 00439 if (!II) 00440 II = &Ctx.Idents.get(name); 00441 00442 if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParenImpCasts())) 00443 if (const EnumConstantDecl * 00444 EnumD = dyn_cast_or_null<EnumConstantDecl>(DRE->getDecl())) 00445 return EnumD->getIdentifier() == II; 00446 00447 return false; 00448 } 00449 00450 Selector NSAPI::getOrInitSelector(ArrayRef<StringRef> Ids, 00451 Selector &Sel) const { 00452 if (Sel.isNull()) { 00453 SmallVector<IdentifierInfo *, 4> Idents; 00454 for (ArrayRef<StringRef>::const_iterator 00455 I = Ids.begin(), E = Ids.end(); I != E; ++I) 00456 Idents.push_back(&Ctx.Idents.get(*I)); 00457 Sel = Ctx.Selectors.getSelector(Idents.size(), Idents.data()); 00458 } 00459 return Sel; 00460 }