//== 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 D && isSubclass(D, "OSMetaClassBase");
}

static bool isOSObjectDynamicCast(StringRef S) {
  return S == "safeMetaCast";
}

static bool isOSObjectRequiredCast(StringRef S) {
  return S == "requiredMetaCast";
}

static bool isOSObjectThisCast(StringRef S) {
  return S == "metaCast";
}


static bool isOSObjectPtr(QualType QT) {
  return isOSObjectSubclass(QT->getPointeeCXXRecordDecl());
}

static bool isISLObjectRef(QualType Ty) {
  return StringRef(Ty.getAsString()).startswith("isl_");
}

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) {
  assert(TrackOSObjects &&
         "Requesting a summary for an OSObject but OSObjects are not tracked");

  if (RetTy->isPointerType()) {
    const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
    if (PD && isOSObjectSubclass(PD)) {
      if (isOSObjectDynamicCast(FName) || isOSObjectRequiredCast(FName) ||
          isOSObjectThisCast(FName))
        return getDefaultSummary();

      // TODO: Add support for the slightly common *Matching(table) idiom.
      // Cf. IOService::nameMatching() etc. - these function have an unusual
      // contract of returning at +0 or +1 depending on their last argument.
      if (FName.endswith("Matching")) {
        return getPersistentStopSummary();
      }

      // All objects returned with functions *not* starting with 'get',
      // or iterators, are returned at +1.
      if ((!FName.startswith("get") && !FName.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 (Parent && isOSObjectSubclass(Parent)) {
      if (FName == "release" || FName == "taggedRelease")
        return getOSSummaryReleaseRule(FD);

      if (FName == "retain" || FName == "taggedRetain")
        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()->castAs<FunctionType>();
  QualType RetTy = FT->getReturnType();

  if (TrackOSObjects)
    if (const RetainSummary *S = getSummaryForOSObject(FD, FName, RetTy))
      return S;

  if (const auto *MD = dyn_cast<CXXMethodDecl>(FD))
    if (!isOSObjectRelated(MD))
      return getPersistentSummary(RetEffect::MakeNoRet(),
                                  ArgEffects(AF.getEmptyMap()),
                                  ArgEffect(DoNothing),
                                  ArgEffect(StopTracking),
                                  ArgEffect(DoNothing));

  if (TrackObjCAndCFObjects)
    if (const RetainSummary *S =
            getSummaryForObjCOrCFObject(FD, FName, RetTy, FT, AllowAnnotations))
      return S;

  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");
}

const RetainSummary *
RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
                                                         AnyCall &C) {
  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 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();
  }

  return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
}

void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(
    const RetainSummary *&S) {

  RetainSummaryTemplate Template(S, *this);

  Template->setReceiverEffect(ArgEffect(DoNothing));
  Template->setRetEffect(RetEffect::MakeNoRet());
}


void RetainSummaryManager::updateSummaryForArgumentTypes(
  const AnyCall &C, const RetainSummary *&RS) {
  RetainSummaryTemplate Template(RS, *this);

  unsigned parm_idx = 0;
  for (auto pi = C.param_begin(), pe = C.param_end(); pi != pe;
       ++pi, ++parm_idx) {
    QualType QT = (*pi)->getType();

    // Skip already created values.
    if (RS->getArgEffects().contains(parm_idx))
      continue;

    ObjKind K = ObjKind::AnyObj;

    if (isISLObjectRef(QT)) {
      K = ObjKind::Generalized;
    } else if (isOSObjectPtr(QT)) {
      K = ObjKind::OS;
    } else if (cocoa::isCocoaObjectRef(QT)) {
      K = ObjKind::ObjC;
    } else if (coreFoundation::isCFObjectRef(QT)) {
      K = ObjKind::CF;
    }

    if (K != ObjKind::AnyObj)
      Template->addArg(AF, parm_idx,
                       ArgEffect(RS->getDefaultArgEffect().getKind(), K));
  }
}

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_or_null<ObjCMessageExpr>(C.getExpr());
    if (!ME) {
      Summ = getMethodSummary(cast<ObjCMethodDecl>(C.getDecl()));
    } else if (ME->isInstanceMessage()) {
      Summ = getInstanceMethodSummary(ME, ReceiverType);
    } else {
      Summ = getClassMethodSummary(ME);
    }
    break;
  }
  }

  if (HasNonZeroCallbackArg)
    Summ = updateSummaryForNonZeroCallbackArg(Summ, C);

  if (IsReceiverUnconsumedSelf)
    updateSummaryForReceiverUnconsumedSelf(Summ);

  updateSummaryForArgumentTypes(C, Summ);

  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 Decl *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 (CE->getNumArgs() == 1 &&
        (cocoa::isRefType(ResultTy, "CF", FName) ||
         cocoa::isRefType(ResultTy, "CG", FName) ||
         cocoa::isRefType(ResultTy, "CV", FName)) &&
        (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 (isOSObjectRequiredCast(FName) && FD->param_size() >= 1) {
        return BehaviorSummary::Identity;
      } 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);
}
