1515#include  < __memory/addressof.h> 
1616#include  < __memory/construct_at.h> 
1717#include  < __type_traits/decay.h> 
18+ #include  < __type_traits/is_pointer.h> 
1819#include  < cstdlib> 
1920#include  < typeinfo> 
2021
@@ -62,7 +63,7 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
6263  static  exception_ptr __from_native_exception_pointer (void *) _NOEXCEPT;
6364
6465  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;
6667
6768public: 
6869  //  exception_ptr is basically a COW string so it is trivially relocatable.
@@ -91,25 +92,21 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
9192  friend  _LIBCPP_EXPORTED_FROM_ABI void  rethrow_exception (exception_ptr);
9293};
9394
94- template  <class  _Ep >
95- _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr (_Ep __e) _NOEXCEPT {
9695#  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 {
9899  using  _Ep2 = __decay_t <_Ep>;
99- 
100100  void * __ex = __cxxabiv1::__cxa_allocate_exception (sizeof (_Ep));
101101#      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+   };
105106#      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)); };
111108#      endif 
112-       } );
109+   ( void ) __cxxabiv1::__cxa_init_primary_exception (__ex,  const_cast <std::type_info*>(& typeid (_Ep)), __cleanup );
113110
114111  try  {
115112    ::new  (__ex) _Ep2 (__e);
@@ -118,18 +115,47 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
118115    __cxxabiv1::__cxa_free_exception (__ex);
119116    return  current_exception ();
120117  }
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 {
122123  try  {
123124    throw  __e;
124125  } catch  (...) {
125126    return  current_exception ();
126127  }
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);
127151#    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 {
130156  std::abort ();
131- #  endif
132157}
158+ #  endif  //  _LIBCPP_HAS_EXCEPTIONS
133159
134160#else  //  _LIBCPP_ABI_MICROSOFT
135161
0 commit comments