1 // { dg-do run { target c++17 } }
2 // { dg-require-effective-target std_allocator_new }
3
4 // Copyright (C) 2021 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 // libstdc++/96088
22
23 #include <string_view>
24 #include <string>
25 #include <unordered_set>
26 #include <vector>
27
28 #include <testsuite_hooks.h>
29 #include <replacement_memory_operators.h>
30
31 static constexpr std::initializer_list<const char*> lst = {
32 "long_str_for_dynamic_allocating"
33 };
34
35 void
test01()36 test01()
37 {
38 __gnu_test::counter::reset();
39 std::unordered_set<std::string> us;
40 us.insert(lst.begin(), lst.end());
41 VERIFY( us.size() == 1 );
42
43 VERIFY( __gnu_test::counter::count() == 3 );
44 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
45
46 us.insert(lst.begin(), lst.end());
47 VERIFY( us.size() == 1 );
48
49 VERIFY( __gnu_test::counter::count() == 3 );
50 VERIFY( __gnu_test::counter::get()._M_increments == 4 );
51 }
52
53 void
test02()54 test02()
55 {
56 __gnu_test::counter::reset();
57 std::unordered_set<std::string,
58 std::hash<std::string_view>,
59 std::equal_to<std::string_view>> us;
60 us.insert(lst.begin(), lst.end());
61 VERIFY( us.size() == 1 );
62
63 VERIFY( __gnu_test::counter::count() == 3 );
64 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
65
66 us.insert(lst.begin(), lst.end());
67 VERIFY( us.size() == 1 );
68
69 VERIFY( __gnu_test::counter::count() == 3 );
70 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
71 }
72
73 std::size_t
hash_string_f(const std::string & str)74 hash_string_f(const std::string& str) noexcept
75 {
76 std::hash<std::string> h;
77 return h(str);
78 }
79
80 void
test11()81 test11()
82 {
83 typedef std::size_t (*hash_string_t)(const std::string&) noexcept;
84 __gnu_test::counter::reset();
85 hash_string_t hasher = &hash_string_f;
86 std::unordered_set<std::string,
87 hash_string_t,
88 std::equal_to<std::string>> us(0, hasher);
89 us.insert(lst.begin(), lst.end());
90 VERIFY( us.size() == 1 );
91
92 VERIFY( __gnu_test::counter::count() == 3 );
93 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
94
95 us.insert(lst.begin(), lst.end());
96 VERIFY( us.size() == 1 );
97
98 VERIFY( __gnu_test::counter::count() == 3 );
99 VERIFY( __gnu_test::counter::get()._M_increments == 4 );
100 }
101
102 std::size_t
hash_string_view_f(const std::string_view & str)103 hash_string_view_f(const std::string_view& str) noexcept
104 {
105 std::hash<std::string_view> h;
106 return h(str);
107 }
108
109 void
test12()110 test12()
111 {
112 typedef std::size_t (*hash_stringview_t)(const std::string_view&) noexcept;
113 __gnu_test::counter::reset();
114 hash_stringview_t hasher = &hash_string_view_f;
115 std::unordered_set<std::string,
116 hash_stringview_t,
117 std::equal_to<std::string_view>> us(0, hasher);
118 us.insert(lst.begin(), lst.end());
119 VERIFY( us.size() == 1 );
120
121 VERIFY( __gnu_test::counter::count() == 3 );
122 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
123
124 us.insert(lst.begin(), lst.end());
125 VERIFY( us.size() == 1 );
126
127 VERIFY( __gnu_test::counter::count() == 3 );
128 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
129 }
130
131 struct hash_string_functor
132 {
133 std::size_t
operator ()hash_string_functor134 operator()(const std::string& str) const noexcept
135 {
136 std::hash<std::string> h;
137 return h(str);
138 }
139 };
140
141 void
test21()142 test21()
143 {
144 __gnu_test::counter::reset();
145 std::unordered_set<std::string,
146 hash_string_functor,
147 std::equal_to<std::string>> us;
148 us.insert(lst.begin(), lst.end());
149 VERIFY( us.size() == 1 );
150
151 VERIFY( __gnu_test::counter::count() == 3 );
152 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
153
154 us.insert(lst.begin(), lst.end());
155 VERIFY( us.size() == 1 );
156
157 VERIFY( __gnu_test::counter::count() == 3 );
158 VERIFY( __gnu_test::counter::get()._M_increments == 4 );
159 }
160
161 struct hash_string_view_noexcept_functor
162 {
163 std::size_t
operator ()hash_string_view_noexcept_functor164 operator()(const std::string_view& str) const noexcept
165 {
166 std::hash<std::string_view> h;
167 return h(str);
168 }
169 };
170
171 void
test22()172 test22()
173 {
174 __gnu_test::counter::reset();
175 std::unordered_set<std::string,
176 hash_string_view_noexcept_functor,
177 std::equal_to<std::string_view>> us;
178 us.insert(lst.begin(), lst.end());
179 VERIFY( us.size() == 1 );
180
181 VERIFY( __gnu_test::counter::count() == 3 );
182 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
183
184 us.insert(lst.begin(), lst.end());
185 VERIFY( us.size() == 1 );
186
187 VERIFY( __gnu_test::counter::count() == 3 );
188 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
189 }
190
191 struct hash_string_view_functor
192 {
193 std::size_t
operator ()hash_string_view_functor194 operator()(const std::string_view& str) const
195 {
196 std::hash<std::string_view> h;
197 return h(str);
198 }
199 };
200
201 void
test23()202 test23()
203 {
204 __gnu_test::counter::reset();
205 std::unordered_set<std::string,
206 hash_string_view_functor,
207 std::equal_to<std::string_view>> us;
208 us.insert(lst.begin(), lst.end());
209 VERIFY( us.size() == 1 );
210
211 VERIFY( __gnu_test::counter::count() == 3 );
212 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
213
214 us.insert(lst.begin(), lst.end());
215 VERIFY( us.size() == 1 );
216
217 VERIFY( __gnu_test::counter::count() == 3 );
218 VERIFY( __gnu_test::counter::get()._M_increments == 3 );
219 }
220
221 void
test03()222 test03()
223 {
224 std::vector<std::string> v;
225 v.insert(v.end(), lst.begin(), lst.end());
226
227 const auto origin = __gnu_test::counter::count();
228
229 {
230 __gnu_test::counter::reset();
231 std::unordered_set<std::string,
232 std::hash<std::string_view>,
233 std::equal_to<std::string_view>> us;
234 us.insert(v.begin(), v.end());
235 VERIFY( us.size() == 1 );
236
237 // Allocate array of buckets, a node, and the std::string (unless COW).
238 constexpr std::size_t increments = _GLIBCXX_USE_CXX11_ABI ? 3 : 2;
239
240 VERIFY( __gnu_test::counter::count() == origin + increments );
241 VERIFY( __gnu_test::counter::get()._M_increments == increments );
242
243 us.insert(v.begin(), v.end());
244 VERIFY( us.size() == 1 );
245
246 VERIFY( __gnu_test::counter::count() == origin + increments );
247 VERIFY( __gnu_test::counter::get()._M_increments == increments );
248 }
249 VERIFY( __gnu_test::counter::count() == origin );
250
251 {
252 __gnu_test::counter::reset();
253 std::unordered_set<std::string,
254 std::hash<std::string_view>,
255 std::equal_to<std::string_view>> us;
256 us.insert(std::make_move_iterator(v.begin()),
257 std::make_move_iterator(v.end()));
258 VERIFY( us.size() == 1 );
259
260 // Allocate array of buckets and a node. String is moved.
261 constexpr std::size_t increments = 2;
262
263 VERIFY( __gnu_test::counter::count() == origin + increments );
264 VERIFY( __gnu_test::counter::get()._M_increments == increments );
265 }
266 }
267
268 int
main()269 main()
270 {
271 test01();
272 test02();
273 test11();
274 test12();
275 test21();
276 test22();
277 test23();
278 test03();
279 return 0;
280 }
281