// MoveChecker.cpp - Check use of moved-from objects. - 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 defines checker which checks for potential misuses of a moved-from
// object. That means method calls on the object or copying it in moved-from
// state.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/ExprCXX.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/StaticAnalyzer/Checkers/BuiltinCheckerRegistration.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/Checker.h"
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
#include "llvm/ADT/StringSet.h"

using namespace clang;
using namespace ento;

namespace {
struct RegionState {
private:
  enum Kind { Moved, Reported } K;
  RegionState(Kind InK) : K(InK) {}

public:
  bool isReported() const { return K == Reported; }
  bool isMoved() const { return K == Moved; }

  static RegionState getReported() { return RegionState(Reported); }
  static RegionState getMoved() { return RegionState(Moved); }

  bool operator==(const RegionState &X) const { return K == X.K; }
  void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
};
} // end of anonymous namespace

namespace {
class MoveChecker
    : public Checker<check::PreCall, check::PostCall,
                     check::DeadSymbols, check::RegionChanges> {
public:
  void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
  void checkPreCall(const CallEvent &MC, CheckerContext &C) const;
  void checkPostCall(const CallEvent &MC, CheckerContext &C) const;
  void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const;
  ProgramStateRef
  checkRegionChanges(ProgramStateRef State,
                     const InvalidatedSymbols *Invalidated,
                     ArrayRef<const MemRegion *> RequestedRegions,
                     ArrayRef<const MemRegion *> InvalidatedRegions,
                     const LocationContext *LCtx, const CallEvent *Call) const;
  void printState(raw_ostream &Out, ProgramStateRef State,
                  const char *NL, const char *Sep) const override;

private:
  enum MisuseKind { MK_FunCall, MK_Copy, MK_Move, MK_Dereference };
  enum StdObjectKind { SK_NonStd, SK_Unsafe, SK_Safe, SK_SmartPtr };

  enum AggressivenessKind { // In any case, don't warn after a reset.
    AK_Invalid = -1,
    AK_KnownsOnly = 0,      // Warn only about known move-unsafe classes.
    AK_KnownsAndLocals = 1, // Also warn about all local objects.
    AK_All = 2,             // Warn on any use-after-move.
    AK_NumKinds = AK_All
  };

  static bool misuseCausesCrash(MisuseKind MK) {
    return MK == MK_Dereference;
  }

  struct ObjectKind {
    // Is this a local variable or a local rvalue reference?
    bool IsLocal;
    // Is this an STL object? If so, of what kind?
    StdObjectKind StdKind;
  };

  // STL smart pointers are automatically re-initialized to null when moved
  // from. So we can't warn on many methods, but we can warn when it is
  // dereferenced, which is UB even if the resulting lvalue never gets read.
  const llvm::StringSet<> StdSmartPtrClasses = {
      "shared_ptr",
      "unique_ptr",
      "weak_ptr",
  };

  // Not all of these are entirely move-safe, but they do provide *some*
  // guarantees, and it means that somebody is using them after move
  // in a valid manner.
  // TODO: We can still try to identify *unsafe* use after move,
  // like we did with smart pointers.
  const llvm::StringSet<> StdSafeClasses = {
      "basic_filebuf",
      "basic_ios",
      "future",
      "optional",
      "packaged_task"
      "promise",
      "shared_future",
      "shared_lock",
      "thread",
      "unique_lock",
  };

  // Should we bother tracking the state of the object?
  bool shouldBeTracked(ObjectKind OK) const {
    // In non-aggressive mode, only warn on use-after-move of local variables
    // (or local rvalue references) and of STL objects. The former is possible
    // because local variables (or local rvalue references) are not tempting
    // their user to re-use the storage. The latter is possible because STL
    // objects are known to end up in a valid but unspecified state after the
    // move and their state-reset methods are also known, which allows us to
    // predict precisely when use-after-move is invalid.
    // Some STL objects are known to conform to additional contracts after move,
    // so they are not tracked. However, smart pointers specifically are tracked
    // because we can perform extra checking over them.
    // In aggressive mode, warn on any use-after-move because the user has
    // intentionally asked us to completely eliminate use-after-move
    // in his code.
    return (Aggressiveness == AK_All) ||
           (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
           OK.StdKind == SK_Unsafe || OK.StdKind == SK_SmartPtr;
  }

  // Some objects only suffer from some kinds of misuses, but we need to track
  // them anyway because we cannot know in advance what misuse will we find.
  bool shouldWarnAbout(ObjectKind OK, MisuseKind MK) const {
    // Additionally, only warn on smart pointers when they are dereferenced (or
    // local or we are aggressive).
    return shouldBeTracked(OK) &&
           ((Aggressiveness == AK_All) ||
            (Aggressiveness >= AK_KnownsAndLocals && OK.IsLocal) ||
            OK.StdKind != SK_SmartPtr || MK == MK_Dereference);
  }

  // Obtains ObjectKind of an object. Because class declaration cannot always
  // be easily obtained from the memory region, it is supplied separately.
  ObjectKind classifyObject(const MemRegion *MR, const CXXRecordDecl *RD) const;

  // Classifies the object and dumps a user-friendly description string to
  // the stream.
  void explainObject(llvm::raw_ostream &OS, const MemRegion *MR,
                     const CXXRecordDecl *RD, MisuseKind MK) const;

  bool belongsTo(const CXXRecordDecl *RD, const llvm::StringSet<> &Set) const;

  class MovedBugVisitor : public BugReporterVisitor {
  public:
    MovedBugVisitor(const MoveChecker &Chk, const MemRegion *R,
                    const CXXRecordDecl *RD, MisuseKind MK)
        : Chk(Chk), Region(R), RD(RD), MK(MK), Found(false) {}

    void Profile(llvm::FoldingSetNodeID &ID) const override {
      static int X = 0;
      ID.AddPointer(&X);
      ID.AddPointer(Region);
      // Don't add RD because it's, in theory, uniquely determined by
      // the region. In practice though, it's not always possible to obtain
      // the declaration directly from the region, that's why we store it
      // in the first place.
    }

    std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
                                                   BugReporterContext &BRC,
                                                   BugReport &BR) override;

  private:
    const MoveChecker &Chk;
    // The tracked region.
    const MemRegion *Region;
    // The class of the tracked object.
    const CXXRecordDecl *RD;
    // How exactly the object was misused.
    const MisuseKind MK;
    bool Found;
  };

  AggressivenessKind Aggressiveness;

public:
  void setAggressiveness(StringRef Str, CheckerManager &Mgr) {
    Aggressiveness =
        llvm::StringSwitch<AggressivenessKind>(Str)
            .Case("KnownsOnly", AK_KnownsOnly)
            .Case("KnownsAndLocals", AK_KnownsAndLocals)
            .Case("All", AK_All)
            .Default(AK_Invalid);

    if (Aggressiveness == AK_Invalid)
      Mgr.reportInvalidCheckerOptionValue(this, "WarnOn",
          "either \"KnownsOnly\", \"KnownsAndLocals\" or \"All\" string value");
  };

private:
  mutable std::unique_ptr<BugType> BT;

  // Check if the given form of potential misuse of a given object
  // should be reported. If so, get it reported. The callback from which
  // this function was called should immediately return after the call
  // because this function adds one or two transitions.
  void modelUse(ProgramStateRef State, const MemRegion *Region,
                const CXXRecordDecl *RD, MisuseKind MK,
                CheckerContext &C) const;

  // Returns the exploded node against which the report was emitted.
  // The caller *must* add any further transitions against this node.
  ExplodedNode *reportBug(const MemRegion *Region, const CXXRecordDecl *RD,
                          CheckerContext &C, MisuseKind MK) const;

  bool isInMoveSafeContext(const LocationContext *LC) const;
  bool isStateResetMethod(const CXXMethodDecl *MethodDec) const;
  bool isMoveSafeMethod(const CXXMethodDecl *MethodDec) const;
  const ExplodedNode *getMoveLocation(const ExplodedNode *N,
                                      const MemRegion *Region,
                                      CheckerContext &C) const;
};
} // end anonymous namespace

