mirror of git://gcc.gnu.org/git/gcc.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<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
This commit is contained in:
parent
481d1b8153
commit
61bf02e007
|
|
@ -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>
|
2013-10-08 Tim Shen <timshen91@gmail.com>
|
||||||
|
|
||||||
* include/bits/regex_executor.h: Add _TodoList class.
|
* include/bits/regex_executor.h: Add _TodoList class.
|
||||||
|
|
|
||||||
|
|
@ -495,29 +495,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Ptr, typename _Deleter>
|
template<typename _Ptr, typename _Deleter>
|
||||||
__shared_count(_Ptr __p, _Deleter __d) : _M_pi(0)
|
__shared_count(_Ptr __p, _Deleter __d)
|
||||||
{
|
: __shared_count(__p, std::move(__d), allocator<void>())
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename _Ptr, typename _Deleter, typename _Alloc>
|
template<typename _Ptr, typename _Deleter, typename _Alloc>
|
||||||
__shared_count(_Ptr __p, _Deleter __d, _Alloc __a) : _M_pi(0)
|
__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.
|
// Special case for unique_ptr<_Tp,_Del> to provide the strong guarantee.
|
||||||
template<typename _Tp, typename _Del>
|
template<typename _Tp, typename _Del>
|
||||||
explicit
|
explicit
|
||||||
__shared_count(std::unique_ptr<_Tp, _Del>&& __r)
|
__shared_count(std::unique_ptr<_Tp, _Del>&& __r) : _M_pi(0)
|
||||||
: _M_pi(_S_create_from_up(std::move(__r)))
|
{
|
||||||
{ __r.release(); }
|
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.
|
// Throw bad_weak_ptr when __r._M_get_use_count() == 0.
|
||||||
explicit __shared_count(const __weak_count<_Lp>& __r);
|
explicit __shared_count(const __weak_count<_Lp>& __r);
|
||||||
|
|
||||||
~__shared_count() noexcept
|
~__shared_count() noexcept
|
||||||
{
|
{
|
||||||
if (_M_pi != 0)
|
if (_M_pi != nullptr)
|
||||||
_M_pi->_M_release();
|
_M_pi->_M_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -647,28 +640,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
private:
|
private:
|
||||||
friend class __weak_count<_Lp>;
|
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;
|
_Sp_counted_base<_Lp>* _M_pi;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ void test01()
|
||||||
{
|
{
|
||||||
X* px = 0;
|
X* px = 0;
|
||||||
std::shared_ptr<X> p1(px); // { dg-error "here" }
|
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" }
|
std::shared_ptr<X> p9(ap()); // { dg-error "here" }
|
||||||
// { dg-error "incomplete" "" { target *-*-* } 307 }
|
// { dg-error "incomplete" "" { target *-*-* } 307 }
|
||||||
|
|
|
||||||
|
|
@ -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 );
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue