]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
2014-06-26 François Dumont <fdumont@gcc.gnu.org>
authorFrançois Dumont <fdumont@gcc.gnu.org>
Thu, 26 Jun 2014 18:42:41 +0000 (18:42 +0000)
committerFrançois Dumont <fdumont@gcc.gnu.org>
Thu, 26 Jun 2014 18:42:41 +0000 (18:42 +0000)
* testsuite/util/testsuite_allocator.h
(tracker_allocator_counter::allocate): Remove new invocation, only
collect information.
(tracker_allocator_counter::deallocate): Remove delete invocation, only
collect information.
(check_inconsistent_alloc_value_type): New.
(tracker_allocator): Transform as a facade for any allocator type.
(uneq_allocator): Likewise.
(propagating_allocator): Likewise.
* testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an
explicitly non propagating allocator.
* testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise.
* testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
* testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
Likewise.
* testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.

From-SVN: r212046

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/testsuite/23_containers/forward_list/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/map/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/multimap/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/multiset/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/set/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/unordered_map/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/unordered_set/debug/move_assign_neg.cc
libstdc++-v3/testsuite/23_containers/vector/debug/move_assign_neg.cc
libstdc++-v3/testsuite/util/testsuite_allocator.h

index ba61134f7bdec1b2d92100714e146e7bac283481..4fcc7ff5efadca0f8186e2cc1fc026921a1054aa 100644 (file)
@@ -1,3 +1,30 @@
+2014-06-26  François Dumont  <fdumont@gcc.gnu.org>
+
+       * testsuite/util/testsuite_allocator.h
+       (tracker_allocator_counter::allocate): Remove new invocation, only
+       collect information.
+       (tracker_allocator_counter::deallocate): Remove delete invocation, only
+       collect information.
+       (check_inconsistent_alloc_value_type): New.
+       (tracker_allocator): Transform as a facade for any allocator type.
+       (uneq_allocator): Likewise.
+       (propagating_allocator): Likewise.
+       * testsuite/23_containers/forward_list/debug/move_assign_neg.cc: Use an
+       explicitly non propagating allocator.
+       * testsuite/23_containers/map/debug/move_assign_neg.cc: Likewise.
+       * testsuite/23_containers/multimap/debug/move_assign_neg.cc: likewise.
+       * testsuite/23_containers/multiset/debug/move_assign_neg.cc: Likewise.
+       * testsuite/23_containers/set/debug/move_assign_neg.cc: Likewise.
+       * testsuite/23_containers/unordered_map/debug/move_assign_neg.cc:
+       Likewise.
+       * testsuite/23_containers/unordered_multimap/debug/move_assign_neg.cc:
+       Likewise.
+       * testsuite/23_containers/unordered_multiset/debug/move_assign_neg.cc:
+       Likewise.
+       * testsuite/23_containers/unordered_set/debug/move_assign_neg.cc:
+       Likewise.
+       * testsuite/23_containers/vector/debug/move_assign_neg.cc: Likewise.
+
 2014-06-26  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/bits/shared_ptr_base.h (__shared_ptr::_Deleter): Fix
index 91e459fd3c3ad2f7d3e38fc0cf41b516b1069b9f..934afbedd6bf78310bd779d70bd164d9a290bd16 100644 (file)
@@ -25,7 +25,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::forward_list<int, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index 0d63fe944bf0645d9d9296bb7cb138b358172eda..3f2a7ca532b347b173e6e9e1f962194a8a24cbf2 100644 (file)
@@ -25,7 +25,8 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+  typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+                                           false> alloc_type;
   typedef __gnu_debug::map<int, int, std::less<int>, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index e514a28dbed704cbbd970592f37d7351a238c820..da2950fe45816d5d5ef3bfa4357775103d7f625b 100644 (file)