REGISTER_MAP_WITH_PROGRAMSTATE(TrackedRegionMap, const MemRegion *, RegionState)

// Define the inter-checker API.
namespace clang {
namespace ento {
namespace move {
bool isMovedFrom(ProgramStateRef State, const MemRegion *Region) {
  const RegionState *RS = State->get<TrackedRegionMap>(Region);
  return RS && (RS->isMoved() || RS->isReported());
}
} // namespace move
} // namespace ento
} // namespace clang

// If a region is removed all of the subregions needs to be removed too.
static ProgramStateRef removeFromState(ProgramStateRef State,
                                       const MemRegion *Region) {
  if (!Region)
    return State;
  for (auto &E : State->get<TrackedRegionMap>()) {
    if (E.first->isSubRegionOf(Region))
      State = State->remove<TrackedRegionMap>(E.first);
  }
  return State;
}

static bool isAnyBaseRegionReported(ProgramStateRef State,
                                    const MemRegion *Region) {
  for (auto &E : State->get<TrackedRegionMap>()) {
    if (Region->isSubRegionOf(E.first) && E.second.isReported())
      return true;
  }
  return false;
}

static const MemRegion *unwrapRValueReferenceIndirection(const MemRegion *MR) {
  if (const auto *SR = dyn_cast_or_null<SymbolicRegion>(MR)) {
    SymbolRef Sym = SR->getSymbol();
    if (Sym->getType()->isRValueReferenceType())
      if (const MemRegion *OriginMR = Sym->getOriginRegion())
        return OriginMR;
  }
  return MR;
}

