]>
Commit | Line | Data |
---|---|---|
1e75b4be | 1 | // -*- C++ -*- Implement the members of exception_ptr. |
f1717362 | 2 | // Copyright (C) 2008-2016 Free Software Foundation, Inc. |
1e75b4be | 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 | |
6bc9506f | 8 | // the Free Software Foundation; either version 3, or (at your option) |
1e75b4be | 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 | // | |
6bc9506f | 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. | |
1e75b4be | 19 | |
6bc9506f | 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/>. | |
1e75b4be | 24 | |
25 | #include <bits/c++config.h> | |
06bc5cca | 26 | #include <bits/atomic_lockfree_defines.h> |
1e75b4be | 27 | |
06bc5cca | 28 | #if ATOMIC_INT_LOCK_FREE > 1 |
1e75b4be | 29 | |
65f3a02c | 30 | #define _GLIBCXX_EH_PTR_COMPAT |
31 | ||
1e75b4be | 32 | #include <exception> |
dee74d2b | 33 | #include <bits/exception_ptr.h> |
1e75b4be | 34 | #include "unwind-cxx.h" |
35 | ||
36 | using namespace __cxxabiv1; | |
37 | ||
c13b2ff9 | 38 | // Verify assumptions about member layout in exception types |
39 | namespace | |
40 | { | |
41 | template<typename Ex> | |
42 | constexpr std::size_t unwindhdr() | |
43 | { return offsetof(Ex, unwindHeader); } | |
44 | ||
45 | template<typename Ex> | |
46 | constexpr std::size_t termHandler() | |
47 | { return unwindhdr<Ex>() - offsetof(Ex, terminateHandler); } | |
48 | ||
49 | static_assert( termHandler<__cxa_exception>() | |
50 | == termHandler<__cxa_dependent_exception>(), | |
aeebd7a5 | 51 | "__cxa_dependent_exception::termHandler layout must be" |
52 | " consistent with __cxa_exception::termHandler" ); | |
c13b2ff9 | 53 | |
54 | #ifndef __ARM_EABI_UNWINDER__ | |
55 | template<typename Ex> | |
56 | constexpr std::ptrdiff_t adjptr() | |
57 | { return unwindhdr<Ex>() - offsetof(Ex, adjustedPtr); } | |
58 | ||
59 | static_assert( adjptr<__cxa_exception>() | |
60 | == adjptr<__cxa_dependent_exception>(), | |
aeebd7a5 | 61 | "__cxa_dependent_exception::adjustedPtr layout must be" |
62 | " consistent with __cxa_exception::adjustedPtr" ); | |
c13b2ff9 | 63 | #endif |
64 | } | |
65 | ||
d2b14329 | 66 | std::__exception_ptr::exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT |
2cc4eeef | 67 | : _M_exception_object(0) { } |
1e75b4be | 68 | |
69 | ||
d2b14329 | 70 | std::__exception_ptr::exception_ptr::exception_ptr(void* obj) |
71 | _GLIBCXX_USE_NOEXCEPT | |
2cc4eeef | 72 | : _M_exception_object(obj) { _M_addref(); } |
1e75b4be | 73 | |
74 | ||
d2b14329 | 75 | std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) |
76 | _GLIBCXX_USE_NOEXCEPT | |
2cc4eeef | 77 | : _M_exception_object(0) { } |
1e75b4be | 78 | |
79 | ||
2cc4eeef | 80 | std::__exception_ptr:: |
d2b14329 | 81 | exception_ptr::exception_ptr(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT |
2cc4eeef | 82 | : _M_exception_object(other._M_exception_object) |
83 | { _M_addref(); } | |
1e75b4be | 84 | |
85 | ||
d2b14329 | 86 | std::__exception_ptr::exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT |
2cc4eeef | 87 | { _M_release(); } |
1e75b4be | 88 | |
89 | ||
90 | std::__exception_ptr::exception_ptr& | |
2cc4eeef | 91 | std::__exception_ptr:: |
d2b14329 | 92 | exception_ptr::operator=(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT |
1e75b4be | 93 | { |
94 | exception_ptr(other).swap(*this); | |
95 | return *this; | |
96 | } | |
97 | ||
98 | ||
99 | void | |
d2b14329 | 100 | std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT |
1e75b4be | 101 | { |
102 | if (_M_exception_object) | |
103 | { | |
d6d31e2d | 104 | __cxa_refcounted_exception *eh = |
105 | __get_refcounted_exception_header_from_obj (_M_exception_object); | |
f06b9073 | 106 | __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL); |
1e75b4be | 107 | } |
108 | } | |
109 | ||
110 | ||
111 | void | |
d2b14329 | 112 | std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT |
1e75b4be | 113 | { |
114 | if (_M_exception_object) | |
115 | { | |
d6d31e2d | 116 | __cxa_refcounted_exception *eh = |
117 | __get_refcounted_exception_header_from_obj (_M_exception_object); | |
f06b9073 | 118 | if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0) |
1e75b4be | 119 | { |
d6d31e2d | 120 | if (eh->exc.exceptionDestructor) |
121 | eh->exc.exceptionDestructor (_M_exception_object); | |
1e75b4be | 122 | |
123 | __cxa_free_exception (_M_exception_object); | |
124 | _M_exception_object = 0; | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | ||
130 | void* | |
d2b14329 | 131 | std::__exception_ptr::exception_ptr::_M_get() const _GLIBCXX_USE_NOEXCEPT |
2cc4eeef | 132 | { return _M_exception_object; } |
1e75b4be | 133 | |
134 | ||
1e75b4be | 135 | void |
d2b14329 | 136 | std::__exception_ptr::exception_ptr::swap(exception_ptr &other) |
137 | _GLIBCXX_USE_NOEXCEPT | |
1e75b4be | 138 | { |
139 | void *tmp = _M_exception_object; | |
140 | _M_exception_object = other._M_exception_object; | |
141 | other._M_exception_object = tmp; | |
142 | } | |
143 | ||
144 | ||
4248af45 | 145 | // Retained for compatibility with CXXABI_1.3. |
146 | void | |
d2b14329 | 147 | std::__exception_ptr::exception_ptr::_M_safe_bool_dummy() |
148 | _GLIBCXX_USE_NOEXCEPT { } | |
4248af45 | 149 | |
150 | ||
65f3a02c | 151 | // Retained for compatibility with CXXABI_1.3. |
1e75b4be | 152 | bool |
d2b14329 | 153 | std::__exception_ptr::exception_ptr::operator!() const _GLIBCXX_USE_NOEXCEPT |
2cc4eeef | 154 | { return _M_exception_object == 0; } |
1e75b4be | 155 | |
156 | ||
65f3a02c | 157 | // Retained for compatibility with CXXABI_1.3. |
d2b14329 | 158 | std::__exception_ptr::exception_ptr::operator __safe_bool() const |
159 | _GLIBCXX_USE_NOEXCEPT | |
1e75b4be | 160 | { |
161 | return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0; | |
162 | } | |
163 | ||
164 | ||
165 | const std::type_info* | |
d2b14329 | 166 | std::__exception_ptr::exception_ptr::__cxa_exception_type() const |
167 | _GLIBCXX_USE_NOEXCEPT | |
1e75b4be | 168 | { |
169 | __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object); | |
170 | return eh->exceptionType; | |
171 | } | |
172 | ||
173 | ||
174 | bool std::__exception_ptr::operator==(const exception_ptr& lhs, | |
d2b14329 | 175 | const exception_ptr& rhs) |
176 | _GLIBCXX_USE_NOEXCEPT | |
2cc4eeef | 177 | { return lhs._M_exception_object == rhs._M_exception_object; } |
1e75b4be | 178 | |
179 | ||
180 | bool std::__exception_ptr::operator!=(const exception_ptr& lhs, | |
d2b14329 | 181 | const exception_ptr& rhs) |
182 | _GLIBCXX_USE_NOEXCEPT | |
2cc4eeef | 183 | { return !(lhs == rhs);} |
1e75b4be | 184 | |
185 | ||
186 | std::exception_ptr | |
d2b14329 | 187 | std::current_exception() _GLIBCXX_USE_NOEXCEPT |
1e75b4be | 188 | { |
189 | __cxa_eh_globals *globals = __cxa_get_globals (); | |
190 | __cxa_exception *header = globals->caughtExceptions; | |
191 | ||
192 | if (!header) | |
193 | return std::exception_ptr(); | |
194 | ||
195 | // Since foreign exceptions can't be counted, we can't return them. | |
196 | if (!__is_gxx_exception_class (header->unwindHeader.exception_class)) | |
197 | return std::exception_ptr(); | |
198 | ||
199 | return std::exception_ptr( | |
200 | __get_object_from_ambiguous_exception (header)); | |
201 | } | |
202 | ||
203 | ||
204 | static void | |
2cc4eeef | 205 | __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code, |
206 | _Unwind_Exception *exc) | |
1e75b4be | 207 | { |
208 | // This cleanup is set only for dependents. | |
209 | __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc); | |
d6d31e2d | 210 | __cxa_refcounted_exception *header = |
211 | __get_refcounted_exception_header_from_obj (dep->primaryException); | |
1e75b4be | 212 | |
213 | // We only want to be called through _Unwind_DeleteException. | |
214 | // _Unwind_DeleteException in the HP-UX IA64 libunwind library | |
215 | // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT | |
216 | // like the GCC _Unwind_DeleteException function does. | |
217 | if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) | |
d6d31e2d | 218 | __terminate (header->exc.terminateHandler); |
1e75b4be | 219 | |
220 | __cxa_free_dependent_exception (dep); | |
221 | ||
f06b9073 | 222 | if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0) |
1e75b4be | 223 | { |
d6d31e2d | 224 | if (header->exc.exceptionDestructor) |
225 | header->exc.exceptionDestructor (header + 1); | |
1e75b4be | 226 | |
227 | __cxa_free_exception (header + 1); | |
228 | } | |
229 | } | |
230 | ||
231 | ||
232 | void | |
233 | std::rethrow_exception(std::exception_ptr ep) | |
234 | { | |
235 | void *obj = ep._M_get(); | |
d6d31e2d | 236 | __cxa_refcounted_exception *eh |
237 | = __get_refcounted_exception_header_from_obj (obj); | |
1e75b4be | 238 | |
239 | __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception (); | |
240 | dep->primaryException = obj; | |
f06b9073 | 241 | __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL); |
1e75b4be | 242 | |
257b4f53 | 243 | dep->unexpectedHandler = get_unexpected (); |
244 | dep->terminateHandler = get_terminate (); | |
1e75b4be | 245 | __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class); |
246 | dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup; | |
247 | ||
102164d9 | 248 | __cxa_eh_globals *globals = __cxa_get_globals (); |
249 | globals->uncaughtExceptions += 1; | |
250 | ||
177cc56c | 251 | #ifdef __USING_SJLJ_EXCEPTIONS__ |
1e75b4be | 252 | _Unwind_SjLj_RaiseException (&dep->unwindHeader); |
253 | #else | |
254 | _Unwind_RaiseException (&dep->unwindHeader); | |
255 | #endif | |
256 | ||
257 | // Some sort of unwinding error. Note that terminate is a handler. | |
258 | __cxa_begin_catch (&dep->unwindHeader); | |
2cc4eeef | 259 | std::terminate(); |
1e75b4be | 260 | } |
261 | ||
65f3a02c | 262 | #undef _GLIBCXX_EH_PTR_COMPAT |
263 | ||
1e75b4be | 264 | #endif |