OSDN Git Service

2009-12-15 Benjamin Kosnik <bkoz@redhat.com>
authorbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Dec 2009 05:16:46 +0000 (05:16 +0000)
committerbkoz <bkoz@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 16 Dec 2009 05:16:46 +0000 (05:16 +0000)
PR libstdc++/21772 part 1
* include/ext/throw_allocator.h: Rework.
(__gnu_cxx::throw_allocator): To...
(__gnu_cxx::throw_allocator_limit): ...this.
(__gnu_cxx::throw_allocator_random): ...and this.
(throw_value_base, throw_value_limit, throw_value_random): Add.
(condition_base, random_condition, limit_condition): Add.
(forced_exception_error): To...
(forced_error): ...this.
* testsuite/ext/throw_value: New.
* testsuite/ext/throw_value/cons.cc: New.
* testsuite/ext/throw_allocator/deallocate_global.cc: Adjust for
throw_allocator, forced_exception_error changes.
* testsuite/ext/throw_allocator/check_delete.cc: Same.
* testsuite/ext/throw_allocator/check_allocate_max_size.cc: Same.
* testsuite/ext/throw_allocator/check_deallocate_null.cc: Same.
* testsuite/ext/throw_allocator/explicit_instantiation.cc: Same.
* testsuite/ext/throw_allocator/check_new.cc: Same.
* testsuite/ext/throw_allocator/variadic_construct.cc: Same.
* testsuite/ext/throw_allocator/deallocate_local.cc: Same.
* testsuite/23_containers/list/modifiers/insert/25288.cc: Same.
* testsuite/23_containers/list/modifiers/insert/25288.h: Same.
* testsuite/util/regression/common_type.hpp: Same.
* testsuite/util/regression/rand/priority_queue/
container_rand_regression_test.tcc: Same.
* testsuite/util/regression/rand/assoc/
container_rand_regression_test.h: Same.
* testsuite/util/regression/rand/assoc/
container_rand_regression_test.tcc: Same.
* testsuite/util/regression/basic_type.hpp: Same.

* testsuite/ext/forced_exception_error/cons_virtual_derivation.cc: To...
* testsuite/ext/forced_error/cons_virtual_derivation.cc: ...this, same.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@155283 138bc75d-0d04-0410-961f-82ee72b054a4

19 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/ext/throw_allocator.h
libstdc++-v3/testsuite/23_containers/list/modifiers/insert/25288.cc
libstdc++-v3/testsuite/23_containers/list/modifiers/insert/25288.h
libstdc++-v3/testsuite/ext/forced_error/cons_virtual_derivation.cc [moved from libstdc++-v3/testsuite/ext/forced_exception_error/cons_virtual_derivation.cc with 94% similarity]
libstdc++-v3/testsuite/ext/throw_allocator/check_allocate_max_size.cc
libstdc++-v3/testsuite/ext/throw_allocator/check_deallocate_null.cc
libstdc++-v3/testsuite/ext/throw_allocator/check_delete.cc
libstdc++-v3/testsuite/ext/throw_allocator/check_new.cc
libstdc++-v3/testsuite/ext/throw_allocator/deallocate_global.cc
libstdc++-v3/testsuite/ext/throw_allocator/deallocate_local.cc
libstdc++-v3/testsuite/ext/throw_allocator/explicit_instantiation.cc
libstdc++-v3/testsuite/ext/throw_allocator/variadic_construct.cc
libstdc++-v3/testsuite/ext/throw_value/cons.cc [new file with mode: 0644]
libstdc++-v3/testsuite/util/regression/basic_type.hpp
libstdc++-v3/testsuite/util/regression/common_type.hpp
libstdc++-v3/testsuite/util/regression/rand/assoc/container_rand_regression_test.h
libstdc++-v3/testsuite/util/regression/rand/assoc/container_rand_regression_test.tcc
libstdc++-v3/testsuite/util/regression/rand/priority_queue/container_rand_regression_test.tcc

