PR77987 Fix unique_ptr<T[], D>::reset(U) for T != U
authorJonathan Wakely <jwakely@redhat.com>
Mon, 17 Oct 2016 12:00:44 +0000 (13:00 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Mon, 17 Oct 2016 12:00:44 +0000 (13:00 +0100)
PR libstdc++/77987
* include/bits/unique_ptr.h (unique_ptr<T[], D>::reset<U>(U)): Copy
value to pointer of the correct type to swap, to support conversions
allowed by LWG 2118 / N4089.
* testsuite/20_util/unique_ptr/assign/assign_neg.cc: Move test for
incompatible deleters from ...
* testsuite/20_util/unique_ptr/assign/cv_qual.cc: ... here.
* testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Move tests for
incompatible pointers to ...
* testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: ... here. Move
destructor definition to base class. Test for invalid derived-to-base
conversion.

From-SVN: r241235

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/unique_ptr.h
libstdc++-v3/testsuite/20_util/unique_ptr/assign/assign_neg.cc
libstdc++-v3/testsuite/20_util/unique_ptr/assign/cv_qual.cc
libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/cv_qual.cc
libstdc++-v3/testsuite/20_util/unique_ptr/modifiers/reset_neg.cc

index b31c1dd331a4a804519d26ce2429eb6de34796a5..ed572815d6447bc82932431a121f0ff1261ba276 100644 (file)
@@ -1,5 +1,18 @@
 2016-10-17  Jonathan Wakely  <jwakely@redhat.com>
 
+       PR libstdc++/77987
+       * include/bits/unique_ptr.h (unique_ptr<T[], D>::reset<U>(U)): Copy
+       value to pointer of the correct type to swap, to support conversions
+       allowed by LWG 2118 / N4089.
+       * testsuite/20_util/unique_ptr/assign/assign_neg.cc: Move test for
+       incompatible deleters from ...
+       * testsuite/20_util/unique_ptr/assign/cv_qual.cc: ... here.
+       * testsuite/20_util/unique_ptr/modifiers/cv_qual.cc: Move tests for
+       incompatible pointers to ...
+       * testsuite/20_util/unique_ptr/modifiers/reset_neg.cc: ... here. Move
+       destructor definition to base class. Test for invalid derived-to-base
+       conversion.
+
        * doc/xml/manual/status_cxx2017.xml: Update status.
        * doc/html/*: Regenerate.
        * include/bits/deque.tcc (deque::emplace_front, deque::emplace_back):
index 15ef8a8947521c54f361bf6b696ff1e8de0d0308..a36794d632ef278780e82c88ff895ebfbd3923d2 100644 (file)
@@ -610,10 +610,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       void
       reset(_Up __p) noexcept
       {
+       pointer __ptr = __p;
        using std::swap;
-       swap(std::get<0>(_M_t), __p);
-       if (__p != nullptr)
-         get_deleter()(__p);
+       swap(std::get<0>(_M_t), __ptr);
+       if (__ptr != nullptr)
+         get_deleter()(__ptr);
       }
 
       void reset(nullptr_t = nullptr) noexcept
index 842b6ed7a862a0a2e284462be19b7d2b935ed91a..9142e6146b4ffaf6511285a47fe62cd523532e2e 100644 (file)
@@ -48,4 +48,25 @@ test03()
   std::unique_ptr<int[2]> p2 = p1; // { dg-error "deleted" }
 }
 
+struct base_pointer { operator base*() const { return nullptr; } };
+
+template<typename T>
+struct deleter
+{
+  deleter() = default;
+  template<typename U>
+    deleter(const deleter<U>) { }
+  typedef T pointer;
+  void operator()(T) const { }
+};
+
+void
+test04()
+{
+  // Disallow conversions from incompatible deleter
+  std::unique_ptr<derived[], deleter<base_pointer>> p;
+  std::unique_ptr<base[], deleter<base*>> upA;
+  upA = std::move(p);  // { dg-error "no match" }
+}
+
 // { dg-prune-output "include" }
index 793499dce4dacf3a895f2de6eb87762d614617d0..7add5a9c0a3ec26782054c0a8d27200ca836739e 100644 (file)
@@ -65,26 +65,3 @@ test03()
   std::unique_ptr<const volatile A[]> cvA;
   cvA = std::move(upA);
 }
-
-struct A_pointer { operator A*() const { return nullptr; } };
-
-template<typename T>
-struct deleter
-{
-  deleter() = default;
-  template<typename U>
-    deleter(const deleter<U>) { }
-  typedef T pointer;
-  void operator()(T) const { }
-};
-
-void
-test04()
-{
-  // Disallow conversions from incompatible deleter
-  std::unique_ptr<B[], deleter<A_pointer>> p;
-  std::unique_ptr<A[], deleter<A*>> upA;
-  upA = std::move(p);  // { dg-error "no match" }
-  // { dg-error "no type" "" { target *-*-* } 537 }
-  // { dg-error "no matching function" "" { target *-*-* } 614 }
-}
index 02845635260ccefcabb56a2a7521123f32c30b74..f92949b441ecdf79c0f564cb4f019d0279b1a724 100644 (file)
@@ -86,15 +86,4 @@ test07()
   vA2.reset((A*)p);
   std::unique_ptr<const volatile A[]> cvA2;
   cvA2.reset((A*)p);
-  // Disallow conversions from user-defined pointer-like types
-  // for the array version
-  std::unique_ptr<A[]> upA3;
-  upA3.reset(p); // { dg-error "no matching function" }
-  std::unique_ptr<const A[]> cA3;
-  cA3.reset(p); // { dg-error "no matching function" }
-  std::unique_ptr<volatile A[]> vA3;
-  vA3.reset(p); // { dg-error "no matching function" }
-  std::unique_ptr<const volatile A[]> cvA3;
-  cvA3.reset(p); // { dg-error "no matching function" }
-  // { dg-error "no matching function" "" { target *-*-* } 614 }
 }
index d2ed03cafd94034c8dfc0489d8ccdad80e73f021..cb5f2e6a1c5bd259257027174c1c7a0f4535264e 100644 (file)
 
 struct A
 {
+  virtual ~A() { }
 };
 
 struct B : A
 {
-  virtual ~B() { }
 };
 
-void test01()
+void
+test01()
 {
   std::unique_ptr<B[]> up;
-  up.reset(new A[3]);          // { dg-error "" }
+  up.reset(new A[3]);          // { dg-error "no matching function" }
+
+  std::unique_ptr<A[]> up2;
+  up2.reset(new B[3]);         // { dg-error "no matching function" }
 }
 
-// { dg-prune-output "include" }
+struct A_pointer { operator A*() const { return nullptr; } };
+
+void
+test02()
+{
+  A_pointer p;
+  // Disallow conversions from user-defined pointer-like types
+  // for the array version
+  std::unique_ptr<A[]> upA3;
+  upA3.reset(p); // { dg-error "no matching function" }
+  std::unique_ptr<const A[]> cA3;
+  cA3.reset(p); // { dg-error "no matching function" }
+  std::unique_ptr<volatile A[]> vA3;
+  vA3.reset(p); // { dg-error "no matching function" }
+  std::unique_ptr<const volatile A[]> cvA3;
+  cvA3.reset(p); // { dg-error "no matching function" }
+}