std::shared_ptr<PathDiagnosticPiece>
MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
                                        BugReporterContext &BRC, BugReport &BR) {
  // We need only the last move of the reported object's region.
  // The visitor walks the ExplodedGraph backwards.
  if (Found)
    return nullptr;
  ProgramStateRef State = N->getState();
  ProgramStateRef StatePrev = N->getFirstPred()->getState();
  const RegionState *TrackedObject = State->get<TrackedRegionMap>(Region);
  const RegionState *TrackedObjectPrev =
      StatePrev->get<TrackedRegionMap>(Region);
  if (!TrackedObject)
    return nullptr;
  if (TrackedObjectPrev && TrackedObject)
    return nullptr;

  // Retrieve the associated statement.
  const Stmt *S = PathDiagnosticLocation::getStmt(N);
  if (!S)
    return nullptr;
  Found = true;

  SmallString<128> Str;
  llvm::raw_svector_ostream OS(Str);

  ObjectKind OK = Chk.classifyObject(Region, RD);
  switch (OK.StdKind) {
    case SK_SmartPtr:
      if (MK == MK_Dereference) {
        OS << "Smart pointer";
        Chk.explainObject(OS, Region, RD, MK);
        OS << " is reset to null when moved from";
        break;
      }

      // If it's not a dereference, we don't care if it was reset to null
      // or that it is even a smart pointer.
      LLVM_FALLTHROUGH;
    case SK_NonStd:
    case SK_Safe:
      OS << "Object";
      Chk.explainObject(OS, Region, RD, MK);
      OS << " is moved";
      break;
    case SK_Unsafe:
      OS << "Object";
      Chk.explainObject(OS, Region, RD, MK);
      OS << " is left in a valid but unspecified state after move";
      break;
  }

  // Generate the extra diagnostic.
  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
                             N->getLocationContext());
  return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
}

