c++: Fix ICE with #embed/RAW_DATA_CST after list conversion [PR118671]
[gcc.git] / libstdc++-v3 / testsuite / util / exception / safety.h
blob8226c1762016aabf83a5ea38d059bc3228f5c9a1
1 // -*- C++ -*-
3 // Copyright (C) 2009-2025 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>
25 #include <cstdlib> // getenv, atoi
26 #include <cstdio> // printf, fflush
28 // Container requirement testing.
29 namespace __gnu_test
31 // Base class for exception testing, contains utilities.
32 struct setup_base
34 typedef std::size_t size_type;
35 typedef std::uniform_int_distribution<size_type> distribution_type;
36 typedef std::mt19937 engine_type;
38 static engine_type
39 get_engine()
41 engine_type engine;
42 if (const char* v = std::getenv("GLIBCXX_SEED_TEST_RNG"))
44 // A single seed value is much smaller than the mt19937 state size,
45 // but we're not trying to be cryptographically secure here.
46 int s = std::atoi(v);
47 if (s == 0)
48 s = (int)std::random_device{}();
49 std::printf("Using random seed %d\n", s);
50 std::fflush(stdout);
51 engine.seed((unsigned)s);
53 return engine;
56 // Return randomly generated integer on range [0, __max_size].
57 static size_type
58 generate(size_type __max_size)
60 using param_type = typename distribution_type::param_type;
62 // Make the engine and distribution static...
63 static engine_type engine = get_engine();
64 static distribution_type distribution;
65 return distribution(engine, param_type{0, __max_size});
68 // Given an instantiating type, return a unique value.
69 template<typename _Tp>
70 struct generate_unique
72 typedef _Tp value_type;
74 operator value_type()
76 static value_type __ret;
77 ++__ret;
78 return __ret;
82 // Partial specialization for pair.
83 template<typename _Tp1, typename _Tp2>
84 struct generate_unique<std::pair<const _Tp1, _Tp2>>
86 typedef _Tp1 first_type;
87 typedef _Tp2 second_type;
88 typedef std::pair<const _Tp1, _Tp2> pair_type;
90 operator pair_type()
92 static first_type _S_1;
93 static second_type _S_2;
94 ++_S_1;
95 ++_S_2;
96 return pair_type(_S_1, _S_2);
100 // Partial specialization for throw_value
101 template<typename _Cond>
102 struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
104 typedef __gnu_cxx::throw_value_base<_Cond> value_type;
106 operator value_type()
108 static size_t _S_i(0);
109 return value_type(_S_i++);
114 // Construct container of size n directly. _Tp == container type.
115 template<typename _Tp>
116 struct make_container_base
118 _Tp _M_container;
120 make_container_base() = default;
121 make_container_base(const size_type n): _M_container(n) { }
123 operator _Tp&() { return _M_container; }
126 // Construct container of size n, via multiple insertions. For
127 // associated and unordered types, unique value_type elements are
128 // necessary.
129 template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
130 struct make_insert_container_base
131 : public make_container_base<_Tp>
133 using make_container_base<_Tp>::_M_container;
134 typedef typename _Tp::value_type value_type;
136 make_insert_container_base(const size_type n)
138 for (size_type i = 0; i < n; ++i)
140 value_type v = generate_unique<value_type>();
141 _M_container.insert(v);
143 assert(_M_container.size() == n);
147 template<typename _Tp>
148 struct make_insert_container_base<_Tp, false>
149 : public make_container_base<_Tp>
151 using make_container_base<_Tp>::_M_container;
152 typedef typename _Tp::value_type value_type;
154 make_insert_container_base(const size_type n)
156 for (size_type i = 0; i < n; ++i)
158 value_type v = generate_unique<value_type>();
159 _M_container.insert(_M_container.end(), v);
161 assert(_M_container.size() == n);
165 template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
166 struct make_container_n;
168 // Specialization for non-associative types that have a constructor with
169 // a size argument.
170 template<typename _Tp>
171 struct make_container_n<_Tp, true>
172 : public make_container_base<_Tp>
174 make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
177 template<typename _Tp>
178 struct make_container_n<_Tp, false>
179 : public make_insert_container_base<_Tp>
181 make_container_n(const size_type n)
182 : make_insert_container_base<_Tp>(n) { }
186 // Randomly size and populate a given container reference.
187 // NB: Responsibility for turning off exceptions lies with caller.
188 template<typename _Tp, bool = traits<_Tp>::is_allocator_aware::value>
189 struct populate
191 typedef _Tp container_type;
192 typedef typename container_type::allocator_type allocator_type;
193 typedef typename container_type::value_type value_type;
195 populate(_Tp& __container)
197 const allocator_type a = __container.get_allocator();
199 // Size test container.
200 const size_type max_elements = 100;
201 size_type n = generate(max_elements);
203 // Construct new container.
204 make_container_n<container_type> made(n);
205 container_type& tmp = made;
206 std::swap(tmp, __container);
210 // Partial specialization, empty.
211 template<typename _Tp>
212 struct populate<_Tp, false>
214 populate(_Tp&) { }
217 // Compare two containers for equivalence.
218 // Right now, that means size.
219 // Returns true if equal, throws if not.
220 template<typename _Tp>
221 static bool
222 compare(const _Tp& __control, const _Tp& __test)
224 // Make sure test container is in a consistent state, as
225 // compared to the control container.
226 // NB: Should be equivalent to __test != __control, but
227 // computed without equivalence operators
228 const size_type szt
229 = std::distance(__test.begin(), __test.end());
230 const size_type szc
231 = std::distance(__control.begin(), __control.end());
233 if (szt != szc)
234 throw std::logic_error(
235 "setup_base::compare containers size not equal");
237 // Should test iterator validity before and after exception.
238 bool __equal_it = std::equal(__test.begin(), __test.end(),
239 __control.begin());
241 if (!__equal_it)
242 throw std::logic_error(
243 "setup_base::compare containers iterators not equal");
245 return true;
250 // Containing structure holding functors.
251 struct functor_base : public setup_base
253 // Abstract the erase function.
254 template<typename _Tp>
255 struct erase_base
257 typedef typename _Tp::iterator iterator;
258 typedef typename _Tp::const_iterator const_iterator;
260 iterator (_Tp::* _F_erase_point)(const_iterator);
261 iterator (_Tp::* _F_erase_range)(const_iterator, const_iterator);
263 erase_base()
264 : _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
267 #if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
268 // Specialization, old C++03 signature.
269 template<typename _Tp1, typename _Tp2, typename _Tp3>
270 struct erase_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
272 typedef std::basic_string<_Tp1, _Tp2, _Tp3> container_type;
273 typedef typename container_type::iterator iterator;
275 iterator (container_type::* _F_erase_point)(iterator);
276 iterator (container_type::* _F_erase_range)(iterator, iterator);
278 erase_base()
279 : _F_erase_point(&container_type::erase),
280 _F_erase_range(&container_type::erase) { }
283 template<typename _Tp1, typename _Tp2, typename _Tp3>
284 struct erase_base<__gnu_debug::basic_string<_Tp1, _Tp2, _Tp3>>
286 typedef __gnu_debug::basic_string<_Tp1, _Tp2, _Tp3> container_type;
287 typedef typename container_type::iterator iterator;
289 iterator (container_type::* _F_erase_point)(iterator);
290 iterator (container_type::* _F_erase_range)(iterator, iterator);
292 erase_base()
293 : _F_erase_point(&container_type::erase),
294 _F_erase_range(&container_type::erase) { }
296 #endif
298 // Specialization, as forward_list has erase_after.
299 template<typename _Tp1, typename _Tp2>
300 struct erase_base<std::forward_list<_Tp1, _Tp2>>
302 typedef std::forward_list<_Tp1, _Tp2> container_type;
303 typedef typename container_type::iterator iterator;
304 typedef typename container_type::const_iterator const_iterator;
306 iterator (container_type::* _F_erase_point)(const_iterator);
307 iterator (container_type::* _F_erase_range)(const_iterator,
308 const_iterator);
310 erase_base()
311 : _F_erase_point(&container_type::erase_after),
312 _F_erase_range(&container_type::erase_after) { }
315 template<typename _Tp,
316 bool = traits<_Tp>::has_erase::value,
317 bool = traits<_Tp>::has_erase_after::value>
318 struct erase_point;
320 // Specialization for most containers.
321 template<typename _Tp>
322 struct erase_point<_Tp, true, false> : public erase_base<_Tp>
324 using erase_base<_Tp>::_F_erase_point;
326 void
327 operator()(_Tp& __container)
331 // NB: Should be equivalent to size() member function, but
332 // computed with begin() and end().
333 const size_type sz = std::distance(__container.begin(),
334 __container.end());
335 // Container::erase(pos) requires dereferenceable pos.
336 if (sz == 0)
337 throw std::logic_error("erase_point: empty container");
339 // NB: Lowest common denominator: use forward iterator operations.
340 auto i = __container.begin();
341 std::advance(i, generate(sz - 1));
343 // Makes it easier to think of this as __container.erase(i)
344 (__container.*_F_erase_point)(i);
346 catch(const __gnu_cxx::forced_error&)
347 { throw; }
351 // Specialization for forward_list.
352 template<typename _Tp>
353 struct erase_point<_Tp, false, true> : public erase_base<_Tp>
355 using erase_base<_Tp>::_F_erase_point;
357 void
358 operator()(_Tp& __container)
362 // NB: Should be equivalent to size() member function, but
363 // computed with begin() and end().
364 const size_type sz = std::distance(__container.begin(),
365 __container.end());
366 // forward_list::erase_after(pos) requires dereferenceable pos.
367 if (sz == 0)
368 throw std::logic_error("erase_point: empty container");
370 // NB: Lowest common denominator: use forward iterator operations.
371 auto i = __container.before_begin();
372 std::advance(i, generate(sz - 1));
374 // Makes it easier to think of this as __container.erase_after(i)
375 (__container.*_F_erase_point)(i);
377 catch(const __gnu_cxx::forced_error&)
378 { throw; }
382 // Specialization, empty.
383 template<typename _Tp>
384 struct erase_point<_Tp, false, false>
386 void
387 operator()(_Tp&) { }
391 template<typename _Tp,
392 bool = traits<_Tp>::has_erase::value,
393 bool = traits<_Tp>::has_erase_after::value>
394 struct erase_range;
396 // Specialization for most containers.
397 template<typename _Tp>
398 struct erase_range<_Tp, true, false> : public erase_base<_Tp>
400 using erase_base<_Tp>::_F_erase_range;
402 void
403 operator()(_Tp& __container)
407 const size_type sz = std::distance(__container.begin(),
408 __container.end());
409 size_type s1 = generate(sz);
410 size_type s2 = generate(sz);
411 auto i1 = __container.begin();
412 auto i2 = __container.begin();
413 std::advance(i1, std::min(s1, s2));
414 std::advance(i2, std::max(s1, s2));
416 // Makes it easier to think of this as __container.erase(i1, i2).
417 (__container.*_F_erase_range)(i1, i2);
419 catch(const __gnu_cxx::forced_error&)
420 { throw; }
424 // Specialization for forward_list.
425 template<typename _Tp>
426 struct erase_range<_Tp, false, true> : public erase_base<_Tp>
428 using erase_base<_Tp>::_F_erase_range;
430 void
431 operator()(_Tp& __container)
435 const size_type sz = std::distance(__container.begin(),
436 __container.end());
437 // forward_list::erase_after(pos, last) requires a pos != last
438 if (sz == 0)
439 return; // Caller doesn't check for this, not a logic error.
441 size_type s1 = generate(sz - 1);
442 size_type s2 = generate(sz - 1);
443 auto i1 = __container.before_begin();
444 auto i2 = __container.before_begin();
445 std::advance(i1, std::min(s1, s2));
446 std::advance(i2, std::max(s1, s2) + 1);
448 // Makes it easier to think of this as
449 // __container.erase_after(i1, i2).
450 (__container.*_F_erase_range)(i1, i2);
452 catch(const __gnu_cxx::forced_error&)
453 { throw; }
457 // Specialization, empty.
458 template<typename _Tp>
459 struct erase_range<_Tp, false, false>
461 void
462 operator()(_Tp&) { }
466 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
467 struct pop_front
469 void
470 operator()(_Tp& __container)
474 __container.pop_front();
476 catch(const __gnu_cxx::forced_error&)
477 { throw; }
481 // Specialization, empty.
482 template<typename _Tp>
483 struct pop_front<_Tp, false>
485 void
486 operator()(_Tp&) { }
490 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
491 && traits<_Tp>::is_reversible::value>
492 struct pop_back
494 void
495 operator()(_Tp& __container)
499 __container.pop_back();
501 catch(const __gnu_cxx::forced_error&)
502 { throw; }
506 // Specialization, empty.
507 template<typename _Tp>
508 struct pop_back<_Tp, false>
510 void
511 operator()(_Tp&) { }
515 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
516 struct push_front
518 typedef _Tp container_type;
519 typedef typename container_type::value_type value_type;
521 void
522 operator()(_Tp& __test)
526 const value_type cv = generate_unique<value_type>();
527 __test.push_front(cv);
529 catch(const __gnu_cxx::forced_error&)
530 { throw; }
533 // Assumes containers start out equivalent.
534 void
535 operator()(_Tp& __control, _Tp& __test)
539 const value_type cv = generate_unique<value_type>();
540 __test.push_front(cv);
542 catch(const __gnu_cxx::forced_error&)
543 { throw; }
547 // Specialization, empty.
548 template<typename _Tp>
549 struct push_front<_Tp, false>
551 void
552 operator()(_Tp&) { }
554 void
555 operator()(_Tp&, _Tp&) { }
559 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
560 && traits<_Tp>::is_reversible::value>
561 struct push_back
563 typedef _Tp container_type;
564 typedef typename container_type::value_type value_type;
566 void
567 operator()(_Tp& __test)
571 const value_type cv = generate_unique<value_type>();
572 __test.push_back(cv);
574 catch(const __gnu_cxx::forced_error&)
575 { throw; }
578 // Assumes containers start out equivalent.
579 void
580 operator()(_Tp& __control, _Tp& __test)
584 const value_type cv = generate_unique<value_type>();
585 __test.push_back(cv);
587 catch(const __gnu_cxx::forced_error&)
588 { throw; }
592 // Specialization, empty.
593 template<typename _Tp>
594 struct push_back<_Tp, false>
596 void
597 operator()(_Tp&) { }
599 void
600 operator()(_Tp&, _Tp&) { }
603 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
604 && traits<_Tp>::has_emplace::value>
605 struct emplace_front
607 typedef _Tp container_type;
608 typedef typename container_type::value_type value_type;
610 void
611 operator()(_Tp& __test)
615 const value_type cv = generate_unique<value_type>();
616 __test.emplace_front(cv);
618 catch(const __gnu_cxx::forced_error&)
619 { throw; }
622 // Assumes containers start out equivalent.
623 void
624 operator()(_Tp& __control, _Tp& __test)
628 const value_type cv = generate_unique<value_type>();
629 __test.emplace_front(cv);
631 catch(const __gnu_cxx::forced_error&)
632 { throw; }
636 // Specialization, empty.
637 template<typename _Tp>
638 struct emplace_front<_Tp, false>
640 void
641 operator()(_Tp&) { }
643 void
644 operator()(_Tp&, _Tp&) { }
648 template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
649 && traits<_Tp>::has_emplace::value
650 && traits<_Tp>::is_reversible::value>
651 struct emplace_back
653 typedef _Tp container_type;
654 typedef typename container_type::value_type value_type;
656 void
657 operator()(_Tp& __test)
661 const value_type cv = generate_unique<value_type>();
662 __test.emplace_back(cv);
664 catch(const __gnu_cxx::forced_error&)
665 { throw; }
668 // Assumes containers start out equivalent.
669 void
670 operator()(_Tp& __control, _Tp& __test)
674 const value_type cv = generate_unique<value_type>();
675 __test.push_back(cv);
677 catch(const __gnu_cxx::forced_error&)
678 { throw; }
682 // Specialization, empty.
683 template<typename _Tp>
684 struct emplace_back<_Tp, false>
686 void
687 operator()(_Tp&) { }
689 void
690 operator()(_Tp&, _Tp&) { }
694 // Abstract the insert function into two parts:
695 // 1, insert_base_functions == holds function pointer
696 // 2, insert_base == links function pointer to class insert method
697 template<typename _Tp>
698 struct insert_base
700 typedef typename _Tp::iterator iterator;
701 typedef typename _Tp::const_iterator const_iterator;
702 typedef typename _Tp::value_type value_type;
704 iterator (_Tp::* _F_insert_point)(const_iterator, const value_type&);
706 insert_base() : _F_insert_point(&_Tp::insert) { }
709 // Specialization, old C++03 signature.
710 template<typename _Tp1, typename _Tp2, typename _Tp3>
711 struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
713 typedef std::basic_string<_Tp1, _Tp2, _Tp3> container_type;
714 typedef typename container_type::iterator iterator;
715 typedef typename container_type::const_iterator const_iterator;
716 typedef typename container_type::value_type value_type;
718 #if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
719 iterator (container_type::* _F_insert_point)(iterator, value_type);
720 #else
721 iterator (container_type::* _F_insert_point)(const_iterator,
722 value_type);
723 #endif
725 insert_base() : _F_insert_point(&container_type::insert) { }
728 template<typename _Tp1, typename _Tp2, typename _Tp3>
729 struct insert_base<__gnu_debug::basic_string<_Tp1, _Tp2, _Tp3>>
731 typedef __gnu_debug::basic_string<_Tp1, _Tp2, _Tp3> container_type;
732 typedef typename container_type::iterator iterator;
733 typedef typename container_type::const_iterator const_iterator;
734 typedef typename container_type::value_type value_type;
736 #if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
737 iterator (container_type::* _F_insert_point)(iterator, value_type);
738 #else
739 iterator (container_type::* _F_insert_point)(const_iterator,
740 value_type);
741 #endif
743 insert_base() : _F_insert_point(&container_type::insert) { }
746 // Specialization, by value.
747 template<typename _Tp1, typename _Tp2, typename _Tp3,
748 template <typename, typename, typename> class _Tp4>
749 struct insert_base<__gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>>
751 typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
752 container_type;
753 typedef typename container_type::iterator iterator;
754 typedef typename container_type::const_iterator const_iterator;
755 typedef typename container_type::value_type value_type;
757 iterator (container_type::* _F_insert_point)(const_iterator,
758 value_type);
760 insert_base() : _F_insert_point(&container_type::insert) { }
763 // Specialization, as forward_list has insert_after.
764 template<typename _Tp1, typename _Tp2>
765 struct insert_base<std::forward_list<_Tp1, _Tp2>>
767 typedef std::forward_list<_Tp1, _Tp2> container_type;
768 typedef typename container_type::iterator iterator;
769 typedef typename container_type::const_iterator const_iterator;
770 typedef typename container_type::value_type value_type;
772 iterator (container_type::* _F_insert_point)(const_iterator,
773 const value_type&);
775 insert_base() : _F_insert_point(&container_type::insert_after) { }
778 template<typename _Tp, bool = traits<_Tp>::has_insert::value,
779 bool = traits<_Tp>::has_insert_after::value>
780 struct insert_point;
782 // Specialization for most containers.
783 template<typename _Tp>
784 struct insert_point<_Tp, true, false> : public insert_base<_Tp>
786 typedef _Tp container_type;
787 typedef typename container_type::value_type value_type;
788 using insert_base<_Tp>::_F_insert_point;
790 void
791 operator()(_Tp& __test)
795 const value_type cv = generate_unique<value_type>();
796 const size_type sz = std::distance(__test.begin(), __test.end());
797 size_type s = generate(sz);
798 auto i = __test.begin();
799 std::advance(i, s);
800 (__test.*_F_insert_point)(i, cv);
802 catch(const __gnu_cxx::forced_error&)
803 { throw; }
806 // Assumes containers start out equivalent.
807 void
808 operator()(_Tp& __control, _Tp& __test)
812 const value_type cv = generate_unique<value_type>();
813 const size_type sz = std::distance(__test.begin(), __test.end());
814 size_type s = generate(sz);
815 auto i = __test.begin();
816 std::advance(i, s);
817 (__test.*_F_insert_point)(i, cv);
819 catch(const __gnu_cxx::forced_error&)
820 { throw; }
824 // Specialization for forward_list.
825 template<typename _Tp>
826 struct insert_point<_Tp, false, true> : public insert_base<_Tp>
828 typedef _Tp container_type;
829 typedef typename container_type::value_type value_type;
830 using insert_base<_Tp>::_F_insert_point;
832 void
833 operator()(_Tp& __test)
837 const value_type cv = generate_unique<value_type>();
838 const size_type sz = std::distance(__test.begin(), __test.end());
839 size_type s = generate(sz);
840 auto i = __test.before_begin();
841 std::advance(i, s);
842 (__test.*_F_insert_point)(i, cv);
844 catch(const __gnu_cxx::forced_error&)
845 { throw; }
848 // Assumes containers start out equivalent.
849 void
850 operator()(_Tp& __control, _Tp& __test)
854 const value_type cv = generate_unique<value_type>();
855 const size_type sz = std::distance(__test.begin(), __test.end());
856 size_type s = generate(sz);
857 auto i = __test.before_begin();
858 std::advance(i, s);
859 (__test.*_F_insert_point)(i, cv);
861 catch(const __gnu_cxx::forced_error&)
862 { throw; }
866 // Specialization, empty.
867 template<typename _Tp>
868 struct insert_point<_Tp, false, false>
870 void
871 operator()(_Tp&) { }
873 void
874 operator()(_Tp&, _Tp&) { }
877 template<typename _Tp, bool = traits<_Tp>::has_emplace::value
878 && (traits<_Tp>::is_associative::value
879 || traits<_Tp>::is_unordered::value)>
880 struct emplace;
882 // Specialization for associative and unordered containers.
883 template<typename _Tp>
884 struct emplace<_Tp, true>
886 typedef _Tp container_type;
887 typedef typename container_type::value_type value_type;
888 typedef typename container_type::size_type size_type;
890 void
891 operator()(_Tp& __test)
895 const value_type cv = generate_unique<value_type>();
896 __test.emplace(cv);
898 catch(const __gnu_cxx::forced_error&)
899 { throw; }
902 // Assumes containers start out equivalent.
903 void
904 operator()(_Tp& __control, _Tp& __test)
908 const value_type cv = generate_unique<value_type>();
909 __test.emplace(cv);
911 catch(const __gnu_cxx::forced_error&)
912 { throw; }
916 // Specialization, empty.
917 template<typename _Tp>
918 struct emplace<_Tp, false>
920 void
921 operator()(_Tp&) { }
923 void
924 operator()(_Tp&, _Tp&) { }
927 template<typename _Tp, bool = traits<_Tp>::has_emplace::value,
928 bool = traits<_Tp>::is_associative::value
929 || traits<_Tp>::is_unordered::value,
930 bool = traits<_Tp>::has_insert_after::value>
931 struct emplace_point;
933 // Specialization for most containers.
934 template<typename _Tp>
935 struct emplace_point<_Tp, true, false, false>
937 typedef _Tp container_type;
938 typedef typename container_type::value_type value_type;
940 void
941 operator()(_Tp& __test)
945 const value_type cv = generate_unique<value_type>();
946 const size_type sz = std::distance(__test.begin(), __test.end());
947 size_type s = generate(sz);
948 auto i = __test.begin();
949 std::advance(i, s);
950 __test.emplace(i, cv);
952 catch(const __gnu_cxx::forced_error&)
953 { throw; }
956 // Assumes containers start out equivalent.
957 void
958 operator()(_Tp& __control, _Tp& __test)
962 const value_type cv = generate_unique<value_type>();
963 const size_type sz = std::distance(__test.begin(), __test.end());
964 size_type s = generate(sz);
965 auto i = __test.begin();
966 std::advance(i, s);
967 __test.emplace(i, cv);
969 catch(const __gnu_cxx::forced_error&)
970 { throw; }
974 // Specialization for associative and unordered containers.
975 template<typename _Tp>
976 struct emplace_point<_Tp, true, true, false>
978 typedef _Tp container_type;
979 typedef typename container_type::value_type value_type;
981 void
982 operator()(_Tp& __test)
986 const value_type cv = generate_unique<value_type>();
987 const size_type sz = std::distance(__test.begin(), __test.end());
988 size_type s = generate(sz);
989 auto i = __test.begin();
990 std::advance(i, s);
991 __test.emplace_hint(i, cv);
993 catch(const __gnu_cxx::forced_error&)
994 { throw; }
997 // Assumes containers start out equivalent.
998 void
999 operator()(_Tp& __control, _Tp& __test)
1003 const value_type cv = generate_unique<value_type>();
1004 const size_type sz = std::distance(__test.begin(), __test.end());
1005 size_type s = generate(sz);
1006 auto i = __test.begin();
1007 std::advance(i, s);
1008 __test.emplace_hint(i, cv);
1010 catch(const __gnu_cxx::forced_error&)
1011 { throw; }
1015 // Specialization for forward_list.
1016 template<typename _Tp>
1017 struct emplace_point<_Tp, true, false, true>
1019 typedef _Tp container_type;
1020 typedef typename container_type::value_type value_type;
1022 void
1023 operator()(_Tp& __test)
1027 const value_type cv = generate_unique<value_type>();
1028 const size_type sz = std::distance(__test.begin(), __test.end());
1029 size_type s = generate(sz);
1030 auto i = __test.before_begin();
1031 std::advance(i, s);
1032 __test.emplace_after(i, cv);
1034 catch(const __gnu_cxx::forced_error&)
1035 { throw; }
1038 // Assumes containers start out equivalent.
1039 void
1040 operator()(_Tp& __control, _Tp& __test)
1044 const value_type cv = generate_unique<value_type>();
1045 const size_type sz = std::distance(__test.begin(), __test.end());
1046 size_type s = generate(sz);
1047 auto i = __test.before_begin();
1048 std::advance(i, s);
1049 __test.emplace_after(i, cv);
1051 catch(const __gnu_cxx::forced_error&)
1052 { throw; }
1056 // Specialization, empty.
1057 template<typename _Tp, bool is_associative_or_unordered,
1058 bool has_insert_after>
1059 struct emplace_point<_Tp, false, is_associative_or_unordered,
1060 has_insert_after>
1062 void
1063 operator()(_Tp&) { }
1065 void
1066 operator()(_Tp&, _Tp&) { }
1069 template<typename _Tp, bool = traits<_Tp>::is_associative::value
1070 || traits<_Tp>::is_unordered::value>
1071 struct clear
1073 void
1074 operator()(_Tp& __container)
1078 __container.clear();
1080 catch(const __gnu_cxx::forced_error&)
1081 { throw; }
1085 // Specialization, empty.
1086 template<typename _Tp>
1087 struct clear<_Tp, false>
1089 void
1090 operator()(_Tp&) { }
1094 template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
1095 struct rehash
1097 void
1098 operator()(_Tp& __test)
1102 size_type s = generate(__test.bucket_count());
1103 __test.rehash(s);
1105 catch(const __gnu_cxx::forced_error&)
1106 { throw; }
1109 void
1110 operator()(_Tp& __control, _Tp& __test)
1114 size_type s = generate(__test.bucket_count());
1115 __test.rehash(s);
1117 catch(const __gnu_cxx::forced_error&)
1119 // Also check hash status.
1120 bool fail(false);
1121 if (__control.load_factor() != __test.load_factor())
1122 fail = true;
1123 if (__control.max_load_factor() != __test.max_load_factor())
1124 fail = true;
1125 if (__control.bucket_count() != __test.bucket_count())
1126 fail = true;
1127 if (__control.max_bucket_count() != __test.max_bucket_count())
1128 fail = true;
1130 if (fail)
1132 char buf[40];
1133 std::string __s("setup_base::rehash "
1134 "containers not equal");
1135 __s += "\n";
1136 __s += "\n";
1137 __s += "\t\t\tcontrol : test";
1138 __s += "\n";
1139 __s += "load_factor\t\t";
1140 __builtin_sprintf(buf, "%lu", __control.load_factor());
1141 __s += buf;
1142 __s += " : ";
1143 __builtin_sprintf(buf, "%lu", __test.load_factor());
1144 __s += buf;
1145 __s += "\n";
1147 __s += "max_load_factor\t\t";
1148 __builtin_sprintf(buf, "%lu", __control.max_load_factor());
1149 __s += buf;
1150 __s += " : ";
1151 __builtin_sprintf(buf, "%lu", __test.max_load_factor());
1152 __s += buf;
1153 __s += "\n";
1155 __s += "bucket_count\t\t";
1156 __builtin_sprintf(buf, "%lu", __control.bucket_count());
1157 __s += buf;
1158 __s += " : ";
1159 __builtin_sprintf(buf, "%lu", __test.bucket_count());
1160 __s += buf;
1161 __s += "\n";
1163 __s += "max_bucket_count\t";
1164 __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
1165 __s += buf;
1166 __s += " : ";
1167 __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
1168 __s += buf;
1169 __s += "\n";
1171 std::__throw_logic_error(__s.c_str());
1177 // Specialization, empty.
1178 template<typename _Tp>
1179 struct rehash<_Tp, false>
1181 void
1182 operator()(_Tp&) { }
1184 void
1185 operator()(_Tp&, _Tp&) { }
1189 template<typename _Tp>
1190 struct swap
1192 _Tp _M_other;
1194 void
1195 operator()(_Tp& __container)
1199 __container.swap(_M_other);
1201 catch(const __gnu_cxx::forced_error&)
1202 { throw; }
1207 template<typename _Tp>
1208 struct iterator_operations
1210 typedef _Tp container_type;
1211 typedef typename container_type::iterator iterator;
1213 void
1214 operator()(_Tp& __container)
1218 // Any will do.
1219 iterator i = __container.begin();
1220 iterator __attribute__((unused)) icopy(i);
1221 iterator __attribute__((unused)) iassign = i;
1223 catch(const __gnu_cxx::forced_error&)
1224 { throw; }
1229 template<typename _Tp>
1230 struct const_iterator_operations
1232 typedef _Tp container_type;
1233 typedef typename container_type::const_iterator const_iterator;
1235 void
1236 operator()(_Tp& __container)
1240 // Any will do.
1241 const_iterator i = __container.begin();
1242 const_iterator __attribute__((unused)) icopy(i);
1243 const_iterator __attribute__((unused)) iassign = i;
1245 catch(const __gnu_cxx::forced_error&)
1246 { throw; }
1250 template<typename _Tp>
1251 struct assign_operator
1253 _Tp _M_other;
1255 void
1256 operator()(_Tp& __container)
1260 // An exception while assigning might leave the container empty
1261 // making future attempts less relevant. So we copy it before to
1262 // always assign to a non empty container. It also check for copy
1263 // constructor exception safety at the same time.
1264 _Tp __clone(__container);
1265 __clone = _M_other;
1267 catch(const __gnu_cxx::forced_error&)
1268 { throw; }
1273 #if __cplusplus >= 201103L
1274 template<typename _Tp>
1275 struct move_assign_operator
1277 _Tp _M_other;
1279 void
1280 operator()(_Tp& __container)
1284 __container = std::move(_M_other);
1286 catch(const __gnu_cxx::forced_error&)
1287 { throw; }
1290 #endif
1293 // Base class for exception tests.
1294 template<typename _Tp>
1295 struct test_base: public functor_base
1297 typedef _Tp container_type;
1299 typedef functor_base base_type;
1300 typedef populate<container_type> populate;
1301 typedef make_container_n<container_type> make_container_n;
1303 typedef clear<container_type> clear;
1304 typedef erase_point<container_type> erase_point;
1305 typedef erase_range<container_type> erase_range;
1306 typedef insert_point<container_type> insert_point;
1307 typedef emplace<container_type> emplace;
1308 typedef emplace_point<container_type> emplace_point;
1309 typedef emplace_front<container_type> emplace_front;
1310 typedef emplace_back<container_type> emplace_back;
1311 typedef pop_front<container_type> pop_front;
1312 typedef pop_back<container_type> pop_back;
1313 typedef push_front<container_type> push_front;
1314 typedef push_back<container_type> push_back;
1315 typedef rehash<container_type> rehash;
1316 typedef swap<container_type> swap;
1317 typedef iterator_operations<container_type> iterator_ops;
1318 typedef const_iterator_operations<container_type> const_iterator_ops;
1319 typedef assign_operator<container_type> assign_operator;
1320 #if __cplusplus >= 201103L
1321 typedef move_assign_operator<container_type> move_assign_operator;
1322 #endif
1324 using base_type::compare;
1328 // Run through all member functions for basic exception safety
1329 // guarantee: no resource leaks when exceptions are thrown.
1331 // Types of resources checked: memory.
1333 // For each member function, use throw_value and throw_allocator as
1334 // value_type and allocator_type to force potential exception safety
1335 // errors.
1337 // NB: Assumes
1338 // _Tp::value_type is __gnu_cxx::throw_value_*
1339 // _Tp::allocator_type is __gnu_cxx::throw_allocator_*
1340 // And that the _Cond template parameter for them both is
1341 // __gnu_cxx::limit_condition.
1342 template<typename _Tp>
1343 struct basic_safety : public test_base<_Tp>
1345 typedef _Tp container_type;
1346 typedef test_base<container_type> base_type;
1347 typedef typename base_type::populate populate;
1348 typedef std::function<void(container_type&)> function_type;
1349 typedef __gnu_cxx::limit_condition condition_type;
1351 using base_type::generate;
1353 basic_safety() { run(); }
1355 void
1356 run()
1359 // Setup.
1360 condition_type::never_adjustor off;
1362 // Construct containers.
1363 container_type container;
1364 populate p1(container);
1366 // Construct list of member functions to exercise.
1367 std::vector<function_type> functions;
1368 typename base_type::iterator_ops iops;
1369 functions.push_back(function_type(iops));
1370 typename base_type::const_iterator_ops ciops;
1371 functions.push_back(function_type(ciops));
1373 typename base_type::erase_point erasep;
1374 functions.push_back(function_type(erasep));
1375 typename base_type::erase_range eraser;
1376 functions.push_back(function_type(eraser));
1377 typename base_type::insert_point insertp;
1378 functions.push_back(function_type(insertp));
1379 typename base_type::emplace emplace;
1380 functions.push_back(function_type(emplace));
1381 typename base_type::emplace_point emplacep;
1382 functions.push_back(function_type(emplacep));
1383 typename base_type::emplace_front emplacef;
1384 functions.push_back(function_type(emplacef));
1385 typename base_type::emplace_back emplaceb;
1386 functions.push_back(function_type(emplaceb));
1387 typename base_type::pop_front popf;
1388 functions.push_back(function_type(popf));
1389 typename base_type::pop_back popb;
1390 functions.push_back(function_type(popb));
1391 typename base_type::push_front pushf;
1392 functions.push_back(function_type(pushf));
1393 typename base_type::push_back pushb;
1394 functions.push_back(function_type(pushb));
1395 typename base_type::rehash rehash;
1396 functions.push_back(function_type(rehash));
1397 typename base_type::swap swap;
1398 populate p2(swap._M_other);
1399 functions.push_back(function_type(swap));
1400 typename base_type::assign_operator assignop;
1401 populate p3(assignop._M_other);
1402 functions.push_back(function_type(assignop));
1403 #if __cplusplus >= 201103L
1404 typename base_type::move_assign_operator massignop;
1405 populate p4(massignop._M_other);
1406 functions.push_back(function_type(massignop));
1407 #endif
1408 // Last.
1409 typename base_type::clear clear;
1410 functions.push_back(function_type(clear));
1412 // Run tests.
1413 size_t i(1);
1414 for (auto it = functions.begin(); it != functions.end(); ++it)
1416 function_type& f = *it;
1417 i = run_steps_to_limit(i, container, f);
1421 // Now that all instances has been destroyed check that there is no
1422 // allocation remaining.
1423 std::cout << "Checking remaining stuff" << std::endl;
1424 __gnu_cxx::annotate_base::check();
1427 template<typename _Funct>
1428 size_t
1429 run_steps_to_limit(size_t __step, container_type& __cont,
1430 const _Funct& __f)
1432 bool exit(false);
1433 auto a = __cont.get_allocator();
1437 // Use the current step as an allocator label.
1438 a.set_label(__step);
1442 condition_type::limit_adjustor limit(__step);
1443 __f(__cont);
1445 // If we get here, done.
1446 exit = true;
1448 catch(const __gnu_cxx::forced_error&)
1450 // Check this step for allocations.
1451 // NB: Will throw std::logic_error if allocations.
1452 a.check(__step);
1454 // Check memory allocated with operator new.
1457 ++__step;
1459 while (!exit);
1461 // Log count info.
1462 #if __cpp_rtti
1463 std::cout << __f.target_type().name() << std::endl;
1464 #else
1465 std::cout << "[no type info - rtti disabled]\n";
1466 #endif
1467 std::cout << "end count " << __step << std::endl;
1468 return __step;
1473 // Run through all member functions with a no throw requirement, sudden death.
1474 // all: member functions erase, pop_back, pop_front, swap
1475 // iterator copy ctor, assignment operator
1476 // unordered and associative: clear
1477 // NB: Assumes _Tp::allocator_type is __gnu_cxx::throw_allocator_random.
1478 template<typename _Tp>
1479 struct generation_prohibited : public test_base<_Tp>
1481 typedef _Tp container_type;
1482 typedef test_base<container_type> base_type;
1483 typedef typename base_type::populate populate;
1484 typedef __gnu_cxx::random_condition condition_type;
1486 generation_prohibited() { run(); }
1488 void
1489 run()
1491 // Furthermore, assumes that the test functor will throw
1492 // forced_exception via throw_allocator, that all errors are
1493 // propagated and in error. Sudden death!
1495 // Setup.
1496 container_type container;
1497 typename base_type::swap swap;
1500 condition_type::never_adjustor off;
1501 populate p1(container);
1502 populate p2(swap._M_other);
1505 // Run tests.
1507 condition_type::always_adjustor on;
1509 // NB: Vector and deque are special, erase can throw if the copy
1510 // constructor or assignment operator of value_type throws.
1511 if (!traits<container_type>::has_throwing_erase::value)
1513 if (!container.empty())
1515 typename base_type::erase_point erasep;
1516 erasep(container);
1518 typename base_type::erase_range eraser;
1519 eraser(container);
1522 if (!container.empty())
1524 typename base_type::pop_front popf;
1525 popf(container);
1527 if (!container.empty())
1529 typename base_type::pop_back popb;
1530 popb(container);
1533 typename base_type::iterator_ops iops;
1534 iops(container);
1535 typename base_type::const_iterator_ops ciops;
1536 ciops(container);
1538 swap(container);
1540 // Last.
1541 typename base_type::clear clear;
1542 clear(container);
1548 // Test strong exception guarantee.
1549 // Run through all member functions with a roll-back, consistent
1550 // coherent requirement.
1551 // all: member functions insert and emplace of a single element, push_back,
1552 // push_front
1553 // unordered: rehash
1554 template<typename _Tp>
1555 struct propagation_consistent : public test_base<_Tp>
1557 typedef _Tp container_type;
1558 typedef test_base<container_type> base_type;
1559 typedef typename base_type::populate populate;
1560 typedef std::function<void(container_type&)> function_type;
1561 typedef __gnu_cxx::limit_condition condition_type;
1563 using base_type::compare;
1565 propagation_consistent() { run(); }
1567 // Run test.
1568 void
1569 run()
1571 // Setup.
1572 condition_type::never_adjustor off;
1574 // Construct containers.
1575 container_type container_control;
1577 populate p(container_control);
1579 // Construct list of member functions to exercise.
1580 std::vector<function_type> functions;
1581 typename base_type::emplace emplace;
1582 functions.push_back(function_type(emplace));
1583 typename base_type::emplace_point emplacep;
1584 functions.push_back(function_type(emplacep));
1585 typename base_type::emplace_front emplacef;
1586 functions.push_back(function_type(emplacef));
1587 typename base_type::emplace_back emplaceb;
1588 functions.push_back(function_type(emplaceb));
1589 typename base_type::push_front pushf;
1590 functions.push_back(function_type(pushf));
1591 typename base_type::push_back pushb;
1592 functions.push_back(function_type(pushb));
1593 typename base_type::insert_point insertp;
1594 functions.push_back(function_type(insertp));
1595 typename base_type::rehash rehash;
1596 functions.push_back(function_type(rehash));
1598 // Run tests.
1599 for (auto i = functions.begin(); i != functions.end(); ++i)
1601 function_type& f = *i;
1602 run_steps_to_limit(container_control, f);
1606 template<typename _Funct>
1607 void
1608 run_steps_to_limit(container_type& container_control, const _Funct& __f)
1610 size_t i(1);
1611 bool exit(false);
1615 container_type container_test(container_control);
1619 condition_type::limit_adjustor limit(i);
1620 __f(container_test);
1622 // If we get here, done.
1623 exit = true;
1625 catch(const __gnu_cxx::forced_error&)
1627 compare(container_control, container_test);
1628 ++i;
1631 while (!exit);
1633 // Log count info.
1634 #if __cpp_rtti
1635 std::cout << __f.target_type().name() << std::endl;
1636 #else
1637 std::cout << "[no type info - rtti disabled]\n";
1638 #endif
1639 std::cout << "end count " << i << std::endl;
1643 } // namespace __gnu_test
1645 #endif