From 1f069142c7eda3b10138dfc15aa158a18d17cedf Mon Sep 17 00:00:00 2001
From: Jonathan Wakely <jwakely.gcc@gmail.com>
Date: Thu, 14 Mar 2013 23:28:11 +0000
Subject: [PATCH] re PR libstdc++/56613 (map::operator[](key_type&&) fails with custom allocator)

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.

From-SVN: r196666
---
 libstdc++-v3/ChangeLog                            |  7 +++++++
 libstdc++-v3/include/bits/stl_tree.h              |  8 ++++++--
 libstdc++-v3/testsuite/23_containers/map/56613.cc | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 libstdc++-v3/testsuite/23_containers/map/56613.cc

diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index fd4b2f9..65ed5fc 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,10 @@
+2013-03-14  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+	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.
+
 2013-03-13  Benjamin Kosnik  <bkoz@redhat.com>
 
 	* doc/html/*: Regenerate.
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];
+}
--
libgit2 0.26.0