blob: b0efda648e59d60b669f32dac7b7b1f57430d057 [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>
15 using namespace __cxxabiv1;
16 // On Darwin, there are two STL shared libraries and a lower level ABI
17 // shared libray. The globals holding the current terminate handler and
18 // current unexpected handler are in the ABI library.
19 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
20 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
Howard Hinnantffb308e2010-08-22 00:03:27 +000021#else // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000022 static std::terminate_handler __terminate_handler;
23 static std::unexpected_handler __unexpected_handler;
Howard Hinnantffb308e2010-08-22 00:03:27 +000024#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000025
Howard Hinnantffb308e2010-08-22 00:03:27 +000026std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000027std::set_unexpected(std::unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000028{
Howard Hinnante65e8e32010-12-02 16:45:21 +000029 return __sync_lock_test_and_set(&__unexpected_handler, func);
30}
31
32std::unexpected_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000033std::get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000034{
35 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000036}
37
Howard Hinnant8df96292011-05-26 17:07:32 +000038_ATTRIBUTE(noreturn)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000039void
40std::unexpected()
41{
Howard Hinnante60478c2010-12-06 15:11:48 +000042 (*std::get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000043 // unexpected handler should not return
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000044 std::terminate();
45}
46
Howard Hinnantffb308e2010-08-22 00:03:27 +000047std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000048std::set_terminate(std::terminate_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(&__terminate_handler, func);
51}
52
53std::terminate_handler
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000054std::get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000055{
56 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000057}
58
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000059void
Howard Hinnant8df96292011-05-26 17:07:32 +000060std::terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000061{
Howard Hinnant72f73582010-08-11 17:04:31 +000062#ifndef _LIBCPP_NO_EXCEPTIONS
63 try
64 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000065#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnante60478c2010-12-06 15:11:48 +000066 (*std::get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000067 // handler should not return
68 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000069#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000070 }
Howard Hinnant72f73582010-08-11 17:04:31 +000071 catch (...)
72 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000073 // handler should not throw exception
74 ::abort ();
75 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000076#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000077}
78
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000079bool std::uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000080{
81#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +000082 // on Darwin, there is a helper function so __cxa_get_globals is private
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000083 return __cxxabiapple::__cxa_uncaught_exception();
Howard Hinnantffb308e2010-08-22 00:03:27 +000084#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +000085 #warning uncaught_exception not yet implemented
86 ::abort();
87 // Not provided by Ubuntu gcc-4.2.4's cxxabi.h.
88 // __cxa_eh_globals * globals = __cxa_get_globals();
89 // return (globals->uncaughtExceptions != 0);
Howard Hinnantffb308e2010-08-22 00:03:27 +000090#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000091}
92
Howard Hinnantffb308e2010-08-22 00:03:27 +000093namespace std
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000094{
95
Howard Hinnant1bc52cf2011-05-26 18:23:59 +000096exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +000097{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000098}
99
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000100bad_exception::~bad_exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000101{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000102}
103
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000104const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000105{
106 return "std::exception";
107}
108
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000109const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000110{
111 return "std::bad_exception";
112}
113
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000114exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000115{
116#if __APPLE__
117 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
118#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000119 #warning exception_ptr not yet implemented
120 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000121#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000122}
123
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000124exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000125 : __ptr_(other.__ptr_)
126{
127#if __APPLE__
128 __cxxabiapple::__cxa_increment_exception_refcount(__ptr_);
129#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000130 #warning exception_ptr not yet implemented
131 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000132#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000133}
134
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000135exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000136{
137#if __APPLE__
138 if (__ptr_ != other.__ptr_)
139 {
140 __cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_);
141 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000142 __ptr_ = other.__ptr_;
143 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000144 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000145#else // __APPLE__
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 +0000151nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000152 : __ptr_(current_exception())
153{
154}
155
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000156nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000157{
158}
159
Howard Hinnant8df96292011-05-26 17:07:32 +0000160_ATTRIBUTE(noreturn)
Howard Hinnante4f92722010-05-27 17:06:52 +0000161void
Howard Hinnant8df96292011-05-26 17:07:32 +0000162nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000163{
164 if (__ptr_ == nullptr)
165 terminate();
166 rethrow_exception(__ptr_);
167}
168
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000169} // std
170
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000171std::exception_ptr std::current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000172{
173#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000174 // be nicer if there was a constructor that took a ptr, then
175 // this whole function would be just:
176 // return exception_ptr(__cxa_current_primary_exception());
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000177 std::exception_ptr ptr;
Howard Hinnant34468d42010-08-22 13:53:14 +0000178 ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
179 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000180#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000181 #warning exception_ptr not yet implemented
182 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000183#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000184}
185
186void std::rethrow_exception(exception_ptr p)
187{
188#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000189 __cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
190 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000191 terminate();
192#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000193 #warning exception_ptr not yet implemented
194 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000195#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000196}