1 // -*- C++ -*- Implement the members of exception_ptr. 2 // Copyright (C) 2008, 2009 Free Software Foundation, Inc. 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 8 // the Free Software Foundation; either version 3, or (at your option) 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 // 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. 19 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/>. 24 25 #include <bits/c++config.h> 26 27 #ifdef _GLIBCXX_ATOMIC_BUILTINS_4 28 29 #define _GLIBCXX_EH_PTR_COMPAT 30 31 #include <exception> 32 #include <exception_ptr.h> 33 #include "unwind-cxx.h" 34 35 using namespace __cxxabiv1; 36 37 std::__exception_ptr::exception_ptr::exception_ptr() throw() 38 : _M_exception_object(0) { } 39 40 41 std::__exception_ptr::exception_ptr::exception_ptr(void* obj) throw() 42 : _M_exception_object(obj) { _M_addref(); } 43 44 45 std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) throw() 46 : _M_exception_object(0) { } 47 48 49 std::__exception_ptr:: 50 exception_ptr::exception_ptr(const exception_ptr& other) throw() 51 : _M_exception_object(other._M_exception_object) 52 { _M_addref(); } 53 54 55 std::__exception_ptr::exception_ptr::~exception_ptr() throw() 56 { _M_release(); } 57 58 59 std::__exception_ptr::exception_ptr& 60 std::__exception_ptr:: 61 exception_ptr::operator=(const exception_ptr& other) throw() 62 { 63 exception_ptr(other).swap(*this); 64 return *this; 65 } 66 67 68 void 69 std::__exception_ptr::exception_ptr::_M_addref() throw() 70 { 71 if (_M_exception_object) 72 { 73 __cxa_refcounted_exception *eh = 74 __get_refcounted_exception_header_from_obj (_M_exception_object); 75 __sync_add_and_fetch (&eh->referenceCount, 1); 76 } 77 } 78 79 80 void 81 std::__exception_ptr::exception_ptr::_M_release() throw() 82 { 83 if (_M_exception_object) 84 { 85 __cxa_refcounted_exception *eh = 86 __get_refcounted_exception_header_from_obj (_M_exception_object); 87 if (__sync_sub_and_fetch (&eh->referenceCount, 1) == 0) 88 { 89 if (eh->exc.exceptionDestructor) 90 eh->exc.exceptionDestructor (_M_exception_object); 91 92 __cxa_free_exception (_M_exception_object); 93 _M_exception_object = 0; 94 } 95 } 96 } 97 98 99 void* 100 std::__exception_ptr::exception_ptr::_M_get() const throw() 101 { return _M_exception_object; } 102 103 104 void 105 std::__exception_ptr::exception_ptr::_M_safe_bool_dummy() throw () { } 106 107 108 void 109 std::__exception_ptr::exception_ptr::swap(exception_ptr &other) throw() 110 { 111 void *tmp = _M_exception_object; 112 _M_exception_object = other._M_exception_object; 113 other._M_exception_object = tmp; 114 } 115 116 117 // Retained for compatibility with CXXABI_1.3. 118 bool 119 std::__exception_ptr::exception_ptr::operator!() const throw() 120 { return _M_exception_object == 0; } 121 122 123 // Retained for compatibility with CXXABI_1.3. 124 std::__exception_ptr::exception_ptr::operator __safe_bool() const throw() 125 { 126 return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0; 127 } 128 129 130 const std::type_info* 131 std::__exception_ptr::exception_ptr::__cxa_exception_type() const throw() 132 { 133 __cxa_exception *eh = __get_exception_header_from_obj (_M_exception_object); 134 return eh->exceptionType; 135 } 136 137 138 bool std::__exception_ptr::operator==(const exception_ptr& lhs, 139 const exception_ptr& rhs) throw() 140 { return lhs._M_exception_object == rhs._M_exception_object; } 141 142 143 bool std::__exception_ptr::operator!=(const exception_ptr& lhs, 144 const exception_ptr& rhs) throw() 145 { return !(lhs == rhs);} 146 147 148 std::exception_ptr 149 std::current_exception() throw() 150 { 151 __cxa_eh_globals *globals = __cxa_get_globals (); 152 __cxa_exception *header = globals->caughtExceptions; 153 154 if (!header) 155 return std::exception_ptr(); 156 157 // Since foreign exceptions can't be counted, we can't return them. 158 if (!__is_gxx_exception_class (header->unwindHeader.exception_class)) 159 return std::exception_ptr(); 160 161 return std::exception_ptr( 162 __get_object_from_ambiguous_exception (header)); 163 } 164 165 166 static void 167 __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code, 168 _Unwind_Exception *exc) 169 { 170 // This cleanup is set only for dependents. 171 __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc); 172 __cxa_refcounted_exception *header = 173 __get_refcounted_exception_header_from_obj (dep->primaryException); 174 175 // We only want to be called through _Unwind_DeleteException. 176 // _Unwind_DeleteException in the HP-UX IA64 libunwind library 177 // returns _URC_NO_REASON and not _URC_FOREIGN_EXCEPTION_CAUGHT 178 // like the GCC _Unwind_DeleteException function does. 179 if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON) 180 __terminate (header->exc.terminateHandler); 181 182 __cxa_free_dependent_exception (dep); 183 184 if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0) 185 { 186 if (header->exc.exceptionDestructor) 187 header->exc.exceptionDestructor (header + 1); 188 189 __cxa_free_exception (header + 1); 190 } 191 } 192 193 194 void 195 std::rethrow_exception(std::exception_ptr ep) 196 { 197 void *obj = ep._M_get(); 198 __cxa_refcounted_exception *eh 199 = __get_refcounted_exception_header_from_obj (obj); 200 201 __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception (); 202 dep->primaryException = obj; 203 __sync_add_and_fetch (&eh->referenceCount, 1); 204 205 dep->unexpectedHandler = __unexpected_handler; 206 dep->terminateHandler = __terminate_handler; 207 __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class); 208 dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup; 209 210 #ifdef _GLIBCXX_SJLJ_EXCEPTIONS 211 _Unwind_SjLj_RaiseException (&dep->unwindHeader); 212 #else 213 _Unwind_RaiseException (&dep->unwindHeader); 214 #endif 215 216 // Some sort of unwinding error. Note that terminate is a handler. 217 __cxa_begin_catch (&dep->unwindHeader); 218 std::terminate(); 219 } 220 221 #undef _GLIBCXX_EH_PTR_COMPAT 222 223 #endif 224