]>
Commit | Line | Data |
---|---|---|
182da14a JW |
1 | // Nested Exception support header (nested_exception class) for -*- C++ -*- |
2 | ||
99dee823 | 3 | // Copyright (C) 2009-2021 Free Software Foundation, Inc. |
182da14a JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
7c3e9502 | 25 | /** @file bits/nested_exception.h |
f910786b BK |
26 | * This is an internal header file, included by other library headers. |
27 | * Do not attempt to use it directly. @headername{exception} | |
182da14a JW |
28 | */ |
29 | ||
30 | #ifndef _GLIBCXX_NESTED_EXCEPTION_H | |
31 | #define _GLIBCXX_NESTED_EXCEPTION_H 1 | |
32 | ||
33 | #pragma GCC visibility push(default) | |
34 | ||
734f5023 | 35 | #if __cplusplus < 201103L |
2f95713b | 36 | # include <bits/c++0x_warning.h> |
182da14a JW |
37 | #else |
38 | ||
39 | #include <bits/c++config.h> | |
e3fc446b | 40 | #include <bits/move.h> |
182da14a | 41 | |
182da14a JW |
42 | extern "C++" { |
43 | ||
44 | namespace std | |
45 | { | |
46 | /** | |
47 | * @addtogroup exceptions | |
48 | * @{ | |
49 | */ | |
50 | ||
8eead16e | 51 | /// Exception class with exception_ptr data member. |
182da14a JW |
52 | class nested_exception |
53 | { | |
8eead16e BK |
54 | exception_ptr _M_ptr; |
55 | ||
182da14a | 56 | public: |
8535715d | 57 | nested_exception() noexcept : _M_ptr(current_exception()) { } |
182da14a | 58 | |
2ce8cb99 | 59 | nested_exception(const nested_exception&) noexcept = default; |
182da14a | 60 | |
2ce8cb99 | 61 | nested_exception& operator=(const nested_exception&) noexcept = default; |
182da14a | 62 | |
8535715d | 63 | virtual ~nested_exception() noexcept; |
182da14a | 64 | |
2ce8cb99 | 65 | [[noreturn]] |
182da14a | 66 | void |
2ce8cb99 JW |
67 | rethrow_nested() const |
68 | { | |
69 | if (_M_ptr) | |
70 | rethrow_exception(_M_ptr); | |
71 | std::terminate(); | |
72 | } | |
182da14a JW |
73 | |
74 | exception_ptr | |
2ce8cb99 | 75 | nested_ptr() const noexcept |
182da14a | 76 | { return _M_ptr; } |
182da14a JW |
77 | }; |
78 | ||
2f7f1aca JW |
79 | /// @cond undocumented |
80 | ||
182da14a JW |
81 | template<typename _Except> |
82 | struct _Nested_exception : public _Except, public nested_exception | |
83 | { | |
2ce8cb99 JW |
84 | explicit _Nested_exception(const _Except& __ex) |
85 | : _Except(__ex) | |
86 | { } | |
87 | ||
8eead16e | 88 | explicit _Nested_exception(_Except&& __ex) |
182da14a JW |
89 | : _Except(static_cast<_Except&&>(__ex)) |
90 | { } | |
91 | }; | |
92 | ||
0470fad0 JW |
93 | // [except.nested]/8 |
94 | // Throw an exception of unspecified type that is publicly derived from | |
95 | // both remove_reference_t<_Tp> and nested_exception. | |
2ce8cb99 | 96 | template<typename _Tp> |
c85d1992 | 97 | [[noreturn]] |
0470fad0 JW |
98 | inline void |
99 | __throw_with_nested_impl(_Tp&& __t, true_type) | |
182da14a | 100 | { |
0470fad0 JW |
101 | using _Up = typename remove_reference<_Tp>::type; |
102 | throw _Nested_exception<_Up>{std::forward<_Tp>(__t)}; | |
103 | } | |
2ce8cb99 JW |
104 | |
105 | template<typename _Tp> | |
c85d1992 | 106 | [[noreturn]] |
0470fad0 JW |
107 | inline void |
108 | __throw_with_nested_impl(_Tp&& __t, false_type) | |
109 | { throw std::forward<_Tp>(__t); } | |
2ce8cb99 | 110 | |
2f7f1aca JW |
111 | /// @endcond |
112 | ||
2ce8cb99 JW |
113 | /// If @p __t is derived from nested_exception, throws @p __t. |
114 | /// Else, throws an implementation-defined object derived from both. | |
115 | template<typename _Tp> | |
116 | [[noreturn]] | |
182da14a | 117 | inline void |
2ce8cb99 JW |
118 | throw_with_nested(_Tp&& __t) |
119 | { | |
04c872aa | 120 | using _Up = typename decay<_Tp>::type; |
0470fad0 JW |
121 | using _CopyConstructible |
122 | = __and_<is_copy_constructible<_Up>, is_move_constructible<_Up>>; | |
123 | static_assert(_CopyConstructible::value, | |
124 | "throw_with_nested argument must be CopyConstructible"); | |
125 | using __nest = __and_<is_class<_Up>, __bool_constant<!__is_final(_Up)>, | |
126 | __not_<is_base_of<nested_exception, _Up>>>; | |
40571365 | 127 | std::__throw_with_nested_impl(std::forward<_Tp>(__t), __nest{}); |
2ce8cb99 | 128 | } |
182da14a | 129 | |
2f7f1aca JW |
130 | /// @cond undocumented |
131 | ||
0470fad0 | 132 | // Determine if dynamic_cast<const nested_exception&> would be well-formed. |
2ce8cb99 | 133 | template<typename _Tp> |
0470fad0 JW |
134 | using __rethrow_if_nested_cond = typename enable_if< |
135 | __and_<is_polymorphic<_Tp>, | |
136 | __or_<__not_<is_base_of<nested_exception, _Tp>>, | |
137 | is_convertible<_Tp*, nested_exception*>>>::value | |
138 | >::type; | |
139 | ||
140 | // Attempt dynamic_cast to nested_exception and call rethrow_nested(). | |
141 | template<typename _Ex> | |
142 | inline __rethrow_if_nested_cond<_Ex> | |
143 | __rethrow_if_nested_impl(const _Ex* __ptr) | |
182da14a | 144 | { |
0470fad0 JW |
145 | if (auto __ne_ptr = dynamic_cast<const nested_exception*>(__ptr)) |
146 | __ne_ptr->rethrow_nested(); | |
147 | } | |
148 | ||
149 | // Otherwise, no effects. | |
150 | inline void | |
151 | __rethrow_if_nested_impl(const void*) | |
152 | { } | |
182da14a | 153 | |
2f7f1aca JW |
154 | /// @endcond |
155 | ||
8eead16e | 156 | /// If @p __ex is derived from nested_exception, @p __ex.rethrow_nested(). |
182da14a JW |
157 | template<typename _Ex> |
158 | inline void | |
159 | rethrow_if_nested(const _Ex& __ex) | |
0470fad0 | 160 | { std::__rethrow_if_nested_impl(std::__addressof(__ex)); } |
182da14a | 161 | |
182da14a JW |
162 | // @} group exceptions |
163 | } // namespace std | |
164 | ||
165 | } // extern "C++" | |
166 | ||
734f5023 | 167 | #endif // C++11 |
182da14a JW |
168 | |
169 | #pragma GCC visibility pop | |
170 | ||
171 | #endif // _GLIBCXX_NESTED_EXCEPTION_H |