diff options
| author | Richard Trieu <rtrieu@google.com> | 2015-04-29 01:52:17 +0000 |
|---|---|---|
| committer | Richard Trieu <rtrieu@google.com> | 2015-04-29 01:52:17 +0000 |
| commit | ac3eca536d3de943f4accd3d52a5ed31e3662017 (patch) | |
| tree | 268dfa85eadc684cb50c5d4fe2b47b12d817a867 /clang/test/SemaCXX/warn-pessmizing-move.cpp | |
| parent | f3a8362bf28b80573e4ca27aa5e9f81817c4dd4f (diff) | |
| download | bcm5719-llvm-ac3eca536d3de943f4accd3d52a5ed31e3662017.tar.gz bcm5719-llvm-ac3eca536d3de943f4accd3d52a5ed31e3662017.zip | |
Add -Wpessimizing-move and -Wredundant-move warnings.
-Wpessimizing-move warns when a call to std::move would prevent copy elision
if the argument was not wrapped in a call. This happens when moving a local
variable in a return statement when the variable is the same type as the
return type or using a move to create a new object from a temporary object.
-Wredundant-move warns when an implicit move would already be made, so the
std::move call is not needed, such as when moving a local variable in a return
that is different from the return type.
Differential Revision: http://reviews.llvm.org/D7633
llvm-svn: 236075
Diffstat (limited to 'clang/test/SemaCXX/warn-pessmizing-move.cpp')
| -rw-r--r-- | clang/test/SemaCXX/warn-pessmizing-move.cpp | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/warn-pessmizing-move.cpp b/clang/test/SemaCXX/warn-pessmizing-move.cpp new file mode 100644 index 00000000000..6b49944f287 --- /dev/null +++ b/clang/test/SemaCXX/warn-pessmizing-move.cpp @@ -0,0 +1,203 @@ +// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s +// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s + +// definitions for std::move +namespace std { +inline namespace foo { +template <class T> struct remove_reference { typedef T type; }; +template <class T> struct remove_reference<T&> { typedef T type; }; +template <class T> struct remove_reference<T&&> { typedef T type; }; + +template <class T> typename remove_reference<T>::type &&move(T &&t); +} +} + +struct A {}; +struct B { + B() {} + B(A) {} +}; + +A test1(A a1) { + A a2; + return a1; + return a2; + return std::move(a1); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" + return std::move(a2); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" +} + +B test2(A a1, B b1) { + // Object is different than return type so don't warn. + A a2; + return a1; + return a2; + return std::move(a1); + return std::move(a2); + + B b2; + return b1; + return b2; + return std::move(b1); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" + return std::move(b2); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" +} + +A global_a; +A test3() { + // Don't warn when object is not local. + return global_a; + return std::move(global_a); + static A static_a; + return static_a; + return std::move(static_a); + +} + +A test4() { + return A(); + return test3(); + + return std::move(A()); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:"" + return std::move(test3()); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:"" +} + +void test5(A) { + test5(A()); + test5(test4()); + + test5(std::move(A())); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" + test5(std::move(test4())); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:"" +} + +void test6() { + A a1 = A(); + A a2 = test3(); + + A a3 = std::move(A()); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:"" + A a4 = std::move(test3()); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:"" +} + +A test7() { + A a1 = std::move(A()); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:"" + A a2 = std::move((A())); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:"" + A a3 = (std::move(A())); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:"" + A a4 = (std::move((A()))); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:"" + + return std::move(a1); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:"" + return std::move((a1)); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:"" + return (std::move(a1)); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:"" + return (std::move((a1))); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:"" +} + +#define wrap1(x) x +#define wrap2(x) x + +// Macro test. Since the std::move call is outside the macro, it is +// safe to suggest a fix-it. +A test8(A a) { + return std::move(a); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:"" + return std::move(wrap1(a)); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:28-[[@LINE-4]]:29}:"" + return std::move(wrap1(wrap2(a))); + // expected-warning@-1{{prevents copy elision}} + // expected-note@-2{{remove std::move call}} + // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:"" + // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:35-[[@LINE-4]]:36}:"" +} + +#define test9 \ + A test9(A a) { \ + return std::move(a); \ + } + +// Macro test. The std::call is inside the macro, so no fix-it is suggested. +test9 +// expected-warning@-1{{prevents copy elision}} +// CHECK-NOT: fix-it + +#define return_a return std::move(a) + +// Macro test. The std::call is inside the macro, so no fix-it is suggested. +A test10(A a) { + return_a; + // expected-warning@-1{{prevents copy elision}} + // CHECK-NOT: fix-it +} |