index 9efa407..21a6978 100644 (file)
@@ -1,3 +1,39 @@
+2009-12-15  Benjamin Kosnik  <bkoz@redhat.com>
+
+       PR libstdc++/21772 part 1
+       * include/ext/throw_allocator.h: Rework.
+       (__gnu_cxx::throw_allocator): To...
+       (__gnu_cxx::throw_allocator_limit): ...this.
+       (__gnu_cxx::throw_allocator_random): ...and this.
+       (throw_value_base, throw_value_limit, throw_value_random): Add.
+       (condition_base, random_condition, limit_condition): Add.
+       (forced_exception_error): To...
+       (forced_error): ...this.
+       * testsuite/ext/throw_value: New.
+       * testsuite/ext/throw_value/cons.cc: New.
+       * testsuite/ext/throw_allocator/deallocate_global.cc: Adjust for
+       throw_allocator, forced_exception_error changes.
+       * testsuite/ext/throw_allocator/check_delete.cc: Same.
+       * testsuite/ext/throw_allocator/check_allocate_max_size.cc: Same.
+       * testsuite/ext/throw_allocator/check_deallocate_null.cc: Same.
+       * testsuite/ext/throw_allocator/explicit_instantiation.cc: Same.
+       * testsuite/ext/throw_allocator/check_new.cc: Same.
+       * testsuite/ext/throw_allocator/variadic_construct.cc: Same.
+       * testsuite/ext/throw_allocator/deallocate_local.cc: Same.
+       * testsuite/23_containers/list/modifiers/insert/25288.cc: Same.
+       * testsuite/23_containers/list/modifiers/insert/25288.h: Same.
+       * testsuite/util/regression/common_type.hpp: Same.
+       * testsuite/util/regression/rand/priority_queue/
+       container_rand_regression_test.tcc: Same.
+       * testsuite/util/regression/rand/assoc/
+       container_rand_regression_test.h: Same.
+       * testsuite/util/regression/rand/assoc/
+       container_rand_regression_test.tcc: Same.
+       * testsuite/util/regression/basic_type.hpp: Same.
+
+       * testsuite/ext/forced_exception_error/cons_virtual_derivation.cc: To...
+       * testsuite/ext/forced_error/cons_virtual_derivation.cc: ...this, same.
+
 2009-12-15  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR libstdc++/42381
 2009-12-10  Paolo Carlini  <paolo.carlini@oracle.com>
 
        Revert:
