Index: libcxx/include/exception =================================================================== --- libcxx/include/exception +++ libcxx/include/exception @@ -141,16 +141,72 @@ #ifndef _LIBCPP_ABI_MICROSOFT +// Previously, the copy constructor, assignment operator, and destructor of +// exception_ptr were defined out-of-line, which prevented useful compiler +// optimizations (especially for the case where the exception_ptr is known to +// be empty). Changing the out-of-line definitions to inline definitions is an +// ABI break, however; to prevent this, we have to make sure the symbols +// remain available in the libc++ library, in addition to being defined inline +// here in this header. To this end, we use the __gnu_inline__ attribute via the +// _LIBCPP_EXCEPTION_PTR_GNU_INLINE macro: The macro is defined as empty in +// src/exception.cpp, forcing the definitions of the aforementioned functions to +// be emitted and included in the library. When users of libc++ (re)compile their +// code, however, the _LIBCPP_EXCEPTION_PTR_GNU_INLINE macro won't be defined, +// and thus the __gnu_inline__ attribute will suppress generation of these +// functions while making their definitions available for inlining. +#ifndef _LIBCPP_EXCEPTION_PTR_GNU_INLINE +#if !__has_attribute(__gnu_inline__) +#error "this compiler does not appear to support the __gnu_inline__ attribute!" +#endif + +#ifndef __GLIBCXX__ +#define _LIBCPP_EXCEPTION_PTR_GNU_INLINE __attribute__((__gnu_inline__)) inline +#else +#define _LIBCPP_EXCEPTION_PTR_GNU_INLINE /*empty*/ +#endif +#endif + +_LIBCPP_DIAGNOSTIC_PUSH +_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wgnu-inline-cpp-without-extern") + class _LIBCPP_TYPE_VIS exception_ptr { void* __ptr_; + +#ifndef __GLIBCXX__ + void __incr_refcount() _NOEXCEPT; + void __decr_refcount() _NOEXCEPT; +#endif + public: _LIBCPP_INLINE_VISIBILITY exception_ptr() _NOEXCEPT : __ptr_() {} _LIBCPP_INLINE_VISIBILITY exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} - exception_ptr(const exception_ptr&) _NOEXCEPT; - exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; - ~exception_ptr() _NOEXCEPT; + _LIBCPP_EXCEPTION_PTR_GNU_INLINE exception_ptr(const exception_ptr&) _NOEXCEPT; + _LIBCPP_EXCEPTION_PTR_GNU_INLINE exception_ptr& operator=(const exception_ptr&) _NOEXCEPT; + _LIBCPP_EXCEPTION_PTR_GNU_INLINE ~exception_ptr() _NOEXCEPT; + + _LIBCPP_INLINE_VISIBILITY exception_ptr(exception_ptr&& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { + __rhs.__ptr_ = nullptr; + } + + // Move assignment is not available for the glibcxx ABI because it + // doesn't have __decr_refcount(). +#ifndef __GLIBCXX__ + _LIBCPP_INLINE_VISIBILITY exception_ptr& operator=(exception_ptr&& __rhs) _NOEXCEPT { + if (__ptr_ != nullptr) + __decr_refcount(); + __ptr_ = __rhs.__ptr_; + __rhs.__ptr_ = nullptr; + return *this; + } +#endif + + _LIBCPP_INLINE_VISIBILITY void swap(exception_ptr& __rhs) _NOEXCEPT { + void *__tmp = __ptr_; + __ptr_ = __rhs.__ptr_; + __rhs.__ptr_ = __tmp; + } _LIBCPP_INLINE_VISIBILITY explicit operator bool() const _NOEXCEPT {return __ptr_ != nullptr;} @@ -167,6 +223,44 @@ friend _LIBCPP_FUNC_VIS void rethrow_exception(exception_ptr); }; +// If __GLIBCXX__ is defined, the exception_ptr from libsupc++ is used (which +// works because it happens to have the same layout as our exception_ptr). +// The constructor, assignment operator, and destructor should just delegate +// to the libsupc++ implementations then, so we don't provide definitions for +// them here. +#ifndef __GLIBCXX__ +_LIBCPP_EXCEPTION_PTR_GNU_INLINE +exception_ptr::exception_ptr(const exception_ptr& __rhs) _NOEXCEPT : __ptr_(__rhs.__ptr_) { + if (__rhs.__ptr_ != nullptr) + __incr_refcount(); +} + +_LIBCPP_EXCEPTION_PTR_GNU_INLINE +exception_ptr& exception_ptr::operator=(const exception_ptr& __rhs) _NOEXCEPT { + if (__ptr_ != __rhs.__ptr_) { + if (__ptr_ != nullptr) + __decr_refcount(); + __ptr_ = __rhs.__ptr_; + if (__ptr_ != nullptr) + __incr_refcount(); + } + return *this; +} + +_LIBCPP_EXCEPTION_PTR_GNU_INLINE +exception_ptr::~exception_ptr() _NOEXCEPT { + if (__ptr_ != nullptr) + __decr_refcount(); +} +#endif // __GLIBCXX__ + +_LIBCPP_DIAGNOSTIC_POP // pops CLANG_DIAGNOSTIC_IGNORED("-Wgnu-inline-cpp-without-extern") + +inline _LIBCPP_INLINE_VISIBILITY void +swap(exception_ptr& __lhs, exception_ptr& __rhs) _NOEXCEPT { + __lhs.swap(__rhs); +} + template _LIBCPP_INLINE_VISIBILITY exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT Index: libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist @@ -816,6 +816,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist =================================================================== --- libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist +++ libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist @@ -806,6 +806,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist @@ -254,6 +254,8 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} Index: libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist @@ -254,6 +254,8 @@ {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} +{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'storage_mapping_class': 'DS', 'type': 'FUNC'} {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist @@ -816,6 +816,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist +++ libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.nodebug.noincomplete.abilist @@ -806,6 +806,8 @@ {'is_defined': True, 'name': '__ZNSt13bad_exceptionD0Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD1Ev', 'type': 'I'} {'is_defined': True, 'name': '__ZNSt13bad_exceptionD2Ev', 'type': 'I'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '__ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '__ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.incomplete.abilist @@ -524,6 +524,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.noincomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.noincomplete.abilist +++ libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.debug.noincomplete.abilist @@ -524,6 +524,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.nodebug.incomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.nodebug.incomplete.abilist +++ libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.nodebug.incomplete.abilist @@ -514,6 +514,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.debug.incomplete.abilist =================================================================== --- libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.debug.incomplete.abilist +++ libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.debug.incomplete.abilist @@ -496,6 +496,8 @@ {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD0Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD1Ev', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt12experimental19bad_optional_accessD2Ev', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__decr_refcountEv', 'type': 'FUNC'} +{'is_defined': True, 'name': '_ZNSt13exception_ptr15__incr_refcountEv', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'} {'is_defined': True, 'name': '_ZNSt13exception_ptrD1Ev', 'type': 'FUNC'} Index: libcxx/src/exception.cpp =================================================================== --- libcxx/src/exception.cpp +++ libcxx/src/exception.cpp @@ -6,7 +6,9 @@ // //===----------------------------------------------------------------------===// +#define _LIBCPP_EXCEPTION_PTR_GNU_INLINE /*empty*/ #include + #include #include Index: libcxx/src/support/runtime/exception_pointer_cxxabi.ipp =================================================================== --- libcxx/src/support/runtime/exception_pointer_cxxabi.ipp +++ libcxx/src/support/runtime/exception_pointer_cxxabi.ipp @@ -13,27 +13,15 @@ namespace std { -exception_ptr::~exception_ptr() noexcept { +void exception_ptr::__decr_refcount() noexcept { __cxa_decrement_exception_refcount(__ptr_); } -exception_ptr::exception_ptr(const exception_ptr& other) noexcept - : __ptr_(other.__ptr_) +void exception_ptr::__incr_refcount() noexcept { __cxa_increment_exception_refcount(__ptr_); } -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept -{ - if (__ptr_ != other.__ptr_) - { - __cxa_increment_exception_refcount(other.__ptr_); - __cxa_decrement_exception_refcount(__ptr_); - __ptr_ = other.__ptr_; - } - return *this; -} - nested_exception::nested_exception() noexcept : __ptr_(current_exception()) { Index: libcxx/src/support/runtime/exception_pointer_unimplemented.ipp =================================================================== --- libcxx/src/support/runtime/exception_pointer_unimplemented.ipp +++ libcxx/src/support/runtime/exception_pointer_unimplemented.ipp @@ -12,22 +12,14 @@ namespace std { -exception_ptr::~exception_ptr() noexcept +void exception_ptr::__decr_refcount() noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n"); ::abort(); } -exception_ptr::exception_ptr(const exception_ptr& other) noexcept - : __ptr_(other.__ptr_) -{ -# warning exception_ptr not yet implemented - fprintf(stderr, "exception_ptr not yet implemented\n"); - ::abort(); -} - -exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept +void exception_ptr::__incr_refcount() noexcept { # warning exception_ptr not yet implemented fprintf(stderr, "exception_ptr not yet implemented\n");