@@ -30,6 +30,28 @@ _LIBCPP_PUSH_MACROS
3030
3131#ifndef _LIBCPP_ABI_MICROSOFT
3232
33+ // Previously, parts of exception_ptr were defined out-of-line, which prevented
34+ // useful compiler optimizations. Changing the out-of-line definitions to inline
35+ // definitions is an ABI break, however. To prevent this, we have to make sure
36+ // the symbols remain available in the libc++ library, in addition to being
37+ // defined inline here in this header.
38+ // To this end, we use _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE macro:
39+ // The macro is defined as empty for src/exception.cpp, forcing the definitions of
40+ // the functions to be emitted and included in the library. When users of libc++
41+ // compile their code, the __gnu_inline__ attribute will suppress generation of
42+ // these functions while making their definitions available for inlining.
43+ #ifdef _LIBCPP_EMIT_CODE_FOR_EXCEPTION_PTR
44+ # define _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE _LIBCPP_EXPORTED_FROM_ABI
45+ #else
46+ # if !__has_cpp_attribute(__gnu__::__gnu_inline__)
47+ # error "GNU inline attribute is not supported"
48+ # endif
49+ # define _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE [[__gnu__::__gnu_inline__]] inline
50+ #endif
51+
52+ _LIBCPP_DIAGNOSTIC_PUSH
53+ _LIBCPP_CLANG_DIAGNOSTIC_IGNORED (" -Wgnu-inline-cpp-without-extern" )
54+
3355# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
3456
3557namespace __cxxabiv1 {
@@ -67,6 +89,11 @@ inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _
6789class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
6890 void * __ptr_;
6991
92+ static void __do_increment_refcount (void * __ptr) _NOEXCEPT;
93+ static void __do_decrement_refcount (void * __ptr) _NOEXCEPT;
94+ _LIBCPP_HIDE_FROM_ABI static void __increment_refcount (void * __ptr) _NOEXCEPT { if (__ptr) __do_increment_refcount (__ptr); }
95+ _LIBCPP_HIDE_FROM_ABI static void __decrement_refcount (void * __ptr) _NOEXCEPT { if (__ptr) __do_decrement_refcount (__ptr); }
96+
7097 static exception_ptr __from_native_exception_pointer (void *) _NOEXCEPT;
7198
7299 template <class _Ep >
@@ -81,17 +108,18 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
81108 _LIBCPP_HIDE_FROM_ABI exception_ptr () _NOEXCEPT : __ptr_() {}
82109 _LIBCPP_HIDE_FROM_ABI exception_ptr (nullptr_t ) _NOEXCEPT : __ptr_() {}
83110
84- exception_ptr (const exception_ptr&) _NOEXCEPT;
111+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr (const exception_ptr&) _NOEXCEPT;
85112 _LIBCPP_HIDE_FROM_ABI exception_ptr (exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) {
86113 __other.__ptr_ = nullptr ;
87114 }
88- exception_ptr& operator =(const exception_ptr&) _NOEXCEPT;
115+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr& operator =(const exception_ptr&) _NOEXCEPT;
89116 _LIBCPP_HIDE_FROM_ABI exception_ptr& operator =(exception_ptr&& __other) _NOEXCEPT {
90- exception_ptr __tmp (std::move (__other));
91- std::swap (__tmp, *this );
117+ __decrement_refcount (__ptr_);
118+ __ptr_ = __other.__ptr_ ;
119+ __other.__ptr_ = nullptr ;
92120 return *this ;
93121 }
94- ~exception_ptr () _NOEXCEPT;
122+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE ~exception_ptr () _NOEXCEPT;
95123
96124 _LIBCPP_HIDE_FROM_ABI explicit operator bool () const _NOEXCEPT { return __ptr_ != nullptr ; }
97125
@@ -109,6 +137,25 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
109137 friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception (exception_ptr);
110138};
111139
140+ // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE
141+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr::exception_ptr (const exception_ptr& __other) _NOEXCEPT
142+ : __ptr_(__other.__ptr_) {
143+ __increment_refcount (__ptr_);
144+ }
145+
146+ // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE
147+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr& exception_ptr::operator =(const exception_ptr& __other) _NOEXCEPT {
148+ if (__ptr_ != __other.__ptr_ ) {
149+ __increment_refcount (__other.__ptr_ );
150+ __decrement_refcount (__ptr_);
151+ __ptr_ = __other.__ptr_ ;
152+ }
153+ return *this ;
154+ }
155+
156+ // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE
157+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr::~exception_ptr () _NOEXCEPT { __decrement_refcount (__ptr_); }
158+
112159inline _LIBCPP_HIDE_FROM_ABI void swap (exception_ptr& __x, exception_ptr& __y) _NOEXCEPT {
113160 std::swap (__x.__ptr_ , __y.__ptr_ );
114161}
@@ -222,6 +269,8 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
222269#endif // _LIBCPP_ABI_MICROSOFT
223270_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
224271
272+ _LIBCPP_DIAGNOSTIC_POP
273+
225274_LIBCPP_POP_MACROS
226275
227276#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
0 commit comments