//=== RetainSummaryManager.h - Summaries for reference counting ---*- C++ -*--//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
//  This file defines summaries implementation for retain counting, which
//  implements a reference count checker for Core Foundation and Cocoa
//  on (Mac OS X).
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H
#define LLVM_CLANG_ANALYSIS_RETAINSUMMARY_MANAGER_H

#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/ImmutableMap.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/ParentMap.h"
#include "clang/Analysis/AnyCall.h"
#include "clang/Analysis/SelectorExtras.h"
#include "llvm/ADT/STLExtras.h"

using namespace clang;

namespace clang {
namespace ento {

/// Determines the object kind of a tracked object.
enum class ObjKind {
  /// Indicates that the tracked object is a CF object.
  CF,

  /// Indicates that the tracked object is an Objective-C object.
  ObjC,

  /// Indicates that the tracked object could be a CF or Objective-C object.
  AnyObj,

  /// Indicates that the tracked object is a generalized object.
  Generalized,

  /// Indicates that the tracking object is a descendant of a
  /// referenced-counted OSObject, used in the Darwin kernel.
  OS
};

enum ArgEffectKind {
  /// There is no effect.
  DoNothing,

  /// The argument is treated as if an -autorelease message had been sent to
  /// the referenced object.
  Autorelease,

  /// The argument is treated as if the referenced object was deallocated.
  Dealloc,

  /// The argument has its reference count decreased by 1.
  DecRef,

  /// The argument has its reference count decreased by 1 to model
  /// a transferred bridge cast under ARC.
  DecRefBridgedTransferred,

  /// The argument has its reference count increased by 1.
  IncRef,

  /// The argument is a pointer to a retain-counted object; on exit, the new
  /// value of the pointer is a +0 value.
  UnretainedOutParameter,

  /// The argument is a pointer to a retain-counted object; on exit, the new
  /// value of the pointer is a +1 value.
  RetainedOutParameter,

  /// The argument is a pointer to a retain-counted object; on exit, the new
  /// value of the pointer is a +1 value iff the return code is zero.
  RetainedOutParameterOnZero,

  /// The argument is a pointer to a retain-counted object; on exit, the new
  /// value of the pointer is a +1 value iff the return code is non-zero.
  RetainedOutParameterOnNonZero,

  /// The argument is treated as potentially escaping, meaning that
  /// even when its reference count hits 0 it should be treated as still
  /// possibly being alive as someone else *may* be holding onto the object.
  MayEscape,

  /// All typestate tracking of the object ceases.  This is usually employed
  /// when the effect of the call is completely unknown.
  StopTracking,

  /// All typestate tracking of the object ceases.  Unlike StopTracking,
  /// this is also enforced when the method body is inlined.
  ///
  /// In some cases, we obtain a better summary for this checker
  /// by looking at the call site than by inlining the function.
  /// Signifies that we should stop tracking the symbol even if
  /// the function is inlined.
  StopTrackingHard,

  /// Performs the combined functionality of DecRef and StopTrackingHard.
  ///
  /// The models the effect that the called function decrements the reference
  /// count of the argument and all typestate tracking on that argument
  /// should cease.
  DecRefAndStopTrackingHard,
};

/// An ArgEffect summarizes the retain count behavior on an argument or receiver
/// to a function or method.
class ArgEffect {
  ArgEffectKind K;
  ObjKind O;
public:
  explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
      : K(K), O(O) {}

  ArgEffectKind getKind() const { return K; }
  ObjKind getObjKind() const { return O; }

  ArgEffect withKind(ArgEffectKind NewK) {
    return ArgEffect(NewK, O);
  }

  bool operator==(const ArgEffect &Other) const {
    return K == Other.K && O == Other.O;
  }
};

/// RetEffect summarizes a call's retain/release behavior with respect
/// to its return value.
class RetEffect {
public:
  enum Kind {
    /// Indicates that no retain count information is tracked for
    /// the return value.
    NoRet,

    /// Indicates that the returned value is an owned (+1) symbol.
    OwnedSymbol,

    /// Indicates that the returned value is an object with retain count
    /// semantics but that it is not owned (+0).  This is the default
    /// for getters, etc.
    NotOwnedSymbol,

    /// Indicates that the return value is an owned object when the
    /// receiver is also a tracked object.
    OwnedWhenTrackedReceiver,