@@ -25,7 +25,8 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+  typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+                                           false> alloc_type;
   typedef __gnu_debug::multimap<int, int, std::less<int>, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index af879d94dadb0ff93380842b135e79e9c8a8b5af..6f5f5b430ccfce7da2aa9518a660cfa148025495 100644 (file)
@@ -25,7 +25,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::multiset<int, std::less<int>, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index b7f51efd3933f305daf298f4966d0b6567cec28c..b491a03276da608b0693c44f3caa2309349dbda4 100644 (file)
@@ -25,7 +25,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::set<int, std::less<int>, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index ef5db1165f397c82c9debafc7b05f3f893b1b9ef..3670f73b0d37dd4fe201fa702994c70aca4a94be 100644 (file)
@@ -25,7 +25,8 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<std::pair<const int, int> > alloc_type;
+  typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+                                           false> alloc_type;
   typedef __gnu_debug::unordered_map<int, int,
                                     std::hash<int>, std::equal_to<int>,
                                     alloc_type> test_type;
index b6de1eef581e7fb30ba744ec80517e7bf1aded81..7a8fa77c4d856b8ed2dbb5905b3ee130e0426b69 100644 (file)
@@ -25,7 +25,8 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<std::pair<const int, int>> alloc_type;
+  typedef __gnu_test::propagating_allocator<std::pair<const int, int>,
+                                           false> alloc_type;
   typedef __gnu_debug::unordered_multimap<int, int, std::hash<int>,
                                          std::equal_to<int>,
                                          alloc_type> test_type;
index 52a8df2a9f2ca4144f096155311cf48aa854028b..9fe72e1f254860d4b81859b93dca40f2a309d148 100644 (file)
@@ -25,7 +25,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::unordered_multiset<int, std::hash<int>,
                                          std::equal_to<int>,
                                          alloc_type> test_type;
index 9d2a8abc4254ce013145de8feb9a2022cd82c567..b1b71e118ff85b7f102207896cfe2466896f5bb8 100644 (file)
@@ -25,7 +25,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::unordered_set<int, std::hash<int>,
                                     std::equal_to<int>,
                                     alloc_type> test_type;
index eb2233b35fe1e80687690b89772186368e430306..3de0723195ea3ba49a070a649bcee29b4d795f96 100644 (file)
@@ -27,7 +27,7 @@ void test01()
 {
   bool test __attribute__((unused)) = true;
 
-  typedef __gnu_test::uneq_allocator<int> alloc_type;
+  typedef __gnu_test::propagating_allocator<int, false> alloc_type;
   typedef __gnu_debug::vector<int, alloc_type> test_type;
 
   test_type v1(alloc_type(1));
index 822a025f4fa25428cf2b274074e57506b032227e..8aae8c215148b9dce357fc331e80a36ffb786ce2 100644 (file)
@@ -29,6 +29,7 @@
 #include <tr1/unordered_map>
 #include <bits/move.h>
 #include <ext/pointer.h>
+#include <ext/alloc_traits.h>
 #include <testsuite_hooks.h>
 
 namespace __gnu_test
@@ -38,26 +39,19 @@ namespace __gnu_test
   public:
     typedef std::size_t    size_type; 
 
-    static void*
+    static void
     allocate(size_type blocksize)
-    {
-      void* p = ::operator new(blocksize);
-      allocationCount_ += blocksize;
-      return p;
-    }
+    { allocationCount_ += blocksize; }
 
     static void
-    construct() { constructCount_++; }
+    construct() { ++constructCount_; }
 
     static void
-    destroy() { destructCount_++; }
+    destroy() { ++destructCount_; }
 
     static void
-    deallocate(void* p, size_type blocksize)
-    {
-      ::operator delete(p);
-      deallocationCount_ += blocksize;
-    }
+    deallocate(size_type blocksize)
+    { deallocationCount_ += blocksize; }
 
     static size_type
     get_allocation_count() { return allocationCount_; }
@@ -87,103 +81,142 @@ namespace __gnu_test
     static int        destructCount_;
   };
 
