1 // Copyright (C) 2019 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 <testsuite_hooks.h>
22 #include <testsuite_allocator.h>
23 
24 using test_allocator = __gnu_test::uneq_allocator<int>;
25 
26 struct Arg { };
27 
28 struct A
29 {
AA30   A() : nargs(0) { }
AA31   A(float&) : nargs(1) { }
AA32   A(int, void*) : nargs(2) { }
33 
34   // These should not be used:
35   A(const test_allocator& a);
36   A(float&, const test_allocator& a);
37   A(int, void*, const test_allocator& a);
38 
39   const int nargs;
40   const int alloc_id = -1;
41 
42   // std::uses_allocator<A, test_allocator> should be false:
43   using allocator_type = void*();
44 };
45 
46 struct B
47 {
48   // This means std::uses_allocator<B, test_allocator> is true:
49   using allocator_type = test_allocator;
50 
BB51   B() : nargs(0) { }
BB52   B(float&) : nargs(1) { }
BB53   B(int, void*) : nargs(2) { }
54 
BB55   B(std::allocator_arg_t, const test_allocator& a)
56   : nargs(0), alloc_id(a.get_personality()) { }
BB57   B(std::allocator_arg_t, const test_allocator& a, float&)
58   : nargs(1), alloc_id(a.get_personality()) { }
BB59   B(std::allocator_arg_t, const test_allocator& a, int, void*)
60   : nargs(2), alloc_id(a.get_personality()) { }
BB61   B(std::allocator_arg_t, const test_allocator& a, B&& b)
62   : nargs(b.nargs), alloc_id(a.get_personality()) { }
63 
64   // These should not be used:
65   B(const test_allocator&);
66   B(float&, const test_allocator&, float&);
67   B(int, void*, const test_allocator&);
68   B(const test_allocator&, float&);
69   B(const test_allocator&, int, void*);
70   B(B&&);
71   B(B&&, const test_allocator&);
72 
73   const int nargs;
74   const int alloc_id = -1;
75 };
76 
77 struct C
78 {
CC79   C() : nargs(0) { }
CC80   C(float&) : nargs(1) { }
CC81   C(int, void*) : nargs(2) { }
82 
CC83   C(const test_allocator& a)
84   : nargs(0), alloc_id(a.get_personality()) { }
CC85   C(float&, const test_allocator& a)
86   : nargs(1), alloc_id(a.get_personality()) { }
CC87   C(int, void*, const test_allocator& a)
88   : nargs(2), alloc_id(a.get_personality()) { }
CC89   C(C&& c, const test_allocator& a)
90   : nargs(c.nargs), alloc_id(a.get_personality()) { }
91 
92   C(C&&);
93 
94   const int nargs;
95   const int alloc_id = -1;
96 };
97 
98 namespace std {
99   // This means std::uses_allocator<C, test_allocator> is true:
100   template<> struct uses_allocator<C, test_allocator> : std::true_type { };
101 }
102 
103 test_allocator alloc1(1);
104 test_allocator alloc2(2);
105 
106 void
test01()107 test01()
108 {
109   auto i0 = std::make_obj_using_allocator<int>(alloc1, 2);
110   VERIFY( i0 == 2 );
111 
112   float f = 0.0f;
113 
114   auto a0 = std::make_obj_using_allocator<A>(alloc1);
115   VERIFY( a0.nargs == 0 );
116   VERIFY( a0.alloc_id == -1 );
117   auto a1 = std::make_obj_using_allocator<A>(alloc1, f);
118   VERIFY( a1.nargs == 1 );
119   VERIFY( a1.alloc_id == -1 );
120   auto a2 = std::make_obj_using_allocator<A>(alloc1, 123, nullptr);
121   VERIFY( a2.nargs == 2 );
122   VERIFY( a2.alloc_id == -1 );
123 
124   auto b0 = std::make_obj_using_allocator<B>(alloc1);
125   VERIFY( b0.nargs == 0 );
126   VERIFY( b0.alloc_id == 1 );
127   auto b1 = std::make_obj_using_allocator<B>(alloc2, f);
128   VERIFY( b1.nargs == 1 );
129   VERIFY( b1.alloc_id == 2 );
130   auto b2 = std::make_obj_using_allocator<B>(alloc1, 123, nullptr);
131   VERIFY( b2.nargs == 2 );
132   VERIFY( b2.alloc_id == 1 );
133 
134   auto c0 = std::make_obj_using_allocator<C>(alloc1);
135   VERIFY( c0.nargs == 0 );
136   VERIFY( c0.alloc_id == 1 );
137   auto c1 = std::make_obj_using_allocator<C>(alloc2, f);
138   VERIFY( c1.nargs == 1 );
139   VERIFY( c1.alloc_id == 2 );
140   auto c2 = std::make_obj_using_allocator<C>(alloc1, 123, nullptr);
141   VERIFY( c2.nargs == 2 );
142   VERIFY( c2.alloc_id == 1 );
143 }
144 
145 void
test02()146 test02()
147 {
148   decltype(auto) b
149     = std::make_obj_using_allocator<const B>(alloc1, 123, nullptr);
150   static_assert( std::is_const_v<decltype(b)> );
151   VERIFY( b.nargs == 2 );
152   VERIFY( b.alloc_id == 1 );
153 
154   decltype(auto) c = std::make_obj_using_allocator<const C>(alloc1);
155   static_assert( std::is_const_v<decltype(c)> );
156   VERIFY( c.nargs == 0 );
157   VERIFY( c.alloc_id == 1 );
158 }
159 
160 void
test03()161 test03()
162 {
163   B b;
164   decltype(auto) ref = std::make_obj_using_allocator<B&>(alloc1, b);
165   static_assert( std::is_same_v<decltype(ref), B&> );
166   VERIFY( &ref == &b );
167   VERIFY( ref.nargs == 0 );
168   VERIFY( ref.alloc_id == -1 );
169   const B& cref = std::make_obj_using_allocator<const B&>(alloc1, b);
170   static_assert( std::is_same_v<decltype(cref), const B&> );
171   VERIFY( &cref == &b );
172   VERIFY( cref.nargs == 0 );
173   VERIFY( cref.alloc_id == -1 );
174 }
175 
176 void
test04()177 test04()
178 {
179   struct D
180   {
181     D(std::allocator_arg_t) { }
182     D(std::allocator_arg_t, int) { }
183 
184     // These should not be used:
185     D(std::allocator_arg_t, const test_allocator&);
186     D(std::allocator_arg_t, const test_allocator&, int);
187 
188     ~D() { }
189   };
190 
191   D d1 = std::make_obj_using_allocator<D>(alloc1, std::allocator_arg);
192 
193   struct E
194   {
195     using allocator_type = test_allocator;
196 
197     E(std::allocator_arg_t, const test_allocator&) { }
198     E(std::allocator_arg_t, int, const test_allocator&) { }
199 
200     // These should not be used:
201     E(std::allocator_arg_t);
202     E(std::allocator_arg_t, int);
203 
204     ~E() { }
205   };
206 
207   E e1 = std::make_obj_using_allocator<E>(alloc1, std::allocator_arg);
208   E e2 = std::make_obj_using_allocator<E>(alloc2, std::allocator_arg, 2);
209 }
210 
211 void
test05()212 test05()
213 {
214   using std::pair;
215   std::piecewise_construct_t p;
216   std::tuple<> t0;
217   float f = 0.0f;
218   std::tuple<float&> t1(f);
219   std::tuple<int, void*> t2{};
220 
221   auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t0, t0);
222   VERIFY( aa00.first.nargs == 0 );
223   VERIFY( aa00.first.alloc_id == -1 );
224   VERIFY( aa00.second.nargs == 0 );
225   VERIFY( aa00.second.alloc_id == -1 );
226   auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t0, t0);
227   VERIFY( ab00.first.nargs == 0 );
228   VERIFY( ab00.first.alloc_id == -1 );
229   VERIFY( ab00.second.nargs == 0 );
230   VERIFY( ab00.second.alloc_id == 1 );
231   auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t0, t0);
232   VERIFY( bc00.first.nargs == 0 );
233   VERIFY( bc00.first.alloc_id == 2 );
234   VERIFY( bc00.second.nargs == 0 );
235   VERIFY( bc00.second.alloc_id == 2 );
236   auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t0, t0);
237   VERIFY( cb00.first.nargs == 0 );
238   VERIFY( cb00.first.alloc_id == 2 );
239   VERIFY( cb00.second.nargs == 0 );
240   VERIFY( cb00.second.alloc_id == 2 );
241   auto cc00
242     = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t0, t0);
243   VERIFY( cc00.first.nargs == 0 );
244   VERIFY( cc00.first.alloc_id == 1 );
245   VERIFY( cc00.second.nargs == 0 );
246   VERIFY( cc00.second.alloc_id == 1 );
247 
248   auto aa21 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t2, t1);
249   VERIFY( aa21.first.nargs == 2 );
250   VERIFY( aa21.first.alloc_id == -1 );
251   VERIFY( aa21.second.nargs == 1 );
252   VERIFY( aa21.second.alloc_id == -1 );
253   auto ab21 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t2, t1);
254   VERIFY( ab21.first.nargs == 2 );
255   VERIFY( ab21.first.alloc_id == -1 );
256   VERIFY( ab21.second.nargs == 1 );
257   VERIFY( ab21.second.alloc_id == 1 );
258   auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t1, t1);
259   VERIFY( bc11.first.nargs == 1 );
260   VERIFY( bc11.first.alloc_id == 2 );
261   VERIFY( bc11.second.nargs == 1 );
262   VERIFY( bc11.second.alloc_id == 2 );
263   auto cb12 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t1, t2);
264   VERIFY( cb12.first.nargs == 1 );
265   VERIFY( cb12.first.alloc_id == 2 );
266   VERIFY( cb12.second.nargs == 2 );
267   VERIFY( cb12.second.alloc_id == 2 );
268   auto cc22
269     = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t2, t1);
270   VERIFY( cc22.first.nargs == 2 );
271   VERIFY( cc22.first.alloc_id == 1 );
272   VERIFY( cc22.second.nargs == 1 );
273   VERIFY( cc22.second.alloc_id == 1 );
274 }
275 
276 void
test06()277 test06()
278 {
279   using std::pair;
280   float f = 0.0f;
281 
282   auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1);
283   VERIFY( aa00.first.nargs == 0 );
284   VERIFY( aa00.first.alloc_id == -1 );
285   VERIFY( aa00.second.nargs == 0 );
286   VERIFY( aa00.second.alloc_id == -1 );
287   auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1);
288   VERIFY( ab00.first.nargs == 0 );
289   VERIFY( ab00.first.alloc_id == -1 );
290   VERIFY( ab00.second.nargs == 0 );
291   VERIFY( ab00.second.alloc_id == 1 );
292   auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2);
293   VERIFY( bc00.first.nargs == 0 );
294   VERIFY( bc00.first.alloc_id == 2 );
295   VERIFY( bc00.second.nargs == 0 );
296   VERIFY( bc00.second.alloc_id == 2 );
297   auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2);
298   VERIFY( cb00.first.nargs == 0 );
299   VERIFY( cb00.first.alloc_id == 2 );
300   VERIFY( cb00.second.nargs == 0 );
301   VERIFY( cb00.second.alloc_id == 2 );
302   auto cc00 = std::make_obj_using_allocator<pair<C, const C>>(alloc1);
303   VERIFY( cc00.first.nargs == 0 );
304   VERIFY( cc00.first.alloc_id == 1 );
305   VERIFY( cc00.second.nargs == 0 );
306   VERIFY( cc00.second.alloc_id == 1 );
307 
308   auto aa11 = std::make_obj_using_allocator<pair<A, A>>(alloc1, f, f);
309   VERIFY( aa11.first.nargs == 1 );
310   VERIFY( aa11.first.alloc_id == -1 );
311   VERIFY( aa11.second.nargs == 1 );
312   VERIFY( aa11.second.alloc_id == -1 );
313   auto aba1 = std::make_obj_using_allocator<pair<A, B>>(alloc1, A{}, f);
314   VERIFY( aba1.first.nargs == 0 );
315   VERIFY( aba1.first.alloc_id == -1 );
316   VERIFY( aba1.second.nargs == 1 );
317   VERIFY( aba1.second.alloc_id == 1 );
318   auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, f, f);
319   VERIFY( bc11.first.nargs == 1 );
320   VERIFY( bc11.first.alloc_id == 2 );
321   VERIFY( bc11.second.nargs == 1 );
322   VERIFY( bc11.second.alloc_id == 2 );
323   auto cb1b = std::make_obj_using_allocator<pair<C, B>>(alloc2, f, B{});
324   VERIFY( cb1b.first.nargs == 1 );
325   VERIFY( cb1b.first.alloc_id == 2 );
326   VERIFY( cb1b.second.nargs == 0 );
327   VERIFY( cb1b.second.alloc_id == 2 );
328   auto cccc
329     = std::make_obj_using_allocator<pair<C, const C>>(alloc1, C{}, C{});
330   VERIFY( cccc.first.nargs == 0 );
331   VERIFY( cccc.first.alloc_id == 1 );
332   VERIFY( cccc.second.nargs == 0 );
333   VERIFY( cccc.second.alloc_id == 1 );
334 
335   pair<float&, A> p1a(f, A{});
336   pair<float&, float&> p11(f, f);
337   auto aa1a = std::make_obj_using_allocator<pair<A, A>>(alloc1, p1a);
338   VERIFY( aa1a.first.nargs == 1 );
339   VERIFY( aa1a.first.alloc_id == -1 );
340   VERIFY( aa1a.second.nargs == 0 );
341   VERIFY( aa1a.second.alloc_id == -1 );
342   auto ab11 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p11);
343   VERIFY( ab11.first.nargs == 1 );
344   VERIFY( ab11.first.alloc_id == -1 );
345   VERIFY( ab11.second.nargs == 1 );
346   VERIFY( ab11.second.alloc_id == 1 );
347   auto cb11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p11);
348   VERIFY( cb11.first.nargs == 1 );
349   VERIFY( cb11.first.alloc_id == 2 );
350   VERIFY( cb11.second.nargs == 1 );
351   VERIFY( cb11.second.alloc_id == 2 );
352 
353   auto bcbc = std::make_obj_using_allocator<pair<B, C>>(alloc2, pair<B, C>());
354   VERIFY( bcbc.first.nargs == 0 );
355   VERIFY( bcbc.first.alloc_id == 2 );
356   VERIFY( bcbc.second.nargs == 0 );
357   VERIFY( bcbc.second.alloc_id == 2 );
358 
359   auto cc11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, std::move(p11));
360   VERIFY( cc11.first.nargs == 1 );
361   VERIFY( cc11.first.alloc_id == 2 );
362   VERIFY( cc11.second.nargs == 1 );
363   VERIFY( cc11.second.alloc_id == 2 );
364 }
365 
366 void
test07()367 test07()
368 {
369   using nested_pair = std::pair<const std::pair<B, const B>, C>;
370   auto p = std::make_obj_using_allocator<const nested_pair>(alloc1);
371   VERIFY( p.first.first.alloc_id == 1 );
372   VERIFY( p.first.second.alloc_id == 1 );
373   VERIFY( p.second.alloc_id == 1 );
374 }
375 
376 void
test08()377 test08()
378 {
379   // LWG DR 3187.
380   // P0591R4 reverted DR 2586 fixes to scoped_allocator_adaptor::construct()
381 
382   struct X {
383     using allocator_type = std::allocator<X>;
384     X(std::allocator_arg_t, allocator_type&&) { }
385     X(const allocator_type&) { }
386   };
387 
388   std::allocator<X> a;
389   std::make_obj_using_allocator<X>(a);
390 }
391 
392 int
main()393 main()
394 {
395   test01();
396   test02();
397   test03();
398   test04();
399   test05();
400   test06();
401   test07();
402   test08();
403 }
404