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