//==- CheckObjCDealloc.cpp - Check ObjC -dealloc implementation --*- 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 checker analyzes Objective-C -dealloc methods and their callees
//  to warn about improper releasing of instance variables that back synthesized
// properties. It warns about missing releases in the following cases:
//  - When a class has a synthesized instance variable for a 'retain' or 'copy'
//    property and lacks a -dealloc method in its implementation.
//  - When a class has a synthesized instance variable for a 'retain'/'copy'
//   property but the ivar is not released in -dealloc by either -release
//   or by nilling out the property.
//
//  It warns about extra releases in -dealloc (but not in callees) when a
//  synthesized instance variable is released in the following cases:
//  - When the property is 'assign' and is not 'readonly'.
//  - When the property is 'weak'.
//
//  This checker only warns for instance variables synthesized to back
//  properties. Handling the more general case would require inferring whether
//  an instance variable is stored retained or not. For synthesized properties,
//  this is specified in the property declaration itself.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/raw_ostream.h"
#include <optional>

using namespace clang;
using namespace ento;

/// Indicates whether an instance variable is required to be released in
/// -dealloc.
enum class ReleaseRequirement {
  /// The instance variable must be released, either by calling
  /// -release on it directly or by nilling it out with a property setter.
  MustRelease,

  /// The instance variable must not be directly released with -release.
  MustNotReleaseDirectly,

  /// The requirement for the instance variable could not be determined.
  Unknown
};

/// Returns true if the property implementation is synthesized and the
/// type of the property is retainable.
static bool isSynthesizedRetainableProperty(const ObjCPropertyImplDecl *I,
                                            const ObjCIvarDecl **ID,
                                            const ObjCPropertyDecl **PD) {

  if (I->getPropertyImplementation() != ObjCPropertyImplDecl::Synthesize)
    return false;

  (*ID) = I->getPropertyIvarDecl();
  if (!(*ID))
    return false;

  QualType T = (*ID)->getType();
  if (!T->isObjCRetainableType())
    return false;

  (*PD) = I->getPropertyDecl();
  // Shouldn't be able to synthesize a property that doesn't exist.
  assert(*PD);

  return true;
}

namespace {

class ObjCDeallocChecker
    : public Checker<check::ASTDecl<ObjCImplementationDecl>,
                     check::PreObjCMessage, check::PostObjCMessage,
                     check::PreCall,
                     check::BeginFunction, check::EndFunction,
                     eval::Assume,
                     check::PointerEscape,
                     check::PreStmt<ReturnStmt>> {

  mutable const IdentifierInfo *NSObjectII = nullptr;
  mutable const IdentifierInfo *SenTestCaseII = nullptr;
  mutable const IdentifierInfo *XCTestCaseII = nullptr;
  mutable const IdentifierInfo *Block_releaseII = nullptr;
  mutable const IdentifierInfo *CIFilterII = nullptr;

  mutable Selector DeallocSel;
  mutable Selector ReleaseSel;

  const BugType MissingReleaseBugType{this, "Missing ivar release (leak)",
                                      categories::MemoryRefCount};
  const BugType ExtraReleaseBugType{this, "Extra ivar release",
                                    categories::MemoryRefCount};
  const BugType MistakenDeallocBugType{this, "Mistaken dealloc",
                                       categories::MemoryRefCount};

public:
  void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr,
                    BugReporter &BR) const;
  void checkBeginFunction(CheckerContext &Ctx) const;
  void checkPreObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;
  void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
  void checkPostObjCMessage(const ObjCMethodCall &M, CheckerContext &C) const;

  ProgramStateRef evalAssume(ProgramStateRef State, SVal Cond,
                             bool Assumption) const;

  ProgramStateRef checkPointerEscape(ProgramStateRef State,
                                     const InvalidatedSymbols &Escaped,
                                     const CallEvent *Call,
                                     PointerEscapeKind Kind) const;
  void checkPreStmt(const ReturnStmt *RS, CheckerContext &C) const;
  void checkEndFunction(const ReturnStmt *RS, CheckerContext &Ctx) const;

private:
  void diagnoseMissingReleases(CheckerContext &C) const;

  bool diagnoseExtraRelease(SymbolRef ReleasedValue, const ObjCMethodCall &M,
                            CheckerContext &C) const;

  bool diagnoseMistakenDealloc(SymbolRef DeallocedValue,
                               const ObjCMethodCall &M,
                               CheckerContext &C) const;

  SymbolRef getValueReleasedByNillingOut(const ObjCMethodCall &M,
                                         CheckerContext &C) const;

  const ObjCIvarRegion *getIvarRegionForIvarSymbol(SymbolRef IvarSym) const;
  SymbolRef getInstanceSymbolFromIvarSymbol(SymbolRef IvarSym) const;

  const ObjCPropertyImplDecl*
  findPropertyOnDeallocatingInstance(SymbolRef IvarSym,
                                     CheckerContext &C) const;

  ReleaseRequirement
  getDeallocReleaseRequirement(const ObjCPropertyImplDecl *PropImpl) const;

