commit e2405ae375e28ca1c73c2f3fd138e63ffabf610d
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Mon Jan 11 14:29:07 2016 +0000

    allocator_traits<allocator<T>> partial specialization
    
    	PR libstdc++/60976
    	* include/bits/alloc_traits.h (allocator_traits<allocator<_Tp>>):
    	Define partial specialization.
    	* testsuite/20_util/shared_ptr/cons/58659.cc: Add construct and
    	destroy members to std::allocator explicit specialization.

diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h
index 8abd02f..d2d13c6 100644
--- a/libstdc++-v3/include/bits/alloc_traits.h
+++ b/libstdc++-v3/include/bits/alloc_traits.h
@@ -331,7 +331,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  Calls @c __a.destroy(__p) if that expression is well-formed,
        *  otherwise calls @c __p->~_Tp()
       */
-      template <class _Tp>
+      template<typename _Tp>
 	static void destroy(_Alloc& __a, _Tp* __p)
 	{ _S_destroy(__a, __p, 0); }
 
@@ -359,6 +359,133 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       { return _S_select(__rhs, 0); }
     };
 
+  /// Partial specialization for std::allocator.
+  template<typename _Tp>
+    struct allocator_traits<allocator<_Tp>>
+    {
+      /// The allocator type
+      using allocator_type = allocator<_Tp>;
+      /// The allocated type
+      using value_type = _Tp;
+
+      /// The allocator's pointer type.
+      using pointer = _Tp*;
+
+      /// The allocator's const pointer type.
+      using const_pointer = const _Tp*;
+
+      /// The allocator's void pointer type.
+      using void_pointer = void*;
+
+      /// The allocator's const void pointer type.
+      using const_void_pointer = const void*;
+
+      /// The allocator's difference type
+      using difference_type = std::ptrdiff_t;
+
+      /// The allocator's size type
+      using size_type = std::size_t;
+
+      /// How the allocator is propagated on copy assignment
+      using propagate_on_container_copy_assignment = false_type;
+
+      /// How the allocator is propagated on move assignment
+      using propagate_on_container_move_assignment = true_type;
+
+      /// How the allocator is propagated on swap
+      using propagate_on_container_swap = false_type;
+
+      /// Whether all instances of the allocator type compare equal.
+      using is_always_equal = true_type;
+
+      template<typename _Up>
+	using rebind_alloc = allocator<_Up>;
+
+      template<typename _Up>
+	using rebind_traits = allocator_traits<allocator<_Up>>;
+
+      /**
+       *  @brief  Allocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __n  The number of objects to allocate space for.
+       *
+       *  Calls @c a.allocate(n)
+      */
+      static pointer
+      allocate(allocator_type& __a, size_type __n)
+      { return __a.allocate(__n); }
+
+      /**
+       *  @brief  Allocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __n  The number of objects to allocate space for.
+       *  @param  __hint Aid to locality.
+       *  @return Memory of suitable size and alignment for @a n objects
+       *          of type @c value_type
+       *
+       *  Returns <tt> a.allocate(n, hint) </tt>
+      */
+      static pointer
+      allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
+      { return __a.allocate(__n, __hint); }
+
+      /**
+       *  @brief  Deallocate memory.
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to the memory to deallocate.
+       *  @param  __n  The number of objects space was allocated for.
+       *
+       *  Calls <tt> a.deallocate(p, n) </tt>
+      */
+      static void
+      deallocate(allocator_type& __a, pointer __p, size_type __n)
+      { __a.deallocate(__p, __n); }
+
+      /**
+       *  @brief  Construct an object of type @a _Up
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to memory of suitable size and alignment for Tp
+       *  @param  __args Constructor arguments.
+       *
+       *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
+      */
+      template<typename _Up, typename... _Args>
+	static void
+	construct(allocator_type& __a, _Up* __p, _Args&&... __args)
+	{ __a.construct(__p, std::forward<_Args>(__args)...); }
+
+      /**
+       *  @brief  Destroy an object of type @a _Up
+       *  @param  __a  An allocator.
+       *  @param  __p  Pointer to the object to destroy
+       *
+       *  Calls @c __a.destroy(__p).
+      */
+      template<typename _Up>
+	static void
+	destroy(allocator_type& __a, _Up* __p)
+	{ __a.destroy(__p); }
+
+      /**
+       *  @brief  The maximum supported allocation size
+       *  @param  __a  An allocator.
+       *  @return @c __a.max_size()
+      */
+      static size_type
+      max_size(const allocator_type& __a) noexcept
+      { return __a.max_size(); }
+
+      /**
+       *  @brief  Obtain an allocator to use when copying a container.
+       *  @param  __rhs  An allocator.
+       *  @return @c __rhs
+      */
+      static allocator_type
+      select_on_container_copy_construction(const allocator_type& __rhs)
+      { return __rhs; }
+    };
+
+
   template<typename _Alloc>
     inline void
     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
index 1509fdd..2dc3b0c 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
@@ -51,6 +51,14 @@ namespace std
         allocated = false;
       }
 
+      template<typename _Up, typename... _Args>
+        void construct(_Up* __p, _Args&&... __args)
+        { ::new(__p) _Up(std::forward<_Args>(__args)...); }
+
+      template<typename _Up>
+        void destroy(_Up* __p)
+        { __p->~_Up(); }
+
       static char storage[sizeof(spcd)];
       static bool allocated;
     };
