exception.cpp revision 227825
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. 34std::unexpected_handler 35std::set_unexpected(std::unexpected_handler func) _NOEXCEPT 36{ 37 return __sync_lock_test_and_set(&__unexpected_handler, func); 38} 39 40std::unexpected_handler 41std::get_unexpected() _NOEXCEPT 42{ 43 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0); 44} 45 46_ATTRIBUTE(noreturn) 47void 48std::unexpected() 49{ 50 (*std::get_unexpected())(); 51 // unexpected handler should not return 52 std::terminate(); 53} 54 55std::terminate_handler 56std::set_terminate(std::terminate_handler func) _NOEXCEPT 57{ 58 return __sync_lock_test_and_set(&__terminate_handler, func); 59} 60 61std::terminate_handler 62std::get_terminate() _NOEXCEPT 63{ 64 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0); 65} 66 67_ATTRIBUTE(noreturn) 68void 69std::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 89bool 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 103namespace std 104{ 105 106exception::~exception() _NOEXCEPT 107{ 108} 109 110bad_exception::~bad_exception() _NOEXCEPT 111{ 112} 113 114const char* exception::what() const _NOEXCEPT 115{ 116 return "std::exception"; 117} 118 119const char* bad_exception::what() const _NOEXCEPT 120{ 121 return "std::bad_exception"; 122} 123 124exception_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 134exception_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 145exception_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 161nested_exception::nested_exception() _NOEXCEPT 162 : __ptr_(current_exception()) 163{ 164} 165 166nested_exception::~nested_exception() _NOEXCEPT 167{ 168} 169 170_ATTRIBUTE(noreturn) 171void 172nested_exception::rethrow_nested() const 173{ 174 if (__ptr_ == nullptr) 175 terminate(); 176 rethrow_exception(__ptr_); 177} 178 179} // std 180 181std::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 196void 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