  bool isInInstanceDealloc(const CheckerContext &C, SVal &SelfValOut) const;
  bool isInInstanceDealloc(const CheckerContext &C, const StackFrame *SF,
                           SVal &SelfValOut) const;
  bool instanceDeallocIsOnStack(const CheckerContext &C,
                                SVal &InstanceValOut) const;

  bool isSuperDeallocMessage(const ObjCMethodCall &M) const;

  const ObjCImplDecl *getContainingObjCImpl(const StackFrame *SF) const;

  const ObjCPropertyDecl *
  findShadowedPropertyDecl(const ObjCPropertyImplDecl *PropImpl) const;

  void transitionToReleaseValue(CheckerContext &C, SymbolRef Value) const;
  ProgramStateRef removeValueRequiringRelease(ProgramStateRef State,
                                              SymbolRef InstanceSym,
                                              SymbolRef ValueSym) const;

  void initIdentifierInfoAndSelectors(ASTContext &Ctx) const;

  bool classHasSeparateTeardown(const ObjCInterfaceDecl *ID) const;

  bool isReleasedByCIFilterDealloc(const ObjCPropertyImplDecl *PropImpl) const;
  bool isNibLoadedIvarWithoutRetain(const ObjCPropertyImplDecl *PropImpl) const;
};
} // End anonymous namespace.


/// Maps from the symbol for a class instance to the set of
/// symbols remaining that must be released in -dealloc.
REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef)
REGISTER_MAP_WITH_PROGRAMSTATE(UnreleasedIvarMap, SymbolRef, SymbolSet)


/// An AST check that diagnose when the class requires a -dealloc method and
/// is missing one.
void ObjCDeallocChecker::checkASTDecl(const ObjCImplementationDecl *D,
                                      AnalysisManager &Mgr,
                                      BugReporter &BR) const {
  assert(Mgr.getLangOpts().getGC() != LangOptions::GCOnly);
  assert(!Mgr.getLangOpts().ObjCAutoRefCount);
  initIdentifierInfoAndSelectors(Mgr.getASTContext());

  const ObjCInterfaceDecl *ID = D->getClassInterface();
  // If the class is known to have a lifecycle with a separate teardown method
  // then it may not require a -dealloc method.
  if (classHasSeparateTeardown(ID))
    return;

  // Does the class contain any synthesized properties that are retainable?
  // If not, skip the check entirely.
  const ObjCPropertyImplDecl *PropImplRequiringRelease = nullptr;
  bool HasOthers = false;
  for (const auto *I : D->property_impls()) {
    if (getDeallocReleaseRequirement(I) == ReleaseRequirement::MustRelease) {
      if (!PropImplRequiringRelease)
        PropImplRequiringRelease = I;
      else {
        HasOthers = true;
        break;
      }
    }
  }

  if (!PropImplRequiringRelease)
    return;

  const ObjCMethodDecl *MD = nullptr;

  // Scan the instance methods for "dealloc".
  for (const auto *I : D->instance_methods()) {
    if (I->getSelector() == DeallocSel) {
      MD = I;
      break;
    }
  }

  if (!MD) { // No dealloc found.
    const char* Name = "Missing -dealloc";

    std::string Buf;
    llvm::raw_string_ostream OS(Buf);
    OS << "'" << *D << "' lacks a 'dealloc' instance method but "
       << "must release '" << *PropImplRequiringRelease->getPropertyIvarDecl()
       << "'";

    if (HasOthers)
      OS << " and others";
    PathDiagnosticLocation DLoc =
        PathDiagnosticLocation::createBegin(D, BR.getSourceManager());

    BR.EmitBasicReport(D, this, Name, categories::CoreFoundationObjectiveC, Buf,
                       DLoc);
    return;
  }
}

/// If this is the beginning of -dealloc, mark the values initially stored in
/// instance variables that must be released by the end of -dealloc
/// as unreleased in the state.
void ObjCDeallocChecker::checkBeginFunction(
    CheckerContext &C) const {
  initIdentifierInfoAndSelectors(C.getASTContext());

  // Only do this if the current method is -dealloc.
  SVal SelfVal;
  if (!isInInstanceDealloc(C, SelfVal))
    return;

  SymbolRef SelfSymbol = SelfVal.getAsSymbol();

  const StackFrame *SF = C.getStackFrame();
  ProgramStateRef InitialState = C.getState();

  ProgramStateRef State = InitialState;

  SymbolSet::Factory &F = State->getStateManager().get_context<SymbolSet>();

  // Symbols that must be released by the end of the -dealloc;
  SymbolSet RequiredReleases = F.getEmptySet();

  // If we're an inlined -dealloc, we should add our symbols to the existing
  // set from our subclass.
  if (const SymbolSet *CurrSet = State->get<UnreleasedIvarMap>(SelfSymbol))
    RequiredReleases = *CurrSet;

  for (auto *PropImpl : getContainingObjCImpl(SF)->property_impls()) {
    ReleaseRequirement Requirement = getDeallocReleaseRequirement(PropImpl);
    if (Requirement != ReleaseRequirement::MustRelease)
      continue;

    SVal LVal = State->getLValue(PropImpl->getPropertyIvarDecl(), SelfVal);
    std::optional<Loc> LValLoc = LVal.getAs<Loc>();
    if (!LValLoc)
      continue;

    SVal InitialVal = State->getSVal(*LValLoc);
    SymbolRef Symbol = InitialVal.getAsSymbol();
    if (!Symbol || !isa<SymbolRegionValue>(Symbol))
      continue;

    // Mark the value as requiring a release.
    RequiredReleases = F.add(RequiredReleases, Symbol);
  }

  if (!RequiredReleases.isEmpty()) {
    State = State->set<UnreleasedIvarMap>(SelfSymbol, RequiredReleases);
  }

  if (State != InitialState) {
    C.addTransition(State);
  }
}

