Author: mboehme
Date: Fri Oct 14 08:23:39 2016
New Revision: 284235

URL: http://llvm.org/viewvc/llvm-project?rev=284235&view=rev
Log:
[clang-tidy] Add additional diagnostic to misc-use-after-move

Summary:
This adds a diagnostic to the misc-use-after-move check that is output when the
use happens on a later loop iteration than the move, for example:

    A a;
    for (int i = 0; i < 10; ++i) {
      a.foo();
      std::move(a);
    }

This situation can be confusing to users because, in terms of source code
location, the use is above the move. This can make it look as if the warning
is a false positive, particularly if the loop is long but the use and move are
close together.

In cases like these, misc-use-after-move will now output an additional
diagnostic:

  a.cpp:393:7: note: the use happens in a later loop iteration than the move

Reviewers: hokein

Subscribers: cfe-commits

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

Modified:
    clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp
    clang-tools-extra/trunk/test/clang-tidy/misc-use-after-move.cpp

Modified: clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp?rev=284235&r1=284234&r2=284235&view=diff
==============================================================================
--- clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp (original)
+++ clang-tools-extra/trunk/clang-tidy/misc/UseAfterMoveCheck.cpp Fri Oct 14 
08:23:39 2016
@@ -562,18 +562,24 @@ void UseAfterMoveFinder::getReinits(
 }
 
 static void emitDiagnostic(const Expr *MovingCall,
-                           const ValueDecl *MovedVariable,
+                           const DeclRefExpr *MoveArg,
                            const UseAfterMove &Use, ClangTidyCheck *Check,
                            ASTContext *Context) {
-  Check->diag(Use.DeclRef->getExprLoc(), "'%0' used after it was moved")
-      << MovedVariable->getName();
-  Check->diag(MovingCall->getExprLoc(), "move occurred here",
-              DiagnosticIDs::Note);
+  SourceLocation UseLoc = Use.DeclRef->getExprLoc();
+  SourceLocation MoveLoc = MovingCall->getExprLoc();
+
+  Check->diag(UseLoc, "'%0' used after it was moved")
+      << MoveArg->getDecl()->getName();
+  Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note);
   if (Use.EvaluationOrderUndefined) {
-    Check->diag(Use.DeclRef->getExprLoc(),
+    Check->diag(UseLoc,
                 "the use and move are unsequenced, i.e. there is no guarantee "
                 "about the order in which they are evaluated",
                 DiagnosticIDs::Note);
+  } else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) {
+    Check->diag(UseLoc,
+                "the use happens in a later loop iteration than the move",
+                DiagnosticIDs::Note);
   }
 }
 
@@ -625,8 +631,6 @@ void UseAfterMoveCheck::check(const Matc
   else
     return;
 
-  const ValueDecl *MovedVariable = Arg->getDecl();
-
   // Ignore the std::move if the variable that was passed to it isn't a local
   // variable.
   if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod())
@@ -634,8 +638,8 @@ void UseAfterMoveCheck::check(const Matc
 
   UseAfterMoveFinder finder(Result.Context);
   UseAfterMove Use;
-  if (finder.find(FunctionBody, MovingCall, MovedVariable, &Use))
-    emitDiagnostic(MovingCall, MovedVariable, Use, this, Result.Context);
+  if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
+    emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
 }
 
 } // namespace misc

Modified: clang-tools-extra/trunk/test/clang-tidy/misc-use-after-move.cpp
URL: 
http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/test/clang-tidy/misc-use-after-move.cpp?rev=284235&r1=284234&r2=284235&view=diff
==============================================================================
--- clang-tools-extra/trunk/test/clang-tidy/misc-use-after-move.cpp (original)
+++ clang-tools-extra/trunk/test/clang-tidy/misc-use-after-move.cpp Fri Oct 14 
08:23:39 2016
@@ -133,6 +133,7 @@ void moveAfterMove() {
       std::move(a);
       // CHECK-MESSAGES: [[@LINE-1]]:17: warning: 'a' used after it was moved
       // CHECK-MESSAGES: [[@LINE-2]]:7: note: move occurred here
+      // CHECK-MESSAGES: [[@LINE-3]]:17: note: the use happens in a later loop
     }
   }
 }
@@ -391,7 +392,8 @@ void useAndMoveInLoop() {
     for (int i = 0; i < 10; ++i) {
       a.foo();
       // CHECK-MESSAGES: [[@LINE-1]]:7: warning: 'a' used after it was moved
-      // CHECK-MESSAGES: [[@LINE+1]]:7: note: move occurred here
+      // CHECK-MESSAGES: [[@LINE+2]]:7: note: move occurred here
+      // CHECK-MESSAGES: [[@LINE-3]]:7: note: the use happens in a later loop
       std::move(a);
     }
   }
@@ -586,7 +588,7 @@ void assignments(int i) {
   }
 }
 
-// Passing the object to a function through a non-const pointer or refernce
+// Passing the object to a function through a non-const pointer or reference
 // counts as a re-initialization.
 void passByNonConstPointer(A *);
 void passByNonConstReference(A &);


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to