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