* [PATCH] c++: tweak c++17 ctor/conversion tiebreaker [DR2327]
@ 2023-06-14 14:02 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2023-06-14 14:02 UTC (permalink / raw)
To: gcc-patches
In discussion of this issue CWG decided that the change of behavior on
well-formed code like overload-conv-4.C is undesirable. In further
discussion of possible resolutions, we discovered that we can avoid that
change while still getting the desired behavior on overload-conv-3.C by
making this a tiebreaker after comparing conversions, rather than before.
This also simplifies the implementation.
The issue resolution has not yet been finalized, but this seems like a clear
improvement.
DR 2327
gcc/cp/ChangeLog:
* call.cc (joust_maybe_elide_copy): Don't change cand.
(joust): Move the elided tiebreaker later.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/overload-conv-4.C: Remove warnings.
* g++.dg/cpp1z/elide7.C: New test.
---
gcc/cp/call.cc | 56 ++++++++------------
gcc/testsuite/g++.dg/cpp0x/overload-conv-4.C | 5 +-
gcc/testsuite/g++.dg/cpp1z/elide7.C | 14 +++++
3 files changed, 39 insertions(+), 36 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1z/elide7.C
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 68cf878308e..15a3d6f2a1f 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -12560,11 +12560,11 @@ add_warning (struct z_candidate *winner, struct z_candidate *loser)
}
/* CAND is a constructor candidate in joust in C++17 and up. If it copies a
- prvalue returned from a conversion function, replace CAND with the candidate
- for the conversion and return true. Otherwise, return false. */
+ prvalue returned from a conversion function, return true. Otherwise, return
+ false. */
static bool
-joust_maybe_elide_copy (z_candidate *&cand)
+joust_maybe_elide_copy (z_candidate *cand)
{
tree fn = cand->fn;
if (!DECL_COPY_CONSTRUCTOR_P (fn) && !DECL_MOVE_CONSTRUCTOR_P (fn))
@@ -12580,10 +12580,7 @@ joust_maybe_elide_copy (z_candidate *&cand)
(conv->type, DECL_CONTEXT (fn)));
z_candidate *uc = conv->cand;
if (DECL_CONV_FN_P (uc->fn))
- {
- cand = uc;
- return true;
- }
+ return true;
}
return false;
}
@@ -12735,27 +12732,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
}
}
- /* Handle C++17 copy elision in [over.match.ctor] (direct-init) context. The
- standard currently says that only constructors are candidates, but if one
- copies a prvalue returned by a conversion function we want to treat the
- conversion as the candidate instead.
-
- Clang does something similar, as discussed at
- http://lists.isocpp.org/core/2017/10/3166.php
- http://lists.isocpp.org/core/2019/03/5721.php */
- int elided_tiebreaker = 0;
- if (len == 1 && cxx_dialect >= cxx17
- && DECL_P (cand1->fn)
- && DECL_COMPLETE_CONSTRUCTOR_P (cand1->fn)
- && !(cand1->flags & LOOKUP_ONLYCONVERTING))
- {
- bool elided1 = joust_maybe_elide_copy (cand1);
- bool elided2 = joust_maybe_elide_copy (cand2);
- /* As a tiebreaker below we will prefer a constructor to a conversion
- operator exposed this way. */
- elided_tiebreaker = elided2 - elided1;
- }
-
for (i = 0; i < len; ++i)
{
conversion *t1 = cand1->convs[i + off1];
@@ -12917,11 +12893,6 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
if (winner)
return winner;
- /* Put this tiebreaker first, so that we don't try to look at second_conv of
- a constructor candidate that doesn't have one. */
- if (elided_tiebreaker)
- return elided_tiebreaker;
-
/* DR 495 moved this tiebreaker above the template ones. */
/* or, if not that,
the context is an initialization by user-defined conversion (see
@@ -12958,6 +12929,25 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
}
}
+ /* DR2327: C++17 copy elision in [over.match.ctor] (direct-init) context.
+ The standard currently says that only constructors are candidates, but if
+ one copies a prvalue returned by a conversion function we prefer that.
+
+ Clang does something similar, as discussed at
+ http://lists.isocpp.org/core/2017/10/3166.php
+ http://lists.isocpp.org/core/2019/03/5721.php */
+ if (len == 1 && cxx_dialect >= cxx17
+ && DECL_P (cand1->fn)
+ && DECL_COMPLETE_CONSTRUCTOR_P (cand1->fn)
+ && !(cand1->flags & LOOKUP_ONLYCONVERTING))
+ {
+ bool elided1 = joust_maybe_elide_copy (cand1);
+ bool elided2 = joust_maybe_elide_copy (cand2);
+ winner = elided1 - elided2;
+ if (winner)
+ return winner;
+ }
+
/* or, if not that,
F1 is a non-template function and F2 is a template function
specialization. */
diff --git a/gcc/testsuite/g++.dg/cpp0x/overload-conv-4.C b/gcc/testsuite/g++.dg/cpp0x/overload-conv-4.C
index 6fcdbbaa6a4..d2663e6cb20 100644
--- a/gcc/testsuite/g++.dg/cpp0x/overload-conv-4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/overload-conv-4.C
@@ -17,7 +17,6 @@ B
f (A x)
{
// C++14: we call B::B(A const &)
- // C++17: we call A::operator B()
- return B(x); // { dg-warning "choosing .A::operator B\\(\\). over .B::B\\(const A&\\)" "" { target c++17 } }
- // { dg-warning "for conversion from .A. to .B." "" { target c++17 } .-1 }
+ // C++17: now the same
+ return B(x);
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/elide7.C b/gcc/testsuite/g++.dg/cpp1z/elide7.C
new file mode 100644
index 00000000000..2d8cc65bca8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/elide7.C
@@ -0,0 +1,14 @@
+// DR2327: In direct-initialization, prefer a constructor even if it requires a
+// qualification conversion.
+
+// { dg-do compile { target c++11 } }
+
+struct Dog;
+struct Cat {
+ Cat(const Dog&);
+};
+struct Dog {
+ operator Cat() = delete;
+};
+
+Cat cat(Dog{});
base-commit: b7e42b85212e03eb59193a712eb523f26911a581
--
2.31.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-06-14 14:02 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-14 14:02 [PATCH] c++: tweak c++17 ctor/conversion tiebreaker [DR2327] Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).