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 18 A() {} 19 A(const A &) {} 20 A(A &&) {} 21 A &operator=(const A &) { return *this; } 22 A &operator=(A &&) { return *this; } 23 #endif 24 }; 25 struct B { 26 B() {} 27 B(A) {} 28 }; 29 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 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; 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 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 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 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 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. 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. 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> 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 } 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 } 260 void run_test2() { 261 test2<A, A>(); 262 test2<B, A>(); 263 } 264 } 265