const ExplodedNode *MoveChecker::getMoveLocation(const ExplodedNode *N,
                                                 const MemRegion *Region,
                                                 CheckerContext &C) const {
  // Walk the ExplodedGraph backwards and find the first node that referred to
  // the tracked region.
  const ExplodedNode *MoveNode = N;

  while (N) {
    ProgramStateRef State = N->getState();
    if (!State->get<TrackedRegionMap>(Region))
      break;
    MoveNode = N;
    N = N->pred_empty() ? nullptr : *(N->pred_begin());
  }
  return MoveNode;
}

void MoveChecker::modelUse(ProgramStateRef State, const MemRegion *Region,
                           const CXXRecordDecl *RD, MisuseKind MK,
                           CheckerContext &C) const {
  assert(!C.isDifferent() && "No transitions should have been made by now");
  const RegionState *RS = State->get<TrackedRegionMap>(Region);
  ObjectKind OK = classifyObject(Region, RD);

  // Just in case: if it's not a smart pointer but it does have operator *,
  // we shouldn't call the bug a dereference.
  if (MK == MK_Dereference && OK.StdKind != SK_SmartPtr)
    MK = MK_FunCall;

  if (!RS || !shouldWarnAbout(OK, MK)
          || isInMoveSafeContext(C.getLocationContext())) {
    // Finalize changes made by the caller.
    C.addTransition(State);
    return;
  }

  // Don't report it in case if any base region is already reported.
  // But still generate a sink in case of UB.
  // And still finalize changes made by the caller.
  if (isAnyBaseRegionReported(State, Region)) {
    if (misuseCausesCrash(MK)) {
      C.generateSink(State, C.getPredecessor());
    } else {
      C.addTransition(State);
    }
    return;
  }

  ExplodedNode *N = reportBug(Region, RD, C, MK);

  // If the program has already crashed on this path, don't bother.
  if (N->isSink())
    return;

  State = State->set<TrackedRegionMap>(Region, RegionState::getReported());
  C.addTransition(State, N);
}

ExplodedNode *MoveChecker::reportBug(const MemRegion *Region,
                                     const CXXRecordDecl *RD, CheckerContext &C,
                                     MisuseKind MK) const {
  if (ExplodedNode *N = misuseCausesCrash(MK) ? C.generateErrorNode()
                                              : C.generateNonFatalErrorNode()) {

    if (!BT)
      BT.reset(new BugType(this, "Use-after-move",
                           "C++ move semantics"));

    // Uniqueing report to the same object.
    PathDiagnosticLocation LocUsedForUniqueing;
    const ExplodedNode *MoveNode = getMoveLocation(N, Region, C);

    if (const Stmt *MoveStmt = PathDiagnosticLocation::getStmt(MoveNode))
      LocUsedForUniqueing = PathDiagnosticLocation::createBegin(
          MoveStmt, C.getSourceManager(), MoveNode->getLocationContext());

    // Creating the error message.
    llvm::SmallString<128> Str;
    llvm::raw_svector_ostream OS(Str);
    switch(MK) {
      case MK_FunCall:
        OS << "Method called on moved-from object";
        explainObject(OS, Region, RD, MK);
        break;
      case MK_Copy:
        OS << "Moved-from object";
        explainObject(OS, Region, RD, MK);
        OS << " is copied";
        break;
      case MK_Move:
        OS << "Moved-from object";
        explainObject(OS, Region, RD, MK);
        OS << " is moved";
        break;
      case MK_Dereference:
        OS << "Dereference of null smart pointer";
        explainObject(OS, Region, RD, MK);
        break;
    }

    auto R =
        llvm::make_unique<BugReport>(*BT, OS.str(), N, LocUsedForUniqueing,
                                     MoveNode->getLocationContext()->getDecl());
    R->addVisitor(llvm::make_unique<MovedBugVisitor>(*this, Region, RD, MK));
    C.emitReport(std::move(R));
    return N;
  }
  return nullptr;
}

