From: Jonathan Wakely Date: Tue, 8 Oct 2013 12:33:37 +0000 (+0000) Subject: re PR libstdc++/58659 (Construction of shared_ptr from unique_ptr mismatches new... X-Git-Tag: releases/gcc-4.9.0~3682 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=61bf02e007ceaaa81f92a9e10372303816955ba5;p=thirdparty%2Fgcc.git re PR libstdc++/58659 (Construction of shared_ptr from unique_ptr mismatches new/delete and std::allocator for __shared_ptr_count) 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&&): 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. From-SVN: r203274 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4d6906d5ef4f..af3648ad0c06 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2013-10-08 Jonathan Wakely + + 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&&): 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. + 2013-10-08 Tim Shen * include/bits/regex_executor.h: Add _TodoList class. diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h index f4bff77eabe1..911dd928c0b4 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 - __shared_count(_Ptr __p, _Deleter __d) : _M_pi(0) - { - // The allocator's value_type doesn't matter, will rebind it anyway. - typedef std::allocator _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()) + { } template __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 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::value, + reference_wrapper::type>, + _Del>::type; + using _Sp_cd_type + = _Sp_counted_deleter<_Ptr, _Del2, allocator, _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 - static _Sp_counted_base<_Lp>* - _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, - typename std::enable_if::value>::type* = 0) - { - typedef typename unique_ptr<_Tp, _Del>::pointer _Ptr; - return new _Sp_counted_deleter<_Ptr, _Del, std::allocator, - _Lp>(__r.get(), __r.get_deleter()); - } - - template - static _Sp_counted_base<_Lp>* - _S_create_from_up(std::unique_ptr<_Tp, _Del>&& __r, - typename std::enable_if::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, - _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 b6d1009d8844..fd2a677e0c7b 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 p1(px); // { dg-error "here" } - // { dg-error "incomplete" "" { target *-*-* } 807 } + // { dg-error "incomplete" "" { target *-*-* } 778 } std::shared_ptr 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 000000000000..5e7c730e3ee6 --- /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 +// . + +#include +#include + +struct X { }; + +using spcd = std::_Sp_counted_deleter, +std::allocator, std::__default_lock_policy>; + +namespace std +{ + template<> + struct allocator + { + using value_type = spcd; + + allocator() = default; + + template + allocator(const allocator&) { } + + value_type* allocate(size_t n) + { + if (n != 1) + throw bad_alloc(); + allocated = true; + return static_cast((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::storage[]; + bool allocator::allocated = false; +} + +int main() +{ + std::shared_ptr s( std::unique_ptr(new X) ); + VERIFY( std::allocator::allocated ); + s.reset(); + VERIFY( !std::allocator::allocated ); +}