Patchwork fix libstdc++/57263

login
register
mail settings
Submitter Jonathan Wakely
Date June 16, 2013, 5:16 p.m.
Message ID <CAH6eHdQxquv7veEyFTmtYwR39jLNkmRDkiEyVumE4ajbxk7_Ew@mail.gmail.com>
Download mbox | patch
Permalink /patch/251727/
State New
Headers show

Comments

Jonathan Wakely - June 16, 2013, 5:16 p.m.
PR libstdc++/57263
        * include/bits/forward_list.h (_Fwd_list_base): Convert to/from
        allocator's pointer type.
        * include/bits/hashtable.h (_Hashtable): Likewise.
        * testsuite/util/testsuite_allocator.h (CustomPointerAlloc): Add.
        * testsuite/23_containers/forward_list/allocator/ext_ptr.cc: New.
        * testsuite/23_containers/unordered_set/allocator/ext_ptr.cc: New.
        * testsuite/23_containers/vector/allocator/ext_ptr.cc: New.

Tested x86_64-linux, committed to trunk.
commit b4514c0c6f530fbbcc66a478b5ef45263907f1d3
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Wed May 15 01:10:22 2013 +0100

    	PR libstdc++/57263
    	* include/bits/forward_list.h (_Fwd_list_base): Convert to/from
    	allocator's pointer type.
    	* include/bits/hashtable.h (_Hashtable): Likewise.
    	* testsuite/util/testsuite_allocator.h (CustomPointerAlloc): Add.
    	* testsuite/23_containers/forward_list/allocator/ext_ptr.cc: New.
    	* testsuite/23_containers/unordered_set/allocator/ext_ptr.cc: New.
    	* testsuite/23_containers/vector/allocator/ext_ptr.cc: New.

Patch

diff --git a/libstdc++-v3/include/bits/forward_list.h b/libstdc++-v3/include/bits/forward_list.h
index e7c4bdd..c3cee97 100644
--- a/libstdc++-v3/include/bits/forward_list.h
+++ b/libstdc++-v3/include/bits/forward_list.h
@@ -338,7 +338,10 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       _Node*
       _M_get_node()
-      { return _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); }
+      {
+	auto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1);
+	return std::__addressof(*__ptr);
+      }
 
       template<typename... _Args>
         _Node*
@@ -367,7 +370,11 @@  _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
 
       void
       _M_put_node(_Node* __p)
-      { _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); }
+      {
+	typedef typename _Node_alloc_traits::pointer _Ptr;
+	auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p);
+	_Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1);
+      }
 
       _Fwd_list_node_base*
       _M_erase_after(_Fwd_list_node_base* __pos);
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 0ff6e13..8ce264e 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -775,7 +775,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 		 _H1, _H2, _Hash, _RehashPolicy, _Traits>::
       _M_allocate_node(_Args&&... __args)
       {
-	__node_type* __n = _Node_alloc_traits::allocate(_M_node_allocator(), 1);
+	auto __nptr = _Node_alloc_traits::allocate(_M_node_allocator(), 1);
+	__node_type* __n = std::__addressof(*__nptr);
 	__try
 	  {
 	    _Value_alloc_type __a(_M_node_allocator());
@@ -786,7 +787,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  }
 	__catch(...)
 	  {
-	    _Node_alloc_traits::deallocate(_M_node_allocator(), __n, 1);
+	    _Node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1);
 	    __throw_exception_again;
 	  }
       }
@@ -800,10 +801,12 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       _H1, _H2, _Hash, _RehashPolicy, _Traits>::
     _M_deallocate_node(__node_type* __n)
     {
+      typedef typename _Node_alloc_traits::pointer _Ptr;
+      auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n);
       _Value_alloc_type __a(_M_node_allocator());
       _Value_alloc_traits::destroy(__a, __n->_M_valptr());
       __n->~__node_type();
-      _Node_alloc_traits::deallocate(_M_node_allocator(), __n, 1);
+      _Node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1);
     }
 
   template<typename _Key, typename _Value,
@@ -835,7 +838,8 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       _Bucket_alloc_type __alloc(_M_node_allocator());
 
-      __bucket_type* __p = _Bucket_alloc_traits::allocate(__alloc, __n);
+      auto __ptr = _Bucket_alloc_traits::allocate(__alloc, __n);
+      __bucket_type* __p = std::__addressof(*__ptr);
       __builtin_memset(__p, 0, __n * sizeof(__bucket_type));
       return __p;
     }
@@ -849,8 +853,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	       _H1, _H2, _Hash, _RehashPolicy, _Traits>::
     _M_deallocate_buckets(__bucket_type* __bkts, size_type __n)
     {
+      typedef typename _Bucket_alloc_traits::pointer _Ptr;
+      auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts);
       _Bucket_alloc_type __alloc(_M_node_allocator());
