1 // { dg-do run { target c++14 } }
2 // { dg-require-thread-fence "" }
3 
4 // Copyright (C) 2015-2019 Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library.  This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING3.  If not see
19 // <http://www.gnu.org/licenses/>.
20 
21 #include <experimental/memory_resource>
22 #include <experimental/utility>
23 #include <memory>
24 #include <testsuite_hooks.h>
25 #include <testsuite_allocator.h>
26 
27 using std::experimental::pmr::polymorphic_allocator;
28 using std::experimental::pmr::memory_resource;
29 using std::experimental::pmr::new_delete_resource;
30 using std::experimental::pmr::get_default_resource;
31 using std::allocator_arg_t;
32 
33 enum CtorType { Default, Copy, Move, Other, Tuple, Piecewise_Default, Piecewise_Copy};
34 
35 // type that takes a memory_resource before other ctor args
36 struct A
37 {
38   using allocator_type = std::experimental::erased_type;
39 
40   CtorType type;
41   memory_resource* alloc = nullptr;
42 
AA43   A() : type(Default) { }
AA44   A(allocator_arg_t, memory_resource* a) : type(Default), alloc(a) { }
AA45   A(const A&) : type(Copy) { }
AA46   A(allocator_arg_t, memory_resource* a, const A&) : type(Copy), alloc(a) { }
AA47   A(A&&) : type (Move) { }
AA48   A(allocator_arg_t, memory_resource* a, A&&) : type (Move), alloc(a) { }
AA49   A(int) : type(Other) { }
AA50   A(allocator_arg_t, memory_resource* a, int) : type(Other), alloc(a) { }
51 };
52 
53 // type that takes a memory_resource after other ctor args
54 struct B
55 {
56   using allocator_type = std::experimental::erased_type;
57 
58   CtorType type;
59   memory_resource* alloc = nullptr;
60 
BB61   B() : type(Default) { }
BB62   B(memory_resource* a) : type(Default), alloc(a) { }
BB63   B(const B&) : type(Copy) { }
BB64   B(const B&, memory_resource* a) : type(Copy), alloc(a) { }
BB65   B(B&&) : type (Move) { }
BB66   B(B&&, memory_resource* a) : type(Move), alloc(a) { }
BB67   B(int) : type(Other) { }
BB68   B(int, memory_resource* a) : type(Other), alloc(a) { }
69 };
70 
71 // type that takes no memory_resource
72 struct C
73 {
74   CtorType type;
CC75   C() : type(Default) { }
CC76   C(const C&) : type(Copy) { }
CC77   C(C&&) : type(Move) { }
CC78   C(int) : type(Other) { }
79 };
80 
81 // test construct for type that
82 // uses memory_resource* as allocator
83 template<typename A>
test_uses_alloc()84 void test_uses_alloc() {
85   polymorphic_allocator<A> pa;
86   A* p = pa.allocate(1);
87   A a;
88 
89   pa.construct(p);
90   VERIFY(p->alloc == get_default_resource());
91   VERIFY(p->type == Default);
92   pa.destroy(p);
93 
94   pa.construct(p, a);
95   VERIFY(p->type == Copy);
96   pa.destroy(p);
97 
98   pa.construct(p, A());
99   VERIFY(p->type == Move);
100   pa.destroy(p);
101 
102   pa.construct(p, 1);
103   VERIFY(p->type == Other);
104   pa.destroy(p);
105 
106   pa.deallocate(p, 1);
107 }
108 
109 // test construct for type that not using allocator
110 template <typename C>
test_non_alloc()111 void test_non_alloc() {
112   polymorphic_allocator<C> pa;
113   C* p = pa.allocate(1);
114   C b;
115 
116   pa.construct(p);
117   VERIFY(p->type == Default);
118   pa.destroy(p);
119 
120   pa.construct(p, b);
121   VERIFY(p->type == Copy);
122   pa.destroy(p);
123 
124   pa.construct(p, C());
125   VERIFY(p->type == Move);
126   pa.destroy(p);
127 
128   pa.construct(p, 1);
129   VERIFY(p->type == Other);
130   pa.destroy(p);
131 
132   pa.deallocate(p, 1);
133 }
134 
135 // test piecewise_construct
136 template <typename A, typename B>
test_pair()137 void test_pair() {
138   polymorphic_allocator<std::pair<A, B>> pa;
139   std::pair<A, B>* p = pa.allocate(1);
140   std::tuple<> t;
141 
142   // construct(pair<T1, T2>* p, piecewise_construct_t, tuple<...>, tuple<...>)
143   pa.construct(p, std::piecewise_construct, t, t);
144   VERIFY(p->first.type == Default);
145   VERIFY(p->second.type == Default);
146   pa.destroy(p);
147 
148   // construct(pair<T1, T2>* __p)
149   pa.construct(p);
150   VERIFY(p->first.type == Default);
151   VERIFY(p->second.type == Default);
152   pa.destroy(p);
153 
154   // construct(pair<T1, T2>* p, U&& x, V&& y)
155   A a; B b;
156   pa.construct(p, a, b);
157   VERIFY(p->first.type == Copy);
158   VERIFY(p->second.type == Copy);
159   pa.destroy(p);
160 
161   pa.construct(p, A(), B());
162   VERIFY(p->first.type == Move);
163   VERIFY(p->second.type == Move);
164   auto pp = *p;
165   pa.destroy(p);
166 
167   // construct(pair<T1, T2>* p, const pair<U, V>& x)
168   pa.construct(p, pp);
169   VERIFY(p->first.type == Copy);
170   VERIFY(p->second.type == Copy);
171   pa.destroy(p);
172 
173   // construct(pair<T1, T2>* p, pair<U, V>&& x)
174   pa.construct(p, std::move(pp));
175   VERIFY(p->first.type == Move);
176   VERIFY(p->second.type == Move);
177   pa.destroy(p);
178   pa.deallocate(p, 1);
179 }
180 
test01()181 void test01() {
182   test_uses_alloc<A>();
183   test_uses_alloc<B>();
184   test_non_alloc<C>();
185 }
186 
test02()187 void test02() {
188   test_pair<A, A>();
189   test_pair<A, B>();
190   test_pair<A, C>();
191   test_pair<B, B>();
192   test_pair<B, A>();
193   test_pair<B, C>();
194   test_pair<C, C>();
195 }
196 
197 
main()198 int main() {
199   test01();
200   test02();
201 }
202