mirror of git://gcc.gnu.org/git/gcc.git
Implement resolutions of LWG 2399, 2400 and 2401.
* include/bits/shared_ptr.h (shared_ptr, weak_ptr): Define _Convertible alias template to simplify constraints. (shared_ptr(unique_ptr<TD>&&)): Constrain (LWG 2399). * include/bits/shared_ptr_base.h: Likewise. (_Sp_counted_deleter::_M_get_deleter()): Use addressof (LWG 2400). * include/std/functional (function::operator=(nullptr_t)): Add noexcept (LWG 2401). * testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error. * testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error. From-SVN: r217442
This commit is contained in:
parent
3e147937ea
commit
d8af84e67b
|
|
@ -7,6 +7,16 @@
|
||||||
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
|
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
|
||||||
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.
|
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.
|
||||||
|
|
||||||
|
* include/bits/shared_ptr.h (shared_ptr, weak_ptr): Define
|
||||||
|
_Convertible alias template to simplify constraints.
|
||||||
|
(shared_ptr(unique_ptr<TD>&&)): Constrain (LWG 2399).
|
||||||
|
* include/bits/shared_ptr_base.h: Likewise.
|
||||||
|
(_Sp_counted_deleter::_M_get_deleter()): Use addressof (LWG 2400).
|
||||||
|
* include/std/functional (function::operator=(nullptr_t)): Add
|
||||||
|
noexcept (LWG 2401).
|
||||||
|
* testsuite/20_util/shared_ptr/cons/43820_neg.cc: Adjust dg-error.
|
||||||
|
* testsuite/20_util/shared_ptr/cons/void_neg.cc: Adjust dg-error.
|
||||||
|
|
||||||
2014-11-12 Jonathan Wakely <jwakely@redhat.com>
|
2014-11-12 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
PR c++/33911
|
PR c++/33911
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
class shared_ptr : public __shared_ptr<_Tp>
|
class shared_ptr : public __shared_ptr<_Tp>
|
||||||
{
|
{
|
||||||
|
template<typename _Ptr>
|
||||||
|
using _Convertible
|
||||||
|
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Construct an empty %shared_ptr.
|
* @brief Construct an empty %shared_ptr.
|
||||||
|
|
@ -213,8 +217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
* @param __r A %shared_ptr.
|
* @param __r A %shared_ptr.
|
||||||
* @post get() == __r.get() && use_count() == __r.use_count()
|
* @post get() == __r.get() && use_count() == __r.use_count()
|
||||||
*/
|
*/
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
|
shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
|
||||||
: __shared_ptr<_Tp>(__r) { }
|
: __shared_ptr<_Tp>(__r) { }
|
||||||
|
|
||||||
|
|
@ -231,8 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
* @param __r A %shared_ptr rvalue.
|
* @param __r A %shared_ptr rvalue.
|
||||||
* @post *this contains the old value of @a __r, @a __r is empty.
|
* @post *this contains the old value of @a __r, @a __r is empty.
|
||||||
*/
|
*/
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
|
shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
|
||||||
: __shared_ptr<_Tp>(std::move(__r)) { }
|
: __shared_ptr<_Tp>(std::move(__r)) { }
|
||||||
|
|
||||||
|
|
@ -253,7 +255,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
shared_ptr(std::auto_ptr<_Tp1>&& __r);
|
shared_ptr(std::auto_ptr<_Tp1>&& __r);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename _Tp1, typename _Del>
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||||
|
// 2399. shared_ptr's constructor from unique_ptr should be constrained
|
||||||
|
template<typename _Tp1, typename _Del, typename
|
||||||
|
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
|
||||||
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
||||||
: __shared_ptr<_Tp>(std::move(__r)) { }
|
: __shared_ptr<_Tp>(std::move(__r)) { }
|
||||||
|
|
||||||
|
|
@ -464,25 +469,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
class weak_ptr : public __weak_ptr<_Tp>
|
class weak_ptr : public __weak_ptr<_Tp>
|
||||||
{
|
{
|
||||||
|
template<typename _Ptr>
|
||||||
|
using _Convertible
|
||||||
|
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
constexpr weak_ptr() noexcept = default;
|
constexpr weak_ptr() noexcept = default;
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
|
weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
|
||||||
: __weak_ptr<_Tp>(__r) { }
|
: __weak_ptr<_Tp>(__r) { }
|
||||||
|
|
||||||
weak_ptr(const weak_ptr&) noexcept = default;
|
weak_ptr(const weak_ptr&) noexcept = default;
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
|
weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
|
||||||
: __weak_ptr<_Tp>(__r) { }
|
: __weak_ptr<_Tp>(__r) { }
|
||||||
|
|
||||||
weak_ptr(weak_ptr&&) noexcept = default;
|
weak_ptr(weak_ptr&&) noexcept = default;
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
|
weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
|
||||||
: __weak_ptr<_Tp>(std::move(__r)) { }
|
: __weak_ptr<_Tp>(std::move(__r)) { }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
_M_get_deleter(const std::type_info& __ti) noexcept
|
_M_get_deleter(const std::type_info& __ti) noexcept
|
||||||
{
|
{
|
||||||
#ifdef __GXX_RTTI
|
#ifdef __GXX_RTTI
|
||||||
return __ti == typeid(_Deleter) ? &_M_impl._M_del() : nullptr;
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||||
|
// 2400. shared_ptr's get_deleter() should use addressof()
|
||||||
|
return __ti == typeid(_Deleter)
|
||||||
|
? std::__addressof(_M_impl._M_del())
|
||||||
|
: nullptr;
|
||||||
#else
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -862,6 +866,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp, _Lock_policy _Lp>
|
template<typename _Tp, _Lock_policy _Lp>
|
||||||
class __shared_ptr
|
class __shared_ptr
|
||||||
{
|
{
|
||||||
|
template<typename _Ptr>
|
||||||
|
using _Convertible
|
||||||
|
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
|
|
||||||
|
|
@ -916,8 +924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__shared_ptr& operator=(const __shared_ptr&) noexcept = default;
|
__shared_ptr& operator=(const __shared_ptr&) noexcept = default;
|
||||||
~__shared_ptr() = default;
|
~__shared_ptr() = default;
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
|
__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
|
||||||
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
|
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -929,8 +936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
__r._M_ptr = 0;
|
__r._M_ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
|
__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
|
||||||
: _M_ptr(__r._M_ptr), _M_refcount()
|
: _M_ptr(__r._M_ptr), _M_refcount()
|
||||||
{
|
{
|
||||||
|
|
@ -950,7 +956,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
}
|
}
|
||||||
|
|
||||||
// If an exception is thrown this constructor has no effect.
|
// If an exception is thrown this constructor has no effect.
|
||||||
template<typename _Tp1, typename _Del>
|
template<typename _Tp1, typename _Del, typename
|
||||||
|
= _Convertible<typename unique_ptr<_Tp1, _Del>::pointer>>
|
||||||
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
__shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
|
||||||
: _M_ptr(__r.get()), _M_refcount()
|
: _M_ptr(__r.get()), _M_refcount()
|
||||||
{
|
{
|
||||||
|
|
@ -1331,6 +1338,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
template<typename _Tp, _Lock_policy _Lp>
|
template<typename _Tp, _Lock_policy _Lp>
|
||||||
class __weak_ptr
|
class __weak_ptr
|
||||||
{
|
{
|
||||||
|
template<typename _Ptr>
|
||||||
|
using _Convertible
|
||||||
|
= typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef _Tp element_type;
|
typedef _Tp element_type;
|
||||||
|
|
||||||
|
|
@ -1356,14 +1367,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
//
|
//
|
||||||
// It is not possible to avoid spurious access violations since
|
// It is not possible to avoid spurious access violations since
|
||||||
// in multithreaded programs __r._M_ptr may be invalidated at any point.
|
// in multithreaded programs __r._M_ptr may be invalidated at any point.
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
|
__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
|
||||||
: _M_refcount(__r._M_refcount)
|
: _M_refcount(__r._M_refcount)
|
||||||
{ _M_ptr = __r.lock().get(); }
|
{ _M_ptr = __r.lock().get(); }
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
|
__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
|
||||||
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
|
: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
|
||||||
{ }
|
{ }
|
||||||
|
|
@ -1372,8 +1381,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
: _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
|
: _M_ptr(__r._M_ptr), _M_refcount(std::move(__r._M_refcount))
|
||||||
{ __r._M_ptr = nullptr; }
|
{ __r._M_ptr = nullptr; }
|
||||||
|
|
||||||
template<typename _Tp1, typename = typename
|
template<typename _Tp1, typename = _Convertible<_Tp1*>>
|
||||||
std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
|
|
||||||
__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
|
__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
|
||||||
: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
|
: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
|
||||||
{ __r._M_ptr = nullptr; }
|
{ __r._M_ptr = nullptr; }
|
||||||
|
|
|
||||||
|
|
@ -2102,7 +2102,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
|
||||||
* The target of @c *this is deallocated, leaving it empty.
|
* The target of @c *this is deallocated, leaving it empty.
|
||||||
*/
|
*/
|
||||||
function&
|
function&
|
||||||
operator=(nullptr_t)
|
operator=(nullptr_t) noexcept
|
||||||
{
|
{
|
||||||
if (_M_manager)
|
if (_M_manager)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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 *-*-* } 878 }
|
// { dg-error "incomplete" "" { target *-*-* } 886 }
|
||||||
|
|
||||||
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 *-*-* } 877 }
|
// { dg-error "incomplete" "" { target *-*-* } 885 }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue