]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libc++/src/exception.cpp
Merge ^/head r312309 through r312623.
[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 #include <stdio.h>
11
12 #include "exception"
13 #include "new"
14
15 #if defined(_LIBCPP_ABI_MICROSOFT)
16 #include <eh.h>
17 #include <corecrt_terminate.h>
18 #elif defined(__APPLE__) && !defined(LIBCXXRT) && \
19     !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY)
20   #include <cxxabi.h>
21
22   using namespace __cxxabiv1;
23   #define HAVE_DEPENDENT_EH_ABI 1
24   #ifndef _LIBCPPABI_VERSION
25     using namespace __cxxabiapple;
26     // On Darwin, there are two STL shared libraries and a lower level ABI
27     // shared library.  The globals holding the current terminate handler and
28     // current unexpected handler are in the ABI library.
29     #define __terminate_handler  __cxxabiapple::__cxa_terminate_handler
30     #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
31   #endif  // _LIBCPPABI_VERSION
32 #elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
33   #include <cxxabi.h>
34   using namespace __cxxabiv1;
35   #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
36     #define HAVE_DEPENDENT_EH_ABI 1
37   #endif
38 #elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI)
39   _LIBCPP_SAFE_STATIC static std::terminate_handler  __terminate_handler;
40   _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
41 #endif // defined(LIBCXX_BUILDING_LIBCXXABI)
42
43 namespace std
44 {
45
46 #if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
47
48 // libcxxrt provides implementations of these functions itself.
49 unexpected_handler
50 set_unexpected(unexpected_handler func) _NOEXCEPT
51 {
52 #if defined(_LIBCPP_ABI_MICROSOFT)
53   return ::set_unexpected(func);
54 #else
55   return __sync_lock_test_and_set(&__unexpected_handler, func);
56 #endif
57 }
58
59 unexpected_handler
60 get_unexpected() _NOEXCEPT
61 {
62 #if defined(_LIBCPP_ABI_MICROSOFT)
63   return ::_get_unexpected();
64 #else
65   return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
66 #endif
67 }
68
69 _LIBCPP_NORETURN
70 void
71 unexpected()
72 {
73     (*get_unexpected())();
74     // unexpected handler should not return
75     terminate();
76 }
77
78 terminate_handler
79 set_terminate(terminate_handler func) _NOEXCEPT
80 {
81 #if defined(_LIBCPP_ABI_MICROSOFT)
82   return ::set_terminate(func);
83 #else
84   return __sync_lock_test_and_set(&__terminate_handler, func);
85 #endif
86 }
87
88 terminate_handler
89 get_terminate() _NOEXCEPT
90 {
91 #if defined(_LIBCPP_ABI_MICROSOFT)
92   return ::_get_terminate();
93 #else
94   return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
95 #endif
96 }
97
98 #ifndef __EMSCRIPTEN__ // We provide this in JS
99 _LIBCPP_NORETURN
100 void
101 terminate() _NOEXCEPT
102 {
103 #ifndef _LIBCPP_NO_EXCEPTIONS
104     try
105     {
106 #endif  // _LIBCPP_NO_EXCEPTIONS
107         (*get_terminate())();
108         // handler should not return
109         fprintf(stderr, "terminate_handler unexpectedly returned\n");
110         ::abort();
111 #ifndef _LIBCPP_NO_EXCEPTIONS
112     }
113     catch (...)
114     {
115         // handler should not throw exception
116         fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
117         ::abort();
118     }
119 #endif  // _LIBCPP_NO_EXCEPTIONS
120 }
121 #endif // !__EMSCRIPTEN__
122 #endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
123
124 #if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
125
126 bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
127
128 int uncaught_exceptions() _NOEXCEPT
129 {
130 #if !defined(_LIBCPP_BUILDING_HAS_NO_ABI_LIBRARY) && \
131     (defined(__APPLE__) || defined(_LIBCPPABI_VERSION))
132    // on Darwin, there is a helper function so __cxa_get_globals is private
133 # if _LIBCPPABI_VERSION > 1101
134     return __cxa_uncaught_exceptions();
135 # else
136     return __cxa_uncaught_exception() ? 1 : 0;
137 # endif
138 #elif defined(_LIBCPP_ABI_MICROSOFT)
139     return __uncaught_exceptions();
140 #else
141 #   if defined(_MSC_VER) && ! defined(__clang__)
142         _LIBCPP_WARNING("uncaught_exceptions not yet implemented")
143 #   else
144 #       warning uncaught_exception not yet implemented
145 #   endif
146     fprintf(stderr, "uncaught_exceptions not yet implemented\n");
147     ::abort();
148 #endif  // __APPLE__
149 }
150
151
152 #ifndef _LIBCPPABI_VERSION
153
154 exception::~exception() _NOEXCEPT
155 {
156 }
157
158 const char* exception::what() const _NOEXCEPT
159 {
160   return "std::exception";
161 }
162
163 #endif  // _LIBCPPABI_VERSION
164 #endif //LIBCXXRT
165 #if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
166
167 bad_exception::~bad_exception() _NOEXCEPT
168 {
169 }
170
171 const char* bad_exception::what() const _NOEXCEPT
172 {
173   return "std::bad_exception";
174 }
175
176 #endif
177
178 #if defined(__GLIBCXX__)
179
180 // libsupc++ does not implement the dependent EH ABI and the functionality
181 // it uses to implement std::exception_ptr (which it declares as an alias of
182 // std::__exception_ptr::exception_ptr) is not directly exported to clients. So
183 // we have little choice but to hijack std::__exception_ptr::exception_ptr's
184 // (which fortunately has the same layout as our std::exception_ptr) copy
185 // constructor, assignment operator and destructor (which are part of its
186 // stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
187 // function.
188
189 namespace __exception_ptr
190 {
191
192 struct exception_ptr
193 {
194     void* __ptr_;
195
196     exception_ptr(const exception_ptr&) _NOEXCEPT;
197     exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
198     ~exception_ptr() _NOEXCEPT;
199 };
200
201 }
202
203 _LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
204
205 #endif
206
207 exception_ptr::~exception_ptr() _NOEXCEPT
208 {
209 #if HAVE_DEPENDENT_EH_ABI
210     __cxa_decrement_exception_refcount(__ptr_);
211 #elif defined(__GLIBCXX__)
212     reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
213 #else
214 #   if defined(_MSC_VER) && ! defined(__clang__)
215         _LIBCPP_WARNING("exception_ptr not yet implemented")
216 #   else
217 #       warning exception_ptr not yet implemented
218 #   endif
219     fprintf(stderr, "exception_ptr not yet implemented\n");
220     ::abort();
221 #endif
222 }
223
224 exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
225     : __ptr_(other.__ptr_)
226 {
227 #if HAVE_DEPENDENT_EH_ABI
228     __cxa_increment_exception_refcount(__ptr_);
229 #elif defined(__GLIBCXX__)
230     new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
231         reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
232 #else
233 #   if defined(_MSC_VER) && ! defined(__clang__)
234         _LIBCPP_WARNING("exception_ptr not yet implemented")
235 #   else
236 #       warning exception_ptr not yet implemented
237 #   endif
238     fprintf(stderr, "exception_ptr not yet implemented\n");
239     ::abort();
240 #endif
241 }
242
243 exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
244 {
245 #if HAVE_DEPENDENT_EH_ABI
246     if (__ptr_ != other.__ptr_)
247     {
248         __cxa_increment_exception_refcount(other.__ptr_);
249         __cxa_decrement_exception_refcount(__ptr_);
250         __ptr_ = other.__ptr_;
251     }
252     return *this;
253 #elif defined(__GLIBCXX__)
254     *reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
255         reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
256     return *this;
257 #else
258 #   if defined(_MSC_VER) && ! defined(__clang__)
259         _LIBCPP_WARNING("exception_ptr not yet implemented")
260 #   else
261 #       warning exception_ptr not yet implemented
262 #   endif
263     fprintf(stderr, "exception_ptr not yet implemented\n");
264     ::abort();
265 #endif
266 }
267
268 nested_exception::nested_exception() _NOEXCEPT
269     : __ptr_(current_exception())
270 {
271 }
272
273 #if !defined(__GLIBCXX__)
274
275 nested_exception::~nested_exception() _NOEXCEPT
276 {
277 }
278
279 #endif
280
281 _LIBCPP_NORETURN
282 void
283 nested_exception::rethrow_nested() const
284 {
285     if (__ptr_ == nullptr)
286         terminate();
287     rethrow_exception(__ptr_);
288 }
289
290 #if !defined(__GLIBCXX__)
291
292 exception_ptr current_exception() _NOEXCEPT
293 {
294 #if HAVE_DEPENDENT_EH_ABI
295     // be nicer if there was a constructor that took a ptr, then
296     // this whole function would be just:
297     //    return exception_ptr(__cxa_current_primary_exception());
298     exception_ptr ptr;
299     ptr.__ptr_ = __cxa_current_primary_exception();
300     return ptr;
301 #else
302 #   if defined(_MSC_VER) && ! defined(__clang__)
303         _LIBCPP_WARNING( "exception_ptr not yet implemented" )
304 #   else
305 #       warning exception_ptr not yet implemented
306 #   endif
307     fprintf(stderr, "exception_ptr not yet implemented\n");
308     ::abort();
309 #endif
310 }
311
312 #endif  // !__GLIBCXX__
313
314 _LIBCPP_NORETURN
315 void rethrow_exception(exception_ptr p)
316 {
317 #if HAVE_DEPENDENT_EH_ABI
318     __cxa_rethrow_primary_exception(p.__ptr_);
319     // if p.__ptr_ is NULL, above returns so we terminate
320     terminate();
321 #elif defined(__GLIBCXX__)
322     rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
323 #else
324 #   if defined(_MSC_VER) && ! defined(__clang__)
325         _LIBCPP_WARNING("exception_ptr not yet implemented")
326 #   else
327 #       warning exception_ptr not yet implemented
328 #   endif
329     fprintf(stderr, "exception_ptr not yet implemented\n");
330     ::abort();
331 #endif
332 }
333 } // std