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