-  // A simple basic allocator that just forwards to the
-  // tracker_allocator_counter to fulfill memory requests.  This class
-  // is templated on the target object type, but tracker isn't.
-  template<class T>
-  class tracker_allocator
-  {
-  private:
-    typedef tracker_allocator_counter counter_type;
+  // Helper to detect inconsistency between type used to instantiate an
+  // allocator and the underlying allocator value_type.
+  template<typename T, typename Alloc,
+          typename = typename Alloc::value_type>
+    struct check_consistent_alloc_value_type;
+
+  template<typename T, typename Alloc>
+    struct check_consistent_alloc_value_type<T, Alloc, T>
+    { typedef T value_type; };
+
+  // An allocator facade that intercepts allocate/deallocate/construct/detroy
+  // calls and track them through the tracker_allocator_counter class. This
+  // class is templated on the target object type, but tracker isn't.
+  template<typename T, typename Alloc = std::allocator<T> >
+    class tracker_allocator : public Alloc
+    {
+    private:
+      typedef tracker_allocator_counter counter_type;
 
-  public:
-    typedef T              value_type;
-    typedef T*             pointer;
-    typedef const T*       const_pointer;
-    typedef T&             reference;
-    typedef const T&       const_reference;
-    typedef std::size_t    size_type; 
-    typedef std::ptrdiff_t difference_type; 
+      typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+    public:
+      typedef typename
+      check_consistent_alloc_value_type<T, Alloc>::value_type value_type;
+      typedef typename AllocTraits::pointer pointer;
+      typedef typename AllocTraits::size_type size_type;
     
-    template<class U> struct rebind { typedef tracker_allocator<U> other; };
+      template<class U>
+       struct rebind
+       {
+         typedef tracker_allocator<U,
+               typename AllocTraits::template rebind<U>::other> other;
+       };
     
-    pointer
-    address(reference value) const _GLIBCXX_NOEXCEPT
-    { return std::__addressof(value); }
-
-    const_pointer
-    address(const_reference value) const _GLIBCXX_NOEXCEPT
-    { return std::__addressof(value); }
-
-    tracker_allocator() _GLIBCXX_USE_NOEXCEPT
-    { }
-
-    tracker_allocator(const tracker_allocator&) _GLIBCXX_USE_NOEXCEPT
-    { }
+#if __cplusplus >= 201103L
+      tracker_allocator() = default;
+      tracker_allocator(const tracker_allocator&) = default;
+      tracker_allocator(tracker_allocator&&) = default;
+
+      // Perfect forwarding constructor.
+      template<typename... _Args>
+       tracker_allocator(_Args&&... __args)
+         : Alloc(std::forward<_Args>(__args)...)
+       { }
+#else
+      tracker_allocator()
+      { }
 
-    template<class U>
-      tracker_allocator(const tracker_allocator<U>&) _GLIBCXX_USE_NOEXCEPT
+      tracker_allocator(const tracker_allocator&)
       { }
 
-    ~tracker_allocator() _GLIBCXX_USE_NOEXCEPT
-    { }
+      ~tracker_allocator()
+      { }
+#endif
 
-    size_type
-    max_size() const _GLIBCXX_USE_NOEXCEPT
-    { return size_type(-1) / sizeof(T); }
+      template<class U>
+       tracker_allocator(const tracker_allocator<U,
+         typename AllocTraits::template rebind<U>::other>& alloc)
+           _GLIBCXX_USE_NOEXCEPT
+         : Alloc(alloc)
+       { }
 
-    pointer
-    allocate(size_type n, const void* = 0)
-    { return static_cast<pointer>(counter_type::allocate(n * sizeof(T))); }
+      pointer
+      allocate(size_type n, const void* = 0)
+      {
+       pointer p = AllocTraits::allocate(*this, n);
+       counter_type::allocate(n * sizeof(T));
+       return p;
+      }
 
 #if __cplusplus >= 201103L
-    template<typename U, typename... Args>
+      template<typename U, typename... Args>
+       void
+       construct(U* p, Args&&... args) 
+       {
+         AllocTraits::construct(*this, p, std::forward<Args>(args)...);
+         counter_type::construct();
+       }
+
+      template<typename U>
+       void
+       destroy(U* p)
+       {
+         AllocTraits::destroy(*this, p);
+         counter_type::destroy();
+       }
+#else
       void
-      construct(U* p, Args&&... args) 
+      construct(pointer p, const T& value)
       {
-       ::new((void *)p) U(std::forward<Args>(args)...);
+       AllocTraits::construct(*this, p, value);
        counter_type::construct();
       }
 
-    template<typename U>
       void
-      destroy(U* p)
+      destroy(pointer p)
       {
-       p->~U();
+       AllocTraits::destroy(*this, p);
        counter_type::destroy();
       }
-#else
-    void
-    construct(pointer p, const T& value)
-    {
-      ::new ((void *)p) T(value);
-      counter_type::construct();
-    }
-
-    void
-    destroy(pointer p)
-    {
-      p->~T();
-      counter_type::destroy();
-    }
 #endif
 
-    void
-    deallocate(pointer p, size_type num)
-    { counter_type::deallocate(p, num * sizeof(T)); }
-  };
+      void
+      deallocate(pointer p, size_type num)
+      {
+       counter_type::deallocate(num * sizeof(T));
+       AllocTraits::deallocate(*this, p, num);
+      }
+
+      // Implement swap for underlying allocators that might need it.
+      friend inline void
+      swap(tracker_allocator& a, tracker_allocator& b)
+      {
+       using std::swap;
+
+       Alloc& aa = a;
+       Alloc& ab = b;
+       swap(aa, ab);
+      } 
+    };
 
