13e519524SHoward Hinnant// -*- C++ -*-
2eb8650a7SLouis Dionne//===----------------------------------------------------------------------===//
33e519524SHoward Hinnant//
457b08b09SChandler Carruth// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
557b08b09SChandler Carruth// See https://llvm.org/LICENSE.txt for license information.
657b08b09SChandler Carruth// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
73e519524SHoward Hinnant//
83e519524SHoward Hinnant//===----------------------------------------------------------------------===//
93e519524SHoward Hinnant
103e519524SHoward Hinnant#ifndef _LIBCPP_EXCEPTION
113e519524SHoward Hinnant#define _LIBCPP_EXCEPTION
123e519524SHoward Hinnant
133e519524SHoward Hinnant/*
143e519524SHoward Hinnant    exception synopsis
153e519524SHoward Hinnant
163e519524SHoward Hinnantnamespace std
173e519524SHoward Hinnant{
183e519524SHoward Hinnant
193e519524SHoward Hinnantclass exception
203e519524SHoward Hinnant{
213e519524SHoward Hinnantpublic:
22fafca58cSHoward Hinnant    exception() noexcept;
23fafca58cSHoward Hinnant    exception(const exception&) noexcept;
24fafca58cSHoward Hinnant    exception& operator=(const exception&) noexcept;
25fafca58cSHoward Hinnant    virtual ~exception() noexcept;
26fafca58cSHoward Hinnant    virtual const char* what() const noexcept;
273e519524SHoward Hinnant};
283e519524SHoward Hinnant
293e519524SHoward Hinnantclass bad_exception
303e519524SHoward Hinnant    : public exception
313e519524SHoward Hinnant{
323e519524SHoward Hinnantpublic:
33fafca58cSHoward Hinnant    bad_exception() noexcept;
34fafca58cSHoward Hinnant    bad_exception(const bad_exception&) noexcept;
35fafca58cSHoward Hinnant    bad_exception& operator=(const bad_exception&) noexcept;
36fafca58cSHoward Hinnant    virtual ~bad_exception() noexcept;
37fafca58cSHoward Hinnant    virtual const char* what() const noexcept;
383e519524SHoward Hinnant};
393e519524SHoward Hinnant
403e519524SHoward Hinnanttypedef void (*unexpected_handler)();
41fafca58cSHoward Hinnantunexpected_handler set_unexpected(unexpected_handler  f ) noexcept;
42fafca58cSHoward Hinnantunexpected_handler get_unexpected() noexcept;
43fafca58cSHoward Hinnant[[noreturn]] void unexpected();
443e519524SHoward Hinnant
453e519524SHoward Hinnanttypedef void (*terminate_handler)();
46fafca58cSHoward Hinnantterminate_handler set_terminate(terminate_handler  f ) noexcept;
47fafca58cSHoward Hinnantterminate_handler get_terminate() noexcept;
48fafca58cSHoward Hinnant[[noreturn]] void terminate() noexcept;
493e519524SHoward Hinnant
50fafca58cSHoward Hinnantbool uncaught_exception()  noexcept;
5189102f0fSMarshall Clowint  uncaught_exceptions() noexcept;  // C++17
523e519524SHoward Hinnant
533e519524SHoward Hinnanttypedef unspecified exception_ptr;
543e519524SHoward Hinnant
55fafca58cSHoward Hinnantexception_ptr current_exception() noexcept;
563e519524SHoward Hinnantvoid rethrow_exception [[noreturn]] (exception_ptr p);
57fafca58cSHoward Hinnanttemplate<class E> exception_ptr make_exception_ptr(E e) noexcept;
583e519524SHoward Hinnant
593e519524SHoward Hinnantclass nested_exception
603e519524SHoward Hinnant{
613e519524SHoward Hinnantpublic:
62fafca58cSHoward Hinnant    nested_exception() noexcept;
63fafca58cSHoward Hinnant    nested_exception(const nested_exception&) noexcept = default;
64fafca58cSHoward Hinnant    nested_exception& operator=(const nested_exception&) noexcept = default;
653e519524SHoward Hinnant    virtual ~nested_exception() = default;
663e519524SHoward Hinnant
673e519524SHoward Hinnant    // access functions
68fafca58cSHoward Hinnant    [[noreturn]] void rethrow_nested() const;
69fafca58cSHoward Hinnant    exception_ptr nested_ptr() const noexcept;
703e519524SHoward Hinnant};
713e519524SHoward Hinnant
72fafca58cSHoward Hinnanttemplate <class T> [[noreturn]] void throw_with_nested(T&& t);
733e519524SHoward Hinnanttemplate <class E> void rethrow_if_nested(const E& e);
743e519524SHoward Hinnant
753e519524SHoward Hinnant}  // std
763e519524SHoward Hinnant
773e519524SHoward Hinnant*/
783e519524SHoward Hinnant
79385cc25aSLouis Dionne#include <__assert> // all public C++ headers provide the assertion handler
802eadbc86SLouis Dionne#include <__availability>
81bfbd73f8SArthur O'Dwyer#include <__config>
82f992cfbaSLouis Dionne#include <__memory/addressof.h>
833e519524SHoward Hinnant#include <cstddef>
84613dc646SEric Fiselier#include <cstdlib>
85019fe4b8SHoward Hinnant#include <type_traits>
86f56972e2SMarshall Clow#include <version>
873e519524SHoward Hinnant
88e69290dcSEric Fiselier#if defined(_LIBCPP_ABI_VCRUNTIME)
89d22c9dc4SEric Fiselier#include <vcruntime_exception.h>
90d22c9dc4SEric Fiselier#endif
91d22c9dc4SEric Fiselier
92073458b1SHoward Hinnant#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
933e519524SHoward Hinnant#  pragma GCC system_header
94073458b1SHoward Hinnant#endif
953e519524SHoward Hinnant
963e519524SHoward Hinnantnamespace std  // purposefully not using versioning namespace
973e519524SHoward Hinnant{
983e519524SHoward Hinnant
99e69290dcSEric Fiselier#if !defined(_LIBCPP_ABI_VCRUNTIME)
1003e519524SHoward Hinnantclass _LIBCPP_EXCEPTION_ABI exception
1013e519524SHoward Hinnant{
1023e519524SHoward Hinnantpublic:
103fafca58cSHoward Hinnant    _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {}
104585a3cc3SDimitry Andric    _LIBCPP_INLINE_VISIBILITY exception(const exception&) _NOEXCEPT = default;
105585a3cc3SDimitry Andric
106fafca58cSHoward Hinnant    virtual ~exception() _NOEXCEPT;
107fafca58cSHoward Hinnant    virtual const char* what() const _NOEXCEPT;
1083e519524SHoward Hinnant};
1093e519524SHoward Hinnant
1103e519524SHoward Hinnantclass _LIBCPP_EXCEPTION_ABI bad_exception
1113e519524SHoward Hinnant    : public exception
1123e519524SHoward Hinnant{
1133e519524SHoward Hinnantpublic:
114fafca58cSHoward Hinnant    _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {}
115fafca58cSHoward Hinnant    virtual ~bad_exception() _NOEXCEPT;
116fafca58cSHoward Hinnant    virtual const char* what() const _NOEXCEPT;
1173e519524SHoward Hinnant};
118e69290dcSEric Fiselier#endif // !_LIBCPP_ABI_VCRUNTIME
1193e519524SHoward Hinnant
1202a1bfa98SEric Fiselier#if _LIBCPP_STD_VER <= 14 \
1212a1bfa98SEric Fiselier    || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) \
1222a1bfa98SEric Fiselier    || defined(_LIBCPP_BUILDING_LIBRARY)
1233e519524SHoward Hinnanttypedef void (*unexpected_handler)();
1246e41256fSHoward Hinnant_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
1256e41256fSHoward Hinnant_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT;
1266e41256fSHoward Hinnant_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected();
1272a1bfa98SEric Fiselier#endif
1283e519524SHoward Hinnant
1293e519524SHoward Hinnanttypedef void (*terminate_handler)();
1306e41256fSHoward Hinnant_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
1316e41256fSHoward Hinnant_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;
1326e41256fSHoward Hinnant_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
1333e519524SHoward Hinnant
1346e41256fSHoward Hinnant_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
135e9c66ad9SMehdi Amini_LIBCPP_FUNC_VIS _LIBCPP_AVAILABILITY_UNCAUGHT_EXCEPTIONS int uncaught_exceptions() _NOEXCEPT;
1363e519524SHoward Hinnant
1376e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS exception_ptr;
1383e519524SHoward Hinnant
139f0544c20SHoward Hinnant_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
140f0544c20SHoward Hinnant_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
1413e519524SHoward Hinnant
1423e254a6eSEric Fiselier#ifndef _LIBCPP_ABI_MICROSOFT
1433e254a6eSEric Fiselier
1446e41256fSHoward Hinnantclass _LIBCPP_TYPE_VIS exception_ptr
1453e519524SHoward Hinnant{
1463e519524SHoward Hinnant    void* __ptr_;
1473e519524SHoward Hinnantpublic:
148fafca58cSHoward Hinnant    _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
149fafca58cSHoward Hinnant    _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
1503e254a6eSEric Fiselier
151fafca58cSHoward Hinnant    exception_ptr(const exception_ptr&) _NOEXCEPT;
152fafca58cSHoward Hinnant    exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
153fafca58cSHoward Hinnant    ~exception_ptr() _NOEXCEPT;
1543e519524SHoward Hinnant
155317e92a3SArthur O'Dwyer    _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT
1563e254a6eSEric Fiselier    {return __ptr_ != nullptr;}
1573e519524SHoward Hinnant
158fb100021SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
159fafca58cSHoward Hinnant    bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
1603e519524SHoward Hinnant        {return __x.__ptr_ == __y.__ptr_;}
1613e254a6eSEric Fiselier
162fb100021SHoward Hinnant    friend _LIBCPP_INLINE_VISIBILITY
163fafca58cSHoward Hinnant    bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
1643e519524SHoward Hinnant        {return !(__x == __y);}
1653e519524SHoward Hinnant
166f0544c20SHoward Hinnant    friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
167f0544c20SHoward Hinnant    friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
1683e519524SHoward Hinnant};
1693e519524SHoward Hinnant
170c003db1fSHoward Hinnanttemplate<class _Ep>
171352adb65SLouis Dionne_LIBCPP_INLINE_VISIBILITY exception_ptr
172c003db1fSHoward Hinnantmake_exception_ptr(_Ep __e) _NOEXCEPT
1733e519524SHoward Hinnant{
17454b409fdSHoward Hinnant#ifndef _LIBCPP_NO_EXCEPTIONS
1753e519524SHoward Hinnant    try
1763e519524SHoward Hinnant    {
1773e519524SHoward Hinnant        throw __e;
1783e519524SHoward Hinnant    }
1793e519524SHoward Hinnant    catch (...)
1803e519524SHoward Hinnant    {
1813e519524SHoward Hinnant        return current_exception();
1823e519524SHoward Hinnant    }
183613dc646SEric Fiselier#else
184fd838227SEric Fiselier    ((void)__e);
185613dc646SEric Fiselier    _VSTD::abort();
186613dc646SEric Fiselier#endif
1873e519524SHoward Hinnant}
1883e519524SHoward Hinnant
1893e254a6eSEric Fiselier#else // _LIBCPP_ABI_MICROSOFT
1903e254a6eSEric Fiselier
1913e254a6eSEric Fiselierclass _LIBCPP_TYPE_VIS exception_ptr
1923e254a6eSEric Fiselier{
193a7c2a628SNikolas Klauser_LIBCPP_DIAGNOSTIC_PUSH
194a7c2a628SNikolas Klauser_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field")
1953e254a6eSEric Fiselier    void* __ptr1_;
1963e254a6eSEric Fiselier    void* __ptr2_;
197a7c2a628SNikolas Klauser_LIBCPP_DIAGNOSTIC_POP
1983e254a6eSEric Fiselierpublic:
1993e254a6eSEric Fiselier    exception_ptr() _NOEXCEPT;
2003e254a6eSEric Fiselier    exception_ptr(nullptr_t) _NOEXCEPT;
2013e254a6eSEric Fiselier    exception_ptr(const exception_ptr& __other) _NOEXCEPT;
2023e254a6eSEric Fiselier    exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT;
2033e254a6eSEric Fiselier    exception_ptr& operator=(nullptr_t) _NOEXCEPT;
2043e254a6eSEric Fiselier    ~exception_ptr() _NOEXCEPT;
205317e92a3SArthur O'Dwyer    explicit operator bool() const _NOEXCEPT;
2063e254a6eSEric Fiselier};
2073e254a6eSEric Fiselier
2083e254a6eSEric Fiselier_LIBCPP_FUNC_VIS
2093e254a6eSEric Fiselierbool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT;
2103e254a6eSEric Fiselier
2113e254a6eSEric Fiselierinline _LIBCPP_INLINE_VISIBILITY
2123e254a6eSEric Fiselierbool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
2133e254a6eSEric Fiselier    {return !(__x == __y);}
2143e254a6eSEric Fiselier
2153e254a6eSEric Fiselier_LIBCPP_FUNC_VIS void swap(exception_ptr&, exception_ptr&) _NOEXCEPT;
2163e254a6eSEric Fiselier
2173e254a6eSEric Fiselier_LIBCPP_FUNC_VIS exception_ptr __copy_exception_ptr(void *__except, const void* __ptr);
2183e254a6eSEric Fiselier_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
219*b48c5010SNikolas Klauser_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
2203e254a6eSEric Fiselier
2213e254a6eSEric Fiselier// This is a built-in template function which automagically extracts the required
2223e254a6eSEric Fiselier// information.
2233e254a6eSEric Fiseliertemplate <class _E> void *__GetExceptionInfo(_E);
2243e254a6eSEric Fiselier
2253e254a6eSEric Fiseliertemplate<class _Ep>
226352adb65SLouis Dionne_LIBCPP_INLINE_VISIBILITY exception_ptr
2273e254a6eSEric Fiseliermake_exception_ptr(_Ep __e) _NOEXCEPT
2283e254a6eSEric Fiselier{
2293e254a6eSEric Fiselier  return __copy_exception_ptr(_VSTD::addressof(__e), __GetExceptionInfo(__e));
2303e254a6eSEric Fiselier}
2313e254a6eSEric Fiselier
2323e254a6eSEric Fiselier#endif // _LIBCPP_ABI_MICROSOFT
233019fe4b8SHoward Hinnant// nested_exception
234019fe4b8SHoward Hinnant
235019fe4b8SHoward Hinnantclass _LIBCPP_EXCEPTION_ABI nested_exception
236019fe4b8SHoward Hinnant{
237019fe4b8SHoward Hinnant    exception_ptr __ptr_;
238019fe4b8SHoward Hinnantpublic:
239fafca58cSHoward Hinnant    nested_exception() _NOEXCEPT;
240fafca58cSHoward Hinnant//     nested_exception(const nested_exception&) noexcept = default;
241fafca58cSHoward Hinnant//     nested_exception& operator=(const nested_exception&) noexcept = default;
242fafca58cSHoward Hinnant    virtual ~nested_exception() _NOEXCEPT;
243019fe4b8SHoward Hinnant
244019fe4b8SHoward Hinnant    // access functions
245535a86c3SRichard Smith    _LIBCPP_NORETURN void rethrow_nested() const;
246fafca58cSHoward Hinnant    _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;}
247019fe4b8SHoward Hinnant};
248019fe4b8SHoward Hinnant
249019fe4b8SHoward Hinnanttemplate <class _Tp>
250019fe4b8SHoward Hinnantstruct __nested
251019fe4b8SHoward Hinnant    : public _Tp,
252019fe4b8SHoward Hinnant      public nested_exception
253019fe4b8SHoward Hinnant{
254fb100021SHoward Hinnant    _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {}
255019fe4b8SHoward Hinnant};
256019fe4b8SHoward Hinnant
257e9ca2bb8SMarshall Clow#ifndef _LIBCPP_NO_EXCEPTIONS
258e9ca2bb8SMarshall Clowtemplate <class _Tp, class _Up, bool>
259e9ca2bb8SMarshall Clowstruct __throw_with_nested;
260e9ca2bb8SMarshall Clow
261e9ca2bb8SMarshall Clowtemplate <class _Tp, class _Up>
262e9ca2bb8SMarshall Clowstruct __throw_with_nested<_Tp, _Up, true> {
263dc7200b4SLouis Dionne    _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void
264e9ca2bb8SMarshall Clow    __do_throw(_Tp&& __t)
265019fe4b8SHoward Hinnant    {
2666adbc83eSChristopher Di Bella        throw __nested<_Up>(static_cast<_Tp&&>(__t));
267019fe4b8SHoward Hinnant    }
268e9ca2bb8SMarshall Clow};
269e9ca2bb8SMarshall Clow
270e9ca2bb8SMarshall Clowtemplate <class _Tp, class _Up>
271e9ca2bb8SMarshall Clowstruct __throw_with_nested<_Tp, _Up, false> {
272dc7200b4SLouis Dionne    _LIBCPP_NORETURN static inline _LIBCPP_INLINE_VISIBILITY void
2736ded58e2SEric Fiselier#ifndef _LIBCPP_CXX03_LANG
274e9ca2bb8SMarshall Clow    __do_throw(_Tp&& __t)
275e9ca2bb8SMarshall Clow#else
276e9ca2bb8SMarshall Clow    __do_throw (_Tp& __t)
2776ded58e2SEric Fiselier#endif // _LIBCPP_CXX03_LANG
278e9ca2bb8SMarshall Clow    {
2796adbc83eSChristopher Di Bella        throw static_cast<_Tp&&>(__t);
280e9ca2bb8SMarshall Clow    }
281e9ca2bb8SMarshall Clow};
282e9ca2bb8SMarshall Clow#endif
283019fe4b8SHoward Hinnant
284019fe4b8SHoward Hinnanttemplate <class _Tp>
285535a86c3SRichard Smith_LIBCPP_NORETURN
286019fe4b8SHoward Hinnantvoid
287e9ca2bb8SMarshall Clowthrow_with_nested(_Tp&& __t)
288019fe4b8SHoward Hinnant{
28954b409fdSHoward Hinnant#ifndef _LIBCPP_NO_EXCEPTIONS
2905948e392SMarshall Clow    typedef typename decay<_Tp>::type _Up;
2915948e392SMarshall Clow    static_assert( is_copy_constructible<_Up>::value, "type thrown must be CopyConstructible");
292e9ca2bb8SMarshall Clow    __throw_with_nested<_Tp, _Up,
293e9ca2bb8SMarshall Clow        is_class<_Up>::value &&
294e9ca2bb8SMarshall Clow        !is_base_of<nested_exception, _Up>::value &&
295e9ca2bb8SMarshall Clow        !__libcpp_is_final<_Up>::value>::
2966adbc83eSChristopher Di Bella            __do_throw(static_cast<_Tp&&>(__t));
297fd838227SEric Fiselier#else
298fd838227SEric Fiselier    ((void)__t);
299fd838227SEric Fiselier    // FIXME: Make this abort
30054b409fdSHoward Hinnant#endif
301019fe4b8SHoward Hinnant}
302019fe4b8SHoward Hinnant
30355cfe4c1SMarshall Clowtemplate <class _From, class _To>
304f900f702SLouis Dionnestruct __can_dynamic_cast : _BoolConstant<
30555cfe4c1SMarshall Clow              is_polymorphic<_From>::value &&
30655cfe4c1SMarshall Clow                 (!is_base_of<_To, _From>::value ||
307f900f702SLouis Dionne                   is_convertible<const _From*, const _To*>::value)> {};
30855cfe4c1SMarshall Clow
309c003db1fSHoward Hinnanttemplate <class _Ep>
310fb100021SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
311019fe4b8SHoward Hinnantvoid
31255cfe4c1SMarshall Clowrethrow_if_nested(const _Ep& __e,
3134887d047SNikolas Klauser                  __enable_if_t< __can_dynamic_cast<_Ep, nested_exception>::value>* = 0)
314019fe4b8SHoward Hinnant{
31594b5bc42SMarshall Clow    const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e));
316a391bc13SHoward Hinnant    if (__nep)
317a391bc13SHoward Hinnant        __nep->rethrow_nested();
318019fe4b8SHoward Hinnant}
319019fe4b8SHoward Hinnant
320c003db1fSHoward Hinnanttemplate <class _Ep>
321fb100021SHoward Hinnantinline _LIBCPP_INLINE_VISIBILITY
322019fe4b8SHoward Hinnantvoid
32355cfe4c1SMarshall Clowrethrow_if_nested(const _Ep&,
3244887d047SNikolas Klauser                  __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value>* = 0)
325019fe4b8SHoward Hinnant{
326019fe4b8SHoward Hinnant}
327019fe4b8SHoward Hinnant
328d2b0df35SNikolas Klauser} // namespace std
3293e519524SHoward Hinnant
3303e519524SHoward Hinnant#endif // _LIBCPP_EXCEPTION
331