blob: d160695207ad6f8c76b73c4a66da9e9165cc6400 [file] [log] [blame]
Richard Trieuac3eca52015-04-29 01:52:17 +00001// RUN: %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -verify %s
Richard Trieu8d4006a2015-07-28 19:06:16 +00002// RUN: not %clang_cc1 -fsyntax-only -Wredundant-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
Richard Trieuac3eca52015-04-29 01:52:17 +00003
4// definitions for std::move
5namespace std {
6inline namespace foo {
7template <class T> struct remove_reference { typedef T type; };
8template <class T> struct remove_reference<T&> { typedef T type; };
9template <class T> struct remove_reference<T&&> { typedef T type; };
10
11template <class T> typename remove_reference<T>::type &&move(T &&t);
12}
13}
14
15struct A {};
16struct B : public A {};
17
18A test1(B b1) {
19 B b2;
Richard Trieu1d4911bc2015-05-18 19:54:08 +000020 return b1;
21 return b2;
Richard Trieuac3eca52015-04-29 01:52:17 +000022 return std::move(b1);
23 // expected-warning@-1{{redundant move}}
24 // expected-note@-2{{remove std::move call}}
25 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
26 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
27 return std::move(b2);
28 // expected-warning@-1{{redundant move}}
29 // expected-note@-2{{remove std::move call}}
30 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
31 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
32}
33
34struct C {
35 C() {}
36 C(A) {}
37};
38
39C test2(A a1, B b1) {
40 A a2;
41 B b2;
42
43 return a1;
44 return a2;
45 return b1;
46 return b2;
47
48 return std::move(a1);
49 // expected-warning@-1{{redundant move}}
50 // expected-note@-2{{remove std::move call}}
51 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
52 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
53 return std::move(a2);
54 // expected-warning@-1{{redundant move}}
55 // expected-note@-2{{remove std::move call}}
56 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
57 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
58 return std::move(b1);
59 // expected-warning@-1{{redundant move}}
60 // expected-note@-2{{remove std::move call}}
61 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
62 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
63 return std::move(b2);
64 // expected-warning@-1{{redundant move}}
65 // expected-note@-2{{remove std::move call}}
66 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
67 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
68}
Richard Trieu1d4911bc2015-05-18 19:54:08 +000069
70// Copy of tests above with types changed to reference types.
71A test3(B& b1) {
72 B& b2 = b1;
73 return b1;
74 return b2;
75 return std::move(b1);
76 return std::move(b2);
77}
78
79C test4(A& a1, B& b1) {
80 A& a2 = a1;
81 B& b2 = b1;
82
83 return a1;
84 return a2;
85 return b1;
86 return b2;
87
88 return std::move(a1);
89 return std::move(a2);
90 return std::move(b1);
91 return std::move(b2);
92}
Davide Italiano7842c3f2015-07-18 01:15:19 +000093
Richard Trieu159e5ed2015-07-21 23:38:30 +000094// PR23819, case 2
95struct D {};
96D test5(D d) {
97 return d;
98
99 return std::move(d);
100 // expected-warning@-1{{redundant move in return statement}}
101 // expected-note@-2{{remove std::move call here}}
102 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
103 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
104}
Richard Trieu8d4006a2015-07-28 19:06:16 +0000105
Richard Trieu6093d142015-07-29 17:03:34 +0000106namespace templates {
107 struct A {};
108 struct B { B(A); };
109 struct C { C(); C(C&&); };
110 struct D { D(C); };
111
112 // Warn once here since the type is not dependent.
113 template <typename T>
114 B test1() {
115 A a;
116 return std::move(a);
117 // expected-warning@-1{{redundant move in return statement}}
118 // expected-note@-2{{remove std::move call here}}
119 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
120 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
121 }
122 void run_test1() {
123 test1<A>();
124 test1<B>();
125 test1<C>();
126 test1<D>();
127 }
128
129 // Either a pessimizing move, a redundant move, or no warning could be
130 // emitted, given the right types. So just drop the warning.
131 template <typename T1, typename T2>
132 T1 test2() {
133 T2 t;
134 return std::move(t);
135 }
136 void run_test2() {
137 test2<A, A>();
138 test2<B, A>();
139 test2<D, C>();
140 }
141}
142
Richard Trieu8d4006a2015-07-28 19:06:16 +0000143// No more fix-its past here.
144// CHECK-NOT: fix-it
145
146// A deleted copy constructor will prevent moves without std::move
147struct E {
148 E(E &&e);
149 E(const E &e) = delete;
150 // expected-note@-1{{deleted here}}
151};
152
153struct F {
154 F(E);
155 // expected-note@-1{{passing argument to parameter here}}
156};
157
158F test6(E e) {
159 return e;
160 // expected-error@-1{{call to deleted constructor of 'E'}}
161 return std::move(e);
162}
163
164struct G {
165 G(G &&g);
166 // expected-note@-1{{copy constructor is implicitly deleted because 'G' has a user-declared move constructor}}
167};
168
169struct H {
170 H(G);
171 // expected-note@-1{{passing argument to parameter here}}
172};
173
174H test6(G g) {
175 return g; // expected-error{{call to implicitly-deleted copy constructor of 'G'}}
176 return std::move(g);
177}