[patch] fix libstdc++/58659

Jonathan Wakely jwakely.gcc@gmail.com
Tue Oct 8 12:33:00 GMT 2013


        PR libstdc++/58659
        * include/bits/shared_ptr_base.h (__shared_count::__shared_count(P,D)):
        Delegate to constructor taking allocator.
        (__shared_count::_S_create_from_up): Inline into ...
        (__shared_count::__shared_count(unique_ptr<Y,D>&&): Here. Use
        std::conditional instead of constrained overloads. Allocate memory
        using the allocator type that will be used for deallocation.
        * testsuite/20_util/shared_ptr/cons/58659.cc: New.
        * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust.

Tested x86_64-linux, committed to trunk.
-------------- next part --------------
commit a6857ab59da2f7001495982dbcc2b58adcbe84e5
Author: Jonathan Wakely <jwakely.gcc@gmail.com>
Date:   Tue Oct 8 01:02:19 2013 +0100

    	PR libstdc++/58659
    	* include/bits/shared_ptr_base.h (__shared_count::__shared_count(P,D)):
    	Delegate to constructor taking allocator.
    	(__shared_count::_S_create_from_up): Inline into ...
    	(__shared_count::__shared_count(unique_ptr<Y,D>&&): Here. Use
    	std::conditional instead of constrained overloads. Allocate memory
    	using the allocator type that will be used for deallocation.
    	* testsuite/20_util/shared_ptr/cons/58659.cc: New.
    	* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust.

diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index f4bff77..911dd92 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -495,29 +495,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
 
       template<typename _Ptr, typename _Deleter>
-	__shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
-	{
-	  // The allocator's value_type doesn't matter, will rebind it anyway.
-	  typedef std::allocator<int> _Alloc;
-	  typedef _Sp_counted_deleter<_Ptr, _Deleter, _Alloc, _Lp> _Sp_cd_type;
-	  typedef typename allocator_traits<_Alloc>::template
-	    rebind_traits<_Sp_cd_type> _Alloc_traits;
-	  typename _Alloc_traits::allocator_type __a;
-	  _Sp_cd_type* __mem = 0;
-	  __try
-	    {
-	      __mem = _Alloc_traits::allocate(__a, 1);
-	      _Alloc_traits::construct(__a, __mem, __p, std::move(__d));
-	      _M_pi = __mem;
-	    }
-	  __catch(...)
-	    {
-	      __d(__p); // Call _Deleter on __p.
-	      if (__mem)
-	        _Alloc_traits::deallocate(__a, __mem, 1);
-	      __throw_exception_again;
-	    }
-	}
+	__shared_count(_Ptr __p, _Deleter __d)
+	: __shared_count(__p, std::move(__d), allocator<void>())
+	{ }
 
       template<typename _Ptr, typename _Deleter, typename _Alloc>
 	__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
@@ -576,16 +556,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
       template<typename _Tp, typename _Del>
         explicit
-	__shared_count(std::unique_ptr<_Tp, _Del>&& __r)
-	: _M_pi(_S_create_from_up(std::move(__r)))
-	{ __r.release(); }
+	__shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
+	{
+	  using _Ptr = typename unique_ptr<_Tp, _Del>::pointer;
+	  using _Del2 = typename conditional<is_reference<_Del>::value,
+	      reference_wrapper<typename remove_reference<_Del>::type>,
+	      _Del>::type;
+	  using _Sp_cd_type
+	    = _Sp_counted_deleter<_Ptr, _Del2, allocator<void>, _Lp>;
+	  using _Alloc = allocator<_Sp_cd_type>;
+	  using _Alloc_traits = allocator_traits<_Alloc>;
+	  _Alloc __a;
+	  _Sp_cd_type* __mem = _Alloc_traits::allocate(__a, 1);
+	  _Alloc_traits::construct(__a, __mem, __r.release(),
+				   __r.get_deleter());  // non-throwing
+	  _M_pi = __mem;
+	}
 
       // Throw bad_weak_ptr when __r._M_get_use_count() == 0.
       explicit __shared_count(const __weak_count<_Lp>& __r);
 
       ~__shared_count() noexcept
       {
-	if (_M_pi != 0)
+	if (_M_pi != nullptr)
 	  _M_pi->_M_release();
       }
 
@@ -647,28 +640,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     private:
       friend class __weak_count<_Lp>;
 
-      template<typename _Tp, typename _Del>
-	static _Sp_counted_base<_Lp>*
-	_S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
-	  typename std::enable_if<!std::is_reference<_Del>::value>::type* = 0)
-	{
-	  typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr;
-	  return new _Sp_counted_deleter<_Ptr, _Del, std::allocator<void>,
-	    _Lp>(__r.get(), __r.get_deleter());
-	}
-
-      template<typename _Tp, typename _Del>
-	static _Sp_counted_base<_Lp>*
-	_S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r,
-	  typename std::enable_if<std::is_reference<_Del>::value>::type* = 0)
-	{
-	  typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr;
-	  typedef typename std::remove_reference<_Del>::type _Del1;
-	  typedef std::reference_wrapper<_Del1> _Del2;
-	  return new _Sp_counted_deleter<_Ptr, _Del2, std::allocator<void>,
-	    _Lp>(__r.get(), std::ref(__r.get_deleter()));
-	}
-
       _Sp_counted_base<_Lp>*  _M_pi;
     };
 
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
index b6d1009..fd2a677 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc
@@ -32,7 +32,7 @@ void test01()
 {
   X* px = 0;
   std::shared_ptr<X> p1(px);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 807 }
+  // { dg-error "incomplete" "" { target *-*-* } 778 }
 
   std::shared_ptr<X> p9(ap());  // { dg-error "here" }
   // { dg-error "incomplete" "" { target *-*-* } 307 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
new file mode 100644
index 0000000..5e7c730
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc
@@ -0,0 +1,69 @@
+// { dg-options "-std=gnu++11" }
+
+// 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 <memory>
+#include <testsuite_hooks.h>
+
+struct X { };
+
+using spcd = std::_Sp_counted_deleter<X*, std::default_delete<X>,
+std::allocator<void>, std::__default_lock_policy>;
+
+namespace std
+{
+  template<>
+    struct allocator<spcd>
+    {
+      using value_type = spcd;
+
+      allocator() = default;
+
+      template<typename U>
+        allocator(const allocator<U>&) { }
+
+      value_type* allocate(size_t n)
+      {
+        if (n != 1)
+          throw bad_alloc();
+        allocated = true;
+        return static_cast<value_type*>((void*)(storage));
+      }
+
+      void deallocate(value_type* p, size_t n)
+      {
+        if (n != 1 || p != (void*)storage || !allocated)
+          abort();
+        allocated = false;
+      }
+
+      static char storage[sizeof(spcd)];
+      static bool allocated;
+    };
+
+  char allocator<spcd>::storage[];
+  bool allocator<spcd>::allocated = false;
+}
+
+int main()
+{
+  std::shared_ptr<X> s( std::unique_ptr<X>(new X) );
+  VERIFY( std::allocator<spcd>::allocated );
+  s.reset();
+  VERIFY( !std::allocator<spcd>::allocated );
+}


More information about the Gcc-patches mailing list