r348201 - [analyzer] Rename MisusedMovedObjectChecker to MoveChecker

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 3 14:32:32 PST 2018


Author: dergachev
Date: Mon Dec  3 14:32:32 2018
New Revision: 348201

URL: http://llvm.org/viewvc/llvm-project?rev=348201&view=rev
Log:
[analyzer] Rename MisusedMovedObjectChecker to MoveChecker

This follows the Static Analyzer's tradition to name checkers after
things in which they find bugs, not after bugs they find.

Differential Revision: https://reviews.llvm.org/D54556

Added:
    cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
      - copied, changed from r348200, cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
    cfe/trunk/test/Analysis/use-after-move.cpp
      - copied, changed from r348200, cfe/trunk/test/Analysis/MisusedMovedObject.cpp
Removed:
    cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
    cfe/trunk/test/Analysis/MisusedMovedObject.cpp
Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt

Modified: cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td?rev=348201&r1=348200&r2=348201&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Checkers/Checkers.td Mon Dec  3 14:32:32 2018
@@ -303,9 +303,8 @@ def MismatchedIteratorChecker : Checker<
   HelpText<"Check for use of iterators of different containers where iterators "
            "of the same container are expected">;
 
-def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
-     HelpText<"Method calls on a moved-from object and copying a moved-from "
-              "object will be reported">;
+def MoveChecker: Checker<"Move">,
+     HelpText<"Find use-after-move bugs in C++">;
 
 def UninitializedObjectChecker: Checker<"UninitializedObject">,
      HelpText<"Reports uninitialized fields after object construction">;

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=348201&r1=348200&r2=348201&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Mon Dec  3 14:32:32 2018
@@ -52,7 +52,7 @@ add_clang_library(clangStaticAnalyzerChe
   MallocOverflowSecurityChecker.cpp
   MallocSizeofChecker.cpp
   MmapWriteExecChecker.cpp
-  MisusedMovedObjectChecker.cpp
+  MoveChecker.cpp
   MPI-Checker/MPIBugReporter.cpp
   MPI-Checker/MPIChecker.cpp
   MPI-Checker/MPIFunctionClassifier.cpp

Removed: cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp?rev=348200&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp (removed)
@@ -1,519 +0,0 @@
-// 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(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 *> 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 BugReporterVisitor {
-  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,
-                                                   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,
-                                                      BugReporterContext &BRC,
-                                                      BugReport &) {
-  // 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;
-
-  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(const ReturnStmt *RS,
-                                                 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.
-  return (MethodDec && MethodDec->getDeclName().isIdentifier() &&
-      (MethodDec->getName().lower() == "empty" ||
-       MethodDec->getName().lower() == "isempty"));
-}
-
-bool MisusedMovedObjectChecker::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();
-    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 auto *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 (const auto *Region : ExplicitRegions) {
-    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>();
-}

Copied: cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp (from r348200, cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp?p2=cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp&p1=cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp&r1=348200&r2=348201&rev=348201&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp Mon Dec  3 14:32:32 2018
@@ -1,4 +1,4 @@
-// MisusedMovedObjectChecker.cpp - Check use of moved-from objects. - C++ -===//
+// MoveChecker.cpp - Check use of moved-from objects. - C++ ---------------===//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -42,7 +42,7 @@ public:
   void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger(K); }
 };
 
