3 // Copyright (C) 2009-2014 Free Software Foundation, Inc.
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
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.
29 // Base class for exception testing, contains utilities.
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].
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())
50 std::__throw_out_of_range_fmt(__N("setup_base::generate\n"
51 "random number generated is: %zu "
52 "out of range [%zu, %zu]\n"),
54 (size_t)distribution
.min(),
55 (size_t)distribution
.max());
59 // Given an instantiating type, return a unique value.
60 template<typename _Tp
>
61 struct generate_unique
63 typedef _Tp value_type
;
67 static value_type __ret
;
73 // Partial specialization for pair.
74 template<typename _Tp1
, typename _Tp2
>
75 struct generate_unique
<std::pair
<const _Tp1
, _Tp2
>>
77 typedef _Tp1 first_type
;
78 typedef _Tp2 second_type
;
79 typedef std::pair
<const _Tp1
, _Tp2
> pair_type
;
83 static first_type _S_1
;
84 static second_type _S_2
;
87 return pair_type(_S_1
, _S_2
);
91 // Partial specialization for throw_value
92 template<typename _Cond
>
93 struct generate_unique
<__gnu_cxx::throw_value_base
<_Cond
>>
95 typedef __gnu_cxx::throw_value_base
<_Cond
> value_type
;
99 static size_t _S_i(0);
100 return value_type(_S_i
++);
105 // Construct container of size n directly. _Tp == container type.
106 template<typename _Tp
>
107 struct make_container_base
111 make_container_base() = default;
112 make_container_base(const size_type n
): _M_container(n
) { }
114 operator _Tp
&() { return _M_container
; }
117 // Construct container of size n, via multiple insertions. For
118 // associated and unordered types, unique value_type elements are
120 template<typename _Tp
, bool = traits
<_Tp
>::is_mapped::value
>
121 struct make_insert_container_base
122 : public make_container_base
<_Tp
>
124 using make_container_base
<_Tp
>::_M_container
;
125 typedef typename
_Tp::value_type value_type
;
127 make_insert_container_base(const size_type n
)
129 for (size_type i
= 0; i
< n
; ++i
)
131 value_type v
= generate_unique
<value_type
>();
132 _M_container
.insert(v
);
134 assert(_M_container
.size() == n
);
138 template<typename _Tp
>
139 struct make_insert_container_base
<_Tp
, false>
140 : public make_container_base
<_Tp
>
142 using make_container_base
<_Tp
>::_M_container
;
143 typedef typename
_Tp::value_type value_type
;
145 make_insert_container_base(const size_type n
)
147 for (size_type i
= 0; i
< n
; ++i
)
149 value_type v
= generate_unique
<value_type
>();
150 _M_container
.insert(_M_container
.end(), v
);
152 assert(_M_container
.size() == n
);
156 template<typename _Tp
, bool = traits
<_Tp
>::has_size_type_constructor::value
>
157 struct make_container_n
;
159 // Specialization for non-associative types that have a constructor with
161 template<typename _Tp
>
162 struct make_container_n
<_Tp
, true>
163 : public make_container_base
<_Tp
>
165 make_container_n(const size_type n
) : make_container_base
<_Tp
>(n
) { }
168 template<typename _Tp
>
169 struct make_container_n
<_Tp
, false>
170 : public make_insert_container_base
<_Tp
>
172 make_container_n(const size_type n
)
173 : make_insert_container_base
<_Tp
>(n
) { }
177 // Randomly size and populate a given container reference.
178 // NB: Responsibility for turning off exceptions lies with caller.
179 template<typename _Tp
, bool = traits
<_Tp
>::is_allocator_aware::value
>
182 typedef _Tp container_type
;
183 typedef typename
container_type::allocator_type allocator_type
;
184 typedef typename
container_type::value_type value_type
;
186 populate(_Tp
& __container
)
188 const allocator_type a
= __container
.get_allocator();
190 // Size test container.
191 const size_type max_elements
= 100;
192 size_type n
= generate(max_elements
);
194 // Construct new container.
195 make_container_n
<container_type
> made(n
);
196 container_type
& tmp
= made
;
197 std::swap(tmp
, __container
);
201 // Partial specialization, empty.
202 template<typename _Tp
>
203 struct populate
<_Tp
, false>
208 // Compare two containers for equivalence.
209 // Right now, that means size.
210 // Returns true if equal, throws if not.
211 template<typename _Tp
>
213 compare(const _Tp
& __control
, const _Tp
& __test
)
215 // Make sure test container is in a consistent state, as
216 // compared to the control container.
217 // NB: Should be equivalent to __test != __control, but
218 // computed without equivalence operators
220 = std::distance(__test
.begin(), __test
.end());
222 = std::distance(__control
.begin(), __control
.end());
225 throw std::logic_error(
226 "setup_base::compare containers size not equal");
228 // Should test iterator validity before and after exception.
229 bool __equal_it
= std::equal(__test
.begin(), __test
.end(),
233 throw std::logic_error(
234 "setup_base::compare containers iterators not equal");
241 // Containing structure holding functors.
242 struct functor_base
: public setup_base
244 // Abstract the erase function.
245 template<typename _Tp
>
248 typedef typename
_Tp::iterator iterator
;
249 typedef typename
_Tp::const_iterator const_iterator
;
251 iterator (_Tp::* _F_erase_point
)(const_iterator
);
252 iterator (_Tp::* _F_erase_range
)(const_iterator
, const_iterator
);
255 : _F_erase_point(&_Tp::erase
), _F_erase_range(&_Tp::erase
) { }
258 #if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
259 // Specialization, old C++03 signature.
260 template<typename _Tp1
, typename _Tp2
, typename _Tp3
>
261 struct erase_base
<std::basic_string
<_Tp1
, _Tp2
, _Tp3
>>
263 typedef std::basic_string
<_Tp1
, _Tp2
, _Tp3
> container_type
;
264 typedef typename
container_type::iterator iterator
;
266 iterator (container_type::* _F_erase_point
)(iterator
);
267 iterator (container_type::* _F_erase_range
)(iterator
, iterator
);
270 : _F_erase_point(&container_type::erase
),
271 _F_erase_range(&container_type::erase
) { }
275 // Specialization, as forward_list has erase_after.
276 template<typename _Tp1
, typename _Tp2
>
277 struct erase_base
<std::forward_list
<_Tp1
, _Tp2
>>
279 typedef std::forward_list
<_Tp1
, _Tp2
> container_type
;
280 typedef typename
container_type::iterator iterator
;
281 typedef typename
container_type::const_iterator const_iterator
;
283 iterator (container_type::* _F_erase_point
)(const_iterator
);
284 iterator (container_type::* _F_erase_range
)(const_iterator
,
288 : _F_erase_point(&container_type::erase_after
),
289 _F_erase_range(&container_type::erase_after
) { }
292 template<typename _Tp
,
293 bool = traits
<_Tp
>::has_erase::value
,
294 bool = traits
<_Tp
>::has_erase_after::value
>
297 // Specialization for most containers.
298 template<typename _Tp
>
299 struct erase_point
<_Tp
, true, false> : public erase_base
<_Tp
>
301 using erase_base
<_Tp
>::_F_erase_point
;
304 operator()(_Tp
& __container
)
308 // NB: Should be equivalent to size() member function, but
309 // computed with begin() and end().
310 const size_type sz
= std::distance(__container
.begin(),
313 // NB: Lowest common denominator: use forward iterator operations.
314 auto i
= __container
.begin();
315 std::advance(i
, generate(sz
));
317 // Makes it easier to think of this as __container.erase(i)
318 (__container
.*_F_erase_point
)(i
);
320 catch(const __gnu_cxx::forced_error
&)
325 // Specialization for forward_list.
326 template<typename _Tp
>
327 struct erase_point
<_Tp
, false, true> : public erase_base
<_Tp
>
329 using erase_base
<_Tp
>::_F_erase_point
;
332 operator()(_Tp
& __container
)
336 // NB: Should be equivalent to size() member function, but
337 // computed with begin() and end().
338 const size_type sz
= std::distance(__container
.begin(),
341 // NB: Lowest common denominator: use forward iterator operations.
342 auto i
= __container
.before_begin();
343 std::advance(i
, generate(sz
));
345 // Makes it easier to think of this as __container.erase(i)
346 (__container
.*_F_erase_point
)(i
);
348 catch(const __gnu_cxx::forced_error
&)
353 // Specialization, empty.
354 template<typename _Tp
>
355 struct erase_point
<_Tp
, false, false>
362 template<typename _Tp
,
363 bool = traits
<_Tp
>::has_erase::value
,
364 bool = traits
<_Tp
>::has_erase_after::value
>
367 // Specialization for most containers.
368 template<typename _Tp
>
369 struct erase_range
<_Tp
, true, false> : public erase_base
<_Tp
>
371 using erase_base
<_Tp
>::_F_erase_range
;
374 operator()(_Tp
& __container
)
378 const size_type sz
= std::distance(__container
.begin(),
380 size_type s1
= generate(sz
);
381 size_type s2
= generate(sz
);
382 auto i1
= __container
.begin();
383 auto i2
= __container
.begin();
384 std::advance(i1
, std::min(s1
, s2
));
385 std::advance(i2
, std::max(s1
, s2
));
387 // Makes it easier to think of this as __container.erase(i1, i2).
388 (__container
.*_F_erase_range
)(i1
, i2
);
390 catch(const __gnu_cxx::forced_error
&)
395 // Specialization for forward_list.
396 template<typename _Tp
>
397 struct erase_range
<_Tp
, false, true> : public erase_base
<_Tp
>
399 using erase_base
<_Tp
>::_F_erase_range
;
402 operator()(_Tp
& __container
)
406 const size_type sz
= std::distance(__container
.begin(),
408 size_type s1
= generate(sz
);
409 size_type s2
= generate(sz
);
410 auto i1
= __container
.before_begin();
411 auto i2
= __container
.before_begin();
412 std::advance(i1
, std::min(s1
, s2
));
413 std::advance(i2
, std::max(s1
, s2
));
415 // Makes it easier to think of this as __container.erase(i1, i2).
416 (__container
.*_F_erase_range
)(i1
, i2
);
418 catch(const __gnu_cxx::forced_error
&)
423 // Specialization, empty.
424 template<typename _Tp
>
425 struct erase_range
<_Tp
, false, false>
432 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
>
436 operator()(_Tp
& __container
)
440 __container
.pop_front();
442 catch(const __gnu_cxx::forced_error
&)
447 // Specialization, empty.
448 template<typename _Tp
>
449 struct pop_front
<_Tp
, false>
456 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
457 && traits
<_Tp
>::is_reversible::value
>
461 operator()(_Tp
& __container
)
465 __container
.pop_back();
467 catch(const __gnu_cxx::forced_error
&)
472 // Specialization, empty.
473 template<typename _Tp
>
474 struct pop_back
<_Tp
, false>
481 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
>
484 typedef _Tp container_type
;
485 typedef typename
container_type::value_type value_type
;
488 operator()(_Tp
& __test
)
492 const value_type cv
= generate_unique
<value_type
>();
493 __test
.push_front(cv
);
495 catch(const __gnu_cxx::forced_error
&)
499 // Assumes containers start out equivalent.
501 operator()(_Tp
& __control
, _Tp
& __test
)
505 const value_type cv
= generate_unique
<value_type
>();
506 __test
.push_front(cv
);
508 catch(const __gnu_cxx::forced_error
&)
513 // Specialization, empty.
514 template<typename _Tp
>
515 struct push_front
<_Tp
, false>
521 operator()(_Tp
&, _Tp
&) { }
525 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
526 && traits
<_Tp
>::is_reversible::value
>
529 typedef _Tp container_type
;
530 typedef typename
container_type::value_type value_type
;
533 operator()(_Tp
& __test
)
537 const value_type cv
= generate_unique
<value_type
>();
538 __test
.push_back(cv
);
540 catch(const __gnu_cxx::forced_error
&)
544 // Assumes containers start out equivalent.
546 operator()(_Tp
& __control
, _Tp
& __test
)
550 const value_type cv
= generate_unique
<value_type
>();
551 __test
.push_back(cv
);
553 catch(const __gnu_cxx::forced_error
&)
558 // Specialization, empty.
559 template<typename _Tp
>
560 struct push_back
<_Tp
, false>
566 operator()(_Tp
&, _Tp
&) { }
569 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
570 && traits
<_Tp
>::has_emplace::value
>
573 typedef _Tp container_type
;
574 typedef typename
container_type::value_type value_type
;
577 operator()(_Tp
& __test
)
581 const value_type cv
= generate_unique
<value_type
>();
582 __test
.emplace_front(cv
);
584 catch(const __gnu_cxx::forced_error
&)
588 // Assumes containers start out equivalent.
590 operator()(_Tp
& __control
, _Tp
& __test
)
594 const value_type cv
= generate_unique
<value_type
>();
595 __test
.emplace_front(cv
);
597 catch(const __gnu_cxx::forced_error
&)
602 // Specialization, empty.
603 template<typename _Tp
>
604 struct emplace_front
<_Tp
, false>
610 operator()(_Tp
&, _Tp
&) { }
614 template<typename _Tp
, bool = traits
<_Tp
>::has_push_pop::value
615 && traits
<_Tp
>::has_emplace::value
616 && traits
<_Tp
>::is_reversible::value
>
619 typedef _Tp container_type
;
620 typedef typename
container_type::value_type value_type
;
623 operator()(_Tp
& __test
)
627 const value_type cv
= generate_unique
<value_type
>();
628 __test
.emplace_back(cv
);
630 catch(const __gnu_cxx::forced_error
&)
634 // Assumes containers start out equivalent.
636 operator()(_Tp
& __control
, _Tp
& __test
)
640 const value_type cv
= generate_unique
<value_type
>();
641 __test
.push_back(cv
);
643 catch(const __gnu_cxx::forced_error
&)
648 // Specialization, empty.
649 template<typename _Tp
>
650 struct emplace_back
<_Tp
, false>
656 operator()(_Tp
&, _Tp
&) { }
660 // Abstract the insert function into two parts:
661 // 1, insert_base_functions == holds function pointer
662 // 2, insert_base == links function pointer to class insert method
663 template<typename _Tp
>
666 typedef typename
_Tp::iterator iterator
;
667 typedef typename
_Tp::const_iterator const_iterator
;
668 typedef typename
_Tp::value_type value_type
;
670 iterator (_Tp::* _F_insert_point
)(const_iterator
, const value_type
&);
672 insert_base() : _F_insert_point(&_Tp::insert
) { }
675 // Specialization, old C++03 signature.
676 template<typename _Tp1
, typename _Tp2
, typename _Tp3
>
677 struct insert_base
<std::basic_string
<_Tp1
, _Tp2
, _Tp3
>>
679 typedef std::basic_string
<_Tp1
, _Tp2
, _Tp3
> container_type
;
680 typedef typename
container_type::iterator iterator
;
681 typedef typename
container_type::const_iterator const_iterator
;
682 typedef typename
container_type::value_type value_type
;
684 #if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
685 iterator (container_type::* _F_insert_point
)(iterator
, value_type
);
687 iterator (container_type::* _F_insert_point
)(const_iterator
,
691 insert_base() : _F_insert_point(&container_type::insert
) { }
694 // Specialization, by value.
695 template<typename _Tp1
, typename _Tp2
, typename _Tp3
,
696 template <typename
, typename
, typename
> class _Tp4
>
697 struct insert_base
<__gnu_cxx::__versa_string
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>>
699 typedef __gnu_cxx::__versa_string
<_Tp1
, _Tp2
, _Tp3
, _Tp4
>
701 typedef typename
container_type::iterator iterator
;
702 typedef typename
container_type::const_iterator const_iterator
;
703 typedef typename
container_type::value_type value_type
;
705 iterator (container_type::* _F_insert_point
)(const_iterator
,
708 insert_base() : _F_insert_point(&container_type::insert
) { }
711 // Specialization, as forward_list has insert_after.
712 template<typename _Tp1
, typename _Tp2
>
713 struct insert_base
<std::forward_list
<_Tp1
, _Tp2
>>
715 typedef std::forward_list
<_Tp1
, _Tp2
> container_type
;
716 typedef typename
container_type::iterator iterator
;
717 typedef typename
container_type::const_iterator const_iterator
;
718 typedef typename
container_type::value_type value_type
;
720 iterator (container_type::* _F_insert_point
)(const_iterator
,
723 insert_base() : _F_insert_point(&container_type::insert_after
) { }
726 template<typename _Tp
, bool = traits
<_Tp
>::has_insert::value
,
727 bool = traits
<_Tp
>::has_insert_after::value
>
730 // Specialization for most containers.
731 template<typename _Tp
>
732 struct insert_point
<_Tp
, true, false> : public insert_base
<_Tp
>
734 typedef _Tp container_type
;
735 typedef typename
container_type::value_type value_type
;
736 using insert_base
<_Tp
>::_F_insert_point
;
739 operator()(_Tp
& __test
)
743 const value_type cv
= generate_unique
<value_type
>();
744 const size_type sz
= std::distance(__test
.begin(), __test
.end());
745 size_type s
= generate(sz
);
746 auto i
= __test
.begin();
748 (__test
.*_F_insert_point
)(i
, cv
);
750 catch(const __gnu_cxx::forced_error
&)
754 // Assumes containers start out equivalent.
756 operator()(_Tp
& __control
, _Tp
& __test
)
760 const value_type cv
= generate_unique
<value_type
>();
761 const size_type sz
= std::distance(__test
.begin(), __test
.end());
762 size_type s
= generate(sz
);
763 auto i
= __test
.begin();
765 (__test
.*_F_insert_point
)(i
, cv
);
767 catch(const __gnu_cxx::forced_error
&)
772 // Specialization for forward_list.
773 template<typename _Tp
>
774 struct insert_point
<_Tp
, false, true> : public insert_base
<_Tp
>
776 typedef _Tp container_type
;
777 typedef typename
container_type::value_type value_type
;
778 using insert_base
<_Tp
>::_F_insert_point
;
781 operator()(_Tp
& __test
)
785 const value_type cv
= generate_unique
<value_type
>();
786 const size_type sz
= std::distance(__test
.begin(), __test
.end());
787 size_type s
= generate(sz
);
788 auto i
= __test
.before_begin();
790 (__test
.*_F_insert_point
)(i
, cv
);
792 catch(const __gnu_cxx::forced_error
&)
796 // Assumes containers start out equivalent.
798 operator()(_Tp
& __control
, _Tp
& __test
)
802 const value_type cv
= generate_unique
<value_type
>();
803 const size_type sz
= std::distance(__test
.begin(), __test
.end());
804 size_type s
= generate(sz
);
805 auto i
= __test
.before_begin();
807 (__test
.*_F_insert_point
)(i
, cv
);
809 catch(const __gnu_cxx::forced_error
&)
814 // Specialization, empty.
815 template<typename _Tp
>
816 struct insert_point
<_Tp
, false, false>
822 operator()(_Tp
&, _Tp
&) { }
825 template<typename _Tp
, bool = traits
<_Tp
>::has_emplace::value
826 && (traits
<_Tp
>::is_associative::value
827 || traits
<_Tp
>::is_unordered::value
)>
830 // Specialization for associative and unordered containers.
831 template<typename _Tp
>
832 struct emplace
<_Tp
, true>
834 typedef _Tp container_type
;
835 typedef typename
container_type::value_type value_type
;
836 typedef typename
container_type::size_type size_type
;
839 operator()(_Tp
& __test
)
843 const value_type cv
= generate_unique
<value_type
>();
846 catch(const __gnu_cxx::forced_error
&)
850 // Assumes containers start out equivalent.
852 operator()(_Tp
& __control
, _Tp
& __test
)
856 const value_type cv
= generate_unique
<value_type
>();
859 catch(const __gnu_cxx::forced_error
&)
864 // Specialization, empty.
865 template<typename _Tp
>
866 struct emplace
<_Tp
, false>
872 operator()(_Tp
&, _Tp
&) { }
875 template<typename _Tp
, bool = traits
<_Tp
>::has_emplace::value
,
876 bool = traits
<_Tp
>::is_associative::value
877 || traits
<_Tp
>::is_unordered::value
,
878 bool = traits
<_Tp
>::has_insert_after::value
>
879 struct emplace_point
;
881 // Specialization for most containers.
882 template<typename _Tp
>
883 struct emplace_point
<_Tp
, true, false, false>
885 typedef _Tp container_type
;
886 typedef typename
container_type::value_type value_type
;
889 operator()(_Tp
& __test
)
893 const value_type cv
= generate_unique
<value_type
>();
894 const size_type sz
= std::distance(__test
.begin(), __test
.end());
895 size_type s
= generate(sz
);
896 auto i
= __test
.begin();
898 __test
.emplace(i
, cv
);
900 catch(const __gnu_cxx::forced_error
&)
904 // Assumes containers start out equivalent.
906 operator()(_Tp
& __control
, _Tp
& __test
)
910 const value_type cv
= generate_unique
<value_type
>();
911 const size_type sz
= std::distance(__test
.begin(), __test
.end());
912 size_type s
= generate(sz
);
913 auto i
= __test
.begin();
915 __test
.emplace(i
, cv
);
917 catch(const __gnu_cxx::forced_error
&)
922 // Specialization for associative and unordered containers.
923 template<typename _Tp
>
924 struct emplace_point
<_Tp
, true, true, false>
926 typedef _Tp container_type
;
927 typedef typename
container_type::value_type value_type
;
930 operator()(_Tp
& __test
)
934 const value_type cv
= generate_unique
<value_type
>();
935 const size_type sz
= std::distance(__test
.begin(), __test
.end());
936 size_type s
= generate(sz
);
937 auto i
= __test
.begin();
939 __test
.emplace_hint(i
, cv
);
941 catch(const __gnu_cxx::forced_error
&)
945 // Assumes containers start out equivalent.
947 operator()(_Tp
& __control
, _Tp
& __test
)
951 const value_type cv
= generate_unique
<value_type
>();
952 const size_type sz
= std::distance(__test
.begin(), __test
.end());
953 size_type s
= generate(sz
);
954 auto i
= __test
.begin();
956 __test
.emplace_hint(i
, cv
);
958 catch(const __gnu_cxx::forced_error
&)
963 // Specialization for forward_list.
964 template<typename _Tp
>
965 struct emplace_point
<_Tp
, true, false, true>
967 typedef _Tp container_type
;
968 typedef typename
container_type::value_type value_type
;
971 operator()(_Tp
& __test
)
975 const value_type cv
= generate_unique
<value_type
>();
976 const size_type sz
= std::distance(__test
.begin(), __test
.end());
977 size_type s
= generate(sz
);
978 auto i
= __test
.before_begin();
980 __test
.emplace_after(i
, cv
);
982 catch(const __gnu_cxx::forced_error
&)
986 // Assumes containers start out equivalent.
988 operator()(_Tp
& __control
, _Tp
& __test
)
992 const value_type cv
= generate_unique
<value_type
>();
993 const size_type sz
= std::distance(__test
.begin(), __test
.end());
994 size_type s
= generate(sz
);
995 auto i
= __test
.before_begin();
997 __test
.emplace_after(i
, cv
);
999 catch(const __gnu_cxx::forced_error
&)
1004 // Specialization, empty.
1005 template<typename _Tp
, bool is_associative_or_unordered
,
1006 bool has_insert_after
>
1007 struct emplace_point
<_Tp
, false, is_associative_or_unordered
,
1011 operator()(_Tp
&) { }
1014 operator()(_Tp
&, _Tp
&) { }
1017 template<typename _Tp
, bool = traits
<_Tp
>::is_associative::value
1018 || traits
<_Tp
>::is_unordered::value
>
1022 operator()(_Tp
& __container
)
1026 __container
.clear();
1028 catch(const __gnu_cxx::forced_error
&)
1033 // Specialization, empty.
1034 template<typename _Tp
>
1035 struct clear
<_Tp
, false>
1038 operator()(_Tp
&) { }
1042 template<typename _Tp
, bool = traits
<_Tp
>::is_unordered::value
>
1046 operator()(_Tp
& __test
)
1050 size_type s
= generate(__test
.bucket_count());
1053 catch(const __gnu_cxx::forced_error
&)
1058 operator()(_Tp
& __control
, _Tp
& __test
)
1062 size_type s
= generate(__test
.bucket_count());
1065 catch(const __gnu_cxx::forced_error
&)
1067 // Also check hash status.
1069 if (__control
.load_factor() != __test
.load_factor())
1071 if (__control
.max_load_factor() != __test
.max_load_factor())
1073 if (__control
.bucket_count() != __test
.bucket_count())
1075 if (__control
.max_bucket_count() != __test
.max_bucket_count())
1081 std::string
__s("setup_base::rehash "
1082 "containers not equal");
1085 __s
+= "\t\t\tcontrol : test";
1087 __s
+= "load_factor\t\t";
1088 __builtin_sprintf(buf
, "%lu", __control
.load_factor());
1091 __builtin_sprintf(buf
, "%lu", __test
.load_factor());
1095 __s
+= "max_load_factor\t\t";
1096 __builtin_sprintf(buf
, "%lu", __control
.max_load_factor());
1099 __builtin_sprintf(buf
, "%lu", __test
.max_load_factor());
1103 __s
+= "bucket_count\t\t";
1104 __builtin_sprintf(buf
, "%lu", __control
.bucket_count());
1107 __builtin_sprintf(buf
, "%lu", __test
.bucket_count());
1111 __s
+= "max_bucket_count\t";
1112 __builtin_sprintf(buf
, "%lu", __control
.max_bucket_count());
1115 __builtin_sprintf(buf
, "%lu", __test
.max_bucket_count());
1119 std::__throw_logic_error(__s
.c_str());
1125 // Specialization, empty.
1126 template<typename _Tp
>
1127 struct rehash
<_Tp
, false>
1130 operator()(_Tp
&) { }
1133 operator()(_Tp
&, _Tp
&) { }
1137 template<typename _Tp
>
1143 operator()(_Tp
& __container
)
1147 __container
.swap(_M_other
);
1149 catch(const __gnu_cxx::forced_error
&)
1155 template<typename _Tp
>
1156 struct iterator_operations
1158 typedef _Tp container_type
;
1159 typedef typename
container_type::iterator iterator
;
1162 operator()(_Tp
& __container
)
1167 iterator i
= __container
.begin();
1168 iterator
__attribute__((unused
)) icopy(i
);
1169 iterator
__attribute__((unused
)) iassign
= i
;
1171 catch(const __gnu_cxx::forced_error
&)
1177 template<typename _Tp
>
1178 struct const_iterator_operations
1180 typedef _Tp container_type
;
1181 typedef typename
container_type::const_iterator const_iterator
;
1184 operator()(_Tp
& __container
)
1189 const_iterator i
= __container
.begin();
1190 const_iterator
__attribute__((unused
)) icopy(i
);
1191 const_iterator
__attribute__((unused
)) iassign
= i
;
1193 catch(const __gnu_cxx::forced_error
&)
1198 template<typename _Tp
>
1199 struct assign_operator
1204 operator()(_Tp
& __container
)
1208 // An exception while assigning might leave the container empty
1209 // making future attempts less relevant. So we copy it before to
1210 // always assign to a non empty container. It also check for copy
1211 // constructor exception safety at the same time.
1212 _Tp
__clone(__container
);
1215 catch(const __gnu_cxx::forced_error
&)
1221 #if __cplusplus >= 201103L
1222 template<typename _Tp
>
1223 struct move_assign_operator
1228 operator()(_Tp
& __container
)
1232 __container
= std::move(_M_other
);
1234 catch(const __gnu_cxx::forced_error
&)
1241 // Base class for exception tests.
1242 template<typename _Tp
>
1243 struct test_base
: public functor_base
1245 typedef _Tp container_type
;
1247 typedef functor_base base_type
;
1248 typedef populate
<container_type
> populate
;
1249 typedef make_container_n
<container_type
> make_container_n
;
1251 typedef clear
<container_type
> clear
;
1252 typedef erase_point
<container_type
> erase_point
;
1253 typedef erase_range
<container_type
> erase_range
;
1254 typedef insert_point
<container_type
> insert_point
;
1255 typedef emplace
<container_type
> emplace
;
1256 typedef emplace_point
<container_type
> emplace_point
;
1257 typedef emplace_front
<container_type
> emplace_front
;
1258 typedef emplace_back
<container_type
> emplace_back
;
1259 typedef pop_front
<container_type
> pop_front
;
1260 typedef pop_back
<container_type
> pop_back
;
1261 typedef push_front
<container_type
> push_front
;
1262 typedef push_back
<container_type
> push_back
;
1263 typedef rehash
<container_type
> rehash
;
1264 typedef swap
<container_type
> swap
;
1265 typedef iterator_operations
<container_type
> iterator_ops
;
1266 typedef const_iterator_operations
<container_type
> const_iterator_ops
;
1267 typedef assign_operator
<container_type
> assign_operator
;
1268 #if __cplusplus >= 201103L
1269 typedef move_assign_operator
<container_type
> move_assign_operator
;
1272 using base_type::compare
;
1276 // Run through all member functions for basic exception safety
1277 // guarantee: no resource leaks when exceptions are thrown.
1279 // Types of resources checked: memory.
1281 // For each member function, use throw_value and throw_allocator as
1282 // value_type and allocator_type to force potential exception safety
1286 // _Tp::value_type is __gnu_cxx::throw_value_*
1287 // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
1288 // And that the _Cond template parameter for them both is
1289 // __gnu_cxx::limit_condition.
1290 template<typename _Tp
>
1291 struct basic_safety
: public test_base
<_Tp
>
1293 typedef _Tp container_type
;
1294 typedef test_base
<container_type
> base_type
;
1295 typedef typename
base_type::populate populate
;
1296 typedef std::function
<void(container_type
&)> function_type
;
1297 typedef __gnu_cxx::limit_condition condition_type
;
1299 using base_type::generate
;
1301 basic_safety() { run(); }
1308 condition_type::never_adjustor off
;
1310 // Construct containers.
1311 container_type container
;
1312 populate
p1(container
);
1314 // Construct list of member functions to exercise.
1315 std::vector
<function_type
> functions
;
1316 typename
base_type::iterator_ops iops
;
1317 functions
.push_back(function_type(iops
));
1318 typename
base_type::const_iterator_ops ciops
;
1319 functions
.push_back(function_type(ciops
));
1321 typename
base_type::erase_point erasep
;
1322 functions
.push_back(function_type(erasep
));
1323 typename
base_type::erase_range eraser
;
1324 functions
.push_back(function_type(eraser
));
1325 typename
base_type::insert_point insertp
;
1326 functions
.push_back(function_type(insertp
));
1327 typename
base_type::emplace emplace
;
1328 functions
.push_back(function_type(emplace
));
1329 typename
base_type::emplace_point emplacep
;
1330 functions
.push_back(function_type(emplacep
));
1331 typename
base_type::emplace_front emplacef
;
1332 functions
.push_back(function_type(emplacef
));
1333 typename
base_type::emplace_back emplaceb
;
1334 functions
.push_back(function_type(emplaceb
));
1335 typename
base_type::pop_front popf
;
1336 functions
.push_back(function_type(popf
));
1337 typename
base_type::pop_back popb
;
1338 functions
.push_back(function_type(popb
));
1339 typename
base_type::push_front pushf
;
1340 functions
.push_back(function_type(pushf
));
1341 typename
base_type::push_back pushb
;
1342 functions
.push_back(function_type(pushb
));
1343 typename
base_type::rehash rehash
;
1344 functions
.push_back(function_type(rehash
));
1345 typename
base_type::swap swap
;
1346 populate
p2(swap
._M_other
);
1347 functions
.push_back(function_type(swap
));
1348 typename
base_type::assign_operator assignop
;
1349 populate
p3(assignop
._M_other
);
1350 functions
.push_back(function_type(assignop
));
1351 #if __cplusplus >= 201103L
1352 typename
base_type::move_assign_operator massignop
;
1353 populate
p4(massignop
._M_other
);
1354 functions
.push_back(function_type(massignop
));
1357 typename
base_type::clear clear
;
1358 functions
.push_back(function_type(clear
));
1362 for (auto it
= functions
.begin(); it
!= functions
.end(); ++it
)
1364 function_type
& f
= *it
;
1365 i
= run_steps_to_limit(i
, container
, f
);
1369 // Now that all instances has been destroyed check that there is no
1370 // allocation remaining.
1371 std::cout
<< "Checking remaining stuff" << std::endl
;
1372 __gnu_cxx::annotate_base::check();
1375 template<typename _Funct
>
1377 run_steps_to_limit(size_t __step
, container_type
& __cont
,
1381 auto a
= __cont
.get_allocator();
1385 // Use the current step as an allocator label.
1386 a
.set_label(__step
);
1390 condition_type::limit_adjustor
limit(__step
);
1393 // If we get here, done.
1396 catch(const __gnu_cxx::forced_error
&)
1398 // Check this step for allocations.
1399 // NB: Will throw std::logic_error if allocations.
1402 // Check memory allocated with operator new.
1410 std::cout
<< __f
.target_type().name() << std::endl
;
1411 std::cout
<< "end count " << __step
<< std::endl
;
1417 // Run through all member functions with a no throw requirement, sudden death.
1418 // all: member functions erase, pop_back, pop_front, swap
1419 // iterator copy ctor, assignment operator
1420 // unordered and associative: clear
1421 // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1422 template<typename _Tp
>
1423 struct generation_prohibited
: public test_base
<_Tp
>
1425 typedef _Tp container_type
;
1426 typedef test_base
<container_type
> base_type
;
1427 typedef typename
base_type::populate populate
;
1428 typedef __gnu_cxx::random_condition condition_type
;
1430 generation_prohibited() { run(); }
1435 // Furthermore, assumes that the test functor will throw
1436 // forced_exception via throw_allocator, that all errors are
1437 // propagated and in error. Sudden death!
1440 container_type container
;
1441 typename
base_type::swap swap
;
1444 condition_type::never_adjustor off
;
1445 populate
p1(container
);
1446 populate
p2(swap
._M_other
);
1451 condition_type::always_adjustor on
;
1453 // NB: Vector and deque are special, erase can throw if the copy
1454 // constructor or assignment operator of value_type throws.
1455 if (!traits
<container_type
>::has_throwing_erase::value
)
1457 typename
base_type::erase_point erasep
;
1459 typename
base_type::erase_range eraser
;
1463 typename
base_type::pop_front popf
;
1465 typename
base_type::pop_back popb
;
1468 typename
base_type::iterator_ops iops
;
1470 typename
base_type::const_iterator_ops ciops
;
1476 typename
base_type::clear clear
;
1483 // Test strong exception guarantee.
1484 // Run through all member functions with a roll-back, consistent
1485 // coherent requirement.
1486 // all: member functions insert and emplace of a single element, push_back,
1488 // unordered: rehash
1489 template<typename _Tp
>
1490 struct propagation_consistent
: public test_base
<_Tp
>
1492 typedef _Tp container_type
;
1493 typedef test_base
<container_type
> base_type
;
1494 typedef typename
base_type::populate populate
;
1495 typedef std::function
<void(container_type
&)> function_type
;
1496 typedef __gnu_cxx::limit_condition condition_type
;
1498 using base_type::compare
;
1500 propagation_consistent() { run(); }
1507 condition_type::never_adjustor off
;
1509 // Construct containers.
1510 container_type container_control
;
1512 populate
p(container_control
);
1514 // Construct list of member functions to exercise.
1515 std::vector
<function_type
> functions
;
1516 typename
base_type::emplace emplace
;
1517 functions
.push_back(function_type(emplace
));
1518 typename
base_type::emplace_point emplacep
;
1519 functions
.push_back(function_type(emplacep
));
1520 typename
base_type::emplace_front emplacef
;
1521 functions
.push_back(function_type(emplacef
));
1522 typename
base_type::emplace_back emplaceb
;
1523 functions
.push_back(function_type(emplaceb
));
1524 typename
base_type::push_front pushf
;
1525 functions
.push_back(function_type(pushf
));
1526 typename
base_type::push_back pushb
;
1527 functions
.push_back(function_type(pushb
));
1528 typename
base_type::insert_point insertp
;
1529 functions
.push_back(function_type(insertp
));
1530 typename
base_type::rehash rehash
;
1531 functions
.push_back(function_type(rehash
));
1534 for (auto i
= functions
.begin(); i
!= functions
.end(); ++i
)
1536 function_type
& f
= *i
;
1537 run_steps_to_limit(container_control
, f
);
1541 template<typename _Funct
>
1543 run_steps_to_limit(container_type
& container_control
, const _Funct
& __f
)
1550 container_type
container_test(container_control
);
1554 condition_type::limit_adjustor
limit(i
);
1555 __f(container_test
);
1557 // If we get here, done.
1560 catch(const __gnu_cxx::forced_error
&)
1562 compare(container_control
, container_test
);
1569 std::cout
<< __f
.target_type().name() << std::endl
;
1570 std::cout
<< "end count " << i
<< std::endl
;
1574 } // namespace __gnu_test