blob: e080f7c8e517ea42380596bd9629408a4d5e2433 [file] [log] [blame]
Howard Hinnant408927e2013-10-04 21:14:44 +00001
2
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00003//===------------------------ exception.cpp -------------------------------===//
4//
5// The LLVM Compiler Infrastructure
6//
Howard Hinnantee11c312010-11-16 22:09:02 +00007// This file is dual licensed under the MIT and the University of Illinois Open
8// Source Licenses. See LICENSE.TXT for details.
Nick Kledzikd1a61bb2010-05-14 20:19:37 +00009//
10//===----------------------------------------------------------------------===//
11#include <stdlib.h>
Howard Hinnant84f697e2013-07-23 16:05:56 +000012#include <stdio.h>
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000013
14#include "exception"
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +000015#include "new"
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000016
Richard Smithffd74672012-07-11 09:35:47 +000017#ifndef __has_include
18#define __has_include(inc) 0
19#endif
20
Marshall Clowdde4bfe2013-03-18 17:45:34 +000021#ifdef __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000022 #include <cxxabi.h>
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000023
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000024 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000025 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000026 #ifndef _LIBCPPABI_VERSION
27 using namespace __cxxabiapple;
28 // On Darwin, there are two STL shared libraries and a lower level ABI
29 // shared libray. The globals holding the current terminate handler and
30 // current unexpected handler are in the ABI library.
31 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
32 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
33 #endif // _LIBCPPABI_VERSION
Richard Smithffd74672012-07-11 09:35:47 +000034#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
David Chisnall1d581062011-09-21 08:39:44 +000035 #include <cxxabi.h>
36 using namespace __cxxabiv1;
Richard Smithffd74672012-07-11 09:35:47 +000037 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
38 #define HAVE_DEPENDENT_EH_ABI 1
39 #endif
Howard Hinnant02fde3c2013-01-22 14:48:10 +000040#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000041 static std::terminate_handler __terminate_handler;
42 static std::unexpected_handler __unexpected_handler;
Richard Smithffd74672012-07-11 09:35:47 +000043#endif // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000044
Howard Hinnant408927e2013-10-04 21:14:44 +000045_LIBCPP_NORETURN
46static void _libcpp_abort(const char* msg)
47{
48 printf("%s\n", msg);
49 abort();
50}
51
David Chisnall3954f442012-02-29 12:59:17 +000052namespace std
53{
54
Michael J. Spencer7deadc82012-11-30 21:02:29 +000055#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000056
David Chisnall1d581062011-09-21 08:39:44 +000057// libcxxrt provides implementations of these functions itself.
David Chisnall3954f442012-02-29 12:59:17 +000058unexpected_handler
59set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000060{
Howard Hinnante65e8e32010-12-02 16:45:21 +000061 return __sync_lock_test_and_set(&__unexpected_handler, func);
62}
63
David Chisnall3954f442012-02-29 12:59:17 +000064unexpected_handler
65get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000066{
David Chisnall3954f442012-02-29 12:59:17 +000067 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000068}
69
Richard Smithcabd3922012-07-26 02:04:22 +000070_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000071void
David Chisnall3954f442012-02-29 12:59:17 +000072unexpected()
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000073{
David Chisnall3954f442012-02-29 12:59:17 +000074 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000075 // unexpected handler should not return
David Chisnall3954f442012-02-29 12:59:17 +000076 terminate();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000077}
78
David Chisnall3954f442012-02-29 12:59:17 +000079terminate_handler
80set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000081{
Howard Hinnante65e8e32010-12-02 16:45:21 +000082 return __sync_lock_test_and_set(&__terminate_handler, func);
83}
84
David Chisnall3954f442012-02-29 12:59:17 +000085terminate_handler
86get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000087{
David Chisnall3954f442012-02-29 12:59:17 +000088 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000089}
90
Howard Hinnant942dbd22013-03-29 18:27:28 +000091#ifndef EMSCRIPTEN // We provide this in JS
Richard Smithcabd3922012-07-26 02:04:22 +000092_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000093void
David Chisnall3954f442012-02-29 12:59:17 +000094terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000095{
Howard Hinnant72f73582010-08-11 17:04:31 +000096#ifndef _LIBCPP_NO_EXCEPTIONS
97 try
98 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000099#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall3954f442012-02-29 12:59:17 +0000100 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000101 // handler should not return
Howard Hinnant408927e2013-10-04 21:14:44 +0000102 _libcpp_abort("terminate_handler unexpectedly returned\n");
Howard Hinnant72f73582010-08-11 17:04:31 +0000103#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +0000104 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000105 catch (...)
106 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000107 // handler should not throw exception
Howard Hinnant408927e2013-10-04 21:14:44 +0000108 _libcpp_abort("terminate_handler unexpectedly threw an exception\n");
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000109 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000110#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000111}
Howard Hinnant942dbd22013-03-29 18:27:28 +0000112#endif // !EMSCRIPTEN
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000113#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000114
Howard Hinnant942dbd22013-03-29 18:27:28 +0000115#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN)
David Chisnall3954f442012-02-29 12:59:17 +0000116bool uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000117{
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000118#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
Howard Hinnant34468d42010-08-22 13:53:14 +0000119 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000120 return __cxa_uncaught_exception();
Howard Hinnant3472f5b2012-02-29 15:37:30 +0000121#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000122# if defined(_MSC_VER) && ! defined(__clang__)
123 _LIBCPP_WARNING("uncaught_exception not yet implemented")
124# else
125# warning uncaught_exception not yet implemented
126# endif
127 _libcpp_abort("uncaught_exception not yet implemented\n");
Howard Hinnantffb308e2010-08-22 00:03:27 +0000128#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000129}
130
Howard Hinnant408927e2013-10-04 21:14:44 +0000131
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000132#ifndef _LIBCPPABI_VERSION
133
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000134exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000135{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000136}
137
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000138const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000139{
140 return "std::exception";
141}
142
David Chisnallba252b82012-03-14 14:11:13 +0000143#endif // _LIBCPPABI_VERSION
144#endif //LIBCXXRT
Michael J. Spencer7deadc82012-11-30 21:02:29 +0000145#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnallba252b82012-03-14 14:11:13 +0000146
147bad_exception::~bad_exception() _NOEXCEPT
148{
149}
150
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000151const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000152{
153 return "std::bad_exception";
154}
155
David Chisnallba252b82012-03-14 14:11:13 +0000156#endif
157
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000158#if defined(__GLIBCXX__)
159
160// libsupc++ does not implement the dependent EH ABI and the functionality
161// it uses to implement std::exception_ptr (which it declares as an alias of
162// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
163// we have little choice but to hijack std::__exception_ptr::exception_ptr's
164// (which fortunately has the same layout as our std::exception_ptr) copy
165// constructor, assignment operator and destructor (which are part of its
166// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
167// function.
168
169namespace __exception_ptr
170{
171
172struct exception_ptr
173{
174 void* __ptr_;
175
176 exception_ptr(const exception_ptr&) _NOEXCEPT;
177 exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
178 ~exception_ptr() _NOEXCEPT;
179};
180
181}
182
183_LIBCPP_NORETURN void rethrow_exception(__exception_ptr::exception_ptr);
184
185#endif
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000186
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000187exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000188{
David Chisnall1d581062011-09-21 08:39:44 +0000189#if HAVE_DEPENDENT_EH_ABI
190 __cxa_decrement_exception_refcount(__ptr_);
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000191#elif defined(__GLIBCXX__)
192 reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000193#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000194# if defined(_MSC_VER) && ! defined(__clang__)
195 _LIBCPP_WARNING("exception_ptr not yet implemented")
196# else
197# warning exception_ptr not yet implemented
198# endif
199 _libcpp_abort("exception_ptr not yet implemented\n");
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000200#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000201}
202
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000203exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000204 : __ptr_(other.__ptr_)
205{
David Chisnall1d581062011-09-21 08:39:44 +0000206#if HAVE_DEPENDENT_EH_ABI
207 __cxa_increment_exception_refcount(__ptr_);
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000208#elif defined(__GLIBCXX__)
209 new (reinterpret_cast<void*>(this)) __exception_ptr::exception_ptr(
210 reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000211#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000212# if defined(_MSC_VER) && ! defined(__clang__)
213 _LIBCPP_WARNING("exception_ptr not yet implemented")
214# else
215# warning exception_ptr not yet implemented
216# endif
217 _libcpp_abort("exception_ptr not yet implemented\n");
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000218#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000219}
220
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000221exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000222{
David Chisnall1d581062011-09-21 08:39:44 +0000223#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000224 if (__ptr_ != other.__ptr_)
225 {
David Chisnall1d581062011-09-21 08:39:44 +0000226 __cxa_increment_exception_refcount(other.__ptr_);
227 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000228 __ptr_ = other.__ptr_;
229 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000230 return *this;
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000231#elif defined(__GLIBCXX__)
232 *reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
233 reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
234 return *this;
235#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000236# if defined(_MSC_VER) && ! defined(__clang__)
237 _LIBCPP_WARNING("exception_ptr not yet implemented")
238# else
239# warning exception_ptr not yet implemented
240# endif
241 _libcpp_abort("exception_ptr not yet implemented\n");
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000242#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000243}
244
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000245nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000246 : __ptr_(current_exception())
247{
248}
249
Peter Collingbournedc009952013-10-06 22:13:16 +0000250#if !defined(__GLIBCXX__)
251
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000252nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000253{
254}
255
Peter Collingbournedc009952013-10-06 22:13:16 +0000256#endif
257
Richard Smithcabd3922012-07-26 02:04:22 +0000258_LIBCPP_NORETURN
Howard Hinnante4f92722010-05-27 17:06:52 +0000259void
Howard Hinnant8df96292011-05-26 17:07:32 +0000260nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000261{
262 if (__ptr_ == nullptr)
263 terminate();
264 rethrow_exception(__ptr_);
265}
266
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000267#if !defined(__GLIBCXX__)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000268
David Chisnall3954f442012-02-29 12:59:17 +0000269exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000270{
David Chisnall1d581062011-09-21 08:39:44 +0000271#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000272 // be nicer if there was a constructor that took a ptr, then
273 // this whole function would be just:
274 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall3954f442012-02-29 12:59:17 +0000275 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000276 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000277 return ptr;
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000278#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000279# if defined(_MSC_VER) && ! defined(__clang__)
280 _LIBCPP_WARNING( "exception_ptr not yet implemented" )
281# else
282# warning exception_ptr not yet implemented
283# endif
284 _libcpp_abort("exception_ptr not yet implemented\n");
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
305 _libcpp_abort("exception_ptr not yet implemented\n");
Peter Collingbourne4d7da9a2013-10-06 22:13:21 +0000306#endif
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000307}
David Chisnall3954f442012-02-29 12:59:17 +0000308} // std