14684ddb6SLionel Sambuc //===------------------------ exception.cpp -------------------------------===//
24684ddb6SLionel Sambuc //
34684ddb6SLionel Sambuc // The LLVM Compiler Infrastructure
44684ddb6SLionel Sambuc //
54684ddb6SLionel Sambuc // This file is dual licensed under the MIT and the University of Illinois Open
64684ddb6SLionel Sambuc // Source Licenses. See LICENSE.TXT for details.
74684ddb6SLionel Sambuc //
84684ddb6SLionel Sambuc //===----------------------------------------------------------------------===//
94684ddb6SLionel Sambuc #include <stdlib.h>
104684ddb6SLionel Sambuc #include <stdio.h>
114684ddb6SLionel Sambuc
124684ddb6SLionel Sambuc #include "exception"
134684ddb6SLionel Sambuc #include "new"
144684ddb6SLionel Sambuc
154684ddb6SLionel Sambuc #ifndef __has_include
164684ddb6SLionel Sambuc #define __has_include(inc) 0
174684ddb6SLionel Sambuc #endif
184684ddb6SLionel Sambuc
19*0a6a1f1dSLionel Sambuc #if defined(__APPLE__) && !defined(LIBCXXRT)
204684ddb6SLionel Sambuc #include <cxxabi.h>
214684ddb6SLionel Sambuc
224684ddb6SLionel Sambuc using namespace __cxxabiv1;
234684ddb6SLionel Sambuc #define HAVE_DEPENDENT_EH_ABI 1
244684ddb6SLionel Sambuc #ifndef _LIBCPPABI_VERSION
254684ddb6SLionel Sambuc using namespace __cxxabiapple;
264684ddb6SLionel Sambuc // On Darwin, there are two STL shared libraries and a lower level ABI
274684ddb6SLionel Sambuc // shared library. The globals holding the current terminate handler and
284684ddb6SLionel Sambuc // current unexpected handler are in the ABI library.
294684ddb6SLionel Sambuc #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
304684ddb6SLionel Sambuc #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
314684ddb6SLionel Sambuc #endif // _LIBCPPABI_VERSION
32*0a6a1f1dSLionel Sambuc #elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI) || __has_include(<cxxabi.h>)
334684ddb6SLionel Sambuc #include <cxxabi.h>
344684ddb6SLionel Sambuc using namespace __cxxabiv1;
354684ddb6SLionel Sambuc #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
364684ddb6SLionel Sambuc #define HAVE_DEPENDENT_EH_ABI 1
374684ddb6SLionel Sambuc #endif
384684ddb6SLionel Sambuc #elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
394684ddb6SLionel Sambuc static std::terminate_handler __terminate_handler;
404684ddb6SLionel Sambuc static std::unexpected_handler __unexpected_handler;
414684ddb6SLionel Sambuc #endif // __has_include(<cxxabi.h>)
424684ddb6SLionel Sambuc
434684ddb6SLionel Sambuc namespace std
444684ddb6SLionel Sambuc {
454684ddb6SLionel Sambuc
464684ddb6SLionel Sambuc #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
474684ddb6SLionel Sambuc
484684ddb6SLionel Sambuc // libcxxrt provides implementations of these functions itself.
494684ddb6SLionel Sambuc unexpected_handler
set_unexpected(unexpected_handler func)504684ddb6SLionel Sambuc set_unexpected(unexpected_handler func) _NOEXCEPT
514684ddb6SLionel Sambuc {
524684ddb6SLionel Sambuc return __sync_lock_test_and_set(&__unexpected_handler, func);
534684ddb6SLionel Sambuc }
544684ddb6SLionel Sambuc
554684ddb6SLionel Sambuc unexpected_handler
get_unexpected()564684ddb6SLionel Sambuc get_unexpected() _NOEXCEPT
574684ddb6SLionel Sambuc {
584684ddb6SLionel Sambuc return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
594684ddb6SLionel Sambuc }
604684ddb6SLionel Sambuc
614684ddb6SLionel Sambuc _LIBCPP_NORETURN
624684ddb6SLionel Sambuc void
unexpected()634684ddb6SLionel Sambuc unexpected()
644684ddb6SLionel Sambuc {
654684ddb6SLionel Sambuc (*get_unexpected())();
664684ddb6SLionel Sambuc // unexpected handler should not return
674684ddb6SLionel Sambuc terminate();
684684ddb6SLionel Sambuc }
694684ddb6SLionel Sambuc
704684ddb6SLionel Sambuc terminate_handler
set_terminate(terminate_handler func)714684ddb6SLionel Sambuc set_terminate(terminate_handler func) _NOEXCEPT
724684ddb6SLionel Sambuc {
734684ddb6SLionel Sambuc return __sync_lock_test_and_set(&__terminate_handler, func);
744684ddb6SLionel Sambuc }
754684ddb6SLionel Sambuc
764684ddb6SLionel Sambuc terminate_handler
get_terminate()774684ddb6SLionel Sambuc get_terminate() _NOEXCEPT
784684ddb6SLionel Sambuc {
794684ddb6SLionel Sambuc return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
804684ddb6SLionel Sambuc }
814684ddb6SLionel Sambuc
824684ddb6SLionel Sambuc #ifndef __EMSCRIPTEN__ // We provide this in JS
834684ddb6SLionel Sambuc _LIBCPP_NORETURN
844684ddb6SLionel Sambuc void
terminate()854684ddb6SLionel Sambuc terminate() _NOEXCEPT
864684ddb6SLionel Sambuc {
874684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
884684ddb6SLionel Sambuc try
894684ddb6SLionel Sambuc {
904684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS
914684ddb6SLionel Sambuc (*get_terminate())();
924684ddb6SLionel Sambuc // handler should not return
93*0a6a1f1dSLionel Sambuc fprintf(stderr, "terminate_handler unexpectedly returned\n");
944684ddb6SLionel Sambuc ::abort();
954684ddb6SLionel Sambuc #ifndef _LIBCPP_NO_EXCEPTIONS
964684ddb6SLionel Sambuc }
974684ddb6SLionel Sambuc catch (...)
984684ddb6SLionel Sambuc {
994684ddb6SLionel Sambuc // handler should not throw exception
100*0a6a1f1dSLionel Sambuc fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
1014684ddb6SLionel Sambuc ::abort();
1024684ddb6SLionel Sambuc }
1034684ddb6SLionel Sambuc #endif // _LIBCPP_NO_EXCEPTIONS
1044684ddb6SLionel Sambuc }
1054684ddb6SLionel Sambuc #endif // !__EMSCRIPTEN__
1064684ddb6SLionel Sambuc #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
1074684ddb6SLionel Sambuc
1084684ddb6SLionel Sambuc #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
uncaught_exception()109*0a6a1f1dSLionel Sambuc bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
110*0a6a1f1dSLionel Sambuc
uncaught_exceptions()111*0a6a1f1dSLionel Sambuc int uncaught_exceptions() _NOEXCEPT
1124684ddb6SLionel Sambuc {
1134684ddb6SLionel Sambuc #if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
1144684ddb6SLionel Sambuc // on Darwin, there is a helper function so __cxa_get_globals is private
115*0a6a1f1dSLionel Sambuc # if _LIBCPPABI_VERSION > 1101
116*0a6a1f1dSLionel Sambuc return __cxa_uncaught_exceptions();
117*0a6a1f1dSLionel Sambuc # else
118*0a6a1f1dSLionel Sambuc return __cxa_uncaught_exception() ? 1 : 0;
119*0a6a1f1dSLionel Sambuc # endif
1204684ddb6SLionel Sambuc #else // __APPLE__
1214684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
122*0a6a1f1dSLionel Sambuc _LIBCPP_WARNING("uncaught_exceptions not yet implemented")
1234684ddb6SLionel Sambuc # else
1244684ddb6SLionel Sambuc # warning uncaught_exception not yet implemented
1254684ddb6SLionel Sambuc # endif
126*0a6a1f1dSLionel Sambuc fprintf(stderr, "uncaught_exceptions not yet implemented\n");
1274684ddb6SLionel Sambuc ::abort();
1284684ddb6SLionel Sambuc #endif // __APPLE__
1294684ddb6SLionel Sambuc }
1304684ddb6SLionel Sambuc
1314684ddb6SLionel Sambuc
1324684ddb6SLionel Sambuc #ifndef _LIBCPPABI_VERSION
1334684ddb6SLionel Sambuc
~exception()1344684ddb6SLionel Sambuc exception::~exception() _NOEXCEPT
1354684ddb6SLionel Sambuc {
1364684ddb6SLionel Sambuc }
1374684ddb6SLionel Sambuc
what() const1384684ddb6SLionel Sambuc const char* exception::what() const _NOEXCEPT
1394684ddb6SLionel Sambuc {
1404684ddb6SLionel Sambuc return "std::exception";
1414684ddb6SLionel Sambuc }
1424684ddb6SLionel Sambuc
1434684ddb6SLionel Sambuc #endif // _LIBCPPABI_VERSION
1444684ddb6SLionel Sambuc #endif //LIBCXXRT
1454684ddb6SLionel Sambuc #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
1464684ddb6SLionel Sambuc
~bad_exception()1474684ddb6SLionel Sambuc bad_exception::~bad_exception() _NOEXCEPT
1484684ddb6SLionel Sambuc {
1494684ddb6SLionel Sambuc }
1504684ddb6SLionel Sambuc
what() const1514684ddb6SLionel Sambuc const char* bad_exception::what() const _NOEXCEPT
1524684ddb6SLionel Sambuc {
1534684ddb6SLionel Sambuc return "std::bad_exception";
1544684ddb6SLionel Sambuc }
1554684ddb6SLionel Sambuc
1564684ddb6SLionel Sambuc #endif
1574684ddb6SLionel Sambuc
1584684ddb6SLionel Sambuc #if defined(__GLIBCXX__)
1594684ddb6SLionel Sambuc
1604684ddb6SLionel Sambuc // libsupc++ does not implement the dependent EH ABI and the functionality
1614684ddb6SLionel Sambuc // it uses to implement std::exception_ptr (which it declares as an alias of
1624684ddb6SLionel Sambuc // std::__exception_ptr::exception_ptr) is not directly exported to clients. So
1634684ddb6SLionel Sambuc // we have little choice but to hijack std::__exception_ptr::exception_ptr's
1644684ddb6SLionel Sambuc // (which fortunately has the same layout as our std::exception_ptr) copy
1654684ddb6SLionel Sambuc // constructor, assignment operator and destructor (which are part of its
1664684ddb6SLionel Sambuc // stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
1674684ddb6SLionel Sambuc // function.
1684684ddb6SLionel Sambuc
1694684ddb6SLionel Sambuc namespace __exception_ptr
1704684ddb6SLionel Sambuc {
1714684ddb6SLionel Sambuc
1724684ddb6SLionel Sambuc struct exception_ptr
1734684ddb6SLionel Sambuc {
1744684ddb6SLionel Sambuc void* __ptr_;
1754684ddb6SLionel Sambuc
1764684ddb6SLionel Sambuc exception_ptr(const exception_ptr&) _NOEXCEPT;
1774684ddb6SLionel Sambuc exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
1784684ddb6SLionel Sambuc ~exception_ptr() _NOEXCEPT;
1794684ddb6SLionel Sambuc };
1804684ddb6SLionel Sambuc
1814684ddb6SLionel Sambuc }
1824684ddb6SLionel Sambuc
1834684ddb6SLionel Sambuc _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
1844684ddb6SLionel Sambuc
1854684ddb6SLionel Sambuc #endif
1864684ddb6SLionel Sambuc
~exception_ptr()1874684ddb6SLionel Sambuc exception_ptr::~exception_ptr() _NOEXCEPT
1884684ddb6SLionel Sambuc {
1894684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI
1904684ddb6SLionel Sambuc __cxa_decrement_exception_refcount(__ptr_);
1914684ddb6SLionel Sambuc #elif defined(__GLIBCXX__)
1924684ddb6SLionel Sambuc reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
1934684ddb6SLionel Sambuc #else
1944684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
1954684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented")
1964684ddb6SLionel Sambuc # else
1974684ddb6SLionel Sambuc # warning exception_ptr not yet implemented
1984684ddb6SLionel Sambuc # endif
199*0a6a1f1dSLionel Sambuc fprintf(stderr, "exception_ptr not yet implemented\n");
2004684ddb6SLionel Sambuc ::abort();
2014684ddb6SLionel Sambuc #endif
2024684ddb6SLionel Sambuc }
2034684ddb6SLionel Sambuc
exception_ptr(const exception_ptr & other)2044684ddb6SLionel Sambuc exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
2054684ddb6SLionel Sambuc : __ptr_(other.__ptr_)
2064684ddb6SLionel Sambuc {
2074684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI
2084684ddb6SLionel Sambuc __cxa_increment_exception_refcount(__ptr_);
2094684ddb6SLionel Sambuc #elif defined(__GLIBCXX__)
2104684ddb6SLionel Sambuc new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
2114684ddb6SLionel Sambuc reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
2124684ddb6SLionel Sambuc #else
2134684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
2144684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented")
2154684ddb6SLionel Sambuc # else
2164684ddb6SLionel Sambuc # warning exception_ptr not yet implemented
2174684ddb6SLionel Sambuc # endif
218*0a6a1f1dSLionel Sambuc fprintf(stderr, "exception_ptr not yet implemented\n");
2194684ddb6SLionel Sambuc ::abort();
2204684ddb6SLionel Sambuc #endif
2214684ddb6SLionel Sambuc }
2224684ddb6SLionel Sambuc
operator =(const exception_ptr & other)2234684ddb6SLionel Sambuc exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
2244684ddb6SLionel Sambuc {
2254684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI
2264684ddb6SLionel Sambuc if (__ptr_ != other.__ptr_)
2274684ddb6SLionel Sambuc {
2284684ddb6SLionel Sambuc __cxa_increment_exception_refcount(other.__ptr_);
2294684ddb6SLionel Sambuc __cxa_decrement_exception_refcount(__ptr_);
2304684ddb6SLionel Sambuc __ptr_ = other.__ptr_;
2314684ddb6SLionel Sambuc }
2324684ddb6SLionel Sambuc return *this;
2334684ddb6SLionel Sambuc #elif defined(__GLIBCXX__)
2344684ddb6SLionel Sambuc *reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
2354684ddb6SLionel Sambuc reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
2364684ddb6SLionel Sambuc return *this;
2374684ddb6SLionel Sambuc #else
2384684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
2394684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented")
2404684ddb6SLionel Sambuc # else
2414684ddb6SLionel Sambuc # warning exception_ptr not yet implemented
2424684ddb6SLionel Sambuc # endif
243*0a6a1f1dSLionel Sambuc fprintf(stderr, "exception_ptr not yet implemented\n");
2444684ddb6SLionel Sambuc ::abort();
2454684ddb6SLionel Sambuc #endif
2464684ddb6SLionel Sambuc }
2474684ddb6SLionel Sambuc
nested_exception()2484684ddb6SLionel Sambuc nested_exception::nested_exception() _NOEXCEPT
2494684ddb6SLionel Sambuc : __ptr_(current_exception())
2504684ddb6SLionel Sambuc {
2514684ddb6SLionel Sambuc }
2524684ddb6SLionel Sambuc
2534684ddb6SLionel Sambuc #if !defined(__GLIBCXX__)
2544684ddb6SLionel Sambuc
~nested_exception()2554684ddb6SLionel Sambuc nested_exception::~nested_exception() _NOEXCEPT
2564684ddb6SLionel Sambuc {
2574684ddb6SLionel Sambuc }
2584684ddb6SLionel Sambuc
2594684ddb6SLionel Sambuc #endif
2604684ddb6SLionel Sambuc
2614684ddb6SLionel Sambuc _LIBCPP_NORETURN
2624684ddb6SLionel Sambuc void
rethrow_nested() const2634684ddb6SLionel Sambuc nested_exception::rethrow_nested() const
2644684ddb6SLionel Sambuc {
2654684ddb6SLionel Sambuc if (__ptr_ == nullptr)
2664684ddb6SLionel Sambuc terminate();
2674684ddb6SLionel Sambuc rethrow_exception(__ptr_);
2684684ddb6SLionel Sambuc }
2694684ddb6SLionel Sambuc
2704684ddb6SLionel Sambuc #if !defined(__GLIBCXX__)
2714684ddb6SLionel Sambuc
current_exception()2724684ddb6SLionel Sambuc exception_ptr current_exception() _NOEXCEPT
2734684ddb6SLionel Sambuc {
2744684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI
2754684ddb6SLionel Sambuc // be nicer if there was a constructor that took a ptr, then
2764684ddb6SLionel Sambuc // this whole function would be just:
2774684ddb6SLionel Sambuc // return exception_ptr(__cxa_current_primary_exception());
2784684ddb6SLionel Sambuc exception_ptr ptr;
2794684ddb6SLionel Sambuc ptr.__ptr_ = __cxa_current_primary_exception();
2804684ddb6SLionel Sambuc return ptr;
2814684ddb6SLionel Sambuc #else
2824684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
2834684ddb6SLionel Sambuc _LIBCPP_WARNING( "exception_ptr not yet implemented" )
2844684ddb6SLionel Sambuc # else
2854684ddb6SLionel Sambuc # warning exception_ptr not yet implemented
2864684ddb6SLionel Sambuc # endif
287*0a6a1f1dSLionel Sambuc fprintf(stderr, "exception_ptr not yet implemented\n");
2884684ddb6SLionel Sambuc ::abort();
2894684ddb6SLionel Sambuc #endif
2904684ddb6SLionel Sambuc }
2914684ddb6SLionel Sambuc
2924684ddb6SLionel Sambuc #endif // !__GLIBCXX__
2934684ddb6SLionel Sambuc
2944684ddb6SLionel Sambuc _LIBCPP_NORETURN
rethrow_exception(exception_ptr p)2954684ddb6SLionel Sambuc void rethrow_exception(exception_ptr p)
2964684ddb6SLionel Sambuc {
2974684ddb6SLionel Sambuc #if HAVE_DEPENDENT_EH_ABI
2984684ddb6SLionel Sambuc __cxa_rethrow_primary_exception(p.__ptr_);
2994684ddb6SLionel Sambuc // if p.__ptr_ is NULL, above returns so we terminate
3004684ddb6SLionel Sambuc terminate();
3014684ddb6SLionel Sambuc #elif defined(__GLIBCXX__)
3024684ddb6SLionel Sambuc rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
3034684ddb6SLionel Sambuc #else
3044684ddb6SLionel Sambuc # if defined(_MSC_VER) && ! defined(__clang__)
3054684ddb6SLionel Sambuc _LIBCPP_WARNING("exception_ptr not yet implemented")
3064684ddb6SLionel Sambuc # else
3074684ddb6SLionel Sambuc # warning exception_ptr not yet implemented
3084684ddb6SLionel Sambuc # endif
309*0a6a1f1dSLionel Sambuc fprintf(stderr, "exception_ptr not yet implemented\n");
3104684ddb6SLionel Sambuc ::abort();
3114684ddb6SLionel Sambuc #endif
3124684ddb6SLionel Sambuc }
3134684ddb6SLionel Sambuc } // std
314