On Mon, Mar 16, 2020 at 05:12:15PM -0400, Jason Merrill wrote: > On 3/16/20 10:57 AM, Marek Polacek wrote: > > Now that convert_like creates an IMPLICIT_CONV_EXPR when it converts > > something that involves a class in a template, we must be prepared to > > handle it. In this test, we have a class S and we're converting it > > to long int& using a user-defined conversion since we're performing > > -- on it. So cp_build_unary_op/POSTDECREMENT_EXPR calls > > build_expr_type_conversion which gets the IMPLICIT_CONV_EXPR. Before > > the convert_like change it got *S::operator long int &(&b) whose type > > is long int but now it gets IMPLICIT_CONV_EXPR<long int&>(b) whose type > > is a reference type. > > So you need to make sure that your IMPLICIT_CONV_EXPR gets > convert_from_reference'd at some point.
Perhaps like the following? Bootstrapped/regtested on x86_64-linux, built Boost/cmcstl2. -- >8 -- Now that convert_like creates an IMPLICIT_CONV_EXPR when it converts something that involves a class in a template, we must be prepared to handle it. In this test, we have a class S and we're converting it to long int& using a user-defined conversion since we're performing -- on it. So cp_build_unary_op/POSTDECREMENT_EXPR calls build_expr_type_conversion which gets the IMPLICIT_CONV_EXPR. Before the convert_like change it got *S::operator long int &(&b) whose type is long int but now it gets IMPLICIT_CONV_EXPR<long int&>(b) whose type is a reference type. But the !MAYBE_CLASS_TYPE_P switch doesn't handle reference types and so we complain. Fixed by calling convert_from_reference on the result of convert_like. PR c++/94190 - wrong no post-decrement operator error in template. * call.c (build_new_op_1): Use convert_from_reference on the result of convert_like. * g++.dg/conversion/op7.C: New test. --- gcc/cp/call.c | 3 +++ gcc/testsuite/g++.dg/conversion/op7.C | 22 ++++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 gcc/testsuite/g++.dg/conversion/op7.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1715acc0ec3..d8b28573b95 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -6426,6 +6426,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, { conv = strip_standard_conversion (conv); arg1 = convert_like (conv, arg1, complain); + arg1 = convert_from_reference (arg1); } if (arg2) @@ -6435,6 +6436,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, { conv = strip_standard_conversion (conv); arg2 = convert_like (conv, arg2, complain); + arg2 = convert_from_reference (arg2); } } @@ -6445,6 +6447,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, { conv = strip_standard_conversion (conv); arg3 = convert_like (conv, arg3, complain); + arg3 = convert_from_reference (arg3); } } } diff --git a/gcc/testsuite/g++.dg/conversion/op7.C b/gcc/testsuite/g++.dg/conversion/op7.C new file mode 100644 index 00000000000..c6401d109b4 --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/op7.C @@ -0,0 +1,22 @@ +// PR c++/94190 - wrong no post-decrement operator error in template. + +struct S { operator long & (); } b; + +template<int> void +foo () +{ + b--; + ++b; + --b; + b++; + !b; + ~b; + +b; + -b; +} + +void +bar () +{ + foo<0> (); +} base-commit: 2691ffe6dbaffb704593dd6220178c28848b3855 -- Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA