blob: 6b49944f287813f667e3f1269cb372fe93b73315 [file] [log] [blame]
// 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
}