exception.cpp revision 288943
1161475Sdelphij//===------------------------ exception.cpp -------------------------------===// 260786Sps// 360786Sps// The LLVM Compiler Infrastructure 460786Sps// 5170256Sdelphij// This file is dual licensed under the MIT and the University of Illinois Open 660786Sps// Source Licenses. See LICENSE.TXT for details. 760786Sps// 8170256Sdelphij//===----------------------------------------------------------------------===// 9170256Sdelphij#include <stdlib.h> 10170256Sdelphij#include <stdio.h> 11170256Sdelphij 12170256Sdelphij#include "exception" 13170256Sdelphij#include "new" 14170256Sdelphij 15170256Sdelphij#ifndef __has_include 16170256Sdelphij#define __has_include(inc) 0 17170256Sdelphij#endif 18161475Sdelphij 19161475Sdelphij#if defined(__APPLE__) && !defined(LIBCXXRT) 2060786Sps #include <cxxabi.h> 2160786Sps 22170256Sdelphij using namespace __cxxabiv1; 23170256Sdelphij #define HAVE_DEPENDENT_EH_ABI 1 24170256Sdelphij #ifndef _LIBCPPABI_VERSION 25161475Sdelphij using namespace __cxxabiapple; 26170256Sdelphij // On Darwin, there are two STL shared libraries and a lower level ABI 27161475Sdelphij // shared library. The globals holding the current terminate handler and 28161475Sdelphij // current unexpected handler are in the ABI library. 29161475Sdelphij #define __terminate_handler __cxxabiapple::__cxa_terminate_handler 30161475Sdelphij #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler 3160786Sps #endif // _LIBCPPABI_VERSION 32170256Sdelphij#elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) || __has_include(<cxxabi.h>) 33161475Sdelphij #include <cxxabi.h> 34161475Sdelphij using namespace __cxxabiv1; 3560786Sps #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION) 3660786Sps #define HAVE_DEPENDENT_EH_ABI 1 37170256Sdelphij #endif 38161475Sdelphij#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>) 39161475Sdelphij static std::terminate_handler __terminate_handler; 40161475Sdelphij static std::unexpected_handler __unexpected_handler; 4160786Sps#endif // __has_include(<cxxabi.h>) 42161475Sdelphij 43161475Sdelphijnamespace std 4460786Sps{ 4560786Sps 46161475Sdelphij#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 47161475Sdelphij 48161475Sdelphij// libcxxrt provides implementations of these functions itself. 49161475Sdelphijunexpected_handler 5060786Spsset_unexpected(unexpected_handler func) _NOEXCEPT 51161475Sdelphij{ 52161475Sdelphij return __sync_lock_test_and_set(&__unexpected_handler, func); 5360786Sps} 5460786Sps 55161475Sdelphijunexpected_handler 56161475Sdelphijget_unexpected() _NOEXCEPT 5760786Sps{ 5860786Sps return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0); 59161475Sdelphij} 60161475Sdelphij 6160786Sps_LIBCPP_NORETURN 6260786Spsvoid 63161475Sdelphijunexpected() 64161475Sdelphij{ 65161475Sdelphij (*get_unexpected())(); 6660786Sps // unexpected handler should not return 6760786Sps terminate(); 68161475Sdelphij} 69161475Sdelphij 70161475Sdelphijterminate_handler 7160786Spsset_terminate(terminate_handler func) _NOEXCEPT 72161475Sdelphij{ 73161475Sdelphij return __sync_lock_test_and_set(&__terminate_handler, func); 7460786Sps} 7560786Sps 76161475Sdelphijterminate_handler 77161475Sdelphijget_terminate() _NOEXCEPT 78161475Sdelphij{ 7960786Sps return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0); 8060786Sps} 81161475Sdelphij 82161475Sdelphij#ifndef __EMSCRIPTEN__ // We provide this in JS 83161475Sdelphij_LIBCPP_NORETURN 8460786Spsvoid 8560786Spsterminate() _NOEXCEPT 86161475Sdelphij{ 87161475Sdelphij#ifndef _LIBCPP_NO_EXCEPTIONS 88161475Sdelphij try 89161475Sdelphij { 9089019Sps#endif // _LIBCPP_NO_EXCEPTIONS 9160786Sps (*get_terminate())(); 9260786Sps // handler should not return 93161475Sdelphij fprintf(stderr, "terminate_handler unexpectedly returned\n"); 94161475Sdelphij ::abort(); 95161475Sdelphij#ifndef _LIBCPP_NO_EXCEPTIONS 96161475Sdelphij } 9760786Sps catch (...) 9860786Sps { 9960786Sps // handler should not throw exception 10060786Sps fprintf(stderr, "terminate_handler unexpectedly threw an exception\n"); 101161475Sdelphij ::abort(); 102161475Sdelphij } 10360786Sps#endif // _LIBCPP_NO_EXCEPTIONS 104161475Sdelphij} 105161475Sdelphij#endif // !__EMSCRIPTEN__ 106161475Sdelphij#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) 107161475Sdelphij 10860786Sps#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__) 10960786Spsbool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; } 11060786Sps 111161475Sdelphijint uncaught_exceptions() _NOEXCEPT 112161475Sdelphij{ 11360786Sps#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION) 11460786Sps // on Darwin, there is a helper function so __cxa_get_globals is private 115161475Sdelphij# if _LIBCPPABI_VERSION > 1101 116161475Sdelphij return __cxa_uncaught_exceptions(); 117161475Sdelphij# else 11860786Sps return __cxa_uncaught_exception() ? 1 : 0; 119161475Sdelphij# endif 120170256Sdelphij#else // __APPLE__ 12160786Sps# if defined(_MSC_VER) && ! defined(__clang__) 122170256Sdelphij _LIBCPP_WARNING("uncaught_exceptions not yet implemented") 123170256Sdelphij# else 124161475Sdelphij# warning uncaught_exception not yet implemented 125161475Sdelphij# endif 126161475Sdelphij fprintf(stderr, "uncaught_exceptions not yet implemented\n"); 127161475Sdelphij ::abort(); 128161475Sdelphij#endif // __APPLE__ 129161475Sdelphij} 13060786Sps 131161475Sdelphij 132161475Sdelphij#ifndef _LIBCPPABI_VERSION 133161475Sdelphij 134161475Sdelphijexception::~exception() _NOEXCEPT 135161475Sdelphij{ 136161475Sdelphij} 13760786Sps 138161475Sdelphijconst char* exception::what() const _NOEXCEPT 13960786Sps{ 140161475Sdelphij return "std::exception"; 14160786Sps} 142161475Sdelphij 143161475Sdelphij#endif // _LIBCPPABI_VERSION 14460786Sps#endif //LIBCXXRT 145161475Sdelphij#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__) 146161475Sdelphij 14760786Spsbad_exception::~bad_exception() _NOEXCEPT 148161475Sdelphij{ 149161475Sdelphij} 150161475Sdelphij 151161475Sdelphijconst char* bad_exception::what() const _NOEXCEPT 15260786Sps{ 153161475Sdelphij return "std::bad_exception"; 154161475Sdelphij} 155161475Sdelphij 156161475Sdelphij#endif 15760786Sps 158161475Sdelphij#if defined(__GLIBCXX__) 159161475Sdelphij 16060786Sps// libsupc++ does not implement the dependent EH ABI and the functionality 161161475Sdelphij// it uses to implement std::exception_ptr (which it declares as an alias of 162161475Sdelphij// std::__exception_ptr::exception_ptr) is not directly exported to clients. So 163161475Sdelphij// we have little choice but to hijack std::__exception_ptr::exception_ptr's 164161475Sdelphij// (which fortunately has the same layout as our std::exception_ptr) copy 165161475Sdelphij// constructor, assignment operator and destructor (which are part of its 166161475Sdelphij// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr) 167161475Sdelphij// function. 16860786Sps 16960786Spsnamespace __exception_ptr 17060786Sps{ 17160786Sps 172161475Sdelphijstruct exception_ptr 173161475Sdelphij{ 174161475Sdelphij void* __ptr_; 175161475Sdelphij 17660786Sps exception_ptr(const exception_ptr&) _NOEXCEPT; 17760786Sps exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; 178161475Sdelphij ~exception_ptr() _NOEXCEPT; 179161475Sdelphij}; 180161475Sdelphij 18160786Sps} 18260786Sps 183161475Sdelphij_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr); 18460786Sps 18560786Sps#endif 186161475Sdelphij 187161475Sdelphijexception_ptr::~exception_ptr() _NOEXCEPT 188161475Sdelphij{ 18960786Sps#if HAVE_DEPENDENT_EH_ABI 19060786Sps __cxa_decrement_exception_refcount(__ptr_); 19160786Sps#elif defined(__GLIBCXX__) 192161475Sdelphij reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); 193161475Sdelphij#else 194161475Sdelphij# if defined(_MSC_VER) && ! defined(__clang__) 19560786Sps _LIBCPP_WARNING("exception_ptr not yet implemented") 19660786Sps# else 197161475Sdelphij# warning exception_ptr not yet implemented 198191930Sdelphij# endif 199191930Sdelphij fprintf(stderr, "exception_ptr not yet implemented\n"); 20060786Sps ::abort(); 201161475Sdelphij#endif 202161475Sdelphij} 20360786Sps 20463128Spsexception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT 205161475Sdelphij : __ptr_(other.__ptr_) 206161475Sdelphij{ 207161475Sdelphij#if HAVE_DEPENDENT_EH_ABI 20863128Sps __cxa_increment_exception_refcount(__ptr_); 20960786Sps#elif defined(__GLIBCXX__) 21060786Sps new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr( 21160786Sps reinterpret_cast<const __exception_ptr::exception_ptr&>(other)); 212161475Sdelphij#else 21360786Sps# if defined(_MSC_VER) && ! defined(__clang__) 21460786Sps _LIBCPP_WARNING("exception_ptr not yet implemented") 215161475Sdelphij# else 216161475Sdelphij# warning exception_ptr not yet implemented 217161475Sdelphij# endif 218161475Sdelphij fprintf(stderr, "exception_ptr not yet implemented\n"); 21960786Sps ::abort(); 22060786Sps#endif 221161475Sdelphij} 222161475Sdelphij 223161475Sdelphijexception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT 22460786Sps{ 22560786Sps#if HAVE_DEPENDENT_EH_ABI 22660786Sps if (__ptr_ != other.__ptr_) 22760786Sps { 22860786Sps __cxa_increment_exception_refcount(other.__ptr_); 22960786Sps __cxa_decrement_exception_refcount(__ptr_); 23060786Sps __ptr_ = other.__ptr_; 23160786Sps } 23260786Sps return *this; 23360786Sps#elif defined(__GLIBCXX__) 23460786Sps *reinterpret_cast<__exception_ptr::exception_ptr*>(this) = 23560786Sps reinterpret_cast<const __exception_ptr::exception_ptr&>(other); 236161475Sdelphij return *this; 237161475Sdelphij#else 238161475Sdelphij# if defined(_MSC_VER) && ! defined(__clang__) 239161475Sdelphij _LIBCPP_WARNING("exception_ptr not yet implemented") 240161475Sdelphij# else 241161475Sdelphij# warning exception_ptr not yet implemented 242161475Sdelphij# endif 243161475Sdelphij fprintf(stderr, "exception_ptr not yet implemented\n"); 24460786Sps ::abort(); 245161475Sdelphij#endif 24660786Sps} 247161475Sdelphij 248161475Sdelphijnested_exception::nested_exception() _NOEXCEPT 24960786Sps : __ptr_(current_exception()) 250161475Sdelphij{ 251161475Sdelphij} 25260786Sps 253161475Sdelphij#if !defined(__GLIBCXX__) 254161475Sdelphij 255161475Sdelphijnested_exception::~nested_exception() _NOEXCEPT 256161475Sdelphij{ 257161475Sdelphij} 258161475Sdelphij 25960786Sps#endif 260191930Sdelphij 261191930Sdelphij_LIBCPP_NORETURN 262191930Sdelphijvoid 263191930Sdelphijnested_exception::rethrow_nested() const 264191930Sdelphij{ 265191930Sdelphij if (__ptr_ == nullptr) 266191930Sdelphij terminate(); 267191930Sdelphij rethrow_exception(__ptr_); 268191930Sdelphij} 269191930Sdelphij 270191930Sdelphij#if !defined(__GLIBCXX__) 271191930Sdelphij 272191930Sdelphijexception_ptr current_exception() _NOEXCEPT 273191930Sdelphij{ 274191930Sdelphij#if HAVE_DEPENDENT_EH_ABI 275191930Sdelphij // be nicer if there was a constructor that took a ptr, then 27660786Sps // this whole function would be just: 277191930Sdelphij // return exception_ptr(__cxa_current_primary_exception()); 278191930Sdelphij exception_ptr ptr; 279191930Sdelphij ptr.__ptr_ = __cxa_current_primary_exception(); 280191930Sdelphij return ptr; 281191930Sdelphij#else 282191930Sdelphij# if defined(_MSC_VER) && ! defined(__clang__) 283161475Sdelphij _LIBCPP_WARNING( "exception_ptr not yet implemented" ) 284191930Sdelphij# else 285191930Sdelphij# warning exception_ptr not yet implemented 286191930Sdelphij# endif 287191930Sdelphij fprintf(stderr, "exception_ptr not yet implemented\n"); 288161475Sdelphij ::abort(); 289191930Sdelphij#endif 290161475Sdelphij} 291161475Sdelphij 29260786Sps#endif // !__GLIBCXX__ 29360786Sps 294191930Sdelphij_LIBCPP_NORETURN 295191930Sdelphijvoid rethrow_exception(exception_ptr p) 296161475Sdelphij{ 29760786Sps#if HAVE_DEPENDENT_EH_ABI 298191930Sdelphij __cxa_rethrow_primary_exception(p.__ptr_); 299191930Sdelphij // if p.__ptr_ is NULL, above returns so we terminate 300161475Sdelphij terminate(); 30160786Sps#elif defined(__GLIBCXX__) 302161475Sdelphij rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p)); 303161475Sdelphij#else 30460786Sps# if defined(_MSC_VER) && ! defined(__clang__) 305191930Sdelphij _LIBCPP_WARNING("exception_ptr not yet implemented") 306161475Sdelphij# else 30760786Sps# warning exception_ptr not yet implemented 30860786Sps# endif 30960786Sps fprintf(stderr, "exception_ptr not yet implemented\n"); 310191930Sdelphij ::abort(); 311161475Sdelphij#endif 31260786Sps} 313191930Sdelphij} // std 314161475Sdelphij