Patchwork fix libstdc++/56613

login
register
mail settings
Submitter Jonathan Wakely
Date March 14, 2013, 11:28 p.m.
Message ID <CAH6eHdTq8g3GZhWoLnE00EhPXo8MpVsgCB4eaG8XAJrb4_Z42w@mail.gmail.com>
Download mbox | patch
Permalink /patch/227829/
State New
Headers show

Comments

Jonathan Wakely - March 14, 2013, 11:28 p.m.
This fixes a regression. Technically we shouldn't call construct() for
the node, only for the value within it, but I plan to fix that for
4.9, this just restores the previous behaviour when using a type
meeting the C++03 Allocator requirements.

        PR libstdc++/56613
        * include/bits/stl_tree.h (_Rb_tree::_M_create_node): Use
        allocator_traits instead of calling construct directly.
        * testsuite/23_containers/map/56613.cc: New.


Tested x86_64-linux, committed to trunk.
commit 655eef17cd38d23d7c5ad34137224d53f7315811
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Thu Mar 14 01:40:13 2013 +0000

    	PR libstdc++/56613
    	* include/bits/stl_tree.h (_Rb_tree::_M_create_node): Use
    	allocator_traits instead of calling construct directly.
    	* testsuite/23_containers/map/56613.cc: New.

Patch

diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 59883fc..cb5a8ef 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -62,6 +62,9 @@ 
 #include <bits/allocator.h>
 #include <bits/stl_function.h>
 #include <bits/cpp_type_traits.h>
+#if __cplusplus >= 201103L
+#include <bits/alloc_traits.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -400,8 +403,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  _Link_type __tmp = _M_get_node();
 	  __try
 	    {
-	      _M_get_Node_allocator().construct(__tmp,
-					     std::forward<_Args>(__args)...);
+	      allocator_traits<_Node_allocator>::
+		construct(_M_get_Node_allocator(), __tmp,
+			  std::forward<_Args>(__args)...);
 	    }
 	  __catch(...)
 	    {
diff --git a/libstdc++-v3/testsuite/23_containers/map/56613.cc b/libstdc++-v3/testsuite/23_containers/map/56613.cc
new file mode 100644
index 0000000..9843359
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/map/56613.cc
@@ -0,0 +1,74 @@ 
+// -*- C++ -*-
+
+// Copyright (C) 2013 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 <testsuite_hooks.h>
+#include <map>
+
+// { dg-do compile }
+// { dg-options "-std=gnu++11" }
+
+// libstdc++/56613
+#include <map>
+
+// A conforming C++03 allocator, should still work in C++11 mode.
+template<typename T>
+struct alloc
+{
+    typedef T value_type;
+    typedef T* pointer;
+    typedef const T* const_pointer;
+    typedef T& reference;
+    typedef const T& const_reference;
+    typedef unsigned size_type;
+    typedef int difference_type;
+
+    template<typename U>
+        struct rebind {
+            typedef alloc<U> other;
+        };
+
+    alloc() { }
+    template<typename U>
+        alloc(const alloc<U>&) { }
+
+    pointer allocate(size_type n, const void* = 0) { return
+std::allocator<T>().allocate(n); }
+    void deallocate(pointer p, size_type n) { std::allocator<T>().deallocate(p,
+n); }
+
+    size_type max_size() const { return -1; }
+
+    void construct(pointer p, const T& t) { new ((void*) p) T(t); }
+    void destroy(pointer p) { p->~T(); }
+
+    pointer address(reference x) const throw() { return &x; }
+    const_pointer address(const_reference x) const throw() { return &x; }
+};
+
+template<typename T, typename U>
+bool operator==(alloc<T>, alloc<U>) { return true; }
+
+template<typename T, typename U>
+bool operator!=(alloc<T>, alloc<U>) { return false; }
+
+int main()
+{
+  std::map<int, int, std::less<int>, alloc<int> > m;
+  m[1];
+}