Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions libcxx/docs/ReleaseNotes/22.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ Improvements and New Features
iterators, resulting in a performance improvement for ``std::deque<short>`` and
``std::join_view<vector<vector<short>>>`` iterators.

- ``std::exception_ptr`` was optimized, allowing the compiler to generate better code especially for empty
``std::exception_ptr`` values.

Deprecations and Removals
-------------------------

Expand Down
6 changes: 6 additions & 0 deletions libcxx/include/__configuration/availability.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,12 @@
#define _LIBCPP_AVAILABILITY_HAS_PMR _LIBCPP_INTRODUCED_IN_LLVM_16
#define _LIBCPP_AVAILABILITY_PMR

// This macro controls the availability of exception_ptr::__{inc,dec}rement_refcount
// which are used in the inline implementations of exception_ptr's move constructor,
// assignment operator, and destructor (see libcxx/include/__exception/exception_ptr.h).
#define _LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR _LIBCPP_INTRODUCED_IN_LLVM_21
// No attribute, since we've have a fallback implementation in the headers

// These macros controls the availability of __cxa_init_primary_exception
// in the built library, which std::make_exception_ptr might use
// (see libcxx/include/__exception/exception_ptr.h).
Expand Down
51 changes: 32 additions & 19 deletions libcxx/include/__exception/exception_ptr.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,13 @@
#include <__memory/construct_at.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_pointer.h>
#include <__utility/move.h>
#include <__utility/swap.h>
#include <__verbose_abort>
#include <typeinfo>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

#ifndef _LIBCPP_ABI_MICROSOFT

# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
Expand Down Expand Up @@ -63,11 +58,12 @@ _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD

#ifndef _LIBCPP_ABI_MICROSOFT

inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT;

class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
void* __ptr_;

static void __increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void*) _NOEXCEPT;
static void __decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void*) _NOEXCEPT;

static exception_ptr __from_native_exception_pointer(void*) _NOEXCEPT;

template <class _Ep>
Expand All @@ -82,17 +78,42 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
_LIBCPP_HIDE_FROM_ABI exception_ptr() _NOEXCEPT : __ptr_() {}
_LIBCPP_HIDE_FROM_ABI exception_ptr(nullptr_t) _NOEXCEPT : __ptr_() {}

// These symbols are still exported from the library to prevent ABI breakage.
# if defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR
exception_ptr(const exception_ptr&) _NOEXCEPT;
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
~exception_ptr() _NOEXCEPT;
# else // defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR
_LIBCPP_HIDE_FROM_ABI exception_ptr(const exception_ptr& __other) _NOEXCEPT : __ptr_(__other.__ptr_) {
if (__ptr_)
__increment_refcount(__ptr_);
}
_LIBCPP_HIDE_FROM_ABI exception_ptr& operator=(const exception_ptr& __other) _NOEXCEPT {
if (__ptr_ == __other.__ptr_)
return *this;
if (__other.__ptr_)
__increment_refcount(__other.__ptr_);
if (__ptr_)
__decrement_refcount(__ptr_);
__ptr_ = __other.__ptr_;
return *this;
}
_LIBCPP_HIDE_FROM_ABI ~exception_ptr() _NOEXCEPT {
if (__ptr_)
__decrement_refcount(__ptr_);
}
# endif // defined(_LIBCPP_BUILDING_LIBRARY) || !_LIBCPP_AVAILABILITY_HAS_INCREMENT_DECREMENT_REFCOUNT_EXCEPTION_PTR

_LIBCPP_HIDE_FROM_ABI exception_ptr(exception_ptr&& __other) _NOEXCEPT : __ptr_(__other.__ptr_) {
__other.__ptr_ = nullptr;
}
exception_ptr& operator=(const exception_ptr&) _NOEXCEPT;
_LIBCPP_HIDE_FROM_ABI exception_ptr& operator=(exception_ptr&& __other) _NOEXCEPT {
exception_ptr __tmp(std::move(__other));
std::swap(__tmp, *this);
if (__ptr_)
__decrement_refcount(__ptr_);
__ptr_ = __other.__ptr_;
__other.__ptr_ = nullptr;
Comment on lines +111 to +114
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change required?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

We have 3 choices:

  1. implement both swap and the move operator, delegate move to swap (previous solution)
  2. implement both swap and the move operator independently (currently in review)
  3. implement only the move operator, and don't provide a specialization for swap

To me, (3) actually feels most natural. My gut feeling tells me that "move" assignments are more frequently used/specialized than swap, so it feels more natural to implement the more common function (move) and delegate the less frequently used (swap) to the other one

I updated the PR accordingly. Please let me know in case you prefer going into a different direction

return *this;
}
~exception_ptr() _NOEXCEPT;

_LIBCPP_HIDE_FROM_ABI explicit operator bool() const _NOEXCEPT { return __ptr_ != nullptr; }

Expand All @@ -104,16 +125,10 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr {
return !(__x == __y);
}

friend _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT;

friend _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
friend _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
};

inline _LIBCPP_HIDE_FROM_ABI void swap(exception_ptr& __x, exception_ptr& __y) _NOEXCEPT {
std::swap(__x.__ptr_, __y.__ptr_);
}

