blob: 6c389c28082ab47392a139c28da71c489aefe106 [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
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000027std::set_unexpected(std::unexpected_handler func) throw()
28{
Howard Hinnante65e8e32010-12-02 16:45:21 +000029 return __sync_lock_test_and_set(&__unexpected_handler, func);
30}
31
32std::unexpected_handler
33std::get_unexpected() throw()
34{
35 return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000036}
37
38void
39std::unexpected()
40{
Howard Hinnantf64dfce2010-12-04 19:54:11 +000041 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000042 // unexpected handler should not return
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000043 std::terminate();
44}
45
Howard Hinnantffb308e2010-08-22 00:03:27 +000046std::terminate_handler
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000047std::set_terminate(std::terminate_handler func) throw()
48{
Howard Hinnante65e8e32010-12-02 16:45:21 +000049 return __sync_lock_test_and_set(&__terminate_handler, func);
50}
51
52std::terminate_handler
53std::get_terminate() throw()
54{
55 return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000056}
57
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000058void
59std::terminate()
60{
Howard Hinnant72f73582010-08-11 17:04:31 +000061#ifndef _LIBCPP_NO_EXCEPTIONS
62 try
63 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000064#endif // _LIBCPP_NO_EXCEPTIONS
Howard Hinnantf64dfce2010-12-04 19:54:11 +000065 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000066 // handler should not return
67 ::abort ();
Howard Hinnant72f73582010-08-11 17:04:31 +000068#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000069 }
Howard Hinnant72f73582010-08-11 17:04:31 +000070 catch (...)
71 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000072 // handler should not throw exception
73 ::abort ();
74 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000075#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000076}
77
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000078bool std::uncaught_exception() throw()
79{
80#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +000081 // on Darwin, there is a helper function so __cxa_get_globals is private
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000082 return __cxxabiapple::__cxa_uncaught_exception();
Howard Hinnantffb308e2010-08-22 00:03:27 +000083#else // __APPLE__
Howard Hinnant155c2af2010-05-24 17:49:41 +000084 #warning uncaught_exception not yet implemented
85 ::abort();
86 // Not provided by Ubuntu gcc-4.2.4's cxxabi.h.
87 // __cxa_eh_globals * globals = __cxa_get_globals();
88 // return (globals->uncaughtExceptions != 0);
Howard Hinnantffb308e2010-08-22 00:03:27 +000089#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000090}
91
Howard Hinnantffb308e2010-08-22 00:03:27 +000092namespace std
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000093{
94
Howard Hinnantffb308e2010-08-22 00:03:27 +000095exception::~exception() throw()
96{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000097}
98
Howard Hinnantffb308e2010-08-22 00:03:27 +000099bad_exception::~bad_exception() throw()
100{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000101}
102
103const char* exception::what() const throw()
104{
105 return "std::exception";
106}
107
108const char* bad_exception::what() const throw()
109{
110 return "std::bad_exception";
111}
112
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000113exception_ptr::~exception_ptr()
114{
115#if __APPLE__
116 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
117#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000118 #warning exception_ptr not yet implemented
119 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000120#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000121}
122
123exception_ptr::exception_ptr(const exception_ptr& other)
124 : __ptr_(other.__ptr_)
125{
126#if __APPLE__
127 __cxxabiapple::__cxa_increment_exception_refcount(__ptr_);
128#else
Howard Hinnant34468d42010-08-22 13:53:14 +0000129 #warning exception_ptr not yet implemented
130 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000131#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000132}
133
134exception_ptr& exception_ptr::operator=(const exception_ptr& other)
135{
136#if __APPLE__
137 if (__ptr_ != other.__ptr_)
138 {
139 __cxxabiapple::__cxa_increment_exception_refcount(other.__ptr_);
140 __cxxabiapple::__cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000141 __ptr_ = other.__ptr_;
142 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000143 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000144#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000145 #warning exception_ptr not yet implemented
146 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000147#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000148}
149
Howard Hinnante4f92722010-05-27 17:06:52 +0000150nested_exception::nested_exception()
151 : __ptr_(current_exception())
152{
153}
154
155nested_exception::~nested_exception()
156{
157}
158
159void
160nested_exception::rethrow_nested /*[[noreturn]]*/ () const
161{
162 if (__ptr_ == nullptr)
163 terminate();
164 rethrow_exception(__ptr_);
165}
166
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000167} // std
168
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000169std::exception_ptr std::current_exception()
170{
171#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000172 // be nicer if there was a constructor that took a ptr, then
173 // this whole function would be just:
174 // return exception_ptr(__cxa_current_primary_exception());
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000175 std::exception_ptr ptr;
Howard Hinnant34468d42010-08-22 13:53:14 +0000176 ptr.__ptr_ = __cxxabiapple::__cxa_current_primary_exception();
177 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000178#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000179 #warning exception_ptr not yet implemented
180 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000181#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000182}
183
184void std::rethrow_exception(exception_ptr p)
185{
186#if __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000187 __cxxabiapple::__cxa_rethrow_primary_exception(p.__ptr_);
188 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000189 terminate();
190#else // __APPLE__
Howard Hinnant34468d42010-08-22 13:53:14 +0000191 #warning exception_ptr not yet implemented
192 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000193#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000194}