1 // -*- C++ -*- Implement the members of exception_ptr. 2 // Copyright (C) 2008-2015 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 #include <bits/atomic_lockfree_defines.h> 27 28 #if ATOMIC_INT_LOCK_FREE > 1 29 30 #define _GLIBCXX_EH_PTR_COMPAT 31 32 #include <exception> 33 #include <bits/exception_ptr.h> 34 #include "unwind-cxx.h" 35 36 using namespace __cxxabiv1; 37 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>(), 51 "__cxa_dependent_exception::termHandler layout must be" 52 " consistent with __cxa_exception::termHandler" ); 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>(), 61 "__cxa_dependent_exception::adjustedPtr layout must be" 62 " consistent with __cxa_exception::adjustedPtr" ); 63 #endif 64 } 65 66 std::__exception_ptr::exception_ptr::exception_ptr() _GLIBCXX_USE_NOEXCEPT 67 : _M_exception_object(0) { } 68 69 70 std::__exception_ptr::exception_ptr::exception_ptr(void* obj) 71 _GLIBCXX_USE_NOEXCEPT 72 : _M_exception_object(obj) { _M_addref(); } 73 74 75 std::__exception_ptr::exception_ptr::exception_ptr(__safe_bool) 76 _GLIBCXX_USE_NOEXCEPT 77 : _M_exception_object(0) { } 78 79 80 std::__exception_ptr:: 81 exception_ptr::exception_ptr(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT 82 : _M_exception_object(other._M_exception_object) 83 { _M_addref(); } 84 85 86 std::__exception_ptr::exception_ptr::~exception_ptr() _GLIBCXX_USE_NOEXCEPT 87 { _M_release(); } 88 89 90 std::__exception_ptr::exception_ptr& 91 std::__exception_ptr:: 92 exception_ptr::operator=(const exception_ptr& other) _GLIBCXX_USE_NOEXCEPT 93 { 94 exception_ptr(other).swap(*this); 95 return *this; 96 } 97 98 99 void 100 std::__exception_ptr::exception_ptr::_M_addref() _GLIBCXX_USE_NOEXCEPT 101 { 102 if (_M_exception_object) 103 { 104 __cxa_refcounted_exception *eh = 105 __get_refcounted_exception_header_from_obj (_M_exception_object); 106 __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL); 107 } 108 } 109 110 111 void 112 std::__exception_ptr::exception_ptr::_M_release() _GLIBCXX_USE_NOEXCEPT 113 { 114 if (_M_exception_object) 115 { 116 __cxa_refcounted_exception *eh = 117 __get_refcounted_exception_header_from_obj (_M_exception_object); 118 if (__atomic_sub_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL) == 0) 119 { 120 if (eh->exc.exceptionDestructor) 121 eh->exc.exceptionDestructor (_M_exception_object); 122 123 __cxa_free_exception (_M_exception_object); 124 _M_exception_object = 0; 125 } 126 } 127 } 128 129 130 void* 131 std::__exception_ptr::exception_ptr::_M_get() const _GLIBCXX_USE_NOEXCEPT 132 { return _M_exception_object; } 133 134 135 void 136 std::__exception_ptr::exception_ptr::swap(exception_ptr &other) 137 _GLIBCXX_USE_NOEXCEPT 138 { 139 void *tmp = _M_exception_object; 140 _M_exception_object = other._M_exception_object; 141 other._M_exception_object = tmp; 142 } 143 144 145 // Retained for compatibility with CXXABI_1.3. 146 void 147 std::__exception_ptr::exception_ptr::_M_safe_bool_dummy() 148 _GLIBCXX_USE_NOEXCEPT { } 149 150 151 // Retained for compatibility with CXXABI_1.3. 152 bool 153 std::__exception_ptr::exception_ptr::operator!() const _GLIBCXX_USE_NOEXCEPT 154 { return _M_exception_object == 0; } 155 156 157 // Retained for compatibility with CXXABI_1.3. 158 std::__exception_ptr::exception_ptr::operator __safe_bool() const 159 _GLIBCXX_USE_NOEXCEPT 160 { 161 return _M_exception_object ? &exception_ptr::_M_safe_bool_dummy : 0; 162 } 163 164 165 const std::type_info* 166 std::__exception_ptr::exception_ptr::__cxa_exception_type() const 167 _GLIBCXX_USE_NOEXCEPT 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, 175 const exception_ptr& rhs) 176 _GLIBCXX_USE_NOEXCEPT 177 { return lhs._M_exception_object == rhs._M_exception_object; } 178 179 180 bool std::__exception_ptr::operator!=(const exception_ptr& lhs, 181 const exception_ptr& rhs) 182 _GLIBCXX_USE_NOEXCEPT 183 { return !(lhs == rhs);} 184 185 186 std::exception_ptr 187 std::current_exception() _GLIBCXX_USE_NOEXCEPT 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 205 __gxx_dependent_exception_cleanup(_Unwind_Reason_Code code, 206 _Unwind_Exception *exc) 207 { 208 // This cleanup is set only for dependents. 209 __cxa_dependent_exception *dep = __get_dependent_exception_from_ue (exc); 210 __cxa_refcounted_exception *header = 211 __get_refcounted_exception_header_from_obj (dep->primaryException); 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) 218 __terminate (header->exc.terminateHandler); 219 220 __cxa_free_dependent_exception (dep); 221 222 if (__atomic_sub_fetch (&header->referenceCount, 1, __ATOMIC_ACQ_REL) == 0) 223 { 224 if (header->exc.exceptionDestructor) 225 header->exc.exceptionDestructor (header + 1); 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(); 236 __cxa_refcounted_exception *eh 237 = __get_refcounted_exception_header_from_obj (obj); 238 239 __cxa_dependent_exception *dep = __cxa_allocate_dependent_exception (); 240 dep->primaryException = obj; 241 __atomic_add_fetch (&eh->referenceCount, 1, __ATOMIC_ACQ_REL); 242 243 dep->unexpectedHandler = get_unexpected (); 244 dep->terminateHandler = get_terminate (); 245 __GXX_INIT_DEPENDENT_EXCEPTION_CLASS(dep->unwindHeader.exception_class); 246 dep->unwindHeader.exception_cleanup = __gxx_dependent_exception_cleanup; 247 248 __cxa_eh_globals *globals = __cxa_get_globals (); 249 globals->uncaughtExceptions += 1; 250 251 #ifdef _GLIBCXX_SJLJ_EXCEPTIONS 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); 259 std::terminate(); 260 } 261 262 #undef _GLIBCXX_EH_PTR_COMPAT 263 264 #endif 265