This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
gcc compiler bug
- To: bug-gcc at gnu dot org
- Subject: gcc compiler bug
- From: Dale Williamson <Dale dot Williamson at trw dot com>
- Date: Wed, 31 May 2000 15:55:51 -0700
- Cc: Al Danial <Al dot Danial at trw dot com>
/* File badbit.c
May 30, 2000
Originator: Dale R. Williamson
Synopsis: under certain circumstances the bits of a double number re-
turned from a function may not be reliably transferred to a variable across an equal sign, as in the expression: (double)X = (double)func()
Severity: serious
Priority: medium
Category: c
Class: wrong-code
Release: 2.91.66
Environment: linux, x86
Description: bit is being set incorrectly; no error message
How-to-Repeat: program provided below
Further information:
GCC version and system type:
gcc version: 2.7.2.3
redhat linux version 5.2
gcc version: 2.91.66
mandrake linux version 7
Compiler options:
> gcc badbit.c;a.out
Detailed description and program:
Using the gnu C compiler, it has been found that under certain circum-
stances the bits of a double number returned from a function may not be
reliably transferred to a variable across an equal sign, as in the ex-
pression: (double)X = (double)func().
The problem has serious implications for bit pattern encoding and decod-
ing when double words are used. It does not occur on other platforms
and appears to be related to the gcc compiler and x86 floating point
hardware.
The program on this file shows a bug where bit 52 (counting from 0 at
leftmost) is changed from 0 to 1 under certain conditions when a double
variable is equated to a function that returns a double word value.
It is shown that the bug does not occur when a long long int variable
is equated to a function returning a long long int value.
Three cases are run by the program where all 64 bits are set to 1 except
the ones noted.
The following output is produced on a machine running Redhat linux and
gcc version 2.7.2.3:
Case 1: only bit 52 equals zero
Y=X.x: equate to double value FFFFFFFFFFFFF7FF correct
Y=Ylong: equate to long long function FFFFFFFFFFFFF7FF correct
Y=Ydoub: equate to double function FFFFFFFFFFFFFFFF incorrect
Case 2: bit 52 and bit 0 equal zero
Y=X.x: equate to double value 7FFFFFFFFFFFF7FF correct
Y=Ylong: equate to long long function 7FFFFFFFFFFFF7FF correct
Y=Ydoub: equate to double function 7FFFFFFFFFFFFFFF incorrect
Case 3: bits 52 and 60 are zero
Y=X.x: equate to double value FFFFFFFFFFFFF7F7 correct
Y=Ylong: equate to long long function FFFFFFFFFFFFF7F7 correct
Y=Ydoub: equate to double function FFFFFFFFFFFFF7F7 correct
In cases 1 and 2, the bug occurs where a double variable is equated to a
function that returns a double word. In each case the value of bit 52
switches from 0 to 1.
In case 3 where one of the exponent bits is also 0, the bug does not
occur. Other cases like case 3 have been run, showing that the bug
does not occur when bit 52 is zero and any one of the 11 exponent bits
is also zero.
Looking at cases where one other bit might be zero at the same time, the
bug occurs when bit 52 is zero and no other bit is zero, or when bit 52
is zero and one of the other mantissa bits, or the sign bit, is zero.
Thus the bug occurs in 53 out of 64 instances where one other bit (or no
other bit) is zero simultaneously with bit 52.
Shown next are these cases run on a Mandrake system, and they show the
case of equating double value to double value to also be in error (the
cases for equating to a double value, labeled improperly by the built-in
format of the program, have been changed by hand):
Case 1: only bit 52 equals zero
Y=X.x: equate to double value FFFFFFFFFFFFFFFF incorrect
Y=Ylong: equate to long long function FFFFFFFFFFFFF7FF correct
Y=Ydoub: equate to double function FFFFFFFFFFFFFFFF incorrect
Case 2: bit 52 and bit 0 equal zero
Y=X.x: equate to double value 7FFFFFFFFFFFFFFF incorrect
Y=Ylong: equate to long long function 7FFFFFFFFFFFF7FF correct
Y=Ydoub: equate to double function 7FFFFFFFFFFFFFFF incorrect
Case 3: bits 52 and 60 are zero
Y=X.x: equate to double value FFFFFFFFFFFFF7F7 correct
Y=Ylong: equate to long long function FFFFFFFFFFFFF7F7 correct
Y=Ydoub: equate to double function FFFFFFFFFFFFF7F7 correct
Finally, here are results from an IBM workstation--all are correct (a-
gain with approprate hand editing of the labels to fix the program's
improper built-in ones). Of course on the workstation the bits being
set do not relate to the same mantissa or exponent bits.
Case 1: only bit 52 equals zero
Y=X.x: equate to double value FFFFFFFFFFF7FFFF correct
Y=Ylong: equate to long long function FFFFFFFFFFF7FFFF correct
Y=Ydoub: equate to double function FFFFFFFFFFF7FFFF correct
Case 2: bit 52 and bit 0 equal zero
Y=X.x: equate to double value FFFFFF7FFFF7FFFF correct
Y=Ylong: equate to long long function FFFFFF7FFFF7FFFF correct
Y=Ydoub: equate to double function FFFFFF7FFFF7FFFF correct
Case 3: bits 52 and 60 are zero
Y=X.x: equate to double value FFFFFFFFF7F7FFFF correct
Y=Ylong: equate to long long function FFFFFFFFF7F7FFFF correct
Y=Ydoub: equate to double function FFFFFFFFF7F7FFFF correct
For further information, feel free to contact me.
dale.williamson@trw.com
*/
#include <stdio.h>
union {
double x;
long long int l;
unsigned int i[2];
} static X={0};
double funcd() { return X.x; }
long long int funcl() { return X.l; }
void main()
{
int k;
union {
double d;
long long int l;
unsigned char c[sizeof(double)];
} Y={0};
/* Case 1 */
fprintf(stdout,"\n\r Case 1: only bit 52 equals zero\n\r");
X.i[0]=0xFFFFFFFF;
X.i[1]=0xFFF7FFFF;
Y.d=X.x;
fprintf(stdout," Y=X.x: equate to double value ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct\n\r");
Y.l=funcl();
fprintf(stdout," Y=Ylong: equate to long long function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct \n\r");
Y.d=funcd();
fprintf(stdout," Y=Ydoub: equate to double function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," incorrect\n\r");
/* Case 2 */
fprintf(stdout,"\n\r Case 2: bit 52 and bit 0 equal zero\n\r");
X.i[0]=0xFFFFFF7F;
X.i[1]=0xFFF7FFFF;
Y.d=X.x;
fprintf(stdout," Y=X.x: equate to double value ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct\n\r");
Y.l=funcl();
fprintf(stdout," Y=Ylong: equate to long long function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct \n\r");
Y.d=funcd();
fprintf(stdout," Y=Ydoub: equate to double function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," incorrect\n\r");
/* Case 3 */
fprintf(stdout,"\n\r Case 3: bits 52 and 60 are zero\n\r");
X.i[0]=0xFFFFFFFF;
X.i[1]=0xF7F7FFFF;
Y.d=X.x;
fprintf(stdout," Y=X.x: equate to double value ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct\n\r");
Y.l=funcl();
fprintf(stdout," Y=Ylong: equate to long long function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct \n\r");
Y.d=funcd();
fprintf(stdout," Y=Ydoub: equate to double function ");
for(k=0;k<sizeof(double);k++) fprintf(stdout,"%02X",*(Y.c+k));
fprintf(stdout," correct\n\r");
fprintf(stdout,"\n\r");
}