class.c (check_bases): Propagate non-literality.
[official-gcc.git] / libstdc++-v3 / testsuite / util / exception / safety.h
blobcab31e2285412140ad3a92a009e25a7419fd2f58
1 // -*- C++ -*-
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the terms
7 // of the GNU General Public License as published by the Free Software
8 // Foundation; either version 3, or (at your option) any later
9 // version.
11 // This library is distributed in the hope that it will be useful, but
12 // WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING3. If not see
18 // <http://www.gnu.org/licenses/>.
20 #ifndef _GLIBCXX_EXCEPTION_SAFETY_H
21 #define _GLIBCXX_EXCEPTION_SAFETY_H
23 #include <testsuite_container_traits.h>
24 #include <ext/throw_allocator.h>
26 // Container requirement testing.
27 namespace __gnu_test
29 // Base class for exception testing, contains utilities.
30 struct setup_base
32 typedef std::size_t size_type;
33 typedef std::uniform_int_distribution<size_type> distribution_type;
34 typedef std::mt19937 engine_type;
36 // Return randomly generated integer on range [0, __max_size].
37 static size_type
38 generate(size_type __max_size)
40 // Make the generator static...
41 const engine_type engine;
42 const distribution_type distribution;
43 static auto generator = std::bind(distribution, engine,
44 std::placeholders::_1);
46 // ... but set the range for this particular invocation here.
47 const typename distribution_type::param_type p(0, __max_size);
48 size_type random = generator(p);
49 if (random < distribution.min() || random > distribution.max())
51 std::string __s("setup_base::generate");
52 __s += "\n";
53 __s += "random number generated is: ";
54 char buf[40];
55 __builtin_sprintf(buf, "%lu", (unsigned long)random);
56 __s += buf;
57 __s += " on range [";
58 __builtin_sprintf(buf, "%lu", (unsigned long)distribution.min());
59 __s += buf;
60 __s += ", ";
61 __builtin_sprintf(buf, "%lu", (unsigned long)distribution.max());
62 __s += buf;
63 __s += "]\n";
64 std::__throw_out_of_range(__s.c_str());
66 return random;
69 // Given an instantiating type, return a unique value.
70 template<typename _Tp>
71 struct generate_unique
73 typedef _Tp value_type;
75 operator value_type()
77 static value_type __ret;
78 ++__ret;
79 return __ret;
83 // Partial specialization for pair.
84 template<typename _Tp1, typename _Tp2>
85 struct generate_unique<std::pair<const _Tp1, _Tp2>>
87 typedef _Tp1 first_type;
88 typedef _Tp2 second_type;
89 typedef std::pair<const _Tp1, _Tp2> pair_type;
91 operator pair_type()
93 static first_type _S_1;
94 static second_type _S_2;
95 ++_S_1;
96 ++_S_2;
97 return pair_type(_S_1, _S_2);
101 // Partial specialization for throw_value
102 template<typename _Cond>
103 struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
105 typedef __gnu_cxx::throw_value_base<_Cond> value_type;
107 operator value_type()
109 static size_t _S_i(0);
110 return value_type(_S_i++);
115 // Construct container of size n directly. _Tp == container type.
116 template<typename _Tp>
117 struct make_container_base
119 _Tp _M_container;
121 make_container_base() = default;
122 make_container_base(const size_type n): _M_container(n) { }
124 operator _Tp&() { return _M_container; }
127 // Construct container of size n, via multiple insertions. For
128 // associated and unordered types, unique value_type elements are
129 // necessary.
130 template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
131 struct make_insert_container_base
132 : public make_container_base<_Tp>
134 using make_container_base<_Tp>::_M_container;
135 typedef typename _Tp::value_type value_type;
137 make_insert_container_base(const size_type n)
139 for (size_type i = 0; i < n; ++i)
141 value_type v = generate_unique<value_type>();
142 _M_container.insert(v);
144 assert(_M_container.size() == n);
148 template<typename _Tp>
149 struct make_insert_container_base<_Tp, false>
150 : public make_container_base<_Tp>
152 using make_container_base<_Tp>::_M_container;
153 typedef typename _Tp::value_type value_type;
155 make_insert_container_base(const size_type n)
157 for (size_type i = 0; i < n; ++i)
159 value_type v = generate_unique<value_type>();
160 _M_container.insert(_M_container.end(), v);
162 assert(_M_container.size() == n);
166 template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
167 struct make_container_n;
169 // Specialization for non-associative types that have a constructor with
170 // a size argument.
171 template<typename _Tp>
172 struct make_container_n<_Tp, true>
173 : public make_container_base<_Tp>
175 make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
178 template<typename _Tp>
179 struct make_container_n<_Tp, false>
180 : public make_insert_container_base<_Tp>
182 make_container_n(const size_type n)
183 : make_insert_container_base<_Tp>(n) { }
187 // Randomly size and populate a given container reference.
188 // NB: Responsibility for turning off exceptions lies with caller.
189 template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value>
190 struct populate
192 typedef _Tp container_type;
193 typedef typename container_type::allocator_type allocator_type;
194 typedef typename container_type::value_type value_type;
196 populate(_Tp& __container)
198 const allocator_type a = __container.get_allocator();
200 // Size test container.
201 const size_type max_elements = 100;
202 size_type n = generate(max_elements);
204 // Construct new container.
205 make_container_n<container_type> made(n);
206 container_type& tmp = made;
207 std::swap(tmp, __container);
211 // Partial specialization, empty.
212 template<typename _Tp>
213 struct populate<_Tp, false>
215 populate(_Tp&) { }
218 // Compare two containers for equivalence.
219 // Right now, that means size.
220 // Returns true if equal, throws if not.
221 template<typename _Tp>
222 static bool
223 compare(const _Tp& __control, const _Tp& __test)
225 // Make sure test container is in a consistent state, as
226 // compared to the control container.
227 // NB: Should be equivalent to __test != __control, but
228 // computed without equivalence operators
229 const size_type szt = std::distance(__test.begin(), __test.end());
230 const size_type szc = std::distance(__control.begin(),
231 __control.end());
232 bool __equal_size = szt == szc;
234 // Should test iterator validity before and after exception.
235 bool __equal_it = std::equal(__test.begin(), __test.end(),
236 __control.begin());
238 if (!__equal_size || !__equal_it)
239 throw std::logic_error("setup_base::compare containers not equal");
241 return true;
246 // Containing structure holding functors.
247 struct functor_base : public setup_base
249 // Abstract the erase function.
250 template<typename _Tp>
251 struct erase_base
253 typedef typename _Tp::iterator iterator;
255 iterator (_Tp::* _F_erase_point)(iterator);
256 iterator (_Tp::* _F_erase_range)(iterator, iterator);
258 erase_base()
259 : _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
262 // Specialization, as forward_list has erase_after.
263 template<typename _Tp1, typename _Tp2>
264 struct erase_base<std::forward_list<_Tp1, _Tp2>>
266 typedef std::forward_list<_Tp1, _Tp2> container_type;
267 typedef typename container_type::iterator iterator;
268 typedef typename container_type::const_iterator const_iterator;
270 iterator (container_type::* _F_erase_point)(const_iterator);
271 iterator (container_type::* _F_erase_range)(const_iterator,
272 const_iterator);
274 erase_base()
275 : _F_erase_point(&container_type::erase_after),
276 _F_erase_range(&container_type::erase_after) { }
279 // Specializations for the unordered containers.
280 template<typename _Tp1, typename _Tp2, typename _Tp3,
281 typename _Tp4, typename _Tp5>
282 struct erase_base<std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
284 typedef std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
285 container_type;
286 typedef typename container_type::iterator iterator;
287 typedef typename container_type::const_iterator const_iterator;
289 iterator (container_type::* _F_erase_point)(const_iterator);
290 iterator (container_type::* _F_erase_range)(const_iterator,
291 const_iterator);
293 erase_base()
294 : _F_erase_point(&container_type::erase),
295 _F_erase_range(&container_type::erase) { }
298 template<typename _Tp1, typename _Tp2, typename _Tp3,
299 typename _Tp4, typename _Tp5>
300 struct erase_base<std::unordered_multimap<_Tp1, _Tp2, _Tp3,
301 _Tp4, _Tp5>>
303 typedef std::unordered_multimap<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
304 container_type;
305 typedef typename container_type::iterator iterator;
306 typedef typename container_type::const_iterator const_iterator;
308 iterator (container_type::* _F_erase_point)(const_iterator);
309 iterator (container_type::* _F_erase_range)(const_iterator,
310 const_iterator);
312 erase_base()
313 : _F_erase_point(&container_type::erase),
314 _F_erase_range(&container_type::erase) { }
317 template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
318 struct erase_base<std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>>
320 typedef std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>
321 container_type;
322 typedef typename container_type::iterator iterator;
323 typedef typename container_type::const_iterator const_iterator;
325 iterator (container_type::* _F_erase_point)(const_iterator);
326 iterator (container_type::* _F_erase_range)(const_iterator,
327 const_iterator);
329 erase_base()
330 : _F_erase_point(&container_type::erase),
331 _F_erase_range(&container_type::erase) { }
334 template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
335 struct erase_base<std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>>
337 typedef std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>
338 container_type;
339 typedef typename container_type::iterator iterator;
340 typedef typename container_type::const_iterator const_iterator;
342 iterator (container_type::* _F_erase_point)(const_iterator);
343 iterator (container_type::* _F_erase_range)(const_iterator,
344 const_iterator);
346 erase_base()
347 : _F_erase_point(&container_type::erase),
348 _F_erase_range(&container_type::erase) { }
351 template<typename _Tp,
352 bool = traits<_Tp>::has_erase::value,
353 bool = traits<_Tp>::has_erase_after::value>
354 struct erase_point;
356 // Specialization for most containers.
357 template<typename _Tp>
358 struct erase_point<_Tp, true, false> : public erase_base<_Tp>
360 using erase_base<_Tp>::_F_erase_point;
362 void
363 operator()(_Tp& __container)
367 // NB: Should be equivalent to size() member function, but
368 // computed with begin() and end().
369 const size_type sz = std::distance(__container.begin(),
370 __container.end());
372 // NB: Lowest common denominator: use forward iterator operations.
373 auto i = __container.begin();
374 std::advance(i, generate(sz));
376 // Makes it easier to think of this as __container.erase(i)
377 (__container.*_F_erase_point)(i);
379 catch(const __gnu_cxx::forced_error&)
380 { throw; }
384 // Specialization for forward_list.
385 template<typename _Tp>
386 struct erase_point<_Tp, false, true> : public erase_base<_Tp>
388 using erase_base<_Tp>::_F_erase_point;
390 void
391 operator()(_Tp& __container)
395 // NB: Should be equivalent to size() member function, but
396 // computed with begin() and end().
397 const size_type sz = std::distance(__container.begin(),
398 __container.end());
400 // NB: Lowest common denominator: use forward iterator operations.
401 auto i = __container.before_begin();
402 std::advance(i, generate(sz));
404 // Makes it easier to think of this as __container.erase(i)
405 (__container.*_F_erase_point)(i);
407 catch(const __gnu_cxx::forced_error&)
408 { throw; }
412 // Specialization, empty.
413 template<typename _Tp>
414 struct erase_point<_Tp, false, false>
416 void
417 operator()(_Tp&) { }
421 template<typename _Tp,
422 bool = traits<_Tp>::has_erase::value,
423 bool = traits<_Tp>::has_erase_after::value>
424 struct erase_range;
426 // Specialization for most containers.
427 template<typename _Tp>
428 struct erase_range<_Tp, true, false> : public erase_base<_Tp>
430 using erase_base<_Tp>::_F_erase_range;
432 void
433 operator()(_Tp& __container)
437 const size_type sz = std::distance(__container.begin(),
438 __container.end());
439 size_type s1 = generate(sz);
440 size_type s2 = generate(sz);
441 auto i1 = __container.begin();
442 auto i2 = __container.begin();
443 std::advance(i1, std::min(s1, s2));
444 std::advance(i2, std::max(s1, s2));
446 // Makes it easier to think of this as __container.erase(i1, i2).
447 (__container.*_F_erase_range)(i1, i2);
449 catch(const __gnu_cxx::forced_error&)
450 { throw; }
454 // Specialization for forward_list.
455 template<typename _Tp>
456 struct erase_range<_Tp, false, true> : public erase_base<_Tp>
458 using erase_base<_Tp>::_F_erase_range;
460 void
461 operator()(_Tp& __container)
465 const size_type sz = std::distance(__container.begin(),
466 __container.end());
467 size_type s1 = generate(sz);
468 size_type s2 = generate(sz);
469 auto i1 = __container.before_begin();
470 auto i2 = __container.before_begin();
471 std::advance(i1, std::min(s1, s2));
472 std::advance(i2, std::max(s1, s2));
474 // Makes it easier to think of this as __container.erase(i1, i2).
475 (__container.*_F_erase_range)(i1, i2);
477 catch(const __gnu_cxx::forced_error&)
478 { throw; }
482 // Specialization, empty.
483 template<typename _Tp>
484 struct erase_range<_Tp, false, false>
486 void
487 operator()(_Tp&) { }
491 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
492 struct pop_front
494 void
495 operator()(_Tp& __container)
499 __container.pop_front();
501 catch(const __gnu_cxx::forced_error&)
502 { throw; }
506 // Specialization, empty.
507 template<typename _Tp>
508 struct pop_front<_Tp, false>
510 void
511 operator()(_Tp&) { }
515 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
516 && traits<_Tp>::is_reversible::value>
517 struct pop_back
519 void
520 operator()(_Tp& __container)
524 __container.pop_back();
526 catch(const __gnu_cxx::forced_error&)
527 { throw; }
531 // Specialization, empty.
532 template<typename _Tp>
533 struct pop_back<_Tp, false>
535 void
536 operator()(_Tp&) { }
540 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
541 struct push_front
543 typedef _Tp container_type;
544 typedef typename container_type::value_type value_type;
546 void
547 operator()(_Tp& __test)
551 const value_type cv = generate_unique<value_type>();
552 __test.push_front(cv);
554 catch(const __gnu_cxx::forced_error&)
555 { throw; }
558 // Assumes containers start out equivalent.
559 void
560 operator()(_Tp& __control, _Tp& __test)
564 const value_type cv = generate_unique<value_type>();
565 __test.push_front(cv);
567 catch(const __gnu_cxx::forced_error&)
568 { throw; }
572 // Specialization, empty.
573 template<typename _Tp>
574 struct push_front<_Tp, false>
576 void
577 operator()(_Tp&) { }
579 void
580 operator()(_Tp&, _Tp&) { }
584 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
585 && traits<_Tp>::is_reversible::value>
586 struct push_back
588 typedef _Tp container_type;
589 typedef typename container_type::value_type value_type;
591 void
592 operator()(_Tp& __test)
596 const value_type cv = generate_unique<value_type>();
597 __test.push_back(cv);
599 catch(const __gnu_cxx::forced_error&)
600 { throw; }
603 // Assumes containers start out equivalent.
604 void
605 operator()(_Tp& __control, _Tp& __test)
609 const value_type cv = generate_unique<value_type>();
610 __test.push_back(cv);
612 catch(const __gnu_cxx::forced_error&)
613 { throw; }
617 // Specialization, empty.
618 template<typename _Tp>
619 struct push_back<_Tp, false>
621 void
622 operator()(_Tp&) { }
624 void
625 operator()(_Tp&, _Tp&) { }
629 // Abstract the insert function into two parts:
630 // 1, insert_base_functions == holds function pointer
631 // 2, insert_base == links function pointer to class insert method
632 template<typename _Tp>
633 struct insert_base
635 typedef typename _Tp::iterator iterator;
636 typedef typename _Tp::value_type value_type;
638 iterator (_Tp::* _F_insert_point)(iterator, const value_type&);
640 insert_base() : _F_insert_point(&_Tp::insert) { }
643 // Specialization, as string insertion has a different signature.
644 template<typename _Tp1, typename _Tp2, typename _Tp3>
645 struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
647 typedef std::basic_string<_Tp1, _Tp2, _Tp3> container_type;
648 typedef typename container_type::iterator iterator;
649 typedef typename container_type::value_type value_type;
651 iterator (container_type::* _F_insert_point)(iterator, value_type);
653 insert_base() : _F_insert_point(&container_type::insert) { }
656 template<typename _Tp1, typename _Tp2, typename _Tp3,
657 template <typename, typename, typename> class _Tp4>
658 struct insert_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
660 typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
661 container_type;
662 typedef typename container_type::iterator iterator;
663 typedef typename container_type::value_type value_type;
665 iterator (container_type::* _F_insert_point)(iterator, value_type);
667 insert_base() : _F_insert_point(&container_type::insert) { }
670 // Specialization, as forward_list insertion has a different signature.
671 template<typename _Tp1, typename _Tp2>
672 struct insert_base<std::forward_list<_Tp1, _Tp2>>
674 typedef std::forward_list<_Tp1, _Tp2> container_type;
675 typedef typename container_type::iterator iterator;
676 typedef typename container_type::const_iterator const_iterator;
677 typedef typename container_type::value_type value_type;
679 iterator (container_type::* _F_insert_point)(const_iterator,
680 const value_type&);
682 insert_base() : _F_insert_point(&container_type::insert_after) { }
685 // Likewise for the unordered containers.
686 template<typename _Tp1, typename _Tp2, typename _Tp3,
687 typename _Tp4, typename _Tp5>
688 struct insert_base<std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>>
690 typedef std::unordered_map<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
691 container_type;
692 typedef typename container_type::iterator iterator;
693 typedef typename container_type::const_iterator const_iterator;
694 typedef typename container_type::value_type value_type;
696 iterator (container_type::* _F_insert_point)(const_iterator,
697 const value_type&);
699 insert_base() : _F_insert_point(&container_type::insert) { }
702 template<typename _Tp1, typename _Tp2, typename _Tp3,
703 typename _Tp4, typename _Tp5>
704 struct insert_base<std::unordered_multimap<_Tp1, _Tp2, _Tp3,
705 _Tp4, _Tp5>>
707 typedef std::unordered_multimap<_Tp1, _Tp2, _Tp3, _Tp4, _Tp5>
708 container_type;
709 typedef typename container_type::iterator iterator;
710 typedef typename container_type::const_iterator const_iterator;
711 typedef typename container_type::value_type value_type;
713 iterator (container_type::* _F_insert_point)(const_iterator,
714 const value_type&);
716 insert_base() : _F_insert_point(&container_type::insert) { }
719 template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
720 struct insert_base<std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>>
722 typedef std::unordered_set<_Tp1, _Tp2, _Tp3, _Tp4>
723 container_type;
724 typedef typename container_type::iterator iterator;
725 typedef typename container_type::const_iterator const_iterator;
726 typedef typename container_type::value_type value_type;
728 iterator (container_type::* _F_insert_point)(const_iterator,
729 const value_type&);
731 insert_base() : _F_insert_point(&container_type::insert) { }
734 template<typename _Tp1, typename _Tp2, typename _Tp3, typename _Tp4>
735 struct insert_base<std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>>
737 typedef std::unordered_multiset<_Tp1, _Tp2, _Tp3, _Tp4>
738 container_type;
739 typedef typename container_type::iterator iterator;
740 typedef typename container_type::const_iterator const_iterator;
741 typedef typename container_type::value_type value_type;
743 iterator (container_type::* _F_insert_point)(const_iterator,
744 const value_type&);
746 insert_base() : _F_insert_point(&container_type::insert) { }
749 template<typename _Tp,
750 bool = traits<_Tp>::has_insert::value,
751 bool = traits<_Tp>::has_insert_after::value>
752 struct insert_point;
754 // Specialization for most containers.
755 template<typename _Tp>
756 struct insert_point<_Tp, true, false> : public insert_base<_Tp>
758 typedef _Tp container_type;
759 typedef typename container_type::value_type value_type;
760 using insert_base<_Tp>::_F_insert_point;
762 void
763 operator()(_Tp& __test)
767 const value_type cv = generate_unique<value_type>();
768 const size_type sz = std::distance(__test.begin(), __test.end());
769 size_type s = generate(sz);
770 auto i = __test.begin();
771 std::advance(i, s);
772 (__test.*_F_insert_point)(i, cv);
774 catch(const __gnu_cxx::forced_error&)
775 { throw; }
778 // Assumes containers start out equivalent.
779 void
780 operator()(_Tp& __control, _Tp& __test)
784 const value_type cv = generate_unique<value_type>();
785 const size_type sz = std::distance(__test.begin(), __test.end());
786 size_type s = generate(sz);
787 auto i = __test.begin();
788 std::advance(i, s);
789 (__test.*_F_insert_point)(i, cv);
791 catch(const __gnu_cxx::forced_error&)
792 { throw; }
796 // Specialization for forward_list.
797 template<typename _Tp>
798 struct insert_point<_Tp, false, true> : public insert_base<_Tp>
800 typedef _Tp container_type;
801 typedef typename container_type::value_type value_type;
802 using insert_base<_Tp>::_F_insert_point;
804 void
805 operator()(_Tp& __test)
809 const value_type cv = generate_unique<value_type>();
810 const size_type sz = std::distance(__test.begin(), __test.end());
811 size_type s = generate(sz);
812 auto i = __test.before_begin();
813 std::advance(i, s);
814 (__test.*_F_insert_point)(i, cv);
816 catch(const __gnu_cxx::forced_error&)
817 { throw; }
820 // Assumes containers start out equivalent.
821 void
822 operator()(_Tp& __control, _Tp& __test)
826 const value_type cv = generate_unique<value_type>();
827 const size_type sz = std::distance(__test.begin(), __test.end());
828 size_type s = generate(sz);
829 auto i = __test.before_begin();
830 std::advance(i, s);
831 (__test.*_F_insert_point)(i, cv);
833 catch(const __gnu_cxx::forced_error&)
834 { throw; }
838 // Specialization, empty.
839 template<typename _Tp>
840 struct insert_point<_Tp, false, false>
842 void
843 operator()(_Tp&) { }
845 void
846 operator()(_Tp&, _Tp&) { }
850 template<typename _Tp, bool = traits<_Tp>::is_associative::value
851 || traits<_Tp>::is_unordered::value>
852 struct clear
854 void
855 operator()(_Tp& __container)
859 __container.clear();
861 catch(const __gnu_cxx::forced_error&)
862 { throw; }
866 // Specialization, empty.
867 template<typename _Tp>
868 struct clear<_Tp, false>
870 void
871 operator()(_Tp&) { }
875 template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
876 struct rehash
878 void
879 operator()(_Tp& __test)
883 size_type s = generate(__test.bucket_count());
884 __test.rehash(s);
886 catch(const __gnu_cxx::forced_error&)
887 { throw; }
890 void
891 operator()(_Tp& __control, _Tp& __test)
895 size_type s = generate(__test.bucket_count());
896 __test.rehash(s);
898 catch(const __gnu_cxx::forced_error&)
900 // Also check hash status.
901 bool fail(false);
902 if (__control.load_factor() != __test.load_factor())
903 fail = true;
904 if (__control.max_load_factor() != __test.max_load_factor())
905 fail = true;
906 if (__control.bucket_count() != __test.bucket_count())
907 fail = true;
908 if (__control.max_bucket_count() != __test.max_bucket_count())
909 fail = true;
911 if (fail)
913 char buf[40];
914 std::string __s("setup_base::rehash "
915 "containers not equal");
916 __s += "\n";
917 __s += "\n";
918 __s += "\t\t\tcontrol : test";
919 __s += "\n";
920 __s += "load_factor\t\t";
921 __builtin_sprintf(buf, "%lu", __control.load_factor());
922 __s += buf;
923 __s += " : ";
924 __builtin_sprintf(buf, "%lu", __test.load_factor());
925 __s += buf;
926 __s += "\n";
928 __s += "max_load_factor\t\t";
929 __builtin_sprintf(buf, "%lu", __control.max_load_factor());
930 __s += buf;
931 __s += " : ";
932 __builtin_sprintf(buf, "%lu", __test.max_load_factor());
933 __s += buf;
934 __s += "\n";
936 __s += "bucket_count\t\t";
937 __builtin_sprintf(buf, "%lu", __control.bucket_count());
938 __s += buf;
939 __s += " : ";
940 __builtin_sprintf(buf, "%lu", __test.bucket_count());
941 __s += buf;
942 __s += "\n";
944 __s += "max_bucket_count\t";
945 __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
946 __s += buf;
947 __s += " : ";
948 __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
949 __s += buf;
950 __s += "\n";
952 std::__throw_logic_error(__s.c_str());
958 // Specialization, empty.
959 template<typename _Tp>
960 struct rehash<_Tp, false>
962 void
963 operator()(_Tp&) { }
965 void
966 operator()(_Tp&, _Tp&) { }
970 template<typename _Tp>
971 struct swap
973 _Tp _M_other;
975 void
976 operator()(_Tp& __container)
980 __container.swap(_M_other);
982 catch(const __gnu_cxx::forced_error&)
983 { throw; }
988 template<typename _Tp>
989 struct iterator_operations
991 typedef _Tp container_type;
992 typedef typename container_type::iterator iterator;
994 void
995 operator()(_Tp& __container)
999 // Any will do.
1000 iterator i = __container.begin();
1001 iterator __attribute__((unused)) icopy(i);
1002 iterator __attribute__((unused)) iassign = i;
1004 catch(const __gnu_cxx::forced_error&)
1005 { throw; }
1010 template<typename _Tp>
1011 struct const_iterator_operations
1013 typedef _Tp container_type;
1014 typedef typename container_type::const_iterator const_iterator;
1016 void
1017 operator()(_Tp& __container)
1021 // Any will do.
1022 const_iterator i = __container.begin();
1023 const_iterator __attribute__((unused)) icopy(i);
1024 const_iterator __attribute__((unused)) iassign = i;
1026 catch(const __gnu_cxx::forced_error&)
1027 { throw; }
1032 // Base class for exception tests.
1033 template<typename _Tp>
1034 struct test_base: public functor_base
1036 typedef _Tp container_type;
1038 typedef functor_base base_type;
1039 typedef populate<container_type> populate;
1040 typedef make_container_n<container_type> make_container_n;
1042 typedef clear<container_type> clear;
1043 typedef erase_point<container_type> erase_point;
1044 typedef erase_range<container_type> erase_range;
1045 typedef insert_point<container_type> insert_point;
1046 typedef pop_front<container_type> pop_front;
1047 typedef pop_back<container_type> pop_back;
1048 typedef push_front<container_type> push_front;
1049 typedef push_back<container_type> push_back;
1050 typedef rehash<container_type> rehash;
1051 typedef swap<container_type> swap;
1052 typedef iterator_operations<container_type> iterator_ops;
1053 typedef const_iterator_operations<container_type> const_iterator_ops;
1055 using base_type::compare;
1057 // Functor objects.
1058 clear _M_clear;
1059 erase_point _M_erasep;
1060 erase_range _M_eraser;
1061 insert_point _M_insertp;
1062 pop_front _M_popf;
1063 pop_back _M_popb;
1064 push_front _M_pushf;
1065 push_back _M_pushb;
1066 rehash _M_rehash;
1067 swap _M_swap;
1069 iterator_ops _M_iops;
1070 const_iterator_ops _M_ciops;
1074 // Run through all member functions for basic exception safety
1075 // guarantee: no resource leaks when exceptions are thrown.
1077 // Types of resources checked: memory.
1079 // For each member function, use throw_value and throw_allocator as
1080 // value_type and allocator_type to force potential exception safety
1081 // errors.
1083 // NB: Assumes
1084 // _Tp::value_type is __gnu_cxx::throw_value_*
1085 // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
1086 // And that the _Cond template parameter for them both is
1087 // __gnu_cxx::limit_condition.
1088 template<typename _Tp>
1089 struct basic_safety : public test_base<_Tp>
1091 typedef _Tp container_type;
1092 typedef test_base<container_type> base_type;
1093 typedef typename base_type::populate populate;
1094 typedef std::function<void(container_type&)> function_type;
1095 typedef __gnu_cxx::limit_condition condition_type;
1097 using base_type::generate;
1099 container_type _M_container;
1100 std::vector<function_type> _M_functions;
1102 basic_safety() { run(); }
1104 void
1105 run()
1107 // Setup.
1108 condition_type::never_adjustor off;
1110 // Construct containers.
1111 populate p1(_M_container);
1112 populate p2(base_type::_M_swap._M_other);
1114 // Construct list of member functions to exercise.
1115 _M_functions.push_back(function_type(base_type::_M_iops));
1116 _M_functions.push_back(function_type(base_type::_M_ciops));
1118 _M_functions.push_back(function_type(base_type::_M_erasep));
1119 _M_functions.push_back(function_type(base_type::_M_eraser));
1120 _M_functions.push_back(function_type(base_type::_M_insertp));
1121 _M_functions.push_back(function_type(base_type::_M_popf));
1122 _M_functions.push_back(function_type(base_type::_M_popb));
1123 _M_functions.push_back(function_type(base_type::_M_pushf));
1124 _M_functions.push_back(function_type(base_type::_M_pushb));
1125 _M_functions.push_back(function_type(base_type::_M_rehash));
1126 _M_functions.push_back(function_type(base_type::_M_swap));
1128 // Last.
1129 _M_functions.push_back(function_type(base_type::_M_clear));
1131 // Run tests.
1132 for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1134 function_type& f = *i;
1135 run_steps_to_limit(f);
1139 template<typename _Funct>
1140 void
1141 run_steps_to_limit(const _Funct& __f)
1143 size_t i(1);
1144 bool exit(false);
1145 auto a = _M_container.get_allocator();
1149 // Use the current step as an allocator label.
1150 a.set_label(i);
1154 condition_type::limit_adjustor limit(i);
1155 __f(_M_container);
1157 // If we get here, done.
1158 exit = true;
1160 catch(const __gnu_cxx::forced_error&)
1162 // Check this step for allocations.
1163 // NB: Will throw std::logic_error if allocations.
1164 a.check_allocated(i);
1166 // Check memory allocated with operator new.
1168 ++i;
1171 while (!exit);
1173 // Log count info.
1174 std::cout << __f.target_type().name() << std::endl;
1175 std::cout << "end count " << i << std::endl;
1180 // Run through all member functions with a no throw requirement, sudden death.
1181 // all: member functions erase, pop_back, pop_front, swap
1182 // iterator copy ctor, assignment operator
1183 // unordered and associative: clear
1184 // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1185 template<typename _Tp>
1186 struct generation_prohibited : public test_base<_Tp>
1188 typedef _Tp container_type;
1189 typedef test_base<container_type> base_type;
1190 typedef typename base_type::populate populate;
1191 typedef __gnu_cxx::random_condition condition_type;
1193 container_type _M_container;
1195 generation_prohibited() { run(); }
1197 void
1198 run()
1200 // Furthermore, assumes that the test functor will throw
1201 // forced_exception via throw_allocator, that all errors are
1202 // propagated and in error. Sudden death!
1204 // Setup.
1206 condition_type::never_adjustor off;
1207 populate p1(_M_container);
1208 populate p2(base_type::_M_swap._M_other);
1211 // Run tests.
1213 condition_type::always_adjustor on;
1215 // NB: Vector and deque are special, erase can throw if the copy
1216 // constructor or assignment operator of value_type throws.
1217 if (!traits<container_type>::has_throwing_erase::value)
1219 _M_erasep(_M_container);
1220 _M_eraser(_M_container);
1223 _M_popf(_M_container);
1224 _M_popb(_M_container);
1226 _M_iops(_M_container);
1227 _M_ciops(_M_container);
1229 _M_swap(_M_container);
1231 // Last.
1232 _M_clear(_M_container);
1238 // Test strong exception guarantee.
1239 // Run through all member functions with a roll-back, consistent
1240 // coherent requirement.
1241 // all: member functions insert of a single element, push_back, push_front
1242 // unordered: rehash
1243 template<typename _Tp>
1244 struct propagation_consistent : public test_base<_Tp>
1246 typedef _Tp container_type;
1247 typedef test_base<container_type> base_type;
1248 typedef typename base_type::populate populate;
1249 typedef std::function<void(container_type&)> function_type;
1250 typedef __gnu_cxx::limit_condition condition_type;
1252 using base_type::compare;
1254 container_type _M_container_test;
1255 container_type _M_container_control;
1256 std::vector<function_type> _M_functions;
1258 propagation_consistent() { run(); }
1260 void
1261 sync()
1262 { _M_container_test = _M_container_control; }
1264 // Run test.
1265 void
1266 run()
1268 // Setup.
1269 condition_type::never_adjustor off;
1271 // Construct containers.
1272 populate p(_M_container_control);
1273 sync();
1275 // Construct list of member functions to exercise.
1276 _M_functions.push_back(function_type(base_type::_M_pushf));
1277 _M_functions.push_back(function_type(base_type::_M_pushb));
1278 _M_functions.push_back(function_type(base_type::_M_insertp));
1279 _M_functions.push_back(function_type(base_type::_M_rehash));
1281 // Run tests.
1282 for (auto i = _M_functions.begin(); i != _M_functions.end(); ++i)
1284 function_type& f = *i;
1285 run_steps_to_limit(f);
1289 template<typename _Funct>
1290 void
1291 run_steps_to_limit(const _Funct& __f)
1293 size_t i(1);
1294 bool exit(false);
1298 sync();
1302 condition_type::limit_adjustor limit(i);
1303 __f(_M_container_test);
1305 // If we get here, done.
1306 exit = true;
1308 catch(const __gnu_cxx::forced_error&)
1310 compare(_M_container_control, _M_container_test);
1311 ++i;
1314 while (!exit);
1316 // Log count info.
1317 std::cout << __f.target_type().name() << std::endl;
1318 std::cout << "end count " << i << std::endl;
1322 } // namespace __gnu_test
1324 #endif