void MoveChecker::checkPostCall(const CallEvent &Call,
                                CheckerContext &C) const {
  const auto *AFC = dyn_cast<AnyFunctionCall>(&Call);
  if (!AFC)
    return;

  ProgramStateRef State = C.getState();
  const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(AFC->getDecl());
  if (!MethodDecl)
    return;

  // Check if an object became moved-from.
  // Object can become moved from after a call to move assignment operator or
  // move constructor .
  const auto *ConstructorDecl = dyn_cast<CXXConstructorDecl>(MethodDecl);
  if (ConstructorDecl && !ConstructorDecl->isMoveConstructor())
    return;

  if (!ConstructorDecl && !MethodDecl->isMoveAssignmentOperator())
    return;

  const auto ArgRegion = AFC->getArgSVal(0).getAsRegion();
  if (!ArgRegion)
    return;

  // Skip moving the object to itself.
  const auto *CC = dyn_cast_or_null<CXXConstructorCall>(&Call);
  if (CC && CC->getCXXThisVal().getAsRegion() == ArgRegion)
    return;

  if (const auto *IC = dyn_cast<CXXInstanceCall>(AFC))
    if (IC->getCXXThisVal().getAsRegion() == ArgRegion)
      return;

  const MemRegion *BaseRegion = ArgRegion->getBaseRegion();
  // Skip temp objects because of their short lifetime.
  if (BaseRegion->getAs<CXXTempObjectRegion>() ||
      AFC->getArgExpr(0)->isRValue())
    return;
  // If it has already been reported do not need to modify the state.

  if (State->get<TrackedRegionMap>(ArgRegion))
    return;

  const CXXRecordDecl *RD = MethodDecl->getParent();
  ObjectKind OK = classifyObject(ArgRegion, RD);
  if (shouldBeTracked(OK)) {
    // Mark object as moved-from.
    State = State->set<TrackedRegionMap>(ArgRegion, RegionState::getMoved());
    C.addTransition(State);
    return;
  }
  assert(!C.isDifferent() && "Should not have made transitions on this path!");
}

bool MoveChecker::isMoveSafeMethod(const CXXMethodDecl *MethodDec) const {
  // We abandon the cases where bool/void/void* conversion happens.
  if (const auto *ConversionDec =
          dyn_cast_or_null<CXXConversionDecl>(MethodDec)) {
    const Type *Tp = ConversionDec->getConversionType().getTypePtrOrNull();
    if (!Tp)
      return false;
    if (Tp->isBooleanType() || Tp->isVoidType() || Tp->isVoidPointerType())
      return true;
  }
  // Function call `empty` can be skipped.
  return (MethodDec && MethodDec->getDeclName().isIdentifier() &&
      (MethodDec->getName().lower() == "empty" ||
       MethodDec->getName().lower() == "isempty"));
}

bool MoveChecker::isStateResetMethod(const CXXMethodDecl *MethodDec) const {
  if (!MethodDec)
      return false;
  if (MethodDec->hasAttr<ReinitializesAttr>())
      return true;
  if (MethodDec->getDeclName().isIdentifier()) {
    std::string MethodName = MethodDec->getName().lower();
    // TODO: Some of these methods (eg., resize) are not always resetting
    // the state, so we should consider looking at the arguments.
    if (MethodName == "assign" || MethodName == "clear" ||
        MethodName == "destroy" || MethodName == "reset" ||
        MethodName == "resize" || MethodName == "shrink")
      return true;
  }
  return false;
}

// Don't report an error inside a move related operation.
// We assume that the programmer knows what she does.
bool MoveChecker::isInMoveSafeContext(const LocationContext *LC) const {
  do {
    const auto *CtxDec = LC->getDecl();
    auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);
    auto *DtorDec = dyn_cast_or_null<CXXDestructorDecl>(CtxDec);
    auto *MethodDec = dyn_cast_or_null<CXXMethodDecl>(CtxDec);
    if (DtorDec || (CtorDec && CtorDec->isCopyOrMoveConstructor()) ||
        (MethodDec && MethodDec->isOverloadedOperator() &&
         MethodDec->getOverloadedOperator() == OO_Equal) ||
        isStateResetMethod(MethodDec) || isMoveSafeMethod(MethodDec))
      return true;
  } while ((LC = LC->getParent()));
  return false;
}

