// MisusedMovedObjectChecker.cpp - Check use of moved-from objects. - C++ -===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// 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 "ClangSACheckers.h"
#include "clang/AST/ExprCXX.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"

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

class MisusedMovedObjectChecker
    : public Checker<check::PreCall, check::PostCall, check::EndFunction,
                     check::DeadSymbols, check::RegionChanges> {
public:
  void checkEndFunction(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 *> ExplicitRegions,
                     ArrayRef<const MemRegion *> Regions,
                     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};
  class MovedBugVisitor : public BugReporterVisitorImpl<MovedBugVisitor> {
  public:
    MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}

    void Profile(llvm::FoldingSetNodeID &ID) const override {
      static int X = 0;
      ID.AddPointer(&X);
      ID.AddPointer(Region);
    }

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

  private:
    // The tracked region.
    const MemRegion *Region;
    bool Found;
  };

  mutable std::unique_ptr<BugType> BT;
  ExplodedNode *reportBug(const MemRegion *Region, const CallEvent &Call,
                          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)

// 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;
}

std::shared_ptr<PathDiagnosticPiece>
MisusedMovedObjectChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
                                                      const ExplodedNode *PrevN,
                                                      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 = PrevN->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;

  std::string ObjectName;
  if (const auto DecReg = Region->getAs<DeclRegion>()) {
    const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
    ObjectName = RegionDecl->getNameAsString();
  }
  std::string InfoText;
  if (ObjectName != "")
    InfoText = "'" + ObjectName + "' became 'moved-from' here";
  else
    InfoText = "Became 'moved-from' here";

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

const ExplodedNode *MisusedMovedObjectChecker::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;
}

ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
                                                   const CallEvent &Call,
                                                   CheckerContext &C,
                                                   MisuseKind MK) const {
  if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
    if (!BT)
      BT.reset(new BugType(this, "Usage of a 'moved-from' object",
                           "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.
    std::string ErrorMessage;
    switch(MK) {
      case MK_FunCall:
        ErrorMessage = "Method call on a 'moved-from' object";
        break;
      case MK_Copy:
        ErrorMessage = "Copying a 'moved-from' object";
        break;
      case MK_Move:
        ErrorMessage = "Moving a 'moved-from' object";
        break;
    }
    if (const auto DecReg = Region->getAs<DeclRegion>()) {
      const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
      ErrorMessage += " '" + RegionDecl->getNameAsString() + "'";
    }

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

// Removing the function parameters' MemRegion from the state. This is needed
// for PODs where the trivial destructor does not even created nor executed.
void MisusedMovedObjectChecker::checkEndFunction(CheckerContext &C) const {
  auto State = C.getState();
  TrackedRegionMapTy Objects = State->get<TrackedRegionMap>();
  if (Objects.isEmpty())
    return;

  auto LC = C.getLocationContext();

  const auto LD = dyn_cast_or_null<FunctionDecl>(LC->getDecl());
  if (!LD)
    return;
  llvm::SmallSet<const MemRegion *, 8> InvalidRegions;

  for (auto Param : LD->parameters()) {
    auto Type = Param->getType().getTypePtrOrNull();
    if (!Type)
      continue;
    if (!Type->isPointerType() && !Type->isReferenceType()) {
      InvalidRegions.insert(State->getLValue(Param, LC).getAsRegion());
    }
  }

  if (InvalidRegions.empty())
    return;

  for (const auto &E : State->get<TrackedRegionMap>()) {
    if (InvalidRegions.count(E.first->getBaseRegion()))
      State = State->remove<TrackedRegionMap>(E.first);
  }

  C.addTransition(State);
}

void MisusedMovedObjectChecker::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;

  const auto *ConstructorDecl = dyn_cast<CXXConstructorDecl>(MethodDecl);

  const auto *CC = dyn_cast_or_null<CXXConstructorCall>(&Call);
  // Check if an object became moved-from.
  // Object can become moved from after a call to move assignment operator or
  // move constructor .
  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.
  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;
  // Mark object as moved-from.
  State = State->set<TrackedRegionMap>(ArgRegion, RegionState::getMoved());
  C.addTransition(State);
}

bool MisusedMovedObjectChecker::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.
  if (MethodDec && MethodDec->getDeclName().isIdentifier() &&
      (MethodDec->getName().lower() == "empty" ||
       MethodDec->getName().lower() == "isempty"))
    return true;

  return false;
}

bool MisusedMovedObjectChecker::isStateResetMethod(
    const CXXMethodDecl *MethodDec) const {
  if (MethodDec && MethodDec->getDeclName().isIdentifier()) {
    std::string MethodName = MethodDec->getName().lower();
    if (MethodName == "reset" || MethodName == "clear" ||
        MethodName == "destroy")
      return true;
  }
  return false;
}

// Don't report an error inside a move related operation.
// We assume that the programmer knows what she does.
bool MisusedMovedObjectChecker::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;
}

