1 // PR c++/87029 2 // { dg-do compile { target c++11 } } 3 // { dg-options "-Wredundant-move" } 4 5 // Define std::move. 6 namespace std { 7 template<typename _Tp> 8 struct remove_reference 9 { typedef _Tp type; }; 10 11 template<typename _Tp> 12 struct remove_reference<_Tp&> 13 { typedef _Tp type; }; 14 15 template<typename _Tp> 16 struct remove_reference<_Tp&&> 17 { typedef _Tp type; }; 18 19 template<typename _Tp> 20 constexpr typename std::remove_reference<_Tp>::type&& 21 move(_Tp&& __t) noexcept 22 { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } 23 } 24 25 struct T { 26 T() { } 27 T(const T&) { } 28 T(T&&) { } 29 }; 30 31 struct U { 32 U() { } 33 U(const U&) { } 34 U(U&&) { } 35 U(T) { } 36 }; 37 38 T 39 fn1 (T t) 40 { 41 return t; 42 } 43 44 T 45 fn2 (T t) 46 { 47 // Will use move even without std::move. 48 return std::move (t); // { dg-warning "redundant move in return statement" } 49 } 50 51 T 52 fn3 (const T t) 53 { 54 // t is const: will decay into copy. 55 return t; 56 } 57 58 T 59 fn4 (const T t) 60 { 61 // t is const: will decay into copy despite std::move, so it's redundant. 62 // We used to warn about this, but no longer since c++/87378. 63 return std::move (t); 64 } 65 66 int 67 fn5 (int i) 68 { 69 // Not a class type. 70 return std::move (i); 71 } 72 73 T 74 fn6 (T t, bool b) 75 { 76 if (b) 77 throw std::move (t); 78 return std::move (t); // { dg-warning "redundant move in return statement" } 79 } 80 81 U 82 fn7 (T t) 83 { 84 // Core 1579 means we'll get a move here. 85 return t; 86 } 87 88 U 89 fn8 (T t) 90 { 91 // Core 1579 means we'll get a move here. Even without std::move. 92 return std::move (t); // { dg-warning "redundant move in return statement" } 93 } 94 95 T 96 fn9 (T& t) 97 { 98 // T is a reference and the move isn't redundant. 99 return std::move (t); 100 } 101 102 T 103 fn10 (T&& t) 104 { 105 // T is a reference and the move isn't redundant. 106 return std::move (t); 107 } 108