/// Given a symbol for an ivar, return the ivar region it was loaded from.
/// Returns nullptr if the instance symbol cannot be found.
const ObjCIvarRegion *
ObjCDeallocChecker::getIvarRegionForIvarSymbol(SymbolRef IvarSym) const {
  return dyn_cast_or_null<ObjCIvarRegion>(IvarSym->getOriginRegion());
}

/// Given a symbol for an ivar, return a symbol for the instance containing
/// the ivar. Returns nullptr if the instance symbol cannot be found.
SymbolRef
ObjCDeallocChecker::getInstanceSymbolFromIvarSymbol(SymbolRef IvarSym) const {

  const ObjCIvarRegion *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
  if (!IvarRegion)
    return nullptr;

  const SymbolicRegion *SR = IvarRegion->getSymbolicBase();
  assert(SR && "Symbolic base should not be nullptr");
  return SR->getSymbol();
}

/// If we are in -dealloc or -dealloc is on the stack, handle the call if it is
/// a release or a nilling-out property setter.
void ObjCDeallocChecker::checkPreObjCMessage(
    const ObjCMethodCall &M, CheckerContext &C) const {
  // Only run if -dealloc is on the stack.
  SVal DeallocedInstance;
  if (!instanceDeallocIsOnStack(C, DeallocedInstance))
    return;

  SymbolRef ReleasedValue = nullptr;

  if (M.getSelector() == ReleaseSel) {
    ReleasedValue = M.getReceiverSVal().getAsSymbol();
  } else if (M.getSelector() == DeallocSel && !M.isReceiverSelfOrSuper()) {
    if (diagnoseMistakenDealloc(M.getReceiverSVal().getAsSymbol(), M, C))
      return;
  }

  if (ReleasedValue) {
    // An instance variable symbol was released with -release:
    //    [_property release];
    if (diagnoseExtraRelease(ReleasedValue,M, C))
      return;
  } else {
    // An instance variable symbol was released nilling out its property:
    //    self.property = nil;
    ReleasedValue = getValueReleasedByNillingOut(M, C);
  }

  if (!ReleasedValue)
    return;

  transitionToReleaseValue(C, ReleasedValue);
}

/// If we are in -dealloc or -dealloc is on the stack, handle the call if it is
/// call to Block_release().
void ObjCDeallocChecker::checkPreCall(const CallEvent &Call,
                                      CheckerContext &C) const {
  const IdentifierInfo *II = Call.getCalleeIdentifier();
  if (II != Block_releaseII)
    return;

  if (Call.getNumArgs() != 1)
    return;

  SymbolRef ReleasedValue = Call.getArgSVal(0).getAsSymbol();
  if (!ReleasedValue)
    return;

  transitionToReleaseValue(C, ReleasedValue);
}
/// If the message was a call to '[super dealloc]', diagnose any missing
/// releases.
void ObjCDeallocChecker::checkPostObjCMessage(
    const ObjCMethodCall &M, CheckerContext &C) const {
  // We perform this check post-message so that if the super -dealloc
  // calls a helper method and that this class overrides, any ivars released in
  // the helper method will be recorded before checking.
  if (isSuperDeallocMessage(M))
    diagnoseMissingReleases(C);
}

/// Check for missing releases even when -dealloc does not call
/// '[super dealloc]'.
void ObjCDeallocChecker::checkEndFunction(
    const ReturnStmt *RS, CheckerContext &C) const {
  diagnoseMissingReleases(C);
}

/// Check for missing releases on early return.
void ObjCDeallocChecker::checkPreStmt(
    const ReturnStmt *RS, CheckerContext &C) const {
  diagnoseMissingReleases(C);
}

