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