PR libstdc++/90239 * doc/xml/manual/status_cxx2020.xml: Amend P0591R4 status. * include/std/scoped_allocator [__cplusplus > 201703L] (scoped_allocator_adaptor::construct): Define in terms of uses_allocator_construction_args, as per P0591R4. * testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc: New test. * testsuite/util/testsuite_allocator.h: Remove name of unused parameter.
Tested powerpc64le-linux, committed to trunk. I'll backport this to gcc-9-branch after the 9.1.0 release.
commit 334fd4749cb72fa39413639d2db6718f1b411527 Author: Jonathan Wakely <jwak...@redhat.com> Date: Thu Apr 25 20:37:58 2019 +0100 PR libstdc++/90239 use uses_allocator_construction_args in <scoped_allocator> PR libstdc++/90239 * doc/xml/manual/status_cxx2020.xml: Amend P0591R4 status. * include/std/scoped_allocator [__cplusplus > 201703L] (scoped_allocator_adaptor::construct): Define in terms of uses_allocator_construction_args, as per P0591R4. * testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc: New test. * testsuite/util/testsuite_allocator.h: Remove name of unused parameter. diff --git a/libstdc++-v3/doc/xml/manual/status_cxx2020.xml b/libstdc++-v3/doc/xml/manual/status_cxx2020.xml index cedb3d03066..a075103ea4a 100644 --- a/libstdc++-v3/doc/xml/manual/status_cxx2020.xml +++ b/libstdc++-v3/doc/xml/manual/status_cxx2020.xml @@ -674,7 +674,9 @@ Feature-testing recommendations for C++</link>. </link> </entry> <entry align="center"> 9.1 </entry> - <entry /> + <entry> + <code>std::scoped_allocator_adaptor</code> changes missing in 9.1.0 + </entry> </row> <row> diff --git a/libstdc++-v3/include/std/scoped_allocator b/libstdc++-v3/include/std/scoped_allocator index 335df483f69..2c7ad8e94d7 100644 --- a/libstdc++-v3/include/std/scoped_allocator +++ b/libstdc++-v3/include/std/scoped_allocator @@ -35,6 +35,7 @@ # include <bits/c++0x_warning.h> #else +#include <memory> #include <utility> #include <tuple> #include <bits/alloc_traits.h> @@ -187,6 +188,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION using __outermost_alloc_traits = allocator_traits<typename __outermost_type<_Alloc>::type>; +#if __cplusplus <= 201703 template<typename _Tp, typename... _Args> void _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) @@ -218,6 +220,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::forward<_Args>(__args)..., inner_allocator()); } +#endif // C++17 template<typename _Alloc> static _Alloc @@ -355,6 +358,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION size_type max_size() const { return __traits::max_size(outer_allocator()); } +#if __cplusplus <= 201703 template<typename _Tp, typename... _Args> typename __not_pair<_Tp>::type construct(_Tp* __p, _Args&&... __args) @@ -417,6 +421,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION std::forward_as_tuple(std::forward<_Up>(__x.first)), std::forward_as_tuple(std::forward<_Vp>(__x.second))); } +#else // C++2a + template<typename _Tp, typename... _Args> + __attribute__((__nonnull__)) + void + construct(_Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits; + std::apply([__p, this](auto&&... __newargs) { + _O_traits::construct(__outermost(*this), __p, + std::forward<decltype(__newargs)>(__newargs)...); + }, + uses_allocator_construction_args<_Tp>(inner_allocator(), + std::forward<_Args>(__args)...)); + } +#endif // C++2a template<typename _Tp> void destroy(_Tp* __p) @@ -439,6 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; private: +#if __cplusplus <= 201703L template<typename _Ind, typename... _Args> tuple<_Args&&...> _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) @@ -461,6 +481,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; } +#endif // C++17 }; template <typename _OutA1, typename _OutA2, typename... _InA> diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc new file mode 100644 index 00000000000..1630f2a4d09 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc @@ -0,0 +1,97 @@ +// 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 +// <http://www.gnu.org/licenses/>. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <scoped_allocator> +#include <vector> +#include <testsuite_hooks.h> +#include <testsuite_allocator.h> + +struct X +{ + using allocator_type = __gnu_test::uneq_allocator<int>; + + X(int personality) : a(personality) { } + X(std::allocator_arg_t, allocator_type a) : a(a) { } + X(std::allocator_arg_t, allocator_type a, const X&) : a(a) { } + + allocator_type a; +}; + +void +test01() +{ + using value_type = std::pair<std::pair<X, int>, std::pair<int, X>>; + using scoped_alloc + = std::scoped_allocator_adaptor<__gnu_test::uneq_allocator<value_type>>; + + const scoped_alloc a(10); + std::vector<value_type, scoped_alloc> v(a); + VERIFY( v.get_allocator().get_personality() == a.get_personality() ); + + value_type val( { X(1), 2 }, { 3, X(4) } ); + v.push_back(val); + X& x1 = v.back().first.first; + VERIFY( x1.a.get_personality() != val.first.first.a.get_personality() ); + VERIFY( x1.a.get_personality() == a.get_personality() ); + + X& x2 = v.back().second.second; + VERIFY( x2.a.get_personality() != val.second.second.a.get_personality() ); + VERIFY( x2.a.get_personality() == a.get_personality() ); + + // Check other members of the pairs are correctly initialized too: + VERIFY( v.back().first.second == val.first.second ); + VERIFY( v.back().second.first == val.second.first ); +} + +void +test02() +{ + using value_type = std::pair<std::pair<X, int>, std::pair<int, X>>; + using scoped_alloc + = std::scoped_allocator_adaptor<__gnu_test::uneq_allocator<value_type>, + X::allocator_type>; + + const scoped_alloc a(10, 20); + std::vector<value_type, scoped_alloc> v(a); + VERIFY( v.get_allocator().get_personality() == a.get_personality() ); + + value_type val( { X(1), 2 }, { 3, X(4) } ); + v.push_back(val); + X& x1 = v.back().first.first; + VERIFY( x1.a.get_personality() != val.first.first.a.get_personality() ); + VERIFY( x1.a.get_personality() != a.get_personality() ); + VERIFY( x1.a.get_personality() == a.inner_allocator().get_personality() ); + + X& x2 = v.back().second.second; + VERIFY( x2.a.get_personality() != val.second.second.a.get_personality() ); + VERIFY( x2.a.get_personality() != a.get_personality() ); + VERIFY( x2.a.get_personality() == a.inner_allocator().get_personality() ); + + // Check other members of the pairs are correctly initialized too: + VERIFY( v.back().first.second == val.first.second ); + VERIFY( v.back().second.first == val.second.first ); +} + +int +main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h index 627749299d2..0392421ca04 100644 --- a/libstdc++-v3/testsuite/util/testsuite_allocator.h +++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h @@ -334,7 +334,7 @@ namespace __gnu_test int get_personality() const { return personality; } pointer - allocate(size_type n, const void* hint = 0) + allocate(size_type n, const void* = 0) { pointer p = AllocTraits::allocate(*this, n);