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 <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. 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.
This commit is contained in:
parent
be246ac2d2
commit
40465293cd
2 changed files with 39 additions and 1 deletions
|
@ -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)
|
||||
|
|
17
gcc/testsuite/g++.dg/conversion/real-to-int1.C
Normal file
17
gcc/testsuite/g++.dg/conversion/real-to-int1.C
Normal file
|
@ -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> ();
|
||||
}
|
Loading…
Add table
Reference in a new issue