xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/libsupc++/exception_ptr.h (revision 4fe0f936ff464bca8e6277bde90f477ef5a4d004)
1 // Exception Handling support header (exception_ptr class) for -*- C++ -*-
2 
3 // Copyright (C) 2008-2022 Free Software Foundation, Inc.
4 //
5 // This file is part of GCC.
6 //
7 // GCC is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 //
12 // GCC is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 /** @file bits/exception_ptr.h
27  *  This is an internal header file, included by other library headers.
28  *  Do not attempt to use it directly. @headername{exception}
29  */
30 
31 #ifndef _EXCEPTION_PTR_H
32 #define _EXCEPTION_PTR_H
33 
34 #pragma GCC visibility push(default)
35 
36 #include <bits/c++config.h>
37 #include <bits/exception_defines.h>
38 #include <bits/cxxabi_init_exception.h>
39 #include <typeinfo>
40 #include <new>
41 
42 #if __cplusplus >= 201103L
43 # include <bits/move.h>
44 #endif
45 
46 #ifdef _GLIBCXX_EH_PTR_RELOPS_COMPAT
47 # define _GLIBCXX_EH_PTR_USED __attribute__((__used__))
48 #else
49 # define _GLIBCXX_EH_PTR_USED
50 #endif
51 
52 extern "C++" {
53 
54 namespace std
55 {
56   class type_info;
57 
58   /**
59    * @addtogroup exceptions
60    * @{
61    */
62 
63   namespace __exception_ptr
64   {
65     class exception_ptr;
66   }
67 
68   using __exception_ptr::exception_ptr;
69 
70   /** Obtain an exception_ptr to the currently handled exception. If there
71    *  is none, or the currently handled exception is foreign, return the null
72    *  value.
73    */
74   exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
75 
76   template<typename _Ex>
77   exception_ptr make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
78 
79   /// Throw the object pointed to by the exception_ptr.
80   void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
81 
82   namespace __exception_ptr
83   {
84     using std::rethrow_exception;
85 
86     /**
87      *  @brief An opaque pointer to an arbitrary exception.
88      *  @ingroup exceptions
89      */
90     class exception_ptr
91     {
92       void* _M_exception_object;
93 
94       explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
95 
96       void _M_addref() _GLIBCXX_USE_NOEXCEPT;
97       void _M_release() _GLIBCXX_USE_NOEXCEPT;
98 
99       void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
100 
101       friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
102       friend void std::rethrow_exception(exception_ptr);
103       template<typename _Ex>
104       friend exception_ptr std::make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT;
105 
106     public:
107       exception_ptr() _GLIBCXX_USE_NOEXCEPT;
108 
109       exception_ptr(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
110 
111 #if __cplusplus >= 201103L
exception_ptr(nullptr_t)112       exception_ptr(nullptr_t) noexcept
113       : _M_exception_object(nullptr)
114       { }
115 
exception_ptr(exception_ptr && __o)116       exception_ptr(exception_ptr&& __o) noexcept
117       : _M_exception_object(__o._M_exception_object)
118       { __o._M_exception_object = nullptr; }
119 #endif
120 
121 #if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
122       typedef void (exception_ptr::*__safe_bool)();
123 
124       // For construction from nullptr or 0.
125       exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
126 #endif
127 
128       exception_ptr&
129       operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
130 
131 #if __cplusplus >= 201103L
132       exception_ptr&
133       operator=(exception_ptr&& __o) noexcept
134       {
135         exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
136         return *this;
137       }
138 #endif
139 
140       ~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
141 
142       void
143       swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
144 
145 #ifdef _GLIBCXX_EH_PTR_COMPAT
146       // Retained for compatibility with CXXABI_1.3.
147       void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT
148 	__attribute__ ((__const__));
149       bool operator!() const _GLIBCXX_USE_NOEXCEPT
150 	__attribute__ ((__pure__));
151       operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
152 #endif
153 
154 #if __cplusplus >= 201103L
155       explicit operator bool() const noexcept
156       { return _M_exception_object; }
157 #endif
158 
159 #if __cpp_impl_three_way_comparison >= 201907L \
160       && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT
161       friend bool
162       operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
163 #else
164       friend _GLIBCXX_EH_PTR_USED bool
165       operator==(const exception_ptr& __x, const exception_ptr& __y)
166       _GLIBCXX_USE_NOEXCEPT
167       { return __x._M_exception_object == __y._M_exception_object; }
168 
169       friend _GLIBCXX_EH_PTR_USED bool
170       operator!=(const exception_ptr& __x, const exception_ptr& __y)
171       _GLIBCXX_USE_NOEXCEPT
172       { return __x._M_exception_object != __y._M_exception_object; }
173 #endif
174 
175       const class std::type_info*
176       __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
177 	__attribute__ ((__pure__));
178     };
179 
180     _GLIBCXX_EH_PTR_USED
181     inline
exception_ptr()182     exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
183     : _M_exception_object(0)
184     { }
185 
186     _GLIBCXX_EH_PTR_USED
187     inline
exception_ptr(const exception_ptr & __other)188     exception_ptr::exception_ptr(const exception_ptr& __other)
189     _GLIBCXX_USE_NOEXCEPT
190     : _M_exception_object(__other._M_exception_object)
191     {
192       if (_M_exception_object)
193 	_M_addref();
194     }
195 
196     _GLIBCXX_EH_PTR_USED
197     inline
~exception_ptr()198     exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
199     {
200       if (_M_exception_object)
201 	_M_release();
202     }
203 
204     _GLIBCXX_EH_PTR_USED
205     inline exception_ptr&
206     exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
207     {
208       exception_ptr(__other).swap(*this);
209       return *this;
210     }
211 
212     _GLIBCXX_EH_PTR_USED
213     inline void
swap(exception_ptr & __other)214     exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
215     {
216       void *__tmp = _M_exception_object;
217       _M_exception_object = __other._M_exception_object;
218       __other._M_exception_object = __tmp;
219     }
220 
221     /// @relates exception_ptr
222     inline void
swap(exception_ptr & __lhs,exception_ptr & __rhs)223     swap(exception_ptr& __lhs, exception_ptr& __rhs)
224     { __lhs.swap(__rhs); }
225 
226     /// @cond undocumented
227     template<typename _Ex>
228       _GLIBCXX_CDTOR_CALLABI
229       inline void
__dest_thunk(void * __x)230       __dest_thunk(void* __x)
231       { static_cast<_Ex*>(__x)->~_Ex(); }
232     /// @endcond
233 
234   } // namespace __exception_ptr
235 
236   /// Obtain an exception_ptr pointing to a copy of the supplied object.
237 #if (__cplusplus >= 201103L && __cpp_rtti) || __cpp_exceptions
238   template<typename _Ex>
239     exception_ptr
make_exception_ptr(_Ex __ex)240     make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
241     {
242 #if __cplusplus >= 201103L && __cpp_rtti
243       using _Ex2 = typename decay<_Ex>::type;
244       void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
245       (void) __cxxabiv1::__cxa_init_primary_exception(
246 	  __e, const_cast<std::type_info*>(&typeid(_Ex)),
247 	  __exception_ptr::__dest_thunk<_Ex2>);
248       __try
249 	{
250 	  ::new (__e) _Ex2(__ex);
251 	  return exception_ptr(__e);
252 	}
253       __catch(...)
254 	{
255 	  __cxxabiv1::__cxa_free_exception(__e);
256 	  return current_exception();
257 	}
258 #else
259       try
260 	{
261           throw __ex;
262 	}
263       catch(...)
264 	{
265 	  return current_exception();
266 	}
267 #endif
268     }
269 #else // no RTTI and no exceptions
270   // This is always_inline so the linker will never use this useless definition
271   // instead of a working one compiled with RTTI and/or exceptions enabled.
272   template<typename _Ex>
273     __attribute__ ((__always_inline__))
274     inline exception_ptr
make_exception_ptr(_Ex)275     make_exception_ptr(_Ex) _GLIBCXX_USE_NOEXCEPT
276     { return exception_ptr(); }
277 #endif
278 
279 #undef _GLIBCXX_EH_PTR_USED
280 
281   /// @} group exceptions
282 } // namespace std
283 
284 } // extern "C++"
285 
286 #pragma GCC visibility pop
287 
288 #endif
289