diff options
author | Marek Polacek <polacek@redhat.com> | 2021-03-03 18:37:49 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-03-17 19:26:25 -0400 |
commit | 40465293cd780aa82dcae75dfcfb1449d8c0561e (patch) | |
tree | afe709bf81a04c581dad3b8c99bc3617bf8a93df /gcc/cp/call.c | |
parent | be246ac2d26e1cb072f205bf97d5eac150220f3f (diff) | |
download | gcc-40465293cd780aa82dcae75dfcfb1449d8c0561e.tar.gz |
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.
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 29f4b50fb66..390b8aa4325 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) |