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