This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

gcc compiler bug


/* 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");
}



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]