diff --git a/libcxx/include/__config b/libcxx/include/__config --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -114,6 +114,8 @@ # define _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON // Remove vector base class # define _LIBCPP_ABI_DO_NOT_EXPORT_VECTOR_BASE_COMMON +// Use [[no_unique_address]] in compressed_pair +# define _LIBCPP_COMPRESSED_PAIR_USE_NO_UNIQUE_ADDRESS #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h --- a/libcxx/include/__memory/compressed_pair.h +++ b/libcxx/include/__memory/compressed_pair.h @@ -26,6 +26,8 @@ struct __default_init_tag {}; struct __value_init_tag {}; +#ifndef _LIBCPP_COMPRESSED_PAIR_USE_NO_UNIQUE_ADDRESS + template ::value && !__libcpp_is_final<_Tp>::value> struct __compressed_pair_elem { using _ParamT = _Tp; @@ -103,6 +105,9 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair() : _Base1(__value_init_tag()), _Base2(__value_init_tag()) {} + // Use the default constructor instead + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(__value_init_tag, __value_init_tag) = delete; + template _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR explicit __compressed_pair(_U1&& __t1, _U2&& __t2) : _Base1(std::forward<_U1>(__t1)), _Base2(std::forward<_U2>(__t2)) {} @@ -154,6 +159,66 @@ } }; +#else + +template +class __compressed_pair { + _LIBCPP_NO_UNIQUE_ADDRESS _T1 __first; + _LIBCPP_NO_UNIQUE_ADDRESS _T2 __second; +public: + + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair() : __first(), __second() {} + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(__default_init_tag, __default_init_tag) {} + // Use the default constructor instead + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(__value_init_tag, __value_init_tag) = delete; + + template + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(_U1&& __t1, __default_init_tag) + : __first(std::forward<_U1>(__t1)) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(__default_init_tag, _U2&& __t2) + : __second(std::forward<_U2>(__t2)) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(_U1&& __t1, __value_init_tag) + : __first(std::forward<_U1>(__t1)), __second() {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr __compressed_pair(__value_init_tag, _U2&& __t2) + : __first(), __second(std::forward<_U2>(__t2)) {} + + template + _LIBCPP_HIDE_FROM_ABI constexpr + __compressed_pair(_U1&& __t1, _U2&& __t2) : __first(std::forward<_U1>(__t1)), __second(std::forward<_U2>(__t2)) {} + + template + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX14 + __compressed_pair(piecewise_construct_t, tuple<_Args1...> __first_args, tuple<_Args2...> __second_args) + : __first( + piecewise_construct_t{}, + std::forward<_Args1>(std::get::type>(__first_args))...), + __second( + piecewise_construct_t{}, + std::forward<_Args2>(std::get::type>(__second_args))...) {} + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _T1& first() noexcept { return __first; } + _LIBCPP_HIDE_FROM_ABI constexpr const _T1& first() const noexcept { return __first; } + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 _T2& second() noexcept { return __second; } + _LIBCPP_HIDE_FROM_ABI constexpr const _T2& second() const noexcept { return __second; } + + _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 + void swap(__compressed_pair& __other) + noexcept(__is_nothrow_swappable<_T1>::value && __is_nothrow_swappable<_T2>::value) { + using std::swap; + swap(first(), __other.first()); + swap(second(), __other.second()); + } + +}; + +#endif // _LIBCPP_COMPRESSED_PAIR_USE_NO_UNIQUE_ADDRESS + template inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_AFTER_CXX11 void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y) diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h --- a/libcxx/include/__memory/shared_ptr.h +++ b/libcxx/include/__memory/shared_ptr.h @@ -330,6 +330,7 @@ // with Allocator construction for _Tp. To allow implementing P0674 in C++20, // we now use a properly aligned char buffer while making sure that we maintain // the same layout that we had when we used a compressed pair. +#ifndef _LIBCPP_COMPRESSED_PAIR_USE_NO_UNIQUE_ADDRESS using _CompressedPair = __compressed_pair<_Alloc, _Tp>; struct _ALIGNAS_TYPE(_CompressedPair) _Storage { char __blob_[sizeof(_CompressedPair)]; @@ -356,6 +357,19 @@ static_assert(_LIBCPP_ALIGNOF(_Storage) == _LIBCPP_ALIGNOF(_CompressedPair), ""); static_assert(sizeof(_Storage) == sizeof(_CompressedPair), ""); +#else + struct _Storage { + _LIBCPP_NO_UNIQUE_ADDRESS _Alloc __alloc; + _LIBCPP_NO_UNIQUE_ADDRESS union { _Tp __elem; }; + + _LIBCPP_HIDE_FROM_ABI explicit _Storage(_Alloc&& __a) : __alloc(std::move(__a)) {} + _LIBCPP_HIDE_FROM_ABI ~_Storage() {} + + _Alloc* __get_alloc() noexcept { return std::addressof(__alloc); } + _Tp* __get_elem() noexcept { return std::addressof(__elem); } + }; +#endif + _Storage __storage_; }; 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 @@ -168,12 +168,12 @@ template > _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_() {} template > _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} template > @@ -390,12 +390,12 @@ template > _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + _LIBCPP_CONSTEXPR unique_ptr() _NOEXCEPT : __ptr_() {} template > _LIBCPP_INLINE_VISIBILITY - _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_(__value_init_tag(), __value_init_tag()) {} + _LIBCPP_CONSTEXPR unique_ptr(nullptr_t) _NOEXCEPT : __ptr_() {} template , diff --git a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp b/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp --- a/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp +++ b/libcxx/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/libcxx.control_block_layout.pass.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03 +// UNSUPPORTED: libcpp-abi-version=2 // This test makes sure that the control block implementation used for non-array // types in std::make_shared and std::allocate_shared is ABI compatbile with the