1*4684ddb6SLionel Sambuc //===------------------------ exception.cpp -------------------------------===// 2*4684ddb6SLionel Sambuc // 3*4684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure 4*4684ddb6SLionel Sambuc // 5*4684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open 6*4684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details. 7*4684ddb6SLionel Sambuc // 8*4684ddb6SLionel Sambuc //===----------------------------------------------------------------------===// 9*4684ddb6SLionel Sambuc #include <stdlib.h> 10*4684ddb6SLionel Sambuc #include <stdio.h> 11*4684ddb6SLionel Sambuc 12*4684ddb6SLionel Sambuc #include "exception" 13*4684ddb6SLionel Sambuc #include "new" 14*4684ddb6SLionel Sambuc 15*4684ddb6SLionel Sambuc #ifndef __has_include 16*4684ddb6SLionel Sambuc #define __has_include(inc) 0 17*4684ddb6SLionel Sambuc #endif 18*4684ddb6SLionel Sambuc 19*4684ddb6SLionel Sambuc #ifdef __APPLE__ 20*4684ddb6SLionel Sambuc #include <cxxabi.h> 21*4684ddb6SLionel Sambuc 22*4684ddb6SLionel Sambuc using namespace __cxxabiv1; 23*4684ddb6SLionel Sambuc #define HAVE_DEPENDENT_EH_ABI 1 24*4684ddb6SLionel Sambuc #ifndef _LIBCPPABI_VERSION 25*4684ddb6SLionel Sambuc using namespace __cxxabiapple; 26*4684ddb6SLionel Sambuc // On Darwin, there are two STL shared libraries and a lower level ABI 27*4684ddb6SLionel Sambuc // shared library. The globals holding the current terminate handler and 28*4684ddb6SLionel Sambuc // current unexpected handler are in the ABI library. 29*4684ddb6SLionel Sambuc #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 30*4684ddb6SLionel Sambuc #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 31*4684ddb6SLionel Sambuc #endif // _LIBCPPABI_VERSION 32*4684ddb6SLionel Sambuc #elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 33*4684ddb6SLionel Sambuc #include <cxxabi.h> 34*4684ddb6SLionel Sambuc using namespace __cxxabiv1; 35*4684ddb6SLionel Sambuc #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 36*4684ddb6SLionel Sambuc #define HAVE_DEPENDENT_EH_ABI 1 37*4684ddb6SLionel Sambuc #endif 38*4684ddb6SLionel Sambuc #elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>) 39*4684ddb6SLionel Sambuc static std::terminate_handler __terminate_handler; 40*4684ddb6SLionel Sambuc static std::unexpected_handler __unexpected_handler; 41*4684ddb6SLionel Sambuc #endif // __has_include(<cxxabi.h>) 42*4684ddb6SLionel Sambuc 43*4684ddb6SLionel Sambuc namespace std 44*4684ddb6SLionel Sambuc { 45*4684ddb6SLionel Sambuc 46*4684ddb6SLionel Sambuc #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 47*4684ddb6SLionel Sambuc 48*4684ddb6SLionel Sambuc // libcxxrt provides implementations of these functions itself. 49*4684ddb6SLionel Sambuc unexpected_handler 50*4684ddb6SLionel Sambuc set_unexpected(unexpected_handler func) _NOEXCEPT 51*4684ddb6SLionel Sambuc { 52*4684ddb6SLionel Sambuc return __sync_lock_test_and_set(&__unexpected_handler, func); 53*4684ddb6SLionel Sambuc } 54*4684ddb6SLionel Sambuc 55*4684ddb6SLionel Sambuc unexpected_handler 56*4684ddb6SLionel Sambuc get_unexpected() _NOEXCEPT 57*4684ddb6SLionel Sambuc { 58*4684ddb6SLionel Sambuc return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 59*4684ddb6SLionel Sambuc } 60*4684ddb6SLionel Sambuc 61*4684ddb6SLionel Sambuc _LIBCPP_NORETURN 62*4684ddb6SLionel Sambuc void 63*4684ddb6SLionel Sambuc unexpected() 64*4684ddb6SLionel Sambuc { 65*4684ddb6SLionel Sambuc (*get_unexpected())(); 66*4684ddb6SLionel Sambuc // unexpected handler should not return 67*4684ddb6SLionel Sambuc terminate(); 68*4684ddb6SLionel Sambuc } 69*4684ddb6SLionel Sambuc 70*4684ddb6SLionel Sambuc terminate_handler 71*4684ddb6SLionel Sambuc set_terminate(terminate_handler func) _NOEXCEPT 72*4684ddb6SLionel Sambuc { 73*4684ddb6SLionel Sambuc return __sync_lock_test_and_set(&__terminate_handler, func); 74*4684ddb6SLionel Sambuc } 75*4684ddb6SLionel Sambuc 76*4684ddb6SLionel Sambuc terminate_handler 77*4684ddb6SLionel Sambuc get_terminate() _NOEXCEPT 78*4684ddb6SLionel Sambuc { 79*4684ddb6SLionel Sambuc return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 80*4684ddb6SLionel Sambuc } 81*4684ddb6SLionel Sambuc 82*4684ddb6SLionel Sambuc #ifndef __EMSCRIPTEN__ // We provide this in JS 83*4684ddb6SLionel Sambuc _LIBCPP_NORETURN 84*4684ddb6SLionel Sambuc void 85*4684ddb6SLionel Sambuc terminate() _NOEXCEPT 86*4684ddb6SLionel Sambuc { 87*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 88*4684ddb6SLionel Sambuc try 89*4684ddb6SLionel Sambuc { 90*4684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS 91*4684ddb6SLionel Sambuc (*get_terminate())(); 92*4684ddb6SLionel Sambuc // handler should not return 93*4684ddb6SLionel Sambuc printf("terminate_handler unexpectedly returned\n"); 94*4684ddb6SLionel Sambuc ::abort(); 95*4684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS 96*4684ddb6SLionel Sambuc } 97*4684ddb6SLionel Sambuc catch (...) 98*4684ddb6SLionel Sambuc { 99*4684ddb6SLionel Sambuc // handler should not throw exception 100*4684ddb6SLionel Sambuc printf("terminate_handler unexpectedly threw an exception\n"); 101*4684ddb6SLionel Sambuc ::abort(); 102*4684ddb6SLionel Sambuc } 103*4684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS 104*4684ddb6SLionel Sambuc } 105*4684ddb6SLionel Sambuc #endif // !__EMSCRIPTEN__ 106*4684ddb6SLionel Sambuc #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 107*4684ddb6SLionel Sambuc 108*4684ddb6SLionel Sambuc #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__) 109*4684ddb6SLionel Sambuc bool uncaught_exception() _NOEXCEPT 110*4684ddb6SLionel Sambuc { 111*4684ddb6SLionel Sambuc #if defined(__APPLE__) || defined(_LIBCPPABI_VERSION) 112*4684ddb6SLionel Sambuc // on Darwin, there is a helper function so __cxa_get_globals is private 113*4684ddb6SLionel Sambuc return __cxa_uncaught_exception(); 114*4684ddb6SLionel Sambuc #else // __APPLE__ 115*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 116*4684ddb6SLionel Sambuc _LIBCPP_WARNING("uncaught_exception not yet implemented") 117*4684ddb6SLionel Sambuc # else 118*4684ddb6SLionel Sambuc # warning uncaught_exception not yet implemented 119*4684ddb6SLionel Sambuc # endif 120*4684ddb6SLionel Sambuc printf("uncaught_exception not yet implemented\n"); 121*4684ddb6SLionel Sambuc ::abort(); 122*4684ddb6SLionel Sambuc #endif // __APPLE__ 123*4684ddb6SLionel Sambuc } 124*4684ddb6SLionel Sambuc 125*4684ddb6SLionel Sambuc 126*4684ddb6SLionel Sambuc #ifndef _LIBCPPABI_VERSION 127*4684ddb6SLionel Sambuc 128*4684ddb6SLionel Sambuc exception::~exception() _NOEXCEPT 129*4684ddb6SLionel Sambuc { 130*4684ddb6SLionel Sambuc } 131*4684ddb6SLionel Sambuc 132*4684ddb6SLionel Sambuc const char* exception::what() const _NOEXCEPT 133*4684ddb6SLionel Sambuc { 134*4684ddb6SLionel Sambuc return "std::exception"; 135*4684ddb6SLionel Sambuc } 136*4684ddb6SLionel Sambuc 137*4684ddb6SLionel Sambuc #endif // _LIBCPPABI_VERSION 138*4684ddb6SLionel Sambuc #endif //LIBCXXRT 139*4684ddb6SLionel Sambuc #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 140*4684ddb6SLionel Sambuc 141*4684ddb6SLionel Sambuc bad_exception::~bad_exception() _NOEXCEPT 142*4684ddb6SLionel Sambuc { 143*4684ddb6SLionel Sambuc } 144*4684ddb6SLionel Sambuc 145*4684ddb6SLionel Sambuc const char* bad_exception::what() const _NOEXCEPT 146*4684ddb6SLionel Sambuc { 147*4684ddb6SLionel Sambuc return "std::bad_exception"; 148*4684ddb6SLionel Sambuc } 149*4684ddb6SLionel Sambuc 150*4684ddb6SLionel Sambuc #endif 151*4684ddb6SLionel Sambuc 152*4684ddb6SLionel Sambuc #if defined(__GLIBCXX__) 153*4684ddb6SLionel Sambuc 154*4684ddb6SLionel Sambuc // libsupc++ does not implement the dependent EH ABI and the functionality 155*4684ddb6SLionel Sambuc // it uses to implement std::exception_ptr (which it declares as an alias of 156*4684ddb6SLionel Sambuc // std::__exception_ptr::exception_ptr) is not directly exported to clients. So 157*4684ddb6SLionel Sambuc // we have little choice but to hijack std::__exception_ptr::exception_ptr's 158*4684ddb6SLionel Sambuc // (which fortunately has the same layout as our std::exception_ptr) copy 159*4684ddb6SLionel Sambuc // constructor, assignment operator and destructor (which are part of its 160*4684ddb6SLionel Sambuc // stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) 161*4684ddb6SLionel Sambuc // function. 162*4684ddb6SLionel Sambuc 163*4684ddb6SLionel Sambuc namespace __exception_ptr 164*4684ddb6SLionel Sambuc { 165*4684ddb6SLionel Sambuc 166*4684ddb6SLionel Sambuc struct exception_ptr 167*4684ddb6SLionel Sambuc { 168*4684ddb6SLionel Sambuc void* __ptr_; 169*4684ddb6SLionel Sambuc 170*4684ddb6SLionel Sambuc exception_ptr(const exception_ptr&) _NOEXCEPT; 171*4684ddb6SLionel Sambuc exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 172*4684ddb6SLionel Sambuc ~exception_ptr() _NOEXCEPT; 173*4684ddb6SLionel Sambuc }; 174*4684ddb6SLionel Sambuc 175*4684ddb6SLionel Sambuc } 176*4684ddb6SLionel Sambuc 177*4684ddb6SLionel Sambuc _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); 178*4684ddb6SLionel Sambuc 179*4684ddb6SLionel Sambuc #endif 180*4684ddb6SLionel Sambuc 181*4684ddb6SLionel Sambuc exception_ptr::~exception_ptr() _NOEXCEPT 182*4684ddb6SLionel Sambuc { 183*4684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI 184*4684ddb6SLionel Sambuc __cxa_decrement_exception_refcount(__ptr_); 185*4684ddb6SLionel Sambuc #elif defined(__GLIBCXX__) 186*4684ddb6SLionel Sambuc reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); 187*4684ddb6SLionel Sambuc #else 188*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 189*4684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented") 190*4684ddb6SLionel Sambuc # else 191*4684ddb6SLionel Sambuc # warning exception_ptr not yet implemented 192*4684ddb6SLionel Sambuc # endif 193*4684ddb6SLionel Sambuc printf("exception_ptr not yet implemented\n"); 194*4684ddb6SLionel Sambuc ::abort(); 195*4684ddb6SLionel Sambuc #endif 196*4684ddb6SLionel Sambuc } 197*4684ddb6SLionel Sambuc 198*4684ddb6SLionel Sambuc exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 199*4684ddb6SLionel Sambuc : __ptr_(other.__ptr_) 200*4684ddb6SLionel Sambuc { 201*4684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI 202*4684ddb6SLionel Sambuc __cxa_increment_exception_refcount(__ptr_); 203*4684ddb6SLionel Sambuc #elif defined(__GLIBCXX__) 204*4684ddb6SLionel Sambuc new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( 205*4684ddb6SLionel Sambuc reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); 206*4684ddb6SLionel Sambuc #else 207*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 208*4684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented") 209*4684ddb6SLionel Sambuc # else 210*4684ddb6SLionel Sambuc # warning exception_ptr not yet implemented 211*4684ddb6SLionel Sambuc # endif 212*4684ddb6SLionel Sambuc printf("exception_ptr not yet implemented\n"); 213*4684ddb6SLionel Sambuc ::abort(); 214*4684ddb6SLionel Sambuc #endif 215*4684ddb6SLionel Sambuc } 216*4684ddb6SLionel Sambuc 217*4684ddb6SLionel Sambuc exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 218*4684ddb6SLionel Sambuc { 219*4684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI 220*4684ddb6SLionel Sambuc if (__ptr_ != other.__ptr_) 221*4684ddb6SLionel Sambuc { 222*4684ddb6SLionel Sambuc __cxa_increment_exception_refcount(other.__ptr_); 223*4684ddb6SLionel Sambuc __cxa_decrement_exception_refcount(__ptr_); 224*4684ddb6SLionel Sambuc __ptr_ = other.__ptr_; 225*4684ddb6SLionel Sambuc } 226*4684ddb6SLionel Sambuc return *this; 227*4684ddb6SLionel Sambuc #elif defined(__GLIBCXX__) 228*4684ddb6SLionel Sambuc *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = 229*4684ddb6SLionel Sambuc reinterpret_cast<const __exception_ptr::exception_ptr&>(other); 230*4684ddb6SLionel Sambuc return *this; 231*4684ddb6SLionel Sambuc #else 232*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 233*4684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented") 234*4684ddb6SLionel Sambuc # else 235*4684ddb6SLionel Sambuc # warning exception_ptr not yet implemented 236*4684ddb6SLionel Sambuc # endif 237*4684ddb6SLionel Sambuc printf("exception_ptr not yet implemented\n"); 238*4684ddb6SLionel Sambuc ::abort(); 239*4684ddb6SLionel Sambuc #endif 240*4684ddb6SLionel Sambuc } 241*4684ddb6SLionel Sambuc 242*4684ddb6SLionel Sambuc nested_exception::nested_exception() _NOEXCEPT 243*4684ddb6SLionel Sambuc : __ptr_(current_exception()) 244*4684ddb6SLionel Sambuc { 245*4684ddb6SLionel Sambuc } 246*4684ddb6SLionel Sambuc 247*4684ddb6SLionel Sambuc #if !defined(__GLIBCXX__) 248*4684ddb6SLionel Sambuc 249*4684ddb6SLionel Sambuc nested_exception::~nested_exception() _NOEXCEPT 250*4684ddb6SLionel Sambuc { 251*4684ddb6SLionel Sambuc } 252*4684ddb6SLionel Sambuc 253*4684ddb6SLionel Sambuc #endif 254*4684ddb6SLionel Sambuc 255*4684ddb6SLionel Sambuc _LIBCPP_NORETURN 256*4684ddb6SLionel Sambuc void 257*4684ddb6SLionel Sambuc nested_exception::rethrow_nested() const 258*4684ddb6SLionel Sambuc { 259*4684ddb6SLionel Sambuc if (__ptr_ == nullptr) 260*4684ddb6SLionel Sambuc terminate(); 261*4684ddb6SLionel Sambuc rethrow_exception(__ptr_); 262*4684ddb6SLionel Sambuc } 263*4684ddb6SLionel Sambuc 264*4684ddb6SLionel Sambuc #if !defined(__GLIBCXX__) 265*4684ddb6SLionel Sambuc 266*4684ddb6SLionel Sambuc exception_ptr current_exception() _NOEXCEPT 267*4684ddb6SLionel Sambuc { 268*4684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI 269*4684ddb6SLionel Sambuc // be nicer if there was a constructor that took a ptr, then 270*4684ddb6SLionel Sambuc // this whole function would be just: 271*4684ddb6SLionel Sambuc // return exception_ptr(__cxa_current_primary_exception()); 272*4684ddb6SLionel Sambuc exception_ptr ptr; 273*4684ddb6SLionel Sambuc ptr.__ptr_ = __cxa_current_primary_exception(); 274*4684ddb6SLionel Sambuc return ptr; 275*4684ddb6SLionel Sambuc #else 276*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 277*4684ddb6SLionel Sambuc _LIBCPP_WARNING( "exception_ptr not yet implemented" ) 278*4684ddb6SLionel Sambuc # else 279*4684ddb6SLionel Sambuc # warning exception_ptr not yet implemented 280*4684ddb6SLionel Sambuc # endif 281*4684ddb6SLionel Sambuc printf("exception_ptr not yet implemented\n"); 282*4684ddb6SLionel Sambuc ::abort(); 283*4684ddb6SLionel Sambuc #endif 284*4684ddb6SLionel Sambuc } 285*4684ddb6SLionel Sambuc 286*4684ddb6SLionel Sambuc #endif // !__GLIBCXX__ 287*4684ddb6SLionel Sambuc 288*4684ddb6SLionel Sambuc _LIBCPP_NORETURN 289*4684ddb6SLionel Sambuc void rethrow_exception(exception_ptr p) 290*4684ddb6SLionel Sambuc { 291*4684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI 292*4684ddb6SLionel Sambuc __cxa_rethrow_primary_exception(p.__ptr_); 293*4684ddb6SLionel Sambuc // if p.__ptr_ is NULL, above returns so we terminate 294*4684ddb6SLionel Sambuc terminate(); 295*4684ddb6SLionel Sambuc #elif defined(__GLIBCXX__) 296*4684ddb6SLionel Sambuc rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); 297*4684ddb6SLionel Sambuc #else 298*4684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__) 299*4684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented") 300*4684ddb6SLionel Sambuc # else 301*4684ddb6SLionel Sambuc # warning exception_ptr not yet implemented 302*4684ddb6SLionel Sambuc # endif 303*4684ddb6SLionel Sambuc printf("exception_ptr not yet implemented\n"); 304*4684ddb6SLionel Sambuc ::abort(); 305*4684ddb6SLionel Sambuc #endif 306*4684ddb6SLionel Sambuc } 307*4684ddb6SLionel Sambuc } // std 308