/// When a symbol is assumed to be nil, remove it from the set of symbols
/// require to be nil.
ProgramStateRef ObjCDeallocChecker::evalAssume(ProgramStateRef State, SVal Cond,
                                               bool Assumption) const {
  if (State->get<UnreleasedIvarMap>().isEmpty())
    return State;

  auto *CondBSE = dyn_cast_or_null<BinarySymExpr>(Cond.getAsSymbol());
  if (!CondBSE)
    return State;

  BinaryOperator::Opcode OpCode = CondBSE->getOpcode();
  if (Assumption) {
    if (OpCode != BO_EQ)
      return State;
  } else {
    if (OpCode != BO_NE)
      return State;
  }

  SymbolRef NullSymbol = nullptr;
  if (auto *SIE = dyn_cast<SymIntExpr>(CondBSE)) {
    const llvm::APInt &RHS = SIE->getRHS();
    if (RHS != 0)
      return State;
    NullSymbol = SIE->getLHS();
  } else if (auto *SIE = dyn_cast<IntSymExpr>(CondBSE)) {
    const llvm::APInt &LHS = SIE->getLHS();
    if (LHS != 0)
      return State;
    NullSymbol = SIE->getRHS();
  } else {
    return State;
  }

  SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(NullSymbol);
  if (!InstanceSymbol)
    return State;

  State = removeValueRequiringRelease(State, InstanceSymbol, NullSymbol);

  return State;
}

/// If a symbol escapes conservatively assume unseen code released it.
ProgramStateRef ObjCDeallocChecker::checkPointerEscape(
    ProgramStateRef State, const InvalidatedSymbols &Escaped,
    const CallEvent *Call, PointerEscapeKind Kind) const {

  if (State->get<UnreleasedIvarMap>().isEmpty())
    return State;

  // Don't treat calls to '[super dealloc]' as escaping for the purposes
  // of this checker. Because the checker diagnoses missing releases in the
  // post-message handler for '[super dealloc], escaping here would cause
  // the checker to never warn.
  auto *OMC = dyn_cast_or_null<ObjCMethodCall>(Call);
  if (OMC && isSuperDeallocMessage(*OMC))
    return State;

  for (const auto &Sym : Escaped) {
    if (!Call || (Call && !Call->isInSystemHeader())) {
      // If Sym is a symbol for an object with instance variables that
      // must be released, remove these obligations when the object escapes
      // unless via a call to a system function. System functions are
      // very unlikely to release instance variables on objects passed to them,
      // and are frequently called on 'self' in -dealloc (e.g., to remove
      // observers) -- we want to avoid false negatives from escaping on
      // them.
      State = State->remove<UnreleasedIvarMap>(Sym);
    }


    SymbolRef InstanceSymbol = getInstanceSymbolFromIvarSymbol(Sym);
    if (!InstanceSymbol)
      continue;

    State = removeValueRequiringRelease(State, InstanceSymbol, Sym);
  }

  return State;
}

/// Report any unreleased instance variables for the current instance being
/// dealloced.
void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  SVal SelfVal;
  if (!isInInstanceDealloc(C, SelfVal))
    return;

  const MemRegion *SelfRegion = SelfVal.castAs<loc::MemRegionVal>().getRegion();
  const StackFrame *SF = C.getStackFrame();

  ExplodedNode *ErrNode = nullptr;

  SymbolRef SelfSym = SelfVal.getAsSymbol();
  if (!SelfSym)
    return;

  const SymbolSet *OldUnreleased = State->get<UnreleasedIvarMap>(SelfSym);
  if (!OldUnreleased)
    return;

  SymbolSet NewUnreleased = *OldUnreleased;
  SymbolSet::Factory &F = State->getStateManager().get_context<SymbolSet>();

  ProgramStateRef InitialState = State;

  for (auto *IvarSymbol : *OldUnreleased) {
    const TypedValueRegion *TVR =
        cast<SymbolRegionValue>(IvarSymbol)->getRegion();
    const ObjCIvarRegion *IvarRegion = cast<ObjCIvarRegion>(TVR);

    // Don't warn if the ivar is not for this instance.
    if (SelfRegion != IvarRegion->getSuperRegion())
      continue;

    const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();
    // Prevent an inlined call to -dealloc in a super class from warning
    // about the values the subclass's -dealloc should release.
    if (IvarDecl->getContainingInterface() !=
        cast<ObjCMethodDecl>(SF->getDecl())->getClassInterface())
      continue;

    // Prevents diagnosing multiple times for the same instance variable
    // at, for example, both a return and at the end of the function.
    NewUnreleased = F.remove(NewUnreleased, IvarSymbol);

    if (State->getStateManager()
            .getConstraintManager()
            .isNull(State, IvarSymbol)
            .isConstrainedTrue()) {
      continue;
    }

    // A missing release manifests as a leak, so treat as a non-fatal error.
    if (!ErrNode)
      ErrNode = C.generateNonFatalErrorNode();
    // If we've already reached this node on another path, return without
    // diagnosing.
    if (!ErrNode)
      return;

    std::string Buf;
    llvm::raw_string_ostream OS(Buf);

    const ObjCInterfaceDecl *Interface = IvarDecl->getContainingInterface();
    // If the class is known to have a lifecycle with teardown that is
    // separate from -dealloc, do not warn about missing releases. We
    // suppress here (rather than not tracking for instance variables in
    // such classes) because these classes are rare.
    if (classHasSeparateTeardown(Interface))
      return;

    ObjCImplDecl *ImplDecl = Interface->getImplementation();

    const ObjCPropertyImplDecl *PropImpl =
        ImplDecl->FindPropertyImplIvarDecl(IvarDecl->getIdentifier());

    const ObjCPropertyDecl *PropDecl = PropImpl->getPropertyDecl();

    assert(PropDecl->getSetterKind() == ObjCPropertyDecl::Copy ||
           PropDecl->getSetterKind() == ObjCPropertyDecl::Retain);

    OS << "The '" << *IvarDecl << "' ivar in '" << *ImplDecl
       << "' was ";

    if (PropDecl->getSetterKind() == ObjCPropertyDecl::Retain)
      OS << "retained";
    else
      OS << "copied";

    OS << " by a synthesized property but not released"
          " before '[super dealloc]'";

    auto BR = std::make_unique<PathSensitiveBugReport>(MissingReleaseBugType,
                                                       Buf, ErrNode);
    C.emitReport(std::move(BR));
  }

  if (NewUnreleased.isEmpty()) {
    State = State->remove<UnreleasedIvarMap>(SelfSym);
  } else {
    State = State->set<UnreleasedIvarMap>(SelfSym, NewUnreleased);
  }

  if (ErrNode) {
    C.addTransition(State, ErrNode);
  } else if (State != InitialState) {
    C.addTransition(State);
  }

  // Make sure that after checking in the top-most frame the list of
  // tracked ivars is empty. This is intended to detect accidental leaks in
  // the UnreleasedIvarMap program state.
  assert(!SF->inTopFrame() || State->get<UnreleasedIvarMap>().isEmpty());
}

