[clang-tools-extra] 82d4dc2 - [clang-tidy] Improve `performance-move-const-arg` message when no move constructor is available
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Sun Jun 18 04:41:56 PDT 2023
Author: AMS21
Date: 2023-06-18T11:40:47Z
New Revision: 82d4dc20efbd72e20b430913e985e38997c7a3e8
URL: https://github.com/llvm/llvm-project/commit/82d4dc20efbd72e20b430913e985e38997c7a3e8
DIFF: https://github.com/llvm/llvm-project/commit/82d4dc20efbd72e20b430913e985e38997c7a3e8.diff
LOG: [clang-tidy] Improve `performance-move-const-arg` message when no move constructor is available
We now display a simple note if the reason is that the used class does not
support move semantics.
This fixes llvm#62550
Reviewed By: PiotrZSL
Differential Revision: https://reviews.llvm.org/D153220
Added:
Modified:
clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
clang-tools-extra/docs/ReleaseNotes.rst
clang-tools-extra/test/clang-tidy/checkers/performance/move-const-arg.cpp
Removed:
################################################################################
diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
index 8d4c6de8dca72..413a37f4af9fa 100644
--- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
@@ -103,6 +103,7 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
AlreadyCheckedMoves.insert(CallMove);
const Expr *Arg = CallMove->getArg(0);
+ const QualType ArgType = Arg->getType().getCanonicalType();
SourceManager &SM = Result.Context->getSourceManager();
CharSourceRange MoveRange =
@@ -112,12 +113,11 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
if (!FileMoveRange.isValid())
return;
- bool IsConstArg = Arg->getType().isConstQualified();
- bool IsTriviallyCopyable =
- Arg->getType().isTriviallyCopyableType(*Result.Context);
+ bool IsConstArg = ArgType.isConstQualified();
+ bool IsTriviallyCopyable = ArgType.isTriviallyCopyableType(*Result.Context);
if (IsConstArg || IsTriviallyCopyable) {
- if (const CXXRecordDecl *R = Arg->getType()->getAsCXXRecordDecl()) {
+ if (const CXXRecordDecl *R = ArgType->getAsCXXRecordDecl()) {
// According to [expr.prim.lambda]p3, "whether the closure type is
// trivially copyable" property can be changed by the implementation of
// the language, so we shouldn't rely on it when issuing diagnostics.
@@ -196,11 +196,28 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
if ((*InvocationParmType)->isRValueReferenceType())
return;
- auto Diag = diag(FileMoveRange.getBegin(),
- "passing result of std::move() as a const reference "
- "argument; no move will actually happen");
+ {
+ auto Diag = diag(FileMoveRange.getBegin(),
+ "passing result of std::move() as a const reference "
+ "argument; no move will actually happen");
+
+ replaceCallWithArg(CallMove, Diag, SM, getLangOpts());
+ }
- replaceCallWithArg(CallMove, Diag, SM, getLangOpts());
+ if (const CXXRecordDecl *RecordDecl = ArgType->getAsCXXRecordDecl();
+ RecordDecl && !(RecordDecl->hasMoveConstructor() &&
+ RecordDecl->hasMoveAssignment())) {
+ const bool MissingMoveAssignment = !RecordDecl->hasMoveAssignment();
+ const bool MissingMoveConstructor = !RecordDecl->hasMoveConstructor();
+ const bool MissingBoth = MissingMoveAssignment && MissingMoveConstructor;
+
+ diag(RecordDecl->getLocation(),
+ "%0 is not move "
+ "%select{|assignable}1%select{|/}2%select{|constructible}3",
+ DiagnosticIDs::Note)
+ << RecordDecl << MissingMoveAssignment << MissingBoth
+ << MissingMoveConstructor;
+ }
}
}
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 7fa744d173649..1ca2db986ef90 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -378,6 +378,10 @@ Changes in existing checks
`IgnoreTemplateInstantiations` option to optionally ignore virtual function
overrides that are part of template instantiations.
+- Improved :doc:`performance-move-const-arg
+ <clang-tidy/checks/performance/move-const-arg>` check to warn when move
+ special member functions are not available.
+
- Improved :doc:`performance-no-automatic-move
<clang-tidy/checks/performance/no-automatic-move>`: warn on ``const &&``
constructors.
diff --git a/clang-tools-extra/test/clang-tidy/checkers/performance/move-const-arg.cpp b/clang-tools-extra/test/clang-tidy/checkers/performance/move-const-arg.cpp
index c1e5761c538e9..4d90c124ad72c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/performance/move-const-arg.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/performance/move-const-arg.cpp
@@ -39,10 +39,14 @@ class A {
A(A &&rhs) {}
};
+using AlsoA = A;
+
struct TriviallyCopyable {
int i;
};
+using TrivialAlias = TriviallyCopyable;
+
void f(TriviallyCopyable) {}
void g() {
@@ -50,6 +54,11 @@ void g() {
f(std::move(obj));
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable' has no effect; remove std::move() [performance-move-const-arg]
// CHECK-FIXES: f(obj);
+
+ TrivialAlias obj2;
+ f(std::move(obj2));
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: std::move of the variable 'obj2' of the trivially-copyable type 'TrivialAlias' (aka 'TriviallyCopyable') has no effect; remove std::move() [performance-move-const-arg]
+ // CHECK-FIXES: f(obj2);
}
int f1() {
@@ -72,12 +81,20 @@ int *f3(int *x3) {
A f4(A x4) { return std::move(x4); }
+AlsoA f4_a(AlsoA x4) { return std::move(x4); }
+
A f5(const A x5) {
return std::move(x5);
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x5' has no effect; remove std::move() or make the variable non-const [performance-move-const-arg]
// CHECK-FIXES: return x5;
}
+AlsoA f5_a(const AlsoA x5) {
+ return std::move(x5);
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the const variable 'x5' has no effect; remove std::move() or make the variable non-const [performance-move-const-arg]
+ // CHECK-FIXES: return x5;
+}
+
template <typename T>
T f6(const T x6) {
return std::move(x6);
@@ -115,6 +132,8 @@ class NoMoveSemantics {
NoMoveSemantics &operator=(const NoMoveSemantics &);
};
+using NoMoveSemanticsAlias = NoMoveSemantics;
+
void callByConstRef(const NoMoveSemantics &);
void callByConstRef(int i, const NoMoveSemantics &);
@@ -147,6 +166,35 @@ void moveToConstReferencePositives() {
// CHECK-FIXES: other = obj;
}
+void moveToConstReferencePositivesAlias() {
+ NoMoveSemanticsAlias obj;
+
+ // Basic case.
+ callByConstRef(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: callByConstRef(obj);
+
+ // Also works for second argument.
+ callByConstRef(1, std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: callByConstRef(1, obj);
+
+ // Works if std::move() applied to a temporary.
+ callByConstRef(std::move(NoMoveSemanticsAlias()));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: callByConstRef(NoMoveSemanticsAlias());
+
+ // Works if calling a copy constructor.
+ NoMoveSemanticsAlias other(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: NoMoveSemanticsAlias other(obj);
+
+ // Works if calling assignment operator.
+ other = std::move(obj);
+ // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-FIXES: other = obj;
+}
+
class MoveSemantics {
public:
MoveSemantics();
@@ -155,6 +203,8 @@ class MoveSemantics {
MoveSemantics &operator=(MoveSemantics &&);
};
+using MoveSemanticsAlias = MoveSemantics;
+
void callByValue(MoveSemantics);
void callByRValueRef(MoveSemantics &&);
@@ -197,6 +247,32 @@ void moveToConstReferenceNegatives() {
auto lambda2 = std::move(lambda);
}
+void moveToConstReferenceNegativesAlias() {
+ // No warning when actual move takes place.
+ MoveSemanticsAlias move_semantics;
+ callByValue(std::move(move_semantics));
+ callByRValueRef(std::move(move_semantics));
+ MoveSemanticsAlias other(std::move(move_semantics));
+ other = std::move(move_semantics);
+
+ // No warning if std::move() not used.
+ NoMoveSemanticsAlias no_move_semantics;
+ callByConstRef(no_move_semantics);
+
+ // No warning if instantiating a template.
+ templateFunction(no_move_semantics);
+
+ // No warning inside of macro expansions.
+ M3(NoMoveSemanticsAlias, no_move_semantics);
+
+ // No warning inside of macro expansion, even if the macro expansion is inside
+ // a lambda that is, in turn, an argument to a macro.
+ CALL([no_move_semantics] { M3(NoMoveSemanticsAlias, no_move_semantics); });
+
+ auto lambda = [] {};
+ auto lambda2 = std::move(lambda);
+}
+
class MoveOnly {
public:
MoveOnly(const MoveOnly &other) = delete;
@@ -210,6 +286,8 @@ void moveOnlyNegatives(MoveOnly val) {
Q(std::move(val));
}
+using MoveOnlyAlias = MoveOnly;
+
void fmovable(MoveSemantics);
void lambda1() {
@@ -236,6 +314,12 @@ void functionInvocation() {
callback(std::move(m));
}
+void functionInvocationAlias() {
+ function<void(MoveSemanticsAlias)> callback;
+ MoveSemanticsAlias m;
+ callback(std::move(m));
+}
+
void lambda2() {
function<void(MoveSemantics)> callback;
@@ -247,6 +331,17 @@ void lambda2() {
f(MoveSemantics());
}
+void lambda2Alias() {
+ function<void(MoveSemanticsAlias)> callback;
+
+ auto f = [callback = std::move(callback)](MoveSemanticsAlias m) mutable {
+ // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: std::move of the variable 'callback' of the trivially-copyable type 'function<void (MoveSemanticsAlias)>' (aka 'function<void (MoveSemantics)>') has no effect; remove std::move() [performance-move-const-arg]
+ // CHECK-FIXES: auto f = [callback = callback](MoveSemanticsAlias m) mutable {
+ callback(std::move(m));
+ };
+ f(MoveSemanticsAlias());
+}
+
void showInt(int &&v);
void showInt(int v1, int &&v2);
void showPointer(const char *&&s);
@@ -266,7 +361,7 @@ void testFunctions() {
showPointer(std::move(s));
// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: std::move of the variable 's' of the trivially-copyable type 'const char *' has no effect [performance-move-const-arg]
// CHECK-MESSAGES: :[[@LINE-16]]:32: note: consider changing the 1st parameter of 'showPointer' from 'const char *&&' to 'const char *'
- showPointer2(std::move(s));
+ showPointer2(std::move(s));
// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: std::move of the variable 's' of the trivially-copyable type 'const char *' has no effect [performance-move-const-arg]
// CHECK-MESSAGES: :[[@LINE-18]]:39: note: consider changing the 1st parameter of 'showPointer2' from 'const char *const &&' to 'const char *const'
TriviallyCopyable *obj = new TriviallyCopyable();
@@ -276,6 +371,13 @@ void testFunctions() {
showTriviallyCopyablePointer(std::move(obj));
// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable *' has no effect [performance-move-const-arg]
// CHECK-MESSAGES: :[[@LINE-23]]:62: note: consider changing the 1st parameter of 'showTriviallyCopyablePointer' from 'const TriviallyCopyable *&&' to 'const TriviallyCopyable *'
+ TrivialAlias* obj2 = new TrivialAlias();
+ showTriviallyCopyable(std::move(*obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: std::move of the expression of the trivially-copyable type 'TriviallyCopyable' has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-28]]:48: note: consider changing the 1st parameter of 'showTriviallyCopyable' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ showTriviallyCopyablePointer(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable *' has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-30]]:62: note: consider changing the 1st parameter of 'showTriviallyCopyablePointer' from 'const TriviallyCopyable *&&' to 'const TriviallyCopyable *'
}
template <class T>
void forwardToShowInt(T && t) {
@@ -297,32 +399,62 @@ struct Tmp {
void showTmp(TriviallyCopyable&& t);
static void showTmpStatic(TriviallyCopyable&& t);
};
+using TmpAlias = Tmp;
+
void testMethods() {
Tmp t;
int a = 10;
Tmp t1(std::move(a));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'a' of the trivially-copyable type 'int' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-13]]:13: note: consider changing the 1st parameter of 'Tmp' from 'int &&' to 'const int &'
+ // CHECK-MESSAGES: :[[@LINE-15]]:13: note: consider changing the 1st parameter of 'Tmp' from 'int &&' to 'const int &'
Tmp t2(a, std::move(a));
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: std::move of the variable 'a' of the trivially-copyable type 'int' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-15]]:21: note: consider changing the 2nd parameter of 'Tmp' from 'int &&' to 'const int &'
+ // CHECK-MESSAGES: :[[@LINE-17]]:21: note: consider changing the 2nd parameter of 'Tmp' from 'int &&' to 'const int &'
const char* s = "";
Tmp t3(std::move(s));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 's' of the trivially-copyable type 'const char *' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-18]]:21: note: consider changing the 1st parameter of 'Tmp' from 'const char *&&' to 'const char *'
+ // CHECK-MESSAGES: :[[@LINE-20]]:21: note: consider changing the 1st parameter of 'Tmp' from 'const char *&&' to 'const char *'
TriviallyCopyable *obj = new TriviallyCopyable();
Tmp t4(std::move(*obj));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the expression of the trivially-copyable type 'TriviallyCopyable' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-21]]:27: note: consider changing the 1st parameter of 'Tmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ // CHECK-MESSAGES: :[[@LINE-23]]:27: note: consider changing the 1st parameter of 'Tmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
Tmp t5(std::move(obj));
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: std::move of the variable 'obj' of the trivially-copyable type 'TriviallyCopyable *' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-23]]:34: note: consider changing the 1st parameter of 'Tmp' from 'const TriviallyCopyable *&&' to 'const TriviallyCopyable *'
+ // CHECK-MESSAGES: :[[@LINE-25]]:34: note: consider changing the 1st parameter of 'Tmp' from 'const TriviallyCopyable *&&' to 'const TriviallyCopyable *'
t.showTmp(std::move(*obj));
// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: std::move of the expression of the trivially-copyable type 'TriviallyCopyable' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-25]]:36: note: consider changing the 1st parameter of 'showTmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ // CHECK-MESSAGES: :[[@LINE-27]]:36: note: consider changing the 1st parameter of 'showTmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
Tmp::showTmpStatic(std::move(*obj));
// CHECK-MESSAGES: :[[@LINE-1]]:22: warning: std::move of the expression of the trivially-copyable type 'TriviallyCopyable' has no effect [performance-move-const-arg]
- // CHECK-MESSAGES: :[[@LINE-27]]:49: note: consider changing the 1st parameter of 'showTmpStatic' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ // CHECK-MESSAGES: :[[@LINE-29]]:49: note: consider changing the 1st parameter of 'showTmpStatic' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+}
+
+void testMethodsAlias() {
+ TmpAlias t;
+ int a = 10;
+ TmpAlias t1(std::move(a));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: std::move of the variable 'a' of the trivially-copyable type 'int' has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-43]]:13: note: consider changing the 1st parameter of 'Tmp' from 'int &&' to 'const int &'
+ TmpAlias t2(a, std::move(a));
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: std::move of the variable 'a' of the trivially-copyable type 'int' has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-45]]:21: note: consider changing the 2nd parameter of 'Tmp' from 'int &&' to 'const int &'
+ const char* s = "";
+ TmpAlias t3(std::move(s));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: std::move of the variable 's' of the trivially-copyable type 'const char *' has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-48]]:21: note: consider changing the 1st parameter of 'Tmp' from 'const char *&&' to 'const char *'
+ TrivialAlias *obj = new TrivialAlias();
+ TmpAlias t4(std::move(*obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: std::move of the expression of the trivially-copyable type 'TrivialAlias' (aka 'TriviallyCopyable') has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-51]]:27: note: consider changing the 1st parameter of 'Tmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ TmpAlias t5(std::move(obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: std::move of the variable 'obj' of the trivially-copyable type 'TrivialAlias *' (aka 'TriviallyCopyable *') has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-53]]:34: note: consider changing the 1st parameter of 'Tmp' from 'const TriviallyCopyable *&&' to 'const TriviallyCopyable *'
+ t.showTmp(std::move(*obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: std::move of the expression of the trivially-copyable type 'TrivialAlias' (aka 'TriviallyCopyable') has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-55]]:36: note: consider changing the 1st parameter of 'showTmp' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
+ TmpAlias::showTmpStatic(std::move(*obj));
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: std::move of the expression of the trivially-copyable type 'TrivialAlias' (aka 'TriviallyCopyable') has no effect [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-57]]:49: note: consider changing the 1st parameter of 'showTmpStatic' from 'TriviallyCopyable &&' to 'const TriviallyCopyable &'
}
void showA(A &&v) {}
@@ -331,6 +463,11 @@ void testA() {
showA(std::move(a));
}
+void testAAlias() {
+ AlsoA a;
+ showA(std::move(a));
+}
+
void testFuncPointer() {
int a = 10;
void (*choice)(int, int &&);
@@ -340,3 +477,68 @@ void testFuncPointer() {
// CHECK-FIXES: choice(a, std::move(a));
// CHECK-MESSAGES: :[[@LINE-3]]:24: warning: std::move of the variable 'a' of the trivially-copyable type 'int' has no effect [performance-move-const-arg]
}
+
+namespace issue_62550 {
+
+struct NonMoveConstructable {
+ NonMoveConstructable();
+ NonMoveConstructable(const NonMoveConstructable&);
+ NonMoveConstructable& operator=(const NonMoveConstructable&);
+ NonMoveConstructable& operator=(NonMoveConstructable&&);
+};
+
+void testNonMoveConstructible() {
+ NonMoveConstructable t1;
+ NonMoveConstructable t2{std::move(t1)};
+ // CHECK-MESSAGES: :[[@LINE-1]]:27: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-11]]:8: note: 'NonMoveConstructable' is not move constructible
+}
+
+struct NonMoveAssignable {
+ NonMoveAssignable();
+ NonMoveAssignable(const NonMoveAssignable&);
+ NonMoveAssignable(NonMoveAssignable&&);
+
+ NonMoveAssignable& operator=(const NonMoveAssignable&);
+};
+
+void testNonMoveAssignable() {
+ NonMoveAssignable t1;
+ NonMoveAssignable t2;
+
+ t2 = std::move(t1);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-14]]:8: note: 'NonMoveAssignable' is not move assignable
+}
+
+struct NonMoveable {
+ NonMoveable();
+ NonMoveable(const NonMoveable&);
+ NonMoveable& operator=(const NonMoveable&);
+};
+
+void testNonMoveable() {
+ NonMoveable t1;
+ NonMoveable t2{std::move(t1)};
+ // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-10]]:8: note: 'NonMoveable' is not move assignable/constructible
+
+ t1 = std::move(t2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-14]]:8: note: 'NonMoveable' is not move assignable/constructible
+}
+
+using AlsoNonMoveable = NonMoveable;
+
+void testAlsoNonMoveable() {
+ AlsoNonMoveable t1;
+ AlsoNonMoveable t2{std::move(t1)};
+ // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-23]]:8: note: 'NonMoveable' is not move assignable/constructible
+
+ t1 = std::move(t2);
+ // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: passing result of std::move() as a const reference argument; no move will actually happen [performance-move-const-arg]
+ // CHECK-MESSAGES: :[[@LINE-27]]:8: note: 'NonMoveable' is not move assignable/constructible
+}
+
+} // namespace issue_62550
More information about the cfe-commits
mailing list