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 _ATTRIBUTE(noreturn) 60 void 61 std::terminate() _NOEXCEPT 62 { 63 #ifndef _LIBCPP_NO_EXCEPTIONS 64 try 65 { 66 #endif // _LIBCPP_NO_EXCEPTIONS 67 (*std::get_terminate())(); 68 // handler should not return 69 ::abort (); 70 #ifndef _LIBCPP_NO_EXCEPTIONS 71 } 72 catch (...) 73 { 74 // handler should not throw exception 75 ::abort (); 76 } 77 #endif // _LIBCPP_NO_EXCEPTIONS 78 } 79 80 bool std::uncaught_exception() _NOEXCEPT 81 { 82 #if __APPLE__ 83 // on Darwin, there is a helper function so __cxa_get_globals is private 84 return __cxxabiapple::__cxa_uncaught_exception(); 85 #else // __APPLE__ 86 #warning uncaught_exception not yet implemented 87 ::abort(); 88 // Not provided by Ubuntu gcc-4.2.4's cxxabi.h. 89 // __cxa_eh_globals * globals = __cxa_get_globals(); 90 // return (globals->uncaughtExceptions != 0); 91 #endif // __APPLE__ 92 } 93 94 namespace std 95 { 96 97 exception::~exception() _NOEXCEPT 98 { 99 } 100 101 bad_exception::~bad_exception() _NOEXCEPT 102 { 103 } 104 105 const char* exception::what() const _NOEXCEPT 106 { 107 return "std::exception"; 108 } 109 110 const char* bad_exception::what() const _NOEXCEPT 111 { 112 return "std::bad_exception"; 113 } 114 115 exception_ptr::~exception_ptr() _NOEXCEPT 116 { 117 #if __APPLE__ 118 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_); 119 #else 120 #warning exception_ptr not yet implemented 121 ::abort(); 122 #endif // __APPLE__ 123 } 124 125 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 126 : __ptr_(other.__ptr_) 127 { 128 #if __APPLE__ 129 __cxxabiapple::__cxa_increment_exception_refcount(__ptr_); 130 #else 131 #warning exception_ptr not yet implemented 132 ::abort(); 133 #endif // __APPLE__ 134 } 135 136 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 137 { 138 #if __APPLE__ 139 if (__ptr_ != other.__ptr_) 140 { 141 __cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_); 142 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_); 143 __ptr_ = other.__ptr_; 144 } 145 return *this; 146 #else // __APPLE__ 147 #warning exception_ptr not yet implemented 148 ::abort(); 149 #endif // __APPLE__ 150 } 151 152 nested_exception::nested_exception() _NOEXCEPT 153 : __ptr_(current_exception()) 154 { 155 } 156 157 nested_exception::~nested_exception() _NOEXCEPT 158 { 159 } 160 161 _ATTRIBUTE(noreturn) 162 void 163 nested_exception::rethrow_nested() const 164 { 165 if (__ptr_ == nullptr) 166 terminate(); 167 rethrow_exception(__ptr_); 168 } 169 170 } // std 171 172 std::exception_ptr std::current_exception() _NOEXCEPT 173 { 174 #if __APPLE__ 175 // be nicer if there was a constructor that took a ptr, then 176 // this whole function would be just: 177 // return exception_ptr(__cxa_current_primary_exception()); 178 std::exception_ptr ptr; 179 ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception(); 180 return ptr; 181 #else // __APPLE__ 182 #warning exception_ptr not yet implemented 183 ::abort(); 184 #endif // __APPLE__ 185 } 186 187 void std::rethrow_exception(exception_ptr p) 188 { 189 #if __APPLE__ 190 __cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_); 191 // if p.__ptr_ is NULL, above returns so we terminate 192 terminate(); 193 #else // __APPLE__ 194 #warning exception_ptr not yet implemented 195 ::abort(); 196 #endif // __APPLE__ 197 } 198