This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR26763, pointer overflow


This patch addresses PR26763 which is another case where we end up
with an expression relying on pointer overflow being defined.  I have
convinced myself that it is a bad idea to assume anything about pointer
overflow, so the only thing we can safely fold is equality and inequality.

Another possibility would be to split the cases of ADDR_EXPR 
(ARRAY_REF(..)) from the cases that only look like these again and rely
on the array domain for folding.  (This also hints at possible problems
with the mem-refs as array-ref thing)

Can anyone specify the conditions in where we are allowed to do
&a[i] CMP &a[j]  ->  i CMP j  conversion and in which cases
a +- i CMP a +- j  ->  i CMP j  ?  (note that i and j are pointers
in the latter case and the addition/subtraction is either signed or
unsigned dependent on the signedness of pointers)

So, as a stop-gap for now, ok for mainline?  (I'll make sure to XFAIL
valid transformations we no longer perform in the testcases that are
around there)

Thanks,
Richard.


2006-04-03  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/26763
	* fold-const.c (fold_comparison): Fold PTR + CST CMP PTR + CST
	only for EQ_EXPR and NE_EXPR.

	* gcc.dg/torture/pr26763-1.c: New testcase.
	* gcc.dg/torture/pr26763-2.c: Likewise.

Index: fold-const.c
===================================================================
*** fold-const.c	(revision 112634)
--- fold-const.c	(working copy)
*************** fold_comparison (enum tree_code code, tr
*** 7307,7336 ****
  
    /* If this is a comparison of two exprs that look like an
       ARRAY_REF of the same object, then we can fold this to a
!      comparison of the two offsets.  */
!   {
!     tree base0, offset0, base1, offset1;
! 
!     if (extract_array_ref (arg0, &base0, &offset0)
! 	&& extract_array_ref (arg1, &base1, &offset1)
! 	&& operand_equal_p (base0, base1, 0))
!       {
! 	/* Handle no offsets on both sides specially.  */
! 	if (offset0 == NULL_TREE && offset1 == NULL_TREE)
! 	  return fold_build2 (code, type, integer_zero_node,
! 			      integer_zero_node);
! 
! 	if (!offset0 || !offset1
! 	    || TREE_TYPE (offset0) == TREE_TYPE (offset1))
! 	  {
! 	    if (offset0 == NULL_TREE)
! 	      offset0 = build_int_cst (TREE_TYPE (offset1), 0);
! 	    if (offset1 == NULL_TREE)
! 	      offset1 = build_int_cst (TREE_TYPE (offset0), 0);
! 	    return fold_build2 (code, type, offset0, offset1);
! 	  }
!       }
!   }
  
    /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1.  */
    if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
--- 7307,7338 ----
  
    /* If this is a comparison of two exprs that look like an
       ARRAY_REF of the same object, then we can fold this to a
!      comparison of the two offsets.  This is only safe for
!      EQ_EXPR and NE_EXPR because of overflow issues.  */
!   if (code == EQ_EXPR || code == NE_EXPR)
!     {
!       tree base0, offset0, base1, offset1;
! 
!       if (extract_array_ref (arg0, &base0, &offset0)
! 	  && extract_array_ref (arg1, &base1, &offset1)
! 	  && operand_equal_p (base0, base1, 0))
!         {
! 	  /* Handle no offsets on both sides specially.  */
! 	  if (offset0 == NULL_TREE && offset1 == NULL_TREE)
! 	    return fold_build2 (code, type, integer_zero_node,
! 			        integer_zero_node);
! 
! 	  if (!offset0 || !offset1
! 	      || TREE_TYPE (offset0) == TREE_TYPE (offset1))
! 	    {
! 	      if (offset0 == NULL_TREE)
! 	        offset0 = build_int_cst (TREE_TYPE (offset1), 0);
! 	      if (offset1 == NULL_TREE)
! 	        offset1 = build_int_cst (TREE_TYPE (offset0), 0);
! 	      return fold_build2 (code, type, offset0, offset1);
! 	    }
!         }
!     }
  
    /* Transform comparisons of the form X +- C1 CMP C2 to X CMP C2 +- C1.  */
    if ((TREE_CODE (arg0) == PLUS_EXPR || TREE_CODE (arg0) == MINUS_EXPR)
Index: testsuite/gcc.dg/torture/pr26763-1.c
===================================================================
*** testsuite/gcc.dg/torture/pr26763-1.c	(revision 0)
--- testsuite/gcc.dg/torture/pr26763-1.c	(revision 0)
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do run } */
+ 
+ extern void abort(void);
+ 
+ int try (int *a)
+ {
+   return a + -1 > a;
+ }
+ 
+ int main(void)
+ {
+   int bla[100];
+ 
+   if (try (bla + 50))
+     abort ();
+ 
+   return 0;
+ }
Index: testsuite/gcc.dg/torture/pr26763-2.c
===================================================================
*** testsuite/gcc.dg/torture/pr26763-2.c	(revision 0)
--- testsuite/gcc.dg/torture/pr26763-2.c	(revision 0)
***************
*** 0 ****
--- 1,18 ----
+ /* { dg-do run } */
+ 
+ extern void abort(void);
+ 
+ int try (char *a, int d)
+ {
+   return a + d > a;
+ }
+ 
+ int main(void)
+ {
+   char bla[100];
+ 
+   if (try (bla + 50, -1))
+     abort ();
+ 
+   return 0;
+ }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]