[PATCH] Fix PR45034
Richard Guenther
rguenther@suse.de
Wed Jul 28 12:39:00 GMT 2010
This fixes yet another undefined signed overflow introduced by
narrowing done via convert_to_integer. We can always use an
unsigned type for negate or bitwise not which avoids the issue.
Bootstrapped and tested on x86_64-unknown-linux-gnu, ok?
Thanks,
Richard.
2010-07-28 Richard Guenther <rguenther@suse.de>
PR middle-end/45034
* convert.c (convert_to_integer): Always use an unsigned
type for narrowed negate and bitwise not.
* gcc.c-torture/execute/pr45034.c: New testcase.
Index: gcc/convert.c
===================================================================
*** gcc/convert.c (revision 162562)
--- gcc/convert.c (working copy)
*************** convert_to_integer (tree type, tree expr
*** 799,812 ****
/* This is not correct for ABS_EXPR,
since we must test the sign before truncation. */
{
! tree typex;
!
! /* Don't do unsigned arithmetic where signed was wanted,
! or vice versa. */
! if (TYPE_UNSIGNED (TREE_TYPE (expr)))
! typex = unsigned_type_for (type);
! else
! typex = signed_type_for (type);
return convert (type,
fold_build1 (ex_form, typex,
convert (typex,
--- 799,805 ----
/* This is not correct for ABS_EXPR,
since we must test the sign before truncation. */
{
! tree typex = unsigned_type_for (type);
return convert (type,
fold_build1 (ex_form, typex,
convert (typex,
Index: gcc/testsuite/gcc.c-torture/execute/pr45034.c
===================================================================
*** gcc/testsuite/gcc.c-torture/execute/pr45034.c (revision 0)
--- gcc/testsuite/gcc.c-torture/execute/pr45034.c (revision 0)
***************
*** 0 ****
--- 1,45 ----
+ extern void abort (void);
+ static void fixnum_neg(signed char x, signed char *py, int *pv)
+ {
+ unsigned char ux, uy;
+
+ ux = (unsigned char)x;
+ uy = -ux;
+ *py = (uy <= 127) ? (signed char)uy : (-(signed char)(255 - uy) - 1);
+ *pv = (x == -128) ? 1 : 0;
+ }
+
+ void __attribute__((noinline)) foo(int x, int y, int v)
+ {
+ if (y < -128 || y > 127)
+ abort();
+ }
+
+ int test_neg(void)
+ {
+ signed char x, y;
+ int v, err;
+
+ err = 0;
+ x = -128;
+ for (;;) {
+ fixnum_neg(x, &y, &v);
+ foo((int)x, (int)y, v);
+ if ((v && x != -128) || (!v && x == -128))
+ ++err;
+ if (x == 127)
+ break;
+ ++x;
+ }
+ return err;
+ }
+
+ int main(void)
+ {
+ if (sizeof (char) != 1)
+ return 0;
+ if (test_neg() != 0)
+ abort();
+ return 0;
+ }
+
More information about the Gcc-patches
mailing list