    // Treat this function as returning a non-tracked symbol even if
    // the function has been inlined. This is used where the call
    // site summary is more precise than the summary indirectly produced
    // by inlining the function
    NoRetHard
  };

private:
  Kind K;
  ObjKind O;

  RetEffect(Kind k, ObjKind o = ObjKind::AnyObj) : K(k), O(o) {}

public:
  Kind getKind() const { return K; }

  ObjKind getObjKind() const { return O; }

  bool isOwned() const {
    return K == OwnedSymbol || K == OwnedWhenTrackedReceiver;
  }

  bool notOwned() const {
    return K == NotOwnedSymbol;
  }

  bool operator==(const RetEffect &Other) const {
    return K == Other.K && O == Other.O;
  }

  static RetEffect MakeOwnedWhenTrackedReceiver() {
    return RetEffect(OwnedWhenTrackedReceiver, ObjKind::ObjC);
  }

  static RetEffect MakeOwned(ObjKind o) {
    return RetEffect(OwnedSymbol, o);
  }
  static RetEffect MakeNotOwned(ObjKind o) {
    return RetEffect(NotOwnedSymbol, o);
  }
  static RetEffect MakeNoRet() {
    return RetEffect(NoRet);
  }
  static RetEffect MakeNoRetHard() {
    return RetEffect(NoRetHard);
  }
};

/// A key identifying a summary.
class ObjCSummaryKey {
  IdentifierInfo* II;
  Selector S;
public:
  ObjCSummaryKey(IdentifierInfo* ii, Selector s)
    : II(ii), S(s) {}

  ObjCSummaryKey(const ObjCInterfaceDecl *d, Selector s)
    : II(d ? d->getIdentifier() : nullptr), S(s) {}

  ObjCSummaryKey(Selector s)
    : II(nullptr), S(s) {}

  IdentifierInfo *getIdentifier() const { return II; }
  Selector getSelector() const { return S; }
};

} // end namespace ento
} // end namespace clang

using namespace ento;

namespace llvm {

//===----------------------------------------------------------------------===//
// Adapters for FoldingSet.
//===----------------------------------------------------------------------===//
template <> struct FoldingSetTrait<ArgEffect> {
static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
  ID.AddInteger((unsigned) X.getKind());
  ID.AddInteger((unsigned) X.getObjKind());
}
};
template <> struct FoldingSetTrait<RetEffect> {
  static inline void Profile(const RetEffect &X, FoldingSetNodeID &ID) {
    ID.AddInteger((unsigned) X.getKind());
    ID.AddInteger((unsigned) X.getObjKind());
}
};

template <> struct DenseMapInfo<ObjCSummaryKey> {
  static inline ObjCSummaryKey getEmptyKey() {
    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getEmptyKey(),
                          DenseMapInfo<Selector>::getEmptyKey());
  }

  static inline ObjCSummaryKey getTombstoneKey() {
    return ObjCSummaryKey(DenseMapInfo<IdentifierInfo*>::getTombstoneKey(),
                          DenseMapInfo<Selector>::getTombstoneKey());
  }

  static unsigned getHashValue(const ObjCSummaryKey &V) {
    typedef std::pair<IdentifierInfo*, Selector> PairTy;
    return DenseMapInfo<PairTy>::getHashValue(PairTy(V.getIdentifier(),
                                                     V.getSelector()));
  }

  static bool isEqual(const ObjCSummaryKey& LHS, const ObjCSummaryKey& RHS) {
    return LHS.getIdentifier() == RHS.getIdentifier() &&
           LHS.getSelector() == RHS.getSelector();
  }

};

} // end llvm namespace


namespace clang {
namespace ento {

/// ArgEffects summarizes the effects of a function/method call on all of
/// its arguments.
typedef llvm::ImmutableMap<unsigned, ArgEffect> ArgEffects;

/// Summary for a function with respect to ownership changes.
class RetainSummary {
  /// Args - a map of (index, ArgEffect) pairs, where index
  ///  specifies the argument (starting from 0).  This can be sparsely
  ///  populated; arguments with no entry in Args use 'DefaultArgEffect'.
  ArgEffects Args;

  /// DefaultArgEffect - The default ArgEffect to apply to arguments that
  ///  do not have an entry in Args.
  ArgEffect DefaultArgEffect;