/// Given a symbol, determine whether the symbol refers to an ivar on
/// the top-most deallocating instance. If so, find the property for that
/// ivar, if one exists. Otherwise return null.
const ObjCPropertyImplDecl *
ObjCDeallocChecker::findPropertyOnDeallocatingInstance(
    SymbolRef IvarSym, CheckerContext &C) const {
  SVal DeallocedInstance;
  if (!isInInstanceDealloc(C, DeallocedInstance))
    return nullptr;

  // Try to get the region from which the ivar value was loaded.
  auto *IvarRegion = getIvarRegionForIvarSymbol(IvarSym);
  if (!IvarRegion)
    return nullptr;

  // Don't try to find the property if the ivar was not loaded from the
  // given instance.
  if (DeallocedInstance.castAs<loc::MemRegionVal>().getRegion() !=
      IvarRegion->getSuperRegion())
    return nullptr;

  const StackFrame *SF = C.getStackFrame();
  const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();

  const ObjCImplDecl *Container = getContainingObjCImpl(SF);
  const ObjCPropertyImplDecl *PropImpl =
      Container->FindPropertyImplIvarDecl(IvarDecl->getIdentifier());
  return PropImpl;
}

/// Emits a warning if the current context is -dealloc and ReleasedValue
/// must not be directly released in a -dealloc. Returns true if a diagnostic
/// was emitted.
bool ObjCDeallocChecker::diagnoseExtraRelease(SymbolRef ReleasedValue,
                                              const ObjCMethodCall &M,
                                              CheckerContext &C) const {
  // Try to get the region from which the released value was loaded.
  // Note that, unlike diagnosing for missing releases, here we don't track
  // values that must not be released in the state. This is because even if
  // these values escape, it is still an error under the rules of MRR to
  // release them in -dealloc.
  const ObjCPropertyImplDecl *PropImpl =
      findPropertyOnDeallocatingInstance(ReleasedValue, C);

  if (!PropImpl)
    return false;

  // If the ivar belongs to a property that must not be released directly
  // in dealloc, emit a warning.
  if (getDeallocReleaseRequirement(PropImpl) !=
      ReleaseRequirement::MustNotReleaseDirectly) {
    return false;
  }

  // If the property is readwrite but it shadows a read-only property in its
  // external interface, treat the property a read-only. If the outside
  // world cannot write to a property then the internal implementation is free
  // to make its own convention about whether the value is stored retained
  // or not. We look up the shadow here rather than in
  // getDeallocReleaseRequirement() because doing so can be expensive.
  const ObjCPropertyDecl *PropDecl = findShadowedPropertyDecl(PropImpl);
  if (PropDecl) {
    if (PropDecl->isReadOnly())
      return false;
  } else {
    PropDecl = PropImpl->getPropertyDecl();
  }

  ExplodedNode *ErrNode = C.generateNonFatalErrorNode();
  if (!ErrNode)
    return false;

  std::string Buf;
  llvm::raw_string_ostream OS(Buf);

  assert(PropDecl->getSetterKind() == ObjCPropertyDecl::Weak ||
         (PropDecl->getSetterKind() == ObjCPropertyDecl::Assign &&
          !PropDecl->isReadOnly()) ||
         isReleasedByCIFilterDealloc(PropImpl)
         );

  const ObjCImplDecl *Container = getContainingObjCImpl(C.getStackFrame());
  OS << "The '" << *PropImpl->getPropertyIvarDecl()
     << "' ivar in '" << *Container;


  if (isReleasedByCIFilterDealloc(PropImpl)) {
    OS << "' will be released by '-[CIFilter dealloc]' but also released here";
  } else {
    OS << "' was synthesized for ";

    if (PropDecl->getSetterKind() == ObjCPropertyDecl::Weak)
      OS << "a weak";
    else
      OS << "an assign, readwrite";

    OS <<  " property but was released in 'dealloc'";
  }

  auto BR = std::make_unique<PathSensitiveBugReport>(ExtraReleaseBugType, Buf,
                                                     ErrNode);
  BR->addRange(M.getOriginExpr()->getSourceRange());

  C.emitReport(std::move(BR));

  return true;
}

