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