gdb/riscv: Use legacy register numbers in default target description
[external/binutils.git] / gdb / common / scope-exit.h
1 /* Copyright (C) 2019 Free Software Foundation, Inc.
2
3    This file is part of GDB.
4
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #ifndef COMMON_SCOPE_EXIT_H
19 #define COMMON_SCOPE_EXIT_H
20
21 #include <functional>
22 #include <type_traits>
23 #include "common/preprocessor.h"
24
25 /* scope_exit is a general-purpose scope guard that calls its exit
26    function at the end of the current scope.  A scope_exit may be
27    canceled by calling the "release" method.  The API is modeled on
28    P0052R5 - Generic Scope Guard and RAII Wrapper for the Standard
29    Library, which is itself based on Andrej Alexandrescu's
30    ScopeGuard/SCOPE_EXIT.
31
32    There are two forms available:
33
34    - The "make_scope_exit" form allows canceling the scope guard.  Use
35      it like this:
36
37      auto cleanup = make_scope_exit ( <function, function object, lambda> );
38      ...
39      cleanup.release (); // cancel
40
41    - If you don't need to cancel the guard, you can use the SCOPE_EXIT
42      macro, like this:
43
44      SCOPE_EXIT
45        {
46          // any code you like here.
47        }
48
49    See also forward_scope_exit.
50 */
51
52 /* CRTP base class for cancelable scope_exit-like classes.  Implements
53    the common call-custom-function-from-dtor functionality.  Classes
54    that inherit this implement the on_exit() method, which is called
55    from scope_exit_base's dtor.  */
56
57 template <typename CRTP>
58 class scope_exit_base
59 {
60 public:
61   scope_exit_base () = default;
62
63   ~scope_exit_base ()
64   {
65     if (!m_released)
66       {
67         auto *self = static_cast<CRTP *> (this);
68         self->on_exit ();
69       }
70   }
71
72   /* This is needed for make_scope_exit because copy elision isn't
73      guaranteed until C++17.  An optimizing compiler will usually skip
74      calling this, but it must exist.  */
75   scope_exit_base (const scope_exit_base &other)
76     : m_released (other.m_released)
77   {
78     other.m_released = true;
79   }
80
81   void operator= (const scope_exit_base &) = delete;
82
83   /* If this is called, then the wrapped function will not be called
84      on destruction.  */
85   void release () noexcept
86   {
87     m_released = true;
88   }
89
90 private:
91
92   /* True if released.  Mutable because of the copy ctor hack
93      above.  */
94   mutable bool m_released = false;
95 };
96
97 /* The scope_exit class.  */
98
99 template<typename EF>
100 class scope_exit : public scope_exit_base<scope_exit<EF>>
101 {
102   /* For access to on_exit().  */
103   friend scope_exit_base<scope_exit<EF>>;
104
105 public:
106
107   template<typename EFP,
108            typename = gdb::Requires<std::is_constructible<EF, EFP>>>
109   scope_exit (EFP &&f)
110     try : m_exit_function ((!std::is_lvalue_reference<EFP>::value
111                             && std::is_nothrow_constructible<EF, EFP>::value)
112                            ? std::move (f)
113                            : f)
114   {
115   }
116   catch (...)
117     {
118       /* "If the initialization of exit_function throws an exception,
119          calls f()."  */
120       f ();
121     }
122
123   template<typename EFP,
124            typename = gdb::Requires<std::is_constructible<EF, EFP>>>
125   scope_exit (scope_exit &&rhs)
126     noexcept (std::is_nothrow_move_constructible<EF>::value
127               || std::is_nothrow_copy_constructible<EF>::value)
128     : m_exit_function (std::is_nothrow_constructible<EFP>::value
129                        ? std::move (rhs)
130                        : rhs)
131   {
132     rhs.release ();
133   }
134
135   /* This is needed for make_scope_exit because copy elision isn't
136      guaranteed until C++17.  An optimizing compiler will usually skip
137      calling this, but it must exist.  */
138   scope_exit (const scope_exit &other)
139     : scope_exit_base<scope_exit<EF>> (other),
140       m_exit_function (other.m_exit_function)
141   {
142   }
143
144   void operator= (const scope_exit &) = delete;
145   void operator= (scope_exit &&) = delete;
146
147 private:
148   void on_exit ()
149   {
150     m_exit_function ();
151   }
152
153   /* The function to call on scope exit.  */
154   EF m_exit_function;
155 };
156
157 template <typename EF>
158 scope_exit<typename std::decay<EF>::type>
159 make_scope_exit (EF &&f)
160 {
161   return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (f));
162 }
163
164 namespace detail
165 {
166
167 enum class scope_exit_lhs {};
168
169 template<typename EF>
170 scope_exit<typename std::decay<EF>::type>
171 operator+ (scope_exit_lhs, EF &&rhs)
172 {
173   return scope_exit<typename std::decay<EF>::type> (std::forward<EF> (rhs));
174 }
175
176 }
177
178 /* Register a block of code to run on scope exit.  Note that the local
179    context is captured by reference, which means you should be careful
180    to avoid inadvertently changing a captured local's value before the
181    scope exit runs.  */
182
183 #define SCOPE_EXIT \
184   auto CONCAT(scope_exit_, __LINE__) = ::detail::scope_exit_lhs () + [&] ()
185
186 #endif /* COMMON_SCOPE_EXIT_H */