r352149 - [analyzer] Port RetainSummaryManager to the new AnyCall interface, decouple ARCMT from the analyzer

George Karpenkov via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 24 17:24:04 PST 2019


Author: george.karpenkov
Date: Thu Jan 24 17:24:04 2019
New Revision: 352149

URL: http://llvm.org/viewvc/llvm-project?rev=352149&view=rev
Log:
[analyzer] Port RetainSummaryManager to the new AnyCall interface, decouple ARCMT from the analyzer

rdar://19694750

Differential Revision: https://reviews.llvm.org/D57127

Added:
    cfe/trunk/include/clang/Analysis/RetainSummaryManager.h
    cfe/trunk/lib/Analysis/RetainSummaryManager.cpp
Removed:
    cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
    cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
Modified:
    cfe/trunk/lib/ARCMigrate/CMakeLists.txt
    cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
    cfe/trunk/lib/Analysis/CMakeLists.txt
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
    cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt

Added: cfe/trunk/include/clang/Analysis/RetainSummaryManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/RetainSummaryManager.h?rev=352149&view=auto
==============================================================================
--- cfe/trunk/include/clang/Analysis/RetainSummaryManager.h (added)
+++ cfe/trunk/include/clang/Analysis/RetainSummaryManager.h Thu Jan 24 17:24:04 2019
@@ -0,0 +1,783 @@
+//=== 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);
+  }
+};
+
+/// Encapsulates the retain count semantics on the arguments, return value,
+/// and receiver (if any) of a function/method call.
+///
+/// Note that construction of these objects is not highly efficient.  That
+/// is okay for clients where creating these objects isn't really a bottleneck.
+/// The purpose of the API is to provide something simple.  The actual
+/// static analyzer checker that implements retain/release typestate
+/// tracking uses something more efficient.
+class CallEffects {
+  llvm::SmallVector<ArgEffect, 10> Args;
+  RetEffect Ret;
+  ArgEffect Receiver;
+
+  CallEffects(const RetEffect &R,
+              ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
+      : Ret(R), Receiver(Receiver) {}
+
+public:
+  /// Returns the argument effects for a call.
+  ArrayRef<ArgEffect> getArgs() const { return Args; }
+
+  /// Returns the effects on the receiver.
+  ArgEffect getReceiver() const { return Receiver; }
+
+  /// Returns the effect on the return value.
+  RetEffect getReturnValue() const { return Ret; }
+
+  /// Return the CallEfect for a given Objective-C method.
+  static CallEffects getEffect(const ObjCMethodDecl *MD);
+
+  /// Return the CallEfect for a given C/C++ function.
+  static CallEffects getEffect(const FunctionDecl *FD);
+};
+
+/// 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; }
+
+  /// 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 FunctionDecl *FD);
+
+  const RetainSummary *getSummary(AnyCall C,
+                                  bool HasNonZeroCallbackArg,
+                                  bool IsReceiverUnconsumedSelf,
+                                  QualType ReceiverType=QualType());
+
+  /// 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);
+
+  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
+private:
+  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);
+
+  void updateSummaryForCall(const RetainSummary *&Summ,
+                            AnyCall C,
+                            bool HasNonZeroCallbackArg,
+                            bool IsReceiverUnconsumedSelf);
+
+  /// 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

Removed: cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h?rev=352148&view=auto
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h (removed)
@@ -1,804 +0,0 @@
-//=== 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_ANALYZER_CORE_RETAINSUMMARYMANAGER
-#define LLVM_CLANG_ANALYZER_CORE_RETAINSUMMARYMANAGER
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/FoldingSet.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/SelectorExtras.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
-#include "llvm/ADT/STLExtras.h"
-
-//===----------------------------------------------------------------------===//
-// Adapters for FoldingSet.
-//===----------------------------------------------------------------------===//
-
-using namespace clang;
-using namespace ento;
-
-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);
-  }
-};
-
-/// Encapsulates the retain count semantics on the arguments, return value,
-/// and receiver (if any) of a function/method call.
-///
-/// Note that construction of these objects is not highly efficient.  That
-/// is okay for clients where creating these objects isn't really a bottleneck.
-/// The purpose of the API is to provide something simple.  The actual
-/// static analyzer checker that implements retain/release typestate
-/// tracking uses something more efficient.
-class CallEffects {
-  llvm::SmallVector<ArgEffect, 10> Args;
-  RetEffect Ret;
-  ArgEffect Receiver;
-
-  CallEffects(const RetEffect &R,
-              ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
-      : Ret(R), Receiver(Receiver) {}
-
-public:
-  /// Returns the argument effects for a call.
-  ArrayRef<ArgEffect> getArgs() const { return Args; }
-
-  /// Returns the effects on the receiver.
-  ArgEffect getReceiver() const { return Receiver; }
-
-  /// Returns the effect on the return value.
-  RetEffect getReturnValue() const { return Ret; }
-
-  /// Return the CallEfect for a given Objective-C method.
-  static CallEffects getEffect(const ObjCMethodDecl *MD);
-
-  /// Return the CallEfect for a given C/C++ function.
-  static CallEffects getEffect(const FunctionDecl *FD);
-};
-
-/// 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
-
-
-namespace llvm {
-
-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; }
-
-  /// 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 usesARC,
-                       bool trackObjCAndCFObjects,
-                       bool trackOSObjects)
-   : Ctx(ctx),
-     ARCEnabled(usesARC),
-     TrackObjCAndCFObjects(trackObjCAndCFObjects),
-     TrackOSObjects(trackOSObjects),
-     AF(BPAlloc),
-     ObjCAllocRetE(usesARC ? RetEffect::MakeNotOwned(ObjKind::ObjC)
-                               : RetEffect::MakeOwned(ObjKind::ObjC)),
-     ObjCInitRetE(usesARC ? 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 FunctionDecl *FD);
-
-  const RetainSummary *getSummary(const CallEvent &Call,
-                                  QualType ReceiverType=QualType());
-
-  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 ObjCMethodCall &M,
-                           QualType ReceiverType);
-
-  const RetainSummary *getClassMethodSummary(const ObjCMethodCall &M) {
-    assert(!M.isInstanceMessage());
-    const ObjCInterfaceDecl *Class = M.getReceiverInterface();
-
-    return getMethodSummary(M.getSelector(), Class, M.getDecl(),
-                            M.getResultType(), ObjCClassMethodSummaries);
-  }
-
-  /// getMethodSummary - This version of getMethodSummary is used to query
-  ///  the summary for the current method being analyzed.
-  const RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
-    const ObjCInterfaceDecl *ID = MD->getClassInterface();
-    Selector S = MD->getSelector();
-    QualType ResultTy = MD->getReturnType();
-
-    ObjCMethodSummariesTy *CachedSummaries;
-    if (MD->isInstanceMethod())
-      CachedSummaries = &ObjCMethodSummaries;
-    else
-      CachedSummaries = &ObjCClassMethodSummaries;
-
-    return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
-  }
-
-  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);
-
-
-  void updateSummaryForCall(const RetainSummary *&Summ,
-                            const CallEvent &Call);
-
-  bool isARCEnabled() const { return ARCEnabled; }
-
-  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
-
-  /// 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

Modified: cfe/trunk/lib/ARCMigrate/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/CMakeLists.txt?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/CMakeLists.txt (original)
+++ cfe/trunk/lib/ARCMigrate/CMakeLists.txt Thu Jan 24 17:24:04 2019
@@ -34,6 +34,4 @@ add_clang_library(clangARCMigrate
   clangRewrite
   clangSema
   clangSerialization
-  clangStaticAnalyzerCheckers
-  clangStaticAnalyzerCore
   )

Modified: cfe/trunk/lib/ARCMigrate/ObjCMT.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/ARCMigrate/ObjCMT.cpp?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/ARCMigrate/ObjCMT.cpp (original)
+++ cfe/trunk/lib/ARCMigrate/ObjCMT.cpp Thu Jan 24 17:24:04 2019
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "Transforms.h"
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/ARCMigrate/ARCMT.h"
 #include "clang/ARCMigrate/ARCMTActions.h"
 #include "clang/AST/ASTConsumer.h"
