libstdc++
exception_ptr.h
Go to the documentation of this file.
1// Exception Handling support header (exception_ptr class) for -*- C++ -*-
2
3// Copyright (C) 2008-2025 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#include <bits/c++config.h>
37#include <typeinfo>
38#include <new>
39
40#if __cplusplus >= 201103L
41# include <bits/move.h>
42#endif
43
44#ifdef _GLIBCXX_EH_PTR_RELOPS_COMPAT
45# define _GLIBCXX_EH_PTR_USED __attribute__((__used__))
46#else
47# define _GLIBCXX_EH_PTR_USED
48#endif
49
50extern "C++" {
51
52namespace std _GLIBCXX_VISIBILITY(default)
53{
54 class type_info;
55
56 /**
57 * @addtogroup exceptions
58 * @{
59 */
60
61 namespace __exception_ptr
62 {
63 class exception_ptr;
64 }
65
66 using __exception_ptr::exception_ptr;
67
68 /** Obtain an exception_ptr to the currently handled exception.
69 *
70 * If there is none, or the currently handled exception is foreign,
71 * return the null value.
72 *
73 * @since C++11
74 */
75 exception_ptr current_exception() _GLIBCXX_USE_NOEXCEPT;
76
77 template<typename _Ex>
78 _GLIBCXX26_CONSTEXPR exception_ptr make_exception_ptr(_Ex)
79 _GLIBCXX_USE_NOEXCEPT;
80
81 /// Throw the object pointed to by the exception_ptr.
82 void rethrow_exception(exception_ptr) __attribute__ ((__noreturn__));
83
84#if __cpp_lib_exception_ptr_cast >= 202506L
85 template<typename _Ex>
86 constexpr const _Ex* exception_ptr_cast(const exception_ptr&) noexcept;
87 template<typename _Ex>
88 void exception_ptr_cast(const exception_ptr&&) = delete;
89#endif
90
91 namespace __exception_ptr
92 {
93 using std::rethrow_exception; // So that ADL finds it.
94
95 /**
96 * @brief An opaque pointer to an arbitrary exception.
97 *
98 * The actual name of this type is unspecified, so the alias
99 * `std::exception_ptr` should be used to refer to it.
100 *
101 * @headerfile exception
102 * @since C++11 (but usable in C++98 as a GCC extension)
103 * @ingroup exceptions
104 */
105 class exception_ptr
106 {
107 void* _M_exception_object;
108
109#if __cplusplus >= 202400L
110 constexpr explicit exception_ptr(void* __e) noexcept
111 : _M_exception_object(__e)
112 {
113 if (_M_exception_object)
114 {
115#if __cpp_if_consteval >= 202106L \
116 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
117 if consteval {
118 __builtin_eh_ptr_adjust_ref(_M_exception_object, 1);
119 return;
120 }
121#endif
122 _M_addref();
123 }
124 }
125#else
126 explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
127#endif
128
129 void _M_addref() _GLIBCXX_USE_NOEXCEPT;
130 void _M_release() _GLIBCXX_USE_NOEXCEPT;
131
132 void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
133
134 friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
135 friend void std::rethrow_exception(exception_ptr);
136 template<typename _Ex>
137 friend _GLIBCXX26_CONSTEXPR exception_ptr std::make_exception_ptr(_Ex)
138 _GLIBCXX_USE_NOEXCEPT;
139#if __cpp_lib_exception_ptr_cast >= 202506L
140 template<typename _Ex>
141 friend constexpr const _Ex*
142 std::exception_ptr_cast(const exception_ptr&) noexcept;
143#endif
144
145 const void* _M_exception_ptr_cast(const type_info&) const
146 _GLIBCXX_USE_NOEXCEPT;
147
148 public:
149 _GLIBCXX26_CONSTEXPR exception_ptr() _GLIBCXX_USE_NOEXCEPT;
150
151 _GLIBCXX26_CONSTEXPR exception_ptr(const exception_ptr&)
152 _GLIBCXX_USE_NOEXCEPT;
153
154#if __cplusplus >= 201103L
155 _GLIBCXX26_CONSTEXPR exception_ptr(nullptr_t) noexcept
156 : _M_exception_object(nullptr)
157 { }
158
159 _GLIBCXX26_CONSTEXPR exception_ptr(exception_ptr&& __o) noexcept
160 : _M_exception_object(__o._M_exception_object)
161 { __o._M_exception_object = nullptr; }
162#endif
163
164#if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
165 typedef void (exception_ptr::*__safe_bool)();
166
167 // For construction from nullptr or 0.
168 exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
169#endif
170
171 _GLIBCXX26_CONSTEXPR exception_ptr&
172 operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
173
174#if __cplusplus >= 201103L
175 _GLIBCXX26_CONSTEXPR exception_ptr&
176 operator=(exception_ptr&& __o) noexcept
177 {
178 exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
179 return *this;
180 }
181#endif
182
183 _GLIBCXX26_CONSTEXPR ~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
184
185 _GLIBCXX26_CONSTEXPR void
186 swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
187
188#ifdef _GLIBCXX_EH_PTR_COMPAT
189 // Retained for compatibility with CXXABI_1.3.
190 void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT;
191 bool operator!() const _GLIBCXX_USE_NOEXCEPT
192 __attribute__ ((__pure__));
193 operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
194#endif
195
196#if __cplusplus >= 201103L
197 _GLIBCXX26_CONSTEXPR explicit operator bool() const noexcept
198 { return _M_exception_object; }
199#endif
200
201#if __cpp_impl_three_way_comparison >= 201907L \
202 && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT
203 _GLIBCXX26_CONSTEXPR friend bool
204 operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
205#else
206 friend _GLIBCXX_EH_PTR_USED bool
207 operator==(const exception_ptr& __x, const exception_ptr& __y)
208 _GLIBCXX_USE_NOEXCEPT
209 { return __x._M_exception_object == __y._M_exception_object; }
210
211 friend _GLIBCXX_EH_PTR_USED bool
212 operator!=(const exception_ptr& __x, const exception_ptr& __y)
213 _GLIBCXX_USE_NOEXCEPT
214 { return __x._M_exception_object != __y._M_exception_object; }
215#endif
216
217 const class std::type_info*
218 __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
219 __attribute__ ((__pure__));
220 };
221
222 _GLIBCXX_EH_PTR_USED
223 _GLIBCXX26_CONSTEXPR inline
224 exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
225 : _M_exception_object(0)
226 { }
227
228 _GLIBCXX_EH_PTR_USED
229 _GLIBCXX26_CONSTEXPR inline
230 exception_ptr::exception_ptr(const exception_ptr& __other)
231 _GLIBCXX_USE_NOEXCEPT
232 : _M_exception_object(__other._M_exception_object)
233 {
234 if (_M_exception_object)
235 {
236#if __cpp_if_consteval >= 202106L \
237 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
238 if consteval {
239 __builtin_eh_ptr_adjust_ref(_M_exception_object, 1);
240 return;
241 }
242#endif
243 _M_addref();
244 }
245 }
246
247 _GLIBCXX_EH_PTR_USED
248 _GLIBCXX26_CONSTEXPR inline
249 exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
250 {
251 if (_M_exception_object)
252 {
253#if __cpp_if_consteval >= 202106L \
254 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
255 if consteval {
256 __builtin_eh_ptr_adjust_ref(_M_exception_object, -1);
257 return;
258 }
259#endif
260 _M_release();
261 }
262 }
263
264 _GLIBCXX_EH_PTR_USED
265 _GLIBCXX26_CONSTEXPR inline exception_ptr&
266 exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
267 {
268 exception_ptr(__other).swap(*this);
269 return *this;
270 }
271
272 _GLIBCXX_EH_PTR_USED
273 _GLIBCXX26_CONSTEXPR inline void
274 exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
275 {
276 void *__tmp = _M_exception_object;
277 _M_exception_object = __other._M_exception_object;
278 __other._M_exception_object = __tmp;
279 }
280
281 /// @relates exception_ptr
282 _GLIBCXX26_CONSTEXPR inline void
283 swap(exception_ptr& __lhs, exception_ptr& __rhs)
284 { __lhs.swap(__rhs); }
285
286 /// @cond undocumented
287 template<typename _Ex>
288 _GLIBCXX_CDTOR_CALLABI
289 inline void
290 __dest_thunk(void* __x)
291 { static_cast<_Ex*>(__x)->~_Ex(); }
292 /// @endcond
293
294 } // namespace __exception_ptr
295
296 using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it.
297
298 /// Obtain an exception_ptr pointing to a copy of the supplied object.
299 template<typename _Ex>
300#if !(__cplusplus >= 201103L && __cpp_rtti) && !__cpp_exceptions
301 // This is always_inline so the linker will never use a useless definition
302 // instead of a working one compiled with RTTI and/or exceptions enabled.
303 __attribute__ ((__always_inline__)) inline
304#endif
305 _GLIBCXX26_CONSTEXPR exception_ptr
306 make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
307 {
308#if __cplusplus >= 201103L && __cpp_rtti
309 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
310 // We can't use this for C++98 because it relies on std::decay.
311#ifdef __glibcxx_constexpr_exceptions
312 if ! consteval
313#endif
314 {
315 using _Ex2 = typename decay<_Ex>::type;
316 void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
317 (void) __cxxabiv1::__cxa_init_primary_exception(
318 __e, const_cast<std::type_info*>(&typeid(_Ex)),
319 __exception_ptr::__dest_thunk<_Ex2>);
320 __try
321 {
322 ::new (__e) _Ex2(__ex);
323 return exception_ptr(__e);
324 }
325 __catch(...)
326 {
327 __cxxabiv1::__cxa_free_exception(__e);
328 return current_exception();
329 }
330 }
331#endif
332
333#ifdef __cpp_exceptions
334 try
335 {
336 throw __ex;
337 }
338 catch(...)
339 {
340 return current_exception();
341 }
342#endif
343 return exception_ptr();
344 }
345
346#if __cpp_lib_exception_ptr_cast >= 202506L
347 template<typename _Ex>
348 [[__gnu__::__always_inline__]]
349 constexpr const _Ex*
350 exception_ptr_cast(const exception_ptr& __p) noexcept
351 {
352 static_assert(!std::is_const_v<_Ex>);
353 static_assert(!std::is_reference_v<_Ex>);
354 static_assert(std::is_object_v<_Ex>);
355 static_assert(!std::is_array_v<_Ex>);
356 static_assert(!std::is_pointer_v<_Ex>);
357 static_assert(!std::is_member_pointer_v<_Ex>);
358
359#ifdef __cpp_rtti
360 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
361 if ! consteval {
362 const type_info &__id = typeid(const _Ex&);
363 return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
364 }
365#endif
366
367#ifdef __cpp_exceptions
368 if (__p._M_exception_object)
369 try
370 {
372 }
373 catch (const _Ex& __exc)
374 {
375 return &__exc;
376 }
377 catch (...)
378 {
379 }
380#endif
381
382 return nullptr;
383 }
384#endif
385
386#undef _GLIBCXX_EH_PTR_USED
387
388 /// @} group exceptions
389} // namespace std
390
391} // extern "C++"
392
393#endif
exception_ptr current_exception() noexcept
exception_ptr make_exception_ptr(_Ex) noexcept
Obtain an exception_ptr pointing to a copy of the supplied object.
void rethrow_exception(exception_ptr)
Throw the object pointed to by the exception_ptr.
ISO C++ entities toplevel namespace is std.
Part of RTTI.
Definition typeinfo:94
An opaque pointer to an arbitrary exception.
An opaque pointer to an arbitrary exception.