blob: 96bd7ee59a02b0c48835b904bde2d02638d49782 [file] [log] [blame]
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00001//===------------------------ exception.cpp -------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnantee11c312010-11-16 22:09:02 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00007//
8//===----------------------------------------------------------------------===//
9#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000010#include <stdio.h>
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000011
12#include "exception"
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +000013#include "new"
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000014
Eric Fiselier224f9602017-01-02 22:27:45 +000015#if defined(__APPLE__) && !defined(LIBCXXRT)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000016 #include <cxxabi.h>
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000017
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000018 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000019 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000020 #ifndef _LIBCPPABI_VERSION
21 using namespace __cxxabiapple;
22 // On Darwin, there are two STL shared libraries and a lower level ABI
Marshall Clowf98383c2013-11-11 23:27:19 +000023 // shared library. The globals holding the current terminate handler and
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000024 // 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
Benjamin Krameraf9fc2c2015-10-16 11:14:30 +000028#elif defined(LIBCXXRT) || defined(LIBCXX_BUILDING_LIBCXXABI)
David Chisnall1d581062011-09-21 08:39:44 +000029 #include <cxxabi.h>
30 using namespace __cxxabiv1;
Richard Smithffd74672012-07-11 09:35:47 +000031 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
32 #define HAVE_DEPENDENT_EH_ABI 1
33 #endif
Benjamin Krameraf9fc2c2015-10-16 11:14:30 +000034#elif !defined(__GLIBCXX__) // defined(LIBCXX_BUILDING_LIBCXXABI)
Eric Fiselier637dd952016-09-28 22:08:13 +000035 _LIBCPP_SAFE_STATIC static std::terminate_handler __terminate_handler;
36 _LIBCPP_SAFE_STATIC static std::unexpected_handler __unexpected_handler;
Benjamin Krameraf9fc2c2015-10-16 11:14:30 +000037#endif // defined(LIBCXX_BUILDING_LIBCXXABI)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000038
David Chisnall3954f442012-02-29 12:59:17 +000039namespace std
40{
41
Michael J. Spencer7deadc82012-11-30 21:02:29 +000042#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000043
David Chisnall1d581062011-09-21 08:39:44 +000044// libcxxrt provides implementations of these functions itself.
David Chisnall3954f442012-02-29 12:59:17 +000045unexpected_handler
46set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000047{
Howard Hinnante65e8e32010-12-02 16:45:21 +000048 return __sync_lock_test_and_set(&__unexpected_handler, func);
49}
50
David Chisnall3954f442012-02-29 12:59:17 +000051unexpected_handler
52get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000053{
David Chisnall3954f442012-02-29 12:59:17 +000054 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000055}
56
Richard Smithcabd3922012-07-26 02:04:22 +000057_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000058void
David Chisnall3954f442012-02-29 12:59:17 +000059unexpected()
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000060{
David Chisnall3954f442012-02-29 12:59:17 +000061 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000062 // unexpected handler should not return
David Chisnall3954f442012-02-29 12:59:17 +000063 terminate();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000064}
65
David Chisnall3954f442012-02-29 12:59:17 +000066terminate_handler
67set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000068{
Howard Hinnante65e8e32010-12-02 16:45:21 +000069 return __sync_lock_test_and_set(&__terminate_handler, func);
70}
71
David Chisnall3954f442012-02-29 12:59:17 +000072terminate_handler
73get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000074{
David Chisnall3954f442012-02-29 12:59:17 +000075 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000076}
77
Marshall Cloweae03f62013-11-19 18:05:03 +000078#ifndef __EMSCRIPTEN__ // We provide this in JS
Richard Smithcabd3922012-07-26 02:04:22 +000079_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000080void
David Chisnall3954f442012-02-29 12:59:17 +000081terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000082{
Howard Hinnant72f73582010-08-11 17:04:31 +000083#ifndef _LIBCPP_NO_EXCEPTIONS
84 try
85 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000086#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall3954f442012-02-29 12:59:17 +000087 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000088 // handler should not return
Ed Schouten7a441452015-03-10 07:57:43 +000089 fprintf(stderr, "terminate_handler unexpectedly returned\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +000090 ::abort();
Howard Hinnant72f73582010-08-11 17:04:31 +000091#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +000092 }
Howard Hinnant72f73582010-08-11 17:04:31 +000093 catch (...)
94 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000095 // handler should not throw exception
Ed Schouten7a441452015-03-10 07:57:43 +000096 fprintf(stderr, "terminate_handler unexpectedly threw an exception\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +000097 ::abort();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000098 }
Howard Hinnantffb308e2010-08-22 00:03:27 +000099#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000100}
Marshall Cloweae03f62013-11-19 18:05:03 +0000101#endif // !__EMSCRIPTEN__
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000102#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000103
Marshall Clowe6a76af2015-06-02 22:25:23 +0000104#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(__EMSCRIPTEN__)
Marshall Clow209dacc2015-06-02 15:33:38 +0000105bool uncaught_exception() _NOEXCEPT { return uncaught_exceptions() > 0; }
106
Marshall Clow209dacc2015-06-02 15:33:38 +0000107int uncaught_exceptions() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000108{
Eric Fiselier224f9602017-01-02 22:27:45 +0000109#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
Marshall Clow209dacc2015-06-02 15:33:38 +0000110 // 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
Howard Hinnant3472f5b2012-02-29 15:37:30 +0000116#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000117# if defined(_MSC_VER) && ! defined(__clang__)
Marshall Clow209dacc2015-06-02 15:33:38 +0000118 _LIBCPP_WARNING("uncaught_exceptions not yet implemented")
Howard Hinnant408927e2013-10-04 21:14:44 +0000119# else
120# warning uncaught_exception not yet implemented
121# endif
Marshall Clow209dacc2015-06-02 15:33:38 +0000122 fprintf(stderr, "uncaught_exceptions not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000123 ::abort();
Howard Hinnantffb308e2010-08-22 00:03:27 +0000124#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000125}
126
Howard Hinnant408927e2013-10-04 21:14:44 +0000127
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000128#ifndef _LIBCPPABI_VERSION
129
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000130exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000131{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000132}
133
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000134const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000135{
136 return "std::exception";
137}
138
David Chisnallba252b82012-03-14 14:11:13 +0000139#endif // _LIBCPPABI_VERSION
140#endif //LIBCXXRT
Michael J. Spencer7deadc82012-11-30 21:02:29 +0000141#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnallba252b82012-03-14 14:11:13 +0000142
143bad_exception::~bad_exception() _NOEXCEPT
144{
145}
146
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000147const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000148{
149 return "std::bad_exception";
150}
151
David Chisnallba252b82012-03-14 14:11:13 +0000152#endif
153
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000154#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
165namespace __exception_ptr
166{
167
168struct 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
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000182
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000183exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000184{
David Chisnall1d581062011-09-21 08:39:44 +0000185#if HAVE_DEPENDENT_EH_ABI
186 __cxa_decrement_exception_refcount(__ptr_);
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000187#elif defined(__GLIBCXX__)
188 reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000189#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000190# 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
Ed Schouten7a441452015-03-10 07:57:43 +0000195 fprintf(stderr, "exception_ptr not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000196 ::abort();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000197#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000198}
199
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000200exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000201 : __ptr_(other.__ptr_)
202{
David Chisnall1d581062011-09-21 08:39:44 +0000203#if HAVE_DEPENDENT_EH_ABI
204 __cxa_increment_exception_refcount(__ptr_);
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000205#elif defined(__GLIBCXX__)
206 new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
207 reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000208#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000209# 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
Ed Schouten7a441452015-03-10 07:57:43 +0000214 fprintf(stderr, "exception_ptr not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000215 ::abort();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000216#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000217}
218
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000219exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000220{
David Chisnall1d581062011-09-21 08:39:44 +0000221#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000222 if (__ptr_ != other.__ptr_)
223 {
David Chisnall1d581062011-09-21 08:39:44 +0000224 __cxa_increment_exception_refcount(other.__ptr_);
225 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000226 __ptr_ = other.__ptr_;
227 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000228 return *this;
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000229#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
Howard Hinnant408927e2013-10-04 21:14:44 +0000234# 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
Ed Schouten7a441452015-03-10 07:57:43 +0000239 fprintf(stderr, "exception_ptr not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000240 ::abort();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000241#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000242}
243
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000244nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000245 : __ptr_(current_exception())
246{
247}
248
Peter Collingbournedc009952013-10-06 22:13:16 +0000249#if !defined(__GLIBCXX__)
250
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000251nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000252{
253}
254
Peter Collingbournedc009952013-10-06 22:13:16 +0000255#endif
256
Richard Smithcabd3922012-07-26 02:04:22 +0000257_LIBCPP_NORETURN
Howard Hinnante4f92722010-05-27 17:06:52 +0000258void
Howard Hinnant8df96292011-05-26 17:07:32 +0000259nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000260{
261 if (__ptr_ == nullptr)
262 terminate();
263 rethrow_exception(__ptr_);
264}
265
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000266#if !defined(__GLIBCXX__)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000267
David Chisnall3954f442012-02-29 12:59:17 +0000268exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000269{
David Chisnall1d581062011-09-21 08:39:44 +0000270#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000271 // 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());
David Chisnall3954f442012-02-29 12:59:17 +0000274 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000275 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000276 return ptr;
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000277#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000278# 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
Ed Schouten7a441452015-03-10 07:57:43 +0000283 fprintf(stderr, "exception_ptr not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000284 ::abort();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000285#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000286}
287
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000288#endif // !__GLIBCXX__
289
Richard Smithcabd3922012-07-26 02:04:22 +0000290_LIBCPP_NORETURN
David Chisnall3954f442012-02-29 12:59:17 +0000291void rethrow_exception(exception_ptr p)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000292{
David Chisnall1d581062011-09-21 08:39:44 +0000293#if HAVE_DEPENDENT_EH_ABI
294 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000295 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000296 terminate();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000297#elif defined(__GLIBCXX__)
298 rethrow_exception(reinterpret_cast<__exception_ptr::exception_ptr&>(p));
299#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000300# 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
Ed Schouten7a441452015-03-10 07:57:43 +0000305 fprintf(stderr, "exception_ptr not yet implemented\n");
Peter Collingbourne5f845a72013-10-06 22:13:24 +0000306 ::abort();
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000307#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000308}
David Chisnall3954f442012-02-29 12:59:17 +0000309} // std