17a984708SDavid Chisnall// -*- C++ -*-
27a984708SDavid Chisnall//===-------------------------- exception ---------------------------------===//
37a984708SDavid Chisnall//
47a984708SDavid Chisnall//                     The LLVM Compiler Infrastructure
57a984708SDavid Chisnall//
67a984708SDavid Chisnall// This file is dual licensed under the MIT and the University of Illinois Open
77a984708SDavid Chisnall// Source Licenses. See LICENSE.TXT for details.
87a984708SDavid Chisnall//
97a984708SDavid Chisnall//===----------------------------------------------------------------------===//
107a984708SDavid Chisnall
117a984708SDavid Chisnall#ifndef _LIBCPP_EXCEPTION
127a984708SDavid Chisnall#define _LIBCPP_EXCEPTION
137a984708SDavid Chisnall
147a984708SDavid Chisnall/*
157a984708SDavid Chisnall    exception synopsis
167a984708SDavid Chisnall
177a984708SDavid Chisnallnamespace std
187a984708SDavid Chisnall{
197a984708SDavid Chisnall
207a984708SDavid Chisnallclass exception
217a984708SDavid Chisnall{
227a984708SDavid Chisnallpublic:
237a984708SDavid Chisnall    exception() noexcept;
247a984708SDavid Chisnall    exception(const exception&) noexcept;
257a984708SDavid Chisnall    exception& operator=(const exception&) noexcept;
267a984708SDavid Chisnall    virtual ~exception() noexcept;
277a984708SDavid Chisnall    virtual const char* what() const noexcept;
287a984708SDavid Chisnall};
297a984708SDavid Chisnall
307a984708SDavid Chisnallclass bad_exception
317a984708SDavid Chisnall    : public exception
327a984708SDavid Chisnall{
337a984708SDavid Chisnallpublic:
347a984708SDavid Chisnall    bad_exception() noexcept;
357a984708SDavid Chisnall    bad_exception(const bad_exception&) noexcept;
367a984708SDavid Chisnall    bad_exception& operator=(const bad_exception&) noexcept;
377a984708SDavid Chisnall    virtual ~bad_exception() noexcept;
387a984708SDavid Chisnall    virtual const char* what() const noexcept;
397a984708SDavid Chisnall};
407a984708SDavid Chisnall
417a984708SDavid Chisnalltypedef void (*unexpected_handler)();
427a984708SDavid Chisnallunexpected_handler set_unexpected(unexpected_handler  f ) noexcept;
437a984708SDavid Chisnallunexpected_handler get_unexpected() noexcept;
447a984708SDavid Chisnall[[noreturn]] void unexpected();
457a984708SDavid Chisnall
467a984708SDavid Chisnalltypedef void (*terminate_handler)();
477a984708SDavid Chisnallterminate_handler set_terminate(terminate_handler  f ) noexcept;
487a984708SDavid Chisnallterminate_handler get_terminate() noexcept;
497a984708SDavid Chisnall[[noreturn]] void terminate() noexcept;
507a984708SDavid Chisnall
517a984708SDavid Chisnallbool uncaught_exception()  noexcept;
52854fa44bSDimitry Andricint  uncaught_exceptions() noexcept;  // C++17
537a984708SDavid Chisnall
547a984708SDavid Chisnalltypedef unspecified exception_ptr;
557a984708SDavid Chisnall
567a984708SDavid Chisnallexception_ptr current_exception() noexcept;
577a984708SDavid Chisnallvoid rethrow_exception [[noreturn]] (exception_ptr p);
587a984708SDavid Chisnalltemplate<class E> exception_ptr make_exception_ptr(E e) noexcept;
597a984708SDavid Chisnall
607a984708SDavid Chisnallclass nested_exception
617a984708SDavid Chisnall{
627a984708SDavid Chisnallpublic:
637a984708SDavid Chisnall    nested_exception() noexcept;
647a984708SDavid Chisnall    nested_exception(const nested_exception&) noexcept = default;
657a984708SDavid Chisnall    nested_exception& operator=(const nested_exception&) noexcept = default;
667a984708SDavid Chisnall    virtual ~nested_exception() = default;
677a984708SDavid Chisnall
687a984708SDavid Chisnall    // access functions
697a984708SDavid Chisnall    [[noreturn]] void rethrow_nested() const;
707a984708SDavid Chisnall    exception_ptr nested_ptr() const noexcept;
717a984708SDavid Chisnall};
727a984708SDavid Chisnall
737a984708SDavid Chisnalltemplate <class T> [[noreturn]] void throw_with_nested(T&& t);
747a984708SDavid Chisnalltemplate <class E> void rethrow_if_nested(const E& e);
757a984708SDavid Chisnall
767a984708SDavid Chisnall}  // std
777a984708SDavid Chisnall
787a984708SDavid Chisnall*/
797a984708SDavid Chisnall
807a984708SDavid Chisnall#include <__config>
817a984708SDavid Chisnall#include <cstddef>
82067a6c9eSDimitry Andric#include <cstdlib>
83aed8d94eSDimitry Andric#include <type_traits>
84*b5893f02SDimitry Andric#include <version>
857a984708SDavid Chisnall
86b2c7081bSDimitry Andric#if defined(_LIBCPP_ABI_MICROSOFT) && !defined(_LIBCPP_NO_VCRUNTIME)
87540d2a8bSDimitry Andric#include <vcruntime_exception.h>
88540d2a8bSDimitry Andric#endif
89540d2a8bSDimitry Andric
907a984708SDavid Chisnall#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
917a984708SDavid Chisnall#pragma GCC system_header
927a984708SDavid Chisnall#endif
937a984708SDavid Chisnall
947a984708SDavid Chisnallnamespace std  // purposefully not using versioning namespace
957a984708SDavid Chisnall{
967a984708SDavid Chisnall
97b2c7081bSDimitry Andric#if !defined(_LIBCPP_ABI_MICROSOFT) || defined(_LIBCPP_NO_VCRUNTIME)
987a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI exception
997a984708SDavid Chisnall{
1007a984708SDavid Chisnallpublic:
1017a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {}
1027a984708SDavid Chisnall    virtual ~exception() _NOEXCEPT;
1037a984708SDavid Chisnall    virtual const char* what() const _NOEXCEPT;
1047a984708SDavid Chisnall};
1057a984708SDavid Chisnall
1067a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI bad_exception
1077a984708SDavid Chisnall    : public exception
1087a984708SDavid Chisnall{
1097a984708SDavid Chisnallpublic:
1107a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {}
1117a984708SDavid Chisnall    virtual ~bad_exception() _NOEXCEPT;
1127a984708SDavid Chisnall    virtual const char* what() const _NOEXCEPT;
1137a984708SDavid Chisnall};
114b2c7081bSDimitry Andric#endif // !_LIBCPP_ABI_MICROSOFT || _LIBCPP_NO_VCRUNTIME
1157a984708SDavid Chisnall
116540d2a8bSDimitry Andric#if _LIBCPP_STD_VER <= 14 \
117540d2a8bSDimitry Andric    || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \
118540d2a8bSDimitry Andric    || defined(_LIBCPP_BUILDING_LIBRARY)
1197a984708SDavid Chisnalltypedef void (*unexpected_handler)();
1201bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
1211bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT;
1221bf9f7c1SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected();
123540d2a8bSDimitry Andric#endif
1247a984708SDavid Chisnall
1257a984708SDavid Chisnalltypedef void (*terminate_handler)();
1261bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
1271bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;
1281bf9f7c1SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
1297a984708SDavid Chisnall
1301bf9f7c1SDimitry Andric_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
1310f5676f4SDimitry Andric_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT;
1327a984708SDavid Chisnall
1331bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr;
1347a984708SDavid Chisnall
1354f7ab58eSDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
1364f7ab58eSDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
1377a984708SDavid Chisnall
1380f5676f4SDimitry Andric#ifndef _LIBCPP_ABI_MICROSOFT
1390f5676f4SDimitry Andric
1401bf9f7c1SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr
1417a984708SDavid Chisnall{
1427a984708SDavid Chisnall    void* __ptr_;
1437a984708SDavid Chisnallpublic:
1447a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
1457a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
1460f5676f4SDimitry Andric
1477a984708SDavid Chisnall    exception_ptr(const exception_ptr&) _NOEXCEPT;
1487a984708SDavid Chisnall    exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
1497a984708SDavid Chisnall    ~exception_ptr() _NOEXCEPT;
1507a984708SDavid Chisnall
1510f5676f4SDimitry Andric    _LIBCPP_INLINE_VISIBILITY _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT
1520f5676f4SDimitry Andric    {return __ptr_ != nullptr;}
1537a984708SDavid Chisnall
1547a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
1557a984708SDavid Chisnall    bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
1567a984708SDavid Chisnall        {return __x.__ptr_ == __y.__ptr_;}
1570f5676f4SDimitry Andric
1587a984708SDavid Chisnall    friend _LIBCPP_INLINE_VISIBILITY
1597a984708SDavid Chisnall    bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
1607a984708SDavid Chisnall        {return !(__x == __y);}
1617a984708SDavid Chisnall
1624f7ab58eSDimitry Andric    friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
1634f7ab58eSDimitry Andric    friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
1647a984708SDavid Chisnall};
1657a984708SDavid Chisnall
16694e3ee44SDavid Chisnalltemplate<class _Ep>
167*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr
16894e3ee44SDavid Chisnallmake_exception_ptr(_Ep __e) _NOEXCEPT
1697a984708SDavid Chisnall{
1707a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
1717a984708SDavid Chisnall    try
1727a984708SDavid Chisnall    {
1737a984708SDavid Chisnall        throw __e;
1747a984708SDavid Chisnall    }
1757a984708SDavid Chisnall    catch (...)
1767a984708SDavid Chisnall    {
1777a984708SDavid Chisnall        return current_exception();
1787a984708SDavid Chisnall    }
179aed8d94eSDimitry Andric#else
180aed8d94eSDimitry Andric    ((void)__e);
181aed8d94eSDimitry Andric    _VSTD::abort();
182aed8d94eSDimitry Andric#endif
1837a984708SDavid Chisnall}
1847a984708SDavid Chisnall
1850f5676f4SDimitry Andric#else // _LIBCPP_ABI_MICROSOFT
1860f5676f4SDimitry Andric
1870f5676f4SDimitry Andricclass _LIBCPP_TYPE_VIS exception_ptr
1880f5676f4SDimitry Andric{
1890f5676f4SDimitry Andric#if defined(__clang__)
1900f5676f4SDimitry Andric#pragma clang diagnostic push
1910f5676f4SDimitry Andric#pragma clang diagnostic ignored "-Wunused-private-field"
1920f5676f4SDimitry Andric#endif
1930f5676f4SDimitry Andric    void* __ptr1_;
1940f5676f4SDimitry Andric    void* __ptr2_;
1950f5676f4SDimitry Andric#if defined(__clang__)
1960f5676f4SDimitry Andric#pragma clang diagnostic pop
1970f5676f4SDimitry Andric#endif
1980f5676f4SDimitry Andricpublic:
1990f5676f4SDimitry Andric    exception_ptr() _NOEXCEPT;
2000f5676f4SDimitry Andric    exception_ptr(nullptr_t) _NOEXCEPT;
2010f5676f4SDimitry Andric    exception_ptr(const exception_ptr& __other) _NOEXCEPT;
2020f5676f4SDimitry Andric    exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
2030f5676f4SDimitry Andric    exception_ptr& operator=(nullptr_t) _NOEXCEPT;
2040f5676f4SDimitry Andric    ~exception_ptr() _NOEXCEPT;
2050f5676f4SDimitry Andric    _LIBCPP_EXPLICIT operator bool() const _NOEXCEPT;
2060f5676f4SDimitry Andric};
2070f5676f4SDimitry Andric
2080f5676f4SDimitry Andric_LIBCPP_FUNC_VIS
2090f5676f4SDimitry Andricbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;
2100f5676f4SDimitry Andric
2110f5676f4SDimitry Andricinline _LIBCPP_INLINE_VISIBILITY
2120f5676f4SDimitry Andricbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
2130f5676f4SDimitry Andric    {return !(__x == __y);}
2140f5676f4SDimitry Andric
2150f5676f4SDimitry Andric_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT;
2160f5676f4SDimitry Andric
2170f5676f4SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr);
2180f5676f4SDimitry Andric_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
2190f5676f4SDimitry Andric_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr p);
2200f5676f4SDimitry Andric
2210f5676f4SDimitry Andric// This is a built-in template function which automagically extracts the required
2220f5676f4SDimitry Andric// information.
2230f5676f4SDimitry Andrictemplate <class _E> void *__GetExceptionInfo(_E);
2240f5676f4SDimitry Andric
2250f5676f4SDimitry Andrictemplate<class _Ep>
226*b5893f02SDimitry Andric_LIBCPP_INLINE_VISIBILITY exception_ptr
2270f5676f4SDimitry Andricmake_exception_ptr(_Ep __e) _NOEXCEPT
2280f5676f4SDimitry Andric{
2290f5676f4SDimitry Andric  return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
2300f5676f4SDimitry Andric}
2310f5676f4SDimitry Andric
2320f5676f4SDimitry Andric#endif // _LIBCPP_ABI_MICROSOFT
2337a984708SDavid Chisnall// nested_exception
2347a984708SDavid Chisnall
2357a984708SDavid Chisnallclass _LIBCPP_EXCEPTION_ABI nested_exception
2367a984708SDavid Chisnall{
2377a984708SDavid Chisnall    exception_ptr __ptr_;
2387a984708SDavid Chisnallpublic:
2397a984708SDavid Chisnall    nested_exception() _NOEXCEPT;
2407a984708SDavid Chisnall//     nested_exception(const nested_exception&) noexcept = default;
2417a984708SDavid Chisnall//     nested_exception& operator=(const nested_exception&) noexcept = default;
2427a984708SDavid Chisnall    virtual ~nested_exception() _NOEXCEPT;
2437a984708SDavid Chisnall
2447a984708SDavid Chisnall    // access functions
245936e9439SDimitry Andric    _LIBCPP_NORETURN void rethrow_nested() const;
2467a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;}
2477a984708SDavid Chisnall};
2487a984708SDavid Chisnall
2497a984708SDavid Chisnalltemplate <class _Tp>
2507a984708SDavid Chisnallstruct __nested
2517a984708SDavid Chisnall    : public _Tp,
2527a984708SDavid Chisnall      public nested_exception
2537a984708SDavid Chisnall{
2547a984708SDavid Chisnall    _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {}
2557a984708SDavid Chisnall};
2567a984708SDavid Chisnall
2577a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
258540d2a8bSDimitry Andrictemplate <class _Tp, class _Up, bool>
259540d2a8bSDimitry Andricstruct __throw_with_nested;
260540d2a8bSDimitry Andric
261540d2a8bSDimitry Andrictemplate <class _Tp, class _Up>
262540d2a8bSDimitry Andricstruct __throw_with_nested<_Tp, _Up, true> {
2634ba319b5SDimitry Andric    _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void
264540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
265540d2a8bSDimitry Andric    __do_throw(_Tp&& __t)
266aed8d94eSDimitry Andric#else
267540d2a8bSDimitry Andric    __do_throw (_Tp& __t)
268540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
269540d2a8bSDimitry Andric    {
270540d2a8bSDimitry Andric        throw __nested<_Up>(_VSTD::forward<_Tp>(__t));
2717a984708SDavid Chisnall    }
272540d2a8bSDimitry Andric};
273540d2a8bSDimitry Andric
274540d2a8bSDimitry Andrictemplate <class _Tp, class _Up>
275540d2a8bSDimitry Andricstruct __throw_with_nested<_Tp, _Up, false> {
2764ba319b5SDimitry Andric    _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void
277540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
278540d2a8bSDimitry Andric    __do_throw(_Tp&& __t)
279540d2a8bSDimitry Andric#else
280540d2a8bSDimitry Andric    __do_throw (_Tp& __t)
281540d2a8bSDimitry Andric#endif  // _LIBCPP_CXX03_LANG
282540d2a8bSDimitry Andric    {
283540d2a8bSDimitry Andric        throw _VSTD::forward<_Tp>(__t);
284540d2a8bSDimitry Andric    }
285540d2a8bSDimitry Andric};
286540d2a8bSDimitry Andric#endif
2877a984708SDavid Chisnall
2887a984708SDavid Chisnalltemplate <class _Tp>
289936e9439SDimitry Andric_LIBCPP_NORETURN
2907a984708SDavid Chisnallvoid
291540d2a8bSDimitry Andric#ifndef _LIBCPP_CXX03_LANG
292540d2a8bSDimitry Andricthrow_with_nested(_Tp&& __t)
293540d2a8bSDimitry Andric#else
294540d2a8bSDimitry Andricthrow_with_nested (_Tp& __t)
295540d2a8bSDimitry Andric#endif // _LIBCPP_CXX03_LANG
2967a984708SDavid Chisnall{
2977a984708SDavid Chisnall#ifndef _LIBCPP_NO_EXCEPTIONS
298540d2a8bSDimitry Andric    typedef typename decay<_Tp>::type _Up;
299540d2a8bSDimitry Andric    static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible");
300540d2a8bSDimitry Andric    __throw_with_nested<_Tp, _Up,
301540d2a8bSDimitry Andric        is_class<_Up>::value &&
302540d2a8bSDimitry Andric        !is_base_of<nested_exception, _Up>::value &&
303540d2a8bSDimitry Andric        !__libcpp_is_final<_Up>::value>::
304540d2a8bSDimitry Andric            __do_throw(_VSTD::forward<_Tp>(__t));
305aed8d94eSDimitry Andric#else
306aed8d94eSDimitry Andric    ((void)__t);
307aed8d94eSDimitry Andric    // FIXME: Make this abort
3087a984708SDavid Chisnall#endif
3097a984708SDavid Chisnall}
3107a984708SDavid Chisnall
311540d2a8bSDimitry Andrictemplate <class _From, class _To>
312540d2a8bSDimitry Andricstruct __can_dynamic_cast : public _LIBCPP_BOOL_CONSTANT(
313540d2a8bSDimitry Andric              is_polymorphic<_From>::value &&
314540d2a8bSDimitry Andric                 (!is_base_of<_To, _From>::value ||
315540d2a8bSDimitry Andric                   is_convertible<const _From*, const _To*>::value)) {};
316540d2a8bSDimitry Andric
31794e3ee44SDavid Chisnalltemplate <class _Ep>
3187a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
3197a984708SDavid Chisnallvoid
320540d2a8bSDimitry Andricrethrow_if_nested(const _Ep& __e,
321540d2a8bSDimitry Andric                  typename enable_if< __can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0)
3227a984708SDavid Chisnall{
3239729cf09SDimitry Andric    const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e));
3247a984708SDavid Chisnall    if (__nep)
3257a984708SDavid Chisnall        __nep->rethrow_nested();
3267a984708SDavid Chisnall}
3277a984708SDavid Chisnall
32894e3ee44SDavid Chisnalltemplate <class _Ep>
3297a984708SDavid Chisnallinline _LIBCPP_INLINE_VISIBILITY
3307a984708SDavid Chisnallvoid
331540d2a8bSDimitry Andricrethrow_if_nested(const _Ep&,
332540d2a8bSDimitry Andric                  typename enable_if<!__can_dynamic_cast<_Ep, nested_exception>::value>::type* = 0)
3337a984708SDavid Chisnall{
3347a984708SDavid Chisnall}
3357a984708SDavid Chisnall
3367a984708SDavid Chisnall}  // std
3377a984708SDavid Chisnall
3387a984708SDavid Chisnall#endif  // _LIBCPP_EXCEPTION
339