blob: 40327d6a07dc6976aafb8f4f9e6658e6524e4474 [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>
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000015
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000016 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000017 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000018 #ifndef _LIBCPPABI_VERSION
19 using namespace __cxxabiapple;
20 // On Darwin, there are two STL shared libraries and a lower level ABI
21 // shared libray. The globals holding the current terminate handler and
22 // current unexpected handler are in the ABI library.
23 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
24 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
25 #endif // _LIBCPPABI_VERSION
David Chisnall1d581062011-09-21 08:39:44 +000026#elif defined(LIBCXXRT)
27 #include <cxxabi.h>
28 using namespace __cxxabiv1;
29 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnantffb308e2010-08-22 00:03:27 +000030#else // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000031 static std::terminate_handler __terminate_handler;
32 static std::unexpected_handler __unexpected_handler;
Howard Hinnantffb308e2010-08-22 00:03:27 +000033#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000034
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000035#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
36
David Chisnall1d581062011-09-21 08:39:44 +000037// libcxxrt provides implementations of these functions itself.
Howard Hinnantffb308e2010-08-22 00:03:27 +000038std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000039std::set_unexpected(std::unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000040{
Howard Hinnante65e8e32010-12-02 16:45:21 +000041 return __sync_lock_test_and_set(&__unexpected_handler, func);
42}
43
44std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000045std::get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000046{
47 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000048}
49
Howard Hinnant8df96292011-05-26 17:07:32 +000050_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000051void
52std::unexpected()
53{
Howard Hinnante60478c2010-12-06 15:11:48 +000054 (*std::get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000055 // unexpected handler should not return
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000056 std::terminate();
57}
58
Howard Hinnantffb308e2010-08-22 00:03:27 +000059std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000060std::set_terminate(std::terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000061{
Howard Hinnante65e8e32010-12-02 16:45:21 +000062 return __sync_lock_test_and_set(&__terminate_handler, func);
63}
64
65std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000066std::get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000067{
68 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000069}
70
Howard Hinnant986832c2011-07-29 21:35:53 +000071_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000072void
Howard Hinnant8df96292011-05-26 17:07:32 +000073std::terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000074{
Howard Hinnant72f73582010-08-11 17:04:31 +000075#ifndef _LIBCPP_NO_EXCEPTIONS
76 try
77 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000078#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnante60478c2010-12-06 15:11:48 +000079 (*std::get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000080 // handler should not return
81 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000082#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000083 }
Howard Hinnant72f73582010-08-11 17:04:31 +000084 catch (...)
85 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000086 // handler should not throw exception
87 ::abort ();
88 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000089#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000090}
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000091#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000092
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000093bool std::uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000094{
95#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +000096 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000097 return __cxa_uncaught_exception();
David Chisnall1d581062011-09-21 08:39:44 +000098#elif LIBCXXRT
99 __cxa_eh_globals * globals = __cxa_get_globals();
100 return (globals->uncaughtExceptions != 0);
Howard Hinnantffb308e2010-08-22 00:03:27 +0000101#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000102 #warning uncaught_exception not yet implemented
103 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000104#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000105}
106
Howard Hinnantffb308e2010-08-22 00:03:27 +0000107namespace std
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000108{
109
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000110#ifndef _LIBCPPABI_VERSION
111
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000112exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000113{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000114}
115
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000116bad_exception::~bad_exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000117{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000118}
119
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000120const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000121{
122 return "std::exception";
123}
124
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000125const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000126{
127 return "std::bad_exception";
128}
129
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000130#endif // _LIBCPPABI_VERSION
131
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000132exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000133{
David Chisnall1d581062011-09-21 08:39:44 +0000134#if HAVE_DEPENDENT_EH_ABI
135 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000136#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000137 #warning exception_ptr not yet implemented
138 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000139#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000140}
141
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000142exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000143 : __ptr_(other.__ptr_)
144{
David Chisnall1d581062011-09-21 08:39:44 +0000145#if HAVE_DEPENDENT_EH_ABI
146 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000147#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000148 #warning exception_ptr not yet implemented
149 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000150#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000151}
152
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000153exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000154{
David Chisnall1d581062011-09-21 08:39:44 +0000155#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000156 if (__ptr_ != other.__ptr_)
157 {
David Chisnall1d581062011-09-21 08:39:44 +0000158 __cxa_increment_exception_refcount(other.__ptr_);
159 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000160 __ptr_ = other.__ptr_;
161 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000162 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000163#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000164 #warning exception_ptr not yet implemented
165 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000166#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000167}
168
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000169nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000170 : __ptr_(current_exception())
171{
172}
173
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000174nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000175{
176}
177
Howard Hinnant8df96292011-05-26 17:07:32 +0000178_ATTRIBUTE(noreturn)
Howard Hinnante4f92722010-05-27 17:06:52 +0000179void
Howard Hinnant8df96292011-05-26 17:07:32 +0000180nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000181{
182 if (__ptr_ == nullptr)
183 terminate();
184 rethrow_exception(__ptr_);
185}
186
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000187} // std
188
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000189std::exception_ptr std::current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000190{
David Chisnall1d581062011-09-21 08:39:44 +0000191#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000192 // be nicer if there was a constructor that took a ptr, then
193 // this whole function would be just:
194 // return exception_ptr(__cxa_current_primary_exception());
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000195 std::exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000196 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000197 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000198#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000199 #warning exception_ptr not yet implemented
200 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000201#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000202}
203
204void std::rethrow_exception(exception_ptr p)
205{
David Chisnall1d581062011-09-21 08:39:44 +0000206#if HAVE_DEPENDENT_EH_ABI
207 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000208 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000209 terminate();
210#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000211 #warning exception_ptr not yet implemented
212 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000213#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000214}