mirror of git://gcc.gnu.org/git/gcc.git
re PR libstdc++/59656 (weak_ptr::lock function crashes when compiling with -fno-exceptions flag)
2014-01-28 Jonathan Wakely <jwakely@redhat.com> Kyle Lippincott <spectral@google.com> PR libstdc++/59656 * include/bits/shared_ptr.h (shared_ptr): Add new non-throwing constructor and grant friendship to weak_ptr. (weak_ptr::lock()): Use new constructor. * include/bits/shared_ptr_base.h (_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function and define specializations. (__shared_count): Add new non-throwing constructor. (__shared_ptr): Add new non-throwing constructor and grant friendship to __weak_ptr. (__weak_ptr::lock()): Use new constructor. * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise. Co-Authored-By: Kyle Lippincott <spectral@google.com> From-SVN: r207180
This commit is contained in:
parent
9ec2d2c168
commit
156b60e0b9
|
|
@ -1,3 +1,20 @@
|
||||||
|
2014-01-28 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
Kyle Lippincott <spectral@google.com>
|
||||||
|
|
||||||
|
PR libstdc++/59656
|
||||||
|
* include/bits/shared_ptr.h (shared_ptr): Add new non-throwing
|
||||||
|
constructor and grant friendship to weak_ptr.
|
||||||
|
(weak_ptr::lock()): Use new constructor.
|
||||||
|
* include/bits/shared_ptr_base.h
|
||||||
|
(_Sp_counted_base::_M_add_ref_lock_nothrow()): Declare new function
|
||||||
|
and define specializations.
|
||||||
|
(__shared_count): Add new non-throwing constructor.
|
||||||
|
(__shared_ptr): Add new non-throwing constructor and grant friendship
|
||||||
|
to __weak_ptr.
|
||||||
|
(__weak_ptr::lock()): Use new constructor.
|
||||||
|
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
|
||||||
|
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Likewise.
|
||||||
|
|
||||||
2014-01-27 Jonathan Wakely <jwakely@redhat.com>
|
2014-01-27 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
PR libstdc++/59215
|
PR libstdc++/59215
|
||||||
|
|
|
||||||
|
|
@ -319,6 +319,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp1, typename _Alloc, typename... _Args>
|
template<typename _Tp1, typename _Alloc, typename... _Args>
|
||||||
friend shared_ptr<_Tp1>
|
friend shared_ptr<_Tp1>
|
||||||
allocate_shared(const _Alloc& __a, _Args&&... __args);
|
allocate_shared(const _Alloc& __a, _Args&&... __args);
|
||||||
|
|
||||||
|
// This constructor is non-standard, it is used by weak_ptr::lock().
|
||||||
|
shared_ptr(const weak_ptr<_Tp>& __r, std::nothrow_t)
|
||||||
|
: __shared_ptr<_Tp>(__r, std::nothrow) { }
|
||||||
|
|
||||||
|
friend class weak_ptr<_Tp>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 20.7.2.2.7 shared_ptr comparisons
|
// 20.7.2.2.7 shared_ptr comparisons
|
||||||
|
|
@ -492,23 +498,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
shared_ptr<_Tp>
|
shared_ptr<_Tp>
|
||||||
lock() const noexcept
|
lock() const noexcept
|
||||||
{
|
{ return shared_ptr<_Tp>(*this, std::nothrow); }
|
||||||
#ifdef __GTHREADS
|
|
||||||
if (this->expired())
|
|
||||||
return shared_ptr<_Tp>();
|
|
||||||
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
return shared_ptr<_Tp>(*this);
|
|
||||||
}
|
|
||||||
__catch(const bad_weak_ptr&)
|
|
||||||
{
|
|
||||||
return shared_ptr<_Tp>();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 20.7.2.3.6 weak_ptr specialized algorithms.
|
// 20.7.2.3.6 weak_ptr specialized algorithms.
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
void
|
void
|
||||||
_M_add_ref_lock();
|
_M_add_ref_lock();
|
||||||
|
|
||||||
|
bool
|
||||||
|
_M_add_ref_lock_nothrow();
|
||||||
|
|
||||||
void
|
void
|
||||||
_M_release() noexcept
|
_M_release() noexcept
|
||||||
{
|
{
|
||||||
|
|
@ -246,6 +249,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__ATOMIC_RELAXED));
|
__ATOMIC_RELAXED));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
_Sp_counted_base<_S_single>::
|
||||||
|
_M_add_ref_lock_nothrow()
|
||||||
|
{
|
||||||
|
if (_M_use_count == 0)
|
||||||
|
return false;
|
||||||
|
++_M_use_count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
_Sp_counted_base<_S_mutex>::
|
||||||
|
_M_add_ref_lock_nothrow()
|
||||||
|
{
|
||||||
|
__gnu_cxx::__scoped_lock sentry(*this);
|
||||||
|
if (__gnu_cxx::__exchange_and_add_dispatch(&_M_use_count, 1) == 0)
|
||||||
|
{
|
||||||
|
_M_use_count = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool
|
||||||
|
_Sp_counted_base<_S_atomic>::
|
||||||
|
_M_add_ref_lock_nothrow()
|
||||||
|
{
|
||||||
|
// Perform lock-free add-if-not-zero operation.
|
||||||
|
_Atomic_word __count = _M_get_use_count();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (__count == 0)
|
||||||
|
return false;
|
||||||
|
// Replace the current counter value with the old value + 1, as
|
||||||
|
// long as it's not changed meanwhile.
|
||||||
|
}
|
||||||
|
while (!__atomic_compare_exchange_n(&_M_use_count, &__count, __count + 1,
|
||||||
|
true, __ATOMIC_ACQ_REL,
|
||||||
|
__ATOMIC_RELAXED));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
inline void
|
inline void
|
||||||
_Sp_counted_base<_S_single>::_M_add_ref_copy()
|
_Sp_counted_base<_S_single>::_M_add_ref_copy()
|
||||||
|
|
@ -609,6 +657,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
// 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);
|
||||||
|
|
||||||
|
// Does not throw if __r._M_get_use_count() == 0, caller must check.
|
||||||
|
explicit __shared_count(const __weak_count<_Lp>& __r, std::nothrow_t);
|
||||||
|
|
||||||
~__shared_count() noexcept
|
~__shared_count() noexcept
|
||||||
{
|
{
|
||||||
if (_M_pi != nullptr)
|
if (_M_pi != nullptr)
|
||||||
|
|
@ -761,15 +812,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
// Now that __weak_count is defined we can define this constructor:
|
// Now that __weak_count is defined we can define this constructor:
|
||||||
template<_Lock_policy _Lp>
|
template<_Lock_policy _Lp>
|
||||||
inline __shared_count<_Lp>:: __shared_count(const __weak_count<_Lp>& __r)
|
inline
|
||||||
|
__shared_count<_Lp>::__shared_count(const __weak_count<_Lp>& __r)
|
||||||
: _M_pi(__r._M_pi)
|
: _M_pi(__r._M_pi)
|
||||||
{
|
{
|
||||||
if (_M_pi != 0)
|
if (_M_pi != nullptr)
|
||||||
_M_pi->_M_add_ref_lock();
|
_M_pi->_M_add_ref_lock();
|
||||||
else
|
else
|
||||||
__throw_bad_weak_ptr();
|
__throw_bad_weak_ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now that __weak_count is defined we can define this constructor:
|
||||||
|
template<_Lock_policy _Lp>
|
||||||
|
inline
|
||||||
|
__shared_count<_Lp>::
|
||||||
|
__shared_count(const __weak_count<_Lp>& __r, std::nothrow_t)
|
||||||
|
: _M_pi(__r._M_pi)
|
||||||
|
{
|
||||||
|
if (_M_pi != nullptr)
|
||||||
|
if (!_M_pi->_M_add_ref_lock_nothrow())
|
||||||
|
_M_pi = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// Support for enable_shared_from_this.
|
// Support for enable_shared_from_this.
|
||||||
|
|
||||||
|
|
@ -1077,6 +1140,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
friend __shared_ptr<_Tp1, _Lp1>
|
friend __shared_ptr<_Tp1, _Lp1>
|
||||||
__allocate_shared(const _Alloc& __a, _Args&&... __args);
|
__allocate_shared(const _Alloc& __a, _Args&&... __args);
|
||||||
|
|
||||||
|
// This constructor is used by __weak_ptr::lock() and
|
||||||
|
// shared_ptr::shared_ptr(const weak_ptr&, std::nothrow_t).
|
||||||
|
__shared_ptr(const __weak_ptr<_Tp, _Lp>& __r, std::nothrow_t)
|
||||||
|
: _M_refcount(__r._M_refcount, std::nothrow)
|
||||||
|
{
|
||||||
|
_M_ptr = _M_refcount._M_get_use_count() ? __r._M_ptr : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class __weak_ptr<_Tp, _Lp>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void*
|
void*
|
||||||
_M_get_deleter(const std::type_info& __ti) const noexcept
|
_M_get_deleter(const std::type_info& __ti) const noexcept
|
||||||
|
|
@ -1322,31 +1395,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
|
|
||||||
__shared_ptr<_Tp, _Lp>
|
__shared_ptr<_Tp, _Lp>
|
||||||
lock() const noexcept
|
lock() const noexcept
|
||||||
{
|
{ return __shared_ptr<element_type, _Lp>(*this, std::nothrow); }
|
||||||
#ifdef __GTHREADS
|
|
||||||
// Optimization: avoid throw overhead.
|
|
||||||
if (expired())
|
|
||||||
return __shared_ptr<element_type, _Lp>();
|
|
||||||
|
|
||||||
__try
|
|
||||||
{
|
|
||||||
return __shared_ptr<element_type, _Lp>(*this);
|
|
||||||
}
|
|
||||||
__catch(const bad_weak_ptr&)
|
|
||||||
{
|
|
||||||
// Q: How can we get here?
|
|
||||||
// A: Another thread may have invalidated r after the
|
|
||||||
// use_count test above.
|
|
||||||
return __shared_ptr<element_type, _Lp>();
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
// Optimization: avoid try/catch overhead when single threaded.
|
|
||||||
return expired() ? __shared_ptr<element_type, _Lp>()
|
|
||||||
: __shared_ptr<element_type, _Lp>(*this);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
} // XXX MT
|
|
||||||
|
|
||||||
long
|
long
|
||||||
use_count() const noexcept
|
use_count() const noexcept
|
||||||
|
|
|
||||||
|
|
@ -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 *-*-* } 812 }
|
// { dg-error "incomplete" "" { target *-*-* } 875 }
|
||||||
|
|
||||||
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 }
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,5 @@
|
||||||
void test01()
|
void test01()
|
||||||
{
|
{
|
||||||
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
|
std::shared_ptr<void> p((void*)nullptr); // { dg-error "here" }
|
||||||
// { dg-error "incomplete" "" { target *-*-* } 811 }
|
// { dg-error "incomplete" "" { target *-*-* } 874 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue