mboehme updated this revision to Diff 516390.
mboehme marked 2 inline comments as done.
mboehme added a comment.

Changes in response to review comments, and rebased to head.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D148110

Files:
  clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  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
@@ -1160,42 +1160,63 @@
   }
 }
 
+namespace InitializerListSequences {
+
+struct S1 {
+  int i;
+  A a;
+};
+
+struct S2 {
+  A a;
+  int i;
+};
+
+struct S3 {
+  S3() {}
+  S3(int, A) {}
+  S3(A, int) {}
+};
+
 // An initializer list sequences its initialization clauses.
 void initializerListSequences() {
   {
-    struct S1 {
-      int i;
-      A a;
-    };
-    {
-      A a;
-      S1 s1{a.getInt(), std::move(a)};
-    }
-    {
-      A a;
-      S1 s1{.i = a.getInt(), .a = std::move(a)};
-    }
+    A a;
+    S1 s1{a.getInt(), std::move(a)};
   }
   {
-    struct S2 {
-      A a;
-      int i;
-    };
-    {
-      A a;
-      S2 s2{std::move(a), a.getInt()};
-      // CHECK-NOTES: [[@LINE-1]]:27: warning: 'a' used after it was moved
-      // CHECK-NOTES: [[@LINE-2]]:13: note: move occurred here
-    }
-    {
-      A a;
-      S2 s2{.a = std::move(a), .i = a.getInt()};
-      // CHECK-NOTES: [[@LINE-1]]:37: warning: 'a' used after it was moved
-      // CHECK-NOTES: [[@LINE-2]]:13: note: move occurred here
-    }
+    A a;
+    S1 s1{.i = a.getInt(), .a = std::move(a)};
+  }
+  {
+    A a;
+    S2 s2{std::move(a), a.getInt()};
+    // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+    // CHECK-NOTES: [[@LINE-2]]:11: note: move occurred here
+  }
+  {
+    A a;
+    S2 s2{.a = std::move(a), .i = a.getInt()};
+    // CHECK-NOTES: [[@LINE-1]]:35: warning: 'a' used after it was moved
+    // CHECK-NOTES: [[@LINE-2]]:11: note: move occurred here
+  }
+  {
+    // Check the case where the constructed type has a constructor and the
+    // initializer list therefore manifests as a `CXXConstructExpr` instead of
+    // an `InitListExpr`.
+    A a;
+    S3 s3{a.getInt(), std::move(a)};
+  }
+  {
+    A a;
+    S3 s3{std::move(a), a.getInt()};
+    // CHECK-NOTES: [[@LINE-1]]:25: warning: 'a' used after it was moved
+    // CHECK-NOTES: [[@LINE-2]]:11: note: move occurred here
   }
 }
 
+} // namespace InitializerListSequences
+
 // A declaration statement containing multiple declarations sequences the
 // initializer expressions.
 void declarationSequences() {
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -214,8 +214,9 @@
   to ``std::forward``.
 
 - Improved :doc:`bugprone-use-after-move
-  <clang-tidy/checks/bugprone/use-after-move>` check to also cover constructor
-  initializers.
+  <clang-tidy/checks/bugprone/use-after-move>` check: Also cover constructor
+  initializers. Fix check to understand that constructor arguments are
+  sequenced when constructor call is written as list-initialization.
 
 - Deprecated :doc:`cert-dcl21-cpp
   <clang-tidy/checks/cert/dcl21-cpp>` check.
Index: clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
===================================================================
--- clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
+++ clang-tools-extra/clang-tidy/utils/ExprSequence.cpp
@@ -131,6 +131,16 @@
           }
         }
       }
+    } else if (const auto *ConstructExpr = dyn_cast<CXXConstructExpr>(Parent)) {
+      // Constructor arguments are sequenced if the constructor call is written
+      // as list-initialization.
+      if (ConstructExpr->isListInitialization()) {
+        for (unsigned I = 1; I < ConstructExpr->getNumArgs(); ++I) {
+          if (ConstructExpr->getArg(I - 1) == S) {
+            return ConstructExpr->getArg(I);
+          }
+        }
+      }
     } else if (const auto *Compound = dyn_cast<CompoundStmt>(Parent)) {
       // Compound statement: Each sub-statement is sequenced after the
       // statements that precede it.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to