diff mbox series

[pushed] c++: "perfect" implicitly deleted move [PR100644]

Message ID 20210518194410.1349652-1-jason@redhat.com
State New
Headers show
Series [pushed] c++: "perfect" implicitly deleted move [PR100644] | expand

Commit Message

Jason Merrill May 18, 2021, 7:44 p.m. UTC
Here we were ignoring the template constructor because the implicit move
constructor had all perfect conversions.  But CWG1402 says that an
implicitly deleted move constructor is ignored by overload resolution; we
implement that instead by preferring any other candidate in joust, to get
better diagnostics, but that means we need to handle that case here as well.

Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/ChangeLog:

	PR c++/100644
	* call.c (perfect_candidate_p): An implicitly deleted move
	is not perfect.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/implicit-delete1.C: New test.
---
 gcc/cp/call.c                                 |  5 +++++
 gcc/testsuite/g++.dg/cpp0x/implicit-delete1.C | 20 +++++++++++++++++++
 2 files changed, 25 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/implicit-delete1.C


base-commit: cd323d97d0592135ca4345701ef051659d8d4507
diff mbox series

Patch

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1e2d1d43184..4a59b97c110 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5890,6 +5890,11 @@  perfect_candidate_p (z_candidate *cand)
 {
   if (cand->viable < 1)
     return false;
+  /* CWG1402 makes an implicitly deleted move op worse than other
+     candidates.  */
+  if (DECL_DELETED_FN (cand->fn) && DECL_DEFAULTED_FN (cand->fn)
+      && move_fn_p (cand->fn))
+    return false;
   int len = cand->num_convs;
   for (int i = 0; i < len; ++i)
     if (!perfect_conversion_p (cand->convs[i]))
diff --git a/gcc/testsuite/g++.dg/cpp0x/implicit-delete1.C b/gcc/testsuite/g++.dg/cpp0x/implicit-delete1.C
new file mode 100644
index 00000000000..6dcced4fb2d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/implicit-delete1.C
@@ -0,0 +1,20 @@ 
+// PR c++/100644
+// { dg-do compile { target c++11 } }
+
+struct NonMovable {
+  NonMovable(NonMovable&&) = delete;
+};
+
+template <class T>
+struct Maybe {
+  NonMovable mMember;
+
+  template <typename U>
+  Maybe(Maybe<U>&&);
+};
+
+void foo(Maybe<int>);
+
+void unlucky(Maybe<int>&& x) {
+  Maybe<int> var{(Maybe<int>&&)x};
+}