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 { 17 B() {} 18 B(A) {} 19 }; 20 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 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; 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 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 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 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 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. 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. 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> 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