1 // Copyright (C) 2010-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 
19 #include <vector>
20 #include <deque>
21 #include <list>
22 #ifndef _GLIBCXX_DEBUG
23 #  include <debug/vector>
24 #  include <debug/deque>
25 #  include <debug/list>
26 #endif
27 #include <testsuite_hooks.h>
28 
29 namespace __gnu_test
30 {
31   template<typename _Tp>
32     struct CopyableValueType
33     {
34       typedef _Tp value_type;
35     };
36 
37   template<typename _Tp1, typename _Tp2>
38     struct CopyableValueType<std::pair<const _Tp1, _Tp2> >
39     {
40       typedef std::pair<_Tp1, _Tp2> value_type;
41     };
42 
43   template<typename _Tp>
44     struct generate_unique
45     {
46       typedef _Tp value_type;
47 
48       value_type build()
49       {
50 	static value_type _S_;
51 	++_S_;
52 	return _S_;
53       }
54     };
55 
56   template<>
57     struct generate_unique<bool>
58     {
59       typedef bool value_type;
60 
61       value_type build()
62       {
63 	static value_type _S_;
64 	_S_ = !_S_;
65 	return _S_;
66       }
67     };
68 
69   template<typename _Tp1, typename _Tp2>
70     struct generate_unique<std::pair<_Tp1, _Tp2> >
71     {
72       typedef _Tp1 first_type;
73       typedef _Tp2 second_type;
74       typedef std::pair<_Tp1, _Tp2> pair_type;
75 
76       pair_type build()
77       {
78 	static first_type _S_1;
79 	static second_type _S_2;
80 	++_S_1;
81 	++_S_2;
82 	return pair_type(_S_1, _S_2);
83       }
84     };
85 
86   // Check that invalid range of pointers is detected
87   template<typename _Tp>
88     void
89     check_assign1()
90     {
91       typedef _Tp cont_type;
92       typedef typename cont_type::value_type cont_val_type;
93       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
94       typedef std::vector<val_type> vector_type;
95 
96       generate_unique<val_type> gu;
97 
98       vector_type v;
99       for (int i = 0; i != 5; ++i)
100         v.push_back(gu.build());
101       VERIFY(v.size() == 5);
102 
103       const val_type* first = &v.front() + 1;
104       const val_type* last = first + 2;
105 
106       cont_type c1;
107       c1.assign(first, last);
108       VERIFY(c1.size() == 2);
109 
110       cont_type c2;
111       c2.assign(last, first); // Expected failure
112     }
113 
114   // Check that invalid range of debug random iterators is detected
115   template<typename _Tp>
116     void
117     check_assign2()
118     {
119       typedef _Tp cont_type;
120       typedef typename cont_type::value_type cont_val_type;
121       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
122       typedef std::vector<val_type> vector_type;
123 
124       generate_unique<val_type> gu;
125 
126       vector_type v;
127       for (int i = 0; i != 5; ++i)
128         v.push_back(gu.build());
129       VERIFY(v.size() == 5);
130 
131       typename vector_type::iterator first = v.begin() + 1;
132       typename vector_type::iterator last = first + 2;
133       cont_type c1;
134       c1.assign(first, last);
135       VERIFY(c1.size() == 2);
136 
137       cont_type c2;
138       c2.assign(last, first); // Expected failure
139     }
140 
141   // Check that invalid range of debug not random iterators is detected
142   template<typename _Tp>
143     void
144     check_assign3()
145     {
146       typedef _Tp cont_type;
147       typedef typename cont_type::value_type cont_val_type;
148       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
149       typedef std::list<val_type> list_type;
150 
151       generate_unique<val_type> gu;
152 
153       list_type l;
154       for (int i = 0; i != 5; ++i)
155         l.push_back(gu.build());
156       VERIFY(l.size() == 5);
157 
158       typename list_type::iterator first = l.begin(); ++first;
159       typename list_type::iterator last = first; ++last; ++last;
160       cont_type c1;
161       c1.assign(first, last);
162       VERIFY(c1.size() == 2);
163 
164       cont_type c2;
165       c2.assign(last, first); // Expected failure
166     }
167 
168   // Check that invalid range of pointers is detected
169   template<typename _Tp>
170     void
171     check_construct1()
172     {
173       typedef _Tp cont_type;
174       typedef typename cont_type::value_type cont_val_type;
175       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
176       typedef std::vector<val_type> vector_type;
177 
178       generate_unique<val_type> gu;
179 
180       vector_type v;
181       for (int i = 0; i != 5; ++i)
182         v.push_back(gu.build());
183       VERIFY(v.size() == 5);
184 
185       val_type *first = &v.front() + 1;
186       val_type *last = first + 2;
187 
188       cont_type c(last, first); // Expected failure
189     }
190 
191   // Check that invalid range of debug random iterators is detected
192   template<typename _Tp>
193     void
194     check_construct2()
195     {
196       typedef _Tp cont_type;
197       typedef typename cont_type::value_type cont_val_type;
198       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
199       typedef std::vector<val_type> vector_type;
200 
201       generate_unique<val_type> gu;
202 
203       vector_type v;
204       for (int i = 0; i != 5; ++i)
205         v.push_back(gu.build());
206       VERIFY(v.size() == 5);
207 
208       typename vector_type::iterator first = v.begin() + 1;
209       typename vector_type::iterator last = first + 2;
210 
211       cont_type c(last, first); // Expected failure
212     }
213 
214   // Check that invalid range of debug not random iterators is detected
215   template<typename _Tp>
216     void
217     check_construct3()
218     {
219       typedef _Tp cont_type;
220       typedef typename cont_type::value_type cont_val_type;
221       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
222       typedef std::list<val_type> list_type;
223 
224       generate_unique<val_type> gu;
225 
226       list_type l;
227       for (int i = 0; i != 5; ++i)
228         l.push_back(gu.build());
229       VERIFY(l.size() == 5);
230 
231       typename list_type::iterator first = l.begin(); ++first;
232       typename list_type::iterator last = first; ++last; ++last;
233 
234       cont_type c(last, first); // Expected failure
235     }
236 
237   template <typename _Cont>
238     struct InsertRangeHelper
239     {
240       template <typename _It>
241         static void
242         Insert(_Cont& cont, _It first, _It last)
243 	{ cont.insert(first, last); }
244     };
245 
246   template <typename _Cont>
247     struct InsertRangeHelperAux
248     {
249       template <typename _It>
250         static void
251         Insert(_Cont& cont, _It first, _It last)
252 	{ cont.insert(cont.begin(), first, last); }
253     };
254 
255   template <typename _Tp1, typename _Tp2>
256     struct InsertRangeHelper<std::vector<_Tp1, _Tp2> >
257     : InsertRangeHelperAux<std::vector<_Tp1, _Tp2> >
258     { };
259 
260   template <typename _Tp1, typename _Tp2>
261     struct InsertRangeHelper<std::deque<_Tp1, _Tp2> >
262     : InsertRangeHelperAux<std::deque<_Tp1, _Tp2> >
263     { };
264 
265   template <typename _Tp1, typename _Tp2>
266     struct InsertRangeHelper<std::list<_Tp1, _Tp2> >
267     : InsertRangeHelperAux<std::list<_Tp1, _Tp2> >
268     { };
269 
270 #ifndef _GLIBCXX_DEBUG
271   template <typename _Tp1, typename _Tp2>
272     struct InsertRangeHelper<__gnu_debug::vector<_Tp1, _Tp2> >
273     : InsertRangeHelperAux<__gnu_debug::vector<_Tp1, _Tp2> >
274     { };
275 
276   template <typename _Tp1, typename _Tp2>
277     struct InsertRangeHelper<__gnu_debug::deque<_Tp1, _Tp2> >
278     : InsertRangeHelperAux<__gnu_debug::deque<_Tp1, _Tp2> >
279     { };
280 
281   template <typename _Tp1, typename _Tp2>
282     struct InsertRangeHelper<__gnu_debug::list<_Tp1, _Tp2> >
283     : InsertRangeHelperAux<__gnu_debug::list<_Tp1, _Tp2> >
284     { };
285 #endif
286 
287   template<typename _Tp>
288     void
289     check_insert1()
290     {
291       typedef _Tp cont_type;
292       typedef typename cont_type::value_type cont_val_type;
293       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
294       typedef std::vector<val_type> vector_type;
295 
296       generate_unique<val_type> gu;
297 
298       vector_type v;
299       for (int i = 0; i != 5; ++i)
300         v.push_back(gu.build());
301       VERIFY(v.size() == 5);
302 
303       const val_type* first = &v.front() + 1;
304       const val_type* last = first + 2;
305 
306       cont_type c1;
307       InsertRangeHelper<cont_type>::Insert(c1, first, last);
308       VERIFY(c1.size() == 2);
309 
310       cont_type c2;
311       InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
312     }
313 
314   template<typename _Tp>
315     void
316     check_insert2()
317     {
318       typedef _Tp cont_type;
319       typedef typename cont_type::value_type cont_val_type;
320       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
321       typedef std::vector<val_type> vector_type;
322 
323       generate_unique<val_type> gu;
324 
325       vector_type v;
326       for (int i = 0; i != 5; ++i)
327         v.push_back(gu.build());
328       VERIFY(v.size() == 5);
329 
330       typename vector_type::iterator first = v.begin() + 1;
331       typename vector_type::iterator last = first + 2;
332 
333       cont_type c1;
334       InsertRangeHelper<cont_type>::Insert(c1, first, last);
335       VERIFY(c1.size() == 2);
336 
337       cont_type c2;
338       InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
339     }
340 
341   template<typename _Tp>
342     void
343     check_insert3()
344     {
345       typedef _Tp cont_type;
346       typedef typename cont_type::value_type cont_val_type;
347       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
348       typedef std::list<val_type> list_type;
349 
350       generate_unique<val_type> gu;
351 
352       list_type l;
353       for (int i = 0; i != 5; ++i)
354         l.push_back(gu.build());
355       VERIFY(l.size() == 5);
356 
357       typename list_type::iterator first = l.begin(); ++first;
358       typename list_type::iterator last = first; ++last; ++last;
359 
360       cont_type c1;
361       InsertRangeHelper<cont_type>::Insert(c1, first, last);
362       VERIFY(c1.size() == 2);
363 
364       cont_type c2;
365       InsertRangeHelper<cont_type>::Insert(c2, last, first); // Expected failure
366     }
367 
368   template<typename _Tp>
369     void
370     check_insert4()
371     {
372       typedef _Tp cont_type;
373       typedef typename cont_type::value_type cont_val_type;
374       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
375       typedef std::list<val_type> list_type;
376 
377       generate_unique<val_type> gu;
378 
379       list_type l;
380       for (int i = 0; i != 5; ++i)
381         l.push_back(gu.build());
382       VERIFY(l.size() == 5);
383 
384       typename list_type::iterator first = l.begin(); ++first;
385       typename list_type::iterator last = first; ++last; ++last;
386 
387       cont_type c1;
388       InsertRangeHelper<cont_type>::Insert(c1, l.begin(), l.end());
389       VERIFY(c1.size() == 5);
390 
391       c1.insert(c1.begin(), c1.begin(), c1.end()); // Expected failure.
392     }
393 
394   template<typename _Tp>
395     void use_invalid_iterator()
396     {
397       typedef _Tp cont_type;
398       typedef typename cont_type::value_type cont_val_type;
399       typedef typename CopyableValueType<cont_val_type>::value_type val_type;
400       generate_unique<val_type> gu;
401 
402       cont_type c;
403       for (size_t i = 0; i != 5; ++i)
404 	c.insert(gu.build());
405 
406       typename cont_type::iterator it = c.begin();
407       cont_val_type val = *it;
408       c.clear();
409       VERIFY( *it == val );
410     }
411 }
412 
413