diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-01-13 18:23:57 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-01-13 18:23:57 +0100 |
commit | 3456db4de8940235b303ca38a689353854c9239f (patch) | |
tree | 8ed8ca4781c33441f22e56dd743915016e9520c5 | |
parent | 325a79b2c629bb7a2271dfebd678a27afcef4d01 (diff) | |
download | gcc-3456db4de8940235b303ca38a689353854c9239f.zip gcc-3456db4de8940235b303ca38a689353854c9239f.tar.gz gcc-3456db4de8940235b303ca38a689353854c9239f.tar.bz2 |
c++: Avoid some false positive -Wfloat-conversion warnings with extended precision [PR108285]
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.
2023-01-13 Jakub Jelinek <jakub@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.
-rw-r--r-- | gcc/cp/call.cc | 8 | ||||
-rw-r--r-- | gcc/cp/cvt.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/pr108285.C | 11 |
3 files changed, 20 insertions, 5 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index bd174b8..2cad1c0 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -8863,12 +8863,14 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, 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; } diff --git a/gcc/cp/cvt.cc b/gcc/cp/cvt.cc index 434d306..1cd2b4a 100644 --- a/gcc/cp/cvt.cc +++ b/gcc/cp/cvt.cc @@ -652,8 +652,10 @@ cp_convert (tree type, tree expr, tsubst_flags_t complain) 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 expr, tsubst_flags_t complain) 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; diff --git a/gcc/testsuite/g++.dg/warn/pr108285.C b/gcc/testsuite/g++.dg/warn/pr108285.C new file mode 100644 index 0000000..74cb234 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/pr108285.C @@ -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" } +} |