diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -156,6 +156,11 @@ // The implementation moved to the header, but we still export the symbols from // the dylib for backwards compatibility. # define _LIBCPP_ABI_DO_NOT_EXPORT_TO_CHARS_BASE_10 + +// Defines exactly one std::default_delete for the whole program, as opposed +// to one per std::unique_ptr (only relevant to std::unique_ptr: other instances +// can still exist). +# define _LIBCPP_EXACTLY_ONE_DEFAULT_DELETE_PER_TYPE # elif _LIBCPP_ABI_VERSION == 1 # if !(defined(_LIBCPP_OBJECT_FORMAT_COFF) || defined(_LIBCPP_OBJECT_FORMAT_XCOFF)) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/include/__memory/unique_ptr.h b/libcxx/include/__memory/unique_ptr.h --- a/libcxx/include/__memory/unique_ptr.h +++ b/libcxx/include/__memory/unique_ptr.h @@ -35,7 +35,9 @@ #include <__type_traits/is_swappable.h> #include <__type_traits/is_void.h> #include <__type_traits/remove_extent.h> +#include <__type_traits/remove_pointer.h> #include <__type_traits/type_identity.h> +#include <__utility/exchange.h> #include <__utility/forward.h> #include <__utility/move.h> #include @@ -131,7 +133,8 @@ "the specified deleter type cannot be an rvalue reference"); private: - __compressed_pair __ptr_; + _LIBCPP_NO_UNIQUE_ADDRESS pointer __ptr_; + _LIBCPP_NO_UNIQUE_ADDRESS deleter_type __deleter_; struct __nat { int __for_bool_; }; @@ -177,27 +180,27 @@ >::type; public: - template > - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + template > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {} - template > - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + template > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : unique_ptr() {} template > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(pointer __p) _NOEXCEPT - : __ptr_(__p, __value_init_tag()) {} + : __ptr_(__p), + __deleter_() {} template > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(pointer __p, _LValRefType<_Dummy> __d) _NOEXCEPT - : __ptr_(__p, __d) {} + : __ptr_(__p), + __deleter_(__d) {} template > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 - unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT : __ptr_(__p, _VSTD::move(__d)) { + unique_ptr(pointer __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT + : __ptr_(__p), + __deleter_(_VSTD::move(__d)) { static_assert(!is_reference::value, "rvalue deleter bound to reference"); } @@ -208,28 +211,30 @@ unique_ptr(pointer __p, _BadRValRefType<_Dummy> __d) = delete; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT - : __ptr_(__u.release(), _VSTD::forward(__u.get_deleter())) {} + : __ptr_(__u.release()), + __deleter_(_VSTD::forward(__u.get_deleter())) {} template , _Up>, class = _EnableIfDeleterConvertible<_Ep> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT - : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {} + : __ptr_(__u.release()), + __deleter_(_VSTD::forward<_Ep>(__u.get_deleter())) {} #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_AUTO_PTR) template - _LIBCPP_INLINE_VISIBILITY - unique_ptr(auto_ptr<_Up>&& __p, - typename enable_if::value && - is_same<_Dp, default_delete<_Tp> >::value, - __nat>::type = __nat()) _NOEXCEPT - : __ptr_(__p.release(), __value_init_tag()) {} + _LIBCPP_INLINE_VISIBILITY unique_ptr( + auto_ptr<_Up>&& __p, + typename enable_if::value && is_same<_Dp, default_delete<_Tp> >::value, __nat>::type = + __nat()) _NOEXCEPT + : __ptr_(__p.release()), + __deleter_() {} #endif _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); - __ptr_.second() = _VSTD::forward(__u.get_deleter()); + __deleter_ = _VSTD::forward(__u.get_deleter()); return *this; } @@ -239,7 +244,7 @@ class = _EnableIfDeleterAssignable<_Ep> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { reset(__u.release()); - __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); + __deleter_ = _VSTD::forward<_Ep>(__u.get_deleter()); return *this; } @@ -268,41 +273,37 @@ } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator*() const { - return *__ptr_.first(); - } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { - return __ptr_.first(); - } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_.first(); } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { - return __ptr_.second(); + return *__ptr_; } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer operator->() const _NOEXCEPT { return __ptr_; } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT { - return __ptr_.second(); + return __deleter_; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT { - return __ptr_.first() != nullptr; + return __ptr_ != nullptr; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT { - pointer __t = __ptr_.first(); - __ptr_.first() = pointer(); + pointer __t = __ptr_; + __ptr_ = pointer(); return __t; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(pointer __p = pointer()) _NOEXCEPT { - pointer __tmp = __ptr_.first(); - __ptr_.first() = __p; + pointer __tmp = __ptr_; + __ptr_ = __p; if (__tmp) - __ptr_.second()(__tmp); + __deleter_(__tmp); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT { - __ptr_.swap(__u.__ptr_); + std::swap(__ptr_, __u.__ptr_); + std::swap(__deleter_, __u.__deleter_); } }; - template class _LIBCPP_UNIQUE_PTR_TRIVIAL_ABI _LIBCPP_TEMPLATE_VIS unique_ptr<_Tp[], _Dp> { public: @@ -311,7 +312,8 @@ typedef typename __pointer<_Tp, deleter_type>::type pointer; private: - __compressed_pair __ptr_; + _LIBCPP_NO_UNIQUE_ADDRESS pointer __ptr_; + _LIBCPP_NO_UNIQUE_ADDRESS deleter_type __deleter_; template struct _CheckArrayPointerConversion : is_same<_From, pointer> {}; @@ -375,47 +377,48 @@ >::type; public: - template > - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + template > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(), __deleter_() {} - template > - _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + template > + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : unique_ptr() {} template , class = _EnableIfPointerConvertible<_Pp> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit unique_ptr(_Pp __p) _NOEXCEPT - : __ptr_(__p, __value_init_tag()) {} + : __ptr_(__p), + __deleter_() {} template >, class = _EnableIfPointerConvertible<_Pp> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __p, _LValRefType<_Dummy> __d) _NOEXCEPT - : __ptr_(__p, __d) {} + : __ptr_(__p), + __deleter_(__d) {} template > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _LValRefType<_Dummy> __d) _NOEXCEPT - : __ptr_(nullptr, __d) {} + : __ptr_(nullptr), + __deleter_(__d) {} template >, class = _EnableIfPointerConvertible<_Pp> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(_Pp __p, _GoodRValRefType<_Dummy> __d) _NOEXCEPT - : __ptr_(__p, _VSTD::move(__d)) { + : __ptr_(__p), + __deleter_(_VSTD::move(__d)) { static_assert(!is_reference::value, "rvalue deleter bound to reference"); } template > > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(nullptr_t, _GoodRValRefType<_Dummy> __d) _NOEXCEPT - : __ptr_(nullptr, _VSTD::move(__d)) { + : __ptr_(nullptr), + __deleter_(_VSTD::move(__d)) { static_assert(!is_reference::value, "rvalue deleter bound to reference"); } @@ -427,11 +430,12 @@ unique_ptr(_Pp __p, _BadRValRefType<_Dummy> __d) = delete; _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr&& __u) _NOEXCEPT - : __ptr_(__u.release(), _VSTD::forward(__u.get_deleter())) {} + : __ptr_(__u.release()), + __deleter_(_VSTD::forward(__u.get_deleter())) {} _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr&& __u) _NOEXCEPT { reset(__u.release()); - __ptr_.second() = _VSTD::forward(__u.get_deleter()); + __deleter_ = _VSTD::forward(__u.get_deleter()); return *this; } @@ -440,7 +444,8 @@ class = _EnableIfMoveConvertible, _Up>, class = _EnableIfDeleterConvertible<_Ep> > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT - : __ptr_(__u.release(), _VSTD::forward<_Ep>(__u.get_deleter())) {} + : __ptr_(__u.release()), + __deleter_(_VSTD::forward<_Ep>(__u.get_deleter())) {} template > _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) _NOEXCEPT { reset(__u.release()); - __ptr_.second() = _VSTD::forward<_Ep>(__u.get_deleter()); + __deleter_ = _VSTD::forward<_Ep>(__u.get_deleter()); return *this; } @@ -466,24 +471,22 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 __add_lvalue_reference_t<_Tp> operator[](size_t __i) const { - return __ptr_.first()[__i]; + return __ptr_[__i]; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_.first(); } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer get() const _NOEXCEPT { return __ptr_; } - _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { - return __ptr_.second(); - } + _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 deleter_type& get_deleter() _NOEXCEPT { return __deleter_; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 const deleter_type& get_deleter() const _NOEXCEPT { - return __ptr_.second(); + return __deleter_; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 explicit operator bool() const _NOEXCEPT { - return __ptr_.first() != nullptr; + return __ptr_ != nullptr; } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 pointer release() _NOEXCEPT { - pointer __t = __ptr_.first(); - __ptr_.first() = pointer(); + pointer __t = __ptr_; + __ptr_ = pointer(); return __t; } @@ -491,21 +494,22 @@ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 typename enable_if< _CheckArrayPointerConversion<_Pp>::value >::type reset(_Pp __p) _NOEXCEPT { - pointer __tmp = __ptr_.first(); - __ptr_.first() = __p; + pointer __tmp = __ptr_; + __ptr_ = __p; if (__tmp) - __ptr_.second()(__tmp); + __deleter_(__tmp); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void reset(nullptr_t = nullptr) _NOEXCEPT { - pointer __tmp = __ptr_.first(); - __ptr_.first() = nullptr; + pointer __tmp = __ptr_; + __ptr_ = nullptr; if (__tmp) - __ptr_.second()(__tmp); + __deleter_(__tmp); } _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX23 void swap(unique_ptr& __u) _NOEXCEPT { - __ptr_.swap(__u.__ptr_); + std::swap(__ptr_, __u.__ptr_); + std::swap(__deleter_, __u.__deleter_); } };