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 // Friend for ADL with module std.
218 friend _GLIBCXX26_CONSTEXPR void
219 swap(exception_ptr& __lhs, exception_ptr& __rhs);
220
221 const class std::type_info*
222 __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
223 __attribute__ ((__pure__));
224 };
225
226 _GLIBCXX_EH_PTR_USED
227 _GLIBCXX26_CONSTEXPR inline
228 exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
229 : _M_exception_object(0)
230 { }
231
232 _GLIBCXX_EH_PTR_USED
233 _GLIBCXX26_CONSTEXPR inline
234 exception_ptr::exception_ptr(const exception_ptr& __other)
235 _GLIBCXX_USE_NOEXCEPT
236 : _M_exception_object(__other._M_exception_object)
237 {
238 if (_M_exception_object)
239 {
240#if __cpp_if_consteval >= 202106L \
241 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
242 if consteval {
243 __builtin_eh_ptr_adjust_ref(_M_exception_object, 1);
244 return;
245 }
246#endif
247 _M_addref();
248 }
249 }
250
251 _GLIBCXX_EH_PTR_USED
252 _GLIBCXX26_CONSTEXPR inline
253 exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
254 {
255 if (_M_exception_object)
256 {
257#if __cpp_if_consteval >= 202106L \
258 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
259 if consteval {
260 __builtin_eh_ptr_adjust_ref(_M_exception_object, -1);
261 return;
262 }
263#endif
264 _M_release();
265 }
266 }
267
268 _GLIBCXX_EH_PTR_USED
269 _GLIBCXX26_CONSTEXPR inline exception_ptr&
270 exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
271 {
272 exception_ptr(__other).swap(*this);
273 return *this;
274 }
275
276 _GLIBCXX_EH_PTR_USED
277 _GLIBCXX26_CONSTEXPR inline void
278 exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
279 {
280 void *__tmp = _M_exception_object;
281 _M_exception_object = __other._M_exception_object;
282 __other._M_exception_object = __tmp;
283 }
284
285 /// @relates exception_ptr
286 _GLIBCXX26_CONSTEXPR inline void
287 swap(exception_ptr& __lhs, exception_ptr& __rhs)
288 { __lhs.swap(__rhs); }
289
290 /// @cond undocumented
291 template<typename _Ex>
292 _GLIBCXX_CDTOR_CALLABI
293 inline void
294 __dest_thunk(void* __x)
295 { static_cast<_Ex*>(__x)->~_Ex(); }
296 /// @endcond
297
298 } // namespace __exception_ptr
299
300 using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it.
301
302 /// Obtain an exception_ptr pointing to a copy of the supplied object.
303 template<typename _Ex>
304#if !(__cplusplus >= 201103L && __cpp_rtti) && !__cpp_exceptions
305 // This is always_inline so the linker will never use a useless definition
306 // instead of a working one compiled with RTTI and/or exceptions enabled.
307 __attribute__ ((__always_inline__)) inline
308#endif
309 _GLIBCXX26_CONSTEXPR exception_ptr
310 make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
311 {
312#if __cplusplus >= 201103L && __cpp_rtti
313 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
314 // We can't use this for C++98 because it relies on std::decay.
315#ifdef __glibcxx_constexpr_exceptions
316 if ! consteval
317#endif
318 {
319 using _Ex2 = typename decay<_Ex>::type;
320 void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
321 (void) __cxxabiv1::__cxa_init_primary_exception(
322 __e, const_cast<std::type_info*>(&typeid(_Ex)),
323 __exception_ptr::__dest_thunk<_Ex2>);
324 __try
325 {
326 ::new (__e) _Ex2(__ex);
327 return exception_ptr(__e);
328 }
329 __catch(...)
330 {
331 __cxxabiv1::__cxa_free_exception(__e);
332 return current_exception();
333 }
334 }
335#endif
336
337#ifdef __cpp_exceptions
338 try
339 {
340 throw __ex;
341 }
342 catch(...)
343 {
344 return current_exception();
345 }
346#endif
347 return exception_ptr();
348 }
349
350#if __cpp_lib_exception_ptr_cast >= 202506L
351 template<typename _Ex>
352 [[__gnu__::__always_inline__]]
353 constexpr const _Ex*
354 exception_ptr_cast(const exception_ptr& __p) noexcept
355 {
356 static_assert(!std::is_const_v<_Ex>);
357 static_assert(!std::is_reference_v<_Ex>);
358 static_assert(std::is_object_v<_Ex>);
359 static_assert(!std::is_array_v<_Ex>);
360 static_assert(!std::is_pointer_v<_Ex>);
361 static_assert(!std::is_member_pointer_v<_Ex>);
362
363#ifdef __cpp_rtti
364 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
365 if ! consteval {
366 const type_info &__id = typeid(const _Ex&);
367 return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
368 }
369#endif
370
371#ifdef __cpp_exceptions
372 if (__p._M_exception_object)
373 try
374 {
376 }
377 catch (const _Ex& __exc)
378 {
379 return &__exc;
380 }
381 catch (...)
382 {
383 }
384#endif
385
386 return nullptr;
387 }
388#endif
389
390#undef _GLIBCXX_EH_PTR_USED
391
392 /// @} group exceptions
393} // namespace std
394
395} // extern "C++"
396
397#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.