1 //=== RetainSummaryManager.h - 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 and Cocoa 11 // on (Mac OS X). 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H 16 #define LLVM_CLANG_ANALYSIS_RETAINSUMMARYMANAGER_H 17 18 #include "llvm/ADT/DenseMap.h" 19 #include "llvm/ADT/FoldingSet.h" 20 #include "llvm/ADT/ImmutableMap.h" 21 #include "clang/AST/Attr.h" 22 #include "clang/AST/DeclCXX.h" 23 #include "clang/AST/DeclObjC.h" 24 #include "clang/AST/ParentMap.h" 25 #include "clang/Analysis/AnyCall.h" 26 #include "clang/Analysis/SelectorExtras.h" 27 #include "llvm/ADT/STLExtras.h" 28 29 using namespace clang; 30 31 namespace clang { 32 namespace ento { 33 34 /// Determines the object kind of a tracked object. 35 enum class ObjKind { 36 /// Indicates that the tracked object is a CF object. 37 CF, 38 39 /// Indicates that the tracked object is an Objective-C object. 40 ObjC, 41 42 /// Indicates that the tracked object could be a CF or Objective-C object. 43 AnyObj, 44 45 /// Indicates that the tracked object is a generalized object. 46 Generalized, 47 48 /// Indicates that the tracking object is a descendant of a 49 /// referenced-counted OSObject, used in the Darwin kernel. 50 OS 51 }; 52 53 enum ArgEffectKind { 54 /// There is no effect. 55 DoNothing, 56 57 /// The argument is treated as if an -autorelease message had been sent to 58 /// the referenced object. 59 Autorelease, 60 61 /// The argument is treated as if the referenced object was deallocated. 62 Dealloc, 63 64 /// The argument has its reference count decreased by 1. 65 DecRef, 66 67 /// The argument has its reference count decreased by 1 to model 68 /// a transferred bridge cast under ARC. 69 DecRefBridgedTransferred, 70 71 /// The argument has its reference count increased by 1. 72 IncRef, 73 74 /// The argument is a pointer to a retain-counted object; on exit, the new 75 /// value of the pointer is a +0 value. 76 UnretainedOutParameter, 77 78 /// The argument is a pointer to a retain-counted object; on exit, the new 79 /// value of the pointer is a +1 value. 80 RetainedOutParameter, 81 82 /// The argument is a pointer to a retain-counted object; on exit, the new 83 /// value of the pointer is a +1 value iff the return code is zero. 84 RetainedOutParameterOnZero, 85 86 /// The argument is a pointer to a retain-counted object; on exit, the new 87 /// value of the pointer is a +1 value iff the return code is non-zero. 88 RetainedOutParameterOnNonZero, 89 90 /// The argument is treated as potentially escaping, meaning that 91 /// even when its reference count hits 0 it should be treated as still 92 /// possibly being alive as someone else *may* be holding onto the object. 93 MayEscape, 94 95 /// All typestate tracking of the object ceases. This is usually employed 96 /// when the effect of the call is completely unknown. 97 StopTracking, 98 99 /// All typestate tracking of the object ceases. Unlike StopTracking, 100 /// this is also enforced when the method body is inlined. 101 /// 102 /// In some cases, we obtain a better summary for this checker 103 /// by looking at the call site than by inlining the function. 104 /// Signifies that we should stop tracking the symbol even if 105 /// the function is inlined. 106 StopTrackingHard, 107 108 /// Performs the combined functionality of DecRef and StopTrackingHard. 109 /// 110 /// The models the effect that the called function decrements the reference 111 /// count of the argument and all typestate tracking on that argument 112 /// should cease. 113 DecRefAndStopTrackingHard, 114 }; 115 116 /// An ArgEffect summarizes the retain count behavior on an argument or receiver 117 /// to a function or method. 118 class ArgEffect { 119 ArgEffectKind K; 120 ObjKind O; 121 public: 122 explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj) 123 : K(K), O(O) {} 124 125 ArgEffectKind getKind() const { return K; } 126 ObjKind getObjKind() const { return O; } 127 128 ArgEffect withKind(ArgEffectKind NewK) { 129 return ArgEffect(NewK, O); 130 } 131 132 bool operator==(const ArgEffect &Other) const { 133 return K == Other.K && O == Other.O; 134 } 135 }; 136 137 /// RetEffect summarizes a call's retain/release behavior with respect 138 /// to its return value. 139 class RetEffect { 140 public: 141 enum Kind { 142 /// Indicates that no retain count information is tracked for 143 /// the return value. 144 NoRet, 145 146 /// Indicates that the returned value is an owned (+1) symbol. 147 OwnedSymbol, 148 149 /// Indicates that the returned value is an object with retain count 150 /// semantics but that it is not owned (+0). This is the default 151 /// for getters, etc. 152 NotOwnedSymbol, 153 154 /// Indicates that the return value is an owned object when the 155 /// receiver is also a tracked object. 156 OwnedWhenTrackedReceiver, 157 158 // Treat this function as returning a non-tracked symbol even if 159 // the function has been inlined. This is used where the call 160 // site summary is more precise than the summary indirectly produced 161 // by inlining the function 162 NoRetHard 163 }; 164 165 private: 166 Kind K; 167 ObjKind O; 168 169 RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {} 170 171 public: 172 Kind getKind() const { return K; } 173 174 ObjKind getObjKind() const { return O; } 175 176 bool isOwned() const { 177 return K == OwnedSymbol || K == OwnedWhenTrackedReceiver; 178 } 179 180 bool notOwned() const { 181 return K == NotOwnedSymbol; 182 } 183 184 bool operator==(const RetEffect &Other) const { 185 return K == Other.K && O == Other.O; 186 } 187 188 static RetEffect MakeOwnedWhenTrackedReceiver() { 189 return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC); 190 } 191 192 static RetEffect MakeOwned(ObjKind o) { 193 return RetEffect(OwnedSymbol, o); 194 } 195 static RetEffect MakeNotOwned(ObjKind o) { 196 return RetEffect(NotOwnedSymbol, o); 197 } 198 static RetEffect MakeNoRet() { 199 return RetEffect(NoRet); 200 } 201 static RetEffect MakeNoRetHard() { 202 return RetEffect(NoRetHard); 203 } 204 }; 205 206 /// A key identifying a summary. 207 class ObjCSummaryKey { 208 IdentifierInfo* II; 209 Selector S; 210 public: 211 ObjCSummaryKey(IdentifierInfo* ii, Selector s) 212 : II(ii), S(s) {} 213 214 ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s) 215 : II(d ? d->getIdentifier() : nullptr), S(s) {} 216 217 ObjCSummaryKey(Selector s) 218 : II(nullptr), S(s) {} 219 220 IdentifierInfo *getIdentifier() const { return II; } 221 Selector getSelector() const { return S; } 222 }; 223 224 } // end namespace ento 225 } // end namespace clang 226 227 using namespace ento; 228 229 namespace llvm { 230 231 //===----------------------------------------------------------------------===// 232 // Adapters for FoldingSet. 233 //===----------------------------------------------------------------------===// 234 template <> struct FoldingSetTrait<ArgEffect> { 235 static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) { 236 ID.AddInteger((unsigned) X.getKind()); 237 ID.AddInteger((unsigned) X.getObjKind()); 238 } 239 }; 240 template <> struct FoldingSetTrait<RetEffect> { 241 static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) { 242 ID.AddInteger((unsigned) X.getKind()); 243 ID.AddInteger((unsigned) X.getObjKind()); 244 } 245 }; 246 247 template <> struct DenseMapInfo<ObjCSummaryKey> { 248 static inline ObjCSummaryKey getEmptyKey() { 249 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(), 250 DenseMapInfo<Selector>::getEmptyKey()); 251 } 252 253 static inline ObjCSummaryKey getTombstoneKey() { 254 return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(), 255 DenseMapInfo<Selector>::getTombstoneKey()); 256 } 257 258 static unsigned getHashValue(const ObjCSummaryKey &V) { 259 typedef std::pair<IdentifierInfo*, Selector> PairTy; 260 return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(), 261 V.getSelector())); 262 } 263 264 static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) { 265 return LHS.getIdentifier() == RHS.getIdentifier() && 266 LHS.getSelector() == RHS.getSelector(); 267 } 268 269 }; 270 271 } // end llvm namespace 272 273 274 namespace clang { 275 namespace ento { 276 277 /// ArgEffects summarizes the effects of a function/method call on all of 278 /// its arguments. 279 typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects; 280 281 /// Summary for a function with respect to ownership changes. 282 class RetainSummary { 283 /// Args - a map of (index, ArgEffect) pairs, where index 284 /// specifies the argument (starting from 0). This can be sparsely 285 /// populated; arguments with no entry in Args use 'DefaultArgEffect'. 286 ArgEffects Args; 287 288 /// DefaultArgEffect - The default ArgEffect to apply to arguments that 289 /// do not have an entry in Args. 290 ArgEffect DefaultArgEffect; 291 292 /// Receiver - If this summary applies to an Objective-C message expression, 293 /// this is the effect applied to the state of the receiver. 294 ArgEffect Receiver; 295 296 /// Effect on "this" pointer - applicable only to C++ method calls. 297 ArgEffect This; 298 299 /// Ret - The effect on the return value. Used to indicate if the 300 /// function/method call returns a new tracked symbol. 301 RetEffect Ret; 302 303 public: 304 RetainSummary(ArgEffects A, 305 RetEffect R, 306 ArgEffect defaultEff, 307 ArgEffect ReceiverEff, 308 ArgEffect ThisEff) 309 : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff), 310 This(ThisEff), Ret(R) {} 311 312 /// getArg - Return the argument effect on the argument specified by 313 /// idx (starting from 0). 314 ArgEffect getArg(unsigned idx) const { 315 if (const ArgEffect *AE = Args.lookup(idx)) 316 return *AE; 317 318 return DefaultArgEffect; 319 } 320 321 void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) { 322 Args = af.add(Args, idx, e); 323 } 324 325 /// setDefaultArgEffect - Set the default argument effect. 326 void setDefaultArgEffect(ArgEffect E) { 327 DefaultArgEffect = E; 328 } 329 330 /// getRetEffect - Returns the effect on the return value of the call. 331 RetEffect getRetEffect() const { return Ret; } 332 333 /// setRetEffect - Set the effect of the return value of the call. 334 void setRetEffect(RetEffect E) { Ret = E; } 335 336 337 /// Sets the effect on the receiver of the message. 338 void setReceiverEffect(ArgEffect e) { Receiver = e; } 339 340 /// getReceiverEffect - Returns the effect on the receiver of the call. 341 /// This is only meaningful if the summary applies to an ObjCMessageExpr*. 342 ArgEffect getReceiverEffect() const { return Receiver; } 343 344 /// \return the effect on the "this" receiver of the method call. 345 /// This is only meaningful if the summary applies to CXXMethodDecl*. 346 ArgEffect getThisEffect() const { return This; } 347 348 ArgEffect getDefaultEffect() const { return DefaultArgEffect; } 349 350 /// Set the effect of the method on "this". 351 void setThisEffect(ArgEffect e) { This = e; } 352 353 bool isNoop() const { 354 return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing 355 && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing 356 && Args.isEmpty(); 357 } 358 359 /// Test if two retain summaries are identical. Note that merely equivalent 360 /// summaries are not necessarily identical (for example, if an explicit 361 /// argument effect matches the default effect). 362 bool operator==(const RetainSummary &Other) const { 363 return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect && 364 Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret; 365 } 366 367 /// Profile this summary for inclusion in a FoldingSet. 368 void Profile(llvm::FoldingSetNodeID& ID) const { 369 ID.Add(Args); 370 ID.Add(DefaultArgEffect); 371 ID.Add(Receiver); 372 ID.Add(This); 373 ID.Add(Ret); 374 } 375 376 /// A retain summary is simple if it has no ArgEffects other than the default. 377 bool isSimple() const { 378 return Args.isEmpty(); 379 } 380 381 ArgEffects getArgEffects() const { return Args; } 382 383 private: 384 ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; } 385 386 friend class RetainSummaryManager; 387 }; 388 389 class ObjCSummaryCache { 390 typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy; 391 MapTy M; 392 public: 393 ObjCSummaryCache() {} 394 395 const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) { 396 // Do a lookup with the (D,S) pair. If we find a match return 397 // the iterator. 398 ObjCSummaryKey K(D, S); 399 MapTy::iterator I = M.find(K); 400 401 if (I != M.end()) 402 return I->second; 403 if (!D) 404 return nullptr; 405 406 // Walk the super chain. If we find a hit with a parent, we'll end 407 // up returning that summary. We actually allow that key (null,S), as 408 // we cache summaries for the null ObjCInterfaceDecl* to allow us to 409 // generate initial summaries without having to worry about NSObject 410 // being declared. 411 // FIXME: We may change this at some point. 412 for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) { 413 if ((I = M.find(ObjCSummaryKey(C, S))) != M.end()) 414 break; 415 416 if (!C) 417 return nullptr; 418 } 419 420 // Cache the summary with original key to make the next lookup faster 421 // and return the iterator. 422 const RetainSummary *Summ = I->second; 423 M[K] = Summ; 424 return Summ; 425 } 426 427 const RetainSummary *find(IdentifierInfo* II, Selector S) { 428 // FIXME: Class method lookup. Right now we don't have a good way 429 // of going between IdentifierInfo* and the class hierarchy. 430 MapTy::iterator I = M.find(ObjCSummaryKey(II, S)); 431 432 if (I == M.end()) 433 I = M.find(ObjCSummaryKey(S)); 434 435 return I == M.end() ? nullptr : I->second; 436 } 437 438 const RetainSummary *& operator[](ObjCSummaryKey K) { 439 return M[K]; 440 } 441 442 const RetainSummary *& operator[](Selector S) { 443 return M[ ObjCSummaryKey(S) ]; 444 } 445 }; 446 447 class RetainSummaryTemplate; 448 449 class RetainSummaryManager { 450 typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *> 451 FuncSummariesTy; 452 453 typedef ObjCSummaryCache ObjCMethodSummariesTy; 454 455 typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode; 456 457 /// Ctx - The ASTContext object for the analyzed ASTs. 458 ASTContext &Ctx; 459 460 /// Records whether or not the analyzed code runs in ARC mode. 461 const bool ARCEnabled; 462 463 /// Track Objective-C and CoreFoundation objects. 464 const bool TrackObjCAndCFObjects; 465 466 /// Track sublcasses of OSObject. 467 const bool TrackOSObjects; 468 469 /// FuncSummaries - A map from FunctionDecls to summaries. 470 FuncSummariesTy FuncSummaries; 471 472 /// ObjCClassMethodSummaries - A map from selectors (for instance methods) 473 /// to summaries. 474 ObjCMethodSummariesTy ObjCClassMethodSummaries; 475 476 /// ObjCMethodSummaries - A map from selectors to summaries. 477 ObjCMethodSummariesTy ObjCMethodSummaries; 478 479 /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects, 480 /// and all other data used by the checker. 481 llvm::BumpPtrAllocator BPAlloc; 482 483 /// AF - A factory for ArgEffects objects. 484 ArgEffects::Factory AF; 485 486 /// ObjCAllocRetE - Default return effect for methods returning Objective-C 487 /// objects. 488 RetEffect ObjCAllocRetE; 489 490 /// ObjCInitRetE - Default return effect for init methods returning 491 /// Objective-C objects. 492 RetEffect ObjCInitRetE; 493 494 /// SimpleSummaries - Used for uniquing summaries that don't have special 495 /// effects. 496 llvm::FoldingSet<CachedSummaryNode> SimpleSummaries; 497 498 /// Create an OS object at +1. 499 const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD); 500 501 /// Get an OS object at +0. 502 const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD); 503 504 /// Increment the reference count on OS object. 505 const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD); 506 507 /// Decrement the reference count on OS object. 508 const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD); 509 510 /// Free the OS object. 511 const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD); 512 513 const RetainSummary *getUnarySummary(const FunctionType* FT, 514 ArgEffectKind AE); 515 516 const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD); 517 const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD); 518 const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD); 519 520 const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm); 521 522 const RetainSummary * 523 getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs, 524 ArgEffect ReceiverEff = ArgEffect(DoNothing), 525 ArgEffect DefaultEff = ArgEffect(MayEscape), 526 ArgEffect ThisEff = ArgEffect(DoNothing)) { 527 RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff); 528 return getPersistentSummary(Summ); 529 } 530 531 const RetainSummary *getDoNothingSummary() { 532 return getPersistentSummary(RetEffect::MakeNoRet(), 533 ArgEffects(AF.getEmptyMap()), 534 ArgEffect(DoNothing), ArgEffect(DoNothing)); 535 } 536 537 const RetainSummary *getDefaultSummary() { 538 return getPersistentSummary(RetEffect::MakeNoRet(), 539 ArgEffects(AF.getEmptyMap()), 540 ArgEffect(DoNothing), ArgEffect(MayEscape)); 541 } 542 543 const RetainSummary *getPersistentStopSummary() { 544 return getPersistentSummary( 545 RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()), 546 ArgEffect(StopTracking), ArgEffect(StopTracking)); 547 } 548 549 void InitializeClassMethodSummaries(); 550 void InitializeMethodSummaries(); 551 552 void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) { 553 ObjCClassMethodSummaries[S] = Summ; 554 } 555 556 void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) { 557 ObjCMethodSummaries[S] = Summ; 558 } 559 560 void addClassMethSummary(const char* Cls, const char* name, 561 const RetainSummary *Summ, bool isNullary = true) { 562 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls); 563 Selector S = isNullary ? GetNullarySelector(name, Ctx) 564 : GetUnarySelector(name, Ctx); 565 ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; 566 } 567 568 void addInstMethSummary(const char* Cls, const char* nullaryName, 569 const RetainSummary *Summ) { 570 IdentifierInfo* ClsII = &Ctx.Idents.get(Cls); 571 Selector S = GetNullarySelector(nullaryName, Ctx); 572 ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; 573 } 574 575 template <typename... Keywords> 576 void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries, 577 const RetainSummary *Summ, Keywords *... Kws) { 578 Selector S = getKeywordSelector(Ctx, Kws...); 579 Summaries[ObjCSummaryKey(ClsII, S)] = Summ; 580 } 581 582 template <typename... Keywords> 583 void addInstMethSummary(const char *Cls, const RetainSummary *Summ, 584 Keywords *... Kws) { 585 addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...); 586 } 587 588 template <typename... Keywords> 589 void addClsMethSummary(const char *Cls, const RetainSummary *Summ, 590 Keywords *... Kws) { 591 addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ, 592 Kws...); 593 } 594 595 template <typename... Keywords> 596 void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ, 597 Keywords *... Kws) { 598 addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...); 599 } 600 601 const RetainSummary * generateSummary(const FunctionDecl *FD, 602 bool &AllowAnnotations); 603 604 /// Return a summary for OSObject, or nullptr if not found. 605 const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD, 606 StringRef FName, QualType RetTy); 607 608 /// Return a summary for Objective-C or CF object, or nullptr if not found. 609 const RetainSummary *getSummaryForObjCOrCFObject( 610 const FunctionDecl *FD, 611 StringRef FName, 612 QualType RetTy, 613 const FunctionType *FT, 614 bool &AllowAnnotations); 615 616 /// Apply the annotation of @c pd in function @c FD 617 /// to the resulting summary stored in out-parameter @c Template. 618 /// \return whether an annotation was applied. 619 bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx, 620 const NamedDecl *FD, 621 RetainSummaryTemplate &Template); 622 623 public: 624 RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects, 625 bool trackOSObjects) 626 : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount), 627 TrackObjCAndCFObjects(trackObjCAndCFObjects), 628 TrackOSObjects(trackOSObjects), AF(BPAlloc), 629 ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC) 630 : RetEffect::MakeOwned(ObjKind::ObjC)), 631 ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC) 632 : RetEffect::MakeOwnedWhenTrackedReceiver()) { 633 InitializeClassMethodSummaries(); 634 InitializeMethodSummaries(); 635 } 636 637 enum class BehaviorSummary { 638 // Function does not return. 639 NoOp, 640 641 // Function returns the first argument. 642 Identity, 643 644 // Function returns "this" argument. 645 IdentityThis, 646 647 // Function either returns zero, or the input parameter. 648 IdentityOrZero 649 }; 650 651 Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD, 652 bool &hasTrustedImplementationAnnotation); 653 654 /// \return Whether the type corresponds to a known smart pointer 655 /// implementation (that is, everything about it is inlineable). 656 static bool isKnownSmartPointer(QualType QT); 657 658 bool isTrustedReferenceCountImplementation(const Decl *FD); 659 660 const RetainSummary *getSummary(AnyCall C, 661 bool HasNonZeroCallbackArg=false, 662 bool IsReceiverUnconsumedSelf=false, 663 QualType ReceiverType={}); 664 665 RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; } 666 667 private: 668 669 /// getMethodSummary - This version of getMethodSummary is used to query 670 /// the summary for the current method being analyzed. 671 const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD); 672 673 const RetainSummary *getFunctionSummary(const FunctionDecl *FD); 674 675 const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID, 676 const ObjCMethodDecl *MD, 677 QualType RetTy, 678 ObjCMethodSummariesTy &CachedSummaries); 679 680 const RetainSummary * 681 getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType); 682 683 const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME); 684 685 const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD, 686 Selector S, QualType RetTy); 687 688 /// Determine if there is a special return effect for this function or method. 689 Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy, 690 const Decl *D); 691 692 void updateSummaryFromAnnotations(const RetainSummary *&Summ, 693 const ObjCMethodDecl *MD); 694 695 void updateSummaryFromAnnotations(const RetainSummary *&Summ, 696 const FunctionDecl *FD); 697 698 const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S, 699 AnyCall &C); 700 701 /// Special case '[super init];' and '[self init];' 702 /// 703 /// Even though calling '[super init]' without assigning the result to self 704 /// and checking if the parent returns 'nil' is a bad pattern, it is common. 705 /// Additionally, our Self Init checker already warns about it. To avoid 706 /// overwhelming the user with messages from both checkers, we model the case 707 /// of '[super init]' in cases when it is not consumed by another expression 708 /// as if the call preserves the value of 'self'; essentially, assuming it can 709 /// never fail and return 'nil'. 710 /// Note, we don't want to just stop tracking the value since we want the 711 /// RetainCount checker to report leaks and use-after-free if SelfInit checker 712 /// is turned off. 713 void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S); 714 715 /// Set argument types for arguments which are not doing anything. 716 void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS); 717 718 /// Determine whether a declaration @c D of correspondent type (return 719 /// type for functions/methods) @c QT has any of the given attributes, 720 /// provided they pass necessary validation checks AND tracking the given 721 /// attribute is enabled. 722 /// Returns the object kind corresponding to the present attribute, or None, 723 /// if none of the specified attributes are present. 724 /// Crashes if passed an attribute which is not explicitly handled. 725 template <class T> 726 Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); 727 728 template <class T1, class T2, class... Others> 729 Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT); 730 731 friend class RetainSummaryTemplate; 732 }; 733 734 735 // Used to avoid allocating long-term (BPAlloc'd) memory for default retain 736 // summaries. If a function or method looks like it has a default summary, but 737 // it has annotations, the annotations are added to the stack-based template 738 // and then copied into managed memory. 739 class RetainSummaryTemplate { 740 RetainSummaryManager &Manager; 741 const RetainSummary *&RealSummary; 742 RetainSummary ScratchSummary; 743 bool Accessed; 744 public: 745 RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr) 746 : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {} 747 748 ~RetainSummaryTemplate() { 749 if (Accessed) 750 RealSummary = Manager.getPersistentSummary(ScratchSummary); 751 } 752 753 RetainSummary &operator*() { 754 Accessed = true; 755 return ScratchSummary; 756 } 757 758 RetainSummary *operator->() { 759 Accessed = true; 760 return &ScratchSummary; 761 } 762 }; 763 764 } // end namespace ento 765 } // end namespace clang 766 767 #endif 768