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