aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/memory
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/memory')
-rw-r--r--libcxx/include/memory40
1 files changed, 30 insertions, 10 deletions
diff --git a/libcxx/include/memory b/libcxx/include/memory
index efb10c8fd25b..62235cf72b35 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -810,10 +810,35 @@ public:
};
#endif
+// This class provides a non-trivial default constructor to the class that derives from it
+// if the condition is satisfied.
+//
+// The second template parameter exists to allow giving a unique type to __non_trivial_if,
+// which makes it possible to avoid breaking the ABI when making this a base class of an
+// existing class. Without that, imagine we have classes D1 and D2, both of which used to
+// have no base classes, but which now derive from __non_trivial_if. The layout of a class
+// that inherits from both D1 and D2 will change because the two __non_trivial_if base
+// classes are not allowed to share the same address.
+//
+// By making those __non_trivial_if base classes unique, we work around this problem and
+// it is safe to start deriving from __non_trivial_if in existing classes.
+template <bool _Cond, class _Unique>
+struct __non_trivial_if { };
+
+template <class _Unique>
+struct __non_trivial_if<true, _Unique> {
+ _LIBCPP_INLINE_VISIBILITY
+ _LIBCPP_CONSTEXPR __non_trivial_if() _NOEXCEPT { }
+};
+
// allocator
+//
+// Note: For ABI compatibility between C++20 and previous standards, we make
+// allocator<void> trivial in C++20.
template <class _Tp>
class _LIBCPP_TEMPLATE_VIS allocator
+ : private __non_trivial_if<!is_void<_Tp>::value, allocator<_Tp> >
{
public:
typedef size_t size_type;
@@ -823,7 +848,7 @@ public:
typedef true_type is_always_equal;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- allocator() _NOEXCEPT { }
+ allocator() _NOEXCEPT _LIBCPP_DEFAULT
template <class _Up>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -895,6 +920,7 @@ public:
template <class _Tp>
class _LIBCPP_TEMPLATE_VIS allocator<const _Tp>
+ : private __non_trivial_if<!is_void<_Tp>::value, allocator<const _Tp> >
{
public:
typedef size_t size_type;
@@ -904,7 +930,7 @@ public:
typedef true_type is_always_equal;
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
- allocator() _NOEXCEPT { }
+ allocator() _NOEXCEPT _LIBCPP_DEFAULT
template <class _Up>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
@@ -2745,7 +2771,6 @@ public:
typename enable_if
<
!is_lvalue_reference<_Dp>::value &&
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type = __nat());
@@ -2754,7 +2779,6 @@ public:
typename enable_if
<
is_lvalue_reference<_Dp>::value &&
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type = __nat());
@@ -2795,7 +2819,6 @@ public:
template <class _Yp, class _Dp>
typename enable_if
<
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
shared_ptr&
>::type
@@ -3157,7 +3180,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
typename enable_if
<
!is_lvalue_reference<_Dp>::value &&
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type)
@@ -3170,7 +3192,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
#endif
{
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
- typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk;
+ typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer, _Dp, _AllocT > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
__enable_weak_this(__r.get(), __r.get());
}
@@ -3183,7 +3205,6 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
typename enable_if
<
is_lvalue_reference<_Dp>::value &&
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer, element_type*>::value,
__nat
>::type)
@@ -3196,7 +3217,7 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp>&& __r,
#endif
{
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
- typedef __shared_ptr_pointer<_Yp*,
+ typedef __shared_ptr_pointer<typename unique_ptr<_Yp, _Dp>::pointer,
reference_wrapper<typename remove_reference<_Dp>::type>,
_AllocT > _CntrlBlk;
__cntrl_ = new _CntrlBlk(__r.get(), _VSTD::ref(__r.get_deleter()), _AllocT());
@@ -3280,7 +3301,6 @@ template <class _Yp, class _Dp>
inline
typename enable_if
<
- !is_array<_Yp>::value &&
is_convertible<typename unique_ptr<_Yp, _Dp>::pointer,
typename shared_ptr<_Tp>::element_type*>::value,
shared_ptr<_Tp>&