xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/libsupc++/eh_ptr.cc (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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