1 // Copyright (C) 2016-2021 Free Software Foundation, Inc.
2 //
3 // This file is part of the GNU ISO C++ Library.  This library is free
4 // software; you can redistribute it and/or modify it under the
5 // terms of the GNU General Public License as published by the
6 // Free Software Foundation; either version 3, or (at your option)
7 // any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 
14 // You should have received a copy of the GNU General Public License along
15 // with this library; see the file COPYING3.  If not see
16 // <http://www.gnu.org/licenses/>.
17 
18 // { dg-options "-std=gnu++2a" }
19 // { dg-do run { target c++2a } }
20 
21 #include <memory_resource>
22 #include <utility>
23 #include <tuple>
24 #include <testsuite_hooks.h>
25 #include <testsuite_allocator.h>
26 
27 struct do_not_copy {
28   do_not_copy() = default;
do_not_copydo_not_copy29   do_not_copy(const do_not_copy&) { throw 1; }
30 };
31 
32 void
test01()33 test01()
34 {
35   struct X {
36     X(do_not_copy&&) { }
37   };
38 
39   using pair = std::pair<X, int>;
40   std::pmr::polymorphic_allocator<pair> a;
41   auto ptr = a.allocate(1);
42   a.construct(ptr, std::piecewise_construct,
43       std::tuple<do_not_copy>{}, std::make_tuple(1));
44   a.deallocate(ptr, 1);
45 }
46 
47 void
test02()48 test02()
49 {
50   struct X {
51     using allocator_type = std::pmr::polymorphic_allocator<int>;
52     X(do_not_copy&&, const allocator_type&) { }
53   };
54 
55   using pair = std::pair<X, int>;
56   std::pmr::polymorphic_allocator<pair> a;
57   auto ptr = a.allocate(1);
58   a.construct(ptr, std::piecewise_construct,
59       std::tuple<do_not_copy>{}, std::make_tuple(1));
60   a.deallocate(ptr, 1);
61 }
62 
63 void
test03()64 test03()
65 {
66   struct X {
67     using allocator_type = std::pmr::polymorphic_allocator<int>;
68     X(std::allocator_arg_t, const allocator_type&, do_not_copy&&) { }
69   };
70 
71   using pair = std::pair<X, int>;
72   std::pmr::polymorphic_allocator<pair> a;
73   auto ptr = a.allocate(1);
74   a.construct(ptr, std::piecewise_construct,
75       std::tuple<do_not_copy>{}, std::make_tuple(1));
76   a.deallocate(ptr, 1);
77 }
78 
79 void
test04()80 test04()
81 {
82   struct X
83   {
84     using allocator_type = std::pmr::polymorphic_allocator<int>;
85     X() = default;
86     X(const X&) { throw 1; }
87     X(const X&, const allocator_type&) { }
88   };
89 
90   struct Y
91   {
92     using allocator_type = std::pmr::polymorphic_allocator<int>;
93     Y() = default;
94     Y(const Y&) = delete;
95     Y(std::allocator_arg_t, const allocator_type&, const Y&) { }
96   };
97 
98   using pair_type = std::pair<X, Y>;
99   std::pmr::polymorphic_allocator<pair_type> a;
100   auto ptr = a.allocate(1);
101   /* not const */ pair_type p;
102   a.construct(ptr, p); // LWG 2975
103   a.deallocate(ptr, 1);
104 }
105 
106 void
test05()107 test05()
108 {
109   struct X {
110     using allocator_type = std::pmr::polymorphic_allocator<char>;
111     X(int);
112     X(int, const allocator_type&) { }
113   };
114   std::pmr::polymorphic_allocator<X> a;
115   auto ptr = a.allocate(1);
116   a.construct(ptr, 1);
117   a.deallocate(ptr, 1);
118 }
119 
120 // P0591R4 makes uses-allocator construction apply recursively for nested pairs
121 void
test06()122 test06()
123 {
124   struct X
125   {
126     using allocator_type = std::pmr::polymorphic_allocator<int>;
127     X() = default;
128     X(const X&) { throw 1; }
129     X(const X&, const allocator_type& a) : mr(a.resource()) { }
130 
131     std::pmr::memory_resource* mr = nullptr;
132   };
133 
134   struct Y
135   {
136     using allocator_type = std::pmr::polymorphic_allocator<int>;
137     Y() = default;
138     Y(const Y&) = delete;
139     Y(std::allocator_arg_t, const allocator_type& a, const Y&)
140     : mr(a.resource()) { }
141 
142     std::pmr::memory_resource* mr = nullptr;
143   };
144 
145   using value_type = std::pair<std::pair<X, int>, std::pair<int, Y>>;
146   __gnu_test::memory_resource mr;
147   std::pmr::polymorphic_allocator<int> a(&mr);
148   std::pmr::vector<value_type> v(a);
149   VERIFY( v.get_allocator().resource() == &mr );
150 
151   value_type val;
152   val.first.second = 2;
153   val.second.first = 3;
154   v.push_back(val);
155   X& x = v.back().first.first;
156   VERIFY( x.mr != val.first.first.mr );
157   VERIFY( x.mr == &mr );
158 
159   Y& y = v.back().second.second;
160   VERIFY( y.mr != val.second.second.mr );
161   VERIFY( y.mr == &mr );
162 
163   // Check other members of the pairs are correctly initialized too:
164   VERIFY( v.back().first.second == val.first.second );
165   VERIFY( v.back().second.first == val.second.first );
166 }
167 
main()168 int main()
169 {
170   test01();
171   test02();
172   test03();
173   test04();
174   test05();
175   test06();
176 }
177