# if _LIBCPP_HAS_EXCEPTIONS
# if _LIBCPP_AVAILABILITY_HAS_INIT_PRIMARY_EXCEPTION
template <class _Ep>
Expand Down Expand Up @@ -223,6 +238,4 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
#endif // _LIBCPP_ABI_MICROSOFT
_LIBCPP_END_UNVERSIONED_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
Original file line number Diff line number Diff line change
Expand Up @@ -858,6 +858,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_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,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_ptr20__decrement_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', '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'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,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_ptr20__decrement_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', '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'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -857,6 +857,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_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,8 @@
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD0Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13bad_exceptionD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,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_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,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_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,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_ptr20__decrement_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr20__increment_refcountEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptr31__from_native_exception_pointerEPv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC1ERKS_', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt13exception_ptrC2ERKS_', 'type': 'FUNC'}
Expand Down
1 change: 0 additions & 1 deletion libcxx/modules/std/exception.inc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export namespace std {
using std::rethrow_exception;
using std::rethrow_if_nested;
using std::set_terminate;
using std::swap;
using std::terminate;
using std::terminate_handler;
using std::throw_with_nested;
Expand Down
3 changes: 3 additions & 0 deletions libcxx/src/exception.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,15 @@ using namespace __cxxabiv1;
#elif defined(_LIBCPPABI_VERSION)
# include "support/runtime/exception_libcxxabi.ipp"
# include "support/runtime/exception_pointer_cxxabi.ipp"
# include "support/runtime/exception_pointer_refcounted.ipp"
#elif defined(LIBCXXRT)
# include "support/runtime/exception_libcxxrt.ipp"
# include "support/runtime/exception_pointer_cxxabi.ipp"
# include "support/runtime/exception_pointer_refcounted.ipp"
#elif defined(__GLIBCXX__)
# include "support/runtime/exception_glibcxx.ipp"
# include "support/runtime/exception_pointer_glibcxx.ipp"
# include "support/runtime/exception_pointer_refcounted.ipp"
#else
# include "include/atomic_support.h"
# include "support/runtime/exception_fallback.ipp"
Expand Down
23 changes: 4 additions & 19 deletions libcxx/src/support/runtime/exception_pointer_cxxabi.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,12 @@

namespace std {

exception_ptr::~exception_ptr() noexcept { __cxa_decrement_exception_refcount(__ptr_); }

exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) {
__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;
void exception_ptr::__increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept {
__cxa_increment_exception_refcount(__ptr);
}

exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept {
exception_ptr ptr;
ptr.__ptr_ = __e;
__cxa_increment_exception_refcount(ptr.__ptr_);

return ptr;
void exception_ptr::__decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept {
__cxa_decrement_exception_refcount(__ptr);
}

nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {}
Expand Down
33 changes: 9 additions & 24 deletions libcxx/src/support/runtime/exception_pointer_glibcxx.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
// it uses to implement std::exception_ptr (which it declares as an alias of
// std::__exception_ptr::exception_ptr) is not directly exported to clients. So
// we have little choice but to hijack std::__exception_ptr::exception_ptr's
// (which fortunately has the same layout as our std::exception_ptr) copy
// constructor, assignment operator and destructor (which are part of its
// stable ABI), and its rethrow_exception(std::__exception_ptr::exception_ptr)
// function.
// _M_addref and _M_release and its rethrow_exception function. Fortunately,
// glibcxx's exception_ptr has the same layout as our exception_ptr and we can
// reinterpret_cast between the two.

namespace std {

Expand All @@ -23,34 +22,20 @@ namespace __exception_ptr {
struct exception_ptr {
void* __ptr_;

explicit exception_ptr(void*) noexcept;
exception_ptr(const exception_ptr&) noexcept;
exception_ptr& operator=(const exception_ptr&) noexcept;
~exception_ptr() noexcept;
void _M_addref() noexcept;
void _M_release() noexcept;
};

} // namespace __exception_ptr

[[noreturn]] void rethrow_exception(__exception_ptr::exception_ptr);

exception_ptr::~exception_ptr() noexcept { reinterpret_cast<__exception_ptr::exception_ptr*>(this)->~exception_ptr(); }

exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) {
new (reinterpret_cast<void*>(this))
__exception_ptr::exception_ptr(reinterpret_cast<const __exception_ptr::exception_ptr&>(other));
}

exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept {
*reinterpret_cast<__exception_ptr::exception_ptr*>(this) =
reinterpret_cast<const __exception_ptr::exception_ptr&>(other);
return *this;
void exception_ptr::__increment_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept {
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->_M_addref();
}

exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept {
exception_ptr ptr{};
new (reinterpret_cast<void*>(&ptr)) __exception_ptr::exception_ptr(__e);

return ptr;
void exception_ptr::__decrement_refcount([[__gnu__::__nonnull__]] _LIBCPP_NOESCAPE void* __ptr) noexcept {
reinterpret_cast<__exception_ptr::exception_ptr*>(this)->_M_release();
}

nested_exception::nested_exception() noexcept : __ptr_(current_exception()) {}
Expand Down
37 changes: 37 additions & 0 deletions libcxx/src/support/runtime/exception_pointer_refcounted.ipp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// Provides the common functionality shared between cxxabi and glibcxx.

namespace std {

exception_ptr exception_ptr::__from_native_exception_pointer(void* __e) noexcept {
exception_ptr ptr;
ptr.__ptr_ = __e;
__increment_refcount(ptr.__ptr_);

return ptr;
}

exception_ptr::~exception_ptr() noexcept { __decrement_refcount(__ptr_); }

exception_ptr::exception_ptr(const exception_ptr& other) noexcept : __ptr_(other.__ptr_) {
__increment_refcount(__ptr_);
}

exception_ptr& exception_ptr::operator=(const exception_ptr& other) noexcept {
if (__ptr_ != other.__ptr_) {
__increment_refcount(other.__ptr_);
__decrement_refcount(__ptr_);
__ptr_ = other.__ptr_;
}
return *this;
}

} // namespace std
Loading