Home | History | Annotate | Line # | Download | only in Analysis
      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_RETAINSUMMARY_MANAGER_H
     16 #define LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_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