blob: 6b5e6984a60694c5da227608cfc9d50712a7be60 [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
David Chisnall3954f442012-02-29 12:59:17 +000035namespace std
36{
37
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000038#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
39
David Chisnall1d581062011-09-21 08:39:44 +000040// libcxxrt provides implementations of these functions itself.
David Chisnall3954f442012-02-29 12:59:17 +000041unexpected_handler
42set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000043{
Howard Hinnante65e8e32010-12-02 16:45:21 +000044 return __sync_lock_test_and_set(&__unexpected_handler, func);
45}
46
David Chisnall3954f442012-02-29 12:59:17 +000047unexpected_handler
48get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000049{
David Chisnall3954f442012-02-29 12:59:17 +000050 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000051}
52
Howard Hinnant8df96292011-05-26 17:07:32 +000053_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000054void
David Chisnall3954f442012-02-29 12:59:17 +000055unexpected()
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000056{
David Chisnall3954f442012-02-29 12:59:17 +000057 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000058 // unexpected handler should not return
David Chisnall3954f442012-02-29 12:59:17 +000059 terminate();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000060}
61
David Chisnall3954f442012-02-29 12:59:17 +000062terminate_handler
63set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000064{
Howard Hinnante65e8e32010-12-02 16:45:21 +000065 return __sync_lock_test_and_set(&__terminate_handler, func);
66}
67
David Chisnall3954f442012-02-29 12:59:17 +000068terminate_handler
69get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000070{
David Chisnall3954f442012-02-29 12:59:17 +000071 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000072}
73
Howard Hinnant986832c2011-07-29 21:35:53 +000074_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000075void
David Chisnall3954f442012-02-29 12:59:17 +000076terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000077{
Howard Hinnant72f73582010-08-11 17:04:31 +000078#ifndef _LIBCPP_NO_EXCEPTIONS
79 try
80 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000081#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall3954f442012-02-29 12:59:17 +000082 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000083 // handler should not return
84 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000085#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000086 }
Howard Hinnant72f73582010-08-11 17:04:31 +000087 catch (...)
88 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000089 // handler should not throw exception
90 ::abort ();
91 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000092#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000093}
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000094#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000095
David Chisnall3954f442012-02-29 12:59:17 +000096#ifndef LIBCXXRT
97bool uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000098{
99#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000100 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000101 return __cxa_uncaught_exception();
Howard Hinnant3472f5b2012-02-29 15:37:30 +0000102#elif LIBCXXRT
103 __cxa_eh_globals * globals = __cxa_get_globals();
104 return (globals->uncaughtExceptions != 0);
105#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000106 #warning uncaught_exception not yet implemented
107 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000108#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000109}
110
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000111#ifndef _LIBCPPABI_VERSION
112
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000113exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000114{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000115}
116
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000117bad_exception::~bad_exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000118{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000119}
120
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000121const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000122{
123 return "std::exception";
124}
125
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000126const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000127{
128 return "std::bad_exception";
129}
130
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000131#endif // _LIBCPPABI_VERSION
David Chisnall3954f442012-02-29 12:59:17 +0000132#endif //LIBCXXRT
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000133
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000134exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000135{
David Chisnall1d581062011-09-21 08:39:44 +0000136#if HAVE_DEPENDENT_EH_ABI
137 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000138#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000139 #warning exception_ptr not yet implemented
140 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000141#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000142}
143
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000144exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000145 : __ptr_(other.__ptr_)
146{
David Chisnall1d581062011-09-21 08:39:44 +0000147#if HAVE_DEPENDENT_EH_ABI
148 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000149#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000150 #warning exception_ptr not yet implemented
151 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000152#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000153}
154
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000155exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000156{
David Chisnall1d581062011-09-21 08:39:44 +0000157#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000158 if (__ptr_ != other.__ptr_)
159 {
David Chisnall1d581062011-09-21 08:39:44 +0000160 __cxa_increment_exception_refcount(other.__ptr_);
161 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000162 __ptr_ = other.__ptr_;
163 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000164 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000165#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000166 #warning exception_ptr not yet implemented
167 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000168#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000169}
170
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000171nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000172 : __ptr_(current_exception())
173{
174}
175
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000176nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000177{
178}
179
Howard Hinnant8df96292011-05-26 17:07:32 +0000180_ATTRIBUTE(noreturn)
Howard Hinnante4f92722010-05-27 17:06:52 +0000181void
Howard Hinnant8df96292011-05-26 17:07:32 +0000182nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000183{
184 if (__ptr_ == nullptr)
185 terminate();
186 rethrow_exception(__ptr_);
187}
188
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000189
David Chisnall3954f442012-02-29 12:59:17 +0000190exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000191{
David Chisnall1d581062011-09-21 08:39:44 +0000192#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000193 // be nicer if there was a constructor that took a ptr, then
194 // this whole function would be just:
195 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall3954f442012-02-29 12:59:17 +0000196 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000197 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000198 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000199#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000200 #warning exception_ptr not yet implemented
201 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000202#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000203}
204
Howard Hinnant1aa88192012-02-03 18:31:43 +0000205_ATTRIBUTE(noreturn)
David Chisnall3954f442012-02-29 12:59:17 +0000206void rethrow_exception(exception_ptr p)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000207{
David Chisnall1d581062011-09-21 08:39:44 +0000208#if HAVE_DEPENDENT_EH_ABI
209 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000210 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000211 terminate();
212#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000213 #warning exception_ptr not yet implemented
214 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000215#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000216}
David Chisnall3954f442012-02-29 12:59:17 +0000217} // std