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