-class MisusedMovedObjectChecker
+class MoveChecker
     : public Checker<check::PreCall, check::PostCall, check::EndFunction,
                      check::DeadSymbols, check::RegionChanges> {
 public:
@@ -117,9 +117,8 @@ static bool isAnyBaseRegionReported(Prog
 }
 
 std::shared_ptr<PathDiagnosticPiece>
-MisusedMovedObjectChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
-                                                      BugReporterContext &BRC,
-                                                      BugReport &) {
+MoveChecker::MovedBugVisitor::VisitNode(const ExplodedNode *N,
+                                        BugReporterContext &BRC, BugReport &) {
   // We need only the last move of the reported object's region.
   // The visitor walks the ExplodedGraph backwards.
   if (Found)
@@ -157,8 +156,9 @@ MisusedMovedObjectChecker::MovedBugVisit
   return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
 }
 
-const ExplodedNode *MisusedMovedObjectChecker::getMoveLocation(
-    const ExplodedNode *N, const MemRegion *Region, CheckerContext &C) const {
+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;
@@ -173,10 +173,9 @@ const ExplodedNode *MisusedMovedObjectCh
   return MoveNode;
 }
 
-ExplodedNode *MisusedMovedObjectChecker::reportBug(const MemRegion *Region,
-                                                   const CallEvent &Call,
-                                                   CheckerContext &C,
-                                                   MisuseKind MK) const {
+ExplodedNode *MoveChecker::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",
@@ -220,8 +219,8 @@ ExplodedNode *MisusedMovedObjectChecker:
 
 // 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(const ReturnStmt *RS,
-                                                 CheckerContext &C) const {
+void MoveChecker::checkEndFunction(const ReturnStmt *RS,
+                                   CheckerContext &C) const {
   auto State = C.getState();
   TrackedRegionMapTy Objects = State->get<TrackedRegionMap>();
   if (Objects.isEmpty())
@@ -254,8 +253,8 @@ void MisusedMovedObjectChecker::checkEnd
   C.addTransition(State);
 }
 
-void MisusedMovedObjectChecker::checkPostCall(const CallEvent &Call,
-                                              CheckerContext &C) const {
+void MoveChecker::checkPostCall(const CallEvent &Call,
+                                CheckerContext &C) const {
   const auto *AFC = dyn_cast<AnyFunctionCall>(&Call);
   if (!AFC)
     return;
@@ -302,8 +301,7 @@ void MisusedMovedObjectChecker::checkPos
   C.addTransition(State);
 }
 
-bool MisusedMovedObjectChecker::isMoveSafeMethod(
-    const CXXMethodDecl *MethodDec) const {
+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)) {
@@ -319,8 +317,7 @@ bool MisusedMovedObjectChecker::isMoveSa
        MethodDec->getName().lower() == "isempty"));
 }
 
