]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/src/exception.cpp
Update libarchive to 3.0.3
[FreeBSD/FreeBSD.git] / contrib / libc++ / src / exception.cpp
1 //===------------------------ exception.cpp -------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include <stdlib.h>
10
11 #include "exception"
12
13 #if __APPLE__
14   #include <cxxabi.h>
15   using namespace __cxxabiv1;
16   using namespace __cxxabiapple;
17   // On Darwin, there are two STL shared libraries and a lower level ABI
18   // shared libray.  The globals holding the current terminate handler and
19   // current unexpected handler are in the ABI library.
20   #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
21   #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
22   #define HAVE_DEPENDENT_EH_ABI 1
23 #elif defined(LIBCXXRT)
24   #include <cxxabi.h>
25   using namespace __cxxabiv1;
26   #define HAVE_DEPENDENT_EH_ABI 1
27 #else  // __APPLE__
28   static std::terminate_handler  __terminate_handler;
29   static std::unexpected_handler __unexpected_handler;
30 #endif  // __APPLE__
31
32 #ifndef LIBCXXRT
33 // libcxxrt provides implementations of these functions itself.
34 std::unexpected_handler
35 std::set_unexpected(std::unexpected_handler func) _NOEXCEPT
36 {
37     return __sync_lock_test_and_set(&__unexpected_handler, func);
38 }
39
40 std::unexpected_handler
41 std::get_unexpected() _NOEXCEPT
42 {
43     return __sync_fetch_and_add(&__unexpected_handler, (std::unexpected_handler)0);
44 }
45
46 _ATTRIBUTE(noreturn)
47 void
48 std::unexpected()
49 {
50     (*std::get_unexpected())();
51     // unexpected handler should not return
52     std::terminate();
53 }
54
55 std::terminate_handler
56 std::set_terminate(std::terminate_handler func) _NOEXCEPT
57 {
58     return __sync_lock_test_and_set(&__terminate_handler, func);
59 }
60
61 std::terminate_handler
62 std::get_terminate() _NOEXCEPT
63 {
64     return __sync_fetch_and_add(&__terminate_handler, (std::terminate_handler)0);
65 }
66
67 _ATTRIBUTE(noreturn)
68 void
69 std::terminate() _NOEXCEPT
70 {
71 #ifndef _LIBCPP_NO_EXCEPTIONS
72     try
73     {
74 #endif  // _LIBCPP_NO_EXCEPTIONS
75         (*std::get_terminate())();
76         // handler should not return
77         ::abort ();
78 #ifndef _LIBCPP_NO_EXCEPTIONS
79     }
80     catch (...)
81     {
82         // handler should not throw exception
83         ::abort ();
84     }
85 #endif  // _LIBCPP_NO_EXCEPTIONS
86 }
87 #endif // LIBCXXRT
88
89 bool std::uncaught_exception() _NOEXCEPT
90 {
91 #if __APPLE__
92     // on Darwin, there is a helper function so __cxa_get_globals is private
93     return __cxxabiapple::__cxa_uncaught_exception();
94 #elif LIBCXXRT
95     __cxa_eh_globals * globals = __cxa_get_globals();
96     return (globals->uncaughtExceptions != 0);
97 #else  // __APPLE__
98     #warning uncaught_exception not yet implemented
99     ::abort();
100 #endif  // __APPLE__
101 }
102
103 namespace std
104 {
105
106 exception::~exception() _NOEXCEPT
107 {
108 }
109
110 bad_exception::~bad_exception() _NOEXCEPT
111 {
112 }
113
114 const char* exception::what() const _NOEXCEPT
115 {
116   return "std::exception";
117 }
118
119 const char* bad_exception::what() const _NOEXCEPT
120 {
121   return "std::bad_exception";
122 }
123
124 exception_ptr::~exception_ptr() _NOEXCEPT
125 {
126 #if HAVE_DEPENDENT_EH_ABI
127     __cxa_decrement_exception_refcount(__ptr_);
128 #else
129     #warning exception_ptr not yet implemented
130     ::abort();
131 #endif  // __APPLE__
132 }
133
134 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
135     : __ptr_(other.__ptr_)
136 {
137 #if HAVE_DEPENDENT_EH_ABI
138     __cxa_increment_exception_refcount(__ptr_);
139 #else
140     #warning exception_ptr not yet implemented
141     ::abort();
142 #endif  // __APPLE__
143 }
144
145 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
146 {
147 #if HAVE_DEPENDENT_EH_ABI
148     if (__ptr_ != other.__ptr_)
149     {
150         __cxa_increment_exception_refcount(other.__ptr_);
151         __cxa_decrement_exception_refcount(__ptr_);
152         __ptr_ = other.__ptr_;
153     }
154     return *this;
155 #else  // __APPLE__
156     #warning exception_ptr not yet implemented
157     ::abort();
158 #endif  // __APPLE__
159 }
160
161 nested_exception::nested_exception() _NOEXCEPT
162     : __ptr_(current_exception())
163 {
164 }
165
166 nested_exception::~nested_exception() _NOEXCEPT
167 {
168 }
169
170 _ATTRIBUTE(noreturn)
171 void
172 nested_exception::rethrow_nested() const
173 {
174     if (__ptr_ == nullptr)
175         terminate();
176     rethrow_exception(__ptr_);
177 }
178
179 } // std
180
181 std::exception_ptr std::current_exception() _NOEXCEPT
182 {
183 #if HAVE_DEPENDENT_EH_ABI
184     // be nicer if there was a constructor that took a ptr, then
185     // this whole function would be just:
186     //    return exception_ptr(__cxa_current_primary_exception());
187     std::exception_ptr ptr;
188     ptr.__ptr_ = __cxa_current_primary_exception();
189     return ptr;
190 #else  // __APPLE__
191     #warning exception_ptr not yet implemented
192     ::abort();
193 #endif  // __APPLE__
194 }
195
196 void std::rethrow_exception(exception_ptr p)
197 {
198 #if HAVE_DEPENDENT_EH_ABI
199     __cxa_rethrow_primary_exception(p.__ptr_);
200     // if p.__ptr_ is NULL, above returns so we terminate
201     terminate();
202 #else  // __APPLE__
203     #warning exception_ptr not yet implemented
204     ::abort();
205 #endif  // __APPLE__
206 }