zinovy.nis updated this revision to Diff 250375.
zinovy.nis added a comment.

Removed top-level consts.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74692/new/

https://reviews.llvm.org/D74692

Files:
  clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
  clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp
===================================================================
--- clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone-use-after-move.cpp
@@ -129,6 +129,16 @@
   // CHECK-NOTES: [[@LINE-3]]:15: note: move occurred here
 }
 
+void simpleConst() {
+  const A a;
+  a.foo();
+  A other_a = std::move(a);
+  a.foo();
+  // CHECK-NOTES: [[@LINE-1]]:3: warning: 'a' used after it was moved; move of a 'const' argument has no effect
+  // CHECK-NOTES: [[@LINE-3]]:15: note: move occurred here
+  // CHECK-NOTES: [[@LINE-6]]:11: note: variable 'a' declared const here
+}
+
 // A warning should only be emitted for one use-after-move.
 void onlyFlagOneUseAfterMove() {
   A a;
@@ -314,8 +324,21 @@
     auto lambda = [a] {
       std::move(a);
       a.foo();
-      // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved
+      // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved; move of a 'const' argument has no effect
       // CHECK-NOTES: [[@LINE-3]]:7: note: move occurred here
+      // CHECK-NOTES: [[@LINE-5]]:20: note: variable 'a' captured const here
+    };
+  }
+  // Use-after-moves inside a lambda should be detected.
+  {
+    A a;
+    // Implicit capture
+    auto lambda = [=] {
+      std::move(a);
+      a.foo();
+      // CHECK-NOTES: [[@LINE-1]]:7: warning: 'a' used after it was moved; move of a 'const' argument has no effect
+      // CHECK-NOTES: [[@LINE-3]]:7: note: move occurred here
+      // CHECK-NOTES: [[@LINE-5]]:20: note: variable 'a' implicitly captured const here
     };
   }
   // This is just as true if the variable was declared inside the lambda.
@@ -721,14 +744,16 @@
     const A a;
     std::move(a);
     passByConstPointer(&a);
-    // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+    // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved; move of a 'const' argument has no effect
     // CHECK-NOTES: [[@LINE-3]]:5: note: move occurred here
+    // CHECK-NOTES: [[@LINE-5]]:13: note: variable 'a' declared const here
   }
   const A a;
   std::move(a);
   passByConstReference(a);
-  // CHECK-NOTES: [[@LINE-1]]:24: warning: 'a' used after it was moved
+  // CHECK-NOTES: [[@LINE-1]]:24: warning: 'a' used after it was moved; move of a 'const' argument has no effect
   // CHECK-NOTES: [[@LINE-3]]:3: note: move occurred here
+  // CHECK-NOTES: [[@LINE-5]]:11: note: variable 'a' declared const here
 }
 
 // Clearing a standard container using clear() is treated as a
Index: clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
===================================================================
--- clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp
@@ -373,14 +373,36 @@
 }
 
 static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
-                           const UseAfterMove &Use, ClangTidyCheck *Check,
+                           const UseAfterMove &Use,
+                           const LambdaExpr *Lambda, ClangTidyCheck *Check,
                            ASTContext *Context) {
   SourceLocation UseLoc = Use.DeclRef->getExprLoc();
   SourceLocation MoveLoc = MovingCall->getExprLoc();
+  int MoveArgIsConst = MoveArg->getType().isConstQualified();
 
-  Check->diag(UseLoc, "'%0' used after it was moved")
-      << MoveArg->getDecl()->getName();
+  Check->diag(UseLoc, "'%0' used after it was moved%select{|; move of a "
+                      "'const' argument has no effect}1")
+      << MoveArg->getDecl()->getName() << MoveArgIsConst;
   Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note);
+  if (MoveArgIsConst) {
+    if (Lambda) {
+      for (const auto &Capture : Lambda->captures()) {
+        if (MoveArg->getDecl() == Capture.getCapturedVar()) {
+          int IsExplicitCapture = Capture.isExplicit();
+          Check->diag(IsExplicitCapture ? Capture.getLocation()
+                                        : Lambda->getCaptureDefaultLoc(),
+                      "variable %0 %select{implicitly|}1 captured const here",
+                      DiagnosticIDs::Note)
+              << Capture.getCapturedVar() << IsExplicitCapture;
+          break;
+        }
+      }
+    } else {
+      Check->diag(MoveArg->getDecl()->getLocation(),
+                  "variable '%0' declared const here", DiagnosticIDs::Note);
+    }
+  }
+
   if (Use.EvaluationOrderUndefined) {
     Check->diag(UseLoc,
                 "the use and move are unsequenced, i.e. there is no guarantee "
@@ -447,7 +469,7 @@
   UseAfterMoveFinder finder(Result.Context);
   UseAfterMove Use;
   if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
-    emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
+    emitDiagnostic(MovingCall, Arg, Use, ContainingLambda, this, Result.Context);
 }
 
 } // namespace bugprone
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to