Ever since operation_could_trap_helper_p claimed that CONSTRUCTOR (or COMPLEX_EXPR) cannot throw stmt_could_throw_1_p ignored whether the LHS of an assignment possibly could. The following fixes this by refactoring the code a bit and handling the LHS before the RHS.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2017-03-17 Richard Biener <rguent...@suse.de> PR middle-end/80075 * tree-eh.c (stmt_could_throw_1_p): Only handle gimple assigns. Properly verify the LHS before the RHS possibly claims to be handled. (stmt_could_throw_p): Hande gimple conds fully here. Clobbers do not throw. * g++.dg/torture/pr80075.C: New testcase. Index: gcc/tree-eh.c =================================================================== *** gcc/tree-eh.c (revision 246216) --- gcc/tree-eh.c (working copy) *************** tree_could_trap_p (tree expr) *** 2726,2734 **** an assignment or a conditional) may throw. */ static bool ! stmt_could_throw_1_p (gimple *stmt) { ! enum tree_code code = gimple_expr_code (stmt); bool honor_nans = false; bool honor_snans = false; bool fp_operation = false; --- 2726,2734 ---- an assignment or a conditional) may throw. */ static bool ! stmt_could_throw_1_p (gassign *stmt) { ! enum tree_code code = gimple_assign_rhs_code (stmt); bool honor_nans = false; bool honor_snans = false; bool fp_operation = false; *************** stmt_could_throw_1_p (gimple *stmt) *** 2742,2752 **** || TREE_CODE_CLASS (code) == tcc_binary || code == FMA_EXPR) { ! if (is_gimple_assign (stmt) ! && TREE_CODE_CLASS (code) == tcc_comparison) t = TREE_TYPE (gimple_assign_rhs1 (stmt)); - else if (gimple_code (stmt) == GIMPLE_COND) - t = TREE_TYPE (gimple_cond_lhs (stmt)); else t = gimple_expr_type (stmt); fp_operation = FLOAT_TYPE_P (t); --- 2742,2749 ---- || TREE_CODE_CLASS (code) == tcc_binary || code == FMA_EXPR) { ! if (TREE_CODE_CLASS (code) == tcc_comparison) t = TREE_TYPE (gimple_assign_rhs1 (stmt)); else t = gimple_expr_type (stmt); fp_operation = FLOAT_TYPE_P (t); *************** stmt_could_throw_1_p (gimple *stmt) *** 2759,2775 **** honor_trapv = true; } /* Check if the main expression may trap. */ - t = is_gimple_assign (stmt) ? gimple_assign_rhs2 (stmt) : NULL; ret = operation_could_trap_helper_p (code, fp_operation, honor_trapv, ! honor_nans, honor_snans, t, &handled); if (handled) return ret; /* If the expression does not trap, see if any of the individual operands may trap. */ ! for (i = 0; i < gimple_num_ops (stmt); i++) if (tree_could_trap_p (gimple_op (stmt, i))) return true; --- 2756,2776 ---- honor_trapv = true; } + /* First check the LHS. */ + if (tree_could_trap_p (gimple_assign_lhs (stmt))) + return true; + /* Check if the main expression may trap. */ ret = operation_could_trap_helper_p (code, fp_operation, honor_trapv, ! honor_nans, honor_snans, ! gimple_assign_rhs2 (stmt), &handled); if (handled) return ret; /* If the expression does not trap, see if any of the individual operands may trap. */ ! for (i = 1; i < gimple_num_ops (stmt); i++) if (tree_could_trap_p (gimple_op (stmt, i))) return true; *************** stmt_could_throw_p (gimple *stmt) *** 2795,2805 **** case GIMPLE_CALL: return !gimple_call_nothrow_p (as_a <gcall *> (stmt)); - case GIMPLE_ASSIGN: case GIMPLE_COND: ! if (!cfun->can_throw_non_call_exceptions) return false; ! return stmt_could_throw_1_p (stmt); case GIMPLE_ASM: if (!cfun->can_throw_non_call_exceptions) --- 2796,2817 ---- case GIMPLE_CALL: return !gimple_call_nothrow_p (as_a <gcall *> (stmt)); case GIMPLE_COND: ! { ! if (!cfun->can_throw_non_call_exceptions) ! return false; ! gcond *cond = as_a <gcond *> (stmt); ! tree lhs = gimple_cond_lhs (cond); ! return operation_could_trap_p (gimple_cond_code (cond), ! FLOAT_TYPE_P (TREE_TYPE (lhs)), ! false, NULL_TREE); ! } ! ! case GIMPLE_ASSIGN: ! if (!cfun->can_throw_non_call_exceptions ! || gimple_clobber_p (stmt)) return false; ! return stmt_could_throw_1_p (as_a <gassign *> (stmt)); case GIMPLE_ASM: if (!cfun->can_throw_non_call_exceptions) Index: gcc/testsuite/g++.dg/torture/pr80075.C =================================================================== *** gcc/testsuite/g++.dg/torture/pr80075.C (nonexistent) --- gcc/testsuite/g++.dg/torture/pr80075.C (working copy) *************** *** 0 **** --- 1,27 ---- + // { dg-do compile } + // { dg-additional-options "-fnon-call-exceptions" } + + struct s { + int i; + }; + + extern int use_memcpy; + extern void my_memcpy(void*, void*, int); + + int + f (struct s* p) + { + struct s a; + + try + { + a = (struct s){}; + if (!use_memcpy) + *p = a; + else + my_memcpy (p, &a, sizeof (struct s)); + } catch (...) { + return 0; + } + return 1; + }