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