/// Emits a warning if the current context is -dealloc and DeallocedValue
/// must not be directly dealloced in a -dealloc. Returns true if a diagnostic
/// was emitted.
bool ObjCDeallocChecker::diagnoseMistakenDealloc(SymbolRef DeallocedValue,
                                                 const ObjCMethodCall &M,
                                                 CheckerContext &C) const {
  // TODO: Apart from unknown/undefined receivers, this may happen when
  // dealloc is called as a class method. Should we warn?
  if (!DeallocedValue)
    return false;

  // Find the property backing the instance variable that M
  // is dealloc'ing.
  const ObjCPropertyImplDecl *PropImpl =
      findPropertyOnDeallocatingInstance(DeallocedValue, C);
  if (!PropImpl)
    return false;

  if (getDeallocReleaseRequirement(PropImpl) !=
      ReleaseRequirement::MustRelease) {
    return false;
  }

  ExplodedNode *ErrNode = C.generateErrorNode();
  if (!ErrNode)
    return false;

  std::string Buf;
  llvm::raw_string_ostream OS(Buf);

  OS << "'" << *PropImpl->getPropertyIvarDecl()
     << "' should be released rather than deallocated";

  auto BR = std::make_unique<PathSensitiveBugReport>(MistakenDeallocBugType,
                                                     Buf, ErrNode);
  BR->addRange(M.getOriginExpr()->getSourceRange());

  C.emitReport(std::move(BR));

  return true;
}

void ObjCDeallocChecker::initIdentifierInfoAndSelectors(
    ASTContext &Ctx) const {
  if (NSObjectII)
    return;

  NSObjectII = &Ctx.Idents.get("NSObject");
  SenTestCaseII = &Ctx.Idents.get("SenTestCase");
  XCTestCaseII = &Ctx.Idents.get("XCTestCase");
  Block_releaseII = &Ctx.Idents.get("_Block_release");
  CIFilterII = &Ctx.Idents.get("CIFilter");

  const IdentifierInfo *DeallocII = &Ctx.Idents.get("dealloc");
  const IdentifierInfo *ReleaseII = &Ctx.Idents.get("release");
  DeallocSel = Ctx.Selectors.getSelector(0, &DeallocII);
  ReleaseSel = Ctx.Selectors.getSelector(0, &ReleaseII);
}

/// Returns true if M is a call to '[super dealloc]'.
bool ObjCDeallocChecker::isSuperDeallocMessage(
    const ObjCMethodCall &M) const {
  if (M.getOriginExpr()->getReceiverKind() != ObjCMessageExpr::SuperInstance)
    return false;

  return M.getSelector() == DeallocSel;
}

/// Returns the ObjCImplDecl containing the method declaration in SF.
const ObjCImplDecl *
ObjCDeallocChecker::getContainingObjCImpl(const StackFrame *SF) const {
  auto *MD = cast<ObjCMethodDecl>(SF->getDecl());
  return cast<ObjCImplDecl>(MD->getDeclContext());
}

/// Returns the property that shadowed by PropImpl if one exists and
/// nullptr otherwise.
const ObjCPropertyDecl *ObjCDeallocChecker::findShadowedPropertyDecl(
    const ObjCPropertyImplDecl *PropImpl) const {
  const ObjCPropertyDecl *PropDecl = PropImpl->getPropertyDecl();

  // Only readwrite properties can shadow.
  if (PropDecl->isReadOnly())
    return nullptr;

  auto *CatDecl = dyn_cast<ObjCCategoryDecl>(PropDecl->getDeclContext());

  // Only class extensions can contain shadowing properties.
  if (!CatDecl || !CatDecl->IsClassExtension())
    return nullptr;

  IdentifierInfo *ID = PropDecl->getIdentifier();
  DeclContext::lookup_result R = CatDecl->getClassInterface()->lookup(ID);
  for (const NamedDecl *D : R) {
    auto *ShadowedPropDecl = dyn_cast<ObjCPropertyDecl>(D);
    if (!ShadowedPropDecl)
      continue;

    if (ShadowedPropDecl->isInstanceProperty()) {
      assert(ShadowedPropDecl->isReadOnly());
      return ShadowedPropDecl;
    }
  }

  return nullptr;
}

