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

2023-05-24 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

In D151092#4368225 , @courbet wrote:

> In D151092#4368151 , @aaron.ballman 
> wrote:
>
>> The release note references documentation that doesn't exist, so Sphinx is 
>> failing: https://lab.llvm.org/buildbot/#/builders/115/builds/46942
>
> Sorry, fixed in rG62dc3ba8442f 
> 

Thanks! In retrospect, I should have fixed that myself rather than mention it 
here, sorry for that. :-D


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

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


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

2023-05-24 Thread Clement Courbet via Phabricator via cfe-commits
courbet added a comment.

In D151092#4368151 , @aaron.ballman 
wrote:

> The release note references documentation that doesn't exist, so Sphinx is 
> failing: https://lab.llvm.org/buildbot/#/builders/115/builds/46942

Sorry, fixed in rG62dc3ba8442f 



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

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


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

2023-05-24 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

The release note references documentation that doesn't exist, so Sphinx is 
failing: https://lab.llvm.org/buildbot/#/builders/115/builds/46942


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

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


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

2023-05-24 Thread Clement Courbet via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9182c679dde7: [clang-tidy]performance-no-automatic-move: fix 
false negative on `const T&&`… (authored by courbet).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

Files:
  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

Index: clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
@@ -7,30 +7,42 @@
   virtual ~Obj();
 };
 
-template 
-struct StatusOr {
-  StatusOr(const T &);
-  StatusOr(T &&);
-};
-
 struct NonTemplate {
   NonTemplate(const Obj &);
   NonTemplate(Obj &&);
 };
 
+template  struct TemplateCtorPair {
+  TemplateCtorPair(const T &);
+  TemplateCtorPair(T &&value);
+};
+
+template  struct UrefCtor {
+  template  UrefCtor(U &&value);
+};
+
 template 
 T Make();
 
