blob: d3e1b292d34ca5ffd95877dd48df1cfa79d1ca17 [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>
Howard Hinnanted14a762013-07-23 16:05:56 +000010#include <stdio.h>
Nick Kledzik804b6e72010-05-14 20:19:37 +000011
12#include "exception"
13
Richard Smith591e32d2012-07-11 09:35:47 +000014#ifndef __has_include
15#define __has_include(inc) 0
16#endif
17
Marshall Clowdece7fe2013-03-18 17:45:34 +000018#ifdef __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +000019 #include <cxxabi.h>
Howard Hinnantdea7f392012-02-02 20:48:35 +000020
Nick Kledzik804b6e72010-05-14 20:19:37 +000021 using namespace __cxxabiv1;
David Chisnallc512df12011-09-21 08:39:44 +000022 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnantdea7f392012-02-02 20:48:35 +000023 #ifndef _LIBCPPABI_VERSION
24 using namespace __cxxabiapple;
25 // On Darwin, there are two STL shared libraries and a lower level ABI
26 // shared libray. The globals holding the current terminate handler and
27 // current unexpected handler are in the ABI library.
28 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
29 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
30 #endif // _LIBCPPABI_VERSION
Richard Smith591e32d2012-07-11 09:35:47 +000031#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
David Chisnallc512df12011-09-21 08:39:44 +000032 #include <cxxabi.h>
33 using namespace __cxxabiv1;
Richard Smith591e32d2012-07-11 09:35:47 +000034 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
35 #define HAVE_DEPENDENT_EH_ABI 1
36 #endif
Howard Hinnante0f0bfb2013-01-22 14:48:10 +000037#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
Nick Kledzik804b6e72010-05-14 20:19:37 +000038 static std::terminate_handler __terminate_handler;
39 static std::unexpected_handler __unexpected_handler;
Richard Smith591e32d2012-07-11 09:35:47 +000040#endif // __has_include(<cxxabi.h>)
Nick Kledzik804b6e72010-05-14 20:19:37 +000041
David Chisnall1e8b3f92012-02-29 12:59:17 +000042namespace std
43{
44
Michael J. Spencera358fbe2012-11-30 21:02:29 +000045#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnantdea7f392012-02-02 20:48:35 +000046
David Chisnallc512df12011-09-21 08:39:44 +000047// libcxxrt provides implementations of these functions itself.
David Chisnall1e8b3f92012-02-29 12:59:17 +000048unexpected_handler
49set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000050{
Howard Hinnanta4451512010-12-02 16:45:21 +000051 return __sync_lock_test_and_set(&__unexpected_handler, func);
52}
53
David Chisnall1e8b3f92012-02-29 12:59:17 +000054unexpected_handler
55get_unexpected() _NOEXCEPT
Howard Hinnanta4451512010-12-02 16:45:21 +000056{
David Chisnall1e8b3f92012-02-29 12:59:17 +000057 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzik804b6e72010-05-14 20:19:37 +000058}
59
Richard Smith0405cc42012-07-26 02:04:22 +000060_LIBCPP_NORETURN
Nick Kledzik804b6e72010-05-14 20:19:37 +000061void
David Chisnall1e8b3f92012-02-29 12:59:17 +000062unexpected()
Nick Kledzik804b6e72010-05-14 20:19:37 +000063{
David Chisnall1e8b3f92012-02-29 12:59:17 +000064 (*get_unexpected())();
Howard Hinnantd5109772010-08-22 13:53:14 +000065 // unexpected handler should not return
David Chisnall1e8b3f92012-02-29 12:59:17 +000066 terminate();
Nick Kledzik804b6e72010-05-14 20:19:37 +000067}
68
David Chisnall1e8b3f92012-02-29 12:59:17 +000069terminate_handler
70set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000071{
Howard Hinnanta4451512010-12-02 16:45:21 +000072 return __sync_lock_test_and_set(&__terminate_handler, func);
73}
74
David Chisnall1e8b3f92012-02-29 12:59:17 +000075terminate_handler
76get_terminate() _NOEXCEPT
Howard Hinnanta4451512010-12-02 16:45:21 +000077{
David Chisnall1e8b3f92012-02-29 12:59:17 +000078 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzik804b6e72010-05-14 20:19:37 +000079}
80
Howard Hinnantfc2f0212013-03-29 18:27:28 +000081#ifndef EMSCRIPTEN // We provide this in JS
Richard Smith0405cc42012-07-26 02:04:22 +000082_LIBCPP_NORETURN
Nick Kledzik804b6e72010-05-14 20:19:37 +000083void
David Chisnall1e8b3f92012-02-29 12:59:17 +000084terminate() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +000085{
Howard Hinnantd4444702010-08-11 17:04:31 +000086#ifndef _LIBCPP_NO_EXCEPTIONS
87 try
88 {
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000089#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall1e8b3f92012-02-29 12:59:17 +000090 (*get_terminate())();
Nick Kledzik804b6e72010-05-14 20:19:37 +000091 // handler should not return
Howard Hinnanted14a762013-07-23 16:05:56 +000092 printf("terminate_handler unexpectedly returned\n");
Nick Kledzik804b6e72010-05-14 20:19:37 +000093 ::abort ();
Howard Hinnantd4444702010-08-11 17:04:31 +000094#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnant16e6e1d2010-08-22 00:03:27 +000095 }
Howard Hinnantd4444702010-08-11 17:04:31 +000096 catch (...)
97 {
Nick Kledzik804b6e72010-05-14 20:19:37 +000098 // handler should not throw exception
Howard Hinnanted14a762013-07-23 16:05:56 +000099 printf("terminate_handler unexpectedly threw an exception\n");
Nick Kledzik804b6e72010-05-14 20:19:37 +0000100 ::abort ();
101 }
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000102#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzik804b6e72010-05-14 20:19:37 +0000103}
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000104#endif // !EMSCRIPTEN
Howard Hinnantdea7f392012-02-02 20:48:35 +0000105#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzik804b6e72010-05-14 20:19:37 +0000106
Howard Hinnantfc2f0212013-03-29 18:27:28 +0000107#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN)
David Chisnall1e8b3f92012-02-29 12:59:17 +0000108bool uncaught_exception() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000109{
Marshall Clowdece7fe2013-03-18 17:45:34 +0000110#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
Howard Hinnantd5109772010-08-22 13:53:14 +0000111 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnantdea7f392012-02-02 20:48:35 +0000112 return __cxa_uncaught_exception();
Howard Hinnantd0ed21e2012-02-29 15:37:30 +0000113#else // __APPLE__
Howard Hinnantadff4892010-05-24 17:49:41 +0000114 #warning uncaught_exception not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000115 printf("uncaught_exception not yet implemented\n");
Howard Hinnantadff4892010-05-24 17:49:41 +0000116 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000117#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000118}
119
Howard Hinnantdea7f392012-02-02 20:48:35 +0000120#ifndef _LIBCPPABI_VERSION
121
Howard Hinnanted569212011-05-26 18:23:59 +0000122exception::~exception() _NOEXCEPT
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000123{
Nick Kledzik804b6e72010-05-14 20:19:37 +0000124}
125
Howard Hinnanted569212011-05-26 18:23:59 +0000126const char* exception::what() const _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000127{
128 return "std::exception";
129}
130
David Chisnall21a84cf2012-03-14 14:11:13 +0000131#endif // _LIBCPPABI_VERSION
132#endif //LIBCXXRT
Michael J. Spencera358fbe2012-11-30 21:02:29 +0000133#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnall21a84cf2012-03-14 14:11:13 +0000134
135bad_exception::~bad_exception() _NOEXCEPT
136{
137}
138
Howard Hinnanted569212011-05-26 18:23:59 +0000139const char* bad_exception::what() const _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000140{
141 return "std::bad_exception";
142}
143
David Chisnall21a84cf2012-03-14 14:11:13 +0000144#endif
145
Howard Hinnantdea7f392012-02-02 20:48:35 +0000146
Howard Hinnanted569212011-05-26 18:23:59 +0000147exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000148{
David Chisnallc512df12011-09-21 08:39:44 +0000149#if HAVE_DEPENDENT_EH_ABI
150 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzik804b6e72010-05-14 20:19:37 +0000151#else
Howard Hinnantd5109772010-08-22 13:53:14 +0000152 #warning exception_ptr not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000153 printf("exception_ptr not yet implemented\n");
Howard Hinnantd5109772010-08-22 13:53:14 +0000154 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000155#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000156}
157
Howard Hinnanted569212011-05-26 18:23:59 +0000158exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000159 : __ptr_(other.__ptr_)
160{
David Chisnallc512df12011-09-21 08:39:44 +0000161#if HAVE_DEPENDENT_EH_ABI
162 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzik804b6e72010-05-14 20:19:37 +0000163#else
Howard Hinnantd5109772010-08-22 13:53:14 +0000164 #warning exception_ptr not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000165 printf("exception_ptr not yet implemented\n");
Howard Hinnantd5109772010-08-22 13:53:14 +0000166 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000167#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000168}
169
Howard Hinnanted569212011-05-26 18:23:59 +0000170exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000171{
David Chisnallc512df12011-09-21 08:39:44 +0000172#if HAVE_DEPENDENT_EH_ABI
Nick Kledzik804b6e72010-05-14 20:19:37 +0000173 if (__ptr_ != other.__ptr_)
174 {
David Chisnallc512df12011-09-21 08:39:44 +0000175 __cxa_increment_exception_refcount(other.__ptr_);
176 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnantd5109772010-08-22 13:53:14 +0000177 __ptr_ = other.__ptr_;
178 }
Nick Kledzik804b6e72010-05-14 20:19:37 +0000179 return *this;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000180#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000181 #warning exception_ptr not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000182 printf("exception_ptr not yet implemented\n");
Howard Hinnantd5109772010-08-22 13:53:14 +0000183 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000184#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000185}
186
Howard Hinnanted569212011-05-26 18:23:59 +0000187nested_exception::nested_exception() _NOEXCEPT
Howard Hinnanted2c2912010-05-27 17:06:52 +0000188 : __ptr_(current_exception())
189{
190}
191
Howard Hinnanted569212011-05-26 18:23:59 +0000192nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnanted2c2912010-05-27 17:06:52 +0000193{
194}
195
Richard Smith0405cc42012-07-26 02:04:22 +0000196_LIBCPP_NORETURN
Howard Hinnanted2c2912010-05-27 17:06:52 +0000197void
Howard Hinnant4b7a43d2011-05-26 17:07:32 +0000198nested_exception::rethrow_nested() const
Howard Hinnanted2c2912010-05-27 17:06:52 +0000199{
200 if (__ptr_ == nullptr)
201 terminate();
202 rethrow_exception(__ptr_);
203}
204
Nick Kledzik804b6e72010-05-14 20:19:37 +0000205
David Chisnall1e8b3f92012-02-29 12:59:17 +0000206exception_ptr current_exception() _NOEXCEPT
Nick Kledzik804b6e72010-05-14 20:19:37 +0000207{
David Chisnallc512df12011-09-21 08:39:44 +0000208#if HAVE_DEPENDENT_EH_ABI
Howard Hinnantd5109772010-08-22 13:53:14 +0000209 // be nicer if there was a constructor that took a ptr, then
210 // this whole function would be just:
211 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall1e8b3f92012-02-29 12:59:17 +0000212 exception_ptr ptr;
David Chisnallc512df12011-09-21 08:39:44 +0000213 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnantd5109772010-08-22 13:53:14 +0000214 return ptr;
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000215#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000216 #warning exception_ptr not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000217 printf("exception_ptr not yet implemented\n");
Howard Hinnantd5109772010-08-22 13:53:14 +0000218 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000219#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000220}
221
Richard Smith0405cc42012-07-26 02:04:22 +0000222_LIBCPP_NORETURN
David Chisnall1e8b3f92012-02-29 12:59:17 +0000223void rethrow_exception(exception_ptr p)
Nick Kledzik804b6e72010-05-14 20:19:37 +0000224{
David Chisnallc512df12011-09-21 08:39:44 +0000225#if HAVE_DEPENDENT_EH_ABI
226 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnantd5109772010-08-22 13:53:14 +0000227 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000228 terminate();
229#else // __APPLE__
Howard Hinnantd5109772010-08-22 13:53:14 +0000230 #warning exception_ptr not yet implemented
Howard Hinnanted14a762013-07-23 16:05:56 +0000231 printf("exception_ptr not yet implemented\n");
Howard Hinnantd5109772010-08-22 13:53:14 +0000232 ::abort();
Howard Hinnant16e6e1d2010-08-22 00:03:27 +0000233#endif // __APPLE__
Nick Kledzik804b6e72010-05-14 20:19:37 +0000234}
David Chisnall1e8b3f92012-02-29 12:59:17 +0000235} // std