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