From 75c6a925dab5b7af9ab47c10906cb0e140261cc2 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Thu, 24 Oct 2019 16:29:41 +0100 Subject: [PATCH] Revert ABI changes to std::allocator in C++20 The recent C++20 changes to remove the std::allocator explicit specialization and the destructor in the std::allocator primary template change the result of some is_trivially_xxx type traits. To avoid those changes, this patch restores the explicit specialization and the destructor. In order to meet the C++20 requirements the std::allocator explicit specialization must provide the same interface as the primary template (except for the unusable allocate and deallocate member functions) and the destructor in the primary template must be constexpr. * include/bits/allocator.h (allocator): Restore the explicit specialization for C++20, but make its API consistent with the primary template. (allocator::~allocator()): Restore the destructor for C++20, but make it constexpr. * testsuite/20_util/allocator/rebind_c++20.cc: Check allocator. * testsuite/20_util/allocator/requirements/typedefs_c++20.cc: Likewise. * testsuite/20_util/allocator/void.cc: Check that constructors and destructors are trivial. Check for converting constructor in C++20. * testsuite/ext/malloc_allocator/variadic_construct.cc: Simplify dejagnu target selector. * testsuite/ext/new_allocator/variadic_construct.cc: Likewise. From-SVN: r277410 --- libstdc++-v3/ChangeLog | 13 +++++++++++ libstdc++-v3/include/bits/allocator.h | 19 ++++++++++------ .../20_util/allocator/rebind_c++20.cc | 5 ++++- .../allocator/requirements/typedefs_c++20.cc | 11 ++++++++++ .../testsuite/20_util/allocator/void.cc | 22 +++++++++++++++++++ .../malloc_allocator/variadic_construct.cc | 2 +- .../ext/new_allocator/variadic_construct.cc | 2 +- 7 files changed, 64 insertions(+), 10 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 13e834bfb3e..0ae347ee4ff 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,18 @@ 2019-10-24 Jonathan Wakely + * include/bits/allocator.h (allocator): Restore the explicit + specialization for C++20, but make its API consistent with the primary + template. + (allocator::~allocator()): Restore the destructor for C++20, but make + it constexpr. + * testsuite/20_util/allocator/rebind_c++20.cc: Check allocator. + * testsuite/20_util/allocator/requirements/typedefs_c++20.cc: Likewise. + * testsuite/20_util/allocator/void.cc: Check that constructors and + destructors are trivial. Check for converting constructor in C++20. + * testsuite/ext/malloc_allocator/variadic_construct.cc: Simplify + dejagnu target selector. + * testsuite/ext/new_allocator/variadic_construct.cc: Likewise. + * include/experimental/executor (__use_future_ct, use_future_t): Define partial specializations for std::allocator. (__use_future_ch): Overload constructor for completion tokens using diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h index 1a3eb88eded..2559c57b12e 100644 --- a/libstdc++-v3/include/bits/allocator.h +++ b/libstdc++-v3/include/bits/allocator.h @@ -63,23 +63,30 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * @{ */ -#if __cplusplus <= 201703L /// allocator specialization. template<> class allocator { public: + typedef void value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L typedef void* pointer; typedef const void* const_pointer; - typedef void value_type; template struct rebind { typedef allocator<_Tp1> other; }; +#else + allocator() = default; -#if __cplusplus >= 201103L + template + constexpr + allocator(const allocator<_Up>&) { } +#endif // ! C++20 + +#if __cplusplus >= 201103L && __cplusplus <= 201703L // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2103. std::allocator propagate_on_container_move_assignment typedef true_type propagate_on_container_move_assignment; @@ -98,9 +105,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION destroy(_Up* __p) noexcept(noexcept(__p->~_Up())) { __p->~_Up(); } -#endif // C++11 +#endif // C++11 to C++17 }; -#endif // ! C++20 /** * @brief The @a standard allocator, as per [20.4]. @@ -154,9 +160,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX20_CONSTEXPR allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { } -#if __cplusplus <= 201703L + _GLIBCXX20_CONSTEXPR ~allocator() _GLIBCXX_NOTHROW { } -#endif #if __cplusplus > 201703L [[nodiscard,__gnu__::__always_inline__]] diff --git a/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc b/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc index 968e1de931b..dd7cd67f943 100644 --- a/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc +++ b/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc @@ -23,6 +23,9 @@ template struct Alloc : std::allocator { }; using T = std::allocator_traits>; - // Prior to C++20 this finds std::allocator::rebind and so fails: static_assert( std::is_same_v, Alloc> ); + +using V = std::allocator_traits>; +// Prior to C++20 this finds std::allocator::rebind and so fails: +static_assert( std::is_same_v, Alloc> ); diff --git a/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs_c++20.cc b/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs_c++20.cc index e986cc9a809..ef193fb1bf1 100644 --- a/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs_c++20.cc +++ b/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs_c++20.cc @@ -54,3 +54,14 @@ static_assert( !has_rebind ); static_assert( !has_construct ); static_assert( !has_destroy ); static_assert( !has_max_size ); + +using V = std::allocator; + +static_assert( !has_pointer ); +static_assert( !has_const_pointer ); +static_assert( !has_reference ); +static_assert( !has_const_reference ); +static_assert( !has_rebind ); +static_assert( !has_construct ); +static_assert( !has_destroy ); +static_assert( !has_max_size ); diff --git a/libstdc++-v3/testsuite/20_util/allocator/void.cc b/libstdc++-v3/testsuite/20_util/allocator/void.cc index d7aa6bd80ed..9d94fac3cc0 100644 --- a/libstdc++-v3/testsuite/20_util/allocator/void.cc +++ b/libstdc++-v3/testsuite/20_util/allocator/void.cc @@ -33,6 +33,28 @@ test01() std::allocator_traits::destroy(a, &i); } +// These properties are formally unspecified, but have always been true for +// the libstdc++ definition of allocator. +static_assert( + std::is_trivially_default_constructible>::value, + "explicit specialization has trivial default constructor"); +static_assert( + std::is_trivially_copy_constructible>::value, + "explicit specialization has trivial copy constructor"); +static_assert( + std::is_trivially_move_constructible>::value, + "explicit specialization has trivial move constructor"); +static_assert( + std::is_trivially_destructible>::value, + "explicit specialization has trivial destructor"); + +#if __cplusplus > 201703L +// C++20 removes the allocator explicit specialization, so it can now be +// constructed using the converting constructor from other specializations. +static_assert( std::is_constructible_v, + std::allocator> ); +#endif + int main() { diff --git a/libstdc++-v3/testsuite/ext/malloc_allocator/variadic_construct.cc b/libstdc++-v3/testsuite/ext/malloc_allocator/variadic_construct.cc index b786fae9f0a..f122768d8ac 100644 --- a/libstdc++-v3/testsuite/ext/malloc_allocator/variadic_construct.cc +++ b/libstdc++-v3/testsuite/ext/malloc_allocator/variadic_construct.cc @@ -1,4 +1,4 @@ -// { dg-do run { target { { c++11_only || c++14_only } || c++17_only } } } +// { dg-do run { target { c++11 && { ! c++2a } } } } // 2007-10-26 Paolo Carlini diff --git a/libstdc++-v3/testsuite/ext/new_allocator/variadic_construct.cc b/libstdc++-v3/testsuite/ext/new_allocator/variadic_construct.cc index 5b23e5b4a2c..cfe93a7b6d9 100644 --- a/libstdc++-v3/testsuite/ext/new_allocator/variadic_construct.cc +++ b/libstdc++-v3/testsuite/ext/new_allocator/variadic_construct.cc @@ -1,4 +1,4 @@ -// { dg-do run { target { { c++11_only || c++14_only } || c++17_only } } } +// { dg-do run { target { c++11 && { ! c++2a } } } } // 2007-10-26 Paolo Carlini -- 2.30.2