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   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 struct U {
31   U() { }
32   U(const U&) { }
33   U(U&&) { }
34   U(T) { }
35 };
36 
37 T g;
38 
39 T
40 fn1 ()
41 {
42   T t;
43   return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
44 }
45 
46 T
47 fn2 ()
48 {
49   // Not a local variable.
50   return std::move (g);
51 }
52 
53 int
54 fn3 ()
55 {
56   int i = 42;
57   // Not a class type.
58   return std::move (i);
59 }
60 
61 T
62 fn4 (bool b)
63 {
64   T t;
65   if (b)
66     throw std::move (t);
67   return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
68 }
69 
70 T
71 fn5 (T t)
72 {
73   // Function parameter; std::move is redundant but not pessimizing.
74   return std::move (t);
75 }
76 
77 U
78 fn6 (T t, U u, bool b)
79 {
80   if (b)
81     return std::move (t);
82   else
83     // Function parameter; std::move is redundant but not pessimizing.
84     return std::move (u);
85 }
86 
87 U
88 fn6 (bool b)
89 {
90   T t;
91   U u;
92   if (b)
93     return std::move (t);
94   else
95     return std::move (u); // { dg-warning "moving a local object in a return statement prevents copy elision" }
96 }
97 
98 T
99 fn7 ()
100 {
101   static T t;
102   // Non-local; don't warn.
103   return std::move (t);
104 }
105 
106 T
107 fn8 ()
108 {
109   return T();
110 }
111 
112 T
113 fn9 (int i)
114 {
115   T t;
116 
117   switch (i)
118     {
119     case 1:
120       return std::move ((t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
121     case 2:
122       return (std::move (t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
123     default:
124       return (std::move ((t))); // { dg-warning "moving a local object in a return statement prevents copy elision" }
125     }
126 }
127 
128 int
129 fn10 ()
130 {
131   return std::move (42);
132 }
133