diff options
author | Jonathan Wakely <jwakely.gcc@gmail.com> | 2013-10-08 12:33:37 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2013-10-08 13:33:37 +0100 |
commit | 61bf02e007ceaaa81f92a9e10372303816955ba5 (patch) | |
tree | 9ae99d30df85db39801dab11898c312ec74fccfe /libstdc++-v3 | |
parent | 481d1b81534c70122187f38c26d6a19db587528f (diff) | |
download | gcc-61bf02e007ceaaa81f92a9e10372303816955ba5.zip gcc-61bf02e007ceaaa81f92a9e10372303816955ba5.tar.gz gcc-61bf02e007ceaaa81f92a9e10372303816955ba5.tar.bz2 |
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<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.
From-SVN: r203274
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 12 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/shared_ptr_base.h | 69 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/shared_ptr/cons/43820_neg.cc | 2 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/shared_ptr/cons/58659.cc | 69 |
4 files changed, 102 insertions, 50 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 4d6906d..af3648a 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2013-10-08 Jonathan Wakely <jwakely.gcc@gmail.com> + + 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. + 2013-10-08 Tim Shen <timshen91@gmail.com> * 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 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 ); +} |