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