1 // PR c++/86981
2 // { dg-do compile { target c++11 } }
3 // { dg-options "-Wpessimizing-move" }
4 
5 // Define std::move.
6 namespace std {
7   inline namespace _8 { }
8   namespace _8 {
9     template<typename _Tp>
10       struct remove_reference
11       { typedef _Tp   type; };
12 
13     template<typename _Tp>
14       struct remove_reference<_Tp&>
15       { typedef _Tp   type; };
16 
17     template<typename _Tp>
18       struct remove_reference<_Tp&&>
19       { typedef _Tp   type; };
20 
21     template<typename _Tp>
22       constexpr typename std::remove_reference<_Tp>::type&&
23       move(_Tp&& __t) noexcept
24       { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
25   }
26 }
27 
28 struct T {
29   T() { }
30   T(const T&) { }
31   T(T&&) { }
32 };
33 struct U {
34   U() { }
35   U(const U&) { }
36   U(U&&) { }
37   U(T) { }
38 };
39 
40 T g;
41 
42 T
43 fn1 ()
44 {
45   T t;
46   return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
47 }
48 
49 T
50 fn2 ()
51 {
52   // Not a local variable.
53   return std::move (g);
54 }
55 
56 int
57 fn3 ()
58 {
59   int i = 42;
60   // Not a class type.
61   return std::move (i);
62 }
63 
64 T
65 fn4 (bool b)
66 {
67   T t;
68   if (b)
69     throw std::move (t);
70   return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
71 }
72 
73 T
74 fn5 (T t)
75 {
76   // Function parameter; std::move is redundant but not pessimizing.
77   return std::move (t);
78 }
79 
80 U
81 fn6 (T t, U u, bool b)
82 {
83   if (b)
84     return std::move (t);
85   else
86     // Function parameter; std::move is redundant but not pessimizing.
87     return std::move (u);
88 }
89 
90 U
91 fn6 (bool b)
92 {
93   T t;
94   U u;
95   if (b)
96     return std::move (t);
97   else
98     return std::move (u); // { dg-warning "moving a local object in a return statement prevents copy elision" }
99 }
100 
101 T
102 fn7 ()
103 {
104   static T t;
105   // Non-local; don't warn.
106   return std::move (t);
107 }
108 
109 T
110 fn8 ()
111 {
112   return T();
113 }
114 
115 T
116 fn9 (int i)
117 {
118   T t;
119 
120   switch (i)
121     {
122     case 1:
123       return std::move ((t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
124     case 2:
125       return (std::move (t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
126     default:
127       return (std::move ((t))); // { dg-warning "moving a local object in a return statement prevents copy elision" }
128     }
129 }
130 
131 int
132 fn10 ()
133 {
134   return std::move (42);
135 }
136