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