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