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