blob: 9a80d3e92ef547b4be57b282d4780180629a444f [file] [log] [blame]
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00001//===------------------------ exception.cpp -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnantee11c312010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00007//
8//===----------------------------------------------------------------------===//
9#include <stdlib.h>
10
11#include "exception"
12
13#if __APPLE__
14 #include <cxxabi.h>
15 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000016 using namespace __cxxabiv1::__cxxabiapple;
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000017 // On Darwin, there are two STL shared libraries and a lower level ABI
18 // shared libray. The globals holding the current terminate handler and
19 // current unexpected handler are in the ABI library.
20 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
21 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
David Chisnall1d581062011-09-21 08:39:44 +000022 #define HAVE_DEPENDENT_EH_ABI 1
23#elif defined(LIBCXXRT)
24 #include <cxxabi.h>
25 using namespace __cxxabiv1;
26 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnantffb308e2010-08-22 00:03:27 +000027#else // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000028 static std::terminate_handler __terminate_handler;
29 static std::unexpected_handler __unexpected_handler;
Howard Hinnantffb308e2010-08-22 00:03:27 +000030#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000031
David Chisnall1d581062011-09-21 08:39:44 +000032#ifndef LIBCXXRT
33// libcxxrt provides implementations of these functions itself.
Howard Hinnantffb308e2010-08-22 00:03:27 +000034std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000035std::set_unexpected(std::unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000036{
Howard Hinnante65e8e32010-12-02 16:45:21 +000037 return __sync_lock_test_and_set(&__unexpected_handler, func);
38}
39
40std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000041std::get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000042{
43 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000044}
45
Howard Hinnant8df96292011-05-26 17:07:32 +000046_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000047void
48std::unexpected()
49{
Howard Hinnante60478c2010-12-06 15:11:48 +000050 (*std::get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000051 // unexpected handler should not return
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000052 std::terminate();
53}
54
Howard Hinnantffb308e2010-08-22 00:03:27 +000055std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000056std::set_terminate(std::terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000057{
Howard Hinnante65e8e32010-12-02 16:45:21 +000058 return __sync_lock_test_and_set(&__terminate_handler, func);
59}
60
61std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000062std::get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000063{
64 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000065}
66
Howard Hinnant986832c2011-07-29 21:35:53 +000067_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000068void
Howard Hinnant8df96292011-05-26 17:07:32 +000069std::terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000070{
Howard Hinnant72f73582010-08-11 17:04:31 +000071#ifndef _LIBCPP_NO_EXCEPTIONS
72 try
73 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000074#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnante60478c2010-12-06 15:11:48 +000075 (*std::get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000076 // handler should not return
77 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000078#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000079 }
Howard Hinnant72f73582010-08-11 17:04:31 +000080 catch (...)
81 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000082 // handler should not throw exception
83 ::abort ();
84 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000085#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000086}
David Chisnall1d581062011-09-21 08:39:44 +000087#endif // LIBCXXRT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000088
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000089bool std::uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000090{
91#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +000092 // on Darwin, there is a helper function so __cxa_get_globals is private
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000093 return __cxxabiapple::__cxa_uncaught_exception();
David Chisnall1d581062011-09-21 08:39:44 +000094#elif LIBCXXRT
95 __cxa_eh_globals * globals = __cxa_get_globals();
96 return (globals->uncaughtExceptions != 0);
Howard Hinnantffb308e2010-08-22 00:03:27 +000097#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +000098 #warning uncaught_exception not yet implemented
99 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000100#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000101}
102
Howard Hinnantffb308e2010-08-22 00:03:27 +0000103namespace std
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000104{
105
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000106exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000107{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000108}
109
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000110bad_exception::~bad_exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000111{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000112}
113
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000114const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000115{
116 return "std::exception";
117}
118
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000119const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000120{
121 return "std::bad_exception";
122}
123
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000124exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000125{
David Chisnall1d581062011-09-21 08:39:44 +0000126#if HAVE_DEPENDENT_EH_ABI
127 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000128#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000129 #warning exception_ptr not yet implemented
130 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000131#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000132}
133
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000134exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000135 : __ptr_(other.__ptr_)
136{
David Chisnall1d581062011-09-21 08:39:44 +0000137#if HAVE_DEPENDENT_EH_ABI
138 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000139#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000140 #warning exception_ptr not yet implemented
141 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000142#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000143}
144
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000145exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000146{
David Chisnall1d581062011-09-21 08:39:44 +0000147#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000148 if (__ptr_ != other.__ptr_)
149 {
David Chisnall1d581062011-09-21 08:39:44 +0000150 __cxa_increment_exception_refcount(other.__ptr_);
151 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000152 __ptr_ = other.__ptr_;
153 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000154 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000155#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000156 #warning exception_ptr not yet implemented
157 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000158#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000159}
160
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000161nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000162 : __ptr_(current_exception())
163{
164}
165
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000166nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000167{
168}
169
Howard Hinnant8df96292011-05-26 17:07:32 +0000170_ATTRIBUTE(noreturn)
Howard Hinnante4f92722010-05-27 17:06:52 +0000171void
Howard Hinnant8df96292011-05-26 17:07:32 +0000172nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000173{
174 if (__ptr_ == nullptr)
175 terminate();
176 rethrow_exception(__ptr_);
177}
178
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000179} // std
180
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000181std::exception_ptr std::current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000182{
David Chisnall1d581062011-09-21 08:39:44 +0000183#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000184 // be nicer if there was a constructor that took a ptr, then
185 // this whole function would be just:
186 // return exception_ptr(__cxa_current_primary_exception());
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000187 std::exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000188 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000189 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000190#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000191 #warning exception_ptr not yet implemented
192 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000193#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000194}
195
196void std::rethrow_exception(exception_ptr p)
197{
David Chisnall1d581062011-09-21 08:39:44 +0000198#if HAVE_DEPENDENT_EH_ABI
199 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000200 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000201 terminate();
202#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000203 #warning exception_ptr not yet implemented
204 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000205#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000206}