]>
Commit | Line | Data |
---|---|---|
30a333ce | 1 | // -*- C++ -*- Implement the members of exception_ptr. |
83ffe9cd | 2 | // Copyright (C) 2008-2023 Free Software Foundation, Inc. |
30a333ce PC |
3 | // |
4 | // This file is part of GCC. | |
5 | // | |
6 | // GCC is free software; you can redistribute it and/or modify | |
7 | // it under the terms of the GNU General Public License as published by | |
748086b7 | 8 | // the Free Software Foundation; either version 3, or (at your option) |
30a333ce PC |
9 | // any later version. |
10 | // | |
11 | // GCC is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | // | |
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
30a333ce | 19 | |
748086b7 JJ |
20 | // You should have received a copy of the GNU General Public License and |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
30a333ce PC |
24 | |
25 | #include <bits/c++config.h> | |
ed3cb497 | 26 | #include "eh_atomics.h" |
30a333ce | 27 | |
710508c7 | 28 | // This macro causes exception_ptr to declare an older API (with corresponding |
bc0f7db7 | 29 | // definitions in this file). |
110a123a | 30 | #define _GLIBCXX_EH_PTR_COMPAT |
bc0f7db7 JW |
31 | |
32 | #if ! _GLIBCXX_INLINE_VERSION | |
33 | // This macro causes some inline functions in exception_ptr to be marked | |
34 | // as "used" so that definitions will be emitted in this translation unit. | |
35 | // We need this because those functions were not inline in previous releases. | |
36 | #define _GLIBCXX_EH_PTR_RELOPS_COMPAT | |
710508c7 | 37 | #endif |
110a123a | 38 | |
30a333ce | 39 | #include <exception> |
7c3e9502 | 40 | #include <bits/exception_ptr.h> |
30a333ce PC |
41 | #include "unwind-cxx.h" |
42 | ||
43 | using namespace __cxxabiv1; | |
44 | ||
3941b260 JW |
45 | // Verify assumptions about member layout in exception types |
46 | namespace | |
47 | { | |
48 | template<typename Ex> | |
49 | constexpr std::size_t unwindhdr() | |
50 | { return offsetof(Ex, unwindHeader); } | |
51 | ||
52 | template<typename Ex> | |
53 | constexpr std::size_t termHandler() | |
54 | { return unwindhdr<Ex>() - offsetof(Ex, terminateHandler); } | |
55 | ||
56 | static_assert( termHandler<__cxa_exception>() | |
57 | == termHandler<__cxa_dependent_exception>(), | |
0812493f JW |
58 | "__cxa_dependent_exception::termHandler layout must be" |
59 | " consistent with __cxa_exception::termHandler" ); | |
3941b260 JW |
60 | |
61 | #ifndef __ARM_EABI_UNWINDER__ | |
62 | template<typename Ex> | |
63 | constexpr std::ptrdiff_t adjptr() | |
64 | { return unwindhdr<Ex>() - offsetof(Ex, adjustedPtr); } | |
65 | ||
66 | static_assert( adjptr<__cxa_exception>() | |
67 | == adjptr<__cxa_dependent_exception>(), | |
0812493f JW |
68 | "__cxa_dependent_exception::adjustedPtr layout must be" |
69 | " consistent with __cxa_exception::adjustedPtr" ); | |
3941b260 JW |
70 | #endif |
71 | } | |
72 | ||
710508c7 JW |
73 | // Define non-inline functions. |
74 | ||
a3dbb635 | 75 | std::__exception_ptr::exception_ptr::exception_ptr(void* obj) noexcept |
8eead16e | 76 | : _M_exception_object(obj) { _M_addref(); } |
30a333ce PC |
77 | |
78 | ||
a3dbb635 | 79 | std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) noexcept |
1352ea19 | 80 | : _M_exception_object(nullptr) { } |
30a333ce PC |
81 | |
82 | ||
83 | void | |
a3dbb635 | 84 | std::__exception_ptr::exception_ptr::_M_addref() noexcept |
30a333ce | 85 | { |
1352ea19 | 86 | if (__builtin_expect(_M_exception_object != nullptr, true)) |
30a333ce | 87 | { |
c4bca01b JJ |
88 | __cxa_refcounted_exception *eh = |
89 | __get_refcounted_exception_header_from_obj (_M_exception_object); | |
ed3cb497 | 90 | __gnu_cxx::__eh_atomic_inc (&eh->referenceCount); |
30a333ce PC |
91 | } |
92 | } | |
93 | ||
94 | ||
95 | void | |
a3dbb635 | 96 | std::__exception_ptr::exception_ptr::_M_release() noexcept |
30a333ce | 97 | { |
1352ea19 | 98 | if (__builtin_expect(_M_exception_object != nullptr, true)) |
30a333ce | 99 | { |
c4bca01b JJ |
100 | __cxa_refcounted_exception *eh = |
101 | __get_refcounted_exception_header_from_obj (_M_exception_object); | |
ed3cb497 | 102 | if (__gnu_cxx::__eh_atomic_dec (&eh->referenceCount)) |
30a333ce | 103 | { |
c4bca01b JJ |
104 | if (eh->exc.exceptionDestructor) |
105 | eh->exc.exceptionDestructor (_M_exception_object); | |
30a333ce PC |
106 | |
107 | __cxa_free_exception (_M_exception_object); | |
1352ea19 | 108 | _M_exception_object = nullptr; |
30a333ce PC |
109 | } |
110 | } | |
111 | } | |
112 | ||
113 | ||
114 | void* | |
a3dbb635 | 115 | std::__exception_ptr::exception_ptr::_M_get() const noexcept |
8eead16e | 116 | { return _M_exception_object; } |
30a333ce PC |
117 | |
118 | ||
30a333ce | 119 | |
b4e77f9b JW |
120 | // Retained for compatibility with CXXABI_1.3. |
121 | void | |
a3dbb635 | 122 | std::__exception_ptr::exception_ptr::_M_safe_bool_dummy() noexcept { } |
b4e77f9b JW |
123 | |
124 | ||
110a123a | 125 | // Retained for compatibility with CXXABI_1.3. |
30a333ce | 126 | bool |
a3dbb635 | 127 | std::__exception_ptr::exception_ptr::operator!() const noexcept |
1352ea19 | 128 | { return _M_exception_object == nullptr; } |
30a333ce PC |
129 | |
130 | ||
110a123a | 131 | // Retained for compatibility with CXXABI_1.3. |
a3dbb635 | 132 | std::__exception_ptr::exception_ptr::operator __safe_bool() const noexcept |
30a333ce | 133 | { |
1352ea19 | 134 | return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : nullptr; |
30a333ce PC |
135 | } |
136 | ||
30a333ce | 137 | const std::type_info* |
a3dbb635 | 138 | std::__exception_ptr::exception_ptr::__cxa_exception_type() const noexcept |
30a333ce PC |
139 | { |
140 | __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object); | |
141 | return eh->exceptionType; | |
142 | } | |
143 | ||
30a333ce | 144 | std::exception_ptr |
a3dbb635 | 145 | std::current_exception() noexcept |
30a333ce PC |
146 | { |
147 | __cxa_eh_globals *globals = __cxa_get_globals (); | |
148 | __cxa_exception *header = globals->caughtExceptions; | |
149 | ||
150 | if (!header) | |
151 | return std::exception_ptr(); | |
152 | ||
153 | // Since foreign exceptions can't be counted, we can't return them. | |
154 | if (!__is_gxx_exception_class (header->unwindHeader.exception_class)) | |
155 | return std::exception_ptr(); | |
156 | ||
157 | return std::exception_ptr( | |
158 | __get_object_from_ambiguous_exception (header)); | |
159 | } | |
160 | ||
161 | ||
162 | static void | |
8eead16e BK |
163 | __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code, |
164 | _Unwind_Exception *exc) | |
30a333ce PC |
165 | { |
166 | // This cleanup is set only for dependents. | |
167 | __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc); | |
c4bca01b JJ |
168 | __cxa_refcounted_exception *header = |
169 | __get_refcounted_exception_header_from_obj (dep->primaryException); | |
30a333ce PC |
170 | |
171 | // We only want to be called through _Unwind_DeleteException. | |
172 | // _Unwind_DeleteException in the HP-UX IA64 libunwind library | |
173 | // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT | |
174 | // like the GCC _Unwind_DeleteException function does. | |
175 | if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) | |
c4bca01b | 176 | __terminate (header->exc.terminateHandler); |
30a333ce PC |
177 | |
178 | __cxa_free_dependent_exception (dep); | |
179 | ||
ed3cb497 | 180 | if (__gnu_cxx::__eh_atomic_dec (&header->referenceCount)) |
30a333ce | 181 | { |
c4bca01b JJ |
182 | if (header->exc.exceptionDestructor) |
183 | header->exc.exceptionDestructor (header + 1); | |
30a333ce PC |
184 | |
185 | __cxa_free_exception (header + 1); | |
186 | } | |
187 | } | |
188 | ||
189 | ||
190 | void | |
191 | std::rethrow_exception(std::exception_ptr ep) | |
192 | { | |
193 | void *obj = ep._M_get(); | |
c4bca01b JJ |
194 | __cxa_refcounted_exception *eh |
195 | = __get_refcounted_exception_header_from_obj (obj); | |
30a333ce PC |
196 | |
197 | __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception (); | |
198 | dep->primaryException = obj; | |
ed3cb497 | 199 | __gnu_cxx::__eh_atomic_inc (&eh->referenceCount); |
30a333ce | 200 | |
f4130a3e JW |
201 | #pragma GCC diagnostic push |
202 | #pragma GCC diagnostic ignored "-Wdeprecated-declarations" | |
7e20f4b0 | 203 | dep->unexpectedHandler = get_unexpected (); |
f4130a3e | 204 | #pragma GCC diagnostic pop |
7e20f4b0 | 205 | dep->terminateHandler = get_terminate (); |
30a333ce PC |
206 | __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class); |
207 | dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup; | |
208 | ||
f5eedc39 DP |
209 | __cxa_eh_globals *globals = __cxa_get_globals (); |
210 | globals->uncaughtExceptions += 1; | |
211 | ||
9b92a9f3 | 212 | #ifdef __USING_SJLJ_EXCEPTIONS__ |
30a333ce PC |
213 | _Unwind_SjLj_RaiseException (&dep->unwindHeader); |
214 | #else | |
215 | _Unwind_RaiseException (&dep->unwindHeader); | |
216 | #endif | |
217 | ||
218 | // Some sort of unwinding error. Note that terminate is a handler. | |
219 | __cxa_begin_catch (&dep->unwindHeader); | |
8eead16e | 220 | std::terminate(); |
30a333ce PC |
221 | } |
222 | ||
110a123a | 223 | #undef _GLIBCXX_EH_PTR_COMPAT |