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....@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.

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];
+}

Reply via email to