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