  /// Receiver - If this summary applies to an Objective-C message expression,
  ///  this is the effect applied to the state of the receiver.
  ArgEffect Receiver;

  /// Effect on "this" pointer - applicable only to C++ method calls.
  ArgEffect This;

  /// Ret - The effect on the return value.  Used to indicate if the
  ///  function/method call returns a new tracked symbol.
  RetEffect Ret;

public:
  RetainSummary(ArgEffects A,
                RetEffect R,
                ArgEffect defaultEff,
                ArgEffect ReceiverEff,
                ArgEffect ThisEff)
    : Args(A), DefaultArgEffect(defaultEff), Receiver(ReceiverEff),
      This(ThisEff), Ret(R) {}

  /// getArg - Return the argument effect on the argument specified by
  ///  idx (starting from 0).
  ArgEffect getArg(unsigned idx) const {
    if (const ArgEffect *AE = Args.lookup(idx))
      return *AE;

    return DefaultArgEffect;
  }

  void addArg(ArgEffects::Factory &af, unsigned idx, ArgEffect e) {
    Args = af.add(Args, idx, e);
  }

  /// setDefaultArgEffect - Set the default argument effect.
  void setDefaultArgEffect(ArgEffect E) {
    DefaultArgEffect = E;
  }

  /// getRetEffect - Returns the effect on the return value of the call.
  RetEffect getRetEffect() const { return Ret; }

  /// setRetEffect - Set the effect of the return value of the call.
  void setRetEffect(RetEffect E) { Ret = E; }


  /// Sets the effect on the receiver of the message.
  void setReceiverEffect(ArgEffect e) { Receiver = e; }

  /// getReceiverEffect - Returns the effect on the receiver of the call.
  ///  This is only meaningful if the summary applies to an ObjCMessageExpr*.
  ArgEffect getReceiverEffect() const { return Receiver; }

  /// \return the effect on the "this" receiver of the method call.
  /// This is only meaningful if the summary applies to CXXMethodDecl*.
  ArgEffect getThisEffect() const { return This; }

  ArgEffect getDefaultEffect() const { return DefaultArgEffect; }

  /// Set the effect of the method on "this".
  void setThisEffect(ArgEffect e) { This = e; }

  bool isNoop() const {
    return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
      && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
      && Args.isEmpty();
  }

  /// Test if two retain summaries are identical. Note that merely equivalent
  /// summaries are not necessarily identical (for example, if an explicit
  /// argument effect matches the default effect).
  bool operator==(const RetainSummary &Other) const {
    return Args == Other.Args && DefaultArgEffect == Other.DefaultArgEffect &&
           Receiver == Other.Receiver && This == Other.This && Ret == Other.Ret;
  }

  /// Profile this summary for inclusion in a FoldingSet.
  void Profile(llvm::FoldingSetNodeID& ID) const {
    ID.Add(Args);
    ID.Add(DefaultArgEffect);
    ID.Add(Receiver);
    ID.Add(This);
    ID.Add(Ret);
  }

  /// A retain summary is simple if it has no ArgEffects other than the default.
  bool isSimple() const {
    return Args.isEmpty();
  }

  ArgEffects getArgEffects() const { return Args; }

private:
  ArgEffect getDefaultArgEffect() const { return DefaultArgEffect; }

  friend class RetainSummaryManager;
};

class ObjCSummaryCache {
  typedef llvm::DenseMap<ObjCSummaryKey, const RetainSummary *> MapTy;
  MapTy M;
public:
  ObjCSummaryCache() {}

  const RetainSummary * find(const ObjCInterfaceDecl *D, Selector S) {
    // Do a lookup with the (D,S) pair.  If we find a match return
    // the iterator.
    ObjCSummaryKey K(D, S);
    MapTy::iterator I = M.find(K);

    if (I != M.end())
      return I->second;
    if (!D)
      return nullptr;

    // Walk the super chain.  If we find a hit with a parent, we'll end
    // up returning that summary.  We actually allow that key (null,S), as
    // we cache summaries for the null ObjCInterfaceDecl* to allow us to
    // generate initial summaries without having to worry about NSObject
    // being declared.
    // FIXME: We may change this at some point.
    for (ObjCInterfaceDecl *C=D->getSuperClass() ;; C=C->getSuperClass()) {
      if ((I = M.find(ObjCSummaryKey(C, S))) != M.end())
        break;

      if (!C)
        return nullptr;
    }

    // Cache the summary with original key to make the next lookup faster
    // and return the iterator.
    const RetainSummary *Summ = I->second;
    M[K] = Summ;
    return Summ;
  }