/// Add a transition noting the release of the given value.
void ObjCDeallocChecker::transitionToReleaseValue(CheckerContext &C,
                                                  SymbolRef Value) const {
  assert(Value);
  SymbolRef InstanceSym = getInstanceSymbolFromIvarSymbol(Value);
  if (!InstanceSym)
    return;
  ProgramStateRef InitialState = C.getState();

  ProgramStateRef ReleasedState =
      removeValueRequiringRelease(InitialState, InstanceSym, Value);

  if (ReleasedState != InitialState) {
    C.addTransition(ReleasedState);
  }
}

/// Remove the Value requiring a release from the tracked set for
/// Instance and return the resultant state.
ProgramStateRef ObjCDeallocChecker::removeValueRequiringRelease(
    ProgramStateRef State, SymbolRef Instance, SymbolRef Value) const {
  assert(Instance);
  assert(Value);
  const ObjCIvarRegion *RemovedRegion = getIvarRegionForIvarSymbol(Value);
  if (!RemovedRegion)
    return State;

  const SymbolSet *Unreleased = State->get<UnreleasedIvarMap>(Instance);
  if (!Unreleased)
    return State;

  // Mark the value as no longer requiring a release.
  SymbolSet::Factory &F = State->getStateManager().get_context<SymbolSet>();
  SymbolSet NewUnreleased = *Unreleased;
  for (auto &Sym : *Unreleased) {
    const ObjCIvarRegion *UnreleasedRegion = getIvarRegionForIvarSymbol(Sym);
    assert(UnreleasedRegion);
    if (RemovedRegion->getDecl() == UnreleasedRegion->getDecl()) {
      NewUnreleased = F.remove(NewUnreleased, Sym);
    }
  }

  if (NewUnreleased.isEmpty()) {
    return State->remove<UnreleasedIvarMap>(Instance);
  }

  return State->set<UnreleasedIvarMap>(Instance, NewUnreleased);
}

/// Determines whether the instance variable for \p PropImpl must or must not be
/// released in -dealloc or whether it cannot be determined.
ReleaseRequirement ObjCDeallocChecker::getDeallocReleaseRequirement(
    const ObjCPropertyImplDecl *PropImpl) const {
  const ObjCIvarDecl *IvarDecl;
  const ObjCPropertyDecl *PropDecl;
  if (!isSynthesizedRetainableProperty(PropImpl, &IvarDecl, &PropDecl))
    return ReleaseRequirement::Unknown;

  ObjCPropertyDecl::SetterKind SK = PropDecl->getSetterKind();

  switch (SK) {
  // Retain and copy setters retain/copy their values before storing and so
  // the value in their instance variables must be released in -dealloc.
  case ObjCPropertyDecl::Retain:
  case ObjCPropertyDecl::Copy:
    if (isReleasedByCIFilterDealloc(PropImpl))
      return ReleaseRequirement::MustNotReleaseDirectly;

    if (isNibLoadedIvarWithoutRetain(PropImpl))
      return ReleaseRequirement::Unknown;

    return ReleaseRequirement::MustRelease;

  case ObjCPropertyDecl::Weak:
    return ReleaseRequirement::MustNotReleaseDirectly;

  case ObjCPropertyDecl::Assign:
    // It is common for the ivars for read-only assign properties to
    // always be stored retained, so their release requirement cannot be
    // be determined.
    if (PropDecl->isReadOnly())
      return ReleaseRequirement::Unknown;

    return ReleaseRequirement::MustNotReleaseDirectly;
  }
  llvm_unreachable("Unrecognized setter kind");
}

/// Returns the released value if M is a call a setter that releases
/// and nils out its underlying instance variable.
SymbolRef
ObjCDeallocChecker::getValueReleasedByNillingOut(const ObjCMethodCall &M,
                                                 CheckerContext &C) const {
  SVal ReceiverVal = M.getReceiverSVal();
  if (!ReceiverVal.isValid())
    return nullptr;

  if (M.getNumArgs() == 0)
    return nullptr;

  if (!M.getArgExpr(0)->getType()->isObjCRetainableType())
    return nullptr;

  // Is the first argument nil?
  SVal Arg = M.getArgSVal(0);
  ProgramStateRef notNilState, nilState;
  std::tie(notNilState, nilState) =
      C.getState()->assume(Arg.castAs<DefinedOrUnknownSVal>());
  if (!(nilState && !notNilState))
    return nullptr;

  const ObjCPropertyDecl *Prop = M.getAccessedProperty();
  if (!Prop)
    return nullptr;

  ObjCIvarDecl *PropIvarDecl = Prop->getPropertyIvarDecl();
  if (!PropIvarDecl)
    return nullptr;

  ProgramStateRef State = C.getState();

  SVal LVal = State->getLValue(PropIvarDecl, ReceiverVal);
  std::optional<Loc> LValLoc = LVal.getAs<Loc>();
  if (!LValLoc)
    return nullptr;

  SVal CurrentValInIvar = State->getSVal(*LValLoc);
  return CurrentValInIvar.getAsSymbol();
}

