LWG 2996 add rvalue overloads for shared_ptr aliasing and casting
authorJonathan Wakely <jwakely@redhat.com>
Thu, 23 May 2019 21:41:02 +0000 (22:41 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 23 May 2019 21:41:02 +0000 (22:41 +0100)
* doc/xml/manual/intro.xml: Document LWG DR 2996 change.
* doc/html/*: Regenerate.
* include/bits/shared_ptr.h (shared_ptr(shared_ptr&&, T*)): Add
rvalue aliasing constructor.
(static_pointer_cast, const_pointer, dynamic_pointer_cast)
(reinterpret_pointer_cast): Add overloads taking rvalues.
* include/bits/shared_ptr_base.h (__shared_ptr(__shared_ptr&&, T*)):
Add rvalue aliasing constructor.
* testsuite/20_util/shared_ptr/casts/1.cc: Change "compile" test to
"run" and check return values as well as types.
* testsuite/20_util/shared_ptr/casts/reinterpret.cc: Likewise.
* testsuite/20_util/shared_ptr/casts/rval.cc: New test.
* testsuite/20_util/shared_ptr/cons/alias-rval.cc: New test.
* testsuite/20_util/shared_ptr/cons/alias.cc: Remove unused return
values.

From-SVN: r271583

libstdc++-v3/ChangeLog
libstdc++-v3/doc/html/manual/api.html
libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/shared_ptr.h
libstdc++-v3/include/bits/shared_ptr_base.h
libstdc++-v3/testsuite/20_util/shared_ptr/casts/1.cc
libstdc++-v3/testsuite/20_util/shared_ptr/casts/reinterpret.cc
libstdc++-v3/testsuite/20_util/shared_ptr/casts/rval.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/shared_ptr/cons/alias-rval.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/shared_ptr/cons/alias.cc

index e230f24ca13ada22843788a578365db4927b8804..48b519e9cd0efcf6cbaae9332c080eeaf39fdc64 100644 (file)
@@ -1,5 +1,21 @@
 2019-05-23  Jonathan Wakely  <jwakely@redhat.com>
 
+       * doc/xml/manual/intro.xml: Document LWG DR 2996 change.
+       * doc/html/*: Regenerate.
+       * include/bits/shared_ptr.h (shared_ptr(shared_ptr&&, T*)): Add
+       rvalue aliasing constructor.
+       (static_pointer_cast, const_pointer, dynamic_pointer_cast)
+       (reinterpret_pointer_cast): Add overloads taking rvalues.
+       * include/bits/shared_ptr_base.h (__shared_ptr(__shared_ptr&&, T*)):
+       Add rvalue aliasing constructor.
+       * testsuite/20_util/shared_ptr/casts/1.cc: Change "compile" test to
+       "run" and check return values as well as types.
+       * testsuite/20_util/shared_ptr/casts/reinterpret.cc: Likewise.
+       * testsuite/20_util/shared_ptr/casts/rval.cc: New test.
+       * testsuite/20_util/shared_ptr/cons/alias-rval.cc: New test.
+       * testsuite/20_util/shared_ptr/cons/alias.cc: Remove unused return
+       values.
+
        * doc/xml/manual/evolution.xml: Document LWG DR 2921 change.
        * doc/xml/manual/intro.xml: Likewise.
        * include/std/future (__create_task_state): Add default arguments
index bb131d3010ca6a716cd543fe897a7967c977635b..345c58802a4909d045b1d34ebd6903447f9ca395 100644 (file)
@@ -393,4 +393,7 @@ now defaults to zero.
   <code class="filename">&lt;experimental/timer&gt;</code>.
 </p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="api.rel_101"></a><code class="constant">10</code></h3></div></div></div><p> Deprecated features removed:
 </p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem"> Profile Mode </li><li class="listitem"><code class="classname">__gnu_cxx::array_allocator</code></li></ul></div><p>
+</p><p>
+  The <code class="classname">std::packaged_task</code> constructors taking
+  an allocator argument are only defined for C++11 and C++14.
 </p></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="abi.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="appendix_porting.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="backwards.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">ABI Policy and Guidelines </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Backwards Compatibility</td></tr></table></div></body></html>
\ No newline at end of file
index f72404baedb1fc734a1b4ea0efff6a83b9fc1dfc..db30048203967052b80d668d5633a3554abc6115 100644 (file)
        <span class="emphasis"><em><code class="code">shared_ptr</code> constructor requirements for a deleter
        </em></span>
     </span></dt><dd><p>Use rvalues for deleters.
+    </p></dd><dt><a id="manual.bugs.dr2921"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2921" target="_top">2921</a>:
+       <span class="emphasis"><em><code class="code">packaged_task</code> and type-erased allocators
+       </em></span>
+    </span></dt><dd><p>For C++17 mode, remove the constructors taking
+      an allocator argument.
     </p></dd><dt><a id="manual.bugs.dr2942"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2942" target="_top">2942</a>:
        <span class="emphasis"><em>LWG 2873's resolution missed
          <code class="code">weak_ptr::owner_before</code>
        </em></span>
     </span></dt><dd><p>Add noexcept.
+    </p></dd><dt><a id="manual.bugs.dr2996"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2996" target="_top">2996</a>:
+       <span class="emphasis"><em>Missing rvalue overloads for
+         <code class="code">shared_ptr</code> operations
+       </em></span>
+    </span></dt><dd><p>Add additional constructor and cast overloads.
     </p></dd><dt><a id="manual.bugs.dr2993"></a><span class="term"><a class="link" href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2993" target="_top">2993</a>:
        <span class="emphasis"><em><code class="code">reference_wrapper&lt;T&gt;</code> conversion from <code class="code">T&amp;&amp;</code>
        </em></span>
index a2162562b549dbe117da7980694e44800b32d247..4a5d25fa0d70cd2c66af32b1f5f32ee2ccbf0190 100644 (file)
@@ -1237,6 +1237,14 @@ requirements of the license of GCC.
     <listitem><para>Add noexcept.
     </para></listitem></varlistentry>
 
+    <varlistentry xml:id="manual.bugs.dr2996"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2996">2996</link>:
+       <emphasis>Missing rvalue overloads for
+         <code>shared_ptr</code> operations
+       </emphasis>
+    </term>
+    <listitem><para>Add additional constructor and cast overloads.
+    </para></listitem></varlistentry>
+
     <varlistentry xml:id="manual.bugs.dr2993"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2993">2993</link>:
        <emphasis><code>reference_wrapper&lt;T&gt;</code> conversion from <code>T&amp;&amp;</code>
        </emphasis>
index 8f219e73d60babb187de8623739fdc7d50985652..41f6b126b3d1b6e842aa6668cd8294efcc7ed03d 100644 (file)
@@ -235,17 +235,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Aliasing constructor
 
       /**
-       *  @brief  Constructs a %shared_ptr instance that stores @a __p
-       *          and shares ownership with @a __r.
-       *  @param  __r  A %shared_ptr.
-       *  @param  __p  A pointer that will remain valid while @a *__r is valid.
-       *  @post   get() == __p && use_count() == __r.use_count()
+       *  @brief  Constructs a `shared_ptr` instance that stores `__p`
+       *          and shares ownership with `__r`.
+       *  @param  __r  A `shared_ptr`.
+       *  @param  __p  A pointer that will remain valid while `*__r` is valid.
+       *  @post   `get() == __p && use_count() == __r.use_count()`
        *
-       *  This can be used to construct a @c shared_ptr to a sub-object
-       *  of an object managed by an existing @c shared_ptr.
+       *  This can be used to construct a `shared_ptr` to a sub-object
+       *  of an object managed by an existing `shared_ptr`. The complete
+       *  object will remain valid while any `shared_ptr` owns it, even
+       *  if they don't store a pointer to the complete object.
        *
        * @code
-       * shared_ptr< pair<int,int> > pii(new pair<int,int>());
+       * shared_ptr<pair<int,int>> pii(new pair<int,int>());
        * shared_ptr<int> pi(pii, &pii->first);
        * assert(pii.use_count() == 2);
        * @endcode
@@ -254,6 +256,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        shared_ptr(const shared_ptr<_Yp>& __r, element_type* __p) noexcept
        : __shared_ptr<_Tp>(__r, __p) { }
 
+#if __cplusplus > 201703L
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2996. Missing rvalue overloads for shared_ptr operations
+      /**
+       *  @brief  Constructs a `shared_ptr` instance that stores `__p`
+       *          and shares ownership with `__r`.
+       *  @param  __r  A `shared_ptr`.
+       *  @param  __p  A pointer that will remain valid while `*__r` is valid.
+       *  @post   `get() == __p && !__r.use_count() && !__r.get()`
+       *
+       *  This can be used to construct a `shared_ptr` to a sub-object
+       *  of an object managed by an existing `shared_ptr`. The complete
+       *  object will remain valid while any `shared_ptr` owns it, even
+       *  if they don't store a pointer to the complete object.
+       *
+       * @code
+       * shared_ptr<pair<int,int>> pii(new pair<int,int>());
+       * shared_ptr<int> pi1(pii, &pii->first);
+       * assert(pii.use_count() == 2);
+       * shared_ptr<int> pi2(std::move(pii), &pii->second);
+       * assert(pii.use_count() == 0);
+       * @endcode
+       */
+      template<typename _Yp>
+       shared_ptr(shared_ptr<_Yp>&& __r, element_type* __p) noexcept
+       : __shared_ptr<_Tp>(std::move(__r), __p) { }
+#endif
       /**
        *  @brief  If @a __r is empty, constructs an empty %shared_ptr;
        *          otherwise construct a %shared_ptr that shares ownership
@@ -568,7 +597,53 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       using _Sp = shared_ptr<_Tp>;
       return _Sp(__r, reinterpret_cast<typename _Sp::element_type*>(__r.get()));
     }
-#endif
+
+#if __cplusplus > 201703L
+  // _GLIBCXX_RESOLVE_LIB_DEFECTS
+  // 2996. Missing rvalue overloads for shared_ptr operations
+
+  /// Convert type of `shared_ptr` rvalue, via `static_cast`
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    static_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(std::move(__r),
+                static_cast<typename _Sp::element_type*>(__r.get()));
+    }
+
+  /// Convert type of `shared_ptr` rvalue, via `const_cast`
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    const_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(std::move(__r),
+                const_cast<typename _Sp::element_type*>(__r.get()));
+    }
+
+  /// Convert type of `shared_ptr` rvalue, via `dynamic_cast`
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    dynamic_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      if (auto* __p = dynamic_cast<typename _Sp::element_type*>(__r.get()))
+       return _Sp(std::move(__r), __p);
+      return _Sp();
+    }
+
+  /// Convert type of `shared_ptr` rvalue, via `reinterpret_cast`
+  template<typename _Tp, typename _Up>
+    inline shared_ptr<_Tp>
+    reinterpret_pointer_cast(shared_ptr<_Up>&& __r) noexcept
+    {
+      using _Sp = shared_ptr<_Tp>;
+      return _Sp(std::move(__r),
+                reinterpret_cast<typename _Sp::element_type*>(__r.get()));
+    }
+#endif // C++20
+#endif // C++17
 
   // @}
 
index 968cc9658e2bc16255ba066f0faf492ef759948c..4acec1cb2c5d467eec6dea94957ecdc183d6f0c1 100644 (file)
@@ -1158,12 +1158,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        : _M_ptr(0), _M_refcount(__p, std::move(__d), std::move(__a))
        { }
 
+      // Aliasing constructor
       template<typename _Yp>
        __shared_ptr(const __shared_ptr<_Yp, _Lp>& __r,
                     element_type* __p) noexcept
        : _M_ptr(__p), _M_refcount(__r._M_refcount) // never throws
        { }
 
+      // Aliasing constructor
+      template<typename _Yp>
+       __shared_ptr(__shared_ptr<_Yp, _Lp>&& __r,
+                    element_type* __p) noexcept
+       : _M_ptr(__p), _M_refcount()
+       {
+         _M_refcount._M_swap(__r._M_refcount);
+         __r._M_ptr = 0;
+       }
+
       __shared_ptr(const __shared_ptr&) noexcept = default;
       __shared_ptr& operator=(const __shared_ptr&) noexcept = default;
       ~__shared_ptr() = default;
index d689daf2f3d98adb51ed3f628409e164748507ea..f2b8a268259b3a1c84873358e641fef3caae2e87 100644 (file)
@@ -1,4 +1,4 @@
-// { dg-do compile { target c++11 } }
+// { dg-do run { target c++11 } }
 
 // Copyright (C) 2006-2019 Free Software Foundation, Inc.
 //
 // 20.6.6.2.10 shared_ptr casts [util.smartptr.shared.cast]
 
 #include <memory>
+#include <testsuite_hooks.h>
 #include <testsuite_tr1.h>
 
 struct MyP { virtual ~MyP() { }; };
 struct MyDP : MyP { };
 
-int main()
+void
+test01()
 {
   using __gnu_test::check_ret_type;
   using std::shared_ptr;
@@ -37,7 +39,50 @@ int main()
   shared_ptr<const int> spci;
   shared_ptr<MyP> spa;
 
-  check_ret_type<shared_ptr<void> >(static_pointer_cast<void>(spd));
-  check_ret_type<shared_ptr<int> >(const_pointer_cast<int>(spci));
-  check_ret_type<shared_ptr<MyDP> >(static_pointer_cast<MyDP>(spa));  
+  check_ret_type<shared_ptr<void>>(static_pointer_cast<void>(spd));
+  check_ret_type<shared_ptr<int>>(const_pointer_cast<int>(spci));
+  check_ret_type<shared_ptr<MyDP>>(dynamic_pointer_cast<MyDP>(spa));
+}
+
+void
+test02()
+{
+  using std::shared_ptr;
+  using std::static_pointer_cast;
+  using std::const_pointer_cast;
+  using std::dynamic_pointer_cast;
+
+  int* ptr = new int(1);
+  shared_ptr<const void> pcv(ptr);
+  auto pci = static_pointer_cast<const int>(pcv);
+  VERIFY(pci.use_count() == 2);
+  VERIFY(pcv.use_count() == 2);
+  VERIFY(pci.get() == ptr);
+  VERIFY(pcv.get() == ptr);
+  auto pi = const_pointer_cast<int>(pci);
+  VERIFY(pi.use_count() == 3);
+  VERIFY(pcv.use_count() == 3);
+  VERIFY(pi.get() == ptr);
+  VERIFY(pci.get() == ptr);
+
+  MyP* pptr = new MyP;
+  shared_ptr<MyP> pp(pptr);
+  auto pdp = dynamic_pointer_cast<MyDP>(pp);
+  VERIFY(pp.use_count() == 1);
+  VERIFY(pdp.use_count() == 0);
+  VERIFY(pdp.get() == nullptr);
+  VERIFY(pp.get() == pptr);
+  pptr = new MyDP;
+  pp.reset(pptr);
+  pdp = dynamic_pointer_cast<MyDP>(pp);
+  VERIFY(pp.use_count() == 2);
+  VERIFY(pdp.use_count() == 2);
+  VERIFY(pdp.get() == pptr);
+  VERIFY(pp.get() == pptr);
+}
+
+int main()
+{
+  test01();
+  test02();
 }
index b16ac045dadc5169ec57882a5ef7819811ceec1a..eae050fd95402e82c8dcaf2163b447fe513734f9 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-options "-std=gnu++17" }
-// { dg-do compile { target c++17 } }
+// { dg-do run { target c++17 } }
 
 // Copyright (C) 2016-2019 Free Software Foundation, Inc.
 //
 // 20.11.2.2.9 shared_ptr casts [util.smartptr.shared.cast]
 
 #include <memory>
+#include <testsuite_hooks.h>
 #include <testsuite_tr1.h>
 
 struct MyP { virtual ~MyP() { }; };
 struct MyDP : MyP { };
 
-int main()
+void
+test01()
 {
   using __gnu_test::check_ret_type;
   using std::shared_ptr;
@@ -36,7 +38,28 @@ int main()
   shared_ptr<const int> spci;
   shared_ptr<MyP> spa;
 
-  check_ret_type<shared_ptr<void> >(reinterpret_pointer_cast<void>(spd));
-  check_ret_type<shared_ptr<const short> >(reinterpret_pointer_cast<const short>(spci));
-  check_ret_type<shared_ptr<MyDP> >(reinterpret_pointer_cast<MyDP>(spa));
+  check_ret_type<shared_ptr<void>>(reinterpret_pointer_cast<void>(spd));
+  check_ret_type<shared_ptr<const short>>(reinterpret_pointer_cast<const short>(spci));
+  check_ret_type<shared_ptr<MyDP>>(reinterpret_pointer_cast<MyDP>(spa));
+}
+
+void
+test02()
+{
+  using std::shared_ptr;
+  using std::reinterpret_pointer_cast;
+
+  int* ptr = new int(2);
+  shared_ptr<int> pi(ptr);
+  auto pl = reinterpret_pointer_cast<long>(pi);
+  VERIFY(pi.use_count() == 2);
+  VERIFY(pl.use_count() == 2);
+  VERIFY(pi.get() == ptr);
+  VERIFY(reinterpret_cast<int*>(pl.get()) == ptr);
+}
+
+int main()
+{
+  test01();
+  test02();
 }
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/casts/rval.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/casts/rval.cc
new file mode 100644 (file)
index 0000000..6f102b2
--- /dev/null
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2019 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/>.
+
+// shared_ptr casts [util.smartptr.shared.cast]
+
+#include <memory>
+#include <testsuite_hooks.h>
+#include <testsuite_tr1.h>
+
+struct MyP { virtual ~MyP() { }; };
+struct MyDP : MyP { };
+
+void test01()
+{
+  using __gnu_test::check_ret_type;
+  using std::shared_ptr;
+  using std::static_pointer_cast;
+  using std::const_pointer_cast;
+  using std::dynamic_pointer_cast;
+  using std::reinterpret_pointer_cast;
+
+  shared_ptr<double> spd;
+  shared_ptr<const int> spci;
+  shared_ptr<MyP> spa;
+
+  check_ret_type<shared_ptr<void>>(static_pointer_cast<void>(std::move(spd)));
+  check_ret_type<shared_ptr<int>>(const_pointer_cast<int>(std::move(spci)));
+  check_ret_type<shared_ptr<MyDP>>(dynamic_pointer_cast<MyDP>(std::move(spa)));
+  check_ret_type<shared_ptr<void>>(reinterpret_pointer_cast<void>(std::move(spd)));
+  check_ret_type<shared_ptr<const short>>(reinterpret_pointer_cast<const short>(std::move(spci)));
+  check_ret_type<shared_ptr<MyDP>>(reinterpret_pointer_cast<MyDP>(std::move(spa)));
+}
+
+void
+test02()
+{
+  using std::shared_ptr;
+  using std::static_pointer_cast;
+  using std::const_pointer_cast;
+  using std::dynamic_pointer_cast;
+  using std::reinterpret_pointer_cast;
+
+  int* ptr = new int(1);
+  shared_ptr<const void> pcv(ptr);
+  auto pci = static_pointer_cast<const int>(std::move(pcv));
+  VERIFY(pci.use_count() == 1);
+  VERIFY(pcv.use_count() == 0);
+  VERIFY(pci.get() == ptr);
+  VERIFY(pcv.get() == nullptr);
+  auto pi = const_pointer_cast<int>(std::move(pci));
+  VERIFY(pi.use_count() == 1);
+  VERIFY(pci.use_count() == 0);
+  VERIFY(pi.get() == ptr);
+  VERIFY(pci.get() == nullptr);
+
+  MyP* pptr = new MyP;
+  shared_ptr<MyP> pp(pptr);
+  auto pdp = dynamic_pointer_cast<MyDP>(std::move(pp));
+  VERIFY(pdp.use_count() == 0);
+  VERIFY(pp.use_count() == 1);
+  VERIFY(pdp.get() == nullptr);
+  VERIFY(pp.get() == pptr);
+  pptr = new MyDP;
+  pp.reset(pptr);
+  pdp = dynamic_pointer_cast<MyDP>(std::move(pp));
+  VERIFY(pdp.use_count() == 1);
+  VERIFY(pp.use_count() == 0);
+  VERIFY(pdp.get() == pptr);
+  VERIFY(pp.get() == nullptr);
+
+  ptr = new int(2);
+  pi.reset(ptr);
+  auto pl = reinterpret_pointer_cast<long>(std::move(pi));
+  VERIFY(pl.use_count() == 1);
+  VERIFY(pi.use_count() == 0);
+  VERIFY(reinterpret_cast<int*>(pl.get()) == ptr);
+  VERIFY(pi.get() == nullptr);
+}
+
+int main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/shared_ptr/cons/alias-rval.cc b/libstdc++-v3/testsuite/20_util/shared_ptr/cons/alias-rval.cc
new file mode 100644 (file)
index 0000000..205587c
--- /dev/null
@@ -0,0 +1,101 @@
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+// Copyright (C) 2019 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/>.
+
+// Template class shared_ptr [util.smartptr.shared]
+
+#include <memory>
+#include <testsuite_hooks.h>
+
+struct A
+{
+  A() : i() { }
+  virtual ~A() { }
+  int i;
+};
+
+struct B : A
+{
+  B() : A(), a() { }
+  virtual ~B() { }
+  A a;
+};
+
+void deletefunc(A* p) { delete p; }
+
+// 20.6.6.2.1 shared_ptr constructors [util.smartptr.shared.const]
+
+// Aliasing constructors
+
+void
+test01()
+{
+  bool test = true;
+
+  std::shared_ptr<A> a;
+  std::shared_ptr<bool> b1(std::move(a), &test);
+  VERIFY( b1.use_count() == 0 );
+  VERIFY( b1.get() == &test );
+  VERIFY( a.use_count() == 0 );
+  VERIFY( a == nullptr );
+
+  std::shared_ptr<bool> b2(b1);
+  VERIFY( b2.use_count() == 0 );
+  VERIFY( b1 == b2 );
+}
+
+void
+test02()
+{
+  std::shared_ptr<A> a(new A);
+  std::shared_ptr<int> i1(std::move(a), &a->i);
+  VERIFY( i1.use_count() == 1 );
+  VERIFY( i1 != nullptr );
+  VERIFY( a.use_count() == 0 );
+  VERIFY( a == nullptr );
+
+  std::shared_ptr<int> i2(i1);
+  VERIFY( i2.use_count() == 2 );
+  VERIFY( i2.get() == &a->i );
+}
+
+void
+test03()
+{
+  std::shared_ptr<B> b1(new B);
+  std::shared_ptr<B> b2(b1);
+  std::shared_ptr<A> a1(std::move(b1), b1.get());
+  std::shared_ptr<A> a2(b2, &b2->a);
+  VERIFY( a2.use_count() == 2 );
+  VERIFY( a1 != nullptr );
+  VERIFY( a2 != nullptr );
+  VERIFY( a1 != a2 );
+  VERIFY( b1.use_count() == 0 );
+  VERIFY( b2.use_count() == 0 );
+  VERIFY( b1 == nullptr );
+  VERIFY( b2 == nullptr );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+  test03();
+}
index 841a51e23afea5f664ae1b04dfbf233d2e6e6ff2..134a05894a24e545b999ef68c28224dc332bbc2a 100644 (file)
@@ -42,7 +42,8 @@ void deletefunc(A* p) { delete p; }
 
 // Aliasing constructors
 
-int test01()
+void
+test01()
 {
   bool test = true;
 
@@ -55,11 +56,9 @@ int test01()
   std::shared_ptr<bool> b2(b1);
   VERIFY( b2.use_count() == 0 );
   VERIFY( b1.get() == b2.get() );
-
-  return 0;
 }
 
-int
+void
 test02()
 {
   std::shared_ptr<A> a(new A);
@@ -69,11 +68,9 @@ test02()
   std::shared_ptr<int> i2(i1);
   VERIFY( i2.use_count() == 3 );
   VERIFY( i2.get() == &a->i );
-
-  return 0;
 }
 
-int
+void
 test03()
 {
   std::shared_ptr<B> b(new B);
@@ -89,8 +86,6 @@ test03()
 
   a3 = a2;
   VERIFY( a3.get() == &b->a );
-
-  return 0;
 }
 
 int
@@ -99,5 +94,4 @@ main()
   test01();
   test02();
   test03();
-  return 0;
 }