From: Jonathan Wakely Date: Tue, 22 Oct 2019 21:48:39 +0000 (+0100) Subject: Remove redundant std::allocator members for C++20 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2cae56bd61a048b0fac5c2829283744abc44c545;p=gcc.git Remove redundant std::allocator members for C++20 C++20 removes a number of std::allocator members that have correct defaults provided by std::allocator_traits, so aren't needed. Several extensions including __gnu_cxx::hash_map and tr1 containers are no longer usable with std::allocator in C++20 mode. They need to be updated to use __gnu_cxx::__alloc_traits in a follow-up patch. * include/bits/alloc_traits.h (allocator_traits>::allocate): Ignore hint for C++20. (allocator_traits>::construct): Perform placement new directly for C++20, instead of calling allocator::construct. (allocator_traits>::destroy): Call destructor directly for C++20, instead of calling allocator::destroy. (allocator_traits>::max_size): Return value directly for C++20, instead of calling std::allocator::max_size(). (__do_alloc_on_copy, __do_alloc_on_move, __do_alloc_on_swap): Do not define for C++17 and up. (__alloc_on_copy, __alloc_on_move, __alloc_on_swap): Use if-constexpr for C++17 and up, instead of tag dispatching. * include/bits/allocator.h (allocator): Remove for C++20. (allocator::pointer, allocator::const_pointer, allocator::reference) (allocator::const_reference, allocator::rebind): Remove for C++20. * include/bits/basic_string.h (basic_string): Use __alloc_traits to rebind allocator. * include/bits/memoryfwd.h (allocator): Remove for C++20. * include/ext/debug_allocator.h: Use __alloc_traits for rebinding. * include/ext/malloc_allocator.h (malloc_allocator::~malloc_allocator) (malloc_allocator::pointer, malloc_allocator::const_pointer) (malloc_allocator::reference, malloc_allocator::const_reference) (malloc_allocator::rebind, malloc_allocator::max_size) (malloc_allocator::construct, malloc_allocator::destroy): Do not define for C++20. (malloc_allocator::_M_max_size): Define new function. * include/ext/new_allocator.h (new_allocator::~new_allocator) (new_allocator::pointer, new_allocator::const_pointer) (new_allocator::reference, new_allocator::const_reference) (new_allocator::rebind, new_allocator::max_size) (new_allocator::construct, new_allocator::destroy): Do not define for C++20. (new_allocator::_M_max_size): Define new function. * include/ext/rc_string_base.h (__rc_string_base::_Rep): Use __alloc_traits to rebind allocator. * include/ext/rope (_Rope_rep_base, _Rope_base): Likewise. (rope::rope(CharT, const allocator_type&)): Use __alloc_traits to construct character. * include/ext/slist (_Slist_base): Use __alloc_traits to rebind allocator. * include/ext/sso_string_base.h (__sso_string_base::_M_max_size): Use __alloc_traits. * include/ext/throw_allocator.h (throw_allocator): Do not use optional members of std::allocator, use __alloc_traits members instead. * include/ext/vstring.h (__versa_string): Use __alloc_traits. * include/ext/vstring_util.h (__vstring_utility): Likewise. * include/std/memory: Include . * testsuite/20_util/allocator/8230.cc: Use __gnu_test::max_size. * testsuite/20_util/allocator/rebind_c++20.cc: New test. * testsuite/20_util/allocator/requirements/typedefs.cc: Do not check for pointer, const_pointer, reference, const_reference or rebind in C++20. * testsuite/20_util/allocator/requirements/typedefs_c++20.cc: New test. * testsuite/23_containers/deque/capacity/29134.cc: Use __gnu_test::max_size. * testsuite/23_containers/forward_list/capacity/1.cc: Likewise. * testsuite/23_containers/list/capacity/29134.cc: Likewise. * testsuite/23_containers/map/capacity/29134.cc: Likewise. * testsuite/23_containers/multimap/capacity/29134.cc: Likewise. * testsuite/23_containers/multiset/capacity/29134.cc: Likewise. * testsuite/23_containers/set/capacity/29134.cc: Likewise. * testsuite/23_containers/vector/capacity/29134.cc: Likewise. * testsuite/ext/malloc_allocator/variadic_construct.cc: Do not run test for C++20. * testsuite/ext/new_allocator/variadic_construct.cc: Likewise. * testsuite/ext/vstring/capacity/29134.cc: Use __gnu_test::max_size. * testsuite/util/replacement_memory_operators.h: Do not assume Alloc::pointer exists. * testsuite/util/testsuite_allocator.h (__gnu_test::max_size): Define helper to call max_size for any allocator. From-SVN: r277300 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 96a70260607..f5d2a0189e4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,76 @@ +2019-10-22 Jonathan Wakely + + * include/bits/alloc_traits.h + (allocator_traits>::allocate): Ignore hint for C++20. + (allocator_traits>::construct): Perform placement new + directly for C++20, instead of calling allocator::construct. + (allocator_traits>::destroy): Call destructor directly + for C++20, instead of calling allocator::destroy. + (allocator_traits>::max_size): Return value directly + for C++20, instead of calling std::allocator::max_size(). + (__do_alloc_on_copy, __do_alloc_on_move, __do_alloc_on_swap): Do not + define for C++17 and up. + (__alloc_on_copy, __alloc_on_move, __alloc_on_swap): Use if-constexpr + for C++17 and up, instead of tag dispatching. + * include/bits/allocator.h (allocator): Remove for C++20. + (allocator::pointer, allocator::const_pointer, allocator::reference) + (allocator::const_reference, allocator::rebind): Remove for C++20. + * include/bits/basic_string.h (basic_string): Use __alloc_traits to + rebind allocator. + * include/bits/memoryfwd.h (allocator): Remove for C++20. + * include/ext/debug_allocator.h: Use __alloc_traits for rebinding. + * include/ext/malloc_allocator.h (malloc_allocator::~malloc_allocator) + (malloc_allocator::pointer, malloc_allocator::const_pointer) + (malloc_allocator::reference, malloc_allocator::const_reference) + (malloc_allocator::rebind, malloc_allocator::max_size) + (malloc_allocator::construct, malloc_allocator::destroy): Do not + define for C++20. + (malloc_allocator::_M_max_size): Define new function. + * include/ext/new_allocator.h (new_allocator::~new_allocator) + (new_allocator::pointer, new_allocator::const_pointer) + (new_allocator::reference, new_allocator::const_reference) + (new_allocator::rebind, new_allocator::max_size) + (new_allocator::construct, new_allocator::destroy): Do not + define for C++20. + (new_allocator::_M_max_size): Define new function. + * include/ext/rc_string_base.h (__rc_string_base::_Rep): Use + __alloc_traits to rebind allocator. + * include/ext/rope (_Rope_rep_base, _Rope_base): Likewise. + (rope::rope(CharT, const allocator_type&)): Use __alloc_traits + to construct character. + * include/ext/slist (_Slist_base): Use __alloc_traits to rebind + allocator. + * include/ext/sso_string_base.h (__sso_string_base::_M_max_size): + Use __alloc_traits. + * include/ext/throw_allocator.h (throw_allocator): Do not use optional + members of std::allocator, use __alloc_traits members instead. + * include/ext/vstring.h (__versa_string): Use __alloc_traits. + * include/ext/vstring_util.h (__vstring_utility): Likewise. + * include/std/memory: Include . + * testsuite/20_util/allocator/8230.cc: Use __gnu_test::max_size. + * testsuite/20_util/allocator/rebind_c++20.cc: New test. + * testsuite/20_util/allocator/requirements/typedefs.cc: Do not check + for pointer, const_pointer, reference, const_reference or rebind in + C++20. + * testsuite/20_util/allocator/requirements/typedefs_c++20.cc: New test. + * testsuite/23_containers/deque/capacity/29134.cc: Use + __gnu_test::max_size. + * testsuite/23_containers/forward_list/capacity/1.cc: Likewise. + * testsuite/23_containers/list/capacity/29134.cc: Likewise. + * testsuite/23_containers/map/capacity/29134.cc: Likewise. + * testsuite/23_containers/multimap/capacity/29134.cc: Likewise. + * testsuite/23_containers/multiset/capacity/29134.cc: Likewise. + * testsuite/23_containers/set/capacity/29134.cc: Likewise. + * testsuite/23_containers/vector/capacity/29134.cc: Likewise. + * testsuite/ext/malloc_allocator/variadic_construct.cc: Do not run + test for C++20. + * testsuite/ext/new_allocator/variadic_construct.cc: Likewise. + * testsuite/ext/vstring/capacity/29134.cc: Use __gnu_test::max_size. + * testsuite/util/replacement_memory_operators.h: Do not assume + Alloc::pointer exists. + * testsuite/util/testsuite_allocator.h (__gnu_test::max_size): Define + helper to call max_size for any allocator. + 2019-10-22 Andreas Schwab * config/abi/post/aarch64-linux-gnu/baseline_symbols.txt: Update. diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index cda768bf391..62bbf0b2e31 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -393,6 +393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { /// The allocator type using allocator_type = allocator<_Tp>; + /// The allocated type using value_type = _Tp; @@ -455,7 +456,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ _GLIBCXX_NODISCARD static pointer allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) - { return __a.allocate(__n, __hint); } + { +#if __cplusplus <= 201703L + return __a.allocate(__n, __hint); +#else + return __a.allocate(__n); +#endif + } /** * @brief Deallocate memory. @@ -480,8 +487,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template static void construct(allocator_type& __a, _Up* __p, _Args&&... __args) - noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) - { __a.construct(__p, std::forward<_Args>(__args)...); } + noexcept(noexcept(::new((void*)__p) _Up(std::forward<_Args>(__args)...))) + { +#if __cplusplus <= 201703L + __a.construct(__p, std::forward<_Args>(__args)...); +#else + ::new((void*)__p) _Up(std::forward<_Args>(__args)...); +#endif + } /** * @brief Destroy an object of type @a _Up @@ -493,8 +506,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template static void destroy(allocator_type& __a, _Up* __p) - noexcept(noexcept(__a.destroy(__p))) - { __a.destroy(__p); } + noexcept(is_nothrow_destructible<_Up>::value) + { +#if __cplusplus <= 201703L + __a.destroy(__p); +#else + __p->~_Up(); +#endif + } /** * @brief The maximum supported allocation size @@ -503,7 +522,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION */ static size_type max_size(const allocator_type& __a) noexcept - { return __a.max_size(); } + { +#if __cplusplus <= 201703L + return __a.max_size(); +#else + return size_t(-1) / sizeof(value_type); +#endif + } /** * @brief Obtain an allocator to use when copying a container. @@ -515,7 +540,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return __rhs; } }; - +#if __cplusplus < 201703L template inline void __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) @@ -525,13 +550,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline void __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) { } +#endif template inline void __alloc_on_copy(_Alloc& __one, const _Alloc& __two) { typedef allocator_traits<_Alloc> __traits; typedef typename __traits::propagate_on_container_copy_assignment __pocca; +#if __cplusplus >= 201703L + if constexpr (__pocca::value) + __one = __two; +#else __do_alloc_on_copy(__one, __two, __pocca()); +#endif } template @@ -541,6 +572,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __traits::select_on_container_copy_construction(__a); } +#if __cplusplus < 201703L template inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) { __one = std::move(__two); } @@ -548,15 +580,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) { } +#endif template inline void __alloc_on_move(_Alloc& __one, _Alloc& __two) { typedef allocator_traits<_Alloc> __traits; typedef typename __traits::propagate_on_container_move_assignment __pocma; +#if __cplusplus >= 201703L + if constexpr (__pocma::value) + __one = std::move(__two); +#else __do_alloc_on_move(__one, __two, __pocma()); +#endif } +#if __cplusplus < 201703L template inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) { @@ -567,13 +606,22 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) { } +#endif template inline void __alloc_on_swap(_Alloc& __one, _Alloc& __two) { typedef allocator_traits<_Alloc> __traits; typedef typename __traits::propagate_on_container_swap __pocs; +#if __cplusplus >= 201703L + if constexpr (__pocs::value) + { + using std::swap; + swap(__one, __two); + } +#else __do_alloc_on_swap(__one, __two, __pocs()); +#endif } template specialization. template<> class allocator @@ -97,8 +98,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION destroy(_Up* __p) noexcept(noexcept(__p->~_Up())) { __p->~_Up(); } -#endif +#endif // C++11 }; +#endif // ! C++20 /** * @brief The @a standard allocator, as per [20.4]. @@ -111,18 +113,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class allocator : public __allocator_base<_Tp> { - public: + public: + typedef _Tp value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; - typedef _Tp value_type; template struct rebind { typedef allocator<_Tp1> other; }; +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index f1bdc6c553f..37e75b455d3 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -3138,7 +3138,9 @@ _GLIBCXX_END_NAMESPACE_CXX11 template class basic_string { - typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_CharT>::other _CharT_alloc_type; + typedef __gnu_cxx::__alloc_traits<_CharT_alloc_type> _CharT_alloc_traits; // Types: public: @@ -3154,8 +3156,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 typedef value_type& reference; typedef const value_type& const_reference; #endif - typedef typename _CharT_alloc_type::pointer pointer; - typedef typename _CharT_alloc_type::const_pointer const_pointer; + typedef typename _CharT_alloc_traits::pointer pointer; + typedef typename _CharT_alloc_traits::const_pointer const_pointer; typedef __gnu_cxx::__normal_iterator iterator; typedef __gnu_cxx::__normal_iterator const_iterator; @@ -3191,7 +3193,8 @@ _GLIBCXX_END_NAMESPACE_CXX11 struct _Rep : _Rep_base { // Types: - typedef typename _Alloc::template rebind::other _Raw_bytes_alloc; + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other _Raw_bytes_alloc; // (Public) Data members: diff --git a/libstdc++-v3/include/bits/memoryfwd.h b/libstdc++-v3/include/bits/memoryfwd.h index 8b1664a398d..d42eabeceb8 100644 --- a/libstdc++-v3/include/bits/memoryfwd.h +++ b/libstdc++-v3/include/bits/memoryfwd.h @@ -63,8 +63,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class allocator; +#if __cplusplus <= 201703L template<> class allocator; +#endif /// Declare uses_allocator so it can be specialized in \ etc. template diff --git a/libstdc++-v3/include/ext/debug_allocator.h b/libstdc++-v3/include/ext/debug_allocator.h index 08f0eb23f5b..b8e0e64d7bd 100644 --- a/libstdc++-v3/include/ext/debug_allocator.h +++ b/libstdc++-v3/include/ext/debug_allocator.h @@ -89,7 +89,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _Alloc _M_allocator; template::other> + typename = typename __alloc_traits<_Alloc2>::template + rebind::other> struct __convertible { }; diff --git a/libstdc++-v3/include/ext/malloc_allocator.h b/libstdc++-v3/include/ext/malloc_allocator.h index 1bc76372f44..cf6284080e8 100644 --- a/libstdc++-v3/include/ext/malloc_allocator.h +++ b/libstdc++-v3/include/ext/malloc_allocator.h @@ -54,17 +54,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class malloc_allocator { public: + typedef _Tp value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; - typedef _Tp value_type; template struct rebind { typedef malloc_allocator<_Tp1> other; }; +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -83,6 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION malloc_allocator(const malloc_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } +#if __cplusplus <= 201703L ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer @@ -92,16 +95,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } +#endif // NB: __n is permitted to be 0. The C++ standard says nothing // about what the return value is when __n == 0. - pointer + _Tp* allocate(size_type __n, const void* = 0) { - if (__n > this->max_size()) + if (__n > this->_M_max_size()) std::__throw_bad_alloc(); - pointer __ret = 0; + _Tp* __ret = 0; #if __cpp_aligned_new #if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC if (alignof(_Tp) > alignof(std::max_align_t)) @@ -131,18 +135,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __p is not permitted to be a null pointer. void - deallocate(pointer __p, size_type) + deallocate(_Tp* __p, size_type) { std::free(static_cast(__p)); } +#if __cplusplus <= 201703L size_type max_size() const _GLIBCXX_USE_NOEXCEPT - { -#if __PTRDIFF_MAX__ < __SIZE_MAX__ - return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); -#else - return std::size_t(-1) / sizeof(_Tp); -#endif - } + { return _M_max_size(); } #if __cplusplus >= 201103L template @@ -160,13 +159,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #else // _GLIBCXX_RESOLVE_LIB_DEFECTS // 402. wrong new expression in [some_] allocator::construct - void - construct(pointer __p, const _Tp& __val) + void + construct(pointer __p, const _Tp& __val) { ::new((void *)__p) value_type(__val); } - void + void destroy(pointer __p) { __p->~_Tp(); } #endif +#endif // ! C++20 template friend bool @@ -179,6 +179,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) _GLIBCXX_NOTHROW { return false; } + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/ext/new_allocator.h b/libstdc++-v3/include/ext/new_allocator.h index ee699532c6a..cff9f1dca9c 100644 --- a/libstdc++-v3/include/ext/new_allocator.h +++ b/libstdc++-v3/include/ext/new_allocator.h @@ -55,17 +55,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION class new_allocator { public: + typedef _Tp value_type; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L typedef _Tp* pointer; typedef const _Tp* const_pointer; typedef _Tp& reference; typedef const _Tp& const_reference; - typedef _Tp value_type; template struct rebind { typedef new_allocator<_Tp1> other; }; +#endif #if __cplusplus >= 201103L // _GLIBCXX_RESOLVE_LIB_DEFECTS @@ -83,6 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX20_CONSTEXPR new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } +#if __cplusplus <= 201703L ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } pointer @@ -92,13 +95,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT { return std::__addressof(__x); } +#endif // NB: __n is permitted to be 0. The C++ standard says nothing // about what the return value is when __n == 0. - _GLIBCXX_NODISCARD pointer + _GLIBCXX_NODISCARD _Tp* allocate(size_type __n, const void* = static_cast(0)) { - if (__n > this->max_size()) + if (__n > this->_M_max_size()) std::__throw_bad_alloc(); #if __cpp_aligned_new @@ -113,7 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // __p is not permitted to be a null pointer. void - deallocate(pointer __p, size_type __t) + deallocate(_Tp* __p, size_type __t) { #if __cpp_aligned_new if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) @@ -133,15 +137,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ); } +#if __cplusplus <= 201703L size_type max_size() const _GLIBCXX_USE_NOEXCEPT - { -#if __PTRDIFF_MAX__ < __SIZE_MAX__ - return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); -#else - return std::size_t(-1) / sizeof(_Tp); -#endif - } + { return _M_max_size(); } #if __cplusplus >= 201103L template @@ -166,6 +165,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void destroy(pointer __p) { __p->~_Tp(); } #endif +#endif // ! C++20 template friend bool @@ -178,6 +178,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION operator!=(const new_allocator&, const new_allocator<_Up>&) _GLIBCXX_NOTHROW { return false; } + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } }; _GLIBCXX_END_NAMESPACE_VERSION diff --git a/libstdc++-v3/include/ext/rc_string_base.h b/libstdc++-v3/include/ext/rc_string_base.h index 529035c5f61..2cf5fb0c5e3 100644 --- a/libstdc++-v3/include/ext/rc_string_base.h +++ b/libstdc++-v3/include/ext/rc_string_base.h @@ -31,6 +31,7 @@ #define _RC_STRING_BASE_H 1 #include +#include #include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) @@ -120,7 +121,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _CharT _M_align; }; - typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type; + typedef typename __alloc_traits<_Alloc>::template rebind<_Rep>::other + _Rep_alloc_type; _CharT* _M_refdata() throw() diff --git a/libstdc++-v3/include/ext/rope b/libstdc++-v3/include/ext/rope index 0788dee3c71..bfb29e1852d 100644 --- a/libstdc++-v3/include/ext/rope +++ b/libstdc++-v3/include/ext/rope @@ -53,6 +53,7 @@ #include #include #include +#include #include # ifdef __GC @@ -565,7 +566,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION # define __ROPE_DEFINE_ALLOC(_Tp, __name) \ typedef typename \ - _Alloc::template rebind<_Tp>::other __name##Alloc; \ + __alloc_traits<_Alloc>::template rebind<_Tp>::other __name##Alloc; \ static _Tp* __name##_allocate(size_type __n) \ { return __name##Alloc().allocate(__n); } \ static void __name##_deallocate(_Tp *__p, size_type __n) \ @@ -1499,7 +1500,7 @@ protected: #define __ROPE_DEFINE_ALLOC(_Tp, __name) \ typedef typename \ - _Alloc::template rebind<_Tp>::other __name##Alloc; \ + __alloc_traits<_Alloc>::template rebind<_Tp>::other __name##Alloc; \ static _Tp* __name##_allocate(std::size_t __n) \ { return __name##Alloc().allocate(__n); } \ static void __name##_deallocate(_Tp *__p, std::size_t __n) \ @@ -1855,7 +1856,8 @@ protected: { _CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1)); - _M_get_allocator().construct(__buf, __c); + __alloc_traits::construct(_M_get_allocator(), + __buf, __c); __try { this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1, diff --git a/libstdc++-v3/include/ext/slist b/libstdc++-v3/include/ext/slist index ff2ea150c4a..93522caf1f6 100644 --- a/libstdc++-v3/include/ext/slist +++ b/libstdc++-v3/include/ext/slist @@ -217,10 +217,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct _Slist_base - : public _Alloc::template rebind<_Slist_node<_Tp> >::other + : public __alloc_traits<_Alloc>::template rebind<_Slist_node<_Tp> >::other { - typedef typename _Alloc::template rebind<_Slist_node<_Tp> >::other - _Node_alloc; + typedef typename __alloc_traits<_Alloc>::template + rebind<_Slist_node<_Tp> >::other _Node_alloc; typedef _Alloc allocator_type; allocator_type diff --git a/libstdc++-v3/include/ext/sso_string_base.h b/libstdc++-v3/include/ext/sso_string_base.h index beae593efa0..e86d81011dd 100644 --- a/libstdc++-v3/include/ext/sso_string_base.h +++ b/libstdc++-v3/include/ext/sso_string_base.h @@ -140,7 +140,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION public: size_type _M_max_size() const - { return (_M_get_allocator().max_size() - 1) / 2; } + { + typedef __alloc_traits<_CharT_alloc_type> _ATraits; + return (_ATraits::max_size(_M_get_allocator()) - 1) / 2; + } _CharT* _M_data() const diff --git a/libstdc++-v3/include/ext/throw_allocator.h b/libstdc++-v3/include/ext/throw_allocator.h index 38e80f721da..f5da751eb69 100644 --- a/libstdc++-v3/include/ext/throw_allocator.h +++ b/libstdc++-v3/include/ext/throw_allocator.h @@ -62,6 +62,7 @@ # include # include #endif +#include namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) { @@ -814,12 +815,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::allocator _M_allocator; + typedef __gnu_cxx::__alloc_traits > traits; + using condition_type::throw_conditionally; public: size_type max_size() const _GLIBCXX_USE_NOEXCEPT - { return _M_allocator.max_size(); } + { return traits::max_size(_M_allocator); } pointer address(reference __x) const _GLIBCXX_NOEXCEPT @@ -830,13 +833,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return std::__addressof(__x); } _GLIBCXX_NODISCARD pointer - allocate(size_type __n, std::allocator::const_pointer hint = 0) + allocate(size_type __n, const void* hint = 0) { if (__n > this->max_size()) std::__throw_bad_alloc(); throw_conditionally(); - pointer const a = _M_allocator.allocate(__n, hint); + pointer const a = traits::allocate(_M_allocator, __n, hint); insert(a, sizeof(value_type) * __n); return a; } @@ -846,7 +849,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION void construct(_Up* __p, _Args&&... __args) { - _M_allocator.construct(__p, std::forward<_Args>(__args)...); + traits::construct(_M_allocator, __p, std::forward<_Args>(__args)...); insert_construct(__p); } @@ -855,7 +858,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION destroy(_Up* __p) { erase_construct(__p); - _M_allocator.destroy(__p); + traits::destroy(_M_allocator, __p); } #else void diff --git a/libstdc++-v3/include/ext/vstring.h b/libstdc++-v3/include/ext/vstring.h index 5942218531f..23ccf15de5b 100644 --- a/libstdc++-v3/include/ext/vstring.h +++ b/libstdc++-v3/include/ext/vstring.h @@ -58,6 +58,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { typedef _Base<_CharT, _Traits, _Alloc> __vstring_base; typedef typename __vstring_base::_CharT_alloc_type _CharT_alloc_type; + typedef __alloc_traits<_CharT_alloc_type> _CharT_alloc_traits; // Types: public: @@ -68,8 +69,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION typedef typename _CharT_alloc_type::difference_type difference_type; typedef value_type& reference; typedef const value_type& const_reference; - typedef typename _CharT_alloc_type::pointer pointer; - typedef typename _CharT_alloc_type::const_pointer const_pointer; + typedef typename _CharT_alloc_traits::pointer pointer; + typedef typename _CharT_alloc_traits::const_pointer const_pointer; typedef __gnu_cxx::__normal_iterator iterator; typedef __gnu_cxx::__normal_iterator const_iterator; diff --git a/libstdc++-v3/include/ext/vstring_util.h b/libstdc++-v3/include/ext/vstring_util.h index 5d00b165cbe..f539a6b0f2c 100644 --- a/libstdc++-v3/include/ext/vstring_util.h +++ b/libstdc++-v3/include/ext/vstring_util.h @@ -40,6 +40,7 @@ #include #include #include +#include #include #include @@ -50,14 +51,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template struct __vstring_utility { - typedef typename _Alloc::template rebind<_CharT>::other _CharT_alloc_type; + typedef typename __alloc_traits<_Alloc>::template rebind<_CharT>::other + _CharT_alloc_type; + typedef __alloc_traits<_CharT_alloc_type> _CharT_alloc_traits; typedef _Traits traits_type; typedef typename _Traits::char_type value_type; typedef typename _CharT_alloc_type::size_type size_type; typedef typename _CharT_alloc_type::difference_type difference_type; - typedef typename _CharT_alloc_type::pointer pointer; - typedef typename _CharT_alloc_type::const_pointer const_pointer; + typedef typename _CharT_alloc_traits::pointer pointer; + typedef typename _CharT_alloc_traits::const_pointer const_pointer; // For __sso_string. typedef __gnu_cxx:: diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory index 0a483d2d8d1..4f09b8deb2c 100644 --- a/libstdc++-v3/include/std/memory +++ b/libstdc++-v3/include/std/memory @@ -76,6 +76,7 @@ # include # include // std::less # include +# include # include # include # include diff --git a/libstdc++-v3/testsuite/20_util/allocator/8230.cc b/libstdc++-v3/testsuite/20_util/allocator/8230.cc index 917e64de374..2559a5117fb 100644 --- a/libstdc++-v3/testsuite/20_util/allocator/8230.cc +++ b/libstdc++-v3/testsuite/20_util/allocator/8230.cc @@ -22,6 +22,7 @@ #include #include #include +#include // libstdc++/8230 void test02() @@ -30,11 +31,11 @@ void test02() try { std::allocator alloc; - const std::allocator::size_type n = alloc.max_size(); + const std::allocator::size_type n = __gnu_test::max_size(alloc); int* p = alloc.allocate(n + 1); p[n] = 2002; } - catch(const std::bad_alloc& e) + catch(const std::bad_alloc& e) { // Allowed. test = true; diff --git a/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc b/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc new file mode 100644 index 00000000000..968e1de931b --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator/rebind_c++20.cc @@ -0,0 +1,28 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +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> ); diff --git a/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs.cc index d293e6b06b6..3275164f144 100644 --- a/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs.cc +++ b/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs.cc @@ -30,6 +30,7 @@ static_assert( is_same::size_type, std::size_t>::value, "size_type" ); static_assert( is_same::difference_type, std::ptrdiff_t>::value, "difference_type" ); +#if __cplusplus <= 201703L static_assert( is_same::pointer, int*>::value, "pointer" ); static_assert( is_same::const_pointer, const int*>::value, @@ -38,12 +39,15 @@ static_assert( is_same::reference, int&>::value, "reference" ); static_assert( is_same::const_reference, const int&>::value, "const_reference" ); +#endif static_assert( is_same::value_type, int>::value, "value_type" ); +#if __cplusplus <= 201703L static_assert( is_same::rebind::other, allocator>::value, "rebind::other" ); +#endif static_assert( is_same::propagate_on_container_move_assignment, std::true_type>::value, 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 new file mode 100644 index 00000000000..e986cc9a809 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator/requirements/typedefs_c++20.cc @@ -0,0 +1,56 @@ +// Copyright (C) 2019 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +template + concept has_pointer = requires { typename Alloc::pointer; }; + +template + concept has_const_pointer = requires { typename Alloc::const_pointer; }; + +template + concept has_reference = requires { typename Alloc::reference; }; + +template + concept has_const_reference = requires { typename Alloc::const_reference; }; + +template + concept has_rebind = requires { typename Alloc::template rebind; }; + +template + concept has_construct = requires(Alloc& a, int* p) { a.construct(p); }; + +template + concept has_destroy = requires(Alloc& a, int* p) { a.destroy(p); }; + +template + concept has_max_size = requires(Alloc& a) { a.max_size(); }; + +using A = 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/23_containers/deque/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/deque/capacity/29134.cc index da5ba3575f4..2d6e13d8944 100644 --- a/libstdc++-v3/testsuite/23_containers/deque/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/deque/capacity/29134.cc @@ -19,13 +19,15 @@ #include #include +#include // libstdc++/29134 void test01() { std::deque d; - VERIFY( d.max_size() == d.get_allocator().max_size() ); + std::allocator a = d.get_allocator(); + VERIFY( d.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc index deb71f2d51b..b36fdc81ad5 100644 --- a/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc +++ b/libstdc++-v3/testsuite/23_containers/forward_list/capacity/1.cc @@ -21,6 +21,7 @@ #include #include +#include void test01() @@ -40,8 +41,8 @@ test01() using std::_Fwd_list_node; #endif - VERIFY( (fld.max_size() - == std::allocator<_Fwd_list_node >().max_size()) ); + std::allocator<_Fwd_list_node > a; + VERIFY( fld.max_size() == __gnu_test::max_size(a) ); } int diff --git a/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc index 1b23938c088..810d964d28a 100644 --- a/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/list/capacity/29134.cc @@ -19,6 +19,7 @@ #include #include +#include // libstdc++/29134 void test01() @@ -32,7 +33,8 @@ void test01() using std::_List_node; #endif - VERIFY( l.max_size() == std::allocator<_List_node >().max_size() ); + std::allocator<_List_node > a; + VERIFY( l.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/map/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/map/capacity/29134.cc index c1696ba93b4..eae36f7037b 100644 --- a/libstdc++-v3/testsuite/23_containers/map/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/map/capacity/29134.cc @@ -19,14 +19,15 @@ #include #include +#include // libstdc++/29134 void test01() { std::map m; - VERIFY( (m.max_size() == std::allocator > >().max_size()) ); + std::allocator > > a; + VERIFY( m.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/multimap/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/multimap/capacity/29134.cc index 52ab07c50b5..ac588de73f7 100644 --- a/libstdc++-v3/testsuite/23_containers/multimap/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/multimap/capacity/29134.cc @@ -19,14 +19,15 @@ #include #include +#include // libstdc++/29134 void test01() { std::multimap mm; - VERIFY( (mm.max_size() == std::allocator > >().max_size()) ); + std::allocator > > a; + VERIFY( mm.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/multiset/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/multiset/capacity/29134.cc index 7f22a317b73..ea856a55156 100644 --- a/libstdc++-v3/testsuite/23_containers/multiset/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/multiset/capacity/29134.cc @@ -19,14 +19,15 @@ #include #include +#include // libstdc++/29134 void test01() { std::multiset ms; - VERIFY( ms.max_size() - == std::allocator >().max_size() ); + std::allocator > a; + VERIFY( ms.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/set/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/set/capacity/29134.cc index f870efda727..7851ee6b7ff 100644 --- a/libstdc++-v3/testsuite/23_containers/set/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/set/capacity/29134.cc @@ -19,14 +19,15 @@ #include #include +#include // libstdc++/29134 void test01() { std::set s; - VERIFY( s.max_size() == - std::allocator >().max_size() ); + std::allocator > a; + VERIFY( s.max_size() == __gnu_test::max_size(a) ); } int main() diff --git a/libstdc++-v3/testsuite/23_containers/vector/capacity/29134.cc b/libstdc++-v3/testsuite/23_containers/vector/capacity/29134.cc index 777e1c86238..3d3b60138d0 100644 --- a/libstdc++-v3/testsuite/23_containers/vector/capacity/29134.cc +++ b/libstdc++-v3/testsuite/23_containers/vector/capacity/29134.cc @@ -19,13 +19,22 @@ #include #include +#include // libstdc++/29134 void test01() { std::vector v; - VERIFY( v.max_size() == v.get_allocator().max_size() ); + std::allocator a = v.get_allocator(); +#if __cplusplus > 201703L + // std::allocator_traits::max_size() is unrealistically large, + // so std::vector::max_size() returns a smaller value. + VERIFY( v.max_size() <= __gnu_test::max_size(a) ); +#else + VERIFY( v.max_size() == __gnu_test::max_size(a) ); +#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 135c7080fad..b786fae9f0a 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 } } +// { dg-do run { target { { c++11_only || c++14_only } || c++17_only } } } // 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 fe4502f49d6..5b23e5b4a2c 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 } } +// { dg-do run { target { { c++11_only || c++14_only } || c++17_only } } } // 2007-10-26 Paolo Carlini diff --git a/libstdc++-v3/testsuite/ext/vstring/capacity/29134.cc b/libstdc++-v3/testsuite/ext/vstring/capacity/29134.cc index cc0302b92ac..003d0406d0a 100644 --- a/libstdc++-v3/testsuite/ext/vstring/capacity/29134.cc +++ b/libstdc++-v3/testsuite/ext/vstring/capacity/29134.cc @@ -19,13 +19,14 @@ #include #include +#include // libstdc++/29134 void test01() { __gnu_cxx::__vstring vs; - VERIFY( vs.max_size() <= vs.get_allocator().max_size() ); + VERIFY( vs.max_size() <= __gnu_test::max_size(vs.get_allocator()) ); } int main() diff --git a/libstdc++-v3/testsuite/util/replacement_memory_operators.h b/libstdc++-v3/testsuite/util/replacement_memory_operators.h index fb0b2be7dcf..cb7e7b9027b 100644 --- a/libstdc++-v3/testsuite/util/replacement_memory_operators.h +++ b/libstdc++-v3/testsuite/util/replacement_memory_operators.h @@ -76,7 +76,11 @@ namespace __gnu_test check_delete(Alloc a = Alloc()) { __gnu_test::counter::exceptions(false); +#if __cplusplus >= 201103L + auto p = a.allocate(10); +#else typename Alloc::pointer p = a.allocate(10); +#endif const std::size_t count1 = __gnu_test::counter::count(); a.deallocate(p, 10); const std::size_t count2 = __gnu_test::counter::count(); diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 67e70a29edb..f3eb199d85e 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -45,6 +45,18 @@ namespace unord = std::tr1; namespace __gnu_test { + // A common API for calling max_size() on an allocator in any -std mode. + template + typename A::size_type + max_size(const A& a) + { +#if __cplusplus >= 201103L + return std::allocator_traits::max_size(a); +#else + return a.max_size(); +#endif + } + class tracker_allocator_counter { public: @@ -252,7 +264,7 @@ namespace __gnu_test Alloc a; try { - (void) a.allocate(a.max_size() + 1); + (void) a.allocate(__gnu_test::max_size(a) + 1); } catch(std::bad_alloc&) {