[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