[backport from gcc-4.7/trunk ] gcc/ 2011-05-23 Richard Guenther PR tree-optimization/49115 * tree-ssa-alias.c (stmt_kills_ref_p_1): If the assignment is not necessarily carried out, do not claim it kills the ref. * tree-ssa-dce.c (mark_aliased_reaching_defs_necessary_1): Likewise. gcc/testsuite/ 2011-05-23 Richard Guenther PR tree-optimization/49115 * g++.dg/torture/pr49115.C: New testcase. --- gcc-4.6.0/gcc/testsuite/g++.dg/torture/pr49115.C.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.6.0/gcc/testsuite/g++.dg/torture/pr49115.C 2011-05-23 21:50:58.000000000 +0200 @@ -0,0 +1,25 @@ +// { dg-do run } + +extern "C" void abort (void); +struct MyException {}; +struct Data { + int nr; + Data() : nr(66) {} +}; +Data __attribute__((noinline,noclone)) getData(int i) +{ + if (i) throw MyException(); + Data data; + data.nr = i; + return data; +} +int main(int, char **) +{ + Data data; + try { + data = getData(1); + } catch (MyException& e) { + if (data.nr != 66) + abort (); + } +} --- gcc-4.6.0/gcc/tree-ssa-alias.c.~1~ 2011-03-03 13:10:40.000000000 +0100 +++ gcc-4.6.0/gcc/tree-ssa-alias.c 2011-05-23 21:50:58.000000000 +0200 @@ -1607,7 +1607,14 @@ static bool stmt_kills_ref_p_1 (gimple stmt, ao_ref *ref) { if (gimple_has_lhs (stmt) - && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME) + && TREE_CODE (gimple_get_lhs (stmt)) != SSA_NAME + /* The assignment is not necessarily carried out if it can throw + and we can catch it in the current function where we could inspect + the previous value. + ??? We only need to care about the RHS throwing. For aggregate + assignments or similar calls and non-call exceptions the LHS + might throw as well. */ + && !stmt_can_throw_internal (stmt)) { tree base, lhs = gimple_get_lhs (stmt); HOST_WIDE_INT size, offset, max_size; --- gcc-4.6.0/gcc/tree-ssa-dce.c.~1~ 2010-11-17 11:43:21.000000000 +0100 +++ gcc-4.6.0/gcc/tree-ssa-dce.c 2011-05-23 21:50:58.000000000 +0200 @@ -529,7 +529,14 @@ mark_aliased_reaching_defs_necessary_1 ( /* If the stmt lhs kills ref, then we can stop walking. */ if (gimple_has_lhs (def_stmt) - && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME) + && TREE_CODE (gimple_get_lhs (def_stmt)) != SSA_NAME + /* The assignment is not necessarily carried out if it can throw + and we can catch it in the current function where we could inspect + the previous value. + ??? We only need to care about the RHS throwing. For aggregate + assignments or similar calls and non-call exceptions the LHS + might throw as well. */ + && !stmt_can_throw_internal (def_stmt)) { tree base, lhs = gimple_get_lhs (def_stmt); HOST_WIDE_INT size, offset, max_size;