-bool MisusedMovedObjectChecker::isStateResetMethod(
-    const CXXMethodDecl *MethodDec) const {
+bool MoveChecker::isStateResetMethod(const CXXMethodDecl *MethodDec) const {
   if (!MethodDec)
       return false;
   if (MethodDec->hasAttr<ReinitializesAttr>())
@@ -336,8 +333,7 @@ bool MisusedMovedObjectChecker::isStateR
 
 // 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 {
+bool MoveChecker::isInMoveSafeContext(const LocationContext *LC) const {
   do {
     const auto *CtxDec = LC->getDecl();
     auto *CtorDec = dyn_cast_or_null<CXXConstructorDecl>(CtxDec);
@@ -352,8 +348,7 @@ bool MisusedMovedObjectChecker::isInMove
   return false;
 }
 
-void MisusedMovedObjectChecker::checkPreCall(const CallEvent &Call,
-                                             CheckerContext &C) const {
+void MoveChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   const LocationContext *LC = C.getLocationContext();
   ExplodedNode *N = nullptr;
@@ -459,8 +454,8 @@ void MisusedMovedObjectChecker::checkPre
   C.addTransition(State, N);
 }
 
-void MisusedMovedObjectChecker::checkDeadSymbols(SymbolReaper &SymReaper,
-                                                 CheckerContext &C) const {
+void MoveChecker::checkDeadSymbols(SymbolReaper &SymReaper,
+                                   CheckerContext &C) const {
   ProgramStateRef State = C.getState();
   TrackedRegionMapTy TrackedRegions = State->get<TrackedRegionMap>();
   for (TrackedRegionMapTy::value_type E : TrackedRegions) {
@@ -475,7 +470,7 @@ void MisusedMovedObjectChecker::checkDea
   C.addTransition(State);
 }
 
-ProgramStateRef MisusedMovedObjectChecker::checkRegionChanges(
+ProgramStateRef MoveChecker::checkRegionChanges(
     ProgramStateRef State, const InvalidatedSymbols *Invalidated,
     ArrayRef<const MemRegion *> ExplicitRegions,
     ArrayRef<const MemRegion *> Regions, const LocationContext *LCtx,
@@ -495,10 +490,8 @@ ProgramStateRef MisusedMovedObjectChecke
   return State;
 }
 
-void MisusedMovedObjectChecker::printState(raw_ostream &Out,
-                                           ProgramStateRef State,
-                                           const char *NL,
-                                           const char *Sep) const {
+void MoveChecker::printState(raw_ostream &Out, ProgramStateRef State,
+                             const char *NL, const char *Sep) const {
 
   TrackedRegionMapTy RS = State->get<TrackedRegionMap>();
 
@@ -514,6 +507,6 @@ void MisusedMovedObjectChecker::printSta
     }
   }
 }
-void ento::registerMisusedMovedObjectChecker(CheckerManager &mgr) {
-  mgr.registerChecker<MisusedMovedObjectChecker>();
+void ento::registerMoveChecker(CheckerManager &mgr) {
+  mgr.registerChecker<MoveChecker>();
 }

Removed: cfe/trunk/test/Analysis/MisusedMovedObject.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/MisusedMovedObject.cpp?rev=348200&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/MisusedMovedObject.cpp (original)
+++ cfe/trunk/test/Analysis/MisusedMovedObject.cpp (removed)
@@ -1,712 +0,0 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text -analyzer-config exploration_strategy=unexplored_first_queue,eagerly-assume=false %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -analyzer-config exploration_strategy=dfs,eagerly-assume=false -verify -analyzer-output=text -DDFS=1 %s
-
-namespace std {
-
-template <typename>
-struct remove_reference;
-
-template <typename _Tp>
-struct remove_reference { typedef _Tp type; };
-
-template <typename _Tp>
-struct remove_reference<_Tp &> { typedef _Tp type; };
-
-template <typename _Tp>
-struct remove_reference<_Tp &&> { typedef _Tp type; };
-
-template <typename _Tp>
-typename remove_reference<_Tp>::type &&move(_Tp &&__t) {
-  return static_cast<typename remove_reference<_Tp>::type &&>(__t);
-}
-
-template <typename _Tp>
-_Tp &&forward(typename remove_reference<_Tp>::type &__t) noexcept {
-  return static_cast<_Tp &&>(__t);
-}
-
-template <class T>
-void swap(T &a, T &b) {
-  T c(std::move(a));
-  a = std::move(b);
-  b = std::move(c);
-}
-
-} // namespace std
-
-class B {
-public:
-  B() = default;
-  B(const B &) = default;
-  B(B &&) = default;
-  B& operator=(const B &q) = default;
-  void operator=(B &&b) {
-    return;
-  }
-  void foo() { return; }
-};
-
-class A {
-  int i;
-  double d;
-
-public:
-  B b;
-  A(int ii = 42, double dd = 1.0) : d(dd), i(ii), b(B()) {}
-  void moveconstruct(A &&other) {
-    std::swap(b, other.b);
-    std::swap(d, other.d);
-    std::swap(i, other.i);
-    return;
-  }
-  static A get() {
-    A v(12, 13);
-    return v;
-  }
-  A(A *a) {
-    moveconstruct(std::move(*a));
-  }
-  A(const A &other) : i(other.i), d(other.d), b(other.b) {}
-  A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) { // expected-note {{'b' became 'moved-from' here}}
-  }
-  A(A &&other, char *k) {
-    moveconstruct(std::move(other));
-  }
-  void operator=(const A &other) {
-    i = other.i;
-    d = other.d;
-    b = other.b;
-    return;
-  }
-  void operator=(A &&other) {
-    moveconstruct(std::move(other));
-    return;
-  }
-  int getI() { return i; }
-  int foo() const;
-  void bar() const;
-  void reset();
-  void destroy();
-  void clear();
-  bool empty() const;
-  bool isEmpty() const;
-  operator bool() const;
-};
-
-int bignum();
-
-void moveInsideFunctionCall(A a) {
-  A b = std::move(a);
-}
-void leftRefCall(A &a) {
-  a.foo();
-}
-void rightRefCall(A &&a) {
-  a.foo();
-}
-void constCopyOrMoveCall(const A a) {
-  a.foo();
-}
-
-void copyOrMoveCall(A a) {
-  a.foo();
-}
-
-void simpleMoveCtorTest() {
-  {
-    A a;
-    A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    a.foo();            // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-  }
-  {
-    A a;
-    A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    b = a;              // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
-  }
-  {
-    A a;
-    A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    b = std::move(a);   // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
-  }
-}
-
-void simpleMoveAssignementTest() {
-  {
-    A a;
-    A b;
-    b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    a.foo();          // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-  }
-  {
-    A a;
-    A b;
-    b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    A c(a);           // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
-  }
-  {
-    A a;
-    A b;
-    b = std::move(a);  // expected-note {{'a' became 'moved-from' here}}
-    A c(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
-  }
-}
-
-void moveInInitListTest() {
-  struct S {
-    A a;
-  };
-  A a;
-  S s{std::move(a)}; // expected-note {{'a' became 'moved-from' here}}
-  a.foo();           // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-// Don't report a bug if the variable was assigned to in the meantime.
-void reinitializationTest(int i) {
-  {
-    A a;
-    A b;
-    b = std::move(a);
-    a = A();
-    a.foo();
-  }
-  {
-    A a;
-    if (i == 1) { // expected-note {{Assuming 'i' is not equal to 1}} expected-note {{Taking false branch}}
-      // expected-note at -1 {{Assuming 'i' is not equal to 1}} expected-note at -1 {{Taking false branch}}
-      A b;
-      b = std::move(a);
-      a = A();
-    }
-    if (i == 2) { // expected-note {{Assuming 'i' is not equal to 2}} expected-note {{Taking false branch}}
-      //expected-note at -1 {{Assuming 'i' is not equal to 2}} expected-note at -1 {{Taking false branch}}
-      a.foo();    // no-warning
-    }
-  }
-  {
-    A a;
-    if (i == 1) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
-      std::move(a);
-    }
-    if (i == 2) { // expected-note {{Taking false branch}} expected-note {{Taking false branch}}
-      a = A();
-      a.foo();
-    }
-  }
-  // The built-in assignment operator should also be recognized as a
-  // reinitialization. (std::move() may be called on built-in types in template
-  // code.)
-  {
-    int a1 = 1, a2 = 2;
-    std::swap(a1, a2);
-  }
-  // A std::move() after the assignment makes the variable invalid again.
-  {
-    A a;
-    A b;
-    b = std::move(a);
-    a = A();
-    b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    a.foo();          // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-  }
-  // If a path exist where we not reinitialize the variable we report a bug.
-  {
-    A a;
-    A b;
-    b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    if (i < 10) {     // expected-note {{Assuming 'i' is >= 10}} expected-note {{Taking false branch}}
-      a = A();
-    }
-    if (i > 5) { // expected-note {{Taking true branch}}
-      a.foo();   // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-    }
-  }
-}
-
-// Using decltype on an expression is not a use.
-void decltypeIsNotUseTest() {
-  A a;
-  // A b(std::move(a));
-  decltype(a) other_a; // no-warning
-}
-
-void loopTest() {
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
-      rightRefCall(std::move(a));        // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}}
-      //expected-note at -1 {{Loop condition is true.  Entering loop body}}
-			//expected-note at -2 {{Loop condition is false. Execution jumps to the end of the function}}
-      rightRefCall(std::move(a)); // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
-      leftRefCall(a);                    // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}} 
-      //expected-note at -1 {{Loop condition is true.  Entering loop body}}
-			//expected-note at -2 {{Loop condition is false. Execution jumps to the end of the function}}
-      leftRefCall(a);             // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
-      constCopyOrMoveCall(a);            // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}} 
-      //expected-note at -1 {{Loop condition is true.  Entering loop body}}
-			//expected-note at -2 {{Loop condition is false. Execution jumps to the end of the function}}
-      constCopyOrMoveCall(a);     // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
-      moveInsideFunctionCall(a);         // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.  Entering loop body}}
-      //expected-note at -1 {{Loop condition is true.  Entering loop body}}
-			//expected-note at -2 {{Loop condition is false. Execution jumps to the end of the function}}
-      moveInsideFunctionCall(a);  // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is false. Execution jumps to the end of the function}}
-      copyOrMoveCall(a);                 // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < 2; i++) { // expected-note {{Loop condition is true.}}
-      //expected-note at -1 {{Loop condition is true.  Entering loop body}}
-			//expected-note at -2 {{Loop condition is false. Execution jumps to the end of the function}}
-      copyOrMoveCall(a);          // no-warning
-    }
-  }
-  {
-    A a;
-    for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is true.  Entering loop body}} expected-note {{Loop condition is true.  Entering loop body}}
-      constCopyOrMoveCall(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
-      // expected-note at -1 {{'a' became 'moved-from' here}}
-    }
-  }
-
-  // Don't warn if we return after the move.
-  {
-    A a;
-    for (int i = 0; i < 3; ++i) {
-      a.bar();
-      if (a.foo() > 0) {
-        A b;
-        b = std::move(a); // no-warning
-        return;
-      }
-    }
-  }
-}
-
-//report a usage of a moved-from object only at the first use
-void uniqueTest(bool cond) {
-  A a(42, 42.0);
-  A b;
-  b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-
-  if (cond) { // expected-note {{Assuming 'cond' is not equal to 0}} expected-note {{Taking true branch}}
-    a.foo();  // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-  }
-  if (cond) {
-    a.bar(); // no-warning
-  }
-
-  a.bar(); // no-warning
-}
-
-void uniqueTest2() {
-  A a;
-  A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-  a.foo();             // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-
-  A a2 = std::move(a); // no-warning
-  a.foo();             // no-warning
-}
-
-// There are exceptions where we assume in general that the method works fine
-//even on moved-from objects.
-void moveSafeFunctionsTest() {
-  A a;
-  A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-  a.empty();          // no-warning
-  a.isEmpty();        // no-warning
-  (void)a;            // no-warning
-  (bool)a;            // expected-warning {{expression result unused}}
-  a.foo();            // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-void moveStateResetFunctionsTest() {
-  {
-    A a;
-    A b = std::move(a);
-    a.reset(); // no-warning
-    a.foo();   // no-warning
-    // Test if resets the state of subregions as well.
-    a.b.foo(); // no-warning
-  }
-  {
-    A a;
-    A b = std::move(a);
-    a.destroy(); // no-warning
-    a.foo();     // no-warning
-  }
-  {
-    A a;
-    A b = std::move(a);
-    a.clear(); // no-warning
-    a.foo();   // no-warning
-    a.b.foo(); // no-warning
-  }
-}
-
-// Moves or uses that occur as part of template arguments.
-template <int>
-class ClassTemplate {
-public:
-  void foo(A a);
-};
-
-template <int>
-void functionTemplate(A a);
-
-void templateArgIsNotUseTest() {
-  {
-    // A pattern like this occurs in the EXPECT_EQ and ASSERT_EQ macros in
-    // Google Test.
-    A a;
-    ClassTemplate<sizeof(A(std::move(a)))>().foo(std::move(a)); // no-warning
-  }
-  {
-    A a;
-    functionTemplate<sizeof(A(std::move(a)))>(std::move(a)); // no-warning
-  }
-}
-
-// Moves of global variables are not reported.
-A global_a;
-void globalVariablesTest() {
-  std::move(global_a);
-  global_a.foo(); // no-warning
-}
-
-// Moves of member variables.
-class memberVariablesTest {
-  A a;
-  static A static_a;
-
-  void f() {
-    A b;
-    b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    a.foo();          // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object 'a'}}
-
-    b = std::move(static_a); // expected-note {{'static_a' became 'moved-from' here}}
-    static_a.foo();          // expected-warning {{Method call on a 'moved-from' object 'static_a'}} expected-note {{Method call on a 'moved-from' object 'static_a'}}
-  }
-};
-
-void PtrAndArrayTest() {
-  A *Ptr = new A(1, 1.5);
-  A Arr[10];
-  Arr[2] = std::move(*Ptr); // expected-note {{Became 'moved-from' here}}
-  (*Ptr).foo();             // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
-  Ptr = &Arr[1];
-  Arr[3] = std::move(Arr[1]); // expected-note {{Became 'moved-from' here}}
-  Ptr->foo();                 // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
-  Arr[3] = std::move(Arr[2]); // expected-note {{Became 'moved-from' here}}
-  Arr[2].foo();               // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object}}
-
-  Arr[2] = std::move(Arr[3]); // reinitialization
-  Arr[2].foo();               // no-warning
-}
-
-void exclusiveConditionsTest(bool cond) {
-  A a;
-  if (cond) {
-    A b;
-    b = std::move(a);
-  }
-  if (!cond) {
-    a.bar(); // no-warning
-  }
-}
-
-void differentBranchesTest(int i) {
-  // Don't warn if the use is in a different branch from the move.
-  {
-    A a;
-    if (i > 0) { // expected-note {{Assuming 'i' is > 0}} expected-note {{Taking true branch}}
-      A b;
-      b = std::move(a);
-    } else {
-      a.foo(); // no-warning
-    }
-  }
-  // Same thing, but with a ternary operator.
-  {
-    A a, b;
-    i > 0 ? (void)(b = std::move(a)) : a.bar(); // no-warning  // expected-note {{'?' condition is true}}
-  }
-  // A variation on the theme above.
-  {
-    A a;
-#ifdef DFS
-    a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is false}} expected-note {{'?' condition is false}}
-#else
-    a.foo() > 0 ? a.foo() : A(std::move(a)).foo(); // expected-note {{Assuming the condition is true}} expected-note {{'?' condition is true}}
-#endif
-  }
-  // Same thing, but with a switch statement.
-  {
-    A a, b;
-    switch (i) { // expected-note {{Control jumps to 'case 1:'}}
-    case 1:
-      b = std::move(a); // no-warning
-      break;            // expected-note {{Execution jumps to the end of the function}}
-    case 2:
-      a.foo(); // no-warning
-      break;
-    }
-  }
-  // However, if there's a fallthrough, we do warn.
-  {
-    A a, b;
-    switch (i) { // expected-note {{Control jumps to 'case 1:'}}
-    case 1:
-      b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    case 2:
-      a.foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object 'a'}}
-      break;
-    }
-  }
-}
-
-void tempTest() {
-  A a = A::get();
-  A::get().foo(); // no-warning
-  for (int i = 0; i < bignum(); i++) {
-    A::get().foo(); // no-warning
-  }
-}
-
-void interFunTest1(A &a) {
-  a.bar(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-}
-
-void interFunTest2() {
-  A a;
-  A b;
-  b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-  interFunTest1(a); // expected-note {{Calling 'interFunTest1'}}
-}
-
-void foobar(A a, int i);
-void foobar(int i, A a);
-
-void paramEvaluateOrderTest() {
-  A a;
-  foobar(std::move(a), a.getI()); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-  // expected-note at -1 {{'a' became 'moved-from' here}}
-
-  //FALSE NEGATIVE since parameters evaluate order is undefined
-  foobar(a.getI(), std::move(a)); //no-warning
-}
-
-void not_known(A &a);
-void not_known(A *a);
-
-void regionAndPointerEscapeTest() {
-  {
-    A a;
-    A b;
-    b = std::move(a);
-    not_known(a);
-    a.foo(); //no-warning
-  }
-  {
-    A a;
-    A b;
-    b = std::move(a);
-    not_known(&a);
-    a.foo(); // no-warning
-  }
-}
-
-// A declaration statement containing multiple declarations sequences the
-// initializer expressions.
-void declarationSequenceTest() {
-  {
-    A a;
-    A a1 = a, a2 = std::move(a); // no-warning
-  }
-  {
-    A a;
-    A a1 = std::move(a), a2 = a; // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
-    // expected-note at -1 {{'a' became 'moved-from' here}}
-  }
-}
-
-// The logical operators && and || sequence their operands.
-void logicalOperatorsSequenceTest() {
-  {
-    A a;
-    if (a.foo() > 0 && A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}} 
-      // expected-note at -1 {{Left side of '&&' is false}} expected-note at -1 {{Left side of '&&' is false}}
-			//expected-note at -2 {{Taking false branch}} expected-note at -2 {{Taking false branch}}
-      A().bar();
-    }
-  }
-  // A variation: Negate the result of the && (which pushes the && further down
-  // into the AST).
-  {
-    A a;
-    if (!(a.foo() > 0 && A(std::move(a)).foo() > 0)) { // expected-note {{Assuming the condition is false}} expected-note {{Assuming the condition is false}}
-      // expected-note at -1 {{Left side of '&&' is false}} expected-note at -1 {{Left side of '&&' is false}}
-      // expected-note at -2 {{Taking true branch}} expected-note at -2 {{Taking true branch}}
-      A().bar();
-    }
-  }
-  {
-    A a;
-    if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-      // expected-note at -1 {{'a' became 'moved-from' here}} expected-note at -1 {{Assuming the condition is true}} expected-note at -1 {{Assuming the condition is false}}
-      // expected-note at -2 {{Left side of '&&' is false}} expected-note at -2 {{Left side of '&&' is true}}
-      // expected-note at -3 {{Taking false branch}}
-      A().bar();
-    }
-  }
-  {
-    A a;
-    if (a.foo() > 0 || A(std::move(a)).foo() > 0) { // expected-note {{Assuming the condition is true}} 
-			//expected-note at -1 {{Left side of '||' is true}}
-			//expected-note at -2 {{Taking true branch}}
-      A().bar();
-    }
-  }
-  {
-    A a;
-    if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-      // expected-note at -1 {{'a' became 'moved-from' here}} expected-note at -1 {{Assuming the condition is false}} expected-note at -1 {{Left side of '||' is false}}
-      A().bar();
-    }
-  }
-}
-
-// A range-based for sequences the loop variable declaration before the body.
-void forRangeSequencesTest() {
-  A v[2] = {A(), A()};
-  for (A &a : v) {
-    A b;
-    b = std::move(a); // no-warning
-  }
-}
-
-// If a variable is declared in an if statement, the declaration of the variable
-// (which is treated like a reinitialization by the check) is sequenced before
-// the evaluation of the condition (which constitutes a use).
-void ifStmtSequencesDeclAndConditionTest() {
-  for (int i = 0; i < 3; ++i) {
-    if (A a = A()) {
-      A b;
-      b = std::move(a); // no-warning
-    }
-  }
-}
-
-struct C : public A {
-  [[clang::reinitializes]] void reinit();
-};
-
-void subRegionMoveTest() {
-  {
-    A a;
-    B b = std::move(a.b); // expected-note {{'b' became 'moved-from' here}}
-    a.b.foo();            // expected-warning {{Method call on a 'moved-from' object 'b'}} expected-note {{Method call on a 'moved-from' object 'b'}}
-  }
-  {
-    A a;
-    A a1 = std::move(a); // expected-note {{Calling move constructor for 'A'}} expected-note {{Returning from move constructor for 'A'}}
-    a.b.foo();           // expected-warning {{Method call on a 'moved-from' object 'b'}} expected-note {{Method call on a 'moved-from' object 'b'}}
-  }
-  // Don't report a misuse if any SuperRegion is already reported.
-  {
-    A a;
-    A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
-    a.foo();             // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
-    a.b.foo();           // no-warning
-  }
-  {
-    C c;
-    C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
-    c.foo();             // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
-    c.b.foo();           // no-warning
-  }
-}
-
-void resetSuperClass() {
-  C c;
-  C c1 = std::move(c);
-  c.clear();
-  C c2 = c; // no-warning
-}
-
-void resetSuperClass2() {
-  C c;
-  C c1 = std::move(c);
-  c.reinit();
-  C c2 = c; // no-warning
-}
-
-void reportSuperClass() {
-  C c;
-  C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
-  c.foo();             // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
-  C c2 = c;            // no-warning
-}
-
-struct Empty {};
-
-Empty inlinedCall() {
-  // Used to warn because region 'e' failed to be cleaned up because no symbols
-  // have ever died during the analysis and the checkDeadSymbols callback
-  // was skipped entirely.
-  Empty e{};
-  return e; // no-warning
-}
-
-void checkInlinedCallZombies() {
-  while (true)
-    inlinedCall();
-}
-
-void checkLoopZombies() {
-  while (true) {
-    Empty e{};
-    Empty f = std::move(e); // no-warning
-  }
-}

Copied: cfe/trunk/test/Analysis/use-after-move.cpp (from r348200, cfe/trunk/test/Analysis/MisusedMovedObject.cpp)
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/use-after-move.cpp?p2=cfe/trunk/test/Analysis/use-after-move.cpp&p1=cfe/trunk/test/Analysis/MisusedMovedObject.cpp&r1=348200&r2=348201&rev=348201&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/MisusedMovedObject.cpp (original)
+++ cfe/trunk/test/Analysis/use-after-move.cpp Mon Dec  3 14:32:32 2018
@@ -1,5 +1,9 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -verify -analyzer-output=text -analyzer-config exploration_strategy=unexplored_first_queue,eagerly-assume=false %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.cplusplus.MisusedMovedObject -std=c++11 -analyzer-config exploration_strategy=dfs,eagerly-assume=false -verify -analyzer-output=text -DDFS=1 %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=unexplored_first_queue
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.cplusplus.Move -verify %s\
+// RUN:  -std=c++11 -analyzer-output=text -analyzer-config eagerly-assume=false\
+// RUN:  -analyzer-config exploration_strategy=dfs -DDFS=1
 
 namespace std {
 




More information about the cfe-commits mailing list