-StatusOr PositiveStatusOrConstValue() {
+NonTemplate PositiveNonTemplate() {
   const Obj obj = Make();
-  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 PositiveTemplateCtorPair() {
   const Obj obj = Make();
-  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 PositiveUrefCtor() {
+  const Obj obj = Make();
+  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 @@
 }
 
 // FIXME: Ideally we would warn here too.
-StatusOr PositiveStatusOrLifetimeExtension() {
+UrefCtor PositiveUrefCtorLifetimeExtension() {
   const Obj &obj = Make();
   return obj;
 }
 
 // Negatives.
 
-StatusOr Temporary() {
-  return Make();
-}
+UrefCtor Temporary() { return Make(); }
 
-StatusOr ConstTemporary() {
-  return Make();
-}
+UrefCtor ConstTemporary() { return Make(); }
 
-StatusOr ConvertingMoveConstructor() {
+UrefCtor ConvertingMoveConstructor() {
   Obj obj = Make();
   return obj;
 }
@@ -85,21 +93,19 @@
   return obj2;
 }
 
-StatusOr Ref() {
+UrefCtor Ref() {
   Obj &obj = Make();
   return obj;
 }
 
-StatusOr ConstRef() {
+UrefCtor ConstRef() {
   const Obj &obj = Make();
   return obj;
 }
 
 const Obj global;
 
-StatusOr Global() {
-  return global;
-}
+UrefCtor Global() { return global; }
 
 struct FromConstRefOnly {
   FromConstRefOnly(const Obj &);
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -387,6 +387,10 @@
   ` when warning would be
   emitted for a const local variable to which NRVO is applied.
 
+- Improved :doc:`performance-no-automatic-move
+  `: warn on ``const &&``
+  constructors.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
===
--- clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -48,15 +48,23 @@
   hasParameter(0, hasType(rValueReferenceType(
   pointee(type(equalsBoundNode("SrcT")));
 
+  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
+  // instantiation of `template  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)

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

2023-05-22 Thread Clement Courbet via Phabricator via cfe-commits
courbet updated this revision to Diff 524288.
courbet marked 2 inline comments as done.
courbet added a comment.

address review comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

Files:
  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

Index: clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
@@ -7,30 +7,42 @@
   virtual ~Obj();
 };
 
-template 
-struct StatusOr {
-  StatusOr(const T &);
-  StatusOr(T &&);
-};
-
 struct NonTemplate {
   NonTemplate(const Obj &);
   NonTemplate(Obj &&);
 };
 
+template  struct TemplateCtorPair {
+  TemplateCtorPair(const T &);
+  TemplateCtorPair(T &&value);
+};
+
+template  struct UrefCtor {
+  template  UrefCtor(U &&value);
+};
+
 template 
 T Make();
 
-StatusOr PositiveStatusOrConstValue() {
+NonTemplate PositiveNonTemplate() {
   const Obj obj = Make();
-  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 PositiveTemplateCtorPair() {
   const Obj obj = Make();
-  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 PositiveUrefCtor() {
+  const Obj obj = Make();
+  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 @@
 }
 
 // FIXME: Ideally we would warn here too.
-StatusOr PositiveStatusOrLifetimeExtension() {
+UrefCtor PositiveUrefCtorLifetimeExtension() {
   const Obj &obj = Make();
   return obj;
 }
 
 // Negatives.
 
-StatusOr Temporary() {
-  return Make();
-}
+UrefCtor Temporary() { return Make(); }
 
-StatusOr ConstTemporary() {
-  return Make();
-}
+UrefCtor ConstTemporary() { return Make(); }
 
-StatusOr ConvertingMoveConstructor() {
+UrefCtor ConvertingMoveConstructor() {
   Obj obj = Make();
   return obj;
 }
@@ -85,21 +93,19 @@
   return obj2;
 }
 
-StatusOr Ref() {
+UrefCtor Ref() {
   Obj &obj = Make();
   return obj;
 }
 
-StatusOr ConstRef() {
+UrefCtor ConstRef() {
   const Obj &obj = Make();
   return obj;
 }
 
 const Obj global;
 
-StatusOr Global() {
-  return global;
-}
+UrefCtor Global() { return global; }
 
 struct FromConstRefOnly {
   FromConstRefOnly(const Obj &);
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -381,6 +381,10 @@
   ` when warning would be
   emitted for a const local variable to which NRVO is applied.
 
+- Improved :doc:`performance-no-automatic-move
+  `: warn on ``const &&``
+  constructors.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
===
--- clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -48,15 +48,23 @@
   hasParameter(0, hasType(rValueReferenceType(
   pointee(type(equalsBoundNode("SrcT")));
 
+  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
+  // instantiation of `template  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(hasReturn

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

2023-05-22 Thread Eugene Zelenko via Phabricator via cfe-commits
Eugene.Zelenko added inline comments.



Comment at: clang-tools-extra/docs/ReleaseNotes.rst:385
+- Improved :doc:`performance-no-automatic-move
+  `: warn on 
`const &&`
+  constructors.

Please use double back-ticks for `const &&`.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp:118
 }
+

Is it really needed?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

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


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

2023-05-22 Thread Clement Courbet via Phabricator via cfe-commits
courbet updated this revision to Diff 524276.
courbet added a comment.

fix release note placemenfix release note placement


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D151092

Files:
  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

Index: clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
@@ -7,30 +7,42 @@
   virtual ~Obj();
 };
 
-template 
-struct StatusOr {
-  StatusOr(const T &);
-  StatusOr(T &&);
-};
-
 struct NonTemplate {
   NonTemplate(const Obj &);
   NonTemplate(Obj &&);
 };
 
+template  struct TemplateCtorPair {
+  TemplateCtorPair(const T &);
+  TemplateCtorPair(T &&value);
+};
+
+template  struct UrefCtor {
+  template  UrefCtor(U &&value);
+};
+
 template 
 T Make();
 
-StatusOr PositiveStatusOrConstValue() {
+NonTemplate PositiveNonTemplate() {
   const Obj obj = Make();
-  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 PositiveTemplateCtorPair() {
   const Obj obj = Make();
-  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 PositiveUrefCtor() {
+  const Obj obj = Make();
+  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 @@
 }
 
 // FIXME: Ideally we would warn here too.
-StatusOr PositiveStatusOrLifetimeExtension() {
+UrefCtor PositiveUrefCtorLifetimeExtension() {
   const Obj &obj = Make();
   return obj;
 }
 
 // Negatives.
 
-StatusOr Temporary() {
-  return Make();
-}
+UrefCtor Temporary() { return Make(); }
 
-StatusOr ConstTemporary() {
-  return Make();
-}
+UrefCtor ConstTemporary() { return Make(); }
 
-StatusOr ConvertingMoveConstructor() {
+UrefCtor ConvertingMoveConstructor() {
   Obj obj = Make();
   return obj;
 }
@@ -85,21 +93,19 @@
   return obj2;
 }
 
-StatusOr Ref() {
+UrefCtor Ref() {
   Obj &obj = Make();
   return obj;
 }
 
-StatusOr ConstRef() {
+UrefCtor ConstRef() {
   const Obj &obj = Make();
   return obj;
 }
 
 const Obj global;
 
-StatusOr Global() {
-  return global;
-}
+UrefCtor Global() { return global; }
 
 struct FromConstRefOnly {
   FromConstRefOnly(const Obj &);
@@ -109,3 +115,4 @@
   const Obj obj = Make();
   return obj;
 }
+
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -381,6 +381,10 @@
   ` when warning would be
   emitted for a const local variable to which NRVO is applied.
 
+- Improved :doc:`performance-no-automatic-move
+  `: warn on `const &&`
+  constructors.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
===
--- clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -48,15 +48,23 @@
   hasParameter(0, hasType(rValueReferenceType(
   pointee(type(equalsBoundNode("SrcT")));
 
+  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
+  // instantiation of `template  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(

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

2023-05-22 Thread Clement Courbet via Phabricator via cfe-commits
courbet created this revision.
courbet added a reviewer: gnanabit.
Herald added subscribers: PiotrZSL, carlosgalvezp, xazax.hun.
Herald added a reviewer: njames93.
Herald added a project: All.
courbet requested review of this revision.
Herald added a project: clang-tools-extra.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D151092

Files:
  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

Index: clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/performance/no-automatic-move.cpp
@@ -7,30 +7,42 @@
   virtual ~Obj();
 };
 
-template 
-struct StatusOr {
-  StatusOr(const T &);
-  StatusOr(T &&);
-};
-
 struct NonTemplate {
   NonTemplate(const Obj &);
   NonTemplate(Obj &&);
 };
 
+template  struct TemplateCtorPair {
+  TemplateCtorPair(const T &);
+  TemplateCtorPair(T &&value);
+};
+
+template  struct UrefCtor {
+  template  UrefCtor(U &&value);
+};
+
 template 
 T Make();
 
-StatusOr PositiveStatusOrConstValue() {
+NonTemplate PositiveNonTemplate() {
   const Obj obj = Make();
-  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 PositiveTemplateCtorPair() {
   const Obj obj = Make();
-  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 PositiveUrefCtor() {
+  const Obj obj = Make();
+  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 @@
 }
 
 // FIXME: Ideally we would warn here too.
-StatusOr PositiveStatusOrLifetimeExtension() {
+UrefCtor PositiveUrefCtorLifetimeExtension() {
   const Obj &obj = Make();
   return obj;
 }
 
 // Negatives.
 
-StatusOr Temporary() {
-  return Make();
-}
+UrefCtor Temporary() { return Make(); }
 
-StatusOr ConstTemporary() {
-  return Make();
-}
+UrefCtor ConstTemporary() { return Make(); }
 
-StatusOr ConvertingMoveConstructor() {
+UrefCtor ConvertingMoveConstructor() {
   Obj obj = Make();
   return obj;
 }
@@ -85,21 +93,19 @@
   return obj2;
 }
 
-StatusOr Ref() {
+UrefCtor Ref() {
   Obj &obj = Make();
   return obj;
 }
 
-StatusOr ConstRef() {
+UrefCtor ConstRef() {
   const Obj &obj = Make();
   return obj;
 }
 
 const Obj global;
 
-StatusOr Global() {
-  return global;
-}
+UrefCtor Global() { return global; }
 
 struct FromConstRefOnly {
   FromConstRefOnly(const Obj &);
@@ -109,3 +115,4 @@
   const Obj obj = Make();
   return obj;
 }
+
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -106,6 +106,9 @@
 - Support specifying `SystemHeaders` in the `.clang-tidy` configuration file,
   with the same functionality as the command-line option `--system-headers`.
 
+- Check :doc:`performance-no-automatic-move
+  ` now warns on `const &&` constructors.
+
 New checks
 ^^
 
Index: clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
===
--- clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
+++ clang-tools-extra/clang-tidy/performance/NoAutomaticMoveCheck.cpp
@@ -48,15 +48,23 @@
   hasParameter(0, hasType(rValueReferenceType(
   pointee(type(equalsBoundNode("SrcT")));
 
+  // A matcher for `DstT::DstT(const Src&&)`, which typically comes from an
+  // instantiation of `template  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(LValueRefCt