@@ -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,17 @@ 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 {
95+ if (__ptr)
96+ __do_increment_refcount (__ptr);
97+ }
98+ _LIBCPP_HIDE_FROM_ABI static void __decrement_refcount (void * __ptr) _NOEXCEPT {
99+ if (__ptr)
100+ __do_decrement_refcount (__ptr);
101+ }
102+
70103 static exception_ptr __from_native_exception_pointer (void *) _NOEXCEPT;
71104
72105 template <class _Ep >
@@ -81,17 +114,18 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
81114 _LIBCPP_HIDE_FROM_ABI exception_ptr () _NOEXCEPT : __ptr_() {}
82115 _LIBCPP_HIDE_FROM_ABI exception_ptr (nullptr_t ) _NOEXCEPT : __ptr_() {}
83116
84- exception_ptr (const exception_ptr&) _NOEXCEPT;
117+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr (const exception_ptr&) _NOEXCEPT;
85118 _LIBCPP_HIDE_FROM_ABI exception_ptr (exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) {
86119 __other.__ptr_ = nullptr ;
87120 }
88- exception_ptr& operator =(const exception_ptr&) _NOEXCEPT;
121+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr& operator =(const exception_ptr&) _NOEXCEPT;
89122 _LIBCPP_HIDE_FROM_ABI exception_ptr& operator =(exception_ptr&& __other) _NOEXCEPT {
90- exception_ptr __tmp (std::move (__other));
91- std::swap (__tmp, *this );
123+ __decrement_refcount (__ptr_);
124+ __ptr_ = __other.__ptr_ ;
125+ __other.__ptr_ = nullptr ;
92126 return *this ;
93127 }
94- ~exception_ptr () _NOEXCEPT;
128+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE ~exception_ptr () _NOEXCEPT;
95129
96130 _LIBCPP_HIDE_FROM_ABI explicit operator bool () const _NOEXCEPT { return __ptr_ != nullptr ; }
97131
@@ -109,6 +143,25 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
109143 friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception (exception_ptr);
110144};
111145
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 (const exception_ptr& __other) _NOEXCEPT
148+ : __ptr_(__other.__ptr_) {
149+ __increment_refcount (__ptr_);
150+ }
151+
152+ // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE
153+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr& exception_ptr::operator =(const exception_ptr& __other) _NOEXCEPT {
154+ if (__ptr_ != __other.__ptr_ ) {
155+ __increment_refcount (__other.__ptr_ );
156+ __decrement_refcount (__ptr_);
157+ __ptr_ = __other.__ptr_ ;
158+ }
159+ return *this ;
160+ }
161+
162+ // Must be defined outside the class definition due to _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE
163+ _LIBCPP_EXPORTED_FROM_LIB_INLINEABLE exception_ptr::~exception_ptr () _NOEXCEPT { __decrement_refcount (__ptr_); }
164+
112165inline _LIBCPP_HIDE_FROM_ABI void swap (exception_ptr& __x, exception_ptr& __y) _NOEXCEPT {
113166 std::swap (__x.__ptr_ , __y.__ptr_ );
114167}
@@ -222,6 +275,8 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
222275#endif // _LIBCPP_ABI_MICROSOFT
223276_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
224277
278+ _LIBCPP_DIAGNOSTIC_POP
279+
225280_LIBCPP_POP_MACROS
226281
227282#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
0 commit comments