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; + }