//== 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(std::string(ClassName)));
  return !(match(SubclassM, *D, D->getASTContext()).empty());
}

static bool isOSObjectSubclass(const Decl *D) {
  // OSSymbols are particular OSObjects that are allocated globally
  // and therefore aren't really refcounted, so we ignore them.
  return D && isSubclass(D, "OSMetaClassBase") && !isSubclass(D, "OSSymbol");
}

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::InheritedConstructor:
  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);
}
