https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87390
Bug ID: 87390
Summary: GCC does not honor FLT_EVAL_METHOD on implicit
conversion of integer to floating point
Product: gcc
Version: 9.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: vincent-gcc at vinc17 dot net
Target Milestone: ---
On 32-bit x86, i.e. with FLT_EVAL_METHOD = 2, the following program
#include <stdio.h>
#include <float.h>
int main (void)
{
unsigned long long i = 1ULL << 63;
double d;
d = i;
printf ("FLT_EVAL_METHOD = %d\n", (int) FLT_EVAL_METHOD);
printf ("%d\n", d + 1.0 == (float) d + (float) 1.0);
printf ("%d\n", d == (float) d + (float) 1.0);
printf ("%d\n", d == i + 1);
return 0;
}
gives:
cventin:~> gcc-snapshot -std=c99 tst.c -o tst -m32
cventin:~> ./tst
FLT_EVAL_METHOD = 2
1
0
1
instead of 0 for the last line. Indeed, according to ISO C99 5.2.4.2.2:
Except for assignment and cast (which remove all extra range and precision),
the values of operations with floating operands and values subject to the
usual arithmetic conversions and of floating constants are evaluated to a
format whose range and precision may be greater than required by the type.
The use of evaluation formats is characterized by the implementation-defined
value of FLT_EVAL_METHOD:
[...]
2 evaluate all operations and constants to the range and precision of the
long double type.
(slightly changed in C11: "[...] the values yielded by operators with [...]").
For the first two tests, (float) d + (float) 1.0 has type float and has been
evaluated with the type long double, and for the == test, this expression is
converted to the semantic type double (because the left-hand side has type
double), but the evaluation type is long double, thus the results 1 and 0
respectively.
For the third test, i + 1 has type unsigned long long, and for the == test,
similarly, this expression should be converted to the semantic type double, but
the evaluation type should be long double, thus the result should be 0, like in
the second test, not 1.