1 //== RetainSummaryManager.cpp - Summaries for reference counting --*- C++ -*--// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines summaries implementation for retain counting, which 10 // implements a reference count checker for Core Foundation, Cocoa 11 // and OSObject (on Mac OS X). 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/Analysis/DomainSpecific/CocoaConventions.h" 16 #include "clang/Analysis/RetainSummaryManager.h" 17 #include "clang/AST/Attr.h" 18 #include "clang/AST/DeclCXX.h" 19 #include "clang/AST/DeclObjC.h" 20 #include "clang/AST/ParentMap.h" 21 #include "clang/ASTMatchers/ASTMatchFinder.h" 22 23 using namespace clang; 24 using namespace ento; 25 26 template <class T> 27 constexpr static bool isOneOf() { 28 return false; 29 } 30 31 /// Helper function to check whether the class is one of the 32 /// rest of varargs. 33 template <class T, class P, class... ToCompare> 34 constexpr static bool isOneOf() { 35 return std::is_same<T, P>::value || isOneOf<T, ToCompare...>(); 36 } 37 38 namespace { 39 40 /// Fake attribute class for RC* attributes. 41 struct GeneralizedReturnsRetainedAttr { 42 static bool classof(const Attr *A) { 43 if (auto AA = dyn_cast<AnnotateAttr>(A)) 44 return AA->getAnnotation() == "rc_ownership_returns_retained"; 45 return false; 46 } 47 }; 48 49 struct GeneralizedReturnsNotRetainedAttr { 50 static bool classof(const Attr *A) { 51 if (auto AA = dyn_cast<AnnotateAttr>(A)) 52 return AA->getAnnotation() == "rc_ownership_returns_not_retained"; 53 return false; 54 } 55 }; 56 57 struct GeneralizedConsumedAttr { 58 static bool classof(const Attr *A) { 59 if (auto AA = dyn_cast<AnnotateAttr>(A)) 60 return AA->getAnnotation() == "rc_ownership_consumed"; 61 return false; 62 } 63 }; 64 65 } 66 67 template <class T> 68 Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D, 69 QualType QT) { 70 ObjKind K; 71 if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr, 72 CFReturnsNotRetainedAttr>()) { 73 if (!TrackObjCAndCFObjects) 74 return None; 75 76 K = ObjKind::CF; 77 } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr, 78 NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr, 79 NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) { 80 81 if (!TrackObjCAndCFObjects) 82 return None; 83 84 if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr, 85 NSReturnsNotRetainedAttr>() && 86 !cocoa::isCocoaObjectRef(QT)) 87 return None; 88 K = ObjKind::ObjC; 89 } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr, 90 OSReturnsNotRetainedAttr, OSReturnsRetainedAttr, 91 OSReturnsRetainedOnZeroAttr, 92 OSReturnsRetainedOnNonZeroAttr>()) { 93 if (!TrackOSObjects) 94 return None; 95 K = ObjKind::OS; 96 } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr, 97 GeneralizedReturnsRetainedAttr, 98 GeneralizedConsumedAttr>()) { 99 K = ObjKind::Generalized; 100 } else { 101 llvm_unreachable("Unexpected attribute"); 102 } 103 if (D->hasAttr<T>()) 104 return K; 105 return None; 106 } 107 108 template <class T1, class T2, class... Others> 109 Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D, 110 QualType QT) { 111 if (auto Out = hasAnyEnabledAttrOf<T1>(D, QT)) 112 return Out; 113 return hasAnyEnabledAttrOf<T2, Others...>(D, QT); 114 } 115 116 const RetainSummary * 117 RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) { 118 // Unique "simple" summaries -- those without ArgEffects. 119 if (OldSumm.isSimple()) { 120 ::llvm::FoldingSetNodeID ID; 121 OldSumm.Profile(ID); 122 123 void *Pos; 124 CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos); 125 126 if (!N) { 127 N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>(); 128 new (N) CachedSummaryNode(OldSumm); 129 SimpleSummaries.InsertNode(N, Pos); 130 } 131 132 return &N->getValue(); 133 } 134 135 RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>(); 136 new (Summ) RetainSummary(OldSumm); 137 return Summ; 138 } 139 140 static bool isSubclass(const Decl *D, 141 StringRef ClassName) { 142 using namespace ast_matchers; 143 DeclarationMatcher SubclassM = 144 cxxRecordDecl(isSameOrDerivedFrom(std::string(ClassName))); 145 return !(match(SubclassM, *D, D->getASTContext()).empty()); 146 } 147 148 static bool isExactClass(const Decl *D, StringRef ClassName) { 149 using namespace ast_matchers; 150 DeclarationMatcher sameClassM = 151 cxxRecordDecl(hasName(std::string(ClassName))); 152 return !(match(sameClassM, *D, D->getASTContext()).empty()); 153 } 154 155 static bool isOSObjectSubclass(const Decl *D) { 156 return D && isSubclass(D, "OSMetaClassBase") && 157 !isExactClass(D, "OSMetaClass"); 158 } 159 160 static bool isOSObjectDynamicCast(StringRef S) { return S == "safeMetaCast"; } 161 162 static bool isOSObjectRequiredCast(StringRef S) { 163 return S == "requiredMetaCast"; 164 } 165 166 static bool isOSObjectThisCast(StringRef S) { 167 return S == "metaCast"; 168 } 169 170 171 static bool isOSObjectPtr(QualType QT) { 172 return isOSObjectSubclass(QT->getPointeeCXXRecordDecl()); 173 } 174 175 static bool isISLObjectRef(QualType Ty) { 176 return StringRef(Ty.getAsString()).startswith("isl_"); 177 } 178 179 static bool isOSIteratorSubclass(const Decl *D) { 180 return isSubclass(D, "OSIterator"); 181 } 182 183 static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) { 184 for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) { 185 if (Ann->getAnnotation() == rcAnnotation) 186 return true; 187 } 188 return false; 189 } 190 191 static bool isRetain(const FunctionDecl *FD, StringRef FName) { 192 return FName.startswith_lower("retain") || FName.endswith_lower("retain"); 193 } 194 195 static bool isRelease(const FunctionDecl *FD, StringRef FName) { 196 return FName.startswith_lower("release") || FName.endswith_lower("release"); 197 } 198 199 static bool isAutorelease(const FunctionDecl *FD, StringRef FName) { 200 return FName.startswith_lower("autorelease") || 201 FName.endswith_lower("autorelease"); 202 } 203 204 static bool isMakeCollectable(StringRef FName) { 205 return FName.contains_lower("MakeCollectable"); 206 } 207 208 /// A function is OSObject related if it is declared on a subclass 209 /// of OSObject, or any of the parameters is a subclass of an OSObject. 210 static bool isOSObjectRelated(const CXXMethodDecl *MD) { 211 if (isOSObjectSubclass(MD->getParent())) 212 return true; 213 214 for (ParmVarDecl *Param : MD->parameters()) { 215 QualType PT = Param->getType()->getPointeeType(); 216 if (!PT.isNull()) 217 if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl()) 218 if (isOSObjectSubclass(RD)) 219 return true; 220 } 221 222 return false; 223 } 224 225 bool 226 RetainSummaryManager::isKnownSmartPointer(QualType QT) { 227 QT = QT.getCanonicalType(); 228 const auto *RD = QT->getAsCXXRecordDecl(); 229 if (!RD) 230 return false; 231 const IdentifierInfo *II = RD->getIdentifier(); 232 if (II && II->getName() == "smart_ptr") 233 if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext())) 234 if (ND->getNameAsString() == "os") 235 return true; 236 return false; 237 } 238 239 const RetainSummary * 240 RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD, 241 StringRef FName, QualType RetTy) { 242 assert(TrackOSObjects && 243 "Requesting a summary for an OSObject but OSObjects are not tracked"); 244 245 if (RetTy->isPointerType()) { 246 const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl(); 247 if (PD && isOSObjectSubclass(PD)) { 248 if (isOSObjectDynamicCast(FName) || isOSObjectRequiredCast(FName) || 249 isOSObjectThisCast(FName)) 250 return getDefaultSummary(); 251 252 // TODO: Add support for the slightly common *Matching(table) idiom. 253 // Cf. IOService::nameMatching() etc. - these function have an unusual 254 // contract of returning at +0 or +1 depending on their last argument. 255 if (FName.endswith("Matching")) { 256 return getPersistentStopSummary(); 257 } 258 259 // All objects returned with functions *not* starting with 'get', 260 // or iterators, are returned at +1. 261 if ((!FName.startswith("get") && !FName.startswith("Get")) || 262 isOSIteratorSubclass(PD)) { 263 return getOSSummaryCreateRule(FD); 264 } else { 265 return getOSSummaryGetRule(FD); 266 } 267 } 268 } 269 270 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 271 const CXXRecordDecl *Parent = MD->getParent(); 272 if (Parent && isOSObjectSubclass(Parent)) { 273 if (FName == "release" || FName == "taggedRelease") 274 return getOSSummaryReleaseRule(FD); 275 276 if (FName == "retain" || FName == "taggedRetain") 277 return getOSSummaryRetainRule(FD); 278 279 if (FName == "free") 280 return getOSSummaryFreeRule(FD); 281 282 if (MD->getOverloadedOperator() == OO_New) 283 return getOSSummaryCreateRule(MD); 284 } 285 } 286 287 return nullptr; 288 } 289 290 const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject( 291 const FunctionDecl *FD, 292 StringRef FName, 293 QualType RetTy, 294 const FunctionType *FT, 295 bool &AllowAnnotations) { 296 297 ArgEffects ScratchArgs(AF.getEmptyMap()); 298 299 std::string RetTyName = RetTy.getAsString(); 300 if (FName == "pthread_create" || FName == "pthread_setspecific") { 301 // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>. 302 // This will be addressed better with IPA. 303 return getPersistentStopSummary(); 304 } else if(FName == "NSMakeCollectable") { 305 // Handle: id NSMakeCollectable(CFTypeRef) 306 AllowAnnotations = false; 307 return RetTy->isObjCIdType() ? getUnarySummary(FT, DoNothing) 308 : getPersistentStopSummary(); 309 } else if (FName == "CMBufferQueueDequeueAndRetain" || 310 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") { 311 // Part of: <rdar://problem/39390714>. 312 return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), 313 ScratchArgs, 314 ArgEffect(DoNothing), 315 ArgEffect(DoNothing)); 316 } else if (FName == "CFPlugInInstanceCreate") { 317 return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs); 318 } else if (FName == "IORegistryEntrySearchCFProperty" || 319 (RetTyName == "CFMutableDictionaryRef" && 320 (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" || 321 FName == "IOServiceNameMatching" || 322 FName == "IORegistryEntryIDMatching" || 323 FName == "IOOpenFirmwarePathMatching"))) { 324 // Part of <rdar://problem/6961230>. (IOKit) 325 // This should be addressed using a API table. 326 return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs, 327 ArgEffect(DoNothing), ArgEffect(DoNothing)); 328 } else if (FName == "IOServiceGetMatchingService" || 329 FName == "IOServiceGetMatchingServices") { 330 // FIXES: <rdar://problem/6326900> 331 // This should be addressed using a API table. This strcmp is also 332 // a little gross, but there is no need to super optimize here. 333 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF)); 334 return getPersistentSummary(RetEffect::MakeNoRet(), 335 ScratchArgs, 336 ArgEffect(DoNothing), ArgEffect(DoNothing)); 337 } else if (FName == "IOServiceAddNotification" || 338 FName == "IOServiceAddMatchingNotification") { 339 // Part of <rdar://problem/6961230>. (IOKit) 340 // This should be addressed using a API table. 341 ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF)); 342 return getPersistentSummary(RetEffect::MakeNoRet(), 343 ScratchArgs, 344 ArgEffect(DoNothing), ArgEffect(DoNothing)); 345 } else if (FName == "CVPixelBufferCreateWithBytes") { 346 // FIXES: <rdar://problem/7283567> 347 // Eventually this can be improved by recognizing that the pixel 348 // buffer passed to CVPixelBufferCreateWithBytes is released via 349 // a callback and doing full IPA to make sure this is done correctly. 350 // FIXME: This function has an out parameter that returns an 351 // allocated object. 352 ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking)); 353 return getPersistentSummary(RetEffect::MakeNoRet(), 354 ScratchArgs, 355 ArgEffect(DoNothing), ArgEffect(DoNothing)); 356 } else if (FName == "CGBitmapContextCreateWithData") { 357 // FIXES: <rdar://problem/7358899> 358 // Eventually this can be improved by recognizing that 'releaseInfo' 359 // passed to CGBitmapContextCreateWithData is released via 360 // a callback and doing full IPA to make sure this is done correctly. 361 ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking))); 362 return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs, 363 ArgEffect(DoNothing), ArgEffect(DoNothing)); 364 } else if (FName == "CVPixelBufferCreateWithPlanarBytes") { 365 // FIXES: <rdar://problem/7283567> 366 // Eventually this can be improved by recognizing that the pixel 367 // buffer passed to CVPixelBufferCreateWithPlanarBytes is released 368 // via a callback and doing full IPA to make sure this is done 369 // correctly. 370 ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking)); 371 return getPersistentSummary(RetEffect::MakeNoRet(), 372 ScratchArgs, 373 ArgEffect(DoNothing), ArgEffect(DoNothing)); 374 } else if (FName == "VTCompressionSessionEncodeFrame") { 375 // The context argument passed to VTCompressionSessionEncodeFrame() 376 // is passed to the callback specified when creating the session 377 // (e.g. with VTCompressionSessionCreate()) which can release it. 378 // To account for this possibility, conservatively stop tracking 379 // the context. 380 ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking)); 381 return getPersistentSummary(RetEffect::MakeNoRet(), 382 ScratchArgs, 383 ArgEffect(DoNothing), ArgEffect(DoNothing)); 384 } else if (FName == "dispatch_set_context" || 385 FName == "xpc_connection_set_context") { 386 // <rdar://problem/11059275> - The analyzer currently doesn't have 387 // a good way to reason about the finalizer function for libdispatch. 388 // If we pass a context object that is memory managed, stop tracking it. 389 // <rdar://problem/13783514> - Same problem, but for XPC. 390 // FIXME: this hack should possibly go away once we can handle 391 // libdispatch and XPC finalizers. 392 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking)); 393 return getPersistentSummary(RetEffect::MakeNoRet(), 394 ScratchArgs, 395 ArgEffect(DoNothing), ArgEffect(DoNothing)); 396 } else if (FName.startswith("NSLog")) { 397 return getDoNothingSummary(); 398 } else if (FName.startswith("NS") && 399 (FName.find("Insert") != StringRef::npos)) { 400 // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can 401 // be deallocated by NSMapRemove. (radar://11152419) 402 ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking)); 403 ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking)); 404 return getPersistentSummary(RetEffect::MakeNoRet(), 405 ScratchArgs, ArgEffect(DoNothing), 406 ArgEffect(DoNothing)); 407 } 408 409 if (RetTy->isPointerType()) { 410 411 // For CoreFoundation ('CF') types. 412 if (cocoa::isRefType(RetTy, "CF", FName)) { 413 if (isRetain(FD, FName)) { 414 // CFRetain isn't supposed to be annotated. However, this may as 415 // well be a user-made "safe" CFRetain function that is incorrectly 416 // annotated as cf_returns_retained due to lack of better options. 417 // We want to ignore such annotation. 418 AllowAnnotations = false; 419 420 return getUnarySummary(FT, IncRef); 421 } else if (isAutorelease(FD, FName)) { 422 // The headers use cf_consumed, but we can fully model CFAutorelease 423 // ourselves. 424 AllowAnnotations = false; 425 426 return getUnarySummary(FT, Autorelease); 427 } else if (isMakeCollectable(FName)) { 428 AllowAnnotations = false; 429 return getUnarySummary(FT, DoNothing); 430 } else { 431 return getCFCreateGetRuleSummary(FD); 432 } 433 } 434 435 // For CoreGraphics ('CG') and CoreVideo ('CV') types. 436 if (cocoa::isRefType(RetTy, "CG", FName) || 437 cocoa::isRefType(RetTy, "CV", FName)) { 438 if (isRetain(FD, FName)) 439 return getUnarySummary(FT, IncRef); 440 else 441 return getCFCreateGetRuleSummary(FD); 442 } 443 444 // For all other CF-style types, use the Create/Get 445 // rule for summaries but don't support Retain functions 446 // with framework-specific prefixes. 447 if (coreFoundation::isCFObjectRef(RetTy)) { 448 return getCFCreateGetRuleSummary(FD); 449 } 450 451 if (FD->hasAttr<CFAuditedTransferAttr>()) { 452 return getCFCreateGetRuleSummary(FD); 453 } 454 } 455 456 // Check for release functions, the only kind of functions that we care 457 // about that don't return a pointer type. 458 if (FName.startswith("CG") || FName.startswith("CF")) { 459 // Test for 'CGCF'. 460 FName = FName.substr(FName.startswith("CGCF") ? 4 : 2); 461 462 if (isRelease(FD, FName)) 463 return getUnarySummary(FT, DecRef); 464 else { 465 assert(ScratchArgs.isEmpty()); 466 // Remaining CoreFoundation and CoreGraphics functions. 467 // We use to assume that they all strictly followed the ownership idiom 468 // and that ownership cannot be transferred. While this is technically 469 // correct, many methods allow a tracked object to escape. For example: 470 // 471 // CFMutableDictionaryRef x = CFDictionaryCreateMutable(...); 472 // CFDictionaryAddValue(y, key, x); 473 // CFRelease(x); 474 // ... it is okay to use 'x' since 'y' has a reference to it 475 // 476 // We handle this and similar cases with the follow heuristic. If the 477 // function name contains "InsertValue", "SetValue", "AddValue", 478 // "AppendValue", or "SetAttribute", then we assume that arguments may 479 // "escape." This means that something else holds on to the object, 480 // allowing it be used even after its local retain count drops to 0. 481 ArgEffectKind E = 482 (StrInStrNoCase(FName, "InsertValue") != StringRef::npos || 483 StrInStrNoCase(FName, "AddValue") != StringRef::npos || 484 StrInStrNoCase(FName, "SetValue") != StringRef::npos || 485 StrInStrNoCase(FName, "AppendValue") != StringRef::npos || 486 StrInStrNoCase(FName, "SetAttribute") != StringRef::npos) 487 ? MayEscape 488 : DoNothing; 489 490 return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs, 491 ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF)); 492 } 493 } 494 495 return nullptr; 496 } 497 498 const RetainSummary * 499 RetainSummaryManager::generateSummary(const FunctionDecl *FD, 500 bool &AllowAnnotations) { 501 // We generate "stop" summaries for implicitly defined functions. 502 if (FD->isImplicit()) 503 return getPersistentStopSummary(); 504 505 const IdentifierInfo *II = FD->getIdentifier(); 506 507 StringRef FName = II ? II->getName() : ""; 508 509 // Strip away preceding '_'. Doing this here will effect all the checks 510 // down below. 511 FName = FName.substr(FName.find_first_not_of('_')); 512 513 // Inspect the result type. Strip away any typedefs. 514 const auto *FT = FD->getType()->castAs<FunctionType>(); 515 QualType RetTy = FT->getReturnType(); 516 517 if (TrackOSObjects) 518 if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy)) 519 return S; 520 521 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) 522 if (!isOSObjectRelated(MD)) 523 return getPersistentSummary(RetEffect::MakeNoRet(), 524 ArgEffects(AF.getEmptyMap()), 525 ArgEffect(DoNothing), 526 ArgEffect(StopTracking), 527 ArgEffect(DoNothing)); 528 529 if (TrackObjCAndCFObjects) 530 if (const RetainSummary *S = 531 getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations)) 532 return S; 533 534 return getDefaultSummary(); 535 } 536 537 const RetainSummary * 538 RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) { 539 // If we don't know what function we're calling, use our default summary. 540 if (!FD) 541 return getDefaultSummary(); 542 543 // Look up a summary in our cache of FunctionDecls -> Summaries. 544 FuncSummariesTy::iterator I = FuncSummaries.find(FD); 545 if (I != FuncSummaries.end()) 546 return I->second; 547 548 // No summary? Generate one. 549 bool AllowAnnotations = true; 550 const RetainSummary *S = generateSummary(FD, AllowAnnotations); 551 552 // Annotations override defaults. 553 if (AllowAnnotations) 554 updateSummaryFromAnnotations(S, FD); 555 556 FuncSummaries[FD] = S; 557 return S; 558 } 559 560 //===----------------------------------------------------------------------===// 561 // Summary creation for functions (largely uses of Core Foundation). 562 //===----------------------------------------------------------------------===// 563 564 static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) { 565 switch (E.getKind()) { 566 case DoNothing: 567 case Autorelease: 568 case DecRefBridgedTransferred: 569 case IncRef: 570 case UnretainedOutParameter: 571 case RetainedOutParameter: 572 case RetainedOutParameterOnZero: 573 case RetainedOutParameterOnNonZero: 574 case MayEscape: 575 case StopTracking: 576 case StopTrackingHard: 577 return E.withKind(StopTrackingHard); 578 case DecRef: 579 case DecRefAndStopTrackingHard: 580 return E.withKind(DecRefAndStopTrackingHard); 581 case Dealloc: 582 return E.withKind(Dealloc); 583 } 584 585 llvm_unreachable("Unknown ArgEffect kind"); 586 } 587 588 const RetainSummary * 589 RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S, 590 AnyCall &C) { 591 ArgEffect RecEffect = getStopTrackingHardEquivalent(S->getReceiverEffect()); 592 ArgEffect DefEffect = getStopTrackingHardEquivalent(S->getDefaultArgEffect()); 593 594 ArgEffects ScratchArgs(AF.getEmptyMap()); 595 ArgEffects CustomArgEffects = S->getArgEffects(); 596 for (ArgEffects::iterator I = CustomArgEffects.begin(), 597 E = CustomArgEffects.end(); 598 I != E; ++I) { 599 ArgEffect Translated = getStopTrackingHardEquivalent(I->second); 600 if (Translated.getKind() != DefEffect.getKind()) 601 ScratchArgs = AF.add(ScratchArgs, I->first, Translated); 602 } 603 604 RetEffect RE = RetEffect::MakeNoRetHard(); 605 606 // Special cases where the callback argument CANNOT free the return value. 607 // This can generally only happen if we know that the callback will only be 608 // called when the return value is already being deallocated. 609 if (const IdentifierInfo *Name = C.getIdentifier()) { 610 // When the CGBitmapContext is deallocated, the callback here will free 611 // the associated data buffer. 612 // The callback in dispatch_data_create frees the buffer, but not 613 // the data object. 614 if (Name->isStr("CGBitmapContextCreateWithData") || 615 Name->isStr("dispatch_data_create")) 616 RE = S->getRetEffect(); 617 } 618 619 return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect); 620 } 621 622 void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf( 623 const RetainSummary *&S) { 624 625 RetainSummaryTemplate Template(S, *this); 626 627 Template->setReceiverEffect(ArgEffect(DoNothing)); 628 Template->setRetEffect(RetEffect::MakeNoRet()); 629 } 630 631 632 void RetainSummaryManager::updateSummaryForArgumentTypes( 633 const AnyCall &C, const RetainSummary *&RS) { 634 RetainSummaryTemplate Template(RS, *this); 635 636 unsigned parm_idx = 0; 637 for (auto pi = C.param_begin(), pe = C.param_end(); pi != pe; 638 ++pi, ++parm_idx) { 639 QualType QT = (*pi)->getType(); 640 641 // Skip already created values. 642 if (RS->getArgEffects().contains(parm_idx)) 643 continue; 644 645 ObjKind K = ObjKind::AnyObj; 646 647 if (isISLObjectRef(QT)) { 648 K = ObjKind::Generalized; 649 } else if (isOSObjectPtr(QT)) { 650 K = ObjKind::OS; 651 } else if (cocoa::isCocoaObjectRef(QT)) { 652 K = ObjKind::ObjC; 653 } else if (coreFoundation::isCFObjectRef(QT)) { 654 K = ObjKind::CF; 655 } 656 657 if (K != ObjKind::AnyObj) 658 Template->addArg(AF, parm_idx, 659 ArgEffect(RS->getDefaultArgEffect().getKind(), K)); 660 } 661 } 662 663 const RetainSummary * 664 RetainSummaryManager::getSummary(AnyCall C, 665 bool HasNonZeroCallbackArg, 666 bool IsReceiverUnconsumedSelf, 667 QualType ReceiverType) { 668 const RetainSummary *Summ; 669 switch (C.getKind()) { 670 case AnyCall::Function: 671 case AnyCall::Constructor: 672 case AnyCall::InheritedConstructor: 673 case AnyCall::Allocator: 674 case AnyCall::Deallocator: 675 Summ = getFunctionSummary(cast_or_null<FunctionDecl>(C.getDecl())); 676 break; 677 case AnyCall::Block: 678 case AnyCall::Destructor: 679 // FIXME: These calls are currently unsupported. 680 return getPersistentStopSummary(); 681 case AnyCall::ObjCMethod: { 682 const auto *ME = cast_or_null<ObjCMessageExpr>(C.getExpr()); 683 if (!ME) { 684 Summ = getMethodSummary(cast<ObjCMethodDecl>(C.getDecl())); 685 } else if (ME->isInstanceMessage()) { 686 Summ = getInstanceMethodSummary(ME, ReceiverType); 687 } else { 688 Summ = getClassMethodSummary(ME); 689 } 690 break; 691 } 692 } 693 694 if (HasNonZeroCallbackArg) 695 Summ = updateSummaryForNonZeroCallbackArg(Summ, C); 696 697 if (IsReceiverUnconsumedSelf) 698 updateSummaryForReceiverUnconsumedSelf(Summ); 699 700 updateSummaryForArgumentTypes(C, Summ); 701 702 assert(Summ && "Unknown call type?"); 703 return Summ; 704 } 705 706 707 const RetainSummary * 708 RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) { 709 if (coreFoundation::followsCreateRule(FD)) 710 return getCFSummaryCreateRule(FD); 711 712 return getCFSummaryGetRule(FD); 713 } 714 715 bool RetainSummaryManager::isTrustedReferenceCountImplementation( 716 const Decl *FD) { 717 return hasRCAnnotation(FD, "rc_ownership_trusted_implementation"); 718 } 719 720 Optional<RetainSummaryManager::BehaviorSummary> 721 RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD, 722 bool &hasTrustedImplementationAnnotation) { 723 724 IdentifierInfo *II = FD->getIdentifier(); 725 if (!II) 726 return None; 727 728 StringRef FName = II->getName(); 729 FName = FName.substr(FName.find_first_not_of('_')); 730 731 QualType ResultTy = CE->getCallReturnType(Ctx); 732 if (ResultTy->isObjCIdType()) { 733 if (II->isStr("NSMakeCollectable")) 734 return BehaviorSummary::Identity; 735 } else if (ResultTy->isPointerType()) { 736 // Handle: (CF|CG|CV)Retain 737 // CFAutorelease 738 // It's okay to be a little sloppy here. 739 if (FName == "CMBufferQueueDequeueAndRetain" || 740 FName == "CMBufferQueueDequeueIfDataReadyAndRetain") { 741 // Part of: <rdar://problem/39390714>. 742 // These are not retain. They just return something and retain it. 743 return None; 744 } 745 if (CE->getNumArgs() == 1 && 746 (cocoa::isRefType(ResultTy, "CF", FName) || 747 cocoa::isRefType(ResultTy, "CG", FName) || 748 cocoa::isRefType(ResultTy, "CV", FName)) && 749 (isRetain(FD, FName) || isAutorelease(FD, FName) || 750 isMakeCollectable(FName))) 751 return BehaviorSummary::Identity; 752 753 // safeMetaCast is called by OSDynamicCast. 754 // We assume that OSDynamicCast is either an identity (cast is OK, 755 // the input was non-zero), 756 // or that it returns zero (when the cast failed, or the input 757 // was zero). 758 if (TrackOSObjects) { 759 if (isOSObjectDynamicCast(FName) && FD->param_size() >= 1) { 760 return BehaviorSummary::IdentityOrZero; 761 } else if (isOSObjectRequiredCast(FName) && FD->param_size() >= 1) { 762 return BehaviorSummary::Identity; 763 } else if (isOSObjectThisCast(FName) && isa<CXXMethodDecl>(FD) && 764 !cast<CXXMethodDecl>(FD)->isStatic()) { 765 return BehaviorSummary::IdentityThis; 766 } 767 } 768 769 const FunctionDecl* FDD = FD->getDefinition(); 770 if (FDD && isTrustedReferenceCountImplementation(FDD)) { 771 hasTrustedImplementationAnnotation = true; 772 return BehaviorSummary::Identity; 773 } 774 } 775 776 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 777 const CXXRecordDecl *Parent = MD->getParent(); 778 if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) 779 if (FName == "release" || FName == "retain") 780 return BehaviorSummary::NoOp; 781 } 782 783 return None; 784 } 785 786 const RetainSummary * 787 RetainSummaryManager::getUnarySummary(const FunctionType* FT, 788 ArgEffectKind AE) { 789 790 // Unary functions have no arg effects by definition. 791 ArgEffects ScratchArgs(AF.getEmptyMap()); 792 793 // Sanity check that this is *really* a unary function. This can 794 // happen if people do weird things. 795 const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT); 796 if (!FTP || FTP->getNumParams() != 1) 797 return getPersistentStopSummary(); 798 799 ArgEffect Effect(AE, ObjKind::CF); 800 801 ScratchArgs = AF.add(ScratchArgs, 0, Effect); 802 return getPersistentSummary(RetEffect::MakeNoRet(), 803 ScratchArgs, 804 ArgEffect(DoNothing), ArgEffect(DoNothing)); 805 } 806 807 const RetainSummary * 808 RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) { 809 return getPersistentSummary(RetEffect::MakeNoRet(), 810 AF.getEmptyMap(), 811 /*ReceiverEff=*/ArgEffect(DoNothing), 812 /*DefaultEff=*/ArgEffect(DoNothing), 813 /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS)); 814 } 815 816 const RetainSummary * 817 RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) { 818 return getPersistentSummary(RetEffect::MakeNoRet(), 819 AF.getEmptyMap(), 820 /*ReceiverEff=*/ArgEffect(DoNothing), 821 /*DefaultEff=*/ArgEffect(DoNothing), 822 /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS)); 823 } 824 825 const RetainSummary * 826 RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) { 827 return getPersistentSummary(RetEffect::MakeNoRet(), 828 AF.getEmptyMap(), 829 /*ReceiverEff=*/ArgEffect(DoNothing), 830 /*DefaultEff=*/ArgEffect(DoNothing), 831 /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS)); 832 } 833 834 const RetainSummary * 835 RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) { 836 return getPersistentSummary(RetEffect::MakeOwned(ObjKind::OS), 837 AF.getEmptyMap()); 838 } 839 840 const RetainSummary * 841 RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) { 842 return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::OS), 843 AF.getEmptyMap()); 844 } 845 846 const RetainSummary * 847 RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) { 848 return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), 849 ArgEffects(AF.getEmptyMap())); 850 } 851 852 const RetainSummary * 853 RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) { 854 return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF), 855 ArgEffects(AF.getEmptyMap()), 856 ArgEffect(DoNothing), ArgEffect(DoNothing)); 857 } 858 859 860 861 862 //===----------------------------------------------------------------------===// 863 // Summary creation for Selectors. 864 //===----------------------------------------------------------------------===// 865 866 Optional<RetEffect> 867 RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy, 868 const Decl *D) { 869 if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy)) 870 return ObjCAllocRetE; 871 872 if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr, 873 GeneralizedReturnsRetainedAttr>(D, RetTy)) 874 return RetEffect::MakeOwned(*K); 875 876 if (auto K = hasAnyEnabledAttrOf< 877 CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr, 878 GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr, 879 NSReturnsAutoreleasedAttr>(D, RetTy)) 880 return RetEffect::MakeNotOwned(*K); 881 882 if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) 883 for (const auto *PD : MD->overridden_methods()) 884 if (auto RE = getRetEffectFromAnnotations(RetTy, PD)) 885 return RE; 886 887 return None; 888 } 889 890 /// \return Whether the chain of typedefs starting from @c QT 891 /// has a typedef with a given name @c Name. 892 static bool hasTypedefNamed(QualType QT, 893 StringRef Name) { 894 while (auto *T = dyn_cast<TypedefType>(QT)) { 895 const auto &Context = T->getDecl()->getASTContext(); 896 if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name)) 897 return true; 898 QT = T->getDecl()->getUnderlyingType(); 899 } 900 return false; 901 } 902 903 static QualType getCallableReturnType(const NamedDecl *ND) { 904 if (const auto *FD = dyn_cast<FunctionDecl>(ND)) { 905 return FD->getReturnType(); 906 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) { 907 return MD->getReturnType(); 908 } else { 909 llvm_unreachable("Unexpected decl"); 910 } 911 } 912 913 bool RetainSummaryManager::applyParamAnnotationEffect( 914 const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD, 915 RetainSummaryTemplate &Template) { 916 QualType QT = pd->getType(); 917 if (auto K = 918 hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr, 919 GeneralizedConsumedAttr>(pd, QT)) { 920 Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K)); 921 return true; 922 } else if (auto K = hasAnyEnabledAttrOf< 923 CFReturnsRetainedAttr, OSReturnsRetainedAttr, 924 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr, 925 GeneralizedReturnsRetainedAttr>(pd, QT)) { 926 927 // For OSObjects, we try to guess whether the object is created based 928 // on the return value. 929 if (K == ObjKind::OS) { 930 QualType QT = getCallableReturnType(FD); 931 932 bool HasRetainedOnZero = pd->hasAttr<OSReturnsRetainedOnZeroAttr>(); 933 bool HasRetainedOnNonZero = pd->hasAttr<OSReturnsRetainedOnNonZeroAttr>(); 934 935 // The usual convention is to create an object on non-zero return, but 936 // it's reverted if the typedef chain has a typedef kern_return_t, 937 // because kReturnSuccess constant is defined as zero. 938 // The convention can be overwritten by custom attributes. 939 bool SuccessOnZero = 940 HasRetainedOnZero || 941 (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero); 942 bool ShouldSplit = !QT.isNull() && !QT->isVoidType(); 943 ArgEffectKind AK = RetainedOutParameter; 944 if (ShouldSplit && SuccessOnZero) { 945 AK = RetainedOutParameterOnZero; 946 } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) { 947 AK = RetainedOutParameterOnNonZero; 948 } 949 Template->addArg(AF, parm_idx, ArgEffect(AK, ObjKind::OS)); 950 } 951 952 // For others: 953 // Do nothing. Retained out parameters will either point to a +1 reference 954 // or NULL, but the way you check for failure differs depending on the 955 // API. Consequently, we don't have a good way to track them yet. 956 return true; 957 } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr, 958 OSReturnsNotRetainedAttr, 959 GeneralizedReturnsNotRetainedAttr>( 960 pd, QT)) { 961 Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter, *K)); 962 return true; 963 } 964 965 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 966 for (const auto *OD : MD->overridden_methods()) { 967 const ParmVarDecl *OP = OD->parameters()[parm_idx]; 968 if (applyParamAnnotationEffect(OP, parm_idx, OD, Template)) 969 return true; 970 } 971 } 972 973 return false; 974 } 975 976 void 977 RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, 978 const FunctionDecl *FD) { 979 if (!FD) 980 return; 981 982 assert(Summ && "Must have a summary to add annotations to."); 983 RetainSummaryTemplate Template(Summ, *this); 984 985 // Effects on the parameters. 986 unsigned parm_idx = 0; 987 for (auto pi = FD->param_begin(), 988 pe = FD->param_end(); pi != pe; ++pi, ++parm_idx) 989 applyParamAnnotationEffect(*pi, parm_idx, FD, Template); 990 991 QualType RetTy = FD->getReturnType(); 992 if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD)) 993 Template->setRetEffect(*RetE); 994 995 if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy)) 996 Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS)); 997 } 998 999 void 1000 RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ, 1001 const ObjCMethodDecl *MD) { 1002 if (!MD) 1003 return; 1004 1005 assert(Summ && "Must have a valid summary to add annotations to"); 1006 RetainSummaryTemplate Template(Summ, *this); 1007 1008 // Effects on the receiver. 1009 if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->getReturnType())) 1010 Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC)); 1011 1012 // Effects on the parameters. 1013 unsigned parm_idx = 0; 1014 for (auto pi = MD->param_begin(), pe = MD->param_end(); pi != pe; 1015 ++pi, ++parm_idx) 1016 applyParamAnnotationEffect(*pi, parm_idx, MD, Template); 1017 1018 QualType RetTy = MD->getReturnType(); 1019 if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD)) 1020 Template->setRetEffect(*RetE); 1021 } 1022 1023 const RetainSummary * 1024 RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD, 1025 Selector S, QualType RetTy) { 1026 // Any special effects? 1027 ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC); 1028 RetEffect ResultEff = RetEffect::MakeNoRet(); 1029 1030 // Check the method family, and apply any default annotations. 1031 switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) { 1032 case OMF_None: 1033 case OMF_initialize: 1034 case OMF_performSelector: 1035 // Assume all Objective-C methods follow Cocoa Memory Management rules. 1036 // FIXME: Does the non-threaded performSelector family really belong here? 1037 // The selector could be, say, @selector(copy). 1038 if (cocoa::isCocoaObjectRef(RetTy)) 1039 ResultEff = RetEffect::MakeNotOwned(ObjKind::ObjC); 1040 else if (coreFoundation::isCFObjectRef(RetTy)) { 1041 // ObjCMethodDecl currently doesn't consider CF objects as valid return 1042 // values for alloc, new, copy, or mutableCopy, so we have to 1043 // double-check with the selector. This is ugly, but there aren't that 1044 // many Objective-C methods that return CF objects, right? 1045 if (MD) { 1046 switch (S.getMethodFamily()) { 1047 case OMF_alloc: 1048 case OMF_new: 1049 case OMF_copy: 1050 case OMF_mutableCopy: 1051 ResultEff = RetEffect::MakeOwned(ObjKind::CF); 1052 break; 1053 default: 1054 ResultEff = RetEffect::MakeNotOwned(ObjKind::CF); 1055 break; 1056 } 1057 } else { 1058 ResultEff = RetEffect::MakeNotOwned(ObjKind::CF); 1059 } 1060 } 1061 break; 1062 case OMF_init: 1063 ResultEff = ObjCInitRetE; 1064 ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC); 1065 break; 1066 case OMF_alloc: 1067 case OMF_new: 1068 case OMF_copy: 1069 case OMF_mutableCopy: 1070 if (cocoa::isCocoaObjectRef(RetTy)) 1071 ResultEff = ObjCAllocRetE; 1072 else if (coreFoundation::isCFObjectRef(RetTy)) 1073 ResultEff = RetEffect::MakeOwned(ObjKind::CF); 1074 break; 1075 case OMF_autorelease: 1076 ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC); 1077 break; 1078 case OMF_retain: 1079 ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC); 1080 break; 1081 case OMF_release: 1082 ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC); 1083 break; 1084 case OMF_dealloc: 1085 ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC); 1086 break; 1087 case OMF_self: 1088 // -self is handled specially by the ExprEngine to propagate the receiver. 1089 break; 1090 case OMF_retainCount: 1091 case OMF_finalize: 1092 // These methods don't return objects. 1093 break; 1094 } 1095 1096 // If one of the arguments in the selector has the keyword 'delegate' we 1097 // should stop tracking the reference count for the receiver. This is 1098 // because the reference count is quite possibly handled by a delegate 1099 // method. 1100 if (S.isKeywordSelector()) { 1101 for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) { 1102 StringRef Slot = S.getNameForSlot(i); 1103 if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) { 1104 if (ResultEff == ObjCInitRetE) 1105 ResultEff = RetEffect::MakeNoRetHard(); 1106 else 1107 ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC); 1108 } 1109 } 1110 } 1111 1112 if (ReceiverEff.getKind() == DoNothing && 1113 ResultEff.getKind() == RetEffect::NoRet) 1114 return getDefaultSummary(); 1115 1116 return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()), 1117 ArgEffect(ReceiverEff), ArgEffect(MayEscape)); 1118 } 1119 1120 const RetainSummary * 1121 RetainSummaryManager::getClassMethodSummary(const ObjCMessageExpr *ME) { 1122 assert(!ME->isInstanceMessage()); 1123 const ObjCInterfaceDecl *Class = ME->getReceiverInterface(); 1124 1125 return getMethodSummary(ME->getSelector(), Class, ME->getMethodDecl(), 1126 ME->getType(), ObjCClassMethodSummaries); 1127 } 1128 1129 const RetainSummary *RetainSummaryManager::getInstanceMethodSummary( 1130 const ObjCMessageExpr *ME, 1131 QualType ReceiverType) { 1132 const ObjCInterfaceDecl *ReceiverClass = nullptr; 1133 1134 // We do better tracking of the type of the object than the core ExprEngine. 1135 // See if we have its type in our private state. 1136 if (!ReceiverType.isNull()) 1137 if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>()) 1138 ReceiverClass = PT->getInterfaceDecl(); 1139 1140 // If we don't know what kind of object this is, fall back to its static type. 1141 if (!ReceiverClass) 1142 ReceiverClass = ME->getReceiverInterface(); 1143 1144 // FIXME: The receiver could be a reference to a class, meaning that 1145 // we should use the class method. 1146 // id x = [NSObject class]; 1147 // [x performSelector:... withObject:... afterDelay:...]; 1148 Selector S = ME->getSelector(); 1149 const ObjCMethodDecl *Method = ME->getMethodDecl(); 1150 if (!Method && ReceiverClass) 1151 Method = ReceiverClass->getInstanceMethod(S); 1152 1153 return getMethodSummary(S, ReceiverClass, Method, ME->getType(), 1154 ObjCMethodSummaries); 1155 } 1156 1157 const RetainSummary * 1158 RetainSummaryManager::getMethodSummary(Selector S, 1159 const ObjCInterfaceDecl *ID, 1160 const ObjCMethodDecl *MD, QualType RetTy, 1161 ObjCMethodSummariesTy &CachedSummaries) { 1162 1163 // Objective-C method summaries are only applicable to ObjC and CF objects. 1164 if (!TrackObjCAndCFObjects) 1165 return getDefaultSummary(); 1166 1167 // Look up a summary in our summary cache. 1168 const RetainSummary *Summ = CachedSummaries.find(ID, S); 1169 1170 if (!Summ) { 1171 Summ = getStandardMethodSummary(MD, S, RetTy); 1172 1173 // Annotations override defaults. 1174 updateSummaryFromAnnotations(Summ, MD); 1175 1176 // Memoize the summary. 1177 CachedSummaries[ObjCSummaryKey(ID, S)] = Summ; 1178 } 1179 1180 return Summ; 1181 } 1182 1183 void RetainSummaryManager::InitializeClassMethodSummaries() { 1184 ArgEffects ScratchArgs = AF.getEmptyMap(); 1185 1186 // Create the [NSAssertionHandler currentHander] summary. 1187 addClassMethSummary("NSAssertionHandler", "currentHandler", 1188 getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::ObjC), 1189 ScratchArgs)); 1190 1191 // Create the [NSAutoreleasePool addObject:] summary. 1192 ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease)); 1193 addClassMethSummary("NSAutoreleasePool", "addObject", 1194 getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs, 1195 ArgEffect(DoNothing), 1196 ArgEffect(Autorelease))); 1197 } 1198 1199 void RetainSummaryManager::InitializeMethodSummaries() { 1200 1201 ArgEffects ScratchArgs = AF.getEmptyMap(); 1202 // Create the "init" selector. It just acts as a pass-through for the 1203 // receiver. 1204 const RetainSummary *InitSumm = getPersistentSummary( 1205 ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC)); 1206 addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm); 1207 1208 // awakeAfterUsingCoder: behaves basically like an 'init' method. It 1209 // claims the receiver and returns a retained object. 1210 addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx), 1211 InitSumm); 1212 1213 // The next methods are allocators. 1214 const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE, 1215 ScratchArgs); 1216 const RetainSummary *CFAllocSumm = 1217 getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs); 1218 1219 // Create the "retain" selector. 1220 RetEffect NoRet = RetEffect::MakeNoRet(); 1221 const RetainSummary *Summ = getPersistentSummary( 1222 NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC)); 1223 addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ); 1224 1225 // Create the "release" selector. 1226 Summ = getPersistentSummary(NoRet, ScratchArgs, 1227 ArgEffect(DecRef, ObjKind::ObjC)); 1228 addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ); 1229 1230 // Create the -dealloc summary. 1231 Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc, 1232 ObjKind::ObjC)); 1233 addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ); 1234 1235 // Create the "autorelease" selector. 1236 Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease, 1237 ObjKind::ObjC)); 1238 addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ); 1239 1240 // For NSWindow, allocated objects are (initially) self-owned. 1241 // FIXME: For now we opt for false negatives with NSWindow, as these objects 1242 // self-own themselves. However, they only do this once they are displayed. 1243 // Thus, we need to track an NSWindow's display status. 1244 // This is tracked in <rdar://problem/6062711>. 1245 // See also http://llvm.org/bugs/show_bug.cgi?id=3714. 1246 const RetainSummary *NoTrackYet = 1247 getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs, 1248 ArgEffect(StopTracking), ArgEffect(StopTracking)); 1249 1250 addClassMethSummary("NSWindow", "alloc", NoTrackYet); 1251 1252 // For NSPanel (which subclasses NSWindow), allocated objects are not 1253 // self-owned. 1254 // FIXME: For now we don't track NSPanels. object for the same reason 1255 // as for NSWindow objects. 1256 addClassMethSummary("NSPanel", "alloc", NoTrackYet); 1257 1258 // For NSNull, objects returned by +null are singletons that ignore 1259 // retain/release semantics. Just don't track them. 1260 // <rdar://problem/12858915> 1261 addClassMethSummary("NSNull", "null", NoTrackYet); 1262 1263 // Don't track allocated autorelease pools, as it is okay to prematurely 1264 // exit a method. 1265 addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet); 1266 addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false); 1267 addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet); 1268 1269 // Create summaries QCRenderer/QCView -createSnapShotImageOfType: 1270 addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType"); 1271 addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType"); 1272 1273 // Create summaries for CIContext, 'createCGImage' and 1274 // 'createCGLayerWithSize'. These objects are CF objects, and are not 1275 // automatically garbage collected. 1276 addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect"); 1277 addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect", 1278 "format", "colorSpace"); 1279 addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info"); 1280 } 1281 1282 const RetainSummary * 1283 RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) { 1284 const ObjCInterfaceDecl *ID = MD->getClassInterface(); 1285 Selector S = MD->getSelector(); 1286 QualType ResultTy = MD->getReturnType(); 1287 1288 ObjCMethodSummariesTy *CachedSummaries; 1289 if (MD->isInstanceMethod()) 1290 CachedSummaries = &ObjCMethodSummaries; 1291 else 1292 CachedSummaries = &ObjCClassMethodSummaries; 1293 1294 return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries); 1295 } 1296