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