-      _Bucket_alloc_traits::deallocate(__alloc, __bkts, __n);
+      _Bucket_alloc_traits::deallocate(__alloc, __ptr, __n);
     }
 
   template<typename _Key, typename _Value,
diff --git a/libstdc++-v3/testsuite/23_containers/forward_list/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/forward_list/allocator/ext_ptr.cc
new file mode 100644
index 0000000..6f3a0ed
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/forward_list/allocator/ext_ptr.cc
@@ -0,0 +1,46 @@ 
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <forward_list>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+bool operator==(const T& l, const T& r) { return l.i == r.i; }
+bool operator<(const T& l, const T& r) { return l.i < r.i; }
+
+using __gnu_test::CustomPointerAlloc;
+
+template class std::forward_list<T, CustomPointerAlloc<T>>;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef CustomPointerAlloc<T> alloc_type;
+  typedef std::forward_list<T, alloc_type> test_type;
+  test_type v;
+  v.push_front(T());
+  VERIFY( ++v.begin() == v.end() );
+}
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/ext_ptr.cc
new file mode 100644
index 0000000..55d9af3
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/unordered_set/allocator/ext_ptr.cc
@@ -0,0 +1,48 @@ 
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <unordered_set>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+bool operator==(const T& l, const T& r) { return l.i == r.i; }
+struct H { std::size_t operator()(const T& t) const noexcept { return t.i; }
+};
+struct E : std::equal_to<T> { };
+
+using __gnu_test::CustomPointerAlloc;
+
+template class std::unordered_set<T, H, E, CustomPointerAlloc<T>>;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef CustomPointerAlloc<T> alloc_type;
+  typedef std::unordered_set<T, H, E, alloc_type> test_type;
+  test_type v;
+  v.insert(T());
+  VERIFY( ++v.begin() == v.end() );
+}
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/23_containers/vector/allocator/ext_ptr.cc b/libstdc++-v3/testsuite/23_containers/vector/allocator/ext_ptr.cc
new file mode 100644
index 0000000..b94a47a
--- /dev/null
+++ b/libstdc++-v3/testsuite/23_containers/vector/allocator/ext_ptr.cc
@@ -0,0 +1,44 @@ 
+// 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/>.
+
+// { dg-options "-std=gnu++11" }
+
+#include <vector>
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+struct T { int i; };
+
+using __gnu_test::CustomPointerAlloc;
+
+template class std::vector<T, CustomPointerAlloc<T>>;
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+  typedef CustomPointerAlloc<T> alloc_type;
+  typedef std::vector<T, alloc_type> test_type;
+  test_type v;
+  v.push_back(T());
+  VERIFY( ++v.begin() == v.end() );
+}
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/util/testsuite_allocator.h b/libstdc++-v3/testsuite/util/testsuite_allocator.h
index 2360274..d569eb0 100644
--- a/libstdc++-v3/testsuite/util/testsuite_allocator.h
+++ b/libstdc++-v3/testsuite/util/testsuite_allocator.h
@@ -28,6 +28,7 @@ 
 
 #include <tr1/unordered_map>
 #include <bits/move.h>
+#include <ext/pointer.h>
 #include <testsuite_hooks.h>
 
 namespace __gnu_test
@@ -488,6 +489,36 @@  namespace __gnu_test
         { typedef ExplicitConsAlloc<Up> other; };
     };
 
+#if __cplusplus >= 201103L
+  template<typename Tp>
+    class CustomPointerAlloc : public std::allocator<Tp>
+    {
+      template<typename Up, typename Sp = __gnu_cxx::_Std_pointer_impl<Up>>
+	using Ptr =  __gnu_cxx::_Pointer_adapter<Sp>;
+
+    public:
+      CustomPointerAlloc() = default;
+
+      template<typename Up>
+        CustomPointerAlloc(const CustomPointerAlloc<Up>&) { }
+
+      template<typename Up>
+        struct rebind
+        { typedef CustomPointerAlloc<Up> other; };
+
+      typedef Ptr<Tp> 		pointer;
+      typedef Ptr<const Tp>	const_pointer;
+      typedef Ptr<void>		void_pointer;
+      typedef Ptr<const void>	const_void_pointer;
+
+      pointer allocate(std::size_t n, pointer = {})
+      { return pointer(std::allocator<Tp>::allocate(n)); }
+
+      void deallocate(pointer p, std::size_t n)
+      { std::allocator<Tp>::deallocate(std::addressof(*p), n); }
+    };
+#endif
+
 } // namespace __gnu_test
 
 #endif // _GLIBCXX_TESTSUITE_ALLOCATOR_H