1 // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s -DUSER_DEFINED
3 // RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
4
5 // definitions for std::move
6 namespace std {
7 inline namespace foo {
8 template <class T> struct remove_reference { typedef T type; };
9 template <class T> struct remove_reference<T&> { typedef T type; };
10 template <class T> struct remove_reference<T&&> { typedef T type; };
11
12 template <class T> typename remove_reference<T>::type &&move(T &&t);
13 }
14 }
15
16 struct A {
17 #ifdef USER_DEFINED
AA18 A() {}
AA19 A(const A &) {}
AA20 A(A &&) {}
operator =A21 A &operator=(const A &) { return *this; }
operator =A22 A &operator=(A &&) { return *this; }
23 #endif
24 };
25 struct B {
BB26 B() {}
BB27 B(A) {}
28 };
29
test1(A a1)30 A test1(A a1) {
31 A a2;
32 return a1;
33 return a2;
34 return std::move(a1);
35 return std::move(a2);
36 // expected-warning@-1{{prevents copy elision}}
37 // expected-note@-2{{remove std::move call}}
38 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
39 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
40 }
41
test2(A a1,B b1)42 B test2(A a1, B b1) {
43 // Object is different than return type so don't warn.
44 A a2;
45 return a1;
46 return a2;
47 return std::move(a1);
48 return std::move(a2);
49
50 B b2;
51 return b1;
52 return b2;
53 return std::move(b1);
54 return std::move(b2);
55 // expected-warning@-1{{prevents copy elision}}
56 // expected-note@-2{{remove std::move call}}
57 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
58 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
59
60 return A();
61 return test1(a2);
62 return std::move(A());
63 // expected-warning@-1{{prevents copy elision}}
64 // expected-note@-2{{remove std::move call}}
65 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
66 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
67 return std::move(test1(a2));
68 // expected-warning@-1{{prevents copy elision}}
69 // expected-note@-2{{remove std::move call}}
70 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
71 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:29-[[@LINE-4]]:30}:""
72 }
73
74 A global_a;
test3()75 A test3() {
76 // Don't warn when object is not local.
77 return global_a;
78 return std::move(global_a);
79 static A static_a;
80 return static_a;
81 return std::move(static_a);
82
83 }
84
test4()85 A test4() {
86 return A();
87 return test3();
88
89 return std::move(A());
90 // expected-warning@-1{{prevents copy elision}}
91 // expected-note@-2{{remove std::move call}}
92 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
93 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
94 return std::move(test3());
95 // expected-warning@-1{{prevents copy elision}}
96 // expected-note@-2{{remove std::move call}}
97 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
98 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
99 }
100
test5(A)101 void test5(A) {
102 test5(A());
103 test5(test4());
104
105 test5(std::move(A()));
106 // expected-warning@-1{{prevents copy elision}}
107 // expected-note@-2{{remove std::move call}}
108 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
109 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
110 test5(std::move(test4()));
111 // expected-warning@-1{{prevents copy elision}}
112 // expected-note@-2{{remove std::move call}}
113 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:9-[[@LINE-3]]:19}:""
114 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""
115 }
116
test6()117 void test6() {
118 A a1 = A();
119 A a2 = test3();
120
121 A a3 = std::move(A());
122 // expected-warning@-1{{prevents copy elision}}
123 // expected-note@-2{{remove std::move call}}
124 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
125 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
126
127 a3 = std::move(A());
128 // expected-warning@-1{{prevents copy elision}}
129 // expected-note@-2{{remove std::move call}}
130 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:18}:""
131 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
132
133 A a4 = std::move(test3());
134 // expected-warning@-1{{prevents copy elision}}
135 // expected-note@-2{{remove std::move call}}
136 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
137 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:27-[[@LINE-4]]:28}:""
138
139 a4 = std::move(test3());
140 // expected-warning@-1{{prevents copy elision}}
141 // expected-note@-2{{remove std::move call}}
142 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:8-[[@LINE-3]]:18}:""
143 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
144 }
145
test7()146 A test7() {
147 A a1 = std::move(A());
148 // expected-warning@-1{{prevents copy elision}}
149 // expected-note@-2{{remove std::move call}}
150 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
151 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
152 A a2 = std::move((A()));
153 // expected-warning@-1{{prevents copy elision}}
154 // expected-note@-2{{remove std::move call}}
155 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
156 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
157 A a3 = (std::move(A()));
158 // expected-warning@-1{{prevents copy elision}}
159 // expected-note@-2{{remove std::move call}}
160 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
161 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""
162 A a4 = (std::move((A())));
163 // expected-warning@-1{{prevents copy elision}}
164 // expected-note@-2{{remove std::move call}}
165 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
166 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:26-[[@LINE-4]]:27}:""
167
168 return std::move(a1);
169 // expected-warning@-1{{prevents copy elision}}
170 // expected-note@-2{{remove std::move call}}
171 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
172 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:22-[[@LINE-4]]:23}:""
173 return std::move((a1));
174 // expected-warning@-1{{prevents copy elision}}
175 // expected-note@-2{{remove std::move call}}
176 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
177 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:24-[[@LINE-4]]:25}:""
178 return (std::move(a1));
179 // expected-warning@-1{{prevents copy elision}}
180 // expected-note@-2{{remove std::move call}}
181 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
182 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
183 return (std::move((a1)));
184 // expected-warning@-1{{prevents copy elision}}
185 // expected-note@-2{{remove std::move call}}
186 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:11-[[@LINE-3]]:21}:""
187 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:25-[[@LINE-4]]:26}:""
188 }
189
190 #define wrap1(x) x
191 #define wrap2(x) x
192
193 // Macro test. Since the std::move call is outside the macro, it is
194 // safe to suggest a fix-it.
test8()195 A test8() {
196 A a;
197 return std::move(a);
198 // expected-warning@-1{{prevents copy elision}}
199 // expected-note@-2{{remove std::move call}}
200 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
201 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:21-[[@LINE-4]]:22}:""
202 return std::move(wrap1(a));
203 // expected-warning@-1{{prevents copy elision}}
204 // expected-note@-2{{remove std::move call}}
205 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
206 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:28-[[@LINE-4]]:29}:""
207 return std::move(wrap1(wrap2(a)));
208 // expected-warning@-1{{prevents copy elision}}
209 // expected-note@-2{{remove std::move call}}
210 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:10-[[@LINE-3]]:20}:""
211 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:35-[[@LINE-4]]:36}:""
212 }
213
214 #define test9 \
215 A test9() { \
216 A a; \
217 return std::move(a); \
218 }
219
220 // Macro test. The std::call is inside the macro, so no fix-it is suggested.
221 test9
222 // expected-warning@-1{{prevents copy elision}}
223 // CHECK-NOT: fix-it
224
225 #define return_a return std::move(a)
226
227 // Macro test. The std::call is inside the macro, so no fix-it is suggested.
test10()228 A test10() {
229 A a;
230 return_a;
231 // expected-warning@-1{{prevents copy elision}}
232 // CHECK-NOT: fix-it
233 }
234
235 namespace templates {
236 struct A {};
237 struct B { B(A); };
238
239 // Warn once here since the type is not dependent.
240 template <typename T>
test1()241 A test1() {
242 A a;
243 return std::move(a);
244 // expected-warning@-1{{prevents copy elision}}
245 // expected-note@-2{{remove std::move call}}
246 // CHECK: fix-it:"{{.*}}":{[[@LINE-3]]:12-[[@LINE-3]]:22}:""
247 // CHECK: fix-it:"{{.*}}":{[[@LINE-4]]:23-[[@LINE-4]]:24}:""
248 }
run_test1()249 void run_test1() {
250 test1<A>();
251 test1<B>();
252 }
253
254 // T1 and T2 may not be the same, the warning may not always apply.
255 template <typename T1, typename T2>
256 T1 test2() {
257 T2 t;
258 return std::move(t);
259 }
run_test2()260 void run_test2() {
261 test2<A, A>();
262 test2<B, A>();
263 }
264 }
265