1 | //===----------------------------------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef _LIBCPP___EXCEPTION_EXCEPTION_PTR_H |
10 | #define _LIBCPP___EXCEPTION_EXCEPTION_PTR_H |
11 | |
12 | #include <__config> |
13 | #include <__exception/operations.h> |
14 | #include <__memory/addressof.h> |
15 | #include <__memory/construct_at.h> |
16 | #include <__type_traits/decay.h> |
17 | #include <cstddef> |
18 | #include <cstdlib> |
19 | #include <new> |
20 | #include <typeinfo> |
21 | |
22 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
23 | # pragma GCC system_header |
24 | #endif |
25 | |
26 | #ifndef _LIBCPP_ABI_MICROSOFT |
27 | |
28 | # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION |
29 | |
30 | namespace __cxxabiv1 { |
31 | |
32 | extern "C" { |
33 | _LIBCPP_OVERRIDABLE_FUNC_VIS void* __cxa_allocate_exception(size_t) throw(); |
34 | _LIBCPP_OVERRIDABLE_FUNC_VIS void __cxa_free_exception(void*) throw(); |
35 | |
36 | struct __cxa_exception; |
37 | _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception( |
38 | void*, |
39 | std::type_info*, |
40 | # if defined(_WIN32) |
41 | void(__thiscall*)(void*)) throw(); |
42 | # elif defined(__wasm__) |
43 | // In Wasm, a destructor returns its argument |
44 | void* (*)(void*)) throw(); |
45 | # else |
46 | void (*)(void*)) throw(); |
47 | # endif |
48 | } |
49 | |
50 | } // namespace __cxxabiv1 |
51 | |
52 | # endif |
53 | |
54 | #endif |
55 | |
56 | namespace std { // purposefully not using versioning namespace |
57 | |
58 | #ifndef _LIBCPP_ABI_MICROSOFT |
59 | |
60 | class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { |
61 | void* __ptr_; |
62 | |
63 | static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT; |
64 | |
65 | template <class _Ep> |
66 | friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep) _NOEXCEPT; |
67 | |
68 | public: |
69 | // exception_ptr is basically a COW string. |
70 | using __trivially_relocatable = exception_ptr; |
71 | |
72 | _LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {} |
73 | _LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} |
74 | |
75 | exception_ptr(const exception_ptr&) _NOEXCEPT; |
76 | exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; |
77 | ~exception_ptr() _NOEXCEPT; |
78 | |
79 | _LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; } |
80 | |
81 | friend _LIBCPP_HIDE_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { |
82 | return __x.__ptr_ == __y.__ptr_; |
83 | } |
84 | |
85 | friend _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { |
86 | return !(__x == __y); |
87 | } |
88 | |
89 | friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; |
90 | friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); |
91 | }; |
92 | |
93 | template <class _Ep> |
94 | _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { |
95 | # ifndef _LIBCPP_HAS_NO_EXCEPTIONS |
96 | # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L |
97 | using _Ep2 = __decay_t<_Ep>; |
98 | |
99 | void* __ex = __cxxabiv1::__cxa_allocate_exception(sizeof(_Ep)); |
100 | # ifdef __wasm__ |
101 | // In Wasm, a destructor returns its argument |
102 | (void)__cxxabiv1::__cxa_init_primary_exception( |
103 | __ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) -> void* { |
104 | # else |
105 | (void)__cxxabiv1::__cxa_init_primary_exception(__ex, const_cast<std::type_info*>(&typeid(_Ep)), [](void* __p) { |
106 | # endif |
107 | std::__destroy_at(static_cast<_Ep2*>(__p)); |
108 | # ifdef __wasm__ |
109 | return __p; |
110 | # endif |
111 | }); |
112 | |
113 | try { |
114 | ::new (__ex) _Ep2(__e); |
115 | return exception_ptr::__from_native_exception_pointer(__ex); |
116 | } catch (...) { |
117 | __cxxabiv1::__cxa_free_exception(__ex); |
118 | return current_exception(); |
119 | } |
120 | # else |
121 | try { |
122 | throw __e; |
123 | } catch (...) { |
124 | return current_exception(); |
125 | } |
126 | # endif |
127 | # else |
128 | ((void)__e); |
129 | std::abort(); |
130 | # endif |
131 | } |
132 | |
133 | #else // _LIBCPP_ABI_MICROSOFT |
134 | |
135 | class _LIBCPP_EXPORTED_FROM_ABI exception_ptr { |
136 | _LIBCPP_DIAGNOSTIC_PUSH |
137 | _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wunused-private-field" ) |
138 | void* __ptr1_; |
139 | void* __ptr2_; |
140 | _LIBCPP_DIAGNOSTIC_POP |
141 | |
142 | public: |
143 | exception_ptr() _NOEXCEPT; |
144 | exception_ptr(nullptr_t) _NOEXCEPT; |
145 | exception_ptr(const exception_ptr& __other) _NOEXCEPT; |
146 | exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT; |
147 | exception_ptr& operator=(nullptr_t) _NOEXCEPT; |
148 | ~exception_ptr() _NOEXCEPT; |
149 | explicit operator bool() const _NOEXCEPT; |
150 | }; |
151 | |
152 | _LIBCPP_EXPORTED_FROM_ABI bool operator==(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT; |
153 | |
154 | inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const exception_ptr& __x, const exception_ptr& __y) _NOEXCEPT { |
155 | return !(__x == __y); |
156 | } |
157 | |
158 | _LIBCPP_EXPORTED_FROM_ABI void swap(exception_ptr&, exception_ptr&) _NOEXCEPT; |
159 | |
160 | _LIBCPP_EXPORTED_FROM_ABI exception_ptr __copy_exception_ptr(void* __except, const void* __ptr); |
161 | _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT; |
162 | _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr); |
163 | |
164 | // This is a built-in template function which automagically extracts the required |
165 | // information. |
166 | template <class _E> |
167 | void* __GetExceptionInfo(_E); |
168 | |
169 | template <class _Ep> |
170 | _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT { |
171 | return __copy_exception_ptr(std::addressof(__e), __GetExceptionInfo(__e)); |
172 | } |
173 | |
174 | #endif // _LIBCPP_ABI_MICROSOFT |
175 | } // namespace std |
176 | |
177 | #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H |
178 | |