🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gdb.bug
Article #8884

gdb 4.6 does not compare `float' to `int' correctly

#8884
From: Paul Eggert
Date: Wed, 15 Jul 1992 22:25
134 lines
5398 bytes
[I reported this bug for GDB 4.5, and got a comment back from the GDB
maintainers; the following bug report accordingly contains an improved patch.]

GDB 4.6 (SunOS 4.1.2, sparc) does not compare `float' to `int' correctly.  It
does the comparison by converting both sides to `double', and comparing the
results.  But in C, you're supposed to compare `float' to `int' by converting
the `int' to a `float', and comparing the resulting `float's.  GDB thus
sometimes reports two values to be not equal even though they are equal
according to C's rules.

Here is a shell transcript that illustrates the problem.

	$ cat t.c
		#define INT_MAX 2147483647
		float f = INT_MAX;
		int i = INT_MAX;
		int compare() { return i == f; }
		int main() { return compare(); }
	$ gcc -g t.c
	$ gdb a.out
	GDB is free software and you are welcome to distribute copies of it
	 under certain conditions; type "show copying" to see the conditions.
	There is absolutely no warranty for GDB; type "show warranty" for details.
	GDB 4.6, Copyright 1992 Free Software Foundation, Inc...
	(gdb) b compare
	Breakpoint 1 at 0x2294: file t.c, line 4.
	(gdb) r
	Starting program: /tmp/a.out 

	Breakpoint 1, compare () at t.c:4
	4               int compare() { return i == f; }
	(gdb) finish
	Run till exit from #0  compare () at t.c:4
	0x22dc in main () at t.c:5
	5               int main() { return compare(); }
	Value returned is $1 = 1
	(gdb) print i == f
	$2 = 0

compare() yields 1, so GDB should print 1 in the last line of output; but it
prints 0.  Here is a patch.

===================================================================
RCS file: valarith.c,v
retrieving revision 4.6
diff -c -r4.6 valarith.c
*** valarith.c	1992/07/06 17:11:18	4.6
--- valarith.c	1992/07/15 22:18:24
***************
*** 337,342 ****
--- 337,359 ----
    return 0;  /* For lint -- never reached */
  }
  
+ /* Convert two operands to floating point, converting to proper precision.  */
+ 
+ static void
+ value_floating_operands (arg1, arg2, av1, av2)
+      value arg1, arg2;
+      double *av1, *av2;
+ {
+   struct type *t1 = VALUE_TYPE (arg1);
+   struct type *t2 = VALUE_TYPE (arg2);
+   struct type *t =
+ 	TYPE_CODE (t1) != TYPE_CODE_FLT ? t2
+ 	: TYPE_CODE (t2) != TYPE_CODE_FLT ? t1
+ 	: TYPE_LENGTH (t1) < TYPE_LENGTH (t2) ? t2 : t1;
+   *av1 = value_as_double (value_from_double (t, value_as_double (arg1)));
+   *av2 = value_as_double (value_from_double (t, value_as_double (arg2)));
+ }
+ 
  /* Perform a binary operation on two integers or two floats.
     Does not support addition and subtraction on pointers;
     use value_add or value_sub if you want to handle those possibilities.  */
***************
*** 365,372 ****
        TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
      {
        double v1, v2, v;
!       v1 = value_as_double (arg1);
!       v2 = value_as_double (arg2);
        switch (op)
  	{
  	case BINOP_ADD:
--- 382,388 ----
        TYPE_CODE (VALUE_TYPE (arg2)) == TYPE_CODE_FLT)
      {
        double v1, v2, v;
!       value_floating_operands (arg1, arg2, &v1, &v2);
        switch (op)
  	{
  	case BINOP_ADD:
***************
*** 598,604 ****
      return value_as_long (arg1) == value_as_long (arg2);
    else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
  	   && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
!     return value_as_double (arg1) == value_as_double (arg2);
  
    /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
       is bigger.  */
--- 614,624 ----
      return value_as_long (arg1) == value_as_long (arg2);
    else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
  	   && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
!     {
!       double v1, v2;
!       value_floating_operands (arg1, arg2, &v1, &v2);
!       return v1 == v2;
!     }
  
    /* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
       is bigger.  */
***************
*** 654,660 ****
      }
    else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
  	   && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
!     return value_as_double (arg1) < value_as_double (arg2);
    else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
      return value_as_pointer (arg1) < value_as_pointer (arg2);
  
--- 674,684 ----
      }
    else if ((code1 == TYPE_CODE_FLT || code1 == TYPE_CODE_INT)
  	   && (code2 == TYPE_CODE_FLT || code2 == TYPE_CODE_INT))
!     {
!       double v1, v2;
!       value_floating_operands (arg1, arg2, &v1, &v2);
!       return v1 < v2;
!     }
    else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
      return value_as_pointer (arg1) < value_as_pointer (arg2);
  
Technical Details
Message-ID: <9207152225.AA20806@farside.twinsun.com>
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!twinsun.COM!eggert

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f5053,f54a404303543b7a,start
X-Google-Attributes: gidf5053,public
X-Google-ArrivalTime: 1992-07-15 16:59:20 PST
Newsgroups: gnu.gdb.bug
Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!twinsun.COM!eggert
From: eggert@twinsun.COM (Paul Eggert)
Subject: gdb 4.6 does not compare `float' to `int' correctly
Message-ID: <9207152225.AA20806@farside.twinsun.com>
Sender: gnulists@ai.mit.edu
Organization: GNUs Not Usenet
Distribution: gnu
Date: Wed, 15 Jul 1992 22:25:23 GMT
Approved: bug-gdb@prep.ai.mit.edu
Lines: 135