15
15
#include < __memory/addressof.h>
16
16
#include < __memory/construct_at.h>
17
17
#include < __type_traits/decay.h>
18
+ #include < __type_traits/is_pointer.h>
18
19
#include < cstdlib>
19
20
#include < typeinfo>
20
21
@@ -62,7 +63,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
62
63
static exception_ptr __from_native_exception_pointer (void *) _NOEXCEPT;
63
64
64
65
template <class _Ep >
65
- friend _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr (_Ep) _NOEXCEPT;
66
+ friend _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit (_Ep& ) _NOEXCEPT;
66
67
67
68
public:
68
69
// exception_ptr is basically a COW string so it is trivially relocatable.
@@ -91,25 +92,21 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
91
92
friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception (exception_ptr);
92
93
};
93
94
94
- template <class _Ep >
95
- _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr (_Ep __e) _NOEXCEPT {
96
95
# if _LIBCPP_HAS_EXCEPTIONS
97
- # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && __cplusplus >= 201103L
96
+ # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
97
+ template <class _Ep >
98
+ _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_explicit (_Ep& __e) _NOEXCEPT {
98
99
using _Ep2 = __decay_t <_Ep>;
99
-
100
100
void * __ex = __cxxabiv1::__cxa_allocate_exception (sizeof (_Ep));
101
101
# ifdef __wasm__
102
- // In Wasm, a destructor returns its argument
103
- (void )__cxxabiv1::__cxa_init_primary_exception (
104
- __ex, const_cast <std::type_info*>(&typeid (_Ep)), [](void * __p) -> void * {
102
+ auto __cleanup = [](void * __p) -> void * {
103
+ std::__destroy_at (static_cast <_Ep2*>(__p));
104
+ return __p;
105
+ };
105
106
# else
106
- (void )__cxxabiv1::__cxa_init_primary_exception (__ex, const_cast <std::type_info*>(&typeid (_Ep)), [](void * __p) {
107
- # endif
108
- std::__destroy_at (static_cast <_Ep2*>(__p));
109
- # ifdef __wasm__
110
- return __p;
107
+ auto __cleanup = [](void * __p) { std::__destroy_at (static_cast <_Ep2*>(__p)); };
111
108
# endif
112
- } );
109
+ ( void ) __cxxabiv1::__cxa_init_primary_exception (__ex, const_cast <std::type_info*>(& typeid (_Ep)), __cleanup );
113
110
114
111
try {
115
112
::new (__ex) _Ep2 (__e);
@@ -118,18 +115,47 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
118
115
__cxxabiv1::__cxa_free_exception (__ex);
119
116
return current_exception ();
120
117
}
121
- # else
118
+ }
119
+ # endif
120
+
121
+ template <class _Ep >
122
+ _LIBCPP_HIDE_FROM_ABI exception_ptr __make_exception_ptr_via_throw (_Ep& __e) _NOEXCEPT {
122
123
try {
123
124
throw __e;
124
125
} catch (...) {
125
126
return current_exception ();
126
127
}
128
+ }
129
+
130
+ template <class _Ep >
131
+ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr (_Ep __e) _NOEXCEPT {
132
+ // Objective-C exceptions are thrown via pointer. When throwing an Objective-C exception,
133
+ // Clang generates a call to `objc_exception_throw` instead of the usual `__cxa_throw`.
134
+ // That function creates an exception with a special Objective-C typeinfo instead of
135
+ // the usual C++ typeinfo, since that is needed to implement the behavior documented
136
+ // at [1]).
137
+ //
138
+ // Because of this special behavior, we can't create an exception via `__cxa_init_primary_exception`
139
+ // for Objective-C exceptions, otherwise we'd bypass `objc_exception_throw`. See https://llvm.org/PR135089.
140
+ //
141
+ // [1]:
142
+ // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Exceptions/Articles/Exceptions64Bit.html
143
+ if _LIBCPP_CONSTEXPR (is_pointer<_Ep>::value) {
144
+ return std::__make_exception_ptr_via_throw (__e);
145
+ }
146
+
147
+ # if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION && !defined(_LIBCPP_CXX03_LANG)
148
+ return std::__make_exception_ptr_explicit (__e);
149
+ # else
150
+ return std::__make_exception_ptr_via_throw (__e);
127
151
# endif
128
- # else
129
- ((void )__e);
152
+ }
153
+ # else // !_LIBCPP_HAS_EXCEPTIONS
154
+ template <class _Ep >
155
+ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr (_Ep) _NOEXCEPT {
130
156
std::abort ();
131
- # endif
132
157
}
158
+ # endif // _LIBCPP_HAS_EXCEPTIONS
133
159
134
160
#else // _LIBCPP_ABI_MICROSOFT
135
161
0 commit comments