-  template<class T1, class T2>
+  template<class T1, class Alloc1, class T2, class Alloc2>
     bool
-    operator==(const tracker_allocator<T1>&, 
-              const tracker_allocator<T2>&) throw()
-    { return true; }
+    operator==(const tracker_allocator<T1, Alloc1>& lhs, 
+              const tracker_allocator<T2, Alloc2>& rhs) throw()
+    {
+      const Alloc1& alloc1 = lhs;
+      const Alloc2& alloc2 = rhs;
+      return lhs == rhs;
+    }
 
-  template<class T1, class T2>
+  template<class T1, class Alloc1, class T2, class Alloc2>
     bool
-    operator!=(const tracker_allocator<T1>&
-              const tracker_allocator<T2>&) throw()
-    { return false; }
+    operator!=(const tracker_allocator<T1, Alloc1>& lhs
+              const tracker_allocator<T2, Alloc2>& rhs) throw()
+    { return !(lhs == rhs); }
 
   bool
   check_construct_destroy(const char* tag, int expected_c, int expected_d);
@@ -193,7 +226,7 @@ namespace __gnu_test
     check_deallocate_null()
     {
       // Let's not core here...
-      Alloc  a;
+      Alloc a;
       a.deallocate(0, 1);
       a.deallocate(0, 10);
       return true;
@@ -219,7 +252,6 @@ namespace __gnu_test
       throw;
     }
 
-
   // A simple allocator which can be constructed endowed of a given
   // "personality" (an integer), queried in operator== to simulate the
   // behavior of realworld "unequal" allocators (i.e., not exploiting
@@ -227,7 +259,7 @@ namespace __gnu_test
   // filled at allocation time with (pointer, personality) pairs, is
   // then consulted to enforce the requirements in Table 32 about
   // deallocation vs allocator equality.  Note that this allocator is
-  // swappable, not assignable, consistently with Option 3 of DR 431
+  // swappable, not copy assignable, consistently with Option 3 of DR 431
   // (see N1599).
   struct uneq_allocator_base
   {
@@ -244,26 +276,33 @@ namespace __gnu_test
     }
   };
 
