On 25/04/19 23:43 +0100, Jonathan Wakely wrote:
        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.

Here's a follow-up which adds a similar test for polymorphic_allocator
(which was already using the new utilities so already had the correct
c++2a behaviour, but it was untested).

Tested powerpc64le-linux, using default flags, and also -std=gnu++2a
and also -std=gnu++2a/-fconcepts.

Committed to trunk.


I'll backport this to gcc-9-branch after the 9.1.0 release.

Richi said the previous patch is OK to backport now, so I'll ask about
this one too (which also only touches C++2a code) after testing on the
branch.


commit 771a0481d6b388c1485ecbd5747aeee9f075edbe
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Fri Apr 26 13:10:10 2019 +0100

    Tweak C++2a uses-allocator construction utilities
    
    The 20_util/scoped_allocator/69293_neg.cc test was failing in C++2a mode
    because the expected static_assert text wasn't matched. The code is
    still ill-formed in C++2a, but uses the new __uses_alloc_args function
    and so fails a different static_assert. This patch adds the same string
    to the new static_assert, so the test passes.
    
    Now that G++ allows concepts to be declared without 'bool' we can use
    the correct C++2a syntax for the _Std_pair concept used to constrain the
    uses-allocator construction utilities.
    
    Also add a new test to verify that pmr::polymorphic_allocator correctly
    performs recursive uses-allocator construction for nested pairs in
    C++2a.
    
            * include/std/memory (__uses_alloc_args): Add string-literal to
            static_assert, to match the one in __uses_alloc.
            [__cpp_concepts] (_Std_pair): Use C++2a syntax for concept.
            * testsuite/20_util/polymorphic_allocator/construct_c++2a.cc: Check
            for recursive uses-allocator construction of nested pairs.
            * testsuite/20_util/scoped_allocator/construct_pair_c++2a.cc:: Add
            comment.

diff --git a/libstdc++-v3/include/std/memory b/libstdc++-v3/include/std/memory
index 57ccf93de86..6677fe782de 100644
--- a/libstdc++-v3/include/std/memory
+++ b/libstdc++-v3/include/std/memory
@@ -191,7 +191,9 @@ get_pointer_safety() noexcept { return pointer_safety::relaxed; }
 	    }
 	  else
 	    {
-	      static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>);
+	      static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>,
+		  "construction with an allocator must be possible"
+		  " if uses_allocator is true");
 
 	      return tuple<_Args&&..., const _Alloc&>(
 		  std::forward<_Args>(__args)..., __a);
@@ -207,7 +209,7 @@ get_pointer_safety() noexcept { return pointer_safety::relaxed; }
 
 #if __cpp_concepts
   template<typename _Tp>
-    concept bool _Std_pair = __is_pair<_Tp>::value;
+    concept _Std_pair = __is_pair<_Tp>::value;
 #endif
 
 // This is a temporary workaround until -fconcepts is implied by -std=gnu++2a
diff --git a/libstdc++-v3/testsuite/20_util/polymorphic_allocator/construct_c++2a.cc b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/construct_c++2a.cc
index 9048ca196ff..df01dccafe1 100644
--- a/libstdc++-v3/testsuite/20_util/polymorphic_allocator/construct_c++2a.cc
+++ b/libstdc++-v3/testsuite/20_util/polymorphic_allocator/construct_c++2a.cc
@@ -21,6 +21,8 @@
 #include <memory_resource>
 #include <utility>
 #include <tuple>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
 
 struct do_not_copy {
   do_not_copy() = default;
@@ -115,6 +117,54 @@ test05()
   a.deallocate(ptr, 1);
 }
 
+// P0591R4 makes uses-allocator construction apply recursively for nested pairs
+void
+test06()
+{
+  struct X
+  {
+    using allocator_type = std::pmr::polymorphic_allocator<int>;
+    X() = default;
+    X(const X&) { throw 1; }
+    X(const X&, const allocator_type& a) : mr(a.resource()) { }
+
+    std::pmr::memory_resource* mr = nullptr;
+  };
+
+  struct Y
+  {
+    using allocator_type = std::pmr::polymorphic_allocator<int>;
+    Y() = default;
+    Y(const Y&) = delete;
+    Y(std::allocator_arg_t, const allocator_type& a, const Y&)
+    : mr(a.resource()) { }
+
+    std::pmr::memory_resource* mr = nullptr;
+  };
+
+  using value_type = std::pair<std::pair<X, int>, std::pair<int, Y>>;
+  __gnu_test::memory_resource mr;
+  std::pmr::polymorphic_allocator<int> a(&mr);
+  std::pmr::vector<value_type> v(a);
+  VERIFY( v.get_allocator().resource() == &mr );
+
+  value_type val;
+  val.first.second = 2;
+  val.second.first = 3;
+  v.push_back(val);
+  X& x = v.back().first.first;
+  VERIFY( x.mr != val.first.first.mr );
+  VERIFY( x.mr == &mr );
+
+  Y& y = v.back().second.second;
+  VERIFY( y.mr != val.second.second.mr );
+  VERIFY( y.mr == &mr );
+
+  // 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();
@@ -122,4 +172,5 @@ int main()
   test03();
   test04();
   test05();
+  test06();
 }
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
index 1630f2a4d09..09050b2bc08 100644
--- 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
@@ -18,6 +18,8 @@
 // { dg-options "-std=gnu++2a" }
 // { dg-do run { target c++2a } }
 
+// P0591R4 makes uses-allocator construction apply recursively for nested pairs
+
 #include <scoped_allocator>
 #include <vector>
 #include <testsuite_hooks.h>

Reply via email to