blob: 6a5803d377459d4b98058c42d5fb1a3d2b1e80fb [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 +0000117const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000118{
119 return "std::exception";
120}
121
David Chisnallba252b82012-03-14 14:11:13 +0000122#endif // _LIBCPPABI_VERSION
123#endif //LIBCXXRT
124#ifndef _LIBCPPABI_VERSION
125
126bad_exception::~bad_exception() _NOEXCEPT
127{
128}
129
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000130const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000131{
132 return "std::bad_exception";
133}
134
David Chisnallba252b82012-03-14 14:11:13 +0000135#endif
136
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000137
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000138exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000139{
David Chisnall1d581062011-09-21 08:39:44 +0000140#if HAVE_DEPENDENT_EH_ABI
141 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000142#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000143 #warning exception_ptr not yet implemented
144 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000145#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000146}
147
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000148exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000149 : __ptr_(other.__ptr_)
150{
David Chisnall1d581062011-09-21 08:39:44 +0000151#if HAVE_DEPENDENT_EH_ABI
152 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000153#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000154 #warning exception_ptr not yet implemented
155 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000156#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000157}
158
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000159exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000160{
David Chisnall1d581062011-09-21 08:39:44 +0000161#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000162 if (__ptr_ != other.__ptr_)
163 {
David Chisnall1d581062011-09-21 08:39:44 +0000164 __cxa_increment_exception_refcount(other.__ptr_);
165 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000166 __ptr_ = other.__ptr_;
167 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000168 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000169#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000170 #warning exception_ptr not yet implemented
171 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000172#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000173}
174
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000175nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000176 : __ptr_(current_exception())
177{
178}
179
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000180nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000181{
182}
183
Howard Hinnant8df96292011-05-26 17:07:32 +0000184_ATTRIBUTE(noreturn)
Howard Hinnante4f92722010-05-27 17:06:52 +0000185void
Howard Hinnant8df96292011-05-26 17:07:32 +0000186nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000187{
188 if (__ptr_ == nullptr)
189 terminate();
190 rethrow_exception(__ptr_);
191}
192
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000193
David Chisnall3954f442012-02-29 12:59:17 +0000194exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000195{
David Chisnall1d581062011-09-21 08:39:44 +0000196#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000197 // be nicer if there was a constructor that took a ptr, then
198 // this whole function would be just:
199 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall3954f442012-02-29 12:59:17 +0000200 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000201 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000202 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000203#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000204 #warning exception_ptr not yet implemented
205 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000206#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000207}
208
Howard Hinnant1aa88192012-02-03 18:31:43 +0000209_ATTRIBUTE(noreturn)
David Chisnall3954f442012-02-29 12:59:17 +0000210void rethrow_exception(exception_ptr p)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000211{
David Chisnall1d581062011-09-21 08:39:44 +0000212#if HAVE_DEPENDENT_EH_ABI
213 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000214 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000215 terminate();
216#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000217 #warning exception_ptr not yet implemented
218 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000219#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000220}
David Chisnall3954f442012-02-29 12:59:17 +0000221} // std