/// Returns true if the current context is a call to -dealloc and false
/// otherwise. If true, it also sets SelfValOut to the value of
/// 'self'.
bool ObjCDeallocChecker::isInInstanceDealloc(const CheckerContext &C,
                                             SVal &SelfValOut) const {
  return isInInstanceDealloc(C, C.getStackFrame(), SelfValOut);
}

/// Returns true if SF is a call to -dealloc and false
/// otherwise. If true, it also sets SelfValOut to the value of
/// 'self'.
bool ObjCDeallocChecker::isInInstanceDealloc(const CheckerContext &C,
                                             const StackFrame *SF,
                                             SVal &SelfValOut) const {
  auto *MD = dyn_cast<ObjCMethodDecl>(SF->getDecl());
  if (!MD || !MD->isInstanceMethod() || MD->getSelector() != DeallocSel)
    return false;

  const ImplicitParamDecl *SelfDecl = SF->getSelfDecl();
  assert(SelfDecl && "No self in -dealloc?");

  ProgramStateRef State = C.getState();
  SelfValOut = State->getSVal(State->getRegion(SelfDecl, SF));
  return true;
}

/// Returns true if there is a call to -dealloc anywhere on the stack and false
/// otherwise. If true, it also sets InstanceValOut to the value of
/// 'self' in the frame for -dealloc.
bool ObjCDeallocChecker::instanceDeallocIsOnStack(const CheckerContext &C,
                                                  SVal &InstanceValOut) const {
  return llvm::any_of(C.stackframes(), [&](const StackFrame &SF) {
    return isInInstanceDealloc(C, &SF, InstanceValOut);
  });
}

/// Returns true if the ID is a class in which is known to have
/// a separate teardown lifecycle. In this case, -dealloc warnings
/// about missing releases should be suppressed.
bool ObjCDeallocChecker::classHasSeparateTeardown(
    const ObjCInterfaceDecl *ID) const {
  // Suppress if the class is not a subclass of NSObject.
  for ( ; ID ; ID = ID->getSuperClass()) {
    IdentifierInfo *II = ID->getIdentifier();

    if (II == NSObjectII)
      return false;

    // FIXME: For now, ignore classes that subclass SenTestCase and XCTestCase,
    // as these don't need to implement -dealloc.  They implement tear down in
    // another way, which we should try and catch later.
    //  http://llvm.org/bugs/show_bug.cgi?id=3187
    if (II == XCTestCaseII || II == SenTestCaseII)
      return true;
  }

  return true;
}

/// The -dealloc method in CIFilter highly unusual in that is will release
/// instance variables belonging to its *subclasses* if the variable name
/// starts with "input" or backs a property whose name starts with "input".
/// Subclasses should not release these ivars in their own -dealloc method --
/// doing so could result in an over release.
///
/// This method returns true if the property will be released by
/// -[CIFilter dealloc].
bool ObjCDeallocChecker::isReleasedByCIFilterDealloc(
    const ObjCPropertyImplDecl *PropImpl) const {
  assert(PropImpl->getPropertyIvarDecl());
  StringRef PropName = PropImpl->getPropertyDecl()->getName();
  StringRef IvarName = PropImpl->getPropertyIvarDecl()->getName();

  const char *ReleasePrefix = "input";
  if (!(PropName.starts_with(ReleasePrefix) ||
        IvarName.starts_with(ReleasePrefix))) {
    return false;
  }

  const ObjCInterfaceDecl *ID =
      PropImpl->getPropertyIvarDecl()->getContainingInterface();
  for ( ; ID ; ID = ID->getSuperClass()) {
    IdentifierInfo *II = ID->getIdentifier();
    if (II == CIFilterII)
      return true;
  }

  return false;
}

/// Returns whether the ivar backing the property is an IBOutlet that
/// has its value set by nib loading code without retaining the value.
///
/// On macOS, if there is no setter, the nib-loading code sets the ivar
/// directly, without retaining the value,
///
/// On iOS and its derivatives, the nib-loading code will call
/// -setValue:forKey:, which retains the value before directly setting the ivar.
bool ObjCDeallocChecker::isNibLoadedIvarWithoutRetain(
    const ObjCPropertyImplDecl *PropImpl) const {
  const ObjCIvarDecl *IvarDecl = PropImpl->getPropertyIvarDecl();
  if (!IvarDecl->hasAttr<IBOutletAttr>())
    return false;

  const llvm::Triple &Target =
      IvarDecl->getASTContext().getTargetInfo().getTriple();

  if (!Target.isMacOSX())
    return false;

  if (PropImpl->getPropertyDecl()->getSetterMethodDecl())
    return false;

  return true;
}

void ento::registerObjCDeallocChecker(CheckerManager &Mgr) {
  Mgr.registerChecker<ObjCDeallocChecker>();
}

bool ento::shouldRegisterObjCDeallocChecker(const CheckerManager &mgr) {
  // These checker only makes sense under MRR.
  const LangOptions &LO = mgr.getLangOpts();
  return LO.getGC() != LangOptions::GCOnly && !LO.ObjCAutoRefCount;
}
