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#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 [[__gnu__::__gnu_inline__]]
111 constexpr inline explicit exception_ptr(void* __e) noexcept
112 : _M_exception_object(__e)
113 {
114 if (_M_exception_object)
115 {
116#if __cpp_if_consteval >= 202106L \
117 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
118 if consteval {
119 __builtin_eh_ptr_adjust_ref(_M_exception_object, 1);
120 return;
121 }
122#endif
123 _M_addref();
124 }
125 }
126#else
127 explicit exception_ptr(void* __e) _GLIBCXX_USE_NOEXCEPT;
128#endif
129
130 void _M_addref() _GLIBCXX_USE_NOEXCEPT;
131 void _M_release() _GLIBCXX_USE_NOEXCEPT;
132
133 void *_M_get() const _GLIBCXX_NOEXCEPT __attribute__ ((__pure__));
134
135 friend exception_ptr std::current_exception() _GLIBCXX_USE_NOEXCEPT;
136 friend void std::rethrow_exception(exception_ptr);
137 template<typename _Ex>
138 friend _GLIBCXX26_CONSTEXPR exception_ptr std::make_exception_ptr(_Ex)
139 _GLIBCXX_USE_NOEXCEPT;
140#if __cpp_lib_exception_ptr_cast >= 202506L
141 template<typename _Ex>
142 friend constexpr const _Ex*
143 std::exception_ptr_cast(const exception_ptr&) noexcept;
144#endif
145
146 const void* _M_exception_ptr_cast(const type_info&) const
147 _GLIBCXX_USE_NOEXCEPT;
148
149 public:
150 _GLIBCXX26_CONSTEXPR exception_ptr() _GLIBCXX_USE_NOEXCEPT;
151
152 _GLIBCXX26_CONSTEXPR exception_ptr(const exception_ptr&)
153 _GLIBCXX_USE_NOEXCEPT;
154
155#if __cplusplus >= 201103L
156 _GLIBCXX26_CONSTEXPR exception_ptr(nullptr_t) noexcept
157 : _M_exception_object(nullptr)
158 { }
159
160 _GLIBCXX26_CONSTEXPR exception_ptr(exception_ptr&& __o) noexcept
161 : _M_exception_object(__o._M_exception_object)
162 { __o._M_exception_object = nullptr; }
163#endif
164
165#if (__cplusplus < 201103L) || defined (_GLIBCXX_EH_PTR_COMPAT)
166 typedef void (exception_ptr::*__safe_bool)();
167
168 // For construction from nullptr or 0.
169 exception_ptr(__safe_bool) _GLIBCXX_USE_NOEXCEPT;
170#endif
171
172 _GLIBCXX26_CONSTEXPR exception_ptr&
173 operator=(const exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
174
175#if __cplusplus >= 201103L
176 _GLIBCXX26_CONSTEXPR exception_ptr&
177 operator=(exception_ptr&& __o) noexcept
178 {
179 exception_ptr(static_cast<exception_ptr&&>(__o)).swap(*this);
180 return *this;
181 }
182#endif
183
184 _GLIBCXX26_CONSTEXPR ~exception_ptr() _GLIBCXX_USE_NOEXCEPT;
185
186 _GLIBCXX26_CONSTEXPR void
187 swap(exception_ptr&) _GLIBCXX_USE_NOEXCEPT;
188
189#ifdef _GLIBCXX_EH_PTR_COMPAT
190 // Retained for compatibility with CXXABI_1.3.
191 void _M_safe_bool_dummy() _GLIBCXX_USE_NOEXCEPT;
192 bool operator!() const _GLIBCXX_USE_NOEXCEPT
193 __attribute__ ((__pure__));
194 operator __safe_bool() const _GLIBCXX_USE_NOEXCEPT;
195#endif
196
197#if __cplusplus >= 201103L
198 _GLIBCXX26_CONSTEXPR explicit operator bool() const noexcept
199 { return _M_exception_object; }
200#endif
201
202#if __cpp_impl_three_way_comparison >= 201907L \
203 && ! defined _GLIBCXX_EH_PTR_RELOPS_COMPAT
204 _GLIBCXX26_CONSTEXPR friend bool
205 operator==(const exception_ptr&, const exception_ptr&) noexcept = default;
206#else
207 friend _GLIBCXX_EH_PTR_USED bool
208 operator==(const exception_ptr& __x, const exception_ptr& __y)
209 _GLIBCXX_USE_NOEXCEPT
210 { return __x._M_exception_object == __y._M_exception_object; }
211
212 friend _GLIBCXX_EH_PTR_USED bool
213 operator!=(const exception_ptr& __x, const exception_ptr& __y)
214 _GLIBCXX_USE_NOEXCEPT
215 { return __x._M_exception_object != __y._M_exception_object; }
216#endif
217
218 // Friend for ADL with module std.
219 friend _GLIBCXX26_CONSTEXPR void
220 swap(exception_ptr& __lhs, exception_ptr& __rhs);
221
222 const class std::type_info*
223 __cxa_exception_type() const _GLIBCXX_USE_NOEXCEPT
224 __attribute__ ((__pure__));
225 };
226
227 _GLIBCXX_EH_PTR_USED
228 _GLIBCXX26_CONSTEXPR inline
229 exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT
230 : _M_exception_object(0)
231 { }
232
233 _GLIBCXX_EH_PTR_USED
234 _GLIBCXX26_CONSTEXPR inline
235 exception_ptr::exception_ptr(const exception_ptr& __other)
236 _GLIBCXX_USE_NOEXCEPT
237 : _M_exception_object(__other._M_exception_object)
238 {
239 if (_M_exception_object)
240 {
241#if __cpp_if_consteval >= 202106L \
242 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
243 if consteval {
244 __builtin_eh_ptr_adjust_ref(_M_exception_object, 1);
245 return;
246 }
247#endif
248 _M_addref();
249 }
250 }
251
252 _GLIBCXX_EH_PTR_USED
253 _GLIBCXX26_CONSTEXPR inline
254 exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT
255 {
256 if (_M_exception_object)
257 {
258#if __cpp_if_consteval >= 202106L \
259 && _GLIBCXX_HAS_BUILTIN(__builtin_eh_ptr_adjust_ref)
260 if consteval {
261 __builtin_eh_ptr_adjust_ref(_M_exception_object, -1);
262 return;
263 }
264#endif
265 _M_release();
266 }
267 }
268
269 _GLIBCXX_EH_PTR_USED
270 _GLIBCXX26_CONSTEXPR inline exception_ptr&
271 exception_ptr::operator=(const exception_ptr& __other) _GLIBCXX_USE_NOEXCEPT
272 {
273 exception_ptr(__other).swap(*this);
274 return *this;
275 }
276
277 _GLIBCXX_EH_PTR_USED
278 _GLIBCXX26_CONSTEXPR inline void
279 exception_ptr::swap(exception_ptr &__other) _GLIBCXX_USE_NOEXCEPT
280 {
281 void *__tmp = _M_exception_object;
282 _M_exception_object = __other._M_exception_object;
283 __other._M_exception_object = __tmp;
284 }
285
286 /// @relates exception_ptr
287 _GLIBCXX26_CONSTEXPR inline void
288 swap(exception_ptr& __lhs, exception_ptr& __rhs)
289 { __lhs.swap(__rhs); }
290
291 /// @cond undocumented
292 template<typename _Ex>
293 _GLIBCXX_CDTOR_CALLABI
294 inline void
295 __dest_thunk(void* __x)
296 { static_cast<_Ex*>(__x)->~_Ex(); }
297 /// @endcond
298
299 } // namespace __exception_ptr
300
301 using __exception_ptr::swap; // So that std::swap(exp1, exp2) finds it.
302
303 /// Obtain an exception_ptr pointing to a copy of the supplied object.
304 template<typename _Ex>
305#if !(__cplusplus >= 201103L && __cpp_rtti) && !__cpp_exceptions
306 // This is always_inline so the linker will never use a useless definition
307 // instead of a working one compiled with RTTI and/or exceptions enabled.
308 __attribute__ ((__always_inline__)) inline
309#endif
310 _GLIBCXX26_CONSTEXPR exception_ptr
311 make_exception_ptr(_Ex __ex) _GLIBCXX_USE_NOEXCEPT
312 {
313#if __cplusplus >= 201103L && __cpp_rtti
314 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
315 // We can't use this for C++98 because it relies on std::decay.
316#ifdef __glibcxx_constexpr_exceptions
317 if ! consteval
318#endif
319 {
320 using _Ex2 = typename decay<_Ex>::type;
321 void* __e = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ex));
322 (void) __cxxabiv1::__cxa_init_primary_exception(
323 __e, const_cast<std::type_info*>(&typeid(_Ex)),
324 __exception_ptr::__dest_thunk<_Ex2>);
325 __try
326 {
327 ::new (__e) _Ex2(__ex);
328 return exception_ptr(__e);
329 }
330 __catch(...)
331 {
332 __cxxabiv1::__cxa_free_exception(__e);
333 return current_exception();
334 }
335 }
336#endif
337
338#ifdef __cpp_exceptions
339 try
340 {
341 throw __ex;
342 }
343 catch(...)
344 {
345 return current_exception();
346 }
347#endif
348 return exception_ptr();
349 }
350
351#if __cpp_lib_exception_ptr_cast >= 202506L
352 template<typename _Ex>
353 [[__gnu__::__always_inline__]]
354 constexpr const _Ex*
355 exception_ptr_cast(const exception_ptr& __p) noexcept
356 {
357 static_assert(!std::is_const_v<_Ex>);
358 static_assert(!std::is_reference_v<_Ex>);
359 static_assert(std::is_object_v<_Ex>);
360 static_assert(!std::is_array_v<_Ex>);
361 static_assert(!std::is_pointer_v<_Ex>);
362 static_assert(!std::is_member_pointer_v<_Ex>);
363
364#ifdef __cpp_rtti
365 // For runtime calls with -frtti enabled we can avoid try-catch overhead.
366 if ! consteval {
367 const type_info &__id = typeid(const _Ex&);
368 return static_cast<const _Ex*>(__p._M_exception_ptr_cast(__id));
369 }
370#endif
371
372#ifdef __cpp_exceptions
373 if (__p._M_exception_object)
374 try
375 {
377 }
378 catch (const _Ex& __exc)
379 {
380 return &__exc;
381 }
382 catch (...)
383 {
384 }
385#endif
386
387 return nullptr;
388 }
389#endif
390
391#undef _GLIBCXX_EH_PTR_USED
392
393 /// @} group exceptions
394} // namespace std
395
396} // extern "C++"
397
398#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.