]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/libc++/src/exception.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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 #ifndef __has_include
14 #define __has_include(inc) 0
15 #endif
16
17 #ifdef __APPLE__
18   #include <cxxabi.h>
19
20   using namespace __cxxabiv1;
21   #define HAVE_DEPENDENT_EH_ABI 1
22   #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
30 #elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
31   #include <cxxabi.h>
32   using namespace __cxxabiv1;
33   #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
34     #define HAVE_DEPENDENT_EH_ABI 1
35   #endif
36 #elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
37   static std::terminate_handler  __terminate_handler;
38   static std::unexpected_handler __unexpected_handler;
39 #endif // __has_include(<cxxabi.h>)
40
41 namespace std
42 {
43
44 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
45
46 // libcxxrt provides implementations of these functions itself.
47 unexpected_handler
48 set_unexpected(unexpected_handler func) _NOEXCEPT
49 {
50     return __sync_lock_test_and_set(&__unexpected_handler, func);
51 }
52
53 unexpected_handler
54 get_unexpected() _NOEXCEPT
55 {
56     return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
57 }
58
59 _LIBCPP_NORETURN
60 void
61 unexpected()
62 {
63     (*get_unexpected())();
64     // unexpected handler should not return
65     terminate();
66 }
67
68 terminate_handler
69 set_terminate(terminate_handler func) _NOEXCEPT
70 {
71     return __sync_lock_test_and_set(&__terminate_handler, func);
72 }
73
74 terminate_handler
75 get_terminate() _NOEXCEPT
76 {
77     return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
78 }
79
80 #ifndef EMSCRIPTEN // We provide this in JS
81 _LIBCPP_NORETURN
82 void
83 terminate() _NOEXCEPT
84 {
85 #ifndef _LIBCPP_NO_EXCEPTIONS
86     try
87     {
88 #endif  // _LIBCPP_NO_EXCEPTIONS
89         (*get_terminate())();
90         // handler should not return
91         ::abort ();
92 #ifndef _LIBCPP_NO_EXCEPTIONS
93     }
94     catch (...)
95     {
96         // handler should not throw exception
97         ::abort ();
98     }
99 #endif  // _LIBCPP_NO_EXCEPTIONS
100 }
101 #endif // !EMSCRIPTEN
102 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
103
104 #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN)
105 bool uncaught_exception() _NOEXCEPT
106 {
107 #if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
108     // on Darwin, there is a helper function so __cxa_get_globals is private
109     return __cxa_uncaught_exception();
110 #else  // __APPLE__
111     #warning uncaught_exception not yet implemented
112     ::abort();
113 #endif  // __APPLE__
114 }
115
116 #ifndef _LIBCPPABI_VERSION
117
118 exception::~exception() _NOEXCEPT
119 {
120 }
121
122 const char* exception::what() const _NOEXCEPT
123 {
124   return "std::exception";
125 }
126
127 #endif  // _LIBCPPABI_VERSION
128 #endif //LIBCXXRT
129 #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
130
131 bad_exception::~bad_exception() _NOEXCEPT
132 {
133 }
134
135 const char* bad_exception::what() const _NOEXCEPT
136 {
137   return "std::bad_exception";
138 }
139
140 #endif
141
142
143 exception_ptr::~exception_ptr() _NOEXCEPT
144 {
145 #if HAVE_DEPENDENT_EH_ABI
146     __cxa_decrement_exception_refcount(__ptr_);
147 #else
148     #warning exception_ptr not yet implemented
149     ::abort();
150 #endif  // __APPLE__
151 }
152
153 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
154     : __ptr_(other.__ptr_)
155 {
156 #if HAVE_DEPENDENT_EH_ABI
157     __cxa_increment_exception_refcount(__ptr_);
158 #else
159     #warning exception_ptr not yet implemented
160     ::abort();
161 #endif  // __APPLE__
162 }
163
164 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
165 {
166 #if HAVE_DEPENDENT_EH_ABI
167     if (__ptr_ != other.__ptr_)
168     {
169         __cxa_increment_exception_refcount(other.__ptr_);
170         __cxa_decrement_exception_refcount(__ptr_);
171         __ptr_ = other.__ptr_;
172     }
173     return *this;
174 #else  // __APPLE__
175     #warning exception_ptr not yet implemented
176     ::abort();
177 #endif  // __APPLE__
178 }
179
180 nested_exception::nested_exception() _NOEXCEPT
181     : __ptr_(current_exception())
182 {
183 }
184
185 nested_exception::~nested_exception() _NOEXCEPT
186 {
187 }
188
189 _LIBCPP_NORETURN
190 void
191 nested_exception::rethrow_nested() const
192 {
193     if (__ptr_ == nullptr)
194         terminate();
195     rethrow_exception(__ptr_);
196 }
197
198
199 exception_ptr current_exception() _NOEXCEPT
200 {
201 #if HAVE_DEPENDENT_EH_ABI
202     // 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());
205     exception_ptr ptr;
206     ptr.__ptr_ = __cxa_current_primary_exception();
207     return ptr;
208 #else  // __APPLE__
209     #warning exception_ptr not yet implemented
210     ::abort();
211 #endif  // __APPLE__
212 }
213
214 _LIBCPP_NORETURN
215 void rethrow_exception(exception_ptr p)
216 {
217 #if HAVE_DEPENDENT_EH_ABI
218     __cxa_rethrow_primary_exception(p.__ptr_);
219     // if p.__ptr_ is NULL, above returns so we terminate
220     terminate();
221 #else  // __APPLE__
222     #warning exception_ptr not yet implemented
223     ::abort();
224 #endif  // __APPLE__
225 }
226 } // std