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