blob: dc6d04904bf422b1b141487b68315f3723ce1214 [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"
15
Richard Smithffd74672012-07-11 09:35:47 +000016#ifndef __has_include
17#define __has_include(inc) 0
18#endif
19
Marshall Clowdde4bfe2013-03-18 17:45:34 +000020#ifdef __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000021 #include <cxxabi.h>
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000022
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000023 using namespace __cxxabiv1;
David Chisnall1d581062011-09-21 08:39:44 +000024 #define HAVE_DEPENDENT_EH_ABI 1
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000025 #ifndef _LIBCPPABI_VERSION
26 using namespace __cxxabiapple;
27 // On Darwin, there are two STL shared libraries and a lower level ABI
28 // shared libray. The globals holding the current terminate handler and
29 // current unexpected handler are in the ABI library.
30 #define __terminate_handler __cxxabiapple::__cxa_terminate_handler
31 #define __unexpected_handler __cxxabiapple::__cxa_unexpected_handler
32 #endif // _LIBCPPABI_VERSION
Richard Smithffd74672012-07-11 09:35:47 +000033#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
David Chisnall1d581062011-09-21 08:39:44 +000034 #include <cxxabi.h>
35 using namespace __cxxabiv1;
Richard Smithffd74672012-07-11 09:35:47 +000036 #if defined(LIBCXXRT) || defined(_LIBCPPABI_VERSION)
37 #define HAVE_DEPENDENT_EH_ABI 1
38 #endif
Howard Hinnant02fde3c2013-01-22 14:48:10 +000039#elif !defined(__GLIBCXX__) // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000040 static std::terminate_handler __terminate_handler;
41 static std::unexpected_handler __unexpected_handler;
Richard Smithffd74672012-07-11 09:35:47 +000042#endif // __has_include(<cxxabi.h>)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000043
Howard Hinnant408927e2013-10-04 21:14:44 +000044_LIBCPP_NORETURN
45static void _libcpp_abort(const char* msg)
46{
47 printf("%s\n", msg);
48 abort();
49}
50
David Chisnall3954f442012-02-29 12:59:17 +000051namespace std
52{
53
Michael J. Spencer7deadc82012-11-30 21:02:29 +000054#if !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
Howard Hinnant4ad4eee2012-02-02 20:48:35 +000055
David Chisnall1d581062011-09-21 08:39:44 +000056// libcxxrt provides implementations of these functions itself.
David Chisnall3954f442012-02-29 12:59:17 +000057unexpected_handler
58set_unexpected(unexpected_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000059{
Howard Hinnante65e8e32010-12-02 16:45:21 +000060 return __sync_lock_test_and_set(&__unexpected_handler, func);
61}
62
David Chisnall3954f442012-02-29 12:59:17 +000063unexpected_handler
64get_unexpected() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000065{
David Chisnall3954f442012-02-29 12:59:17 +000066 return __sync_fetch_and_add(&__unexpected_handler, (unexpected_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000067}
68
Richard Smithcabd3922012-07-26 02:04:22 +000069_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000070void
David Chisnall3954f442012-02-29 12:59:17 +000071unexpected()
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000072{
David Chisnall3954f442012-02-29 12:59:17 +000073 (*get_unexpected())();
Howard Hinnant34468d42010-08-22 13:53:14 +000074 // unexpected handler should not return
David Chisnall3954f442012-02-29 12:59:17 +000075 terminate();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000076}
77
David Chisnall3954f442012-02-29 12:59:17 +000078terminate_handler
79set_terminate(terminate_handler func) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000080{
Howard Hinnante65e8e32010-12-02 16:45:21 +000081 return __sync_lock_test_and_set(&__terminate_handler, func);
82}
83
David Chisnall3954f442012-02-29 12:59:17 +000084terminate_handler
85get_terminate() _NOEXCEPT
Howard Hinnante65e8e32010-12-02 16:45:21 +000086{
David Chisnall3954f442012-02-29 12:59:17 +000087 return __sync_fetch_and_add(&__terminate_handler, (terminate_handler)0);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000088}
89
Howard Hinnant942dbd22013-03-29 18:27:28 +000090#ifndef EMSCRIPTEN // We provide this in JS
Richard Smithcabd3922012-07-26 02:04:22 +000091_LIBCPP_NORETURN
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000092void
David Chisnall3954f442012-02-29 12:59:17 +000093terminate() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +000094{
Howard Hinnant72f73582010-08-11 17:04:31 +000095#ifndef _LIBCPP_NO_EXCEPTIONS
96 try
97 {
Howard Hinnantffb308e2010-08-22 00:03:27 +000098#endif // _LIBCPP_NO_EXCEPTIONS
David Chisnall3954f442012-02-29 12:59:17 +000099 (*get_terminate())();
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000100 // handler should not return
Howard Hinnant408927e2013-10-04 21:14:44 +0000101 _libcpp_abort("terminate_handler unexpectedly returned\n");
Howard Hinnant72f73582010-08-11 17:04:31 +0000102#ifndef _LIBCPP_NO_EXCEPTIONS
Howard Hinnantffb308e2010-08-22 00:03:27 +0000103 }
Howard Hinnant72f73582010-08-11 17:04:31 +0000104 catch (...)
105 {
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000106 // handler should not throw exception
Howard Hinnant408927e2013-10-04 21:14:44 +0000107 _libcpp_abort("terminate_handler unexpectedly threw an exception\n");
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000108 }
Howard Hinnantffb308e2010-08-22 00:03:27 +0000109#endif // _LIBCPP_NO_EXCEPTIONS
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000110}
Howard Hinnant942dbd22013-03-29 18:27:28 +0000111#endif // !EMSCRIPTEN
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000112#endif // !defined(LIBCXXRT) && !defined(_LIBCPPABI_VERSION)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000113
Howard Hinnant942dbd22013-03-29 18:27:28 +0000114#if !defined(LIBCXXRT) && !defined(__GLIBCXX__) && !defined(EMSCRIPTEN)
David Chisnall3954f442012-02-29 12:59:17 +0000115bool uncaught_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000116{
Marshall Clowdde4bfe2013-03-18 17:45:34 +0000117#if defined(__APPLE__) || defined(_LIBCPPABI_VERSION)
Howard Hinnant34468d42010-08-22 13:53:14 +0000118 // on Darwin, there is a helper function so __cxa_get_globals is private
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000119 return __cxa_uncaught_exception();
Howard Hinnant3472f5b2012-02-29 15:37:30 +0000120#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000121# if defined(_MSC_VER) && ! defined(__clang__)
122 _LIBCPP_WARNING("uncaught_exception not yet implemented")
123# else
124# warning uncaught_exception not yet implemented
125# endif
126 _libcpp_abort("uncaught_exception not yet implemented\n");
Howard Hinnantffb308e2010-08-22 00:03:27 +0000127#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000128}
129
Howard Hinnant408927e2013-10-04 21:14:44 +0000130
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000131#ifndef _LIBCPPABI_VERSION
132
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000133exception::~exception() _NOEXCEPT
Howard Hinnantffb308e2010-08-22 00:03:27 +0000134{
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000135}
136
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000137const char* exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000138{
139 return "std::exception";
140}
141
David Chisnallba252b82012-03-14 14:11:13 +0000142#endif // _LIBCPPABI_VERSION
143#endif //LIBCXXRT
Michael J. Spencer7deadc82012-11-30 21:02:29 +0000144#if !defined(_LIBCPPABI_VERSION) && !defined(__GLIBCXX__)
David Chisnallba252b82012-03-14 14:11:13 +0000145
146bad_exception::~bad_exception() _NOEXCEPT
147{
148}
149
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000150const char* bad_exception::what() const _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000151{
152 return "std::bad_exception";
153}
154
David Chisnallba252b82012-03-14 14:11:13 +0000155#endif
156
Howard Hinnant4ad4eee2012-02-02 20:48:35 +0000157
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000158exception_ptr::~exception_ptr() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000159{
David Chisnall1d581062011-09-21 08:39:44 +0000160#if HAVE_DEPENDENT_EH_ABI
161 __cxa_decrement_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000162#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000163# if defined(_MSC_VER) && ! defined(__clang__)
164 _LIBCPP_WARNING("exception_ptr not yet implemented")
165# else
166# warning exception_ptr not yet implemented
167# endif
168 _libcpp_abort("exception_ptr not yet implemented\n");
Howard Hinnantffb308e2010-08-22 00:03:27 +0000169#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000170}
171
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000172exception_ptr::exception_ptr(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000173 : __ptr_(other.__ptr_)
174{
David Chisnall1d581062011-09-21 08:39:44 +0000175#if HAVE_DEPENDENT_EH_ABI
176 __cxa_increment_exception_refcount(__ptr_);
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000177#else
Howard Hinnant408927e2013-10-04 21:14:44 +0000178
179# if defined(_MSC_VER) && ! defined(__clang__)
180 _LIBCPP_WARNING("exception_ptr not yet implemented")
181# else
182# warning exception_ptr not yet implemented
183# endif
184 _libcpp_abort("exception_ptr not yet implemented\n");
185
Howard Hinnantffb308e2010-08-22 00:03:27 +0000186#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000187}
188
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000189exception_ptr& exception_ptr::operator=(const exception_ptr& other) _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000190{
David Chisnall1d581062011-09-21 08:39:44 +0000191#if HAVE_DEPENDENT_EH_ABI
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000192 if (__ptr_ != other.__ptr_)
193 {
David Chisnall1d581062011-09-21 08:39:44 +0000194 __cxa_increment_exception_refcount(other.__ptr_);
195 __cxa_decrement_exception_refcount(__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000196 __ptr_ = other.__ptr_;
197 }
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000198 return *this;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000199#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000200
201# if defined(_MSC_VER) && ! defined(__clang__)
202 _LIBCPP_WARNING("exception_ptr not yet implemented")
203# else
204# warning exception_ptr not yet implemented
205# endif
206 _libcpp_abort("exception_ptr not yet implemented\n");
207
Howard Hinnantffb308e2010-08-22 00:03:27 +0000208#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000209}
210
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000211nested_exception::nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000212 : __ptr_(current_exception())
213{
214}
215
Howard Hinnant1bc52cf2011-05-26 18:23:59 +0000216nested_exception::~nested_exception() _NOEXCEPT
Howard Hinnante4f92722010-05-27 17:06:52 +0000217{
218}
219
Richard Smithcabd3922012-07-26 02:04:22 +0000220_LIBCPP_NORETURN
Howard Hinnante4f92722010-05-27 17:06:52 +0000221void
Howard Hinnant8df96292011-05-26 17:07:32 +0000222nested_exception::rethrow_nested() const
Howard Hinnante4f92722010-05-27 17:06:52 +0000223{
224 if (__ptr_ == nullptr)
225 terminate();
226 rethrow_exception(__ptr_);
227}
228
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000229
David Chisnall3954f442012-02-29 12:59:17 +0000230exception_ptr current_exception() _NOEXCEPT
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000231{
David Chisnall1d581062011-09-21 08:39:44 +0000232#if HAVE_DEPENDENT_EH_ABI
Howard Hinnant34468d42010-08-22 13:53:14 +0000233 // be nicer if there was a constructor that took a ptr, then
234 // this whole function would be just:
235 // return exception_ptr(__cxa_current_primary_exception());
David Chisnall3954f442012-02-29 12:59:17 +0000236 exception_ptr ptr;
David Chisnall1d581062011-09-21 08:39:44 +0000237 ptr.__ptr_ = __cxa_current_primary_exception();
Howard Hinnant34468d42010-08-22 13:53:14 +0000238 return ptr;
Howard Hinnantffb308e2010-08-22 00:03:27 +0000239#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000240# if defined(_MSC_VER) && ! defined(__clang__)
241 _LIBCPP_WARNING( "exception_ptr not yet implemented" )
242# else
243# warning exception_ptr not yet implemented
244# endif
245 _libcpp_abort("exception_ptr not yet implemented\n");
Howard Hinnantffb308e2010-08-22 00:03:27 +0000246#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000247}
248
Richard Smithcabd3922012-07-26 02:04:22 +0000249_LIBCPP_NORETURN
David Chisnall3954f442012-02-29 12:59:17 +0000250void rethrow_exception(exception_ptr p)
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000251{
David Chisnall1d581062011-09-21 08:39:44 +0000252#if HAVE_DEPENDENT_EH_ABI
253 __cxa_rethrow_primary_exception(p.__ptr_);
Howard Hinnant34468d42010-08-22 13:53:14 +0000254 // if p.__ptr_ is NULL, above returns so we terminate
Howard Hinnantffb308e2010-08-22 00:03:27 +0000255 terminate();
256#else // __APPLE__
Howard Hinnant408927e2013-10-04 21:14:44 +0000257# if defined(_MSC_VER) && ! defined(__clang__)
258 _LIBCPP_WARNING("exception_ptr not yet implemented")
259# else
260# warning exception_ptr not yet implemented
261# endif
262 _libcpp_abort("exception_ptr not yet implemented\n");
Howard Hinnantffb308e2010-08-22 00:03:27 +0000263#endif // __APPLE__
Nick Kledzikd1a61bb2010-05-14 20:19:37 +0000264}
David Chisnall3954f442012-02-29 12:59:17 +0000265} // std