This fixes PR60115 where the issue is that tree_could_trap_p does
not evaluate MEM_REFs for possibly out-of-bound accesses (in case
the access is lowered from an ARRAY_REF where the code does that).

I've unified TARGET_MEM_REF and MEM_REF handling and made the
order of checking for trapping base and !TREE_THIS_NOTRAP match
the (non-obvious?) way ARRAY_REF handling works.

Testing for an overlap of at least on byte (thus not considering
the size of the access) should be ok IMHO as alignment constraints
or outer component refs should impose enough constraints that
the source should be invalid if that's not enough.

Bootstrapped and tested on x86_64-unknown-linux-gnu.

Does this look sane?

Thanks,
Richard.

2014-02-10  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/60115
        * tree-eh.c (tree_could_trap_p): Unify TARGET_MEM_REF and
        MEM_REF handling.  Properly verify that the accesses are not
        out of the objects bound.

        * gcc.dg/torture/pr60115.c: New testcase.

Index: gcc/tree-eh.c
===================================================================
*** gcc/tree-eh.c       (revision 207649)
--- gcc/tree-eh.c       (working copy)
*************** tree_could_trap_p (tree expr)
*** 2610,2621 ****
   restart:
    switch (code)
      {
-     case TARGET_MEM_REF:
-       if (TREE_CODE (TMR_BASE (expr)) == ADDR_EXPR
-         && !TMR_INDEX (expr) && !TMR_INDEX2 (expr))
-       return false;
-       return !TREE_THIS_NOTRAP (expr);
- 
      case COMPONENT_REF:
      case REALPART_EXPR:
      case IMAGPART_EXPR:
--- 2610,2615 ----
*************** tree_could_trap_p (tree expr)
*** 2642,2651 ****
        return false;
        return !in_array_bounds_p (expr);
  
      case MEM_REF:
!       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
        return false;
!       /* Fallthru.  */
      case INDIRECT_REF:
        return !TREE_THIS_NOTRAP (expr);
  
--- 2636,2671 ----
        return false;
        return !in_array_bounds_p (expr);
  
+     case TARGET_MEM_REF:
      case MEM_REF:
!       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR
!         && tree_could_trap_p (TREE_OPERAND (TREE_OPERAND (expr, 0), 0)))
!       return true;
!       if (TREE_THIS_NOTRAP (expr))
        return false;
!       /* We cannot prove that the access is in-bounds when we have
!          variable-index TARGET_MEM_REFs.  */
!       if (code == TARGET_MEM_REF
!         && (TMR_INDEX (expr) || TMR_INDEX2 (expr)))
!       return true;
!       if (TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR)
!       {
!         tree base = TREE_OPERAND (TREE_OPERAND (expr, 0), 0);
!         double_int off = mem_ref_offset (expr);
!         if (off.is_negative ())
!           return true;
!         if (TREE_CODE (base) == STRING_CST)
!           return double_int::from_uhwi (TREE_STRING_LENGTH (base)).ule (off);
!         else if (DECL_SIZE_UNIT (base) == NULL_TREE
!                  || TREE_CODE (DECL_SIZE_UNIT (base)) != INTEGER_CST
!                  || tree_to_double_int (DECL_SIZE_UNIT (base)).ule (off))
!           return true;
!         /* Now we are sure the first byte of the access is inside
!            the object.  */
!         return false;
!       }
!       return true;
! 
      case INDIRECT_REF:
        return !TREE_THIS_NOTRAP (expr);
  
Index: gcc/testsuite/gcc.dg/torture/pr60115.c
===================================================================
*** gcc/testsuite/gcc.dg/torture/pr60115.c      (revision 0)
--- gcc/testsuite/gcc.dg/torture/pr60115.c      (working copy)
***************
*** 0 ****
--- 1,14 ----
+ /* { dg-do run } */
+ 
+ int a, b[2];
+ 
+ int
+ main ()
+ {
+ lbl:
+   for (; a; a--)
+     if (b[10000])
+       goto lbl;
+ 
+   return 0;
+ }

Reply via email to