//==- 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/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/Analysis/PathDiagnostic.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/TargetInfo.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/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 IdentifierInfo *NSObjectII, *SenTestCaseII, *XCTestCaseII,
      *Block_releaseII, *CIFilterII;

  mutable Selector DeallocSel, ReleaseSel;

  std::unique_ptr<BugType> MissingReleaseBugType;
  std::unique_ptr<BugType> ExtraReleaseBugType;
  std::unique_ptr<BugType> MistakenDeallocBugType;

public:
  ObjCDeallocChecker();

  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 LocationContext *LCtx,
                           SVal &SelfValOut) const;
  bool instanceDeallocIsOnStack(const CheckerContext &C,
                                SVal &InstanceValOut) const;

  bool isSuperDeallocMessage(const ObjCMethodCall &M) const;

  const ObjCImplDecl *getContainingObjCImpl(const LocationContext *LCtx) 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,
                       OS.str(), 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 LocationContext *LCtx = C.getLocationContext();
  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(LCtx)->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 LocationContext *LCtx = C.getLocationContext();

  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>(LCtx->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,
                                                       OS.str(), 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(!LCtx->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 LocationContext *LCtx = C.getLocationContext();
  const ObjCIvarDecl *IvarDecl = IvarRegion->getDecl();

  const ObjCImplDecl *Container = getContainingObjCImpl(LCtx);
  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.getLocationContext());
  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,
                                                     OS.str(), 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,
                                                     OS.str(), ErrNode);
  BR->addRange(M.getOriginExpr()->getSourceRange());

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

  return true;
}

ObjCDeallocChecker::ObjCDeallocChecker()
    : NSObjectII(nullptr), SenTestCaseII(nullptr), XCTestCaseII(nullptr),
      Block_releaseII(nullptr), CIFilterII(nullptr) {

  MissingReleaseBugType.reset(
      new BugType(this, "Missing ivar release (leak)",
                  categories::MemoryRefCount));

  ExtraReleaseBugType.reset(
      new BugType(this, "Extra ivar release",
                  categories::MemoryRefCount));

  MistakenDeallocBugType.reset(
      new BugType(this, "Mistaken dealloc",
                  categories::MemoryRefCount));
}

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

  IdentifierInfo *DeallocII = &Ctx.Idents.get("dealloc");
  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 LCtx.
const ObjCImplDecl *
ObjCDeallocChecker::getContainingObjCImpl(const LocationContext *LCtx) const {
  auto *MD = cast<ObjCMethodDecl>(LCtx->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) =
      M.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.getLocationContext(), SelfValOut);
}

/// Returns true if LCtx 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 LocationContext *LCtx,
                                             SVal &SelfValOut) const {
  auto *MD = dyn_cast<ObjCMethodDecl>(LCtx->getDecl());
  if (!MD || !MD->isInstanceMethod() || MD->getSelector() != DeallocSel)
    return false;

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

  ProgramStateRef State = C.getState();
  SelfValOut = State->getSVal(State->getRegion(SelfDecl, LCtx));
  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 {
  const LocationContext *LCtx = C.getLocationContext();

  while (LCtx) {
    if (isInInstanceDealloc(C, LCtx, InstanceValOut))
      return true;

    LCtx = LCtx->getParent();
  }

  return false;
}

/// 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.startswith(ReleasePrefix) ||
        IvarName.startswith(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;
}
