Clang Project

clang_source_code/test/SemaCXX/warn-pessmizing-move.cpp
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
5namespace std {
6inline namespace foo {
7template <class T> struct remove_reference { typedef T type; };
8template <class T> struct remove_reference<T&> { typedef T type; };
9template <class T> struct remove_reference<T&&> { typedef T type; };
10
11template <class T> typename remove_reference<T>::type &&move(T &&t);
12}
13}
14
15struct A {};
16struct B {
17  B() {}
18  B(A) {}
19};
20
21A 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
33B 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
52A global_a;
53A 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
63A 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
79void 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
95void 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
111A 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.
160A 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.
186test9
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.
193A test10() {
194  A a;
195  return_a;
196  // expected-warning@-1{{prevents copy elision}}
197  // CHECK-NOT: fix-it
198}
199
200namespace templates {
201  struct A {};
202  struct B { B(A); };
203
204  // Warn once here since the type is not dependent.
205  template <typename T>
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  }
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  }
225  void run_test2() {
226    test2<A, A>();
227    test2<B, A>();
228  }
229}
230