1227825Stheraven//===------------------------ exception.cpp -------------------------------===// 2227825Stheraven// 3227825Stheraven// The LLVM Compiler Infrastructure 4227825Stheraven// 5227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open 6227825Stheraven// Source Licenses. See LICENSE.TXT for details. 7227825Stheraven// 8227825Stheraven//===----------------------------------------------------------------------===// 9227825Stheraven#include <stdlib.h> 10227825Stheraven 11227825Stheraven#include "exception" 12227825Stheraven 13241903Sdim#ifndef __has_include 14241903Sdim#define __has_include(inc) 0 15241903Sdim#endif 16241903Sdim 17249998Sdim#ifdef __APPLE__ 18227825Stheraven #include <cxxabi.h> 19232950Stheraven 20227825Stheraven using namespace __cxxabiv1; 21227825Stheraven #define HAVE_DEPENDENT_EH_ABI 1 22232950Stheraven #ifndef _LIBCPPABI_VERSION 23232950Stheraven using namespace __cxxabiapple; 24232950Stheraven // On Darwin, there are two STL shared libraries and a lower level ABI 25232950Stheraven // shared libray. The globals holding the current terminate handler and 26232950Stheraven // current unexpected handler are in the ABI library. 27232950Stheraven #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 28232950Stheraven #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 29232950Stheraven #endif // _LIBCPPABI_VERSION 30241903Sdim#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>) 31227825Stheraven #include <cxxabi.h> 32227825Stheraven using namespace __cxxabiv1; 33241903Sdim #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 34241903Sdim #define HAVE_DEPENDENT_EH_ABI 1 35241903Sdim #endif 36246487Stheraven#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>) 37227825Stheraven static std::terminate_handler __terminate_handler; 38227825Stheraven static std::unexpected_handler __unexpected_handler; 39241903Sdim#endif // __has_include(<cxxabi.h>) 40227825Stheraven 41232950Stheravennamespace std 42232950Stheraven{ 43232950Stheraven 44246487Stheraven#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 45232950Stheraven 46227825Stheraven// libcxxrt provides implementations of these functions itself. 47232950Stheravenunexpected_handler 48232950Stheravenset_unexpected(unexpected_handler func) _NOEXCEPT 49227825Stheraven{ 50227825Stheraven return __sync_lock_test_and_set(&__unexpected_handler, func); 51227825Stheraven} 52227825Stheraven 53232950Stheravenunexpected_handler 54232950Stheravenget_unexpected() _NOEXCEPT 55227825Stheraven{ 56232950Stheraven return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 57227825Stheraven} 58227825Stheraven 59241903Sdim_LIBCPP_NORETURN 60227825Stheravenvoid 61232950Stheravenunexpected() 62227825Stheraven{ 63232950Stheraven (*get_unexpected())(); 64227825Stheraven // unexpected handler should not return 65232950Stheraven terminate(); 66227825Stheraven} 67227825Stheraven 68232950Stheraventerminate_handler 69232950Stheravenset_terminate(terminate_handler func) _NOEXCEPT 70227825Stheraven{ 71227825Stheraven return __sync_lock_test_and_set(&__terminate_handler, func); 72227825Stheraven} 73227825Stheraven 74232950Stheraventerminate_handler 75232950Stheravenget_terminate() _NOEXCEPT 76227825Stheraven{ 77232950Stheraven return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 78227825Stheraven} 79227825Stheraven 80249998Sdim#ifndef EMSCRIPTEN // We provide this in JS 81241903Sdim_LIBCPP_NORETURN 82227825Stheravenvoid 83232950Stheraventerminate() _NOEXCEPT 84227825Stheraven{ 85227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 86227825Stheraven try 87227825Stheraven { 88227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 89232950Stheraven (*get_terminate())(); 90227825Stheraven // handler should not return 91227825Stheraven ::abort (); 92227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS 93227825Stheraven } 94227825Stheraven catch (...) 95227825Stheraven { 96227825Stheraven // handler should not throw exception 97227825Stheraven ::abort (); 98227825Stheraven } 99227825Stheraven#endif // _LIBCPP_NO_EXCEPTIONS 100227825Stheraven} 101249998Sdim#endif // !EMSCRIPTEN 102232950Stheraven#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 103227825Stheraven 104249998Sdim#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN) 105232950Stheravenbool uncaught_exception() _NOEXCEPT 106227825Stheraven{ 107249998Sdim#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION) 108227825Stheraven // on Darwin, there is a helper function so __cxa_get_globals is private 109232950Stheraven return __cxa_uncaught_exception(); 110227825Stheraven#else // __APPLE__ 111227825Stheraven #warning uncaught_exception not yet implemented 112227825Stheraven ::abort(); 113227825Stheraven#endif // __APPLE__ 114227825Stheraven} 115227825Stheraven 116232950Stheraven#ifndef _LIBCPPABI_VERSION 117227825Stheraven 118227825Stheravenexception::~exception() _NOEXCEPT 119227825Stheraven{ 120227825Stheraven} 121227825Stheraven 122232972Stheravenconst char* exception::what() const _NOEXCEPT 123227825Stheraven{ 124232972Stheraven return "std::exception"; 125227825Stheraven} 126227825Stheraven 127232972Stheraven#endif // _LIBCPPABI_VERSION 128232972Stheraven#endif //LIBCXXRT 129246487Stheraven#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 130232972Stheraven 131232972Stheravenbad_exception::~bad_exception() _NOEXCEPT 132227825Stheraven{ 133227825Stheraven} 134227825Stheraven 135227825Stheravenconst char* bad_exception::what() const _NOEXCEPT 136227825Stheraven{ 137227825Stheraven return "std::bad_exception"; 138227825Stheraven} 139227825Stheraven 140232972Stheraven#endif 141232950Stheraven 142232972Stheraven 143227825Stheravenexception_ptr::~exception_ptr() _NOEXCEPT 144227825Stheraven{ 145227825Stheraven#if HAVE_DEPENDENT_EH_ABI 146227825Stheraven __cxa_decrement_exception_refcount(__ptr_); 147227825Stheraven#else 148227825Stheraven #warning exception_ptr not yet implemented 149227825Stheraven ::abort(); 150227825Stheraven#endif // __APPLE__ 151227825Stheraven} 152227825Stheraven 153227825Stheravenexception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 154227825Stheraven : __ptr_(other.__ptr_) 155227825Stheraven{ 156227825Stheraven#if HAVE_DEPENDENT_EH_ABI 157227825Stheraven __cxa_increment_exception_refcount(__ptr_); 158227825Stheraven#else 159227825Stheraven #warning exception_ptr not yet implemented 160227825Stheraven ::abort(); 161227825Stheraven#endif // __APPLE__ 162227825Stheraven} 163227825Stheraven 164227825Stheravenexception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 165227825Stheraven{ 166227825Stheraven#if HAVE_DEPENDENT_EH_ABI 167227825Stheraven if (__ptr_ != other.__ptr_) 168227825Stheraven { 169227825Stheraven __cxa_increment_exception_refcount(other.__ptr_); 170227825Stheraven __cxa_decrement_exception_refcount(__ptr_); 171227825Stheraven __ptr_ = other.__ptr_; 172227825Stheraven } 173227825Stheraven return *this; 174227825Stheraven#else // __APPLE__ 175227825Stheraven #warning exception_ptr not yet implemented 176227825Stheraven ::abort(); 177227825Stheraven#endif // __APPLE__ 178227825Stheraven} 179227825Stheraven 180227825Stheravennested_exception::nested_exception() _NOEXCEPT 181227825Stheraven : __ptr_(current_exception()) 182227825Stheraven{ 183227825Stheraven} 184227825Stheraven 185227825Stheravennested_exception::~nested_exception() _NOEXCEPT 186227825Stheraven{ 187227825Stheraven} 188227825Stheraven 189241903Sdim_LIBCPP_NORETURN 190227825Stheravenvoid 191227825Stheravennested_exception::rethrow_nested() const 192227825Stheraven{ 193227825Stheraven if (__ptr_ == nullptr) 194227825Stheraven terminate(); 195227825Stheraven rethrow_exception(__ptr_); 196227825Stheraven} 197227825Stheraven 198227825Stheraven 199232950Stheravenexception_ptr current_exception() _NOEXCEPT 200227825Stheraven{ 201227825Stheraven#if HAVE_DEPENDENT_EH_ABI 202227825Stheraven // be nicer if there was a constructor that took a ptr, then 203227825Stheraven // this whole function would be just: 204227825Stheraven // return exception_ptr(__cxa_current_primary_exception()); 205232950Stheraven exception_ptr ptr; 206227825Stheraven ptr.__ptr_ = __cxa_current_primary_exception(); 207227825Stheraven return ptr; 208227825Stheraven#else // __APPLE__ 209227825Stheraven #warning exception_ptr not yet implemented 210227825Stheraven ::abort(); 211227825Stheraven#endif // __APPLE__ 212227825Stheraven} 213227825Stheraven 214241903Sdim_LIBCPP_NORETURN 215232950Stheravenvoid rethrow_exception(exception_ptr p) 216227825Stheraven{ 217227825Stheraven#if HAVE_DEPENDENT_EH_ABI 218227825Stheraven __cxa_rethrow_primary_exception(p.__ptr_); 219227825Stheraven // if p.__ptr_ is NULL, above returns so we terminate 220227825Stheraven terminate(); 221227825Stheraven#else // __APPLE__ 222227825Stheraven #warning exception_ptr not yet implemented 223227825Stheraven ::abort(); 224227825Stheraven#endif // __APPLE__ 225227825Stheraven} 226232950Stheraven} // std 227