xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/ext/throw_allocator.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 // -*- C++ -*-
2 
3 // Copyright (C) 2005-2020 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 // Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL.
26 
27 // Permission to use, copy, modify, sell, and distribute this software
28 // is hereby granted without fee, provided that the above copyright
29 // notice appears in all copies, and that both that copyright notice
30 // and this permission notice appear in supporting documentation. None
31 // of the above authors, nor IBM Haifa Research Laboratories, make any
32 // representation about the suitability of this software for any
33 // purpose. It is provided "as is" without express or implied
34 // warranty.
35 
36 /** @file ext/throw_allocator.h
37  *  This file is a GNU extension to the Standard C++ Library.
38  *
39  *  Contains two exception-generating types (throw_value, throw_allocator)
40  *  intended to be used as value and allocator types while testing
41  *  exception safety in templatized containers and algorithms. The
42  *  allocator has additional log and debug features. The exception
43  *  generated is of type forced_exception_error.
44  */
45 
46 #ifndef _THROW_ALLOCATOR_H
47 #define _THROW_ALLOCATOR_H 1
48 
49 #include <cmath>
50 #include <ctime>
51 #include <map>
52 #include <string>
53 #include <ostream>
54 #include <stdexcept>
55 #include <utility>
56 #include <bits/functexcept.h>
57 #include <bits/move.h>
58 #if __cplusplus >= 201103L
59 # include <functional>
60 # include <random>
61 #else
62 # include <tr1/functional>
63 # include <tr1/random>
64 #endif
65 #include <ext/alloc_traits.h>
66 
67 #if !__has_builtin(__builtin_sprintf)
68 # include <cstdio>
69 #endif
70 
_GLIBCXX_VISIBILITY(default)71 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
72 {
73 _GLIBCXX_BEGIN_NAMESPACE_VERSION
74 
75   /**
76    *  @brief Thown by exception safety machinery.
77    *  @ingroup exceptions
78    */
79   struct forced_error : public std::exception
80   { };
81 
82   // Substitute for forced_error object when -fno-exceptions.
83   inline void
84   __throw_forced_error()
85   { _GLIBCXX_THROW_OR_ABORT(forced_error()); }
86 
87   /**
88    *  @brief Base class for checking address and label information
89    *  about allocations. Create a std::map between the allocated
90    *  address (void*) and a datum for annotations, which are a pair of
91    *  numbers corresponding to label and allocated size.
92    */
93   struct annotate_base
94   {
95   private:
96     typedef std::pair<size_t, size_t>		data_type;
97     typedef std::map<void*, data_type>		map_alloc_type;
98     typedef map_alloc_type::value_type		entry_type;
99     typedef map_alloc_type::const_iterator	const_iterator;
100     typedef map_alloc_type::const_reference	const_reference;
101 #if __cplusplus >= 201103L
102     typedef std::map<void*, size_t>		map_construct_type;
103 #endif
104 
105   public:
106     annotate_base()
107     {
108       label();
109       map_alloc();
110     }
111 
112     static void
113     set_label(size_t l)
114     { label() = l; }
115 
116     static size_t
117     get_label()
118     { return label(); }
119 
120     void
121     insert(void* p, size_t size)
122     {
123       entry_type entry = make_entry(p, size);
124       if (!p)
125 	{
126 	  std::string error("annotate_base::insert null insert!\n");
127 	  log_to_string(error, entry);
128 	  std::__throw_logic_error(error.c_str());
129 	}
130 
131       std::pair<map_alloc_type::iterator, bool> inserted
132 	= map_alloc().insert(entry);
133       if (!inserted.second)
134 	{
135 	  std::string error("annotate_base::insert double insert!\n");
136 	  log_to_string(error, entry);
137 	  log_to_string(error, *inserted.first);
138 	  std::__throw_logic_error(error.c_str());
139 	}
140     }
141 
142     void
143     erase(void* p, size_t size)
144     { map_alloc().erase(check_allocated(p, size)); }
145 
146 #if __cplusplus >= 201103L
147     void
148     insert_construct(void* p)
149     {
150       if (!p)
151 	{
152 	  std::string error("annotate_base::insert_construct null!\n");
153 	  std::__throw_logic_error(error.c_str());
154 	}
155 
156       auto inserted = map_construct().insert(std::make_pair(p, get_label()));
157       if (!inserted.second)
158 	{
159 	  std::string error("annotate_base::insert_construct double insert!\n");
160 	  log_to_string(error, std::make_pair(p, get_label()));
161 	  log_to_string(error, *inserted.first);
162 	  std::__throw_logic_error(error.c_str());
163 	}
164     }
165 
166     void
167     erase_construct(void* p)
168     { map_construct().erase(check_constructed(p)); }
169 #endif
170 
171     // See if a particular address and allocation size has been saved.
172     inline map_alloc_type::iterator
173     check_allocated(void* p, size_t size)
174     {
175       map_alloc_type::iterator found = map_alloc().find(p);
176       if (found == map_alloc().end())
177 	{
178 	  std::string error("annotate_base::check_allocated by value "
179 			    "null erase!\n");
180 	  log_to_string(error, make_entry(p, size));
181 	  std::__throw_logic_error(error.c_str());
182 	}
183 
184       if (found->second.second != size)
185 	{
186 	  std::string error("annotate_base::check_allocated by value "
187 			    "wrong-size erase!\n");
188 	  log_to_string(error, make_entry(p, size));
189 	  log_to_string(error, *found);
190 	  std::__throw_logic_error(error.c_str());
191 	}
192 
193       return found;
194     }
195 
196     // See if a given label has been allocated.
197     inline void
198     check(size_t label)
199     {
200       std::string found;
201       {
202 	const_iterator beg = map_alloc().begin();
203 	const_iterator end = map_alloc().end();
204 	while (beg != end)
205 	  {
206 	    if (beg->second.first == label)
207 	      log_to_string(found, *beg);
208 	    ++beg;
209 	  }
210       }
211 
212 #if __cplusplus >= 201103L
213       {
214 	auto beg = map_construct().begin();
215 	auto end = map_construct().end();
216 	while (beg != end)
217 	  {
218 	    if (beg->second == label)
219 	      log_to_string(found, *beg);
220 	    ++beg;
221 	  }
222       }
223 #endif
224 
225       if (!found.empty())
226 	{
227 	  std::string error("annotate_base::check by label\n");
228 	  error += found;
229 	  std::__throw_logic_error(error.c_str());
230 	}
231     }
232 
233     // See if there is anything left allocated or constructed.
234     inline static void
235     check()
236     {
237       std::string found;
238       {
239 	const_iterator beg = map_alloc().begin();
240 	const_iterator end = map_alloc().end();
241 	while (beg != end)
242 	  {
243 	    log_to_string(found, *beg);
244 	    ++beg;
245 	  }
246       }
247 
248 #if __cplusplus >= 201103L
249       {
250 	auto beg = map_construct().begin();
251 	auto end = map_construct().end();
252 	while (beg != end)
253 	  {
254 	    log_to_string(found, *beg);
255 	    ++beg;
256 	  }
257       }
258 #endif
259 
260       if (!found.empty())
261 	{
262 	  std::string error("annotate_base::check \n");
263 	  error += found;
264 	  std::__throw_logic_error(error.c_str());
265 	}
266     }
267 
268 #if __cplusplus >= 201103L
269     inline map_construct_type::iterator
270     check_constructed(void* p)
271     {
272       auto found = map_construct().find(p);
273       if (found == map_construct().end())
274 	{
275 	  std::string error("annotate_base::check_constructed not "
276 			    "constructed!\n");
277 	  log_to_string(error, std::make_pair(p, get_label()));
278 	  std::__throw_logic_error(error.c_str());
279 	}
280 
281       return found;
282     }
283 
284     inline void
285     check_constructed(size_t label)
286     {
287       auto beg = map_construct().begin();
288       auto end = map_construct().end();
289       std::string found;
290       while (beg != end)
291 	{
292 	  if (beg->second == label)
293 	    log_to_string(found, *beg);
294 	  ++beg;
295 	}
296 
297       if (!found.empty())
298 	{
299 	  std::string error("annotate_base::check_constructed by label\n");
300 	  error += found;
301 	  std::__throw_logic_error(error.c_str());
302 	}
303     }
304 #endif
305 
306   private:
307     friend std::ostream&
308     operator<<(std::ostream&, const annotate_base&);
309 
310     entry_type
311     make_entry(void* p, size_t size)
312     { return std::make_pair(p, data_type(get_label(), size)); }
313 
314     static void
315     log_to_string(std::string& s, const_reference ref)
316     {
317 #if ! __has_builtin(__builtin_sprintf)
318       __typeof__(&std::sprintf) __builtin_sprintf = &std::sprintf;
319 #endif
320 
321       char buf[40];
322       const char tab('\t');
323       s += "label: ";
324       unsigned long l = static_cast<unsigned long>(ref.second.first);
325       __builtin_sprintf(buf, "%lu", l);
326       s += buf;
327       s += tab;
328       s += "size: ";
329       l = static_cast<unsigned long>(ref.second.second);
330       __builtin_sprintf(buf, "%lu", l);
331       s += buf;
332       s += tab;
333       s += "address: ";
334       __builtin_sprintf(buf, "%p", ref.first);
335       s += buf;
336       s += '\n';
337     }
338 
339 #if __cplusplus >= 201103L
340     static void
341     log_to_string(std::string& s, const std::pair<const void*, size_t>& ref)
342     {
343 #if ! __has_builtin(__builtin_sprintf)
344       auto __builtin_sprintf = &std::sprintf;
345 #endif
346 
347       char buf[40];
348       const char tab('\t');
349       s += "label: ";
350       unsigned long l = static_cast<unsigned long>(ref.second);
351       __builtin_sprintf(buf, "%lu", l);
352       s += buf;
353       s += tab;
354       s += "address: ";
355       __builtin_sprintf(buf, "%p", ref.first);
356       s += buf;
357       s += '\n';
358     }
359 #endif
360 
361     static size_t&
362     label()
363     {
364       static size_t _S_label(std::numeric_limits<size_t>::max());
365       return _S_label;
366     }
367 
368     static map_alloc_type&
369     map_alloc()
370     {
371       static map_alloc_type _S_map;
372       return _S_map;
373     }
374 
375 #if __cplusplus >= 201103L
376     static map_construct_type&
377     map_construct()
378     {
379       static map_construct_type _S_map;
380       return _S_map;
381     }
382 #endif
383   };
384 
385   inline std::ostream&
386   operator<<(std::ostream& os, const annotate_base& __b)
387   {
388     std::string error;
389     typedef annotate_base base_type;
390     {
391       base_type::const_iterator beg = __b.map_alloc().begin();
392       base_type::const_iterator end = __b.map_alloc().end();
393       for (; beg != end; ++beg)
394 	__b.log_to_string(error, *beg);
395     }
396 #if __cplusplus >= 201103L
397     {
398       auto beg = __b.map_construct().begin();
399       auto end = __b.map_construct().end();
400       for (; beg != end; ++beg)
401 	__b.log_to_string(error, *beg);
402     }
403 #endif
404     return os << error;
405   }
406 
407 
408   /**
409    *  @brief Base struct for condition policy.
410    *
411    * Requires a public member function with the signature
412    * void throw_conditionally()
413    */
414   struct condition_base
415   {
416 #if __cplusplus >= 201103L
417     condition_base() = default;
418     condition_base(const condition_base&) = default;
419     condition_base& operator=(const condition_base&) = default;
420 #endif
421     virtual ~condition_base() { };
422   };
423 
424 
425   /**
426    *  @brief Base class for incremental control and throw.
427    */
428   struct limit_condition : public condition_base
429   {
430     // Scope-level adjustor objects: set limit for throw at the
431     // beginning of a scope block, and restores to previous limit when
432     // object is destroyed on exiting the block.
433     struct adjustor_base
434     {
435     private:
436       const size_t _M_orig;
437 
438     public:
439       adjustor_base() : _M_orig(limit()) { }
440 
441       virtual
442       ~adjustor_base() { set_limit(_M_orig); }
443     };
444 
445     /// Never enter the condition.
446     struct never_adjustor : public adjustor_base
447     {
448       never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); }
449     };
450 
451     /// Always enter the condition.
452     struct always_adjustor : public adjustor_base
453     {
454       always_adjustor() { set_limit(count()); }
455     };
456 
457     /// Enter the nth condition.
458     struct limit_adjustor : public adjustor_base
459     {
460       limit_adjustor(const size_t __l) { set_limit(__l); }
461     };
462 
463     // Increment _S_count every time called.
464     // If _S_count matches the limit count, throw.
465     static void
466     throw_conditionally()
467     {
468       if (count() == limit())
469 	__throw_forced_error();
470       ++count();
471     }
472 
473     static size_t&
474     count()
475     {
476       static size_t _S_count(0);
477       return _S_count;
478     }
479 
480     static size_t&
481     limit()
482     {
483       static size_t _S_limit(std::numeric_limits<size_t>::max());
484       return _S_limit;
485     }
486 
487     // Zero the throw counter, set limit to argument.
488     static void
489     set_limit(const size_t __l)
490     {
491       limit() = __l;
492       count() = 0;
493     }
494   };
495 
496 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
497   /**
498    *  @brief Base class for random probability control and throw.
499    */
500   struct random_condition : public condition_base
501   {
502     // Scope-level adjustor objects: set probability for throw at the
503     // beginning of a scope block, and restores to previous
504     // probability when object is destroyed on exiting the block.
505     struct adjustor_base
506     {
507     private:
508       const double _M_orig;
509 
510     public:
511       adjustor_base() : _M_orig(probability()) { }
512 
513       virtual ~adjustor_base()
514       { set_probability(_M_orig); }
515     };
516 
517     /// Group condition.
518     struct group_adjustor : public adjustor_base
519     {
520       group_adjustor(size_t size)
521       { set_probability(1 - std::pow(double(1 - probability()),
522 				     double(0.5 / (size + 1))));
523       }
524     };
525 
526     /// Never enter the condition.
527     struct never_adjustor : public adjustor_base
528     {
529       never_adjustor() { set_probability(0); }
530     };
531 
532     /// Always enter the condition.
533     struct always_adjustor : public adjustor_base
534     {
535       always_adjustor() { set_probability(1); }
536     };
537 
538     random_condition()
539     {
540       probability();
541       engine();
542     }
543 
544     static void
545     set_probability(double __p)
546     { probability() = __p; }
547 
548     static void
549     throw_conditionally()
550     {
551       if (generate() < probability())
552 	__throw_forced_error();
553     }
554 
555     void
556     seed(unsigned long __s)
557     { engine().seed(__s); }
558 
559   private:
560 #if __cplusplus >= 201103L
561     typedef std::uniform_real_distribution<double> 	distribution_type;
562     typedef std::mt19937 				engine_type;
563 #else
564     typedef std::tr1::uniform_real<double> 		distribution_type;
565     typedef std::tr1::mt19937 				engine_type;
566 #endif
567 
568     static double
569     generate()
570     {
571 #if __cplusplus >= 201103L
572       const distribution_type distribution(0, 1);
573       static auto generator = std::bind(distribution, engine());
574 #else
575       // Use variate_generator to get normalized results.
576       typedef std::tr1::variate_generator<engine_type, distribution_type> gen_t;
577       distribution_type distribution(0, 1);
578       static gen_t generator(engine(), distribution);
579 #endif
580 
581 #if ! __has_builtin(__builtin_sprintf)
582       __typeof__(&std::sprintf) __builtin_sprintf = &std::sprintf;
583 #endif
584 
585       double random = generator();
586       if (random < distribution.min() || random > distribution.max())
587 	{
588 	  std::string __s("random_condition::generate");
589 	  __s += "\n";
590 	  __s += "random number generated is: ";
591 	  char buf[40];
592 	  __builtin_sprintf(buf, "%f", random);
593 	  __s += buf;
594 	  std::__throw_out_of_range(__s.c_str());
595 	}
596 
597       return random;
598     }
599 
600     static double&
601     probability()
602     {
603       static double _S_p;
604       return _S_p;
605     }
606 
607     static engine_type&
608     engine()
609     {
610       static engine_type _S_e;
611       return _S_e;
612     }
613   };
614 #endif // _GLIBCXX_USE_C99_STDINT_TR1
615 
616   /**
617    *  @brief Class with exception generation control. Intended to be
618    *  used as a value_type in templatized code.
619    *
620    *  Note: Destructor not allowed to throw.
621    */
622   template<typename _Cond>
623     struct throw_value_base : public _Cond
624     {
625       typedef _Cond  				condition_type;
626 
627       using condition_type::throw_conditionally;
628 
629       std::size_t			       	_M_i;
630 
631 #ifndef _GLIBCXX_IS_AGGREGATE
632       throw_value_base() : _M_i(0)
633       { throw_conditionally(); }
634 
635       throw_value_base(const throw_value_base& __v) : _M_i(__v._M_i)
636       { throw_conditionally(); }
637 
638 #if __cplusplus >= 201103L
639       // Shall not throw.
640       throw_value_base(throw_value_base&&) = default;
641 #endif
642 
643       explicit throw_value_base(const std::size_t __i) : _M_i(__i)
644       { throw_conditionally(); }
645 #endif
646 
647       throw_value_base&
648       operator=(const throw_value_base& __v)
649       {
650 	throw_conditionally();
651 	_M_i = __v._M_i;
652 	return *this;
653       }
654 
655 #if __cplusplus >= 201103L
656       // Shall not throw.
657       throw_value_base&
658       operator=(throw_value_base&&) = default;
659 #endif
660 
661       throw_value_base&
662       operator++()
663       {
664 	throw_conditionally();
665 	++_M_i;
666 	return *this;
667       }
668     };
669 
670   template<typename _Cond>
671     inline void
672     swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b)
673     {
674       typedef throw_value_base<_Cond> throw_value;
675       throw_value::throw_conditionally();
676       throw_value orig(__a);
677       __a = __b;
678       __b = orig;
679     }
680 
681   // General instantiable types requirements.
682   template<typename _Cond>
683     inline bool
684     operator==(const throw_value_base<_Cond>& __a,
685 	       const throw_value_base<_Cond>& __b)
686     {
687       typedef throw_value_base<_Cond> throw_value;
688       throw_value::throw_conditionally();
689       bool __ret = __a._M_i == __b._M_i;
690       return __ret;
691     }
692 
693   template<typename _Cond>
694     inline bool
695     operator<(const throw_value_base<_Cond>& __a,
696 	      const throw_value_base<_Cond>& __b)
697     {
698       typedef throw_value_base<_Cond> throw_value;
699       throw_value::throw_conditionally();
700       bool __ret = __a._M_i < __b._M_i;
701       return __ret;
702     }
703 
704   // Numeric algorithms instantiable types requirements.
705   template<typename _Cond>
706     inline throw_value_base<_Cond>
707     operator+(const throw_value_base<_Cond>& __a,
708 	      const throw_value_base<_Cond>& __b)
709     {
710       typedef throw_value_base<_Cond> throw_value;
711       throw_value::throw_conditionally();
712       throw_value __ret(__a._M_i + __b._M_i);
713       return __ret;
714     }
715 
716   template<typename _Cond>
717     inline throw_value_base<_Cond>
718     operator-(const throw_value_base<_Cond>& __a,
719 	      const throw_value_base<_Cond>& __b)
720     {
721       typedef throw_value_base<_Cond> throw_value;
722       throw_value::throw_conditionally();
723       throw_value __ret(__a._M_i - __b._M_i);
724       return __ret;
725     }
726 
727   template<typename _Cond>
728     inline throw_value_base<_Cond>
729     operator*(const throw_value_base<_Cond>& __a,
730 	      const throw_value_base<_Cond>& __b)
731     {
732       typedef throw_value_base<_Cond> throw_value;
733       throw_value::throw_conditionally();
734       throw_value __ret(__a._M_i * __b._M_i);
735       return __ret;
736     }
737 
738 
739   /// Type throwing via limit condition.
740   struct throw_value_limit : public throw_value_base<limit_condition>
741   {
742     typedef throw_value_base<limit_condition> base_type;
743 
744 #ifndef _GLIBCXX_IS_AGGREGATE
745     throw_value_limit() { }
746 
747     throw_value_limit(const throw_value_limit& __other)
748     : base_type(__other._M_i) { }
749 
750 #if __cplusplus >= 201103L
751     throw_value_limit(throw_value_limit&&) = default;
752 #endif
753 
754     explicit throw_value_limit(const std::size_t __i) : base_type(__i) { }
755 #endif
756 
757     throw_value_limit&
758     operator=(const throw_value_limit& __other)
759     {
760       base_type::operator=(__other);
761       return *this;
762     }
763 
764 #if __cplusplus >= 201103L
765     throw_value_limit&
766     operator=(throw_value_limit&&) = default;
767 #endif
768   };
769 
770 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
771   /// Type throwing via random condition.
772   struct throw_value_random : public throw_value_base<random_condition>
773   {
774     typedef throw_value_base<random_condition> base_type;
775 
776 #ifndef _GLIBCXX_IS_AGGREGATE
777     throw_value_random() { }
778 
779     throw_value_random(const throw_value_random& __other)
780     : base_type(__other._M_i) { }
781 
782 #if __cplusplus >= 201103L
783     throw_value_random(throw_value_random&&) = default;
784 #endif
785 
786     explicit throw_value_random(const std::size_t __i) : base_type(__i) { }
787 #endif
788 
789     throw_value_random&
790     operator=(const throw_value_random& __other)
791     {
792       base_type::operator=(__other);
793       return *this;
794     }
795 
796 #if __cplusplus >= 201103L
797     throw_value_random&
798     operator=(throw_value_random&&) = default;
799 #endif
800   };
801 #endif // _GLIBCXX_USE_C99_STDINT_TR1
802 
803   /**
804    *  @brief Allocator class with logging and exception generation control.
805    * Intended to be used as an allocator_type in templatized code.
806    *  @ingroup allocators
807    *
808    *  Note: Deallocate not allowed to throw.
809    */
810   template<typename _Tp, typename _Cond>
811     class throw_allocator_base
812     : public annotate_base, public _Cond
813     {
814     public:
815       typedef std::size_t 			size_type;
816       typedef std::ptrdiff_t 			difference_type;
817       typedef _Tp 				value_type;
818       typedef value_type* 			pointer;
819       typedef const value_type* 		const_pointer;
820       typedef value_type& 			reference;
821       typedef const value_type& 		const_reference;
822 
823 #if __cplusplus >= 201103L
824       // _GLIBCXX_RESOLVE_LIB_DEFECTS
825       // 2103. std::allocator propagate_on_container_move_assignment
826       typedef std::true_type propagate_on_container_move_assignment;
827 #endif
828 
829     private:
830       typedef _Cond				condition_type;
831 
832       std::allocator<value_type> 		_M_allocator;
833 
834       typedef __gnu_cxx::__alloc_traits<std::allocator<value_type> > traits;
835 
836       using condition_type::throw_conditionally;
837 
838     public:
839       size_type
840       max_size() const _GLIBCXX_USE_NOEXCEPT
841       { return traits::max_size(_M_allocator); }
842 
843       pointer
844       address(reference __x) const _GLIBCXX_NOEXCEPT
845       { return std::__addressof(__x); }
846 
847       const_pointer
848       address(const_reference __x) const _GLIBCXX_NOEXCEPT
849       { return std::__addressof(__x); }
850 
851       _GLIBCXX_NODISCARD pointer
852       allocate(size_type __n, const void* hint = 0)
853       {
854 	if (__n > this->max_size())
855 	  std::__throw_bad_alloc();
856 
857 	throw_conditionally();
858 	pointer const a = traits::allocate(_M_allocator, __n, hint);
859 	insert(a, sizeof(value_type) * __n);
860 	return a;
861       }
862 
863 #if __cplusplus >= 201103L
864       template<typename _Up, typename... _Args>
865         void
866         construct(_Up* __p, _Args&&... __args)
867 	{
868 	  traits::construct(_M_allocator, __p, std::forward<_Args>(__args)...);
869 	  insert_construct(__p);
870 	}
871 
872       template<typename _Up>
873         void
874         destroy(_Up* __p)
875         {
876 	  erase_construct(__p);
877 	  traits::destroy(_M_allocator, __p);
878 	}
879 #else
880       void
881       construct(pointer __p, const value_type& val)
882       { return _M_allocator.construct(__p, val); }
883 
884       void
885       destroy(pointer __p)
886       { _M_allocator.destroy(__p); }
887 #endif
888 
889       void
890       deallocate(pointer __p, size_type __n)
891       {
892 	erase(__p, sizeof(value_type) * __n);
893 	_M_allocator.deallocate(__p, __n);
894       }
895 
896       void
897       check_allocated(pointer __p, size_type __n)
898       {
899 	size_type __t = sizeof(value_type) * __n;
900 	annotate_base::check_allocated(__p, __t);
901       }
902 
903       void
904       check(size_type __n)
905       { annotate_base::check(__n); }
906   };
907 
908   template<typename _Tp, typename _Cond>
909     inline bool
910     operator==(const throw_allocator_base<_Tp, _Cond>&,
911 	       const throw_allocator_base<_Tp, _Cond>&)
912     { return true; }
913 
914 #if __cpp_impl_three_way_comparison < 201907L
915   template<typename _Tp, typename _Cond>
916     inline bool
917     operator!=(const throw_allocator_base<_Tp, _Cond>&,
918 	       const throw_allocator_base<_Tp, _Cond>&)
919     { return false; }
920 #endif
921 
922   /// Allocator throwing via limit condition.
923   template<typename _Tp>
924     struct throw_allocator_limit
925     : public throw_allocator_base<_Tp, limit_condition>
926     {
927       template<typename _Tp1>
928 	struct rebind
929 	{ typedef throw_allocator_limit<_Tp1> other; };
930 
931       throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
932 
933       throw_allocator_limit(const throw_allocator_limit&)
934       _GLIBCXX_USE_NOEXCEPT { }
935 
936       template<typename _Tp1>
937 	throw_allocator_limit(const throw_allocator_limit<_Tp1>&)
938 	_GLIBCXX_USE_NOEXCEPT { }
939 
940       ~throw_allocator_limit() _GLIBCXX_USE_NOEXCEPT { }
941     };
942 
943 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
944   /// Allocator throwing via random condition.
945   template<typename _Tp>
946     struct throw_allocator_random
947     : public throw_allocator_base<_Tp, random_condition>
948     {
949       template<typename _Tp1>
950 	struct rebind
951 	{ typedef throw_allocator_random<_Tp1> other; };
952 
953       throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
954 
955       throw_allocator_random(const throw_allocator_random&)
956       _GLIBCXX_USE_NOEXCEPT { }
957 
958       template<typename _Tp1>
959 	throw_allocator_random(const throw_allocator_random<_Tp1>&)
960 	_GLIBCXX_USE_NOEXCEPT { }
961 
962       ~throw_allocator_random() _GLIBCXX_USE_NOEXCEPT { }
963     };
964 #endif // _GLIBCXX_USE_C99_STDINT_TR1
965 
966 _GLIBCXX_END_NAMESPACE_VERSION
967 } // namespace
968 
969 #if __cplusplus >= 201103L
970 
971 # include <bits/functional_hash.h>
972 
_GLIBCXX_VISIBILITY(default)973 namespace std _GLIBCXX_VISIBILITY(default)
974 {
975   /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit.
976   template<>
977     struct hash<__gnu_cxx::throw_value_limit>
978     : public std::unary_function<__gnu_cxx::throw_value_limit, size_t>
979     {
980       size_t
981       operator()(const __gnu_cxx::throw_value_limit& __val) const
982       {
983 	__gnu_cxx::throw_value_limit::throw_conditionally();
984 	std::hash<std::size_t> __h;
985 	size_t __result = __h(__val._M_i);
986 	return __result;
987       }
988     };
989 
990 #ifdef _GLIBCXX_USE_C99_STDINT_TR1
991   /// Explicit specialization of std::hash for __gnu_cxx::throw_value_random.
992   template<>
993     struct hash<__gnu_cxx::throw_value_random>
994     : public std::unary_function<__gnu_cxx::throw_value_random, size_t>
995     {
996       size_t
997       operator()(const __gnu_cxx::throw_value_random& __val) const
998       {
999 	__gnu_cxx::throw_value_random::throw_conditionally();
1000 	std::hash<std::size_t> __h;
1001 	size_t __result = __h(__val._M_i);
1002 	return __result;
1003       }
1004     };
1005 #endif
1006 } // end namespace std
1007 #endif
1008 
1009 #endif
1010