From: Marek Polacek Date: Wed, 3 Mar 2021 23:37:49 +0000 (-0500) Subject: c++: ICE with real-to-int conversion in template [PR97973] X-Git-Tag: upstream/12.2.0~9245 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=40465293cd780aa82dcae75dfcfb1449d8c0561e;p=platform%2Fupstream%2Fgcc.git c++: ICE with real-to-int conversion in template [PR97973] 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 ) 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. gcc/cp/ChangeLog: PR c++/97973 * call.c (conv_unsafe_in_template_p): New. (convert_like): Use it. gcc/testsuite/ChangeLog: PR c++/97973 * g++.dg/conversion/real-to-int1.C: New test. --- diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 29f4b50..390b8aa 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8048,6 +8048,27 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, return expr; } +/* Return true if converting FROM to TO is unsafe in a template. */ + +static bool +conv_unsafe_in_template_p (tree to, tree from) +{ + /* Converting classes involves TARGET_EXPR. */ + if (CLASS_TYPE_P (to) || CLASS_TYPE_P (from)) + return true; + + /* Converting real to integer produces FIX_TRUNC_EXPR which tsubst + doesn't handle. */ + if (SCALAR_FLOAT_TYPE_P (from) && INTEGRAL_OR_ENUMERATION_TYPE_P (to)) + return true; + + /* Converting integer to real isn't a trivial conversion, either. */ + if (INTEGRAL_OR_ENUMERATION_TYPE_P (from) && SCALAR_FLOAT_TYPE_P (to)) + return true; + + return false; +} + /* Wrapper for convert_like_internal that handles creating IMPLICIT_CONV_EXPR. */ @@ -8064,7 +8085,7 @@ 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)))) + && conv_unsafe_in_template_p (convs->type, TREE_TYPE (expr))) { 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 0000000..f7b990b --- /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 +void f () +{ + (foo[0])(1.1); + (foo2[0])(1); +} + +void +g () +{ + f (); +}