1 // -*- C++ -*- Implement the members of exception_ptr.
2 // Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
4 // This file is part of GCC.
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
8 // the Free Software Foundation; either version 3, or (at your option)
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.
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.
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/>.
25 #include <bits/c++config.h>
26 #include <bits/atomic_lockfree_defines.h>
28 #if ATOMIC_INT_LOCK_FREE > 1
30 #define _GLIBCXX_EH_PTR_COMPAT
33 #include <bits/exception_ptr.h>
34 #include "unwind-cxx.h"
36 using namespace __cxxabiv1;
38 std::__exception_ptr::exception_ptr::exception_ptr() throw()
39 : _M_exception_object(0) { }
42 std::__exception_ptr::exception_ptr::exception_ptr(void* obj) throw()
43 : _M_exception_object(obj) { _M_addref(); }
46 std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) throw()
47 : _M_exception_object(0) { }
50 std::__exception_ptr::
51 exception_ptr::exception_ptr(const exception_ptr& other) throw()
52 : _M_exception_object(other._M_exception_object)
56 std::__exception_ptr::exception_ptr::~exception_ptr() throw()
60 std::__exception_ptr::exception_ptr&
61 std::__exception_ptr::
62 exception_ptr::operator=(const exception_ptr& other) throw()
64 exception_ptr(other).swap(*this);
70 std::__exception_ptr::exception_ptr::_M_addref() throw()
72 if (_M_exception_object)
74 __cxa_refcounted_exception *eh =
75 __get_refcounted_exception_header_from_obj (_M_exception_object);
76 __sync_add_and_fetch (&eh->referenceCount, 1);
82 std::__exception_ptr::exception_ptr::_M_release() throw()
84 if (_M_exception_object)
86 __cxa_refcounted_exception *eh =
87 __get_refcounted_exception_header_from_obj (_M_exception_object);
88 if (__sync_sub_and_fetch (&eh->referenceCount, 1) == 0)
90 if (eh->exc.exceptionDestructor)
91 eh->exc.exceptionDestructor (_M_exception_object);
93 __cxa_free_exception (_M_exception_object);
94 _M_exception_object = 0;
101 std::__exception_ptr::exception_ptr::_M_get() const throw()
102 { return _M_exception_object; }
106 std::__exception_ptr::exception_ptr::swap(exception_ptr &other) throw()
108 void *tmp = _M_exception_object;
109 _M_exception_object = other._M_exception_object;
110 other._M_exception_object = tmp;
114 // Retained for compatibility with CXXABI_1.3.
116 std::__exception_ptr::exception_ptr::_M_safe_bool_dummy() throw () { }
119 // Retained for compatibility with CXXABI_1.3.
121 std::__exception_ptr::exception_ptr::operator!() const throw()
122 { return _M_exception_object == 0; }
125 // Retained for compatibility with CXXABI_1.3.
126 std::__exception_ptr::exception_ptr::operator __safe_bool() const throw()
128 return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0;
132 const std::type_info*
133 std::__exception_ptr::exception_ptr::__cxa_exception_type() const throw()
135 __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object);
136 return eh->exceptionType;
140 bool std::__exception_ptr::operator==(const exception_ptr& lhs,
141 const exception_ptr& rhs) throw()
142 { return lhs._M_exception_object == rhs._M_exception_object; }
145 bool std::__exception_ptr::operator!=(const exception_ptr& lhs,
146 const exception_ptr& rhs) throw()
147 { return !(lhs == rhs);}
151 std::current_exception() throw()
153 __cxa_eh_globals *globals = __cxa_get_globals ();
154 __cxa_exception *header = globals->caughtExceptions;
157 return std::exception_ptr();
159 // Since foreign exceptions can't be counted, we can't return them.
160 if (!__is_gxx_exception_class (header->unwindHeader.exception_class))
161 return std::exception_ptr();
163 return std::exception_ptr(
164 __get_object_from_ambiguous_exception (header));
169 __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code,
170 _Unwind_Exception *exc)
172 // This cleanup is set only for dependents.
173 __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc);
174 __cxa_refcounted_exception *header =
175 __get_refcounted_exception_header_from_obj (dep->primaryException);
177 // We only want to be called through _Unwind_DeleteException.
178 // _Unwind_DeleteException in the HP-UX IA64 libunwind library
179 // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT
180 // like the GCC _Unwind_DeleteException function does.
181 if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
182 __terminate (header->exc.terminateHandler);
184 __cxa_free_dependent_exception (dep);
186 if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
188 if (header->exc.exceptionDestructor)
189 header->exc.exceptionDestructor (header + 1);
191 __cxa_free_exception (header + 1);
197 std::rethrow_exception(std::exception_ptr ep)
199 void *obj = ep._M_get();
200 __cxa_refcounted_exception *eh
201 = __get_refcounted_exception_header_from_obj (obj);
203 __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception ();
204 dep->primaryException = obj;
205 __sync_add_and_fetch (&eh->referenceCount, 1);
207 dep->unexpectedHandler = __unexpected_handler;
208 dep->terminateHandler = __terminate_handler;
209 __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class);
210 dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup;
212 #ifdef _GLIBCXX_SJLJ_EXCEPTIONS
213 _Unwind_SjLj_RaiseException (&dep->unwindHeader);
215 _Unwind_RaiseException (&dep->unwindHeader);
218 // Some sort of unwinding error. Note that terminate is a handler.
219 __cxa_begin_catch (&dep->unwindHeader);
223 #undef _GLIBCXX_EH_PTR_COMPAT