@@ -26,7 +27,6 @@
 #include "clang/Lex/PPConditionalDirectiveRecord.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Rewrite/Core/Rewriter.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Path.h"

Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Thu Jan 24 17:24:04 2019
@@ -21,6 +21,7 @@ add_clang_library(clangAnalysis
   PostOrderCFGView.cpp
   ProgramPoint.cpp
   ReachableCode.cpp
+  RetainSummaryManager.cpp
   ThreadSafety.cpp
   ThreadSafetyCommon.cpp
   ThreadSafetyLogical.cpp

Added: cfe/trunk/lib/Analysis/RetainSummaryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RetainSummaryManager.cpp?rev=352149&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/RetainSummaryManager.cpp (added)
+++ cfe/trunk/lib/Analysis/RetainSummaryManager.cpp Thu Jan 24 17:24:04 2019
@@ -0,0 +1,1268 @@
+//== RetainSummaryManager.cpp - 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, Cocoa
+//  and OSObject (on Mac OS X).
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Analysis/RetainSummaryManager.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang;
+using namespace ento;
+
+template <class T>
+constexpr static bool isOneOf() {
+  return false;
+}
+
+/// Helper function to check whether the class is one of the
+/// rest of varargs.
+template <class T, class P, class... ToCompare>
+constexpr static bool isOneOf() {
+  return std::is_same<T, P>::value || isOneOf<T, ToCompare...>();
+}
+
+namespace {
+
+/// Fake attribute class for RC* attributes.
+struct GeneralizedReturnsRetainedAttr {
+  static bool classof(const Attr *A) {
+    if (auto AA = dyn_cast<AnnotateAttr>(A))
+      return AA->getAnnotation() == "rc_ownership_returns_retained";
+    return false;
+  }
+};
+
+struct GeneralizedReturnsNotRetainedAttr {
+  static bool classof(const Attr *A) {
+    if (auto AA = dyn_cast<AnnotateAttr>(A))
+      return AA->getAnnotation() == "rc_ownership_returns_not_retained";
+    return false;
+  }
+};
+
+struct GeneralizedConsumedAttr {
+  static bool classof(const Attr *A) {
+    if (auto AA = dyn_cast<AnnotateAttr>(A))
+      return AA->getAnnotation() == "rc_ownership_consumed";
+    return false;
+  }
+};
+
+}
+
+template <class T>
+Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
+                                                            QualType QT) {
+  ObjKind K;
+  if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,
+              CFReturnsNotRetainedAttr>()) {
+    if (!TrackObjCAndCFObjects)
+      return None;
+
+    K = ObjKind::CF;
+  } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,
+                     NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,
+                     NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {
+
+    if (!TrackObjCAndCFObjects)
+      return None;
+
+    if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,
+                NSReturnsNotRetainedAttr>() &&
+        !cocoa::isCocoaObjectRef(QT))
+      return None;
+    K = ObjKind::ObjC;
+  } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,
+                     OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,
+                     OSReturnsRetainedOnZeroAttr,
+                     OSReturnsRetainedOnNonZeroAttr>()) {
+    if (!TrackOSObjects)
+      return None;
+    K = ObjKind::OS;
+  } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,
+                     GeneralizedReturnsRetainedAttr,
+                     GeneralizedConsumedAttr>()) {
+    K = ObjKind::Generalized;
+  } else {
+    llvm_unreachable("Unexpected attribute");
+  }
+  if (D->hasAttr<T>())
+    return K;
+  return None;
+}
+
+template <class T1, class T2, class... Others>
+Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
+                                                            QualType QT) {
+  if (auto Out = hasAnyEnabledAttrOf<T1>(D, QT))
+    return Out;
+  return hasAnyEnabledAttrOf<T2, Others...>(D, QT);
+}
+
+const RetainSummary *
+RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
+  // Unique "simple" summaries -- those without ArgEffects.
+  if (OldSumm.isSimple()) {
+    ::llvm::FoldingSetNodeID ID;
+    OldSumm.Profile(ID);
+
+    void *Pos;
+    CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
+
+    if (!N) {
+      N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
+      new (N) CachedSummaryNode(OldSumm);
+      SimpleSummaries.InsertNode(N, Pos);
+    }
+
+    return &N->getValue();
+  }
+
+  RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
+  new (Summ) RetainSummary(OldSumm);
+  return Summ;
+}
+
+static bool isSubclass(const Decl *D,
+                       StringRef ClassName) {
+  using namespace ast_matchers;
+  DeclarationMatcher SubclassM = cxxRecordDecl(isSameOrDerivedFrom(ClassName));
+  return !(match(SubclassM, *D, D->getASTContext()).empty());
+}
+
+static bool isOSObjectSubclass(const Decl *D) {
+  return isSubclass(D, "OSMetaClassBase");
+}
+
+static bool isOSObjectDynamicCast(StringRef S) {
+  return S == "safeMetaCast";
+}
+
+static bool isOSObjectThisCast(StringRef S) {
+  return S == "metaCast";
+}
+
+static bool isOSIteratorSubclass(const Decl *D) {
+  return isSubclass(D, "OSIterator");
+}
+
+static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
+  for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
+    if (Ann->getAnnotation() == rcAnnotation)
+      return true;
+  }
+  return false;
+}
+
+static bool isRetain(const FunctionDecl *FD, StringRef FName) {
+  return FName.startswith_lower("retain") || FName.endswith_lower("retain");
+}
+
+static bool isRelease(const FunctionDecl *FD, StringRef FName) {
+  return FName.startswith_lower("release") || FName.endswith_lower("release");
+}
+
+static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
+  return FName.startswith_lower("autorelease") ||
+         FName.endswith_lower("autorelease");
+}
+
+static bool isMakeCollectable(StringRef FName) {
+  return FName.contains_lower("MakeCollectable");
+}
+
+/// A function is OSObject related if it is declared on a subclass
+/// of OSObject, or any of the parameters is a subclass of an OSObject.
+static bool isOSObjectRelated(const CXXMethodDecl *MD) {
+  if (isOSObjectSubclass(MD->getParent()))
+    return true;
+
+  for (ParmVarDecl *Param : MD->parameters()) {
+    QualType PT = Param->getType()->getPointeeType();
+    if (!PT.isNull())
+      if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl())
+        if (isOSObjectSubclass(RD))
+          return true;
+  }
+
+  return false;
+}
+
+bool
+RetainSummaryManager::isKnownSmartPointer(QualType QT) {
+  QT = QT.getCanonicalType();
+  const auto *RD = QT->getAsCXXRecordDecl();
+  if (!RD)
+    return false;
+  const IdentifierInfo *II = RD->getIdentifier();
+  if (II && II->getName() == "smart_ptr")
+    if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()))
+      if (ND->getNameAsString() == "os")
+        return true;
+  return false;
+}
+
+const RetainSummary *
+RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,
+                                            StringRef FName, QualType RetTy) {
+  if (RetTy->isPointerType()) {
+    const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
+    if (PD && isOSObjectSubclass(PD)) {
+      if (const IdentifierInfo *II = FD->getIdentifier()) {
+        StringRef FuncName = II->getName();
+        if (isOSObjectDynamicCast(FuncName) || isOSObjectThisCast(FuncName))
+          return getDefaultSummary();
+
+        // All objects returned with functions *not* starting with
+        // get, or iterators, are returned at +1.
+        if ((!FuncName.startswith("get") && !FuncName.startswith("Get")) ||
+            isOSIteratorSubclass(PD)) {
+          return getOSSummaryCreateRule(FD);
+        } else {
+          return getOSSummaryGetRule(FD);
+        }
+      }
+    }
+  }
+
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+    const CXXRecordDecl *Parent = MD->getParent();
+    if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) {
+      if (FName == "release")
+        return getOSSummaryReleaseRule(FD);
+
+      if (FName == "retain")
+        return getOSSummaryRetainRule(FD);
+
+      if (FName == "free")
+        return getOSSummaryFreeRule(FD);
+
+      if (MD->getOverloadedOperator() == OO_New)
+        return getOSSummaryCreateRule(MD);
+    }
+  }
+
+  return nullptr;
+}
+
+const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
+    const FunctionDecl *FD,
+    StringRef FName,
+    QualType RetTy,
+    const FunctionType *FT,
+    bool &AllowAnnotations) {
+
+  ArgEffects ScratchArgs(AF.getEmptyMap());
+
+  std::string RetTyName = RetTy.getAsString();
+  if (FName == "pthread_create" || FName == "pthread_setspecific") {
+    // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
+    // This will be addressed better with IPA.
+    return getPersistentStopSummary();
+  } else if(FName == "NSMakeCollectable") {
+    // Handle: id NSMakeCollectable(CFTypeRef)
+    AllowAnnotations = false;
+    return RetTy->isObjCIdType() ? getUnarySummary(FT, DoNothing)
+                                 : getPersistentStopSummary();
+  } else if (FName == "CMBufferQueueDequeueAndRetain" ||
+             FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+    // Part of: <rdar://problem/39390714>.
+    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
+                                ScratchArgs,
+                                ArgEffect(DoNothing),
+                                ArgEffect(DoNothing));
+  } else if (FName == "CFPlugInInstanceCreate") {
+    return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs);
+  } else if (FName == "IORegistryEntrySearchCFProperty" ||
+             (RetTyName == "CFMutableDictionaryRef" &&
+              (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||
+               FName == "IOServiceNameMatching" ||
+               FName == "IORegistryEntryIDMatching" ||
+               FName == "IOOpenFirmwarePathMatching"))) {
+    // Part of <rdar://problem/6961230>. (IOKit)
+    // This should be addressed using a API table.
+    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "IOServiceGetMatchingService" ||
+             FName == "IOServiceGetMatchingServices") {
+    // FIXES: <rdar://problem/6326900>
+    // This should be addressed using a API table.  This strcmp is also
+    // a little gross, but there is no need to super optimize here.
+    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "IOServiceAddNotification" ||
+             FName == "IOServiceAddMatchingNotification") {
+    // Part of <rdar://problem/6961230>. (IOKit)
+    // This should be addressed using a API table.
+    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "CVPixelBufferCreateWithBytes") {
+    // FIXES: <rdar://problem/7283567>
+    // Eventually this can be improved by recognizing that the pixel
+    // buffer passed to CVPixelBufferCreateWithBytes is released via
+    // a callback and doing full IPA to make sure this is done correctly.
+    // FIXME: This function has an out parameter that returns an
+    // allocated object.
+    ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "CGBitmapContextCreateWithData") {
+    // FIXES: <rdar://problem/7358899>
+    // Eventually this can be improved by recognizing that 'releaseInfo'
+    // passed to CGBitmapContextCreateWithData is released via
+    // a callback and doing full IPA to make sure this is done correctly.
+    ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
+    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
+    // FIXES: <rdar://problem/7283567>
+    // Eventually this can be improved by recognizing that the pixel
+    // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
+    // via a callback and doing full IPA to make sure this is done
+    // correctly.
+    ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "VTCompressionSessionEncodeFrame") {
+    // The context argument passed to VTCompressionSessionEncodeFrame()
+    // is passed to the callback specified when creating the session
+    // (e.g. with VTCompressionSessionCreate()) which can release it.
+    // To account for this possibility, conservatively stop tracking
+    // the context.
+    ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName == "dispatch_set_context" ||
+             FName == "xpc_connection_set_context") {
+    // <rdar://problem/11059275> - The analyzer currently doesn't have
+    // a good way to reason about the finalizer function for libdispatch.
+    // If we pass a context object that is memory managed, stop tracking it.
+    // <rdar://problem/13783514> - Same problem, but for XPC.
+    // FIXME: this hack should possibly go away once we can handle
+    // libdispatch and XPC finalizers.
+    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs,
+                                ArgEffect(DoNothing), ArgEffect(DoNothing));
+  } else if (FName.startswith("NSLog")) {
+    return getDoNothingSummary();
+  } else if (FName.startswith("NS") &&
+             (FName.find("Insert") != StringRef::npos)) {
+    // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
+    // be deallocated by NSMapRemove. (radar://11152419)
+    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
+    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));
+    return getPersistentSummary(RetEffect::MakeNoRet(),
+                                ScratchArgs, ArgEffect(DoNothing),
+                                ArgEffect(DoNothing));
+  }
+
+  if (RetTy->isPointerType()) {
+
+    // For CoreFoundation ('CF') types.
+    if (cocoa::isRefType(RetTy, "CF", FName)) {
+      if (isRetain(FD, FName)) {
+        // CFRetain isn't supposed to be annotated. However, this may as
+        // well be a user-made "safe" CFRetain function that is incorrectly
+        // annotated as cf_returns_retained due to lack of better options.
+        // We want to ignore such annotation.
+        AllowAnnotations = false;
+
+        return getUnarySummary(FT, IncRef);
+      } else if (isAutorelease(FD, FName)) {
+        // The headers use cf_consumed, but we can fully model CFAutorelease
+        // ourselves.
+        AllowAnnotations = false;
+
+        return getUnarySummary(FT, Autorelease);
+      } else if (isMakeCollectable(FName)) {
+        AllowAnnotations = false;
+        return getUnarySummary(FT, DoNothing);
+      } else {
+        return getCFCreateGetRuleSummary(FD);
+      }
+    }
+
+    // For CoreGraphics ('CG') and CoreVideo ('CV') types.
+    if (cocoa::isRefType(RetTy, "CG", FName) ||
+        cocoa::isRefType(RetTy, "CV", FName)) {
+      if (isRetain(FD, FName))
+        return getUnarySummary(FT, IncRef);
+      else
+        return getCFCreateGetRuleSummary(FD);
+    }
+
+    // For all other CF-style types, use the Create/Get
+    // rule for summaries but don't support Retain functions
+    // with framework-specific prefixes.
+    if (coreFoundation::isCFObjectRef(RetTy)) {
+      return getCFCreateGetRuleSummary(FD);
+    }
+
+    if (FD->hasAttr<CFAuditedTransferAttr>()) {
+      return getCFCreateGetRuleSummary(FD);
+    }
+  }
+
+  // Check for release functions, the only kind of functions that we care
+  // about that don't return a pointer type.
+  if (FName.startswith("CG") || FName.startswith("CF")) {
+    // Test for 'CGCF'.
+    FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
+
+    if (isRelease(FD, FName))
+      return getUnarySummary(FT, DecRef);
+    else {
+      assert(ScratchArgs.isEmpty());
+      // Remaining CoreFoundation and CoreGraphics functions.
+      // We use to assume that they all strictly followed the ownership idiom
+      // and that ownership cannot be transferred.  While this is technically
+      // correct, many methods allow a tracked object to escape.  For example:
+      //
+      //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
+      //   CFDictionaryAddValue(y, key, x);
+      //   CFRelease(x);
+      //   ... it is okay to use 'x' since 'y' has a reference to it
+      //
+      // We handle this and similar cases with the follow heuristic.  If the
+      // function name contains "InsertValue", "SetValue", "AddValue",
+      // "AppendValue", or "SetAttribute", then we assume that arguments may
+      // "escape."  This means that something else holds on to the object,
+      // allowing it be used even after its local retain count drops to 0.
+      ArgEffectKind E =
+          (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
+           StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+           StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+           StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
+           StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
+              ? MayEscape
+              : DoNothing;
+
+      return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+                                  ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF));
+    }
+  }
+
+  return nullptr;
+}
+
+const RetainSummary *
+RetainSummaryManager::generateSummary(const FunctionDecl *FD,
+                                      bool &AllowAnnotations) {
+  // We generate "stop" summaries for implicitly defined functions.
+  if (FD->isImplicit())
+    return getPersistentStopSummary();
+
+  const IdentifierInfo *II = FD->getIdentifier();
+
+  StringRef FName = II ? II->getName() : "";
+
+  // Strip away preceding '_'.  Doing this here will effect all the checks
+  // down below.
+  FName = FName.substr(FName.find_first_not_of('_'));
+
+  // Inspect the result type. Strip away any typedefs.
+  const auto *FT = FD->getType()->getAs<FunctionType>();
+  QualType RetTy = FT->getReturnType();
+
+  if (TrackOSObjects)
+    if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
+      return S;
+
+  if (TrackObjCAndCFObjects)
+    if (const RetainSummary *S =
+            getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
+      return S;
+
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
+    if (!(TrackOSObjects && isOSObjectRelated(MD)))
+      return getPersistentSummary(RetEffect::MakeNoRet(),
+                                  ArgEffects(AF.getEmptyMap()),
+                                  ArgEffect(DoNothing),
+                                  ArgEffect(StopTracking),
+                                  ArgEffect(DoNothing));
+
+  return getDefaultSummary();
+}
+
+const RetainSummary *
+RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
+  // If we don't know what function we're calling, use our default summary.
+  if (!FD)
+    return getDefaultSummary();
+
+  // Look up a summary in our cache of FunctionDecls -> Summaries.
+  FuncSummariesTy::iterator I = FuncSummaries.find(FD);
+  if (I != FuncSummaries.end())
+    return I->second;
+
+  // No summary?  Generate one.
+  bool AllowAnnotations = true;
+  const RetainSummary *S = generateSummary(FD, AllowAnnotations);
+
+  // Annotations override defaults.
+  if (AllowAnnotations)
+    updateSummaryFromAnnotations(S, FD);
+
+  FuncSummaries[FD] = S;
+  return S;
+}
+
+//===----------------------------------------------------------------------===//
+// Summary creation for functions (largely uses of Core Foundation).
+//===----------------------------------------------------------------------===//
+
+static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
+  switch (E.getKind()) {
+  case DoNothing:
+  case Autorelease:
+  case DecRefBridgedTransferred:
+  case IncRef:
+  case UnretainedOutParameter:
+  case RetainedOutParameter:
+  case RetainedOutParameterOnZero:
+  case RetainedOutParameterOnNonZero:
+  case MayEscape:
+  case StopTracking:
+  case StopTrackingHard:
+    return E.withKind(StopTrackingHard);
+  case DecRef:
+  case DecRefAndStopTrackingHard:
+    return E.withKind(DecRefAndStopTrackingHard);
+  case Dealloc:
+    return E.withKind(Dealloc);
+  }
+
+  llvm_unreachable("Unknown ArgEffect kind");
+}
+
+void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
+                                                AnyCall C,
+                                                bool HasNonZeroCallbackArg,
+                                                bool IsReceiverUnconsumedSelf) {
+
+  if (HasNonZeroCallbackArg) {
+    ArgEffect RecEffect =
+      getStopTrackingHardEquivalent(S->getReceiverEffect());
+    ArgEffect DefEffect =
+      getStopTrackingHardEquivalent(S->getDefaultArgEffect());
+
+    ArgEffects ScratchArgs(AF.getEmptyMap());
+    ArgEffects CustomArgEffects = S->getArgEffects();
+    for (ArgEffects::iterator I = CustomArgEffects.begin(),
+                              E = CustomArgEffects.end();
+         I != E; ++I) {
+      ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
+      if (Translated.getKind() != DefEffect.getKind())
+        ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
+    }
+
+    RetEffect RE = RetEffect::MakeNoRetHard();
+
+    // Special cases where the callback argument CANNOT free the return value.
+    // This can generally only happen if we know that the callback will only be
+    // called when the return value is already being deallocated.
+    if (C.getKind() == AnyCall::Function) {
+      if (const IdentifierInfo *Name = C.getIdentifier()) {
+        // When the CGBitmapContext is deallocated, the callback here will free
+        // the associated data buffer.
+        // The callback in dispatch_data_create frees the buffer, but not
+        // the data object.
+        if (Name->isStr("CGBitmapContextCreateWithData") ||
+            Name->isStr("dispatch_data_create"))
+          RE = S->getRetEffect();
+      }
+    }
+
+    S = getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
+  }
+
+  // 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.
+  if (IsReceiverUnconsumedSelf) {
+    RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
+    ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
+    ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
+  }
+}
+
+const RetainSummary *
+RetainSummaryManager::getSummary(AnyCall C,
+                                 bool HasNonZeroCallbackArg,
+                                 bool IsReceiverUnconsumedSelf,
+                                 QualType ReceiverType) {
+  const RetainSummary *Summ;
+  switch (C.getKind()) {
+  case AnyCall::Function:
+  case AnyCall::Constructor:
+  case AnyCall::Allocator:
+  case AnyCall::Deallocator:
+    Summ = getFunctionSummary(cast_or_null<FunctionDecl>(C.getDecl()));
+    break;
+  case AnyCall::Block:
+  case AnyCall::Destructor:
+    // FIXME: These calls are currently unsupported.
+    return getPersistentStopSummary();
+  case AnyCall::ObjCMethod: {
+    const auto *ME = cast<ObjCMessageExpr>(C.getExpr());
+    if (ME->isInstanceMessage())
+      Summ = getInstanceMethodSummary(ME, ReceiverType);
+    else
+      Summ = getClassMethodSummary(ME);
+    break;
+  }
+  }
+
+  updateSummaryForCall(Summ, C, HasNonZeroCallbackArg,
+                       IsReceiverUnconsumedSelf);
+
+  assert(Summ && "Unknown call type?");
+  return Summ;
+}
+
+
+const RetainSummary *
+RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
+  if (coreFoundation::followsCreateRule(FD))
+    return getCFSummaryCreateRule(FD);
+
+  return getCFSummaryGetRule(FD);
+}
+
+bool RetainSummaryManager::isTrustedReferenceCountImplementation(
+    const FunctionDecl *FD) {
+  return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
+}
+
+Optional<RetainSummaryManager::BehaviorSummary>
+RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
+                              bool &hasTrustedImplementationAnnotation) {
+
+  IdentifierInfo *II = FD->getIdentifier();
+  if (!II)
+    return None;
+
+  StringRef FName = II->getName();
+  FName = FName.substr(FName.find_first_not_of('_'));
+
+  QualType ResultTy = CE->getCallReturnType(Ctx);
+  if (ResultTy->isObjCIdType()) {
+    if (II->isStr("NSMakeCollectable"))
+      return BehaviorSummary::Identity;
+  } else if (ResultTy->isPointerType()) {
+    // Handle: (CF|CG|CV)Retain
+    //         CFAutorelease
+    // It's okay to be a little sloppy here.
+    if (FName == "CMBufferQueueDequeueAndRetain" ||
+        FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
+      // Part of: <rdar://problem/39390714>.
+      // These are not retain. They just return something and retain it.
+      return None;
+    }
+    if (cocoa::isRefType(ResultTy, "CF", FName) ||
+        cocoa::isRefType(ResultTy, "CG", FName) ||
+        cocoa::isRefType(ResultTy, "CV", FName))
+      if (isRetain(FD, FName) || isAutorelease(FD, FName) ||
+          isMakeCollectable(FName))
+        return BehaviorSummary::Identity;
+
+    // safeMetaCast is called by OSDynamicCast.
+    // We assume that OSDynamicCast is either an identity (cast is OK,
+    // the input was non-zero),
+    // or that it returns zero (when the cast failed, or the input
+    // was zero).
+    if (TrackOSObjects) {
+      if (isOSObjectDynamicCast(FName) && FD->param_size() >= 1) {
+        return BehaviorSummary::IdentityOrZero;
+      } else if (isOSObjectThisCast(FName) && isa<CXXMethodDecl>(FD) &&
+                 !cast<CXXMethodDecl>(FD)->isStatic()) {
+        return BehaviorSummary::IdentityThis;
+      }
+    }
+
+    const FunctionDecl* FDD = FD->getDefinition();
+    if (FDD && isTrustedReferenceCountImplementation(FDD)) {
+      hasTrustedImplementationAnnotation = true;
+      return BehaviorSummary::Identity;
+    }
+  }
+
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+    const CXXRecordDecl *Parent = MD->getParent();
+    if (TrackOSObjects && Parent && isOSObjectSubclass(Parent))
+      if (FName == "release" || FName == "retain")
+        return BehaviorSummary::NoOp;
+  }
+
+  return None;
+}
+
+const RetainSummary *
+RetainSummaryManager::getUnarySummary(const FunctionType* FT,
+                                      ArgEffectKind AE) {
+
+  // Unary functions have no arg effects by definition.
+  ArgEffects ScratchArgs(AF.getEmptyMap());
+
+  // Sanity check that this is *really* a unary function.  This can
+  // happen if people do weird things.
+  const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
+  if (!FTP || FTP->getNumParams() != 1)
+    return getPersistentStopSummary();
+
+  ArgEffect Effect(AE, ObjKind::CF);
+
+  ScratchArgs = AF.add(ScratchArgs, 0, Effect);
+  return getPersistentSummary(RetEffect::MakeNoRet(),
+                              ScratchArgs,
+                              ArgEffect(DoNothing), ArgEffect(DoNothing));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeNoRet(),
+                              AF.getEmptyMap(),
+                              /*ReceiverEff=*/ArgEffect(DoNothing),
+                              /*DefaultEff=*/ArgEffect(DoNothing),
+                              /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeNoRet(),
+                              AF.getEmptyMap(),
+                              /*ReceiverEff=*/ArgEffect(DoNothing),
+                              /*DefaultEff=*/ArgEffect(DoNothing),
+                              /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeNoRet(),
+                              AF.getEmptyMap(),
+                              /*ReceiverEff=*/ArgEffect(DoNothing),
+                              /*DefaultEff=*/ArgEffect(DoNothing),
+                              /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS));
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::OS),
+                              AF.getEmptyMap());
+}
+
+const RetainSummary *
+RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::OS),
+                              AF.getEmptyMap());
+}
+
+const RetainSummary *
+RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
+                              ArgEffects(AF.getEmptyMap()));
+}
+
+const RetainSummary *
+RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
+  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF),
+                              ArgEffects(AF.getEmptyMap()),
+                              ArgEffect(DoNothing), ArgEffect(DoNothing));
+}
+
+
+
+
+//===----------------------------------------------------------------------===//
+// Summary creation for Selectors.
+//===----------------------------------------------------------------------===//
+
+Optional<RetEffect>
+RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
+                                                  const Decl *D) {
+  if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy))
+    return ObjCAllocRetE;
+
+  if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,
+                                   GeneralizedReturnsRetainedAttr>(D, RetTy))
+    return RetEffect::MakeOwned(*K);
+
+  if (auto K = hasAnyEnabledAttrOf<
+          CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,
+          GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,
+          NSReturnsAutoreleasedAttr>(D, RetTy))
+    return RetEffect::MakeNotOwned(*K);
+
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
+    for (const auto *PD : MD->overridden_methods())
+      if (auto RE = getRetEffectFromAnnotations(RetTy, PD))
+        return RE;
+
+  return None;
+}
+
+/// \return Whether the chain of typedefs starting from {@code QT}
+/// has a typedef with a given name {@code Name}.
+static bool hasTypedefNamed(QualType QT,
+                            StringRef Name) {
+  while (auto *T = dyn_cast<TypedefType>(QT)) {
+    const auto &Context = T->getDecl()->getASTContext();
+    if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name))
+      return true;
+    QT = T->getDecl()->getUnderlyingType();
+  }
+  return false;
+}
+
+static QualType getCallableReturnType(const NamedDecl *ND) {
+  if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
+    return FD->getReturnType();
+  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) {
+    return MD->getReturnType();
+  } else {
+    llvm_unreachable("Unexpected decl");
+  }
+}
+
+bool RetainSummaryManager::applyParamAnnotationEffect(
+    const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD,
+    RetainSummaryTemplate &Template) {
+  QualType QT = pd->getType();
+  if (auto K =
+          hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,
+                              GeneralizedConsumedAttr>(pd, QT)) {
+    Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K));
+    return true;
+  } else if (auto K = hasAnyEnabledAttrOf<
+                 CFReturnsRetainedAttr, OSReturnsRetainedAttr,
+                 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,
+                 GeneralizedReturnsRetainedAttr>(pd, QT)) {
+
+    // For OSObjects, we try to guess whether the object is created based
+    // on the return value.
+    if (K == ObjKind::OS) {
+      QualType QT = getCallableReturnType(FD);
+
+      bool HasRetainedOnZero = pd->hasAttr<OSReturnsRetainedOnZeroAttr>();
+      bool HasRetainedOnNonZero = pd->hasAttr<OSReturnsRetainedOnNonZeroAttr>();
+
+      // The usual convention is to create an object on non-zero return, but
+      // it's reverted if the typedef chain has a typedef kern_return_t,
+      // because kReturnSuccess constant is defined as zero.
+      // The convention can be overwritten by custom attributes.
+      bool SuccessOnZero =
+          HasRetainedOnZero ||
+          (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero);
+      bool ShouldSplit = !QT.isNull() && !QT->isVoidType();
+      ArgEffectKind AK = RetainedOutParameter;
+      if (ShouldSplit && SuccessOnZero) {
+        AK = RetainedOutParameterOnZero;
+      } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {
+        AK = RetainedOutParameterOnNonZero;
+      }
+      Template->addArg(AF, parm_idx, ArgEffect(AK, ObjKind::OS));
+    }
+
+    // For others:
+    // Do nothing. Retained out parameters will either point to a +1 reference
+    // or NULL, but the way you check for failure differs depending on the
+    // API. Consequently, we don't have a good way to track them yet.
+    return true;
+  } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,
+                                          OSReturnsNotRetainedAttr,
+                                          GeneralizedReturnsNotRetainedAttr>(
+                 pd, QT)) {
+    Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter, *K));
+    return true;
+  }
+
+  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+    for (const auto *OD : MD->overridden_methods()) {
+      const ParmVarDecl *OP = OD->parameters()[parm_idx];
+      if (applyParamAnnotationEffect(OP, parm_idx, OD, Template))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                                   const FunctionDecl *FD) {
+  if (!FD)
+    return;
+
+  assert(Summ && "Must have a summary to add annotations to.");
+  RetainSummaryTemplate Template(Summ, *this);
+
+  // Effects on the parameters.
+  unsigned parm_idx = 0;
+  for (auto pi = FD->param_begin(),
+         pe = FD->param_end(); pi != pe; ++pi, ++parm_idx)
+    applyParamAnnotationEffect(*pi, parm_idx, FD, Template);
+
+  QualType RetTy = FD->getReturnType();
+  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
+    Template->setRetEffect(*RetE);
+
+  if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy))
+    Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS));
+}
+
+void
+RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
+                                                   const ObjCMethodDecl *MD) {
+  if (!MD)
+    return;
+
+  assert(Summ && "Must have a valid summary to add annotations to");
+  RetainSummaryTemplate Template(Summ, *this);
+
+  // Effects on the receiver.
+  if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->getReturnType()))
+    Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC));
+
+  // Effects on the parameters.
+  unsigned parm_idx = 0;
+  for (auto pi = MD->param_begin(), pe = MD->param_end(); pi != pe;
+       ++pi, ++parm_idx)
+    applyParamAnnotationEffect(*pi, parm_idx, MD, Template);
+
+  QualType RetTy = MD->getReturnType();
+  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
+    Template->setRetEffect(*RetE);
+}
+
+const RetainSummary *
+RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
+                                               Selector S, QualType RetTy) {
+  // Any special effects?
+  ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC);
+  RetEffect ResultEff = RetEffect::MakeNoRet();
+
+  // Check the method family, and apply any default annotations.
+  switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
+    case OMF_None:
+    case OMF_initialize:
+    case OMF_performSelector:
+      // Assume all Objective-C methods follow Cocoa Memory Management rules.
+      // FIXME: Does the non-threaded performSelector family really belong here?
+      // The selector could be, say, @selector(copy).
+      if (cocoa::isCocoaObjectRef(RetTy))
+        ResultEff = RetEffect::MakeNotOwned(ObjKind::ObjC);
+      else if (coreFoundation::isCFObjectRef(RetTy)) {
+        // ObjCMethodDecl currently doesn't consider CF objects as valid return
+        // values for alloc, new, copy, or mutableCopy, so we have to
+        // double-check with the selector. This is ugly, but there aren't that
+        // many Objective-C methods that return CF objects, right?
+        if (MD) {
+          switch (S.getMethodFamily()) {
+          case OMF_alloc:
+          case OMF_new:
+          case OMF_copy:
+          case OMF_mutableCopy:
+            ResultEff = RetEffect::MakeOwned(ObjKind::CF);
+            break;
+          default:
+            ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
+            break;
+          }
+        } else {
+          ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
+        }
+      }
+      break;
+    case OMF_init:
+      ResultEff = ObjCInitRetE;
+      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
+      break;
+    case OMF_alloc:
+    case OMF_new:
+    case OMF_copy:
+    case OMF_mutableCopy:
+      if (cocoa::isCocoaObjectRef(RetTy))
+        ResultEff = ObjCAllocRetE;
+      else if (coreFoundation::isCFObjectRef(RetTy))
+        ResultEff = RetEffect::MakeOwned(ObjKind::CF);
+      break;
+    case OMF_autorelease:
+      ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC);
+      break;
+    case OMF_retain:
+      ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC);
+      break;
+    case OMF_release:
+      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
+      break;
+    case OMF_dealloc:
+      ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC);
+      break;
+    case OMF_self:
+      // -self is handled specially by the ExprEngine to propagate the receiver.
+      break;
+    case OMF_retainCount:
+    case OMF_finalize:
+      // These methods don't return objects.
+      break;
+  }
+
+  // If one of the arguments in the selector has the keyword 'delegate' we
+  // should stop tracking the reference count for the receiver.  This is
+  // because the reference count is quite possibly handled by a delegate
+  // method.
+  if (S.isKeywordSelector()) {
+    for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
+      StringRef Slot = S.getNameForSlot(i);
+      if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
+        if (ResultEff == ObjCInitRetE)
+          ResultEff = RetEffect::MakeNoRetHard();
+        else
+          ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC);
+      }
+    }
+  }
+
+  if (ReceiverEff.getKind() == DoNothing &&
+      ResultEff.getKind() == RetEffect::NoRet)
+    return getDefaultSummary();
+
+  return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),
+                              ArgEffect(ReceiverEff), ArgEffect(MayEscape));
+}
+
+const RetainSummary *
+RetainSummaryManager::getClassMethodSummary(const ObjCMessageExpr *ME) {
+  assert(!ME->isInstanceMessage());
+  const ObjCInterfaceDecl *Class = ME->getReceiverInterface();
+
+  return getMethodSummary(ME->getSelector(), Class, ME->getMethodDecl(),
+                          ME->getType(), ObjCClassMethodSummaries);
+}
+
+const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
+    const ObjCMessageExpr *ME,
+    QualType ReceiverType) {
+  const ObjCInterfaceDecl *ReceiverClass = nullptr;
+
+  // We do better tracking of the type of the object than the core ExprEngine.
+  // See if we have its type in our private state.
+  if (!ReceiverType.isNull())
+    if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
+      ReceiverClass = PT->getInterfaceDecl();
+
+  // If we don't know what kind of object this is, fall back to its static type.
+  if (!ReceiverClass)
+    ReceiverClass = ME->getReceiverInterface();
+
+  // FIXME: The receiver could be a reference to a class, meaning that
+  //  we should use the class method.
+  // id x = [NSObject class];
+  // [x performSelector:... withObject:... afterDelay:...];
+  Selector S = ME->getSelector();
+  const ObjCMethodDecl *Method = ME->getMethodDecl();
+  if (!Method && ReceiverClass)
+    Method = ReceiverClass->getInstanceMethod(S);
+
+  return getMethodSummary(S, ReceiverClass, Method, ME->getType(),
+                          ObjCMethodSummaries);
+}
+
+const RetainSummary *
+RetainSummaryManager::getMethodSummary(Selector S,
+                                       const ObjCInterfaceDecl *ID,
+                                       const ObjCMethodDecl *MD, QualType RetTy,
+                                       ObjCMethodSummariesTy &CachedSummaries) {
+
+  // Objective-C method summaries are only applicable to ObjC and CF objects.
+  if (!TrackObjCAndCFObjects)
+    return getDefaultSummary();
+
+  // Look up a summary in our summary cache.
+  const RetainSummary *Summ = CachedSummaries.find(ID, S);
+
+  if (!Summ) {
+    Summ = getStandardMethodSummary(MD, S, RetTy);
+
+    // Annotations override defaults.
+    updateSummaryFromAnnotations(Summ, MD);
+
+    // Memoize the summary.
+    CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
+  }
+
+  return Summ;
+}
+
+void RetainSummaryManager::InitializeClassMethodSummaries() {
+  ArgEffects ScratchArgs = AF.getEmptyMap();
+
+  // Create the [NSAssertionHandler currentHander] summary.
+  addClassMethSummary("NSAssertionHandler", "currentHandler",
+                getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::ObjC),
+                                     ScratchArgs));
+
+  // Create the [NSAutoreleasePool addObject:] summary.
+  ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));
+  addClassMethSummary("NSAutoreleasePool", "addObject",
+                      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+                                           ArgEffect(DoNothing),
+                                           ArgEffect(Autorelease)));
+}
+
+void RetainSummaryManager::InitializeMethodSummaries() {
+
+  ArgEffects ScratchArgs = AF.getEmptyMap();
+  // Create the "init" selector.  It just acts as a pass-through for the
+  // receiver.
+  const RetainSummary *InitSumm = getPersistentSummary(
+      ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC));
+  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
+
+  // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
+  // claims the receiver and returns a retained object.
+  addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
+                         InitSumm);
+
+  // The next methods are allocators.
+  const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,
+                                                        ScratchArgs);
+  const RetainSummary *CFAllocSumm =
+    getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs);
+
+  // Create the "retain" selector.
+  RetEffect NoRet = RetEffect::MakeNoRet();
+  const RetainSummary *Summ = getPersistentSummary(
+      NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC));
+  addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
+
+  // Create the "release" selector.
+  Summ = getPersistentSummary(NoRet, ScratchArgs,
+                              ArgEffect(DecRef, ObjKind::ObjC));
+  addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
+
+  // Create the -dealloc summary.
+  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc,
+                                                            ObjKind::ObjC));
+  addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
+
+  // Create the "autorelease" selector.
+  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease,
+                                                            ObjKind::ObjC));
+  addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
+
+  // For NSWindow, allocated objects are (initially) self-owned.
+  // FIXME: For now we opt for false negatives with NSWindow, as these objects
+  //  self-own themselves.  However, they only do this once they are displayed.
+  //  Thus, we need to track an NSWindow's display status.
+  //  This is tracked in <rdar://problem/6062711>.
+  //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
+  const RetainSummary *NoTrackYet =
+      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+                           ArgEffect(StopTracking), ArgEffect(StopTracking));
+
+  addClassMethSummary("NSWindow", "alloc", NoTrackYet);
+
+  // For NSPanel (which subclasses NSWindow), allocated objects are not
+  //  self-owned.
+  // FIXME: For now we don't track NSPanels. object for the same reason
+  //   as for NSWindow objects.
+  addClassMethSummary("NSPanel", "alloc", NoTrackYet);
+
+  // For NSNull, objects returned by +null are singletons that ignore
+  // retain/release semantics.  Just don't track them.
+  // <rdar://problem/12858915>
+  addClassMethSummary("NSNull", "null", NoTrackYet);
+
+  // Don't track allocated autorelease pools, as it is okay to prematurely
+  // exit a method.
+  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
+  addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
+  addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
+
+  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
+  addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
+  addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
+
+  // Create summaries for CIContext, 'createCGImage' and
+  // 'createCGLayerWithSize'.  These objects are CF objects, and are not
+  // automatically garbage collected.
+  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
+  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
+                     "format", "colorSpace");
+  addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
+}
+
+const RetainSummary *
+RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {
+  const ObjCInterfaceDecl *ID = MD->getClassInterface();
+  Selector S = MD->getSelector();
+  QualType ResultTy = MD->getReturnType();
+
+  ObjCMethodSummariesTy *CachedSummaries;
+  if (MD->isInstanceMethod())
+    CachedSummaries = &ObjCMethodSummaries;
+  else
+    CachedSummaries = &ObjCClassMethodSummaries;
+
+  return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
+}
+
+CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
+  ASTContext &Ctx = MD->getASTContext();
+  RetainSummaryManager M(Ctx,
+                         /*TrackNSAndCFObjects=*/true,
+                         /*TrackOSObjects=*/false);
+  const RetainSummary *S = M.getMethodSummary(MD);
+  CallEffects CE(S->getRetEffect(), S->getReceiverEffect());
+  unsigned N = MD->param_size();
+  for (unsigned i = 0; i < N; ++i) {
+    CE.Args.push_back(S->getArg(i));
+  }
+  return CE;
+}
+
+CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
+  ASTContext &Ctx = FD->getASTContext();
+  RetainSummaryManager M(Ctx,
+                         /*TrackNSAndCFObjects=*/true,
+                         /*TrackOSObjects=*/false);
+  const RetainSummary *S = M.getFunctionSummary(FD);
+  CallEffects CE(S->getRetEffect());
+  unsigned N = FD->param_size();
+  for (unsigned i = 0; i < N; ++i) {
+    CE.Args.push_back(S->getArg(i));
+  }
+  return CE;
+}

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Thu Jan 24 17:24:04 2019
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "RetainCountChecker.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 
 using namespace clang;
 using namespace ento;
