1227825Stheraven// -*- C++ -*-
2227825Stheraven//===-------------------------- exception ---------------------------------===//
3227825Stheraven//
4227825Stheraven//                     The LLVM Compiler Infrastructure
5227825Stheraven//
6227825Stheraven// This file is dual licensed under the MIT and the University of Illinois Open
7227825Stheraven// Source Licenses. See LICENSE.TXT for details.
8227825Stheraven//
9227825Stheraven//===----------------------------------------------------------------------===//
10227825Stheraven
11227825Stheraven#ifndef _LIBCPP_EXCEPTION
12227825Stheraven#define _LIBCPP_EXCEPTION
13227825Stheraven
14227825Stheraven/*
15227825Stheraven    exception synopsis
16227825Stheraven
17227825Stheravennamespace std
18227825Stheraven{
19227825Stheraven
20227825Stheravenclass exception
21227825Stheraven{
22227825Stheravenpublic:
23227825Stheraven    exception() noexcept;
24227825Stheraven    exception(const exception&) noexcept;
25227825Stheraven    exception& operator=(const exception&) noexcept;
26227825Stheraven    virtual ~exception() noexcept;
27227825Stheraven    virtual const char* what() const noexcept;
28227825Stheraven};
29227825Stheraven
30227825Stheravenclass bad_exception
31227825Stheraven    : public exception
32227825Stheraven{
33227825Stheravenpublic:
34227825Stheraven    bad_exception() noexcept;
35227825Stheraven    bad_exception(const bad_exception&) noexcept;
36227825Stheraven    bad_exception& operator=(const bad_exception&) noexcept;
37227825Stheraven    virtual ~bad_exception() noexcept;
38227825Stheraven    virtual const char* what() const noexcept;
39227825Stheraven};
40227825Stheraven
41227825Stheraventypedef void (*unexpected_handler)();
42227825Stheravenunexpected_handler set_unexpected(unexpected_handler  f ) noexcept;
43227825Stheravenunexpected_handler get_unexpected() noexcept;
44227825Stheraven[[noreturn]] void unexpected();
45227825Stheraven
46227825Stheraventypedef void (*terminate_handler)();
47227825Stheraventerminate_handler set_terminate(terminate_handler  f ) noexcept;
48227825Stheraventerminate_handler get_terminate() noexcept;
49227825Stheraven[[noreturn]] void terminate() noexcept;
50227825Stheraven
51288943Sdimbool uncaught_exception()  noexcept;
52288943Sdimint  uncaught_exceptions() noexcept;  // C++17
53227825Stheraven
54227825Stheraventypedef unspecified exception_ptr;
55227825Stheraven
56227825Stheravenexception_ptr current_exception() noexcept;
57227825Stheravenvoid rethrow_exception [[noreturn]] (exception_ptr p);
58227825Stheraventemplate<class E> exception_ptr make_exception_ptr(E e) noexcept;
59227825Stheraven
60227825Stheravenclass nested_exception
61227825Stheraven{
62227825Stheravenpublic:
63227825Stheraven    nested_exception() noexcept;
64227825Stheraven    nested_exception(const nested_exception&) noexcept = default;
65227825Stheraven    nested_exception& operator=(const nested_exception&) noexcept = default;
66227825Stheraven    virtual ~nested_exception() = default;
67227825Stheraven
68227825Stheraven    // access functions
69227825Stheraven    [[noreturn]] void rethrow_nested() const;
70227825Stheraven    exception_ptr nested_ptr() const noexcept;
71227825Stheraven};
72227825Stheraven
73227825Stheraventemplate <class T> [[noreturn]] void throw_with_nested(T&& t);
74227825Stheraventemplate <class E> void rethrow_if_nested(const E& e);
75227825Stheraven
76227825Stheraven}  // std
77227825Stheraven
78227825Stheraven*/
79227825Stheraven
80227825Stheraven#include <__config>
81227825Stheraven#include <cstddef>
82227825Stheraven#include <type_traits>
83227825Stheraven
84227825Stheraven#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
85227825Stheraven#pragma GCC system_header
86227825Stheraven#endif
87227825Stheraven
88227825Stheravennamespace std  // purposefully not using versioning namespace
89227825Stheraven{
90227825Stheraven
91227825Stheravenclass _LIBCPP_EXCEPTION_ABI exception
92227825Stheraven{
93227825Stheravenpublic:
94227825Stheraven    _LIBCPP_INLINE_VISIBILITY exception() _NOEXCEPT {}
95227825Stheraven    virtual ~exception() _NOEXCEPT;
96227825Stheraven    virtual const char* what() const _NOEXCEPT;
97227825Stheraven};
98227825Stheraven
99227825Stheravenclass _LIBCPP_EXCEPTION_ABI bad_exception
100227825Stheraven    : public exception
101227825Stheraven{
102227825Stheravenpublic:
103227825Stheraven    _LIBCPP_INLINE_VISIBILITY bad_exception() _NOEXCEPT {}
104227825Stheraven    virtual ~bad_exception() _NOEXCEPT;
105227825Stheraven    virtual const char* what() const _NOEXCEPT;
106227825Stheraven};
107227825Stheraven
108227825Stheraventypedef void (*unexpected_handler)();
109249989Sdim_LIBCPP_FUNC_VIS unexpected_handler set_unexpected(unexpected_handler) _NOEXCEPT;
110249989Sdim_LIBCPP_FUNC_VIS unexpected_handler get_unexpected() _NOEXCEPT;
111249989Sdim_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void unexpected();
112227825Stheraven
113227825Stheraventypedef void (*terminate_handler)();
114249989Sdim_LIBCPP_FUNC_VIS terminate_handler set_terminate(terminate_handler) _NOEXCEPT;
115249989Sdim_LIBCPP_FUNC_VIS terminate_handler get_terminate() _NOEXCEPT;
116249989Sdim_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void terminate() _NOEXCEPT;
117227825Stheraven
118249989Sdim_LIBCPP_FUNC_VIS bool uncaught_exception() _NOEXCEPT;
119288943Sdim_LIBCPP_FUNC_VIS int uncaught_exceptions() _NOEXCEPT;
120227825Stheraven
121249989Sdimclass _LIBCPP_TYPE_VIS exception_ptr;
122227825Stheraven
123261272Sdim_LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
124261272Sdim_LIBCPP_NORETURN _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
125227825Stheraven
126249989Sdimclass _LIBCPP_TYPE_VIS exception_ptr
127227825Stheraven{
128227825Stheraven    void* __ptr_;
129227825Stheravenpublic:
130227825Stheraven    _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {}
131227825Stheraven    _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}
132227825Stheraven    exception_ptr(const exception_ptr&) _NOEXCEPT;
133227825Stheraven    exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
134227825Stheraven    ~exception_ptr() _NOEXCEPT;
135227825Stheraven
136227825Stheraven    _LIBCPP_INLINE_VISIBILITY
137232924Stheraven    _LIBCPP_EXPLICIT
138227825Stheraven        operator bool() const _NOEXCEPT {return __ptr_ != nullptr;}
139227825Stheraven
140227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
141227825Stheraven    bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
142227825Stheraven        {return __x.__ptr_ == __y.__ptr_;}
143227825Stheraven    friend _LIBCPP_INLINE_VISIBILITY
144227825Stheraven    bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT
145227825Stheraven        {return !(__x == __y);}
146227825Stheraven
147261272Sdim    friend _LIBCPP_FUNC_VIS exception_ptr current_exception() _NOEXCEPT;
148261272Sdim    friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr);
149227825Stheraven};
150227825Stheraven
151232924Stheraventemplate<class _Ep>
152227825Stheravenexception_ptr
153232924Stheravenmake_exception_ptr(_Ep __e) _NOEXCEPT
154227825Stheraven{
155227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
156227825Stheraven    try
157227825Stheraven    {
158227825Stheraven        throw __e;
159227825Stheraven    }
160227825Stheraven    catch (...)
161227825Stheraven    {
162227825Stheraven        return current_exception();
163227825Stheraven    }
164227825Stheraven#endif  // _LIBCPP_NO_EXCEPTIONS
165227825Stheraven}
166227825Stheraven
167227825Stheraven// nested_exception
168227825Stheraven
169227825Stheravenclass _LIBCPP_EXCEPTION_ABI nested_exception
170227825Stheraven{
171227825Stheraven    exception_ptr __ptr_;
172227825Stheravenpublic:
173227825Stheraven    nested_exception() _NOEXCEPT;
174227825Stheraven//     nested_exception(const nested_exception&) noexcept = default;
175227825Stheraven//     nested_exception& operator=(const nested_exception&) noexcept = default;
176227825Stheraven    virtual ~nested_exception() _NOEXCEPT;
177227825Stheraven
178227825Stheraven    // access functions
179241900Sdim    _LIBCPP_NORETURN void rethrow_nested() const;
180227825Stheraven    _LIBCPP_INLINE_VISIBILITY exception_ptr nested_ptr() const _NOEXCEPT {return __ptr_;}
181227825Stheraven};
182227825Stheraven
183227825Stheraventemplate <class _Tp>
184227825Stheravenstruct __nested
185227825Stheraven    : public _Tp,
186227825Stheraven      public nested_exception
187227825Stheraven{
188227825Stheraven    _LIBCPP_INLINE_VISIBILITY explicit __nested(const _Tp& __t) : _Tp(__t) {}
189227825Stheraven};
190227825Stheraven
191227825Stheraventemplate <class _Tp>
192241900Sdim_LIBCPP_NORETURN
193227825Stheravenvoid
194227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
195227825Stheraventhrow_with_nested(_Tp&& __t, typename enable_if<
196227825Stheraven                  is_class<typename remove_reference<_Tp>::type>::value &&
197227825Stheraven                  !is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value
198288943Sdim                  && !__libcpp_is_final<typename remove_reference<_Tp>::type>::value
199227825Stheraven                                    >::type* = 0)
200227825Stheraven#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
201227825Stheraventhrow_with_nested (_Tp& __t, typename enable_if<
202227825Stheraven                  is_class<_Tp>::value && !is_base_of<nested_exception, _Tp>::value
203227825Stheraven                                    >::type* = 0)
204227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
205227825Stheraven{
206227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
207227825Stheraven    throw __nested<typename remove_reference<_Tp>::type>(_VSTD::forward<_Tp>(__t));
208227825Stheraven#endif
209227825Stheraven}
210227825Stheraven
211227825Stheraventemplate <class _Tp>
212241900Sdim_LIBCPP_NORETURN
213227825Stheravenvoid
214227825Stheraven#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
215227825Stheraventhrow_with_nested(_Tp&& __t, typename enable_if<
216227825Stheraven                  !is_class<typename remove_reference<_Tp>::type>::value ||
217227825Stheraven                  is_base_of<nested_exception, typename remove_reference<_Tp>::type>::value
218288943Sdim                  || __libcpp_is_final<typename remove_reference<_Tp>::type>::value
219227825Stheraven                                    >::type* = 0)
220227825Stheraven#else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
221227825Stheraventhrow_with_nested (_Tp& __t, typename enable_if<
222227825Stheraven                  !is_class<_Tp>::value || is_base_of<nested_exception, _Tp>::value
223227825Stheraven                                    >::type* = 0)
224227825Stheraven#endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
225227825Stheraven{
226227825Stheraven#ifndef _LIBCPP_NO_EXCEPTIONS
227227825Stheraven    throw _VSTD::forward<_Tp>(__t);
228227825Stheraven#endif
229227825Stheraven}
230227825Stheraven
231232924Stheraventemplate <class _Ep>
232227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
233227825Stheravenvoid
234232924Stheravenrethrow_if_nested(const _Ep& __e, typename enable_if<
235232924Stheraven                                   is_polymorphic<_Ep>::value
236227825Stheraven                                                   >::type* = 0)
237227825Stheraven{
238300770Sdim    const nested_exception* __nep = dynamic_cast<const nested_exception*>(_VSTD::addressof(__e));
239227825Stheraven    if (__nep)
240227825Stheraven        __nep->rethrow_nested();
241227825Stheraven}
242227825Stheraven
243232924Stheraventemplate <class _Ep>
244227825Stheraveninline _LIBCPP_INLINE_VISIBILITY
245227825Stheravenvoid
246232924Stheravenrethrow_if_nested(const _Ep&, typename enable_if<
247232924Stheraven                                   !is_polymorphic<_Ep>::value
248227825Stheraven                                                   >::type* = 0)
249227825Stheraven{
250227825Stheraven}
251227825Stheraven
252227825Stheraven}  // std
253227825Stheraven
254227825Stheraven#endif  // _LIBCPP_EXCEPTION
255