265 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s2// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -verify %s -DUSER_DEFINED3// RUN: %clang_cc1 -fsyntax-only -Wpessimizing-move -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s4 5// definitions for std::move6namespace std {7inline namespace foo {8template <class T> struct remove_reference { typedef T type; };9template <class T> struct remove_reference<T&> { typedef T type; };10template <class T> struct remove_reference<T&&> { typedef T type; };11 12template <class T> typename remove_reference<T>::type &&move(T &&t);13}14}15 16struct A {17#ifdef USER_DEFINED18 A() {}19 A(const A &) {}20 A(A &&) {}21 A &operator=(const A &) { return *this; }22 A &operator=(A &&) { return *this; }23#endif24};25struct B {26 B() {}27 B(A) {}28};29 30A 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 42B 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 74A global_a;75A 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 85A 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 101void 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 117void 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 146A 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) x191#define wrap2(x) x192 193// Macro test. Since the std::move call is outside the macro, it is194// safe to suggest a fix-it.195A 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.221test9222// expected-warning@-1{{prevents copy elision}}223// CHECK-NOT: fix-it224 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.228A test10() {229 A a;230 return_a;231 // expected-warning@-1{{prevents copy elision}}232 // CHECK-NOT: fix-it233}234 235namespace 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