@@ -326,6 +327,31 @@ void RetainCountChecker::checkPostStmt(c
   C.addTransition(State);
 }
 
+static bool isReceiverUnconsumedSelf(const CallEvent &Call) {
+  if (const auto *MC = dyn_cast<ObjCMethodCall>(&Call)) {
+
+    // Check if the message is not consumed, we know it will not be used in
+    // an assignment, ex: "self = [super init]".
+    return MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper() &&
+           !Call.getLocationContext()
+                ->getAnalysisDeclContext()
+                ->getParentMap()
+                .isConsumedExpr(Call.getOriginExpr());
+  }
+  return false;
+}
+
+const static RetainSummary *getSummary(RetainSummaryManager &Summaries,
+                                       const CallEvent &Call,
+                                       QualType ReceiverType) {
+  const Expr *CE = Call.getOriginExpr();
+  AnyCall C =
+      CE ? *AnyCall::forExpr(CE)
+         : AnyCall::forDestructorCall(cast<CXXDestructorDecl>(Call.getDecl()));
+  return Summaries.getSummary(C, Call.hasNonZeroCallbackArg(),
+                              isReceiverUnconsumedSelf(Call), ReceiverType);
+}
+
 void RetainCountChecker::checkPostCall(const CallEvent &Call,
                                        CheckerContext &C) const {
   RetainSummaryManager &Summaries = getSummaryManager(C);
@@ -341,7 +367,7 @@ void RetainCountChecker::checkPostCall(c
     }
   }
 
