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