Hi! On the following testcase trunk emits a false positive warning on ia32. convert_like_internal is there called with type of double and expr EXCESS_PRECISION_EXPR with float type with long double operand 2.L * (long double) x. Now, for the code generation we do the right thing, cp_convert to double from that 2.L * (long double) x, but we call even cp_convert_and_check with that and that emits the -Wfloat-conversion warning. Looking at what the C FE does in this case, it calls convert_and_check with the EXCESS_PRECISION_EXPR expression rather than its operand, and essentially uses the operand for code generation and EXCESS_PRECISION_EXPR itself for warnings.
The following patch does that too for the C++ FE. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2023-01-11 Jakub Jelinek <ja...@redhat.com> PR c++/108285 * cvt.cc (cp_convert_and_check): For EXCESS_PRECISION_EXPR use its operand except that for warning purposes use the original EXCESS_PRECISION_EXPR. * call.cc (convert_like_internal): Only look through EXCESS_PRECISION_EXPR when calling cp_convert, not when calling cp_convert_and_check. * g++.dg/warn/pr108285.C: New test. --- gcc/cp/cvt.cc.jj 2022-10-14 09:32:32.403797521 +0200 +++ gcc/cp/cvt.cc 2023-01-10 13:53:00.639130717 +0100 @@ -652,8 +652,10 @@ cp_convert (tree type, tree expr, tsubst tree cp_convert_and_check (tree type, tree expr, tsubst_flags_t complain) { - tree result; + tree result, expr_for_warning = expr; + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + expr = TREE_OPERAND (expr, 0); if (TREE_TYPE (expr) == type) return expr; if (expr == error_mark_node) @@ -663,7 +665,7 @@ cp_convert_and_check (tree type, tree ex if ((complain & tf_warning) && c_inhibit_evaluation_warnings == 0) { - tree folded = cp_fully_fold (expr); + tree folded = cp_fully_fold (expr_for_warning); tree folded_result; if (folded == expr) folded_result = result; --- gcc/cp/call.cc.jj 2023-01-09 23:41:11.135159084 +0100 +++ gcc/cp/call.cc 2023-01-10 13:50:09.277640628 +0100 @@ -8863,12 +8863,14 @@ convert_like_internal (conversion *convs return error_mark_node; warning_sentinel w (warn_zero_as_null_pointer_constant); - if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) - expr = TREE_OPERAND (expr, 0); if (issue_conversion_warnings) expr = cp_convert_and_check (totype, expr, complain); else - expr = cp_convert (totype, expr, complain); + { + if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR) + expr = TREE_OPERAND (expr, 0); + expr = cp_convert (totype, expr, complain); + } return expr; } --- gcc/testsuite/g++.dg/warn/pr108285.C.jj 2023-01-10 16:52:06.115345345 +0100 +++ gcc/testsuite/g++.dg/warn/pr108285.C 2023-01-10 16:39:26.646532929 +0100 @@ -0,0 +1,11 @@ +// PR c++/108285 +// { dg-do compile } +// { dg-options "-fexcess-precision=standard -Wfloat-conversion" } + +void bar (double); + +void +foo (float x) +{ + bar (2 * x); // { dg-bogus "conversion from '\[^\n\r]\*' to 'double' may change value" } +} Jakub