blob: 1d2f6b25979ed2f0344df68d5f86cca422ec9464 [file] [log] [blame]
Nick Kledzik804b6e72010-05-14 20:19:37 +00001//===------------------------ exception.cpp -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnantb64f8b02010-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 Kledzik804b6e72010-05-14 20:19:37 +00007//
8//===----------------------------------------------------------------------===//
9#include <stdlib.h>
10
11#include "exception"
12
Richard Smith591e32d2012-07-11 09:35:47 +000013#ifndef __has_include
14#define __has_include(inc) 0
15#endif
16
Marshall Clowdece7fe2013-03-18 17:45:34 +000017#ifdef __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +000018 #include <cxxabi.h>
Howard Hinnantdea7f392012-02-02 20:48:35 +000019
Nick Kledzik804b6e72010-05-14 20:19:37 +000020 using namespace __cxxabiv1;
David Chisnallc512df12011-09-21 08:39:44 +000021 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnantdea7f392012-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 Smith591e32d2012-07-11 09:35:47 +000030#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
David Chisnallc512df12011-09-21 08:39:44 +000031 #include <cxxabi.h>
32 using namespace __cxxabiv1;
Richard Smith591e32d2012-07-11 09:35:47 +000033 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
34 #define HAVE_DEPENDENT_EH_ABI 1
35 #endif
Howard Hinnante0f0bfb2013-01-22 14:48:10 +000036#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
Nick Kledzik804b6e72010-05-14 20:19:37 +000037 static std::terminate_handler __terminate_handler;
38 static std::unexpected_handler __unexpected_handler;
Richard Smith591e32d2012-07-11 09:35:47 +000039#endif // __has_include(<cxxabi.h>)
Nick Kledzik804b6e72010-05-14 20:19:37 +000040
David Chisnall1e8b3f92012-02-29 12:59:17 +000041namespace std
42{
43
Michael J. Spencera358fbe2012-11-30 21:02:29 +000044#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnantdea7f392012-02-02 20:48:35 +000045
David Chisnallc512df12011-09-21 08:39:44 +000046// libcxxrt provides implementations of these functions itself.
David Chisnall1e8b3f92012-02-29 12:59:17 +000047unexpected_handler
48set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000049{
Howard Hinnanta4451512010-12-02 16:45:21 +000050 return __sync_lock_test_and_set(&__unexpected_handler, func);
51}
52
David Chisnall1e8b3f92012-02-29 12:59:17 +000053unexpected_handler
54get_unexpected() _NOEXCEPT
Howard Hinnanta4451512010-12-02 16:45:21 +000055{
David Chisnall1e8b3f92012-02-29 12:59:17 +000056 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzik804b6e72010-05-14 20:19:37 +000057}
58
Richard Smith0405cc42012-07-26 02:04:22 +000059_LIBCPP_NORETURN
Nick Kledzik804b6e72010-05-14 20:19:37 +000060void
David Chisnall1e8b3f92012-02-29 12:59:17 +000061unexpected()
Nick Kledzik804b6e72010-05-14 20:19:37 +000062{
David Chisnall1e8b3f92012-02-29 12:59:17 +000063 (*get_unexpected())();
Howard Hinnantd5109772010-08-22 13:53:14 +000064 // unexpected handler should not return
David Chisnall1e8b3f92012-02-29 12:59:17 +000065 terminate();
Nick Kledzik804b6e72010-05-14 20:19:37 +000066}
67
David Chisnall1e8b3f92012-02-29 12:59:17 +000068terminate_handler
69set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000070{
Howard Hinnanta4451512010-12-02 16:45:21 +000071 return __sync_lock_test_and_set(&__terminate_handler, func);
72}
73
David Chisnall1e8b3f92012-02-29 12:59:17 +000074terminate_handler
75get_terminate() _NOEXCEPT
Howard Hinnanta4451512010-12-02 16:45:21 +000076{
David Chisnall1e8b3f92012-02-29 12:59:17 +000077 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzik804b6e72010-05-14 20:19:37 +000078}
79
Howard Hinnantfc2f0212013-03-29 18:27:28 +000080#ifndef EMSCRIPTEN // We provide this in JS
Richard Smith0405cc42012-07-26 02:04:22 +000081_LIBCPP_NORETURN
Nick Kledzik804b6e72010-05-14 20:19:37 +000082void
David Chisnall1e8b3f92012-02-29 12:59:17 +000083terminate() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000084{
Howard Hinnantd4444702010-08-11 17:04:31 +000085#ifndef _LIBCPP_NO_EXCEPTIONS
86 try
87 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000088#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall1e8b3f92012-02-29 12:59:17 +000089 (*get_terminate())();
Nick Kledzik804b6e72010-05-14 20:19:37 +000090 // handler should not return
91 ::abort ();
Howard Hinnantd4444702010-08-11 17:04:31 +000092#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000093 }
Howard Hinnantd4444702010-08-11 17:04:31 +000094 catch (...)
95 {
Nick Kledzik804b6e72010-05-14 20:19:37 +000096 // handler should not throw exception
97 ::abort ();
98 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000099#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzik804b6e72010-05-14 20:19:37 +0000100}
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000101#endif // !EMSCRIPTEN
Howard Hinnantdea7f392012-02-02 20:48:35 +0000102#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzik804b6e72010-05-14 20:19:37 +0000103
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000104#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN)
David Chisnall1e8b3f92012-02-29 12:59:17 +0000105bool uncaught_exception() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000106{
Marshall Clowdece7fe2013-03-18 17:45:34 +0000107#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
Howard Hinnantd5109772010-08-22 13:53:14 +0000108 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnantdea7f392012-02-02 20:48:35 +0000109 return __cxa_uncaught_exception();
Howard Hinnantd0ed21e2012-02-29 15:37:30 +0000110#else // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000111 #warning uncaught_exception not yet implemented
112 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000113#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000114}
115
Howard Hinnantdea7f392012-02-02 20:48:35 +0000116#ifndef _LIBCPPABI_VERSION
117
Howard Hinnanted569212011-05-26 18:23:59 +0000118exception::~exception() _NOEXCEPT
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000119{
Nick Kledzik804b6e72010-05-14 20:19:37 +0000120}
121
Howard Hinnanted569212011-05-26 18:23:59 +0000122const char* exception::what() const _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000123{
124 return "std::exception";
125}
126
David Chisnall21a84cf2012-03-14 14:11:13 +0000127#endif // _LIBCPPABI_VERSION
128#endif //LIBCXXRT
Michael J. Spencera358fbe2012-11-30 21:02:29 +0000129#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnall21a84cf2012-03-14 14:11:13 +0000130
131bad_exception::~bad_exception() _NOEXCEPT
132{
133}
134
Howard Hinnanted569212011-05-26 18:23:59 +0000135const char* bad_exception::what() const _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000136{
137 return "std::bad_exception";
138}
139
David Chisnall21a84cf2012-03-14 14:11:13 +0000140#endif
141
Howard Hinnantdea7f392012-02-02 20:48:35 +0000142
Howard Hinnanted569212011-05-26 18:23:59 +0000143exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000144{
David Chisnallc512df12011-09-21 08:39:44 +0000145#if HAVE_DEPENDENT_EH_ABI
146 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzik804b6e72010-05-14 20:19:37 +0000147#else
Howard Hinnantd5109772010-08-22 13:53:14 +0000148 #warning exception_ptr not yet implemented
149 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000150#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000151}
152
Howard Hinnanted569212011-05-26 18:23:59 +0000153exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000154 : __ptr_(other.__ptr_)
155{
David Chisnallc512df12011-09-21 08:39:44 +0000156#if HAVE_DEPENDENT_EH_ABI
157 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzik804b6e72010-05-14 20:19:37 +0000158#else
Howard Hinnantd5109772010-08-22 13:53:14 +0000159 #warning exception_ptr not yet implemented
160 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000161#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000162}
163
Howard Hinnanted569212011-05-26 18:23:59 +0000164exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000165{
David Chisnallc512df12011-09-21 08:39:44 +0000166#if HAVE_DEPENDENT_EH_ABI
Nick Kledzik804b6e72010-05-14 20:19:37 +0000167 if (__ptr_ != other.__ptr_)
168 {
David Chisnallc512df12011-09-21 08:39:44 +0000169 __cxa_increment_exception_refcount(other.__ptr_);
170 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnantd5109772010-08-22 13:53:14 +0000171 __ptr_ = other.__ptr_;
172 }
Nick Kledzik804b6e72010-05-14 20:19:37 +0000173 return *this;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000174#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000175 #warning exception_ptr not yet implemented
176 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000177#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000178}
179
Howard Hinnanted569212011-05-26 18:23:59 +0000180nested_exception::nested_exception() _NOEXCEPT
Howard Hinnanted2c2912010-05-27 17:06:52 +0000181 : __ptr_(current_exception())
182{
183}
184
Howard Hinnanted569212011-05-26 18:23:59 +0000185nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnanted2c2912010-05-27 17:06:52 +0000186{
187}
188
Richard Smith0405cc42012-07-26 02:04:22 +0000189_LIBCPP_NORETURN
Howard Hinnanted2c2912010-05-27 17:06:52 +0000190void
Howard Hinnant4b7a43d2011-05-26 17:07:32 +0000191nested_exception::rethrow_nested() const
Howard Hinnanted2c2912010-05-27 17:06:52 +0000192{
193 if (__ptr_ == nullptr)
194 terminate();
195 rethrow_exception(__ptr_);
196}
197
Nick Kledzik804b6e72010-05-14 20:19:37 +0000198
David Chisnall1e8b3f92012-02-29 12:59:17 +0000199exception_ptr current_exception() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000200{
David Chisnallc512df12011-09-21 08:39:44 +0000201#if HAVE_DEPENDENT_EH_ABI
Howard Hinnantd5109772010-08-22 13:53:14 +0000202 // be nicer if there was a constructor that took a ptr, then
203 // this whole function would be just:
204 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall1e8b3f92012-02-29 12:59:17 +0000205 exception_ptr ptr;
David Chisnallc512df12011-09-21 08:39:44 +0000206 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnantd5109772010-08-22 13:53:14 +0000207 return ptr;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000208#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000209 #warning exception_ptr not yet implemented
210 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000211#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000212}
213
Richard Smith0405cc42012-07-26 02:04:22 +0000214_LIBCPP_NORETURN
David Chisnall1e8b3f92012-02-29 12:59:17 +0000215void rethrow_exception(exception_ptr p)
Nick Kledzik804b6e72010-05-14 20:19:37 +0000216{
David Chisnallc512df12011-09-21 08:39:44 +0000217#if HAVE_DEPENDENT_EH_ABI
218 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnantd5109772010-08-22 13:53:14 +0000219 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000220 terminate();
221#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000222 #warning exception_ptr not yet implemented
223 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000224#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000225}
David Chisnall1e8b3f92012-02-29 12:59:17 +0000226} // std