🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gdb.bug
Article #8826

GDB 4.7 does not compare `float' to `int' the same way that C does

#8826
From: Paul Eggert
Date: Sun, 25 Oct 1992 18:23
140 lines
5745 bytes
GDB 4.7 (SunOS 4.1.2, sparc) does not compare `float' to `int' the same way
that ANSI C does.  It does the comparison by converting both sides to
`double', and comparing the results.  But in ANSI 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 that A<B or A>B even
though ANSI C says that A==B.  GDB's answer is mathematically correct, but the
discrepancy with C can lead to problems when debugging programs.

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.7, 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.

I reported this bug for GDB 4.5, and got a comment back from the GDB
maintainers asking for improvements; I submitted an improved bug report for
GDB 4.6, but the fix doesn't seem to have made its way into GDB 4.7.  Most
likely you just haven't gotten around to fixing this area, but I'm
resubmitting this report in case it got lost.  The same patch works for both
GDB 4.6 and GDB 4.7.

===================================================================
RCS file: gdb/valarith.c,v
retrieving revision 4.6
retrieving revision 4.6.1.1
diff -c -r4.6 -r4.6.1.1
*** gdb/valarith.c	1992/07/04 03:22:01	4.6
--- gdb/valarith.c	1992/07/15 22:18:24	4.6.1.1
***************
*** 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: <9210251823.AA10331@bi.twinsun.com>
Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!bi.TWinsun.COM!eggert

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f5053,4998b9400c63b1d1,start
X-Google-Attributes: gidf5053,public
X-Google-ArrivalTime: 1992-10-25 12:53:30 PST
Newsgroups: gnu.gdb.bug
Path: arc1-ca.pugleaf.net!sparky!uunet!cis.ohio-state.edu!bi.TWinsun.COM!eggert
From: eggert@bi.TWinsun.COM (Paul Eggert)
Subject: GDB 4.7 does not compare `float' to `int' the same way that C does
Message-ID: <9210251823.AA10331@bi.twinsun.com>
Sender: gnulists@ai.mit.edu
Organization: GNUs Not Usenet
Distribution: gnu
Date: Sun, 25 Oct 1992 18:23:16 GMT
Approved: bug-gdb@prep.ai.mit.edu
Lines: 141