Article View: gnu.gdb.bug
Article #8884gdb 4.6 does not compare `float' to `int' correctly
From: Paul Eggert
Date: Wed, 15 Jul 1992 22:25
Date: Wed, 15 Jul 1992 22:25
134 lines
5398 bytes
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!eggertShow 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