  const RetainSummary *find(IdentifierInfo* II, Selector S) {
    // FIXME: Class method lookup.  Right now we don't have a good way
    // of going between IdentifierInfo* and the class hierarchy.
    MapTy::iterator I = M.find(ObjCSummaryKey(II, S));

    if (I == M.end())
      I = M.find(ObjCSummaryKey(S));

    return I == M.end() ? nullptr : I->second;
  }

  const RetainSummary *& operator[](ObjCSummaryKey K) {
    return M[K];
  }

  const RetainSummary *& operator[](Selector S) {
    return M[ ObjCSummaryKey(S) ];
  }
};

class RetainSummaryTemplate;

class RetainSummaryManager {
  typedef llvm::DenseMap<const FunctionDecl*, const RetainSummary *>
          FuncSummariesTy;

  typedef ObjCSummaryCache ObjCMethodSummariesTy;

  typedef llvm::FoldingSetNodeWrapper<RetainSummary> CachedSummaryNode;

  /// Ctx - The ASTContext object for the analyzed ASTs.
  ASTContext &Ctx;

  /// Records whether or not the analyzed code runs in ARC mode.
  const bool ARCEnabled;

  /// Track Objective-C and CoreFoundation objects.
  const bool TrackObjCAndCFObjects;

  /// Track sublcasses of OSObject.
  const bool TrackOSObjects;

  /// FuncSummaries - A map from FunctionDecls to summaries.
  FuncSummariesTy FuncSummaries;

  /// ObjCClassMethodSummaries - A map from selectors (for instance methods)
  ///  to summaries.
  ObjCMethodSummariesTy ObjCClassMethodSummaries;

  /// ObjCMethodSummaries - A map from selectors to summaries.
  ObjCMethodSummariesTy ObjCMethodSummaries;

  /// BPAlloc - A BumpPtrAllocator used for allocating summaries, ArgEffects,
  ///  and all other data used by the checker.
  llvm::BumpPtrAllocator BPAlloc;

  /// AF - A factory for ArgEffects objects.
  ArgEffects::Factory AF;

  /// ObjCAllocRetE - Default return effect for methods returning Objective-C
  ///  objects.
  RetEffect ObjCAllocRetE;

  /// ObjCInitRetE - Default return effect for init methods returning
  ///   Objective-C objects.
  RetEffect ObjCInitRetE;

  /// SimpleSummaries - Used for uniquing summaries that don't have special
  /// effects.
  llvm::FoldingSet<CachedSummaryNode> SimpleSummaries;

  /// Create an OS object at +1.
  const RetainSummary *getOSSummaryCreateRule(const FunctionDecl *FD);

  /// Get an OS object at +0.
  const RetainSummary *getOSSummaryGetRule(const FunctionDecl *FD);

  /// Increment the reference count on OS object.
  const RetainSummary *getOSSummaryRetainRule(const FunctionDecl *FD);

  /// Decrement the reference count on OS object.
  const RetainSummary *getOSSummaryReleaseRule(const FunctionDecl *FD);

  /// Free the OS object.
  const RetainSummary *getOSSummaryFreeRule(const FunctionDecl *FD);

  const RetainSummary *getUnarySummary(const FunctionType* FT,
                                       ArgEffectKind AE);

  const RetainSummary *getCFSummaryCreateRule(const FunctionDecl *FD);
  const RetainSummary *getCFSummaryGetRule(const FunctionDecl *FD);
  const RetainSummary *getCFCreateGetRuleSummary(const FunctionDecl *FD);

  const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);

  const RetainSummary *
  getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
                       ArgEffect ReceiverEff = ArgEffect(DoNothing),
                       ArgEffect DefaultEff = ArgEffect(MayEscape),
                       ArgEffect ThisEff = ArgEffect(DoNothing)) {
    RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
    return getPersistentSummary(Summ);
  }

  const RetainSummary *getDoNothingSummary() {
    return getPersistentSummary(RetEffect::MakeNoRet(),
                                ArgEffects(AF.getEmptyMap()),
                                ArgEffect(DoNothing), ArgEffect(DoNothing));
  }