void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
                                             CheckerContext &C) const {
  ProgramStateRef State = C.getState();
  const LocationContext *LC = C.getLocationContext();
  ExplodedNode *N = nullptr;

  // 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 RegionState *ArgState = State->get<TrackedRegionMap>(ArgRegion);
      if (ArgState && ArgState->isMoved()) {
        if (!isInMoveSafeContext(LC)) {
          if(CtorDec->isMoveConstructor())
            N = reportBug(ArgRegion, Call, C, MK_Move);
          else
            N = reportBug(ArgRegion, Call, C, MK_Copy);
          State = State->set<TrackedRegionMap>(ArgRegion,
                                               RegionState::getReported());
        }
      }
    }
    C.addTransition(State, N);
    return;
  }

  const auto IC = dyn_cast<CXXInstanceCall>(&Call);
  if (!IC)
    return;
  // In case of destructor call we do not track the object anymore.
  const MemRegion *ThisRegion = IC->getCXXThisVal().getAsRegion();
  if (!ThisRegion)
    return;

  if (dyn_cast_or_null<CXXDestructorDecl>(Call.getDecl())) {
    State = removeFromState(State, ThisRegion);
    C.addTransition(State);
    return;
  }

  const auto MethodDecl = dyn_cast_or_null<CXXMethodDecl>(IC->getDecl());
  if (!MethodDecl)
    return;
  // Checking assignment operators.
  bool OperatorEq = MethodDecl->isOverloadedOperator() &&
                    MethodDecl->getOverloadedOperator() == OO_Equal;
  // Remove the tracked object for every assignment operator, but report bug
  // only for move or copy assignment's argument.
  if (OperatorEq) {
    State = removeFromState(State, ThisRegion);
    if (MethodDecl->isCopyAssignmentOperator() ||
        MethodDecl->isMoveAssignmentOperator()) {
      const RegionState *ArgState =
          State->get<TrackedRegionMap>(IC->getArgSVal(0).getAsRegion());
      if (ArgState && ArgState->isMoved() && !isInMoveSafeContext(LC)) {
        const MemRegion *ArgRegion = IC->getArgSVal(0).getAsRegion();
        if(MethodDecl->isMoveAssignmentOperator())
          N = reportBug(ArgRegion, Call, C, MK_Move);
        else
          N = reportBug(ArgRegion, Call, C, MK_Copy);
        State =
            State->set<TrackedRegionMap>(ArgRegion, RegionState::getReported());
      }
    }
    C.addTransition(State, N);
    return;
  }

  // The remaining part is check only for method call on a moved-from object.

  // We want to investigate the whole object, not only sub-object of a parent
  // class in which the encountered method defined.
  while (const CXXBaseObjectRegion *BR =
             dyn_cast<CXXBaseObjectRegion>(ThisRegion))
    ThisRegion = BR->getSuperRegion();

  if (isMoveSafeMethod(MethodDecl))
    return;

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

  // If it is already reported then we don't report the bug again.
  const RegionState *ThisState = State->get<TrackedRegionMap>(ThisRegion);
  if (!(ThisState && ThisState->isMoved()))
    return;

  // Don't report it in case if any base region is already reported
  if (isAnyBaseRegionReported(State, ThisRegion))
    return;

  if (isInMoveSafeContext(LC))
    return;

  N = reportBug(ThisRegion, Call, C, MK_FunCall);
  State = State->set<TrackedRegionMap>(ThisRegion, RegionState::getReported());
  C.addTransition(State, N);
}

void MisusedMovedObjectChecker::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 MisusedMovedObjectChecker::checkRegionChanges(
    ProgramStateRef State, const InvalidatedSymbols *Invalidated,
    ArrayRef<const MemRegion *> ExplicitRegions,
    ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
    const CallEvent *Call) const {
  // In case of an InstanceCall don't remove the ThisRegion from the GDM since
  // it is handled in checkPreCall and checkPostCall.
  const MemRegion *ThisRegion = nullptr;
  if (const auto *IC = dyn_cast_or_null<CXXInstanceCall>(Call)) {
    ThisRegion = IC->getCXXThisVal().getAsRegion();
  }

  for (ArrayRef<const MemRegion *>::iterator I = ExplicitRegions.begin(),
                                             E = ExplicitRegions.end();
       I != E; ++I) {
    const auto *Region = *I;
    if (ThisRegion != Region) {
      State = removeFromState(State, Region);
    }
  }

  return State;
}

void MisusedMovedObjectChecker::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::registerMisusedMovedObjectChecker(CheckerManager &mgr) {
  mgr.registerChecker<MisusedMovedObjectChecker>();
}