-  const RetainSummary *Summ = Summaries.getSummary(Call, ReceiverType);
+  const RetainSummary *Summ = getSummary(Summaries, Call, ReceiverType);
 
   if (C.wasInlined) {
     processSummaryOfInlined(*Summ, Call, C);

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h Thu Jan 24 17:24:04 2019
@@ -21,6 +21,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/ParentMap.h"
 #include "clang/Analysis/DomainSpecific/CocoaConventions.h"
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/Basic/LangOptions.h"
 #include "clang/Basic/SourceManager.h"
 #include "clang/Analysis/SelectorExtras.h"
@@ -32,7 +33,6 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/ImmutableList.h"
@@ -275,15 +275,9 @@ public:
   RetainCountChecker() {};
 
   RetainSummaryManager &getSummaryManager(ASTContext &Ctx) const {
-    // FIXME: We don't support ARC being turned on and off during one analysis.
-    // (nor, for that matter, do we support changing ASTContexts)
-    bool ARCEnabled = (bool)Ctx.getLangOpts().ObjCAutoRefCount;
-    if (!Summaries) {
-      Summaries.reset(new RetainSummaryManager(
-          Ctx, ARCEnabled, TrackObjCAndCFObjects, TrackOSObjects));
-    } else {
-      assert(Summaries->isARCEnabled() == ARCEnabled);
-    }
+    if (!Summaries)
+      Summaries.reset(
+          new RetainSummaryManager(Ctx, TrackObjCAndCFObjects, TrackOSObjects));
     return *Summaries;
   }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.h Thu Jan 24 17:24:04 2019
@@ -14,10 +14,11 @@
 #ifndef LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
 #define LLVM_CLANG_LIB_STATICANALYZER_CHECKERS_RETAINCOUNTCHECKER_DIAGNOSTICS_H
 
+#include "clang/Analysis/RetainSummaryManager.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 
 namespace clang {
 namespace ento {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt?rev=352149&r1=352148&r2=352149&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CMakeLists.txt Thu Jan 24 17:24:04 2019
@@ -43,7 +43,6 @@ add_clang_library(clangStaticAnalyzerCor
   RangeConstraintManager.cpp
   RangedConstraintManager.cpp
   RegionStore.cpp
-  RetainSummaryManager.cpp
   SarifDiagnostics.cpp
   SimpleConstraintManager.cpp
   SimpleSValBuilder.cpp

Removed: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp?rev=352148&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (removed)
@@ -1,1251 +0,0 @@
-//== RetainSummaryManager.cpp - 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, Cocoa
-//  and OSObject (on Mac OS X).
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/StaticAnalyzer/Core/RetainSummaryManager.h"
-#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
-#include "clang/AST/Attr.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-
-using namespace clang;
-using namespace ento;
-
-template <class T>
-constexpr static bool isOneOf() {
-  return false;
-}
-
-/// Helper function to check whether the class is one of the
-/// rest of varargs.
-template <class T, class P, class... ToCompare>
-constexpr static bool isOneOf() {
-  return std::is_same<T, P>::value || isOneOf<T, ToCompare...>();
-}
-
-namespace {
-
-/// Fake attribute class for RC* attributes.
-struct GeneralizedReturnsRetainedAttr {
-  static bool classof(const Attr *A) {
-    if (auto AA = dyn_cast<AnnotateAttr>(A))
-      return AA->getAnnotation() == "rc_ownership_returns_retained";
-    return false;
-  }
-};
-
-struct GeneralizedReturnsNotRetainedAttr {
-  static bool classof(const Attr *A) {
-    if (auto AA = dyn_cast<AnnotateAttr>(A))
-      return AA->getAnnotation() == "rc_ownership_returns_not_retained";
-    return false;
-  }
-};
-
-struct GeneralizedConsumedAttr {
-  static bool classof(const Attr *A) {
-    if (auto AA = dyn_cast<AnnotateAttr>(A))
-      return AA->getAnnotation() == "rc_ownership_consumed";
-    return false;
-  }
-};
-
-}
-
-template <class T>
-Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
-                                                            QualType QT) {
-  ObjKind K;
-  if (isOneOf<T, CFConsumedAttr, CFReturnsRetainedAttr,
-              CFReturnsNotRetainedAttr>()) {
-    if (!TrackObjCAndCFObjects)
-      return None;
-
-    K = ObjKind::CF;
-  } else if (isOneOf<T, NSConsumedAttr, NSConsumesSelfAttr,
-                     NSReturnsAutoreleasedAttr, NSReturnsRetainedAttr,
-                     NSReturnsNotRetainedAttr, NSConsumesSelfAttr>()) {
-
-    if (!TrackObjCAndCFObjects)
-      return None;
-
-    if (isOneOf<T, NSReturnsRetainedAttr, NSReturnsAutoreleasedAttr,
-                NSReturnsNotRetainedAttr>() &&
-        !cocoa::isCocoaObjectRef(QT))
-      return None;
-    K = ObjKind::ObjC;
-  } else if (isOneOf<T, OSConsumedAttr, OSConsumesThisAttr,
-                     OSReturnsNotRetainedAttr, OSReturnsRetainedAttr,
-                     OSReturnsRetainedOnZeroAttr,
-                     OSReturnsRetainedOnNonZeroAttr>()) {
-    if (!TrackOSObjects)
-      return None;
-    K = ObjKind::OS;
-  } else if (isOneOf<T, GeneralizedReturnsNotRetainedAttr,
-                     GeneralizedReturnsRetainedAttr,
-                     GeneralizedConsumedAttr>()) {
-    K = ObjKind::Generalized;
-  } else {
-    llvm_unreachable("Unexpected attribute");
-  }
-  if (D->hasAttr<T>())
-    return K;
-  return None;
-}
-
-template <class T1, class T2, class... Others>
-Optional<ObjKind> RetainSummaryManager::hasAnyEnabledAttrOf(const Decl *D,
-                                                            QualType QT) {
-  if (auto Out = hasAnyEnabledAttrOf<T1>(D, QT))
-    return Out;
-  return hasAnyEnabledAttrOf<T2, Others...>(D, QT);
-}
-
-const RetainSummary *
-RetainSummaryManager::getPersistentSummary(const RetainSummary &OldSumm) {
-  // Unique "simple" summaries -- those without ArgEffects.
-  if (OldSumm.isSimple()) {
-    ::llvm::FoldingSetNodeID ID;
-    OldSumm.Profile(ID);
-
-    void *Pos;
-    CachedSummaryNode *N = SimpleSummaries.FindNodeOrInsertPos(ID, Pos);
-
-    if (!N) {
-      N = (CachedSummaryNode *) BPAlloc.Allocate<CachedSummaryNode>();
-      new (N) CachedSummaryNode(OldSumm);
-      SimpleSummaries.InsertNode(N, Pos);
-    }
-
-    return &N->getValue();
-  }
-
-  RetainSummary *Summ = (RetainSummary *) BPAlloc.Allocate<RetainSummary>();
-  new (Summ) RetainSummary(OldSumm);
-  return Summ;
-}
-
-static bool isSubclass(const Decl *D,
-                       StringRef ClassName) {
-  using namespace ast_matchers;
-  DeclarationMatcher SubclassM = cxxRecordDecl(isSameOrDerivedFrom(ClassName));
-  return !(match(SubclassM, *D, D->getASTContext()).empty());
-}
-
-static bool isOSObjectSubclass(const Decl *D) {
-  return isSubclass(D, "OSMetaClassBase");
-}
-
-static bool isOSObjectDynamicCast(StringRef S) {
-  return S == "safeMetaCast";
-}
-
-static bool isOSObjectThisCast(StringRef S) {
-  return S == "metaCast";
-}
-
-static bool isOSIteratorSubclass(const Decl *D) {
-  return isSubclass(D, "OSIterator");
-}
-
-static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
-  for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
-    if (Ann->getAnnotation() == rcAnnotation)
-      return true;
-  }
-  return false;
-}
-
-static bool isRetain(const FunctionDecl *FD, StringRef FName) {
-  return FName.startswith_lower("retain") || FName.endswith_lower("retain");
-}
-
-static bool isRelease(const FunctionDecl *FD, StringRef FName) {
-  return FName.startswith_lower("release") || FName.endswith_lower("release");
-}
-
-static bool isAutorelease(const FunctionDecl *FD, StringRef FName) {
-  return FName.startswith_lower("autorelease") ||
-         FName.endswith_lower("autorelease");
-}
-
-static bool isMakeCollectable(StringRef FName) {
-  return FName.contains_lower("MakeCollectable");
-}
-
-/// A function is OSObject related if it is declared on a subclass
-/// of OSObject, or any of the parameters is a subclass of an OSObject.
-static bool isOSObjectRelated(const CXXMethodDecl *MD) {
-  if (isOSObjectSubclass(MD->getParent()))
-    return true;
-
-  for (ParmVarDecl *Param : MD->parameters()) {
-    QualType PT = Param->getType()->getPointeeType();
-    if (!PT.isNull())
-      if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl())
-        if (isOSObjectSubclass(RD))
-          return true;
-  }
-
-  return false;
-}
-
-bool
-RetainSummaryManager::isKnownSmartPointer(QualType QT) {
-  QT = QT.getCanonicalType();
-  const auto *RD = QT->getAsCXXRecordDecl();
-  if (!RD)
-    return false;
-  const IdentifierInfo *II = RD->getIdentifier();
-  if (II && II->getName() == "smart_ptr")
-    if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext()))
-      if (ND->getNameAsString() == "os")
-        return true;
-  return false;
-}
-
-const RetainSummary *
-RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,
-                                            StringRef FName, QualType RetTy) {
-  if (RetTy->isPointerType()) {
-    const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
-    if (PD && isOSObjectSubclass(PD)) {
-      if (const IdentifierInfo *II = FD->getIdentifier()) {
-        StringRef FuncName = II->getName();
-        if (isOSObjectDynamicCast(FuncName) || isOSObjectThisCast(FuncName))
-          return getDefaultSummary();
-
-        // All objects returned with functions *not* starting with
-        // get, or iterators, are returned at +1.
-        if ((!FuncName.startswith("get") && !FuncName.startswith("Get")) ||
-            isOSIteratorSubclass(PD)) {
-          return getOSSummaryCreateRule(FD);
-        } else {
-          return getOSSummaryGetRule(FD);
-        }
-      }
-    }
-  }
-
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
-    const CXXRecordDecl *Parent = MD->getParent();
-    if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) {
-      if (FName == "release")
-        return getOSSummaryReleaseRule(FD);
-
-      if (FName == "retain")
-        return getOSSummaryRetainRule(FD);
-
-      if (FName == "free")
-        return getOSSummaryFreeRule(FD);
-
-      if (MD->getOverloadedOperator() == OO_New)
-        return getOSSummaryCreateRule(MD);
-    }
-  }
-
-  return nullptr;
-}
-
-const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
-    const FunctionDecl *FD,
-    StringRef FName,
-    QualType RetTy,
-    const FunctionType *FT,
-    bool &AllowAnnotations) {
-
-  ArgEffects ScratchArgs(AF.getEmptyMap());
-
-  std::string RetTyName = RetTy.getAsString();
-  if (FName == "pthread_create" || FName == "pthread_setspecific") {
-    // Part of: <rdar://problem/7299394> and <rdar://problem/11282706>.
-    // This will be addressed better with IPA.
-    return getPersistentStopSummary();
-  } else if(FName == "NSMakeCollectable") {
-    // Handle: id NSMakeCollectable(CFTypeRef)
-    AllowAnnotations = false;
-    return RetTy->isObjCIdType() ? getUnarySummary(FT, DoNothing)
-                                 : getPersistentStopSummary();
-  } else if (FName == "CMBufferQueueDequeueAndRetain" ||
-             FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
-    // Part of: <rdar://problem/39390714>.
-    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
-                                ScratchArgs,
-                                ArgEffect(DoNothing),
-                                ArgEffect(DoNothing));
-  } else if (FName == "CFPlugInInstanceCreate") {
-    return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs);
-  } else if (FName == "IORegistryEntrySearchCFProperty" ||
-             (RetTyName == "CFMutableDictionaryRef" &&
-              (FName == "IOBSDNameMatching" || FName == "IOServiceMatching" ||
-               FName == "IOServiceNameMatching" ||
-               FName == "IORegistryEntryIDMatching" ||
-               FName == "IOOpenFirmwarePathMatching"))) {
-    // Part of <rdar://problem/6961230>. (IOKit)
-    // This should be addressed using a API table.
-    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "IOServiceGetMatchingService" ||
-             FName == "IOServiceGetMatchingServices") {
-    // FIXES: <rdar://problem/6326900>
-    // This should be addressed using a API table.  This strcmp is also
-    // a little gross, but there is no need to super optimize here.
-    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "IOServiceAddNotification" ||
-             FName == "IOServiceAddMatchingNotification") {
-    // Part of <rdar://problem/6961230>. (IOKit)
-    // This should be addressed using a API table.
-    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "CVPixelBufferCreateWithBytes") {
-    // FIXES: <rdar://problem/7283567>
-    // Eventually this can be improved by recognizing that the pixel
-    // buffer passed to CVPixelBufferCreateWithBytes is released via
-    // a callback and doing full IPA to make sure this is done correctly.
-    // FIXME: This function has an out parameter that returns an
-    // allocated object.
-    ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "CGBitmapContextCreateWithData") {
-    // FIXES: <rdar://problem/7358899>
-    // Eventually this can be improved by recognizing that 'releaseInfo'
-    // passed to CGBitmapContextCreateWithData is released via
-    // a callback and doing full IPA to make sure this is done correctly.
-    ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
-    return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
-    // FIXES: <rdar://problem/7283567>
-    // Eventually this can be improved by recognizing that the pixel
-    // buffer passed to CVPixelBufferCreateWithPlanarBytes is released
-    // via a callback and doing full IPA to make sure this is done
-    // correctly.
-    ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "VTCompressionSessionEncodeFrame") {
-    // The context argument passed to VTCompressionSessionEncodeFrame()
-    // is passed to the callback specified when creating the session
-    // (e.g. with VTCompressionSessionCreate()) which can release it.
-    // To account for this possibility, conservatively stop tracking
-    // the context.
-    ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName == "dispatch_set_context" ||
-             FName == "xpc_connection_set_context") {
-    // <rdar://problem/11059275> - The analyzer currently doesn't have
-    // a good way to reason about the finalizer function for libdispatch.
-    // If we pass a context object that is memory managed, stop tracking it.
-    // <rdar://problem/13783514> - Same problem, but for XPC.
-    // FIXME: this hack should possibly go away once we can handle
-    // libdispatch and XPC finalizers.
-    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs,
-                                ArgEffect(DoNothing), ArgEffect(DoNothing));
-  } else if (FName.startswith("NSLog")) {
-    return getDoNothingSummary();
-  } else if (FName.startswith("NS") &&
-             (FName.find("Insert") != StringRef::npos)) {
-    // Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
-    // be deallocated by NSMapRemove. (radar://11152419)
-    ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
-    ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));
-    return getPersistentSummary(RetEffect::MakeNoRet(),
-                                ScratchArgs, ArgEffect(DoNothing),
-                                ArgEffect(DoNothing));
-  }
-
-  if (RetTy->isPointerType()) {
-
-    // For CoreFoundation ('CF') types.
-    if (cocoa::isRefType(RetTy, "CF", FName)) {
-      if (isRetain(FD, FName)) {
-        // CFRetain isn't supposed to be annotated. However, this may as
-        // well be a user-made "safe" CFRetain function that is incorrectly
-        // annotated as cf_returns_retained due to lack of better options.
-        // We want to ignore such annotation.
-        AllowAnnotations = false;
-
-        return getUnarySummary(FT, IncRef);
-      } else if (isAutorelease(FD, FName)) {
-        // The headers use cf_consumed, but we can fully model CFAutorelease
-        // ourselves.
-        AllowAnnotations = false;
-
-        return getUnarySummary(FT, Autorelease);
-      } else if (isMakeCollectable(FName)) {
-        AllowAnnotations = false;
-        return getUnarySummary(FT, DoNothing);
-      } else {
-        return getCFCreateGetRuleSummary(FD);
-      }
-    }
-
-    // For CoreGraphics ('CG') and CoreVideo ('CV') types.
-    if (cocoa::isRefType(RetTy, "CG", FName) ||
-        cocoa::isRefType(RetTy, "CV", FName)) {
-      if (isRetain(FD, FName))
-        return getUnarySummary(FT, IncRef);
-      else
-        return getCFCreateGetRuleSummary(FD);
-    }
-
-    // For all other CF-style types, use the Create/Get
-    // rule for summaries but don't support Retain functions
-    // with framework-specific prefixes.
-    if (coreFoundation::isCFObjectRef(RetTy)) {
-      return getCFCreateGetRuleSummary(FD);
-    }
-
-    if (FD->hasAttr<CFAuditedTransferAttr>()) {
-      return getCFCreateGetRuleSummary(FD);
-    }
-  }
-
-  // Check for release functions, the only kind of functions that we care
-  // about that don't return a pointer type.
-  if (FName.startswith("CG") || FName.startswith("CF")) {
-    // Test for 'CGCF'.
-    FName = FName.substr(FName.startswith("CGCF") ? 4 : 2);
-
-    if (isRelease(FD, FName))
-      return getUnarySummary(FT, DecRef);
-    else {
-      assert(ScratchArgs.isEmpty());
-      // Remaining CoreFoundation and CoreGraphics functions.
-      // We use to assume that they all strictly followed the ownership idiom
-      // and that ownership cannot be transferred.  While this is technically
-      // correct, many methods allow a tracked object to escape.  For example:
-      //
-      //   CFMutableDictionaryRef x = CFDictionaryCreateMutable(...);
-      //   CFDictionaryAddValue(y, key, x);
-      //   CFRelease(x);
-      //   ... it is okay to use 'x' since 'y' has a reference to it
-      //
-      // We handle this and similar cases with the follow heuristic.  If the
-      // function name contains "InsertValue", "SetValue", "AddValue",
-      // "AppendValue", or "SetAttribute", then we assume that arguments may
-      // "escape."  This means that something else holds on to the object,
-      // allowing it be used even after its local retain count drops to 0.
-      ArgEffectKind E =
-          (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
-           StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
-           StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
-           StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
-           StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
-              ? MayEscape
-              : DoNothing;
-
-      return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
-                                  ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF));
-    }
-  }
-
-  return nullptr;
-}
-
-const RetainSummary *
-RetainSummaryManager::generateSummary(const FunctionDecl *FD,
-                                      bool &AllowAnnotations) {
-  // We generate "stop" summaries for implicitly defined functions.
-  if (FD->isImplicit())
-    return getPersistentStopSummary();
-
-  const IdentifierInfo *II = FD->getIdentifier();
-
-  StringRef FName = II ? II->getName() : "";
-
-  // Strip away preceding '_'.  Doing this here will effect all the checks
-  // down below.
-  FName = FName.substr(FName.find_first_not_of('_'));
-
-  // Inspect the result type. Strip away any typedefs.
-  const auto *FT = FD->getType()->getAs<FunctionType>();
-  QualType RetTy = FT->getReturnType();
-
-  if (TrackOSObjects)
-    if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
-      return S;
-
-  if (TrackObjCAndCFObjects)
-    if (const RetainSummary *S =
-            getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
-      return S;
-
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
-    if (!(TrackOSObjects && isOSObjectRelated(MD)))
-      return getPersistentSummary(RetEffect::MakeNoRet(),
-                                  ArgEffects(AF.getEmptyMap()),
-                                  ArgEffect(DoNothing),
-                                  ArgEffect(StopTracking),
-                                  ArgEffect(DoNothing));
-
-  return getDefaultSummary();
-}
-
-const RetainSummary *
-RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
-  // If we don't know what function we're calling, use our default summary.
-  if (!FD)
-    return getDefaultSummary();
-
-  // Look up a summary in our cache of FunctionDecls -> Summaries.
-  FuncSummariesTy::iterator I = FuncSummaries.find(FD);
-  if (I != FuncSummaries.end())
-    return I->second;
-
-  // No summary?  Generate one.
-  bool AllowAnnotations = true;
-  const RetainSummary *S = generateSummary(FD, AllowAnnotations);
-
-  // Annotations override defaults.
-  if (AllowAnnotations)
-    updateSummaryFromAnnotations(S, FD);
-
-  FuncSummaries[FD] = S;
-  return S;
-}
-
-//===----------------------------------------------------------------------===//
-// Summary creation for functions (largely uses of Core Foundation).
-//===----------------------------------------------------------------------===//
-
-static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
-  switch (E.getKind()) {
-  case DoNothing:
-  case Autorelease:
-  case DecRefBridgedTransferred:
-  case IncRef:
-  case UnretainedOutParameter:
-  case RetainedOutParameter:
-  case RetainedOutParameterOnZero:
-  case RetainedOutParameterOnNonZero:
-  case MayEscape:
-  case StopTracking:
-  case StopTrackingHard:
-    return E.withKind(StopTrackingHard);
-  case DecRef:
-  case DecRefAndStopTrackingHard:
-    return E.withKind(DecRefAndStopTrackingHard);
-  case Dealloc:
-    return E.withKind(Dealloc);
-  }
-
-  llvm_unreachable("Unknown ArgEffect kind");
-}
-
-void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
-                                                const CallEvent &Call) {
-  if (Call.hasNonZeroCallbackArg()) {
-    ArgEffect RecEffect =
-      getStopTrackingHardEquivalent(S->getReceiverEffect());
-    ArgEffect DefEffect =
-      getStopTrackingHardEquivalent(S->getDefaultArgEffect());
-
-    ArgEffects ScratchArgs(AF.getEmptyMap());
-    ArgEffects CustomArgEffects = S->getArgEffects();
-    for (ArgEffects::iterator I = CustomArgEffects.begin(),
-                              E = CustomArgEffects.end();
-         I != E; ++I) {
-      ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
-      if (Translated.getKind() != DefEffect.getKind())
-        ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
-    }
-
-    RetEffect RE = RetEffect::MakeNoRetHard();
-
-    // Special cases where the callback argument CANNOT free the return value.
-    // This can generally only happen if we know that the callback will only be
-    // called when the return value is already being deallocated.
-    if (const SimpleFunctionCall *FC = dyn_cast<SimpleFunctionCall>(&Call)) {
-      if (IdentifierInfo *Name = FC->getDecl()->getIdentifier()) {
-        // When the CGBitmapContext is deallocated, the callback here will free
-        // the associated data buffer.
-        // The callback in dispatch_data_create frees the buffer, but not
-        // the data object.
-        if (Name->isStr("CGBitmapContextCreateWithData") ||
-            Name->isStr("dispatch_data_create"))
-          RE = S->getRetEffect();
-      }
-    }
-
-    S = getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
-  }
-
-  // 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.
-  if (const ObjCMethodCall *MC = dyn_cast<ObjCMethodCall>(&Call)) {
-    if (MC->getMethodFamily() == OMF_init && MC->isReceiverSelfOrSuper()) {
-
-      // Check if the message is not consumed, we know it will not be used in
-      // an assignment, ex: "self = [super init]".
-      const Expr *ME = MC->getOriginExpr();
-      const LocationContext *LCtx = MC->getLocationContext();
-      ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
-      if (!PM.isConsumedExpr(ME)) {
-        RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
-        ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
-        ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
-      }
-    }
-  }
-}
-
-const RetainSummary *
-RetainSummaryManager::getSummary(const CallEvent &Call,
-                                 QualType ReceiverType) {
-  const RetainSummary *Summ;
-  switch (Call.getKind()) {
-  case CE_Function:
-  case CE_CXXMember:
-  case CE_CXXMemberOperator:
-  case CE_CXXConstructor:
-  case CE_CXXAllocator:
-    Summ = getFunctionSummary(cast_or_null<FunctionDecl>(Call.getDecl()));
-    break;
-  case CE_Block:
-  case CE_CXXDestructor:
-    // FIXME: These calls are currently unsupported.
-    return getPersistentStopSummary();
-  case CE_ObjCMessage: {
-    const ObjCMethodCall &Msg = cast<ObjCMethodCall>(Call);
-    if (Msg.isInstanceMessage())
-      Summ = getInstanceMethodSummary(Msg, ReceiverType);
-    else
-      Summ = getClassMethodSummary(Msg);
-    break;
-  }
-  }
-
-  updateSummaryForCall(Summ, Call);
-
-  assert(Summ && "Unknown call type?");
-  return Summ;
-}
-
-
-const RetainSummary *
-RetainSummaryManager::getCFCreateGetRuleSummary(const FunctionDecl *FD) {
-  if (coreFoundation::followsCreateRule(FD))
-    return getCFSummaryCreateRule(FD);
-
-  return getCFSummaryGetRule(FD);
-}
-
-bool RetainSummaryManager::isTrustedReferenceCountImplementation(
-    const FunctionDecl *FD) {
-  return hasRCAnnotation(FD, "rc_ownership_trusted_implementation");
-}
-
-Optional<RetainSummaryManager::BehaviorSummary>
-RetainSummaryManager::canEval(const CallExpr *CE, const FunctionDecl *FD,
-                              bool &hasTrustedImplementationAnnotation) {
-
-  IdentifierInfo *II = FD->getIdentifier();
-  if (!II)
-    return None;
-
-  StringRef FName = II->getName();
-  FName = FName.substr(FName.find_first_not_of('_'));
-
-  QualType ResultTy = CE->getCallReturnType(Ctx);
-  if (ResultTy->isObjCIdType()) {
-    if (II->isStr("NSMakeCollectable"))
-      return BehaviorSummary::Identity;
-  } else if (ResultTy->isPointerType()) {
-    // Handle: (CF|CG|CV)Retain
-    //         CFAutorelease
-    // It's okay to be a little sloppy here.
-    if (FName == "CMBufferQueueDequeueAndRetain" ||
-        FName == "CMBufferQueueDequeueIfDataReadyAndRetain") {
-      // Part of: <rdar://problem/39390714>.
-      // These are not retain. They just return something and retain it.
-      return None;
-    }
-    if (cocoa::isRefType(ResultTy, "CF", FName) ||
-        cocoa::isRefType(ResultTy, "CG", FName) ||
-        cocoa::isRefType(ResultTy, "CV", FName))
-      if (isRetain(FD, FName) || isAutorelease(FD, FName) ||
-          isMakeCollectable(FName))
-        return BehaviorSummary::Identity;
-
-    // safeMetaCast is called by OSDynamicCast.
-    // We assume that OSDynamicCast is either an identity (cast is OK,
-    // the input was non-zero),
-    // or that it returns zero (when the cast failed, or the input
-    // was zero).
-    if (TrackOSObjects) {
-      if (isOSObjectDynamicCast(FName) && FD->param_size() >= 1) {
-        return BehaviorSummary::IdentityOrZero;
-      } else if (isOSObjectThisCast(FName) && isa<CXXMethodDecl>(FD) &&
-                 !cast<CXXMethodDecl>(FD)->isStatic()) {
-        return BehaviorSummary::IdentityThis;
-      }
-    }
-
-    const FunctionDecl* FDD = FD->getDefinition();
-    if (FDD && isTrustedReferenceCountImplementation(FDD)) {
-      hasTrustedImplementationAnnotation = true;
-      return BehaviorSummary::Identity;
-    }
-  }
-
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
-    const CXXRecordDecl *Parent = MD->getParent();
-    if (TrackOSObjects && Parent && isOSObjectSubclass(Parent))
-      if (FName == "release" || FName == "retain")
-        return BehaviorSummary::NoOp;
-  }
-
-  return None;
-}
-
-const RetainSummary *
-RetainSummaryManager::getUnarySummary(const FunctionType* FT,
-                                      ArgEffectKind AE) {
-
-  // Unary functions have no arg effects by definition.
-  ArgEffects ScratchArgs(AF.getEmptyMap());
-
-  // Sanity check that this is *really* a unary function.  This can
-  // happen if people do weird things.
-  const FunctionProtoType* FTP = dyn_cast<FunctionProtoType>(FT);
-  if (!FTP || FTP->getNumParams() != 1)
-    return getPersistentStopSummary();
-
-  ArgEffect Effect(AE, ObjKind::CF);
-
-  ScratchArgs = AF.add(ScratchArgs, 0, Effect);
-  return getPersistentSummary(RetEffect::MakeNoRet(),
-                              ScratchArgs,
-                              ArgEffect(DoNothing), ArgEffect(DoNothing));
-}
-
-const RetainSummary *
-RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeNoRet(),
-                              AF.getEmptyMap(),
-                              /*ReceiverEff=*/ArgEffect(DoNothing),
-                              /*DefaultEff=*/ArgEffect(DoNothing),
-                              /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS));
-}
-
-const RetainSummary *
-RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeNoRet(),
-                              AF.getEmptyMap(),
-                              /*ReceiverEff=*/ArgEffect(DoNothing),
-                              /*DefaultEff=*/ArgEffect(DoNothing),
-                              /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS));
-}
-
-const RetainSummary *
-RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeNoRet(),
-                              AF.getEmptyMap(),
-                              /*ReceiverEff=*/ArgEffect(DoNothing),
-                              /*DefaultEff=*/ArgEffect(DoNothing),
-                              /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS));
-}
-
-const RetainSummary *
-RetainSummaryManager::getOSSummaryCreateRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::OS),
-                              AF.getEmptyMap());
-}
-
-const RetainSummary *
-RetainSummaryManager::getOSSummaryGetRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::OS),
-                              AF.getEmptyMap());
-}
-
-const RetainSummary *
-RetainSummaryManager::getCFSummaryCreateRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
-                              ArgEffects(AF.getEmptyMap()));
-}
-
-const RetainSummary *
-RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
-  return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF),
-                              ArgEffects(AF.getEmptyMap()),
-                              ArgEffect(DoNothing), ArgEffect(DoNothing));
-}
-
-
-
-
-//===----------------------------------------------------------------------===//
-// Summary creation for Selectors.
-//===----------------------------------------------------------------------===//
-
-Optional<RetEffect>
-RetainSummaryManager::getRetEffectFromAnnotations(QualType RetTy,
-                                                  const Decl *D) {
-  if (hasAnyEnabledAttrOf<NSReturnsRetainedAttr>(D, RetTy))
-    return ObjCAllocRetE;
-
-  if (auto K = hasAnyEnabledAttrOf<CFReturnsRetainedAttr, OSReturnsRetainedAttr,
-                                   GeneralizedReturnsRetainedAttr>(D, RetTy))
-    return RetEffect::MakeOwned(*K);
-
-  if (auto K = hasAnyEnabledAttrOf<
-          CFReturnsNotRetainedAttr, OSReturnsNotRetainedAttr,
-          GeneralizedReturnsNotRetainedAttr, NSReturnsNotRetainedAttr,
-          NSReturnsAutoreleasedAttr>(D, RetTy))
-    return RetEffect::MakeNotOwned(*K);
-
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
-    for (const auto *PD : MD->overridden_methods())
-      if (auto RE = getRetEffectFromAnnotations(RetTy, PD))
-        return RE;
-
-  return None;
-}
-
-/// \return Whether the chain of typedefs starting from {@code QT}
-/// has a typedef with a given name {@code Name}.
-static bool hasTypedefNamed(QualType QT,
-                            StringRef Name) {
-  while (auto *T = dyn_cast<TypedefType>(QT)) {
-    const auto &Context = T->getDecl()->getASTContext();
-    if (T->getDecl()->getIdentifier() == &Context.Idents.get(Name))
-      return true;
-    QT = T->getDecl()->getUnderlyingType();
-  }
-  return false;
-}
-
-static QualType getCallableReturnType(const NamedDecl *ND) {
-  if (const auto *FD = dyn_cast<FunctionDecl>(ND)) {
-    return FD->getReturnType();
-  } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(ND)) {
-    return MD->getReturnType();
-  } else {
-    llvm_unreachable("Unexpected decl");
-  }
-}
-
-bool RetainSummaryManager::applyParamAnnotationEffect(
-    const ParmVarDecl *pd, unsigned parm_idx, const NamedDecl *FD,
-    RetainSummaryTemplate &Template) {
-  QualType QT = pd->getType();
-  if (auto K =
-          hasAnyEnabledAttrOf<NSConsumedAttr, CFConsumedAttr, OSConsumedAttr,
-                              GeneralizedConsumedAttr>(pd, QT)) {
-    Template->addArg(AF, parm_idx, ArgEffect(DecRef, *K));
-    return true;
-  } else if (auto K = hasAnyEnabledAttrOf<
-                 CFReturnsRetainedAttr, OSReturnsRetainedAttr,
-                 OSReturnsRetainedOnNonZeroAttr, OSReturnsRetainedOnZeroAttr,
-                 GeneralizedReturnsRetainedAttr>(pd, QT)) {
-
-    // For OSObjects, we try to guess whether the object is created based
-    // on the return value.
-    if (K == ObjKind::OS) {
-      QualType QT = getCallableReturnType(FD);
-
-      bool HasRetainedOnZero = pd->hasAttr<OSReturnsRetainedOnZeroAttr>();
-      bool HasRetainedOnNonZero = pd->hasAttr<OSReturnsRetainedOnNonZeroAttr>();
-
-      // The usual convention is to create an object on non-zero return, but
-      // it's reverted if the typedef chain has a typedef kern_return_t,
-      // because kReturnSuccess constant is defined as zero.
-      // The convention can be overwritten by custom attributes.
-      bool SuccessOnZero =
-          HasRetainedOnZero ||
-          (hasTypedefNamed(QT, "kern_return_t") && !HasRetainedOnNonZero);
-      bool ShouldSplit = !QT.isNull() && !QT->isVoidType();
-      ArgEffectKind AK = RetainedOutParameter;
-      if (ShouldSplit && SuccessOnZero) {
-        AK = RetainedOutParameterOnZero;
-      } else if (ShouldSplit && (!SuccessOnZero || HasRetainedOnNonZero)) {
-        AK = RetainedOutParameterOnNonZero;
-      }
-      Template->addArg(AF, parm_idx, ArgEffect(AK, ObjKind::OS));
-    }
-
-    // For others:
-    // Do nothing. Retained out parameters will either point to a +1 reference
-    // or NULL, but the way you check for failure differs depending on the
-    // API. Consequently, we don't have a good way to track them yet.
-    return true;
-  } else if (auto K = hasAnyEnabledAttrOf<CFReturnsNotRetainedAttr,
-                                          OSReturnsNotRetainedAttr,
-                                          GeneralizedReturnsNotRetainedAttr>(
-                 pd, QT)) {
-    Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter, *K));
-    return true;
-  }
-
-  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
-    for (const auto *OD : MD->overridden_methods()) {
-      const ParmVarDecl *OP = OD->parameters()[parm_idx];
-      if (applyParamAnnotationEffect(OP, parm_idx, OD, Template))
-        return true;
-    }
-  }
-
-  return false;
-}
-
-void
-RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
-                                                   const FunctionDecl *FD) {
-  if (!FD)
-    return;
-
-  assert(Summ && "Must have a summary to add annotations to.");
-  RetainSummaryTemplate Template(Summ, *this);
-
-  // Effects on the parameters.
-  unsigned parm_idx = 0;
-  for (auto pi = FD->param_begin(),
-         pe = FD->param_end(); pi != pe; ++pi, ++parm_idx)
-    applyParamAnnotationEffect(*pi, parm_idx, FD, Template);
-
-  QualType RetTy = FD->getReturnType();
-  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, FD))
-    Template->setRetEffect(*RetE);
-
-  if (hasAnyEnabledAttrOf<OSConsumesThisAttr>(FD, RetTy))
-    Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS));
-}
-
-void
-RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
-                                                   const ObjCMethodDecl *MD) {
-  if (!MD)
-    return;
-
-  assert(Summ && "Must have a valid summary to add annotations to");
-  RetainSummaryTemplate Template(Summ, *this);
-
-  // Effects on the receiver.
-  if (hasAnyEnabledAttrOf<NSConsumesSelfAttr>(MD, MD->getReturnType()))
-    Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC));
-
-  // Effects on the parameters.
-  unsigned parm_idx = 0;
-  for (auto pi = MD->param_begin(), pe = MD->param_end(); pi != pe;
-       ++pi, ++parm_idx)
-    applyParamAnnotationEffect(*pi, parm_idx, MD, Template);
-
-  QualType RetTy = MD->getReturnType();
-  if (Optional<RetEffect> RetE = getRetEffectFromAnnotations(RetTy, MD))
-    Template->setRetEffect(*RetE);
-}
-
-const RetainSummary *
-RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
-                                               Selector S, QualType RetTy) {
-  // Any special effects?
-  ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC);
-  RetEffect ResultEff = RetEffect::MakeNoRet();
-
-  // Check the method family, and apply any default annotations.
-  switch (MD ? MD->getMethodFamily() : S.getMethodFamily()) {
-    case OMF_None:
-    case OMF_initialize:
-    case OMF_performSelector:
-      // Assume all Objective-C methods follow Cocoa Memory Management rules.
-      // FIXME: Does the non-threaded performSelector family really belong here?
-      // The selector could be, say, @selector(copy).
-      if (cocoa::isCocoaObjectRef(RetTy))
-        ResultEff = RetEffect::MakeNotOwned(ObjKind::ObjC);
-      else if (coreFoundation::isCFObjectRef(RetTy)) {
-        // ObjCMethodDecl currently doesn't consider CF objects as valid return
-        // values for alloc, new, copy, or mutableCopy, so we have to
-        // double-check with the selector. This is ugly, but there aren't that
-        // many Objective-C methods that return CF objects, right?
-        if (MD) {
-          switch (S.getMethodFamily()) {
-          case OMF_alloc:
-          case OMF_new:
-          case OMF_copy:
-          case OMF_mutableCopy:
-            ResultEff = RetEffect::MakeOwned(ObjKind::CF);
-            break;
-          default:
-            ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
-            break;
-          }
-        } else {
-          ResultEff = RetEffect::MakeNotOwned(ObjKind::CF);
-        }
-      }
-      break;
-    case OMF_init:
-      ResultEff = ObjCInitRetE;
-      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
-      break;
-    case OMF_alloc:
-    case OMF_new:
-    case OMF_copy:
-    case OMF_mutableCopy:
-      if (cocoa::isCocoaObjectRef(RetTy))
-        ResultEff = ObjCAllocRetE;
-      else if (coreFoundation::isCFObjectRef(RetTy))
-        ResultEff = RetEffect::MakeOwned(ObjKind::CF);
-      break;
-    case OMF_autorelease:
-      ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC);
-      break;
-    case OMF_retain:
-      ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC);
-      break;
-    case OMF_release:
-      ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC);
-      break;
-    case OMF_dealloc:
-      ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC);
-      break;
-    case OMF_self:
-      // -self is handled specially by the ExprEngine to propagate the receiver.
-      break;
-    case OMF_retainCount:
-    case OMF_finalize:
-      // These methods don't return objects.
-      break;
-  }
-
-  // If one of the arguments in the selector has the keyword 'delegate' we
-  // should stop tracking the reference count for the receiver.  This is
-  // because the reference count is quite possibly handled by a delegate
-  // method.
-  if (S.isKeywordSelector()) {
-    for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
-      StringRef Slot = S.getNameForSlot(i);
-      if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
-        if (ResultEff == ObjCInitRetE)
-          ResultEff = RetEffect::MakeNoRetHard();
-        else
-          ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC);
-      }
-    }
-  }
-
-  if (ReceiverEff.getKind() == DoNothing &&
-      ResultEff.getKind() == RetEffect::NoRet)
-    return getDefaultSummary();
-
-  return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),
-                              ArgEffect(ReceiverEff), ArgEffect(MayEscape));
-}
-
-const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
-    const ObjCMethodCall &Msg,
-    QualType ReceiverType) {
-  const ObjCInterfaceDecl *ReceiverClass = nullptr;
-
-  // We do better tracking of the type of the object than the core ExprEngine.
-  // See if we have its type in our private state.
-  if (!ReceiverType.isNull())
-    if (const auto *PT = ReceiverType->getAs<ObjCObjectPointerType>())
-      ReceiverClass = PT->getInterfaceDecl();
-
-  // If we don't know what kind of object this is, fall back to its static type.
-  if (!ReceiverClass)
-    ReceiverClass = Msg.getReceiverInterface();
-
-  // FIXME: The receiver could be a reference to a class, meaning that
-  //  we should use the class method.
-  // id x = [NSObject class];
-  // [x performSelector:... withObject:... afterDelay:...];
-  Selector S = Msg.getSelector();
-  const ObjCMethodDecl *Method = Msg.getDecl();
-  if (!Method && ReceiverClass)
-    Method = ReceiverClass->getInstanceMethod(S);
-
-  return getMethodSummary(S, ReceiverClass, Method, Msg.getResultType(),
-                          ObjCMethodSummaries);
-}
-
-const RetainSummary *
-RetainSummaryManager::getMethodSummary(Selector S,
-                                       const ObjCInterfaceDecl *ID,
-                                       const ObjCMethodDecl *MD, QualType RetTy,
-                                       ObjCMethodSummariesTy &CachedSummaries) {
-
-  // Objective-C method summaries are only applicable to ObjC and CF objects.
-  if (!TrackObjCAndCFObjects)
-    return getDefaultSummary();
-
-  // Look up a summary in our summary cache.
-  const RetainSummary *Summ = CachedSummaries.find(ID, S);
-
-  if (!Summ) {
-    Summ = getStandardMethodSummary(MD, S, RetTy);
-
-    // Annotations override defaults.
-    updateSummaryFromAnnotations(Summ, MD);
-
-    // Memoize the summary.
-    CachedSummaries[ObjCSummaryKey(ID, S)] = Summ;
-  }
-
-  return Summ;
-}
-
-void RetainSummaryManager::InitializeClassMethodSummaries() {
-  ArgEffects ScratchArgs = AF.getEmptyMap();
-
-  // Create the [NSAssertionHandler currentHander] summary.
-  addClassMethSummary("NSAssertionHandler", "currentHandler",
-                getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::ObjC),
-                                     ScratchArgs));
-
-  // Create the [NSAutoreleasePool addObject:] summary.
-  ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));
-  addClassMethSummary("NSAutoreleasePool", "addObject",
-                      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
-                                           ArgEffect(DoNothing),
-                                           ArgEffect(Autorelease)));
-}
-
-void RetainSummaryManager::InitializeMethodSummaries() {
-
-  ArgEffects ScratchArgs = AF.getEmptyMap();
-  // Create the "init" selector.  It just acts as a pass-through for the
-  // receiver.
-  const RetainSummary *InitSumm = getPersistentSummary(
-      ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC));
-  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
-
-  // awakeAfterUsingCoder: behaves basically like an 'init' method.  It
-  // claims the receiver and returns a retained object.
-  addNSObjectMethSummary(GetUnarySelector("awakeAfterUsingCoder", Ctx),
-                         InitSumm);
-
-  // The next methods are allocators.
-  const RetainSummary *AllocSumm = getPersistentSummary(ObjCAllocRetE,
-                                                        ScratchArgs);
-  const RetainSummary *CFAllocSumm =
-    getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs);
-
-  // Create the "retain" selector.
-  RetEffect NoRet = RetEffect::MakeNoRet();
-  const RetainSummary *Summ = getPersistentSummary(
-      NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC));
-  addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
-
-  // Create the "release" selector.
-  Summ = getPersistentSummary(NoRet, ScratchArgs,
-                              ArgEffect(DecRef, ObjKind::ObjC));
-  addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
-
-  // Create the -dealloc summary.
-  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc,
-                                                            ObjKind::ObjC));
-  addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
-
-  // Create the "autorelease" selector.
-  Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease,
-                                                            ObjKind::ObjC));
-  addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
-
-  // For NSWindow, allocated objects are (initially) self-owned.
-  // FIXME: For now we opt for false negatives with NSWindow, as these objects
-  //  self-own themselves.  However, they only do this once they are displayed.
-  //  Thus, we need to track an NSWindow's display status.
-  //  This is tracked in <rdar://problem/6062711>.
-  //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
-  const RetainSummary *NoTrackYet =
-      getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
-                           ArgEffect(StopTracking), ArgEffect(StopTracking));
-
-  addClassMethSummary("NSWindow", "alloc", NoTrackYet);
-
-  // For NSPanel (which subclasses NSWindow), allocated objects are not
-  //  self-owned.
-  // FIXME: For now we don't track NSPanels. object for the same reason
-  //   as for NSWindow objects.
-  addClassMethSummary("NSPanel", "alloc", NoTrackYet);
-
-  // For NSNull, objects returned by +null are singletons that ignore
-  // retain/release semantics.  Just don't track them.
-  // <rdar://problem/12858915>
-  addClassMethSummary("NSNull", "null", NoTrackYet);
-
-  // Don't track allocated autorelease pools, as it is okay to prematurely
-  // exit a method.
-  addClassMethSummary("NSAutoreleasePool", "alloc", NoTrackYet);
-  addClassMethSummary("NSAutoreleasePool", "allocWithZone", NoTrackYet, false);
-  addClassMethSummary("NSAutoreleasePool", "new", NoTrackYet);
-
-  // Create summaries QCRenderer/QCView -createSnapShotImageOfType:
-  addInstMethSummary("QCRenderer", AllocSumm, "createSnapshotImageOfType");
-  addInstMethSummary("QCView", AllocSumm, "createSnapshotImageOfType");
-
-  // Create summaries for CIContext, 'createCGImage' and
-  // 'createCGLayerWithSize'.  These objects are CF objects, and are not
-  // automatically garbage collected.
-  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect");
-  addInstMethSummary("CIContext", CFAllocSumm, "createCGImage", "fromRect",
-                     "format", "colorSpace");
-  addInstMethSummary("CIContext", CFAllocSumm, "createCGLayerWithSize", "info");
-}
-
-CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
-  ASTContext &Ctx = MD->getASTContext();
-  LangOptions L = Ctx.getLangOpts();
-  RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
-                         /*TrackNSAndCFObjects=*/true,
-                         /*TrackOSObjects=*/false);
-  const RetainSummary *S = M.getMethodSummary(MD);
-  CallEffects CE(S->getRetEffect(), S->getReceiverEffect());
-  unsigned N = MD->param_size();
-  for (unsigned i = 0; i < N; ++i) {
-    CE.Args.push_back(S->getArg(i));
-  }
-  return CE;
-}
-
-CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
-  ASTContext &Ctx = FD->getASTContext();
-  LangOptions L = Ctx.getLangOpts();
-  RetainSummaryManager M(Ctx, L.ObjCAutoRefCount,
-                         /*TrackNSAndCFObjects=*/true,
-                         /*TrackOSObjects=*/false);
-  const RetainSummary *S = M.getFunctionSummary(FD);
-  CallEffects CE(S->getRetEffect());
-  unsigned N = FD->param_size();
-  for (unsigned i = 0; i < N; ++i) {
-    CE.Args.push_back(S->getArg(i));
-  }
-  return CE;
-}




More information about the cfe-commits mailing list