  const RetainSummary *getDefaultSummary() {
    return getPersistentSummary(RetEffect::MakeNoRet(),
                                ArgEffects(AF.getEmptyMap()),
                                ArgEffect(DoNothing), ArgEffect(MayEscape));
  }

  const RetainSummary *getPersistentStopSummary() {
    return getPersistentSummary(
        RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
        ArgEffect(StopTracking), ArgEffect(StopTracking));
  }

  void InitializeClassMethodSummaries();
  void InitializeMethodSummaries();

  void addNSObjectClsMethSummary(Selector S, const RetainSummary *Summ) {
    ObjCClassMethodSummaries[S] = Summ;
  }

  void addNSObjectMethSummary(Selector S, const RetainSummary *Summ) {
    ObjCMethodSummaries[S] = Summ;
  }

  void addClassMethSummary(const char* Cls, const char* name,
                           const RetainSummary *Summ, bool isNullary = true) {
    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
    Selector S = isNullary ? GetNullarySelector(name, Ctx)
                           : GetUnarySelector(name, Ctx);
    ObjCClassMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
  }

  void addInstMethSummary(const char* Cls, const char* nullaryName,
                          const RetainSummary *Summ) {
    IdentifierInfo* ClsII = &Ctx.Idents.get(Cls);
    Selector S = GetNullarySelector(nullaryName, Ctx);
    ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)]  = Summ;
  }

  template <typename... Keywords>
  void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy &Summaries,
                        const RetainSummary *Summ, Keywords *... Kws) {
    Selector S = getKeywordSelector(Ctx, Kws...);
    Summaries[ObjCSummaryKey(ClsII, S)] = Summ;
  }

  template <typename... Keywords>
  void addInstMethSummary(const char *Cls, const RetainSummary *Summ,
                          Keywords *... Kws) {
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, Kws...);
  }

  template <typename... Keywords>
  void addClsMethSummary(const char *Cls, const RetainSummary *Summ,
                         Keywords *... Kws) {
    addMethodSummary(&Ctx.Idents.get(Cls), ObjCClassMethodSummaries, Summ,
                     Kws...);
  }

  template <typename... Keywords>
  void addClsMethSummary(IdentifierInfo *II, const RetainSummary *Summ,
                         Keywords *... Kws) {
    addMethodSummary(II, ObjCClassMethodSummaries, Summ, Kws...);
  }

  const RetainSummary * generateSummary(const FunctionDecl *FD,
                                        bool &AllowAnnotations);

  /// Return a summary for OSObject, or nullptr if not found.
  const RetainSummary *getSummaryForOSObject(const FunctionDecl *FD,
                                             StringRef FName, QualType RetTy);

  /// Return a summary for Objective-C or CF object, or nullptr if not found.
  const RetainSummary *getSummaryForObjCOrCFObject(
    const FunctionDecl *FD,
    StringRef FName,
    QualType RetTy,
    const FunctionType *FT,
    bool &AllowAnnotations);

  /// Apply the annotation of {@code pd} in function {@code FD}
  /// to the resulting summary stored in out-parameter {@code Template}.
  /// \return whether an annotation was applied.
  bool applyParamAnnotationEffect(const ParmVarDecl *pd, unsigned parm_idx,
                                  const NamedDecl *FD,
                                  RetainSummaryTemplate &Template);

public:
  RetainSummaryManager(ASTContext &ctx, bool trackObjCAndCFObjects,
                       bool trackOSObjects)
      : Ctx(ctx), ARCEnabled((bool)Ctx.getLangOpts().ObjCAutoRefCount),
        TrackObjCAndCFObjects(trackObjCAndCFObjects),
        TrackOSObjects(trackOSObjects), AF(BPAlloc),
        ObjCAllocRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
                                 : RetEffect::MakeOwned(ObjKind::ObjC)),
        ObjCInitRetE(ARCEnabled ? RetEffect::MakeNotOwned(ObjKind::ObjC)
                                : RetEffect::MakeOwnedWhenTrackedReceiver()) {
    InitializeClassMethodSummaries();
    InitializeMethodSummaries();
  }

  enum class BehaviorSummary {
    // Function does not return.
    NoOp,

    // Function returns the first argument.
    Identity,

    // Function returns "this" argument.
    IdentityThis,

    // Function either returns zero, or the input parameter.
    IdentityOrZero
  };

  Optional<BehaviorSummary> canEval(const CallExpr *CE, const FunctionDecl *FD,
                                    bool &hasTrustedImplementationAnnotation);

  /// \return Whether the type corresponds to a known smart pointer
  /// implementation (that is, everything about it is inlineable).
  static bool isKnownSmartPointer(QualType QT);

  bool isTrustedReferenceCountImplementation(const Decl *FD);

  const RetainSummary *getSummary(AnyCall C,
                                  bool HasNonZeroCallbackArg=false,
                                  bool IsReceiverUnconsumedSelf=false,
                                  QualType ReceiverType={});

  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }

private:

  /// getMethodSummary - This version of getMethodSummary is used to query
  ///  the summary for the current method being analyzed.
  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD);

  const RetainSummary *getFunctionSummary(const FunctionDecl *FD);

  const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
                                        const ObjCMethodDecl *MD,
                                        QualType RetTy,
                                        ObjCMethodSummariesTy &CachedSummaries);

  const RetainSummary *
  getInstanceMethodSummary(const ObjCMessageExpr *ME, QualType ReceiverType);

  const RetainSummary *getClassMethodSummary(const ObjCMessageExpr *ME);

  const RetainSummary *getStandardMethodSummary(const ObjCMethodDecl *MD,
                                                Selector S, QualType RetTy);

  /// Determine if there is a special return effect for this function or method.
  Optional<RetEffect> getRetEffectFromAnnotations(QualType RetTy,
                                                  const Decl *D);

  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
                                    const ObjCMethodDecl *MD);

  void updateSummaryFromAnnotations(const RetainSummary *&Summ,
                                    const FunctionDecl *FD);

  const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
                                                          AnyCall &C);

  /// Special case '[super init];' and '[self init];'
  ///
  /// Even though calling '[super init]' without assigning the result to self
  /// and checking if the parent returns 'nil' is a bad pattern, it is common.
  /// Additionally, our Self Init checker already warns about it. To avoid
  /// overwhelming the user with messages from both checkers, we model the case
  /// of '[super init]' in cases when it is not consumed by another expression
  /// as if the call preserves the value of 'self'; essentially, assuming it can
  /// never fail and return 'nil'.
  /// Note, we don't want to just stop tracking the value since we want the
  /// RetainCount checker to report leaks and use-after-free if SelfInit checker
  /// is turned off.
  void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);

  /// Set argument types for arguments which are not doing anything.
  void updateSummaryForArgumentTypes(const AnyCall &C, const RetainSummary *&RS);

  /// Determine whether a declaration {@code D} of correspondent type (return
  /// type for functions/methods) {@code QT} has any of the given attributes,
  /// provided they pass necessary validation checks AND tracking the given
  /// attribute is enabled.
  /// Returns the object kind corresponding to the present attribute, or None,
  /// if none of the specified attributes are present.
  /// Crashes if passed an attribute which is not explicitly handled.
  template <class T>
  Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);

  template <class T1, class T2, class... Others>
  Optional<ObjKind> hasAnyEnabledAttrOf(const Decl *D, QualType QT);

  friend class RetainSummaryTemplate;
};


// Used to avoid allocating long-term (BPAlloc'd) memory for default retain
// summaries. If a function or method looks like it has a default summary, but
// it has annotations, the annotations are added to the stack-based template
// and then copied into managed memory.
class RetainSummaryTemplate {
  RetainSummaryManager &Manager;
  const RetainSummary *&RealSummary;
  RetainSummary ScratchSummary;
  bool Accessed;
public:
  RetainSummaryTemplate(const RetainSummary *&real, RetainSummaryManager &mgr)
    : Manager(mgr), RealSummary(real), ScratchSummary(*real), Accessed(false) {}

  ~RetainSummaryTemplate() {
    if (Accessed)
      RealSummary = Manager.getPersistentSummary(ScratchSummary);
  }

  RetainSummary &operator*() {
    Accessed = true;
    return ScratchSummary;
  }

  RetainSummary *operator->() {
    Accessed = true;
    return &ScratchSummary;
  }
};

} // end namespace ento
} // end namespace clang

#endif