-  template<typename Tp>
+  template<typename Tp, typename Alloc = std::allocator<Tp> >
     class uneq_allocator
-    : private uneq_allocator_base
+    : private uneq_allocator_base,
+      public Alloc
     {
+      typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+      Alloc& base() { return *this; }
+      const Alloc& base() const  { return *this; }
+      void swap_base(Alloc& b) { swap(b, this->base()); }
+
     public:
-      typedef std::size_t                         size_type;
-      typedef std::ptrdiff_t                      difference_type;
-      typedef Tp*                                 pointer;
-      typedef const Tp*                           const_pointer;
-      typedef Tp&                                 reference;
-      typedef const Tp&                           const_reference;
-      typedef Tp                                  value_type;
+      typedef typename check_consistent_alloc_value_type<Tp, Alloc>::value_type
+       value_type;
+      typedef typename AllocTraits::size_type  size_type;
+      typedef typename AllocTraits::pointer    pointer;
 
 #if __cplusplus >= 201103L
-      typedef std::true_type                      propagate_on_container_swap;
+      typedef std::true_type                   propagate_on_container_swap;
 #endif
 
       template<typename Tp1>
-        struct rebind
-       { typedef uneq_allocator<Tp1> other; };
+       struct rebind
+       {
+         typedef uneq_allocator<Tp1,
+               typename AllocTraits::template rebind<Tp1>::other> other;
+       };
 
       uneq_allocator() _GLIBCXX_USE_NOEXCEPT
       : personality(0) { }
@@ -272,7 +311,9 @@ namespace __gnu_test
       : personality(person) { }
       
       template<typename Tp1>
-        uneq_allocator(const uneq_allocator<Tp1>& b) _GLIBCXX_USE_NOEXCEPT
+       uneq_allocator(const uneq_allocator<Tp1,
+                      typename AllocTraits::template rebind<Tp1>::other>& b)
+       _GLIBCXX_USE_NOEXCEPT
        : personality(b.get_personality()) { }
 
       ~uneq_allocator() _GLIBCXX_USE_NOEXCEPT
@@ -281,20 +322,9 @@ namespace __gnu_test
       int get_personality() const { return personality; }
       
       pointer
-      address(reference x) const _GLIBCXX_NOEXCEPT
-      { return std::__addressof(x); }
-    
-      const_pointer
-      address(const_reference x) const _GLIBCXX_NOEXCEPT
-      { return std::__addressof(x); }
-
-      pointer
-      allocate(size_type n, const void* = 0)
+      allocate(size_type n, const void* hint = 0)
       { 
-       if (__builtin_expect(n > this->max_size(), false))
-         std::__throw_bad_alloc();
-       
-       pointer p = static_cast<Tp*>(::operator new(n * sizeof(Tp)));
+       pointer p = AllocTraits::allocate(*this, n);
        try
          {
            get_map().insert(map_type::value_type(reinterpret_cast<void*>(p),
@@ -302,14 +332,14 @@ namespace __gnu_test
          }
        catch(...)
          {
-           ::operator delete(p);
+           AllocTraits::deallocate(*this, p, n);
            __throw_exception_again;
          }
        return p;
       }
 
       void
-      deallocate(pointer p, size_type)
+      deallocate(pointer p, size_type n)
       {
        bool test __attribute__((unused)) = true;
 
@@ -323,34 +353,18 @@ namespace __gnu_test
        VERIFY( it->second == personality );
 
        get_map().erase(it);
-       ::operator delete(p);
+       AllocTraits::deallocate(*this, p, n);
       }
 
-      size_type
-      max_size() const _GLIBCXX_USE_NOEXCEPT 
-      { return size_type(-1) / sizeof(Tp); }
-
 #if __cplusplus >= 201103L
-      template<typename U, typename... Args>
-        void
-        construct(U* p, Args&&... args) 
-       { ::new((void *)p) U(std::forward<Args>(args)...); }
-
-      template<typename U>
-       void 
-       destroy(U* p) { p->~U(); }
-
       // Not copy assignable...
       uneq_allocator&
       operator=(const uneq_allocator&) = delete;
-#else
-      void 
-      construct(pointer p, const Tp& val) 
-      { ::new((void *)p) Tp(val); }
-
-      void 
-      destroy(pointer p) { p->~Tp(); }
 
+      // ... but still moveable if base allocator is.
+      uneq_allocator&
+      operator=(uneq_allocator&&) = default;
+#else
     private:
       // Not assignable...
       uneq_allocator&
@@ -358,31 +372,39 @@ namespace __gnu_test
 #endif
 
     private:
-
       // ... yet swappable!
       friend inline void
       swap(uneq_allocator& a, uneq_allocator& b)
-      { std::swap(a.personality, b.personality); } 
-      
+      {
+       std::swap(a.personality, b.personality);
+       a.swap_base(b);
+      } 
+
       template<typename Tp1>
-        friend inline bool
-        operator==(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
-        { return a.personality == b.personality; }
+       friend inline bool
+       operator==(const uneq_allocator& a,
+                  const uneq_allocator<Tp1,
+                  typename AllocTraits::template rebind<Tp1>::other>& b)
+       { return a.personality == b.personality; }
 
       template<typename Tp1>
-        friend inline bool
-        operator!=(const uneq_allocator& a, const uneq_allocator<Tp1>& b)
-        { return !(a == b); }
+       friend inline bool
+       operator!=(const uneq_allocator& a,
+                  const uneq_allocator<Tp1,
+                  typename AllocTraits::template rebind<Tp1>::other>& b)
+       { return !(a == b); }
       
       int personality;
     };
 
 #if __cplusplus >= 201103L
   // An uneq_allocator which can be used to test allocator propagation.
-  template<typename Tp, bool Propagate>
-    class propagating_allocator : public uneq_allocator<Tp>
+  template<typename Tp, bool Propagate, typename Alloc = std::allocator<Tp>>
+    class propagating_allocator : public uneq_allocator<Tp, Alloc>
     {
-      typedef uneq_allocator<Tp> base_alloc;
+      typedef __gnu_cxx::__alloc_traits<Alloc> AllocTraits;
+
+      typedef uneq_allocator<Tp, Alloc> base_alloc;
       base_alloc& base() { return *this; }
       const base_alloc& base() const  { return *this; }
       void swap_base(base_alloc& b) { swap(b, this->base()); }
@@ -393,15 +415,20 @@ namespace __gnu_test
       // default allocator_traits::rebind_alloc would select
       // uneq_allocator::rebind so we must define rebind here
       template<typename Up>
-       struct rebind { typedef propagating_allocator<Up, Propagate> other; };
+       struct rebind
+       {
+         typedef propagating_allocator<Up, Propagate,
+               typename AllocTraits::template rebind<Up>::other> other;
+       };
 
       propagating_allocator(int i) noexcept
       : base_alloc(i)
       { }
 
       template<typename Up>
-       propagating_allocator(const propagating_allocator<Up, Propagate>& a)
-               noexcept
+       propagating_allocator(const propagating_allocator<Up, Propagate,
+                             typename AllocTraits::template rebind<Up>::other>& a)
+       noexcept
        : base_alloc(a)
        { }
 
@@ -418,8 +445,8 @@ namespace __gnu_test
       }
 
       template<bool P2>
-       propagating_allocator&
-       operator=(const propagating_allocator<Tp, P2>& a) noexcept
+       propagating_allocator&
+       operator=(const propagating_allocator<Tp, P2, Alloc>& a) noexcept
        {
          static_assert(P2, "assigning propagating_allocator<T, true>");
          propagating_allocator(a).swap_base(*this);