bool MoveChecker::belongsTo(const CXXRecordDecl *RD,
                            const llvm::StringSet<> &Set) const {
  const IdentifierInfo *II = RD->getIdentifier();
  return II && Set.count(II->getName());
}

MoveChecker::ObjectKind
MoveChecker::classifyObject(const MemRegion *MR,
                            const CXXRecordDecl *RD) const {
  // Local variables and local rvalue references are classified as "Local".
  // For the purposes of this checker, we classify move-safe STL types
  // as not-"STL" types, because that's how the checker treats them.
  MR = unwrapRValueReferenceIndirection(MR);
  bool IsLocal =
      MR && isa<VarRegion>(MR) && isa<StackSpaceRegion>(MR->getMemorySpace());

  if (!RD || !RD->getDeclContext()->isStdNamespace())
    return { IsLocal, SK_NonStd };

  if (belongsTo(RD, StdSmartPtrClasses))
    return { IsLocal, SK_SmartPtr };

  if (belongsTo(RD, StdSafeClasses))
    return { IsLocal, SK_Safe };

  return { IsLocal, SK_Unsafe };
}

void MoveChecker::explainObject(llvm::raw_ostream &OS, const MemRegion *MR,
                                const CXXRecordDecl *RD, MisuseKind MK) const {
  // We may need a leading space every time we actually explain anything,
  // and we never know if we are to explain anything until we try.
  if (const auto DR =
          dyn_cast_or_null<DeclRegion>(unwrapRValueReferenceIndirection(MR))) {
    const auto *RegionDecl = cast<NamedDecl>(DR->getDecl());
    OS << " '" << RegionDecl->getNameAsString() << "'";
  }

  ObjectKind OK = classifyObject(MR, RD);
  switch (OK.StdKind) {
    case SK_NonStd:
    case SK_Safe:
      break;
    case SK_SmartPtr:
      if (MK != MK_Dereference)
        break;

      // We only care about the type if it's a dereference.
      LLVM_FALLTHROUGH;
    case SK_Unsafe:
      OS << " of type '" << RD->getQualifiedNameAsString() << "'";
      break;
  };
}

void MoveChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
  ProgramStateRef State = C.getState();

  // Remove the MemRegions from the map on which a ctor/dtor call or assignment
  // happened.

  // Checking constructor calls.
  if (const auto *CC = dyn_cast<CXXConstructorCall>(&Call)) {
    State = removeFromState(State, CC->getCXXThisVal().getAsRegion());
    auto CtorDec = CC->getDecl();
    // Check for copying a moved-from object and report the bug.
    if (CtorDec && CtorDec->isCopyOrMoveConstructor()) {
      const MemRegion *ArgRegion = CC->getArgSVal(0).getAsRegion();
      const CXXRecordDecl *RD = CtorDec->getParent();
      MisuseKind MK = CtorDec->isMoveConstructor() ? MK_Move : MK_Copy;
      modelUse(State, ArgRegion, RD, MK, C);
      return;
    }
  }

  const auto IC = dyn_cast<CXXInstanceCall>(&Call);
  if (!IC)
    return;

  // Calling a destructor on a moved object is fine.
  if (isa<CXXDestructorCall>(IC))
    return;

  const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
  if (!ThisRegion)
    return;

  // The remaining part is check only for method call on a moved-from object.
  const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(IC->getDecl());
  if (!MethodDecl)
    return;

  // We want to investigate the whole object, not only sub-object of a parent
  // class in which the encountered method defined.
  ThisRegion = ThisRegion->getMostDerivedObjectRegion();

  if (isStateResetMethod(MethodDecl)) {
    State = removeFromState(State, ThisRegion);
    C.addTransition(State);
    return;
  }

  if (isMoveSafeMethod(MethodDecl))
    return;

  // Store class declaration as well, for bug reporting purposes.
  const CXXRecordDecl *RD = MethodDecl->getParent();

  if (MethodDecl->isOverloadedOperator()) {
    OverloadedOperatorKind OOK = MethodDecl->getOverloadedOperator();

    if (OOK == OO_Equal) {
      // Remove the tracked object for every assignment operator, but report bug
      // only for move or copy assignment's argument.
      State = removeFromState(State, ThisRegion);

      if (MethodDecl->isCopyAssignmentOperator() ||
          MethodDecl->isMoveAssignmentOperator()) {
        const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
        MisuseKind MK =
            MethodDecl->isMoveAssignmentOperator() ? MK_Move : MK_Copy;
        modelUse(State, ArgRegion, RD, MK, C);
        return;
      }
      C.addTransition(State);
      return;
    }

    if (OOK == OO_Star || OOK == OO_Arrow) {
      modelUse(State, ThisRegion, RD, MK_Dereference, C);
      return;
    }
  }

  modelUse(State, ThisRegion, RD, MK_FunCall, C);
}

