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