In this test we are building a call in a template, but since neither the function nor any of its arguments are dependent, we go down the normal path in finish_call_expr. convert_arguments sees that we're binding a reference to int to double and therein convert_to_integer creates a FIX_TRUNC_EXPR. Later, we call check_function_arguments which folds the arguments, and, in a template, fold_for_warn calls fold_non_dependent_expr. But tsubst_copy_and_build should not see a FIX_TRUNC_EXPR (see the patch discussed in <https://gcc.gnu.org/pipermail/gcc-patches/2018-March/496183.html>) or we crash.
So let's not create a FIX_TRUNC_EXPR in a template in the first place and instead use IMPLICIT_CONV_EXPR. (I'm not sure why tsubst* also doesn't crash on a FLOAT_EXPR; it'd make sense to me to also create an IMPLICIT_CONV_EXPR for integer to real convs and add "case FLOAT_EXPR" just under FIX_TRUNC_EXPR. But perhaps that's too risky to do now.) Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/10? gcc/cp/ChangeLog: PR c++/97973 * call.c (convert_like): When converting real to integer in a template, use IMPLICIT_CONV_EXPR. gcc/testsuite/ChangeLog: PR c++/97973 * g++.dg/conversion/real-to-int1.C: New test. --- gcc/cp/call.c | 7 ++++++- gcc/testsuite/g++.dg/conversion/real-to-int1.C | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 gcc/testsuite/g++.dg/conversion/real-to-int1.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 123f06b1f2b..8074d8fdba8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8062,7 +8062,12 @@ convert_like (conversion *convs, tree expr, tree fn, int argnum, tree conv_expr = NULL_TREE; if (processing_template_decl && convs->kind != ck_identity - && (CLASS_TYPE_P (convs->type) || CLASS_TYPE_P (TREE_TYPE (expr)))) + && (CLASS_TYPE_P (convs->type) + || CLASS_TYPE_P (TREE_TYPE (expr)) + /* Converting real to integer produces FIX_TRUNC_EXPR which + tsubst also doesn't grok. */ + || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (expr)) + && INTEGRAL_OR_ENUMERATION_TYPE_P (convs->type)))) { conv_expr = build1 (IMPLICIT_CONV_EXPR, convs->type, expr); if (convs->kind != ck_ref_bind) diff --git a/gcc/testsuite/g++.dg/conversion/real-to-int1.C b/gcc/testsuite/g++.dg/conversion/real-to-int1.C new file mode 100644 index 00000000000..f7b990b3f4b --- /dev/null +++ b/gcc/testsuite/g++.dg/conversion/real-to-int1.C @@ -0,0 +1,17 @@ +// PR c++/97973 + +void (*foo[1])(const int &); +void (*foo2[1])(const double &); + +template<typename> +void f () +{ + (foo[0])(1.1); + (foo2[0])(1); +} + +void +g () +{ + f<char> (); +} base-commit: 8d57bdadd2d9c2e5c95515ca7a583d7b407b55c4 -- 2.29.2