Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/13? This isn't a very satisfactory fix, but at least it safely fixes these testcases I guess. Note that there's implementation disagreement about the second testcase, GCC always accepted it but Clang/MSVC/icc reject it.
-- >8 -- In the bad reference binding shortcutting commit r13-1755-g68f37670eff0b872 I made us check the badness criteria in reference_binding earlier in the function so that we can fail fast and avoid unnecessary template instantiation during the first pass of overload resolution. This was for the most part obviously safe, except now the badness criteria are also checked before the recursive case[1] in reference_binding, whereas before the criteria didn't apply in that case. So in order to justify this hoisting I added a sanity check that the badness criteria are still sound in the recursive case. Unfortunately the below testcases triggers the sanity check. I'm not sure if this means the bad conversion shortcutting is unsound since I wasn't able to construct a testcase that affects overload resolution. And if it is unsound, I'm not sure how we can make it sound in light of this recursive logic for non-direct user-defined conversions. But we can at least restore the pre-r13-1755 behavior for the below two testcases by simply getting rid of this sanity check. [1]: Added in https://gcc.gnu.org/pipermail/gcc-patches/2014-April/386365.html PR c++/113141 gcc/cp/ChangeLog: * call.cc (reference_binding): Remove badness criteria sanity check in the recursive case. gcc/testsuite/ChangeLog: * g++.dg/conversion/ref10.C: New test. * g++.dg/conversion/ref11.C: New test. --- gcc/cp/call.cc | 1 - gcc/testsuite/g++.dg/conversion/ref10.C | 13 +++++++++++++ gcc/testsuite/g++.dg/conversion/ref11.C | 16 ++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/conversion/ref10.C create mode 100644 gcc/testsuite/g++.dg/conversion/ref11.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 9de0d77c423..2dce52bc7b8 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -2034,7 +2034,6 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags, if (!new_second) return bad_direct_conv ? bad_direct_conv : nullptr; conv = merge_conversion_sequences (t, new_second); - gcc_assert (maybe_valid_p || conv->bad_p); return conv; } } diff --git a/gcc/testsuite/g++.dg/conversion/ref10.C b/gcc/testsuite/g++.dg/conversion/ref10.C new file mode 100644 index 00000000000..633b7e48e47 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref10.C @@ -0,0 +1,13 @@ +// PR c++/113141 + +struct Matrix { }; + +struct TPoint3 { operator const Matrix(); }; + +void f(Matrix&); + +int main() { + TPoint3 X; + Matrix& m = (Matrix &)X; + f((Matrix &)X); +} diff --git a/gcc/testsuite/g++.dg/conversion/ref11.C b/gcc/testsuite/g++.dg/conversion/ref11.C new file mode 100644 index 00000000000..f893f12dafa --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/ref11.C @@ -0,0 +1,16 @@ +// PR c++/113141 +// { dg-do compile { target c++11 } } + +struct ConvToRef { + operator int&(); +}; + +struct A { int& r; }; + +void f(A); + +int main() { + ConvToRef c; + A a{{c}}; + f({{c}}); +} -- 2.43.0.386.ge02ecfcc53