[clang-tools-extra] 9182c67 - [clang-tidy]performance-no-automatic-move: fix false negative on `const T&&` ctors.

Clement Courbet via cfe-commits cfe-commits at lists.llvm.org
Wed May 24 06:05:51 PDT 2023


Author: Clement Courbet
Date: 2023-05-24T15:05:39+02:00
New Revision: 9182c679dde7cb6480e66b9231a53d43ad03908b

URL: https://github.com/llvm/llvm-project/commit/9182c679dde7cb6480e66b9231a53d43ad03908b
DIFF: https://github.com/llvm/llvm-project/commit/9182c679dde7cb6480e66b9231a53d43ad03908b.diff

LOG: [clang-tidy]performance-no-automatic-move: fix false negative on `const T&&` ctors.

We were only handling `const T&`/`T&&` ctor pairs, and we were missing uref-based ctors.

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

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
index 42bf8ff831868..7022e9d784fa7 100644
--- a/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -48,15 +48,23 @@ void NoAutomaticMoveCheck::registerMatchers(MatchFinder *Finder) {
           hasParameter(0, hasType(rValueReferenceType(
                               pointee(type(equalsBoundNode("SrcT")))))))))));
 
+  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
+  // instantiation of `template <typename U> DstT::DstT(U&&)`.
+  const auto ConstRefRefCtor = cxxConstructorDecl(
+      parameterCountIs(1),
+      hasParameter(0,
+                   hasType(rValueReferenceType(pointee(isConstQualified())))));
+
   Finder->addMatcher(
-      traverse(TK_AsIs,
-               returnStmt(hasReturnValue(
-                   ignoringElidableConstructorCall(ignoringParenImpCasts(
-                       cxxConstructExpr(
-                           hasDeclaration(LValueRefCtor),
-                           hasArgument(0, ignoringParenImpCasts(declRefExpr(
-                                              to(NonNrvoConstLocalVariable)))))
-                           .bind("ctor_call")))))),
+      traverse(
+          TK_AsIs,
+          returnStmt(hasReturnValue(
+              ignoringElidableConstructorCall(ignoringParenImpCasts(
+                  cxxConstructExpr(
+                      hasDeclaration(anyOf(LValueRefCtor, ConstRefRefCtor)),
+                      hasArgument(0, ignoringParenImpCasts(declRefExpr(
+                                         to(NonNrvoConstLocalVariable)))))
+                      .bind("ctor_call")))))),
       this);
 }
 

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7fe2b97de8643..d1fd47542bd51 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -387,6 +387,10 @@ Changes in existing checks
   <clang-tidy/checks/performance/no-automatic-move>` when warning would be
   emitted for a const local variable to which NRVO is applied.
 
+- Improved :doc:`performance-no-automatic-move
+  <clang-tidy/checks/performance/performance-no-automatic-move>`: warn on ``const &&``
+  constructors.
+
 Removed checks
 ^^^^^^^^^^^^^^
 

diff  --git a/clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
index d365f7de8b7c1..1ef7d16e38393 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
@@ -7,30 +7,42 @@ struct Obj {
   virtual ~Obj();
 };
 
-template <typename T>
-struct StatusOr {
-  StatusOr(const T &);
-  StatusOr(T &&);
-};
-
 struct NonTemplate {
   NonTemplate(const Obj &);
   NonTemplate(Obj &&);
 };
 
+template <typename T> struct TemplateCtorPair {
+  TemplateCtorPair(const T &);
+  TemplateCtorPair(T &&value);
+};
+
+template <typename T> struct UrefCtor {
+  template <class U = T> UrefCtor(U &&value);
+};
+
 template <typename T>
 T Make();
 
-StatusOr<Obj> PositiveStatusOrConstValue() {
+NonTemplate PositiveNonTemplate() {
   const Obj obj = Make<Obj>();
-  return obj;
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: constness of 'obj' prevents automatic move [performance-no-automatic-move]
+  return obj; // selects `NonTemplate(const Obj&)`
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: constness of 'obj' prevents
+  // automatic move [performance-no-automatic-move]
 }
 
-NonTemplate PositiveNonTemplateConstValue() {
+TemplateCtorPair<Obj> PositiveTemplateCtorPair() {
   const Obj obj = Make<Obj>();
-  return obj;
-  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: constness of 'obj' prevents automatic move [performance-no-automatic-move]
+  return obj; // selects `TemplateCtorPair(const T&)`
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: constness of 'obj' prevents
+  // automatic move [performance-no-automatic-move]
+}
+
+UrefCtor<Obj> PositiveUrefCtor() {
+  const Obj obj = Make<Obj>();
+  return obj; // selects `UrefCtor(const T&&)`
+  // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: constness of 'obj' prevents
+  // automatic move [performance-no-automatic-move]
 }
 
 Obj PositiveCantNrvo(bool b) {
@@ -51,22 +63,18 @@ NonTemplate PositiveNonTemplateLifetimeExtension() {
 }
 
 // FIXME: Ideally we would warn here too.
-StatusOr<Obj> PositiveStatusOrLifetimeExtension() {
+UrefCtor<Obj> PositiveUrefCtorLifetimeExtension() {
   const Obj &obj = Make<Obj>();
   return obj;
 }
 
 // Negatives.
 
-StatusOr<Obj> Temporary() {
-  return Make<Obj>();
-}
+UrefCtor<Obj> Temporary() { return Make<Obj>(); }
 
-StatusOr<Obj> ConstTemporary() {
-  return Make<const Obj>();
-}
+UrefCtor<Obj> ConstTemporary() { return Make<const Obj>(); }
 
-StatusOr<Obj> ConvertingMoveConstructor() {
+UrefCtor<Obj> ConvertingMoveConstructor() {
   Obj obj = Make<Obj>();
   return obj;
 }
@@ -85,21 +93,19 @@ Obj NotNrvo(bool b) {
   return obj2;
 }
 
-StatusOr<Obj> Ref() {
+UrefCtor<Obj> Ref() {
   Obj &obj = Make<Obj &>();
   return obj;
 }
 
-StatusOr<Obj> ConstRef() {
+UrefCtor<Obj> ConstRef() {
   const Obj &obj = Make<Obj &>();
   return obj;
 }
 
 const Obj global;
 
-StatusOr<Obj> Global() {
-  return global;
-}
+UrefCtor<Obj> Global() { return global; }
 
 struct FromConstRefOnly {
   FromConstRefOnly(const Obj &);


        


More information about the cfe-commits mailing list