Patchwork Fix libstdc++/51626

login
register
mail settings
Submitter Jonathan Wakely
Date Dec. 19, 2011, 10:39 p.m.
Message ID <CAH6eHdTa0crNbvs6RdTMveVT3WEMXPSjbUoWF3F+SfjE-E319A@mail.gmail.com>
Download mbox | patch
Permalink /patch/132329/
State New
Headers show

Comments

Jonathan Wakely - Dec. 19, 2011, 10:39 p.m.
We don't have allocator_traits in 4.6 so this patch adds a test for
whether we can call allocator::construct(p) with a single argument and
calls _Construct(p) if not.

        PR libstdc++/51626
        * include/bits/stl_uninitialized.h (_Construct_default_a): Define
        overloaded functions to conditionally use allocator::construct.
        (_Construct_default_a): Define to dispatch to appropriate
        _Construct_default_a_impl overload.
        (__uninitialized_default_a, __uninitialized_default_n_a): Use
        _Construct_default_a.
        * testsuite/20_util/allocator/51626.cc

Tested x86_64-linux.

I plan to check this in to the 4.6 branch unless anyone has a better
suggestion for fixing the bug.
Jonathan Wakely - Dec. 21, 2011, 6:35 p.m.
On 19 December 2011 22:39, Jonathan Wakely wrote:
> We don't have allocator_traits in 4.6 so this patch adds a test for
> whether we can call allocator::construct(p) with a single argument and
> calls _Construct(p) if not.
>
>        PR libstdc++/51626
>        * include/bits/stl_uninitialized.h (_Construct_default_a): Define
>        overloaded functions to conditionally use allocator::construct.
>        (_Construct_default_a): Define to dispatch to appropriate
>        _Construct_default_a_impl overload.
>        (__uninitialized_default_a, __uninitialized_default_n_a): Use
>        _Construct_default_a.
>        * testsuite/20_util/allocator/51626.cc
>
> Tested x86_64-linux.
>
> I plan to check this in to the 4.6 branch unless anyone has a better
> suggestion for fixing the bug.

I checked it in, with a corrected ChangeLog and updated copyright year
in stl_uninitialized.h

        PR libstdc++/51626
        * include/bits/stl_uninitialized.h (_Construct_default_a_impl): Define
        overloaded functions to conditionally use allocator::construct.
        (_Construct_default_a): Define to dispatch to appropriate
        _Construct_default_a_impl overload.
        (__uninitialized_default_a, __uninitialized_default_n_a): Use
        _Construct_default_a.
        * testsuite/20_util/allocator/51626.cc: New.

Patch

Index: include/bits/stl_uninitialized.h
===================================================================
--- include/bits/stl_uninitialized.h	(revision 182460)
+++ include/bits/stl_uninitialized.h	(working copy)
@@ -530,6 +530,21 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__uninit_default_n(__first, __n);
     }
 
+ template<typename _Tp, typename _Allocator>
+   inline auto
+   _Construct_default_a_impl(_Tp* __ptr, _Allocator& __alloc, void*)
+   -> decltype(__alloc.construct(__ptr))
+   { return __alloc.construct(__ptr); }
+
+  template<typename _Tp, typename _Allocator>
+   inline void
+   _Construct_default_a_impl(_Tp* __ptr, _Allocator& __alloc, ...)
+   { _Construct(__ptr); }
+
+  template<typename _Tp, typename _Allocator>
+   inline void
+   _Construct_default_a(_Tp* __ptr, _Allocator& __alloc)
+   { _Construct_default_a_impl(__ptr, __alloc, nullptr); }
 
   // __uninitialized_default_a
   // Fills [first, last) with std::distance(first, last) default
@@ -544,7 +559,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __try
 	{
 	  for (; __cur != __last; ++__cur)
-	    __alloc.construct(std::__addressof(*__cur));
+	    _Construct_default_a(std::__addressof(*__cur), __alloc);
 	}
       __catch(...)
 	{
@@ -573,7 +588,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __try
 	{
 	  for (; __n > 0; --__n, ++__cur)
-	    __alloc.construct(std::__addressof(*__cur));
+	    _Construct_default_a(std::__addressof(*__cur), __alloc);
 	}
       __catch(...)
 	{
Index: testsuite/20_util/allocator/51626.cc
===================================================================
--- testsuite/20_util/allocator/51626.cc	(revision 0)
+++ testsuite/20_util/allocator/51626.cc	(revision 0)
@@ -0,0 +1,66 @@ 
+// Copyright (C) 2011 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/>.
+
+// { dg-options "-std=gnu++0x" }
+
+#include <memory>
+#include <vector>
+#include <testsuite_hooks.h>
+
+int count = 0;
+
+template <class T>
+  struct allocator98 : std::allocator<T>
+  {
+    template <class U> struct rebind { typedef allocator98<U> other; };
+
+    allocator98() { }
+
+    template <class U> allocator98(const allocator98<U>&) { };
+
+    void construct(T* p, const T& val)
+    {
+      ++count;
+      std::allocator<T>::construct(p, val);
+    }
+  };
+
+template <class T>
+  struct allocator11 : std::allocator<T>
+  {
+    template <class U> struct rebind { typedef allocator11<U> other; };
+
+    allocator11() { }
+
+    template <class U> allocator11(const allocator11<U>&) { };
+
+    template<typename... Args>
+      void construct(T* p, Args&&... args)
+      {
+	++count;
+	std::allocator<T>::construct(p, std::forward<Args>(args)...);
+      }
+  };
+
+int main()
+{
+  std::vector< int, allocator98<int> > v98(1);
+  VERIFY( count == 0 );
+
+  std::vector< int, allocator11<int> > v11(1);
+  VERIFY( count == 1 );
+}