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