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