1 //===------------------------ exception.cpp -------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 #include <stdlib.h> 10 11 #include "exception" 12 13 #if __APPLE__ 14 #include <cxxabi.h> 15 16 using namespace __cxxabiv1; 17 #define HAVE_DEPENDENT_EH_ABI 1 18 #ifndef _LIBCPPABI_VERSION 19 using namespace __cxxabiapple; 20 // On Darwin, there are two STL shared libraries and a lower level ABI 21 // shared libray. The globals holding the current terminate handler and 22 // current unexpected handler are in the ABI library. 23 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 24 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 25 #endif // _LIBCPPABI_VERSION 26 #elif defined(LIBCXXRT) 27 #include <cxxabi.h> 28 using namespace __cxxabiv1; 29 #define HAVE_DEPENDENT_EH_ABI 1 30 #else // __APPLE__ 31 static std::terminate_handler __terminate_handler; 32 static std::unexpected_handler __unexpected_handler; 33 #endif // __APPLE__ 34 35 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 36 37 // libcxxrt provides implementations of these functions itself. 38 std::unexpected_handler 39 std::set_unexpected(std::unexpected_handler func) _NOEXCEPT 40 { 41 return __sync_lock_test_and_set(&__unexpected_handler, func); 42 } 43 44 std::unexpected_handler 45 std::get_unexpected() _NOEXCEPT 46 { 47 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0); 48 } 49 50 _ATTRIBUTE(noreturn) 51 void 52 std::unexpected() 53 { 54 (*std::get_unexpected())(); 55 // unexpected handler should not return 56 std::terminate(); 57 } 58 59 std::terminate_handler 60 std::set_terminate(std::terminate_handler func) _NOEXCEPT 61 { 62 return __sync_lock_test_and_set(&__terminate_handler, func); 63 } 64 65 std::terminate_handler 66 std::get_terminate() _NOEXCEPT 67 { 68 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0); 69 } 70 71 _ATTRIBUTE(noreturn) 72 void 73 std::terminate() _NOEXCEPT 74 { 75 #ifndef _LIBCPP_NO_EXCEPTIONS 76 try 77 { 78 #endif // _LIBCPP_NO_EXCEPTIONS 79 (*std::get_terminate())(); 80 // handler should not return 81 ::abort (); 82 #ifndef _LIBCPP_NO_EXCEPTIONS 83 } 84 catch (...) 85 { 86 // handler should not throw exception 87 ::abort (); 88 } 89 #endif // _LIBCPP_NO_EXCEPTIONS 90 } 91 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 92 93 bool std::uncaught_exception() _NOEXCEPT 94 { 95 #if __APPLE__ 96 // on Darwin, there is a helper function so __cxa_get_globals is private 97 return __cxa_uncaught_exception(); 98 #elif LIBCXXRT 99 __cxa_eh_globals * globals = __cxa_get_globals(); 100 return (globals->uncaughtExceptions != 0); 101 #else // __APPLE__ 102 #warning uncaught_exception not yet implemented 103 ::abort(); 104 #endif // __APPLE__ 105 } 106 107 namespace std 108 { 109 110 #ifndef _LIBCPPABI_VERSION 111 112 exception::~exception() _NOEXCEPT 113 { 114 } 115 116 bad_exception::~bad_exception() _NOEXCEPT 117 { 118 } 119 120 const char* exception::what() const _NOEXCEPT 121 { 122 return "std::exception"; 123 } 124 125 const char* bad_exception::what() const _NOEXCEPT 126 { 127 return "std::bad_exception"; 128 } 129 130 #endif // _LIBCPPABI_VERSION 131 132 exception_ptr::~exception_ptr() _NOEXCEPT 133 { 134 #if HAVE_DEPENDENT_EH_ABI 135 __cxa_decrement_exception_refcount(__ptr_); 136 #else 137 #warning exception_ptr not yet implemented 138 ::abort(); 139 #endif // __APPLE__ 140 } 141 142 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 143 : __ptr_(other.__ptr_) 144 { 145 #if HAVE_DEPENDENT_EH_ABI 146 __cxa_increment_exception_refcount(__ptr_); 147 #else 148 #warning exception_ptr not yet implemented 149 ::abort(); 150 #endif // __APPLE__ 151 } 152 153 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 154 { 155 #if HAVE_DEPENDENT_EH_ABI 156 if (__ptr_ != other.__ptr_) 157 { 158 __cxa_increment_exception_refcount(other.__ptr_); 159 __cxa_decrement_exception_refcount(__ptr_); 160 __ptr_ = other.__ptr_; 161 } 162 return *this; 163 #else // __APPLE__ 164 #warning exception_ptr not yet implemented 165 ::abort(); 166 #endif // __APPLE__ 167 } 168 169 nested_exception::nested_exception() _NOEXCEPT 170 : __ptr_(current_exception()) 171 { 172 } 173 174 nested_exception::~nested_exception() _NOEXCEPT 175 { 176 } 177 178 _ATTRIBUTE(noreturn) 179 void 180 nested_exception::rethrow_nested() const 181 { 182 if (__ptr_ == nullptr) 183 terminate(); 184 rethrow_exception(__ptr_); 185 } 186 187 } // std 188 189 std::exception_ptr std::current_exception() _NOEXCEPT 190 { 191 #if HAVE_DEPENDENT_EH_ABI 192 // be nicer if there was a constructor that took a ptr, then 193 // this whole function would be just: 194 // return exception_ptr(__cxa_current_primary_exception()); 195 std::exception_ptr ptr; 196 ptr.__ptr_ = __cxa_current_primary_exception(); 197 return ptr; 198 #else // __APPLE__ 199 #warning exception_ptr not yet implemented 200 ::abort(); 201 #endif // __APPLE__ 202 } 203 204 _ATTRIBUTE(noreturn) 205 void std::rethrow_exception(exception_ptr p) 206 { 207 #if HAVE_DEPENDENT_EH_ABI 208 __cxa_rethrow_primary_exception(p.__ptr_); 209 // if p.__ptr_ is NULL, above returns so we terminate 210 terminate(); 211 #else // __APPLE__ 212 #warning exception_ptr not yet implemented 213 ::abort(); 214 #endif // __APPLE__ 215 } 216