void MoveChecker::checkDeadSymbols(SymbolReaper &SymReaper,
                                   CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
  for (TrackedRegionMapTy::value_type E : TrackedRegions) {
    const MemRegion *Region = E.first;
    bool IsRegDead = !SymReaper.isLiveRegion(Region);

    // Remove the dead regions from the region map.
    if (IsRegDead) {
      State = State->remove<TrackedRegionMap>(Region);
    }
  }
  C.addTransition(State);
}

ProgramStateRef MoveChecker::checkRegionChanges(
    ProgramStateRef State, const InvalidatedSymbols *Invalidated,
    ArrayRef<const MemRegion *> RequestedRegions,
    ArrayRef<const MemRegion *> InvalidatedRegions,
    const LocationContext *LCtx, const CallEvent *Call) const {
  if (Call) {
    // Relax invalidation upon function calls: only invalidate parameters
    // that are passed directly via non-const pointers or non-const references
    // or rvalue references.
    // In case of an InstanceCall don't invalidate the this-region since
    // it is fully handled in checkPreCall and checkPostCall.
    const MemRegion *ThisRegion = nullptr;
    if (const auto *IC = dyn_cast<CXXInstanceCall>(Call))
      ThisRegion = IC->getCXXThisVal().getAsRegion();

    // Requested ("explicit") regions are the regions passed into the call
    // directly, but not all of them end up being invalidated.
    // But when they do, they appear in the InvalidatedRegions array as well.
    for (const auto *Region : RequestedRegions) {
      if (ThisRegion != Region) {
        if (llvm::find(InvalidatedRegions, Region) !=
            std::end(InvalidatedRegions)) {
          State = removeFromState(State, Region);
        }
      }
    }
  } else {
    // For invalidations that aren't caused by calls, assume nothing. In
    // particular, direct write into an object's field invalidates the status.
    for (const auto *Region : InvalidatedRegions)
      State = removeFromState(State, Region->getBaseRegion());
  }

  return State;
}

void MoveChecker::printState(raw_ostream &Out, ProgramStateRef State,
                             const char *NL, const char *Sep) const {

  TrackedRegionMapTy RS = State->get<TrackedRegionMap>();

  if (!RS.isEmpty()) {
    Out << Sep << "Moved-from objects :" << NL;
    for (auto I: RS) {
      I.first->dumpToStream(Out);
      if (I.second.isMoved())
        Out << ": moved";
      else
        Out << ": moved and reported";
      Out << NL;
    }
  }
}
void ento::registerMoveChecker(CheckerManager &mgr) {
  MoveChecker *chk = mgr.registerChecker<MoveChecker>();
  chk->setAggressiveness(
      mgr.getAnalyzerOptions().getCheckerStringOption(chk, "WarnOn",
                                                      "KnownsAndLocals"), mgr);
}

bool ento::shouldRegisterMoveChecker(const LangOptions &LO) {
  return true;
}