-        2009-12-03  Paolo Carlini  <paolo.carlini@oracle.com>
+       2009-12-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR libstdc++/42261
        * include/bits/basic_string.h (_S_construct_aux(_Integer, _Integer,
 
 2009-11-30  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
-        * include/tr1_impl/functional (function): Add rvalue support and
-        tweak doxygen markup.
-        * testsuite/20_util/function/assign/move.cc: New.
-        * testsuite/20_util/function/cons/move.cc: New.
-        * testsuite/20_util/function/invoke/move_only.cc: New.
-        * testsuite/20_util/function/cmp/cmp_neg.cc: New.
-        * testsuite/20_util/function/1.cc: Copy from testsuite/tr1/.
-        * testsuite/20_util/function/2.cc: Likewise.
-        * testsuite/20_util/function/3.cc: Likewise.
-        * testsuite/20_util/function/4.cc: Likewise.
-        * testsuite/20_util/function/5.cc: Likewise.
-        * testsuite/20_util/function/6.cc: Likewise.
-        * testsuite/20_util/function/7.cc: Likewise.
-        * testsuite/20_util/function/8.cc: Likewise.
-        * testsuite/20_util/function/9.cc: Likewise.
+       * include/tr1_impl/functional (function): Add rvalue support and
+       tweak doxygen markup.
+       * testsuite/20_util/function/assign/move.cc: New.
+       * testsuite/20_util/function/cons/move.cc: New.
+       * testsuite/20_util/function/invoke/move_only.cc: New.
+       * testsuite/20_util/function/cmp/cmp_neg.cc: New.
+       * testsuite/20_util/function/1.cc: Copy from testsuite/tr1/.
+       * testsuite/20_util/function/2.cc: Likewise.
+       * testsuite/20_util/function/3.cc: Likewise.
+       * testsuite/20_util/function/4.cc: Likewise.
+       * testsuite/20_util/function/5.cc: Likewise.
+       * testsuite/20_util/function/6.cc: Likewise.
+       * testsuite/20_util/function/7.cc: Likewise.
+       * testsuite/20_util/function/8.cc: Likewise.
+       * testsuite/20_util/function/9.cc: Likewise.
 
 2009-11-29  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
 
 2009-11-19  Johannes Singler  <singler@kit.edu>
 
-        * include/parallel/partition.h (__parallel_partition): Correctly
-        initialize chunk size.
-        (__parallel_nth_element): Respect nth_element_minimal_n.  Use
-        sequential nth_element as base case, instead of sequential sort.
+       * include/parallel/partition.h (__parallel_partition): Correctly
+       initialize chunk size.
+       (__parallel_nth_element): Respect nth_element_minimal_n.  Use
+       sequential nth_element as base case, instead of sequential sort.
 
 2009-11-17  Benjamin Kosnik  <bkoz@redhat.com>
 
 
 009-10-20  Paolo Carlini  <paolo.carlini@oracle.com>
 
-        PR libstdc++/41773
-        Revert:
-        2009-10-20  Paolo Carlini  <paolo.carlini@oracle.com>
-
-        * include/bits/basic_string.h (_S_construct(const _CharT*, size_type,
-        const _Alloc&)): New, declare.
-        (_S_construct(_CharT*, _CharT*, const _Alloc&),
-        _S_construct(const _CharT*, const _CharT*, const _Alloc&),
-        _S_construct(iterator, iterator, const _Alloc&),
-        _S_construct(const_iterator, const_iterator, const _Alloc&)): New,
-        forward to the latter.
-        * include/bits/basic_string.tcc (_S_construct(const _CharT*,
-        size_type, const _Alloc&)): Define.
-        (basic_string(const basic_string&, size_type, size_type),
-        basic_string(const basic_string&, size_type, size_type,
-        const _Alloc&), basic_string(const _CharT*, size_type,
-        const _Alloc&), basic_string(const _CharT*, const _Alloc&),
-        basic_string(initializer_list<>, const _Alloc&)): Call the latter.
-        * config/abi/pre/gnu.ver: Remove recently added exports.
-        * src/string-inst.cc: Remove instantiations.
+       PR libstdc++/41773
+       Revert:
+       2009-10-20  Paolo Carlini  <paolo.carlini@oracle.com>
+
+       * include/bits/basic_string.h (_S_construct(const _CharT*, size_type,
+       const _Alloc&)): New, declare.
+       (_S_construct(_CharT*, _CharT*, const _Alloc&),
+       _S_construct(const _CharT*, const _CharT*, const _Alloc&),
+       _S_construct(iterator, iterator, const _Alloc&),
+       _S_construct(const_iterator, const_iterator, const _Alloc&)): New,
+       forward to the latter.
+       * include/bits/basic_string.tcc (_S_construct(const _CharT*,
+       size_type, const _Alloc&)): Define.
+       (basic_string(const basic_string&, size_type, size_type),
+       basic_string(const basic_string&, size_type, size_type,
+       const _Alloc&), basic_string(const _CharT*, size_type,
+       const _Alloc&), basic_string(const _CharT*, const _Alloc&),
+       basic_string(initializer_list<>, const _Alloc&)): Call the latter.
+       * config/abi/pre/gnu.ver: Remove recently added exports.
+       * src/string-inst.cc: Remove instantiations.
 
 2009-10-20  Paolo Carlini  <paolo.carlini@oracle.com>
 
index 69daa15..fd939b2 100644 (file)
 /** @file ext/throw_allocator.h
  *  This file is a GNU extension to the Standard C++ Library.
  *
- *  Contains an exception-throwing allocator, useful for testing
- *  exception safety. In addition, allocation addresses are stored and
- *  sanity checked.
+ *  Contains two exception-generating types (throw_value, throw_allocator)
+ *  intended to be used as value and allocator types while testing
+ *  exception safety in templatized containers and algorithms. The
+ *  allocator has additional log and debug features. The exception
+ *  generated is of type forced_exception_error.
  */
 
 #ifndef _THROW_ALLOCATOR_H
 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
 
   /**
-   *  @brief Thown by throw_allocator.
+   *  @brief Thown by exception safety machinery.
    *  @ingroup exceptions
    */
-  struct forced_exception_error : public std::exception
+  struct forced_error : public std::exception
   { };
 
-  // Substitute for concurrence_error object in the case of -fno-exceptions.
+  // Substitute for forced_error object when -fno-exceptions.
   inline void
-  __throw_forced_exception_error()
+  __throw_forced_error()
   {
 #if __EXCEPTIONS
-    throw forced_exception_error();
+    throw forced_error();
 #else
     __builtin_abort();
 #endif
   }
 
-  // Base class for checking address and label information about
-  // allocations. Create a std::map between the allocated address
-  // (void*) and a datum for annotations, which are a pair of numbers
-  // corresponding to label and allocated size.
+
+  /**
+   *  @brief Base class for checking address and label information
+   *  about allocations. Create a std::map between the allocated
+   *  address (void*) and a datum for annotations, which are a pair of
+   *  numbers corresponding to label and allocated size.
+   */
   struct annotate_base
   {
     annotate_base()
@@ -92,7 +97,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       label();
       map();
     }
-    
+
     static void
     set_label(size_t l)
     { label() = l; }
@@ -106,7 +111,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     {
       if (p == NULL)
        {
-         std::string error("throw_allocator_base::insert null insert!\n");
+         std::string error("annotate_base::insert null insert!\n");
          log_to_string(error, make_entry(p, size));
          std::__throw_logic_error(error.c_str());
        }
@@ -114,7 +119,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       const_iterator found = map().find(p);
       if (found != map().end())
        {
-         std::string error("throw_allocator_base::insert double insert!\n");
+         std::string error("annotate_base::insert double insert!\n");
          log_to_string(error, make_entry(p, size));
          log_to_string(error, *found);
          std::__throw_logic_error(error.c_str());
@@ -130,7 +135,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       map().erase(p);
     }
 
-    // See if a particular address and size has been allocated.
+    // See if a particular address and allocation size has been saved.
     inline void
     check_allocated(void* p, size_t size)
     {
@@ -142,7 +147,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
          log_to_string(error, make_entry(p, size));
          std::__throw_logic_error(error.c_str());
        }
-      
+
       if (found->second.second != size)
        {
          std::string error("annotate_base::check_allocated by value "
@@ -166,7 +171,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
            log_to_string(found, *beg);
          ++beg;
        }
-      
+
       if (!found.empty())
        {
          std::string error("annotate_base::check_allocated by label\n");
@@ -213,15 +218,15 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     static size_t&
     label()
     {
-      static size_t ll;
-      return ll;
+      static size_t _S_label(std::numeric_limits<size_t>::max());
+      return _S_label;
     }
 
     static map_type&
     map()
     {
-      static map_type mp;
-      return mp;
+      static map_type _S_map;
+      return _S_map;
     }
   };
 
@@ -237,47 +242,133 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     return os << error;
   }
 
-  /// Base class for probability control and throw.
-  struct probability_base
+
+  /**
+   *  @brief Base struct for condition policy.
+   *
+   * Requires a public member function with the signature
+   * void throw_conditionally()
+   */
+  struct condition_base
+  {
+    virtual ~condition_base() { };
+  };
+
+
+  /**
+   *  @brief Base class for incremental control and throw.
+   */
+  struct limit_condition : public condition_base
   {
-    // Scope-level probability adjustor objects: set probability for
-    // throw at the beginning of a scope block, and restores to
-    // previous probability when object is destroyed on exiting the
-    // block.
+    // Scope-level adjustor objects: set limit for throw at the
+    // beginning of a scope block, and restores to previous limit when
+    // object is destroyed on exiting the block.
     struct adjustor_base
     {
     private:
-      const double _M_prob;
+      const size_t _M_orig;
 
     public:
-      adjustor_base() : _M_prob(get_probability()) { }
+      adjustor_base() : _M_orig(limit()) { }
+
+      virtual
+      ~adjustor_base() { set_limit(_M_orig); }
+    };
+
+    /// Never enter the condition.
+    struct never_adjustor : public adjustor_base
+    {
+      never_adjustor() { set_limit(std::numeric_limits<size_t>::max()); }
+    };
+
+    /// Always enter the condition.
+    struct always_adjustor : public adjustor_base
+    {
+      always_adjustor() { set_limit(count()); }
+    };
+
+    /// Enter the nth condition.
+    struct limit_adjustor : public adjustor_base
+    {
+      limit_adjustor(const size_t __l) { set_limit(__l); }
+    };
+
+    // Increment _S_count every time called.
+    // If _S_count matches the limit count, throw.
+    static void
+    throw_conditionally()
+    {
+      if (count() == limit())
+       __throw_forced_error();
+      ++count();
+    }
+
+    static size_t&
+    count()
+    {
+      static size_t _S_count(0);
+      return _S_count;
+    }
+
+    static size_t&
+    limit()
+    {
+      static size_t _S_limit(std::numeric_limits<size_t>::max());
+      return _S_limit;
+    }
+
+    // Zero the throw counter, set limit to argument.
+    static void
+    set_limit(const size_t __l)
+    {
+      limit() = __l;
+      count() = 0;
+    }
+  };
+
+
+  /**
+   *  @brief Base class for random probability control and throw.
+   */
+  struct random_condition : public condition_base
+  {
+    // Scope-level adjustor objects: set probability for throw at the
+    // beginning of a scope block, and restores to previous
+    // probability when object is destroyed on exiting the block.
+    struct adjustor_base
+    {
+    private:
+      const double _M_orig;
+
+    public:
+      adjustor_base() : _M_orig(probability()) { }
 
       virtual ~adjustor_base()
-      { set_probability(_M_prob); }
+      { set_probability(_M_orig); }
     };
 
-    // Group condition.
+    /// Group condition.
     struct group_adjustor : public adjustor_base
     {
       group_adjustor(size_t size)
-      { set_probability(1 - std::pow(double(1 - get_probability()),
+      { set_probability(1 - std::pow(double(1 - probability()),
                                     double(0.5 / (size + 1))));
       }
     };
 
-    // Never enter the condition.
+    /// Never enter the condition.
     struct never_adjustor : public adjustor_base
     {
       never_adjustor() { set_probability(0); }
     };
 
-    // Always enter the condition.
+    /// Always enter the condition.
     struct always_adjustor : public adjustor_base
     {
       always_adjustor() { set_probability(1); }
     };
 
-    probability_base()
+    random_condition()
     {
       probability();
       engine();
@@ -287,15 +378,11 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     set_probability(double __p)
     { probability() = __p; }
 
-    static double&
-    get_probability()
-    { return probability(); }
-
-    void
+    static void
     throw_conditionally()
     {
-      if (generate() < get_probability())
-       __throw_forced_exception_error();
+      if (generate() < probability())
+       __throw_forced_error();
     }
 
     void
@@ -311,7 +398,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     typedef std::tr1::mt19937                          engine_type;
 #endif
 
-    double
+    static double
     generate()
     {
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -327,7 +414,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       double random = generator();
       if (random < distribution.min() || random > distribution.max())
        {
-         std::string __s("throw_allocator::throw_conditionally");
+         std::string __s("random_condition::generate");
          __s += "\n";
          __s += "random number generated is: ";
          char buf[40];
@@ -342,54 +429,186 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
     static double&
     probability()
     {
-      static double __p;
-      return __p;
+      static double _S_p;
+      return _S_p;
     }
 
     static engine_type&
     engine()
     {
-      static engine_type __e;
-      return __e;
+      static engine_type _S_e;
+      return _S_e;
     }
   };
 
+
   /**
-   *  @brief Allocator class with logging and exception control.
+   *  @brief Class with exception generation control. Intended to be
+   *  used as a value_type in templatized code.
+   *
+   *  Note: Destructor not allowed to throw.
+   */
+  template<typename _Cond>
+    struct throw_value_base : public _Cond
+    {
+      typedef _Cond                            condition_type;
+
+      using condition_type::throw_conditionally;
+
+      std::size_t                              _M_i;
+
+      throw_value_base() : _M_i(0)
+      { throw_conditionally(); }
+
+      throw_value_base(const throw_value_base& __v)
+      : _M_i(__v._M_i)
+      { throw_conditionally(); }
+
+      explicit throw_value_base(const std::size_t __i)
+       : _M_i(__i)
+      { throw_conditionally(); }
+
+      throw_value_base&
+      operator=(const throw_value_base& __v)
+      {
+       throw_conditionally();
+       _M_i = __v._M_i;
+       return *this;
+      }
+
+      throw_value_base&
+      operator++()
+      {
+       throw_conditionally();
+       ++_M_i;
+       return *this;
+      }
+    };
+
+  template<typename _Cond>
+    inline void
+    swap(throw_value_base<_Cond>& __a, throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      throw_value orig(__a);
+      __a = __b;
+      __b = orig;
+    }
+
+  // General instantiable types requirements.
+  template<typename _Cond>
+    inline bool
+    operator==(const throw_value_base<_Cond>& __a,
+              const throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      bool __ret = __a._M_i == __b._M_i;
+      return __ret;
+    }
+
+  template<typename _Cond>
+    inline bool
+    operator<(const throw_value_base<_Cond>& __a,
+             const throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      bool __ret = __a._M_i < __b._M_i;
+      return __ret;
+    }
+
+  // Numeric algorithms instantiable types requirements.
+  template<typename _Cond>
+    inline throw_value_base<_Cond>
+    operator+(const throw_value_base<_Cond>& __a,
+             const throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      throw_value __ret(__a._M_i + __b._M_i);
+      return __ret;
+    }
+
+  template<typename _Cond>
+    inline throw_value_base<_Cond>
+    operator-(const throw_value_base<_Cond>& __a,
+             const throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      throw_value __ret(__a._M_i - __b._M_i);
+      return __ret;
+    }
+
+  template<typename _Cond>
+    inline throw_value_base<_Cond>
+    operator*(const throw_value_base<_Cond>& __a,
+             const throw_value_base<_Cond>& __b)
+    {
+      typedef throw_value_base<_Cond> throw_value;
+      throw_value::throw_conditionally();
+      throw_value __ret(__a._M_i * __b._M_i);
+      return __ret;
+    }
+
+  /// Type throwing via limit condition.
+  struct throw_value_limit : public throw_value_base<limit_condition>
+  {
+    typedef throw_value_base<limit_condition> base_type;
+
+    throw_value_limit() { }
+
+    throw_value_limit(const throw_value_limit& __other)
+    : base_type(__other._M_i) { }
+
+    explicit throw_value_limit(const std::size_t __i) : base_type(__i) { }
+  };
+
+  /// Type throwing via random condition.
+  struct throw_value_random : public throw_value_base<random_condition>
+  {
+    typedef throw_value_base<random_condition> base_type;
+
+    throw_value_random() { }
+
+    throw_value_random(const throw_value_random& __other)
+    : base_type(__other._M_i) { }
+
+
+    explicit throw_value_random(const std::size_t __i) : base_type(__i) { }
+  };
+
+
+  /**
+   *  @brief Allocator class with logging and exception generation control.
+   * Intended to be used as an allocator_type in templatized code.
    *  @ingroup allocators
+   *
+   *  Note: Deallocate not allowed to throw.
    */
-  template<typename T>
-    class throw_allocator
-    : public probability_base, public annotate_base
+  template<typename _Tp, typename _Cond>
+    class throw_allocator_base
+    : public annotate_base, public _Cond
     {
     public:
       typedef size_t                           size_type;
       typedef ptrdiff_t                        difference_type;
-      typedef T                                value_type;
+      typedef _Tp                              value_type;
       typedef value_type*                      pointer;
       typedef const value_type*                const_pointer;
       typedef value_type&                      reference;
       typedef const value_type&                const_reference;
 
     private:
-      std::allocator<value_type>               _M_allocator;
+      typedef _Cond                            condition_type;
 
-    public:
-      template<typename U>
-      struct rebind
-      {
-       typedef throw_allocator<U> other;
-      };
-
-      throw_allocator() throw() { }
-
-      throw_allocator(const throw_allocator&) throw() { }
-
-      template<typename U>
-       throw_allocator(const throw_allocator<U>&) throw() { }
+      std::allocator<value_type>               _M_allocator;
 
-      ~throw_allocator() throw() { }
+      using condition_type::throw_conditionally;
 
+    public:
       size_type
       max_size() const throw()
       { return _M_allocator.max_size(); }
@@ -407,7 +626,7 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       }
 
       void
-      construct(pointer __p, const T& val)
+      construct(pointer __p, const value_type& val)
       { return _M_allocator.construct(__p, val); }
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
@@ -435,19 +654,97 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
        annotate_base::check_allocated(__p, __t);
       }
 
-      using annotate_base::check_allocated;
-    };
+      void
+      check_allocated(size_type __n)
+      { annotate_base::check_allocated(__n); }
+  };
 
-  template<typename T>
+  template<typename _Tp, typename _Cond>
     inline bool
-    operator==(const throw_allocator<T>&, const throw_allocator<T>&)
+    operator==(const throw_allocator_base<_Tp, _Cond>&,
+              const throw_allocator_base<_Tp, _Cond>&)
     { return true; }
 
-  template<typename T>
+  template<typename _Tp, typename _Cond>
     inline bool
-    operator!=(const throw_allocator<T>&, const throw_allocator<T>&)
+    operator!=(const throw_allocator_base<_Tp, _Cond>&,
+              const throw_allocator_base<_Tp, _Cond>&)
     { return false; }
 
+  /// Allocator throwing via limit condition.
+  template<typename _Tp>
+    struct throw_allocator_limit
+    : public throw_allocator_base<_Tp, limit_condition>
+    {
+      template<typename _Tp1>
+       struct rebind
+       { typedef throw_allocator_limit<_Tp1> other; };
+
+      throw_allocator_limit() throw() { }
+
+      throw_allocator_limit(const throw_allocator_limit&) throw() { }
+
+      template<typename _Tp1>
+       throw_allocator_limit(const throw_allocator_limit<_Tp1>&) throw() { }
+
+      ~throw_allocator_limit() throw() { }
+    };
+
+  /// Allocator throwing via random condition.
+  template<typename _Tp>
+    struct throw_allocator_random
+    : public throw_allocator_base<_Tp, random_condition>
+    {
+      template<typename _Tp1>
+       struct rebind
+       { typedef throw_allocator_random<_Tp1> other; };
+
+      throw_allocator_random() throw() { }
+
+      throw_allocator_random(const throw_allocator_random&) throw() { }
+
+      template<typename _Tp1>
+       throw_allocator_random(const throw_allocator_random<_Tp1>&) throw() { }
+
+      ~throw_allocator_random() throw() { }
+    };
+
 _GLIBCXX_END_NAMESPACE
 
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+
+# include <bits/functional_hash.h>
+
+namespace std
+{
+  /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit.
+  template<>
+    struct hash<__gnu_cxx::throw_value_limit>
+    : public std::unary_function<__gnu_cxx::throw_value_limit, size_t>
+    {
+      size_t
+      operator()(__gnu_cxx::throw_value_limit __val) const
+      {
+       std::hash<std::size_t> h;
+       size_t __result = h(__val._M_i);
+       return __result;
+      }
+    };
+
+  /// Explicit specialization of std::hash for __gnu_cxx::throw_value_limit.
+  template<>
+    struct hash<__gnu_cxx::throw_value_random>
+    : public std::unary_function<__gnu_cxx::throw_value_random, size_t>
+    {
+      size_t
+      operator()(__gnu_cxx::throw_value_random __val) const
+      {
+       std::hash<std::size_t> h;
+       size_t __result = h(__val._M_i);
+       return __result;
+      }
+    };
+} // end namespace std
+#endif
+
 #endif
index e9195dd..eb286e0 100644 (file)
@@ -23,7 +23,7 @@
 int main()
 {
   typedef int value_type;
-  typedef __gnu_cxx::throw_allocator<value_type> allocator_type;
+  typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
   typedef std::list<value_type, allocator_type> list_type;
 
   insert1<list_type>();
index c3ec662..aebbe0b 100644 (file)
@@ -47,7 +47,7 @@ void insert1()
            list1.insert(list1.begin(), 10, 99);
            VERIFY( false );
          }
-       catch (__gnu_cxx::forced_exception_error&)
+       catch (__gnu_cxx::forced_error&)
          {
            VERIFY( true );
          }
@@ -74,7 +74,7 @@ void insert1()
            list2.insert(list2.begin(), data, data + 10);
            VERIFY( false );
          }
-       catch (__gnu_cxx::forced_exception_error&)
+       catch (__gnu_cxx::forced_error&)
          {
            VERIFY( true );
          }
@@ -24,7 +24,7 @@
 
 int main()
 {
-  typedef __gnu_cxx::forced_exception_error test_type;
+  typedef __gnu_cxx::forced_error test_type;
   __gnu_test::diamond_derivation<test_type, true>::test();
   return 0;
 }
index 1c7a627..b4d0996 100644 (file)
@@ -24,7 +24,7 @@
 int main()
 {
   typedef int value_type;
-  typedef __gnu_cxx::throw_allocator<value_type> allocator_type;
+  typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
   __gnu_test::check_allocate_max_size<allocator_type>();
   return 0;
 }
index 1a98078..3f9d37a 100644 (file)
@@ -24,7 +24,7 @@
 int main()
 { 
   typedef int value_type;
-  typedef __gnu_cxx::throw_allocator<value_type> allocator_type;
+  typedef __gnu_cxx::throw_allocator_random<value_type> allocator_type;
   
   try { __gnu_test::check_deallocate_null<allocator_type>(); }
   catch (std::logic_error&)
index cfc38ee..181a1eb 100644 (file)
@@ -24,7 +24,7 @@
 
 int main()
 { 
-  typedef __gnu_cxx::throw_allocator<unsigned int> allocator_type;
+  typedef __gnu_cxx::throw_allocator_random<unsigned int> allocator_type;
   __gnu_test::check_delete<allocator_type, true>(); 
   return 0;
 }
index 2d42891..4338471 100644 (file)
@@ -24,7 +24,7 @@
 
 int main()
 { 
-  typedef __gnu_cxx::throw_allocator<unsigned int> allocator_type;
+  typedef __gnu_cxx::throw_allocator_random<unsigned int> allocator_type;
   __gnu_test::check_new<allocator_type, true>(); 
   return 0;
 }
index c53517e..65ef6db 100644 (file)
@@ -25,7 +25,7 @@
 
 typedef char char_t;
 typedef std::char_traits<char_t> traits_t;
-typedef __gnu_cxx::throw_allocator<char_t> allocator_t;
+typedef __gnu_cxx::throw_allocator_random<char_t> allocator_t;
 typedef std::basic_string<char_t, traits_t, allocator_t> string_t;  
 
 string_t s("bayou bend");
index c2e918c..4f00928 100644 (file)
@@ -24,7 +24,7 @@
 
 typedef char char_t;
 typedef std::char_traits<char_t> traits_t;
-typedef __gnu_cxx::throw_allocator<char_t> allocator_t;
+typedef __gnu_cxx::throw_allocator_random<char_t> allocator_t;
 typedef std::basic_string<char_t, traits_t, allocator_t> string_t;  
 
 int main()
index 659807d..c260044 100644 (file)
@@ -21,4 +21,5 @@
 #include <cstdlib>
 #include <ext/throw_allocator.h>
 
-template class __gnu_cxx::throw_allocator<int>;
+template class __gnu_cxx::throw_allocator_random<int>;
+template class __gnu_cxx::throw_allocator_limit<int>;
index 395cacc..fd1ee8d 100644 (file)
@@ -29,7 +29,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
   typedef std::pair<int, char> pair_type;
-  __gnu_cxx::throw_allocator<pair_type> alloc1;
+  __gnu_cxx::throw_allocator_random<pair_type> alloc1;
 
   pair_type* ptp1 = alloc1.allocate(1);
   alloc1.construct(ptp1, 3, 'a');
diff --git a/libstdc++-v3/testsuite/ext/throw_value/cons.cc b/libstdc++-v3/testsuite/ext/throw_value/cons.cc
new file mode 100644 (file)
index 0000000..fa3f3f7
--- /dev/null
@@ -0,0 +1,43 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2009 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+#include <ext/throw_allocator.h>
+
+void foo1()
+{ 
+  typedef __gnu_cxx::throw_value_limit value_type;
+  value_type v1;
+  value_type v2(v2);
+  value_type v3(value_type());
+}
+
+bool foo2()
+{ 
+  typedef __gnu_cxx::throw_value_limit value_type;
+  bool b = std::is_convertible<value_type, value_type>::value;
+  return b;
+}
+
+int main()
+{
+  foo1();
+  foo2();
+  return 0;
+}
index 6d12bd6..9fe6ef2 100644 (file)
@@ -46,7 +46,7 @@ namespace test
 {
 #define PB_DS_BASE_C_DEC \
   std::basic_string<char, std::char_traits<char>, \
-                   __gnu_cxx::throw_allocator<char> >
+                   __gnu_cxx::throw_allocator_random<char> >
 
   struct basic_type : public PB_DS_BASE_C_DEC
   {
index 9e6a80d..37705bc 100644 (file)
@@ -46,7 +46,7 @@ namespace __gnu_pbds
 {
 namespace test
 {
-  typedef __gnu_cxx::throw_allocator<basic_type> alloc_type;
+  typedef __gnu_cxx::throw_allocator_random<basic_type> alloc_type;
 
   struct hash
   {
index 393463a..ca44332 100644 (file)
@@ -80,7 +80,7 @@ namespace detail
     typedef typename test_traits::native_type          native_type;
     typedef twister_rand_gen                           gen;
     typedef __gnu_pbds::container_traits<Cntnr>        container_traits;
-    typedef __gnu_cxx::throw_allocator<char>           alloc_t;
+    typedef __gnu_cxx::throw_allocator_random<char>            alloc_t;
 
     enum op
       {
index d995a04..43cdb9f 100644 (file)
@@ -66,7 +66,7 @@ default_constructor()
     {
       m_p_c = new Cntnr;
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -107,7 +107,7 @@ copy_constructor()
       p_c = new Cntnr(*m_p_c);
       std::swap(p_c, m_p_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -134,7 +134,7 @@ assignment_operator()
       * p_c =* m_p_c;
       std::swap(p_c, m_p_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -210,7 +210,7 @@ it_constructor_imp(__gnu_pbds::cc_hash_tag)
         };
       std::swap(p_c, m_p_c);
     }
-  catch (__gnu_cxx::forced_exception_error&)
+  catch (__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -293,7 +293,7 @@ it_constructor_imp(__gnu_pbds::gp_hash_tag)
         };
       std::swap(p_c, m_p_c);
     }
-  catch (__gnu_cxx::forced_exception_error&)
+  catch (__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -329,7 +329,7 @@ it_constructor_imp(__gnu_pbds::tree_tag)
         };
       std::swap(p_c, m_p_c);
     }
-  catch (__gnu_cxx::forced_exception_error&)
+  catch (__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -354,7 +354,7 @@ it_constructor_imp(__gnu_pbds::list_update_tag)
       p_c = new Cntnr(m_p_c->begin(), m_p_c->end());
       std::swap(p_c, m_p_c);
     }
-  catch (__gnu_cxx::forced_exception_error&)
+  catch (__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -392,7 +392,7 @@ it_constructor_imp(__gnu_pbds::pat_trie_tag)
 
       std::swap(p_c, m_p_c);
     }
-  catch (__gnu_cxx::forced_exception_error&)
+  catch (__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -1088,7 +1088,7 @@ insert()
        }
       m_native_c.insert(test_traits::native_value(v));
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -1139,7 +1139,7 @@ subscript_imp(__gnu_pbds::detail::false_type)
       m_native_c[test_traits::native_value(v).first] =
        test_traits::native_value(v).second;
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -1164,7 +1164,7 @@ subscript_imp(__gnu_pbds::detail::true_type)
       (*m_p_c)[v] = __gnu_pbds::null_mapped_type();
       m_native_c.insert(test_traits::native_value(v));
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -1213,7 +1213,7 @@ erase()
       PB_DS_THROW_IF_FAILED(m_p_c->find(k) == m_p_c->end(), "", 
                            m_p_c, &m_native_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
 
@@ -1251,7 +1251,7 @@ erase_if()
       PB_DS_THROW_IF_FAILED(ersd == native_ersd,
                            ersd << " " << native_ersd, m_p_c, &m_native_c);
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
       PB_DS_THROW_IF_FAILED(container_traits::erase_can_throw, 
@@ -1329,7 +1329,7 @@ erase_it_imp(__gnu_pbds::detail::true_type)
       if (range_guarantee)
        PB_DS_THROW_IF_FAILED(next_ers_it == next_it, "", m_p_c, &m_native_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
       PB_DS_THROW_IF_FAILED(container_traits::erase_can_throw, container_traits::erase_can_throw, m_p_c, &m_native_c);
@@ -1392,7 +1392,7 @@ erase_rev_it_imp(__gnu_pbds::detail::true_type)
       if (native_it != m_native_c.end())
        m_native_c.erase(native_it);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;      
       PB_DS_THROW_IF_FAILED(container_traits::erase_can_throw, 
@@ -1763,7 +1763,7 @@ split_join_imp(__gnu_pbds::detail::true_type)
       PB_DS_THROW_IF_FAILED(rhs.empty(), rhs.size(), m_p_c, &m_native_c);
       m_p_c->swap(lhs);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
       PB_DS_THROW_IF_FAILED(container_traits::split_join_can_throw, 
index fe8ae6b..f964911 100644 (file)
@@ -66,7 +66,7 @@ default_constructor()
     {
       m_p_c = new Cntnr;
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -110,7 +110,7 @@ copy_constructor()
       p_c = new Cntnr(*m_p_c);
       std::swap(p_c, m_p_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -139,7 +139,7 @@ assignment_operator()
       *p_c = *m_p_c;
       std::swap(p_c, m_p_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -180,7 +180,7 @@ it_constructor()
 
       std::swap(p_c, m_p_c);
     }
-  catch(__gnu_cxx::forced_exception_error& )
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
     }
@@ -433,7 +433,7 @@ push()
         _GLIBCXX_THROW_IF(sz != m_p_c->size() - 1, sz, m_p_c, &m_native_c);
         m_native_c.push(test_traits::native_value(v));
       }
-    catch(__gnu_cxx::forced_exception_error& )
+    catch(__gnu_cxx::forced_error&)
       {
         done = false;
       }
@@ -475,7 +475,7 @@ modify()
          m_native_c.modify(native_v, new_native_v);
        }
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
       _GLIBCXX_THROW_IF(true, "", m_p_c, &m_native_c);
@@ -517,7 +517,7 @@ pop()
          m_native_c.pop();
         }
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;
       _GLIBCXX_THROW_IF(true, "", m_p_c, &m_native_c);
@@ -560,7 +560,7 @@ erase_if()
       _GLIBCXX_THROW_IF(ersd != native_ersd, ersd << " " << native_ersd,
                        m_p_c, &m_native_c);
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;      
       _GLIBCXX_THROW_IF(true, "", m_p_c, &m_native_c);
@@ -592,7 +592,7 @@ erase_it()
          m_p_c->erase(it);
        }
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;      
       _GLIBCXX_THROW_IF(true, "", m_p_c, &m_native_c);
@@ -715,7 +715,7 @@ split_join()
       _GLIBCXX_THROW_IF(rhs.size() != 0, rhs.size(), m_p_c, &m_native_c);
       _GLIBCXX_THROW_IF(!rhs.empty(), rhs.size(), m_p_c, &m_native_c);
     }
-  catch(__gnu_cxx::forced_exception_error&)
+  catch(__gnu_cxx::forced_error&)
     {
       done = false;      
       const bool b = __gnu_pbds::container_traits<cntnr>::split_join_can_throw;