blob: f5e6d2259daf998999932e87196a0f0740569a1d [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
Richard Smithffd74672012-07-11 09:35:47 +000013#ifndef __has_include
14#define __has_include(inc) 0
15#endif
16
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000017#if __APPLE__
18 #include <cxxabi.h>
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000019
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000020 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000021 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000022 #ifndef _LIBCPPABI_VERSION
23 using namespace __cxxabiapple;
24 // On Darwin, there are two STL shared libraries and a lower level ABI
25 // shared libray. The globals holding the current terminate handler and
26 // current unexpected handler are in the ABI library.
27 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
28 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
29 #endif // _LIBCPPABI_VERSION
Richard Smithffd74672012-07-11 09:35:47 +000030#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
David Chisnall1d581062011-09-21 08:39:44 +000031 #include <cxxabi.h>
32 using namespace __cxxabiv1;
Richard Smithffd74672012-07-11 09:35:47 +000033 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
34 #define HAVE_DEPENDENT_EH_ABI 1
35 #endif
36#else // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000037 static std::terminate_handler __terminate_handler;
38 static std::unexpected_handler __unexpected_handler;
Richard Smithffd74672012-07-11 09:35:47 +000039#endif // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000040
David Chisnall3954f442012-02-29 12:59:17 +000041namespace std
42{
43
Michael J. Spencer7deadc82012-11-30 21:02:29 +000044#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000045
David Chisnall1d581062011-09-21 08:39:44 +000046// libcxxrt provides implementations of these functions itself.
David Chisnall3954f442012-02-29 12:59:17 +000047unexpected_handler
48set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000049{
Howard Hinnante65e8e32010-12-02 16:45:21 +000050 return __sync_lock_test_and_set(&__unexpected_handler, func);
51}
52
David Chisnall3954f442012-02-29 12:59:17 +000053unexpected_handler
54get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000055{
David Chisnall3954f442012-02-29 12:59:17 +000056 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000057}
58
Richard Smithcabd3922012-07-26 02:04:22 +000059_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000060void
David Chisnall3954f442012-02-29 12:59:17 +000061unexpected()
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000062{
David Chisnall3954f442012-02-29 12:59:17 +000063 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000064 // unexpected handler should not return
David Chisnall3954f442012-02-29 12:59:17 +000065 terminate();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000066}
67
David Chisnall3954f442012-02-29 12:59:17 +000068terminate_handler
69set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000070{
Howard Hinnante65e8e32010-12-02 16:45:21 +000071 return __sync_lock_test_and_set(&__terminate_handler, func);
72}
73
David Chisnall3954f442012-02-29 12:59:17 +000074terminate_handler
75get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000076{
David Chisnall3954f442012-02-29 12:59:17 +000077 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000078}
79
Richard Smithcabd3922012-07-26 02:04:22 +000080_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000081void
David Chisnall3954f442012-02-29 12:59:17 +000082terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000083{
Howard Hinnant72f73582010-08-11 17:04:31 +000084#ifndef _LIBCPP_NO_EXCEPTIONS
85 try
86 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000087#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall3954f442012-02-29 12:59:17 +000088 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000089 // handler should not return
90 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000092 }
Howard Hinnant72f73582010-08-11 17:04:31 +000093 catch (...)
94 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000095 // handler should not throw exception
96 ::abort ();
97 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000098#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000099}
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000100#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000101
Michael J. Spencer7deadc82012-11-30 21:02:29 +0000102#if !defined(LIBCXXRT) && !defined(__GLIBCXX__)
David Chisnall3954f442012-02-29 12:59:17 +0000103bool uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000104{
Richard Smithffd74672012-07-11 09:35:47 +0000105#if __APPLE__ || defined(_LIBCPPABI_VERSION)
Howard Hinnant34468d42010-08-22 13:53:14 +0000106 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000107 return __cxa_uncaught_exception();
Howard Hinnant3472f5b2012-02-29 15:37:30 +0000108#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +0000109 #warning uncaught_exception not yet implemented
110 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000111#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000112}
113
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000114#ifndef _LIBCPPABI_VERSION
115
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000116exception::~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
David Chisnallba252b82012-03-14 14:11:13 +0000125#endif // _LIBCPPABI_VERSION
126#endif //LIBCXXRT
Michael J. Spencer7deadc82012-11-30 21:02:29 +0000127#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnallba252b82012-03-14 14:11:13 +0000128
129bad_exception::~bad_exception() _NOEXCEPT
130{
131}
132
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000133const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000134{
135 return "std::bad_exception";
136}
137
David Chisnallba252b82012-03-14 14:11:13 +0000138#endif
139
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000140
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000141exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000142{
David Chisnall1d581062011-09-21 08:39:44 +0000143#if HAVE_DEPENDENT_EH_ABI
144 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000145#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000146 #warning exception_ptr not yet implemented
147 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000148#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000149}
150
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000151exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000152 : __ptr_(other.__ptr_)
153{
David Chisnall1d581062011-09-21 08:39:44 +0000154#if HAVE_DEPENDENT_EH_ABI
155 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000156#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000157 #warning exception_ptr not yet implemented
158 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000159#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000160}
161
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000162exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000163{
David Chisnall1d581062011-09-21 08:39:44 +0000164#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000165 if (__ptr_ != other.__ptr_)
166 {
David Chisnall1d581062011-09-21 08:39:44 +0000167 __cxa_increment_exception_refcount(other.__ptr_);
168 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000169 __ptr_ = other.__ptr_;
170 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000171 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000172#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000173 #warning exception_ptr not yet implemented
174 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000175#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000176}
177
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000178nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000179 : __ptr_(current_exception())
180{
181}
182
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000183nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000184{
185}
186
Richard Smithcabd3922012-07-26 02:04:22 +0000187_LIBCPP_NORETURN
Howard Hinnante4f92722010-05-27 17:06:52 +0000188void
Howard Hinnant8df96292011-05-26 17:07:32 +0000189nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000190{
191 if (__ptr_ == nullptr)
192 terminate();
193 rethrow_exception(__ptr_);
194}
195
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000196
David Chisnall3954f442012-02-29 12:59:17 +0000197exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000198{
David Chisnall1d581062011-09-21 08:39:44 +0000199#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000200 // be nicer if there was a constructor that took a ptr, then
201 // this whole function would be just:
202 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall3954f442012-02-29 12:59:17 +0000203 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000204 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000205 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000206#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000207 #warning exception_ptr not yet implemented
208 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000209#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000210}
211
Richard Smithcabd3922012-07-26 02:04:22 +0000212_LIBCPP_NORETURN
David Chisnall3954f442012-02-29 12:59:17 +0000213void rethrow_exception(exception_ptr p)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000214{
David Chisnall1d581062011-09-21 08:39:44 +0000215#if HAVE_DEPENDENT_EH_ABI
216 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000217 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000218 terminate();
219#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000220 #warning exception_ptr not yet implemented
221 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000222#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000223}
David Chisnall3954f442012-02-29 12:59:17 +0000224} // std