1// -*- C++ -*-
2
3// Copyright (C) 2009-2015 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.
10
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.
15
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/>.
19
20#ifndef _GLIBCXX_EXCEPTION_SAFETY_H
21#define _GLIBCXX_EXCEPTION_SAFETY_H
22
23#include <testsuite_container_traits.h>
24#include <ext/throw_allocator.h>
25
26// Container requirement testing.
27namespace __gnu_test
28{
29  // Base class for exception testing, contains utilities.
30  struct setup_base
31  {
32    typedef std::size_t 				size_type;
33    typedef std::uniform_int_distribution<size_type> 	distribution_type;
34    typedef std::mt19937 				engine_type;
35
36    // Return randomly generated integer on range [0, __max_size].
37    static size_type
38    generate(size_type __max_size)
39    {
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);
45
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"),
53				      (size_t)random,
54				      (size_t)distribution.min(),
55				      (size_t)distribution.max());
56      return random;
57    }
58
59    // Given an instantiating type, return a unique value.
60    template<typename _Tp>
61      struct generate_unique
62      {
63	typedef _Tp value_type;
64
65	operator value_type()
66	{
67	  static value_type __ret;
68	  ++__ret;
69	  return __ret;
70	}
71      };
72
73    // Partial specialization for pair.
74    template<typename _Tp1, typename _Tp2>
75      struct generate_unique<std::pair<const _Tp1, _Tp2>>
76      {
77	typedef _Tp1 first_type;
78	typedef _Tp2 second_type;
79	typedef std::pair<const _Tp1, _Tp2> pair_type;
80
81	operator pair_type()
82	{
83	  static first_type _S_1;
84	  static second_type _S_2;
85	  ++_S_1;
86	  ++_S_2;
87	  return pair_type(_S_1, _S_2);
88	}
89      };
90
91    // Partial specialization for throw_value
92    template<typename _Cond>
93      struct generate_unique<__gnu_cxx::throw_value_base<_Cond>>
94      {
95	typedef __gnu_cxx::throw_value_base<_Cond> value_type;
96
97	operator value_type()
98	{
99	  static size_t _S_i(0);
100	  return value_type(_S_i++);
101	}
102      };
103
104
105    // Construct container of size n directly. _Tp == container type.
106    template<typename _Tp>
107      struct make_container_base
108      {
109	_Tp _M_container;
110
111	make_container_base() = default;
112	make_container_base(const size_type n): _M_container(n) { }
113
114	operator _Tp&() { return _M_container; }
115      };
116
117    // Construct container of size n, via multiple insertions. For
118    // associated and unordered types, unique value_type elements are
119    // necessary.
120    template<typename _Tp, bool = traits<_Tp>::is_mapped::value>
121      struct make_insert_container_base
122      : public make_container_base<_Tp>
123      {
124	using make_container_base<_Tp>::_M_container;
125	typedef typename _Tp::value_type value_type;
126
127	make_insert_container_base(const size_type n)
128	{
129	  for (size_type i = 0; i < n; ++i)
130	    {
131	      value_type v = generate_unique<value_type>();
132	      _M_container.insert(v);
133	    }
134	  assert(_M_container.size() == n);
135	}
136      };
137
138    template<typename _Tp>
139      struct make_insert_container_base<_Tp, false>
140      : public make_container_base<_Tp>
141      {
142	using make_container_base<_Tp>::_M_container;
143	typedef typename _Tp::value_type value_type;
144
145	make_insert_container_base(const size_type n)
146	{
147	  for (size_type i = 0; i < n; ++i)
148	    {
149	      value_type v = generate_unique<value_type>();
150	      _M_container.insert(_M_container.end(), v);
151	    }
152	  assert(_M_container.size() == n);
153	}
154      };
155
156    template<typename _Tp, bool = traits<_Tp>::has_size_type_constructor::value>
157      struct make_container_n;
158
159    // Specialization for non-associative types that have a constructor with
160    // a size argument.
161    template<typename _Tp>
162      struct make_container_n<_Tp, true>
163      : public make_container_base<_Tp>
164      {
165	make_container_n(const size_type n) : make_container_base<_Tp>(n) { }
166      };
167
168    template<typename _Tp>
169      struct make_container_n<_Tp, false>
170      : public make_insert_container_base<_Tp>
171      {
172	make_container_n(const size_type n)
173	: make_insert_container_base<_Tp>(n) { }
174      };
175
176
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>
180      struct populate
181      {
182	typedef _Tp 					container_type;
183	typedef typename container_type::allocator_type	allocator_type;
184	typedef typename container_type::value_type    	value_type;
185
186	populate(_Tp& __container)
187	{
188	  const allocator_type a = __container.get_allocator();
189
190	  // Size test container.
191	  const size_type max_elements = 100;
192	  size_type n = generate(max_elements);
193
194	  // Construct new container.
195	  make_container_n<container_type> made(n);
196	  container_type& tmp = made;
197	  std::swap(tmp, __container);
198	}
199      };
200
201    // Partial specialization, empty.
202    template<typename _Tp>
203      struct populate<_Tp, false>
204      {
205	populate(_Tp&) { }
206      };
207
208    // Compare two containers for equivalence.
209    // Right now, that means size.
210    // Returns true if equal, throws if not.
211    template<typename _Tp>
212      static bool
213      compare(const _Tp& __control, const _Tp& __test)
214      {
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
219	const size_type szt
220	  = std::distance(__test.begin(), __test.end());
221	const size_type szc
222	  = std::distance(__control.begin(), __control.end());
223
224	if (szt != szc)
225	  throw std::logic_error(
226		"setup_base::compare containers size not equal");
227
228	// Should test iterator validity before and after exception.
229	bool __equal_it = std::equal(__test.begin(), __test.end(),
230				     __control.begin());
231
232	if (!__equal_it)
233	  throw std::logic_error(
234		"setup_base::compare containers iterators not equal");
235
236	return true;
237      }
238  };
239
240
241  // Containing structure holding functors.
242  struct functor_base : public setup_base
243  {
244    // Abstract the erase function.
245    template<typename _Tp>
246      struct erase_base
247      {
248	typedef typename _Tp::iterator 			iterator;
249	typedef typename _Tp::const_iterator		const_iterator;
250
251	iterator (_Tp::* _F_erase_point)(const_iterator);
252	iterator (_Tp::* _F_erase_range)(const_iterator, const_iterator);
253
254	erase_base()
255	: _F_erase_point(&_Tp::erase), _F_erase_range(&_Tp::erase) { }
256      };
257
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>>
262      {
263	typedef std::basic_string<_Tp1, _Tp2, _Tp3>     container_type;
264	typedef typename container_type::iterator 	iterator;
265
266	iterator (container_type::* _F_erase_point)(iterator);
267	iterator (container_type::* _F_erase_range)(iterator, iterator);
268
269	erase_base()
270	: _F_erase_point(&container_type::erase),
271	  _F_erase_range(&container_type::erase) { }
272      };
273#endif
274
275    // Specialization, as forward_list has erase_after.
276    template<typename _Tp1, typename _Tp2>
277      struct erase_base<std::forward_list<_Tp1, _Tp2>>
278      {
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;
282
283	iterator (container_type::* _F_erase_point)(const_iterator);
284	iterator (container_type::* _F_erase_range)(const_iterator,
285						    const_iterator);
286
287	erase_base()
288	: _F_erase_point(&container_type::erase_after),
289	  _F_erase_range(&container_type::erase_after) { }
290      };
291
292    template<typename _Tp,
293	     bool = traits<_Tp>::has_erase::value,
294	     bool = traits<_Tp>::has_erase_after::value>
295      struct erase_point;
296
297    // Specialization for most containers.
298    template<typename _Tp>
299      struct erase_point<_Tp, true, false> : public erase_base<_Tp>
300      {
301	using erase_base<_Tp>::_F_erase_point;
302
303	void
304	operator()(_Tp& __container)
305	{
306	  try
307	    {
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(),
311						 __container.end());
312
313	      // NB: Lowest common denominator: use forward iterator operations.
314	      auto i = __container.begin();
315	      std::advance(i, generate(sz));
316
317	      // Makes it easier to think of this as __container.erase(i)
318	      (__container.*_F_erase_point)(i);
319	    }
320	  catch(const __gnu_cxx::forced_error&)
321	    { throw; }
322	}
323      };
324
325    // Specialization for forward_list.
326    template<typename _Tp>
327      struct erase_point<_Tp, false, true> : public erase_base<_Tp>
328      {
329	using erase_base<_Tp>::_F_erase_point;
330
331	void
332	operator()(_Tp& __container)
333	{
334	  try
335	    {
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(),
339						 __container.end());
340
341	      // NB: Lowest common denominator: use forward iterator operations.
342	      auto i = __container.before_begin();
343	      std::advance(i, generate(sz));
344
345	      // Makes it easier to think of this as __container.erase(i)
346	      (__container.*_F_erase_point)(i);
347	    }
348	  catch(const __gnu_cxx::forced_error&)
349	    { throw; }
350	}
351      };
352
353    // Specialization, empty.
354    template<typename _Tp>
355      struct erase_point<_Tp, false, false>
356      {
357	void
358	operator()(_Tp&) { }
359      };
360
361
362    template<typename _Tp,
363	     bool = traits<_Tp>::has_erase::value,
364	     bool = traits<_Tp>::has_erase_after::value>
365      struct erase_range;
366
367    // Specialization for most containers.
368    template<typename _Tp>
369      struct erase_range<_Tp, true, false> : public erase_base<_Tp>
370      {
371	using erase_base<_Tp>::_F_erase_range;
372
373	void
374	operator()(_Tp& __container)
375	{
376	  try
377	    {
378	      const size_type sz = std::distance(__container.begin(),
379						 __container.end());
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));
386
387	      // Makes it easier to think of this as __container.erase(i1, i2).
388	      (__container.*_F_erase_range)(i1, i2);
389	    }
390	  catch(const __gnu_cxx::forced_error&)
391	    { throw; }
392	}
393      };
394
395    // Specialization for forward_list.
396    template<typename _Tp>
397      struct erase_range<_Tp, false, true> : public erase_base<_Tp>
398      {
399	using erase_base<_Tp>::_F_erase_range;
400
401	void
402	operator()(_Tp& __container)
403	{
404	  try
405	    {
406	      const size_type sz = std::distance(__container.begin(),
407						 __container.end());
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));
414
415	      // Makes it easier to think of this as __container.erase(i1, i2).
416	      (__container.*_F_erase_range)(i1, i2);
417	    }
418	  catch(const __gnu_cxx::forced_error&)
419	    { throw; }
420	}
421      };
422
423    // Specialization, empty.
424    template<typename _Tp>
425      struct erase_range<_Tp, false, false>
426      {
427	void
428	operator()(_Tp&) { }
429      };
430
431
432    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
433      struct pop_front
434      {
435	void
436	operator()(_Tp& __container)
437	{
438	  try
439	    {
440	      __container.pop_front();
441	    }
442	  catch(const __gnu_cxx::forced_error&)
443	    { throw; }
444	}
445      };
446
447    // Specialization, empty.
448    template<typename _Tp>
449      struct pop_front<_Tp, false>
450      {
451	void
452	operator()(_Tp&) { }
453      };
454
455
456    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
457				  && traits<_Tp>::is_reversible::value>
458      struct pop_back
459      {
460	void
461	operator()(_Tp& __container)
462	{
463	  try
464	    {
465	      __container.pop_back();
466	    }
467	  catch(const __gnu_cxx::forced_error&)
468	    { throw; }
469	}
470      };
471
472    // Specialization, empty.
473    template<typename _Tp>
474      struct pop_back<_Tp, false>
475      {
476	void
477	operator()(_Tp&) { }
478      };
479
480
481    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value>
482      struct push_front
483      {
484	typedef _Tp 					container_type;
485	typedef typename container_type::value_type    	value_type;
486
487	void
488	operator()(_Tp& __test)
489	{
490	  try
491	    {
492	      const value_type cv = generate_unique<value_type>();
493	      __test.push_front(cv);
494	    }
495	  catch(const __gnu_cxx::forced_error&)
496	    { throw; }
497	}
498
499	// Assumes containers start out equivalent.
500	void
501	operator()(_Tp& __control, _Tp& __test)
502	{
503	  try
504	    {
505	      const value_type cv = generate_unique<value_type>();
506	      __test.push_front(cv);
507	    }
508	  catch(const __gnu_cxx::forced_error&)
509	    { throw; }
510	}
511    };
512
513    // Specialization, empty.
514    template<typename _Tp>
515      struct push_front<_Tp, false>
516      {
517	void
518	operator()(_Tp&) { }
519
520	void
521	operator()(_Tp&, _Tp&) { }
522      };
523
524
525    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
526				  && traits<_Tp>::is_reversible::value>
527      struct push_back
528      {
529	typedef _Tp 					container_type;
530	typedef typename container_type::value_type    	value_type;
531
532	void
533	operator()(_Tp& __test)
534	{
535	  try
536	    {
537	      const value_type cv = generate_unique<value_type>();
538	      __test.push_back(cv);
539	    }
540	  catch(const __gnu_cxx::forced_error&)
541	    { throw; }
542	}
543
544	// Assumes containers start out equivalent.
545	void
546	operator()(_Tp& __control, _Tp& __test)
547	{
548	  try
549	    {
550	      const value_type cv = generate_unique<value_type>();
551	      __test.push_back(cv);
552	    }
553	  catch(const __gnu_cxx::forced_error&)
554	    { throw; }
555	}
556    };
557
558    // Specialization, empty.
559    template<typename _Tp>
560      struct push_back<_Tp, false>
561      {
562	void
563	operator()(_Tp&) { }
564
565	void
566	operator()(_Tp&, _Tp&) { }
567      };
568
569    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
570				  && traits<_Tp>::has_emplace::value>
571      struct emplace_front
572      {
573	typedef _Tp 					container_type;
574	typedef typename container_type::value_type    	value_type;
575
576	void
577	operator()(_Tp& __test)
578	{
579	  try
580	    {
581	      const value_type cv = generate_unique<value_type>();
582	      __test.emplace_front(cv);
583	    }
584	  catch(const __gnu_cxx::forced_error&)
585	    { throw; }
586	}
587
588	// Assumes containers start out equivalent.
589	void
590	operator()(_Tp& __control, _Tp& __test)
591	{
592	  try
593	    {
594	      const value_type cv = generate_unique<value_type>();
595	      __test.emplace_front(cv);
596	    }
597	  catch(const __gnu_cxx::forced_error&)
598	    { throw; }
599	}
600    };
601
602    // Specialization, empty.
603    template<typename _Tp>
604      struct emplace_front<_Tp, false>
605      {
606	void
607	operator()(_Tp&) { }
608
609	void
610	operator()(_Tp&, _Tp&) { }
611      };
612
613
614    template<typename _Tp, bool = traits<_Tp>::has_push_pop::value
615				  && traits<_Tp>::has_emplace::value
616				  && traits<_Tp>::is_reversible::value>
617      struct emplace_back
618      {
619	typedef _Tp 					container_type;
620	typedef typename container_type::value_type    	value_type;
621
622	void
623	operator()(_Tp& __test)
624	{
625	  try
626	    {
627	      const value_type cv = generate_unique<value_type>();
628	      __test.emplace_back(cv);
629	    }
630	  catch(const __gnu_cxx::forced_error&)
631	    { throw; }
632	}
633
634	// Assumes containers start out equivalent.
635	void
636	operator()(_Tp& __control, _Tp& __test)
637	{
638	  try
639	    {
640	      const value_type cv = generate_unique<value_type>();
641	      __test.push_back(cv);
642	    }
643	  catch(const __gnu_cxx::forced_error&)
644	    { throw; }
645	}
646    };
647
648    // Specialization, empty.
649    template<typename _Tp>
650      struct emplace_back<_Tp, false>
651      {
652	void
653	operator()(_Tp&) { }
654
655	void
656	operator()(_Tp&, _Tp&) { }
657      };
658
659
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>
664      struct insert_base
665      {
666	typedef typename _Tp::iterator 			iterator;
667	typedef typename _Tp::const_iterator    	const_iterator;
668	typedef typename _Tp::value_type 		value_type;
669
670	iterator (_Tp::* _F_insert_point)(const_iterator, const value_type&);
671
672	insert_base() : _F_insert_point(&_Tp::insert) { }
673      };
674
675    // Specialization, old C++03 signature.
676    template<typename _Tp1, typename _Tp2, typename _Tp3>
677      struct insert_base<std::basic_string<_Tp1, _Tp2, _Tp3>>
678      {
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;
683
684#if _GLIBCXX_USE_CXX11_ABI == 0 || __cplusplus < 201103L
685	iterator (container_type::* _F_insert_point)(iterator, value_type);
686#else
687	iterator (container_type::* _F_insert_point)(const_iterator,
688						     value_type);
689#endif
690
691	insert_base() : _F_insert_point(&container_type::insert) { }
692      };
693
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>>
698      {
699	typedef __gnu_cxx::__versa_string<_Tp1, _Tp2, _Tp3, _Tp4>
700                                                        container_type;
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;
704
705	iterator (container_type::* _F_insert_point)(const_iterator,
706						     value_type);
707
708	insert_base() : _F_insert_point(&container_type::insert) { }
709      };
710
711    // Specialization, as forward_list has insert_after.
712    template<typename _Tp1, typename _Tp2>
713      struct insert_base<std::forward_list<_Tp1, _Tp2>>
714      {
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;
719
720	iterator (container_type::* _F_insert_point)(const_iterator,
721						     const value_type&);
722
723	insert_base() : _F_insert_point(&container_type::insert_after) { }
724      };
725
726    template<typename _Tp, bool = traits<_Tp>::has_insert::value,
727			   bool = traits<_Tp>::has_insert_after::value>
728      struct insert_point;
729
730    // Specialization for most containers.
731    template<typename _Tp>
732      struct insert_point<_Tp, true, false> : public insert_base<_Tp>
733      {
734	typedef _Tp 				       	container_type;
735	typedef typename container_type::value_type 	value_type;
736	using insert_base<_Tp>::_F_insert_point;
737
738	void
739	operator()(_Tp& __test)
740	{
741	  try
742	    {
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();
747	      std::advance(i, s);
748	      (__test.*_F_insert_point)(i, cv);
749	    }
750	  catch(const __gnu_cxx::forced_error&)
751	    { throw; }
752	}
753
754	// Assumes containers start out equivalent.
755	void
756	operator()(_Tp& __control, _Tp& __test)
757	{
758	  try
759	    {
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();
764	      std::advance(i, s);
765	      (__test.*_F_insert_point)(i, cv);
766	    }
767	  catch(const __gnu_cxx::forced_error&)
768	    { throw; }
769 	}
770      };
771
772    // Specialization for forward_list.
773    template<typename _Tp>
774      struct insert_point<_Tp, false, true> : public insert_base<_Tp>
775      {
776	typedef _Tp 				       	container_type;
777	typedef typename container_type::value_type 	value_type;
778	using insert_base<_Tp>::_F_insert_point;
779
780	void
781	operator()(_Tp& __test)
782	{
783	  try
784	    {
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();
789	      std::advance(i, s);
790	      (__test.*_F_insert_point)(i, cv);
791	    }
792	  catch(const __gnu_cxx::forced_error&)
793	    { throw; }
794	}
795
796	// Assumes containers start out equivalent.
797	void
798	operator()(_Tp& __control, _Tp& __test)
799	{
800	  try
801	    {
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();
806	      std::advance(i, s);
807	      (__test.*_F_insert_point)(i, cv);
808	    }
809	  catch(const __gnu_cxx::forced_error&)
810	    { throw; }
811 	}
812      };
813
814    // Specialization, empty.
815    template<typename _Tp>
816      struct insert_point<_Tp, false, false>
817      {
818	void
819	operator()(_Tp&) { }
820
821	void
822	operator()(_Tp&, _Tp&) { }
823      };
824
825    template<typename _Tp, bool = traits<_Tp>::has_emplace::value
826				  && (traits<_Tp>::is_associative::value
827				      || traits<_Tp>::is_unordered::value)>
828      struct emplace;
829
830    // Specialization for associative and unordered containers.
831    template<typename _Tp>
832      struct emplace<_Tp, true>
833      {
834	typedef _Tp					container_type;
835	typedef typename container_type::value_type	value_type;
836	typedef typename container_type::size_type	size_type;
837
838	void
839	operator()(_Tp& __test)
840	{
841	  try
842	    {
843	      const value_type cv = generate_unique<value_type>();
844	      __test.emplace(cv);
845	    }
846	  catch(const __gnu_cxx::forced_error&)
847	    { throw; }
848	}
849
850	// Assumes containers start out equivalent.
851	void
852	operator()(_Tp& __control, _Tp& __test)
853	{
854	  try
855	    {
856	      const value_type cv = generate_unique<value_type>();
857	      __test.emplace(cv);
858	    }
859	  catch(const __gnu_cxx::forced_error&)
860	    { throw; }
861 	}
862      };
863
864    // Specialization, empty.
865    template<typename _Tp>
866      struct emplace<_Tp, false>
867      {
868	void
869	operator()(_Tp&) { }
870
871	void
872	operator()(_Tp&, _Tp&) { }
873      };
874
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;
880
881    // Specialization for most containers.
882    template<typename _Tp>
883      struct emplace_point<_Tp, true, false, false>
884      {
885	typedef _Tp 				       	container_type;
886	typedef typename container_type::value_type 	value_type;
887
888	void
889	operator()(_Tp& __test)
890	{
891	  try
892	    {
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();
897	      std::advance(i, s);
898	      __test.emplace(i, cv);
899	    }
900	  catch(const __gnu_cxx::forced_error&)
901	    { throw; }
902	}
903
904	// Assumes containers start out equivalent.
905	void
906	operator()(_Tp& __control, _Tp& __test)
907	{
908	  try
909	    {
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();
914	      std::advance(i, s);
915	      __test.emplace(i, cv);
916	    }
917	  catch(const __gnu_cxx::forced_error&)
918	    { throw; }
919 	}
920      };
921
922    // Specialization for associative and unordered containers.
923    template<typename _Tp>
924      struct emplace_point<_Tp, true, true, false>
925      {
926	typedef _Tp 				       	container_type;
927	typedef typename container_type::value_type 	value_type;
928
929	void
930	operator()(_Tp& __test)
931	{
932	  try
933	    {
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();
938	      std::advance(i, s);
939	      __test.emplace_hint(i, cv);
940	    }
941	  catch(const __gnu_cxx::forced_error&)
942	    { throw; }
943	}
944
945	// Assumes containers start out equivalent.
946	void
947	operator()(_Tp& __control, _Tp& __test)
948	{
949	  try
950	    {
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();
955	      std::advance(i, s);
956	      __test.emplace_hint(i, cv);
957	    }
958	  catch(const __gnu_cxx::forced_error&)
959	    { throw; }
960 	}
961      };
962
963    // Specialization for forward_list.
964    template<typename _Tp>
965      struct emplace_point<_Tp, true, false, true>
966      {
967	typedef _Tp 				       	container_type;
968	typedef typename container_type::value_type 	value_type;
969
970	void
971	operator()(_Tp& __test)
972	{
973	  try
974	    {
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();
979	      std::advance(i, s);
980	      __test.emplace_after(i, cv);
981	    }
982	  catch(const __gnu_cxx::forced_error&)
983	    { throw; }
984	}
985
986	// Assumes containers start out equivalent.
987	void
988	operator()(_Tp& __control, _Tp& __test)
989	{
990	  try
991	    {
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();
996	      std::advance(i, s);
997	      __test.emplace_after(i, cv);
998	    }
999	  catch(const __gnu_cxx::forced_error&)
1000	    { throw; }
1001 	}
1002      };
1003
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,
1008			   has_insert_after>
1009      {
1010	void
1011	operator()(_Tp&) { }
1012
1013	void
1014	operator()(_Tp&, _Tp&) { }
1015      };
1016
1017    template<typename _Tp, bool = traits<_Tp>::is_associative::value
1018				  || traits<_Tp>::is_unordered::value>
1019      struct clear
1020      {
1021	void
1022	operator()(_Tp& __container)
1023	{
1024	  try
1025	    {
1026	      __container.clear();
1027	    }
1028	  catch(const __gnu_cxx::forced_error&)
1029	    { throw; }
1030	}
1031      };
1032
1033    // Specialization, empty.
1034    template<typename _Tp>
1035      struct clear<_Tp, false>
1036      {
1037	void
1038	operator()(_Tp&) { }
1039      };
1040
1041
1042    template<typename _Tp, bool = traits<_Tp>::is_unordered::value>
1043      struct rehash
1044      {
1045	void
1046	operator()(_Tp& __test)
1047	{
1048	  try
1049	    {
1050	      size_type s = generate(__test.bucket_count());
1051	      __test.rehash(s);
1052	    }
1053	  catch(const __gnu_cxx::forced_error&)
1054	    { throw; }
1055	}
1056
1057	void
1058	operator()(_Tp& __control, _Tp& __test)
1059	{
1060	  try
1061	    {
1062	      size_type s = generate(__test.bucket_count());
1063	      __test.rehash(s);
1064	    }
1065	  catch(const __gnu_cxx::forced_error&)
1066	    {
1067	      // Also check hash status.
1068	      bool fail(false);
1069	      if (__control.load_factor() != __test.load_factor())
1070		fail = true;
1071	      if (__control.max_load_factor() != __test.max_load_factor())
1072		fail = true;
1073	      if (__control.bucket_count() != __test.bucket_count())
1074		fail = true;
1075	      if (__control.max_bucket_count() != __test.max_bucket_count())
1076		fail = true;
1077
1078	      if (fail)
1079		{
1080		  char buf[40];
1081		  std::string __s("setup_base::rehash "
1082				  "containers not equal");
1083		  __s += "\n";
1084		  __s += "\n";
1085		  __s += "\t\t\tcontrol : test";
1086		  __s += "\n";
1087		  __s += "load_factor\t\t";
1088		  __builtin_sprintf(buf, "%lu", __control.load_factor());
1089		  __s += buf;
1090		  __s += " : ";
1091		  __builtin_sprintf(buf, "%lu", __test.load_factor());
1092		  __s += buf;
1093		  __s += "\n";
1094
1095		  __s += "max_load_factor\t\t";
1096		  __builtin_sprintf(buf, "%lu", __control.max_load_factor());
1097		  __s += buf;
1098		  __s += " : ";
1099		  __builtin_sprintf(buf, "%lu", __test.max_load_factor());
1100		  __s += buf;
1101		  __s += "\n";
1102
1103		  __s += "bucket_count\t\t";
1104		  __builtin_sprintf(buf, "%lu", __control.bucket_count());
1105		  __s += buf;
1106		  __s += " : ";
1107		  __builtin_sprintf(buf, "%lu", __test.bucket_count());
1108		  __s += buf;
1109		  __s += "\n";
1110
1111		  __s += "max_bucket_count\t";
1112		  __builtin_sprintf(buf, "%lu", __control.max_bucket_count());
1113		  __s += buf;
1114		  __s += " : ";
1115		  __builtin_sprintf(buf, "%lu", __test.max_bucket_count());
1116		  __s += buf;
1117		  __s += "\n";
1118
1119		  std::__throw_logic_error(__s.c_str());
1120		}
1121	    }
1122 	}
1123      };
1124
1125    // Specialization, empty.
1126    template<typename _Tp>
1127      struct rehash<_Tp, false>
1128      {
1129	void
1130	operator()(_Tp&) { }
1131
1132	void
1133	operator()(_Tp&, _Tp&) { }
1134      };
1135
1136
1137    template<typename _Tp>
1138      struct swap
1139      {
1140	_Tp _M_other;
1141
1142	void
1143	operator()(_Tp& __container)
1144	{
1145	  try
1146	    {
1147	      __container.swap(_M_other);
1148	    }
1149	  catch(const __gnu_cxx::forced_error&)
1150	    { throw; }
1151	}
1152      };
1153
1154
1155    template<typename _Tp>
1156      struct iterator_operations
1157      {
1158	typedef _Tp 					container_type;
1159	typedef typename container_type::iterator       iterator;
1160
1161	void
1162	operator()(_Tp& __container)
1163	{
1164	  try
1165	    {
1166	      // Any will do.
1167	      iterator i = __container.begin();
1168	      iterator __attribute__((unused)) icopy(i);
1169	      iterator __attribute__((unused)) iassign = i;
1170	    }
1171	  catch(const __gnu_cxx::forced_error&)
1172	    { throw; }
1173	}
1174      };
1175
1176
1177    template<typename _Tp>
1178      struct const_iterator_operations
1179      {
1180	typedef _Tp 					container_type;
1181	typedef typename container_type::const_iterator	const_iterator;
1182
1183	void
1184	operator()(_Tp& __container)
1185	{
1186	  try
1187	    {
1188	      // Any will do.
1189	      const_iterator i = __container.begin();
1190	      const_iterator __attribute__((unused)) icopy(i);
1191	      const_iterator __attribute__((unused)) iassign = i;
1192	    }
1193	  catch(const __gnu_cxx::forced_error&)
1194	    { throw; }
1195	}
1196      };
1197
1198    template<typename _Tp>
1199      struct assign_operator
1200      {
1201	_Tp _M_other;
1202
1203	void
1204	operator()(_Tp& __container)
1205	{
1206	  try
1207	    {
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);
1213	      __clone = _M_other;
1214	    }
1215	  catch(const __gnu_cxx::forced_error&)
1216	    { throw; }
1217	}
1218      };
1219
1220
1221#if __cplusplus >= 201103L
1222    template<typename _Tp>
1223      struct move_assign_operator
1224      {
1225	_Tp _M_other;
1226
1227	void
1228	operator()(_Tp& __container)
1229	{
1230	  try
1231	    {
1232	      __container = std::move(_M_other);
1233	    }
1234	  catch(const __gnu_cxx::forced_error&)
1235	    { throw; }
1236	}
1237      };
1238#endif
1239  };
1240
1241  // Base class for exception tests.
1242  template<typename _Tp>
1243    struct test_base: public functor_base
1244    {
1245      typedef _Tp 					container_type;
1246
1247      typedef functor_base				base_type;
1248      typedef populate<container_type> 	       		populate;
1249      typedef make_container_n<container_type> 	       	make_container_n;
1250
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;
1270#endif
1271
1272      using base_type::compare;
1273    };
1274
1275
1276  // Run through all member functions for basic exception safety
1277  // guarantee: no resource leaks when exceptions are thrown.
1278  //
1279  // Types of resources checked: memory.
1280  //
1281  // For each member function, use throw_value and throw_allocator as
1282  // value_type and allocator_type to force potential exception safety
1283  // errors.
1284  //
1285  // NB: Assumes
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>
1292    {
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;
1298
1299      using base_type::generate;
1300
1301      basic_safety() { run(); }
1302
1303      void
1304      run()
1305      {
1306	{
1307	  // Setup.
1308	  condition_type::never_adjustor off;
1309
1310	  // Construct containers.
1311	  container_type container;
1312	  populate p1(container);
1313
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));
1320
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));
1355#endif
1356	  // Last.
1357	  typename base_type::clear clear;
1358	  functions.push_back(function_type(clear));
1359
1360	  // Run tests.
1361	  size_t i(1);
1362	  for (auto it = functions.begin(); it != functions.end(); ++it)
1363	    {
1364	      function_type& f = *it;
1365	      i = run_steps_to_limit(i, container, f);
1366	    }
1367	}
1368
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();
1373      }
1374
1375      template<typename _Funct>
1376	size_t
1377	run_steps_to_limit(size_t __step, container_type& __cont,
1378			   const _Funct& __f)
1379	{
1380	  bool exit(false);
1381	  auto a = __cont.get_allocator();
1382
1383	  do
1384	    {
1385	      // Use the current step as an allocator label.
1386	      a.set_label(__step);
1387
1388	      try
1389		{
1390		  condition_type::limit_adjustor limit(__step);
1391		  __f(__cont);
1392
1393		  // If we get here, done.
1394		  exit = true;
1395		}
1396	      catch(const __gnu_cxx::forced_error&)
1397		{
1398		  // Check this step for allocations.
1399		  // NB: Will throw std::logic_error if allocations.
1400		  a.check(__step);
1401
1402		  // Check memory allocated with operator new.
1403
1404		}
1405	      ++__step;
1406	    }
1407	  while (!exit);
1408
1409	  // Log count info.
1410	  std::cout << __f.target_type().name() << std::endl;
1411	  std::cout << "end count " << __step << std::endl;
1412	  return __step;
1413	}
1414  };
1415
1416
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>
1424    {
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;
1429
1430      generation_prohibited()  { run(); }
1431
1432      void
1433      run()
1434      {
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!
1438
1439	// Setup.
1440	container_type container;
1441	typename base_type::swap swap;
1442
1443	{
1444	  condition_type::never_adjustor off;
1445	  populate p1(container);
1446	  populate p2(swap._M_other);
1447	}
1448
1449	// Run tests.
1450	{
1451	  condition_type::always_adjustor on;
1452
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)
1456	    {
1457	      typename base_type::erase_point erasep;
1458	      erasep(container);
1459	      typename base_type::erase_range eraser;
1460	      eraser(container);
1461	    }
1462
1463	  typename base_type::pop_front popf;
1464	  popf(container);
1465	  typename base_type::pop_back popb;
1466	  popb(container);
1467
1468	  typename base_type::iterator_ops iops;
1469	  iops(container);
1470	  typename base_type::const_iterator_ops ciops;
1471	  ciops(container);
1472
1473	  swap(container);
1474
1475	  // Last.
1476	  typename base_type::clear clear;
1477	  clear(container);
1478	}
1479      }
1480    };
1481
1482
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,
1487  // push_front
1488  // unordered: rehash
1489  template<typename _Tp>
1490    struct propagation_consistent : public test_base<_Tp>
1491    {
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;
1497
1498      using base_type::compare;
1499
1500      propagation_consistent() { run(); }
1501
1502      // Run test.
1503      void
1504      run()
1505      {
1506	// Setup.
1507	condition_type::never_adjustor off;
1508
1509	// Construct containers.
1510	container_type container_control;
1511
1512	populate p(container_control);
1513
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));
1532
1533	// Run tests.
1534	for (auto i = functions.begin(); i != functions.end(); ++i)
1535	  {
1536	    function_type& f = *i;
1537	    run_steps_to_limit(container_control, f);
1538	  }
1539      }
1540
1541      template<typename _Funct>
1542	void
1543	run_steps_to_limit(container_type& container_control, const _Funct& __f)
1544	{
1545	  size_t i(1);
1546	  bool exit(false);
1547
1548	  do
1549	    {
1550	      container_type container_test(container_control);
1551
1552	      try
1553		{
1554		  condition_type::limit_adjustor limit(i);
1555		  __f(container_test);
1556
1557		  // If we get here, done.
1558		  exit = true;
1559		}
1560	      catch(const __gnu_cxx::forced_error&)
1561		{
1562		  compare(container_control, container_test);
1563		  ++i;
1564		}
1565	    }
1566	  while (!exit);
1567
1568	  // Log count info.
1569	  std::cout << __f.target_type().name() << std::endl;
1570	  std::cout << "end count " << i << std::endl;
1571	}
1572    };
1573
1574} // namespace __gnu_test
1575
1576#endif
1577