This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] Apply LWG 2399, 2400 and 2401 to std::shared_ptr and std::function


These issues just became DRs in Urbana.

Tested x86_64-linux, committed to trunk.

The other new DRs we need to make changes for are 2212 (to shuffle
some code between headers), 2217 (which I sent an email about earlier)
and 2354 (adding some new insert overloads in RB trees).

commit 5930336c20503e26ed22f8ab5fe81146b31a60e5
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Nov 12 14:21:41 2014 +0000

    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.

diff --git a/libstdc++-v3/include/bits/shared_ptr.h b/libstdc++-v3/include/bits/shared_ptr.h
index c2d56eb..22cb58a 100644
--- a/libstdc++-v3/include/bits/shared_ptr.h
+++ b/libstdc++-v3/include/bits/shared_ptr.h
@@ -92,6 +92,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class shared_ptr : public __shared_ptr<_Tp>
     {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
     public:
       /**
        *  @brief  Construct an empty %shared_ptr.
@@ -213,8 +217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @param  __r  A %shared_ptr.
        *  @post   get() == __r.get() && use_count() == __r.use_count()
        */
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
         : __shared_ptr<_Tp>(__r) { }
 
@@ -231,8 +234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @param  __r  A %shared_ptr rvalue.
        *  @post   *this contains the old value of @a __r, @a __r is empty.
        */
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
 	: __shared_ptr<_Tp>(std::move(__r)) { }
 
@@ -253,7 +255,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	shared_ptr(std::auto_ptr<_Tp1>&& __r);
 #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<_Tp>(std::move(__r)) { }
 
@@ -464,25 +469,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp>
     class weak_ptr : public __weak_ptr<_Tp>
     {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
     public:
       constexpr weak_ptr() noexcept = default;
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
 	: __weak_ptr<_Tp>(__r) { }
 
       weak_ptr(const weak_ptr&) noexcept = default;
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
 	: __weak_ptr<_Tp>(__r) { }
 
       weak_ptr(weak_ptr&&) noexcept = default;
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	weak_ptr(weak_ptr<_Tp1>&& __r) noexcept
 	: __weak_ptr<_Tp>(std::move(__r)) { }
 
diff --git a/libstdc++-v3/include/bits/shared_ptr_base.h b/libstdc++-v3/include/bits/shared_ptr_base.h
index ea74000..fe397d0 100644
--- a/libstdc++-v3/include/bits/shared_ptr_base.h
+++ b/libstdc++-v3/include/bits/shared_ptr_base.h
@@ -477,7 +477,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       _M_get_deleter(const std::type_info& __ti) noexcept
       {
 #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
         return nullptr;
 #endif
@@ -862,6 +866,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, _Lock_policy _Lp>
     class __shared_ptr
     {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
     public:
       typedef _Tp   element_type;
 
@@ -916,8 +924,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
       ~__shared_ptr() = default;
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	__shared_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
 	: _M_ptr(__r._M_ptr), _M_refcount(__r._M_refcount)
 	{ }
@@ -929,8 +936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	__r._M_ptr = 0;
       }
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	__shared_ptr(__shared_ptr<_Tp1, _Lp>&& __r) noexcept
 	: _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.
-      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)
 	: _M_ptr(__r.get()), _M_refcount()
 	{
@@ -1331,6 +1338,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   template<typename _Tp, _Lock_policy _Lp>
     class __weak_ptr
     {
+      template<typename _Ptr>
+	using _Convertible
+	  = typename enable_if<is_convertible<_Ptr, _Tp*>::value>::type;
+
     public:
       typedef _Tp element_type;
 
@@ -1356,14 +1367,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       //
       // It is not possible to avoid spurious access violations since
       // in multithreaded programs __r._M_ptr may be invalidated at any point.
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	__weak_ptr(const __weak_ptr<_Tp1, _Lp>& __r) noexcept
 	: _M_refcount(__r._M_refcount)
         { _M_ptr = __r.lock().get(); }
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	__weak_ptr(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
 	: _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))
       { __r._M_ptr = nullptr; }
 
-      template<typename _Tp1, typename = typename
-	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
+      template<typename _Tp1, typename = _Convertible<_Tp1*>>
 	__weak_ptr(__weak_ptr<_Tp1, _Lp>&& __r) noexcept
 	: _M_ptr(__r.lock().get()), _M_refcount(std::move(__r._M_refcount))
         { __r._M_ptr = nullptr; }
diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional
index e711350..71d97ad 100644
--- a/libstdc++-v3/include/std/functional
+++ b/libstdc++-v3/include/std/functional
@@ -2102,7 +2102,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type)
        *  The target of @c *this is deallocated, leaving it empty.
        */
       function&
-      operator=(nullptr_t)
+      operator=(nullptr_t) noexcept
       {
 	if (_M_manager)
 	  {
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 be33279..d354d20 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 *-*-* } 878 }
+  // { dg-error "incomplete" "" { target *-*-* } 886 }
 
   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/void_neg.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
index 17e036f..d833aea 100644
--- a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/void_neg.cc
@@ -25,5 +25,5 @@
 void test01()
 {
   std::shared_ptr<void> p((void*)nullptr);   // { dg-error "here" }
-  // { dg-error "incomplete" "" { target *-*-* } 877 }
+  // { dg-error "incomplete" "" { target *-*-* } 885 }
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]