static void lower_stmt (tree_stmt_iterator *tsi, struct lower_data *data) { tree stmt = tsi_stmt (*tsi); if (EXPR_HAS_LOCATION (stmt) && data) TREE_BLOCK (stmt) = data->block; switch (TREE_CODE (stmt)) { case BIND_EXPR: lower_bind_expr (tsi, data); return; case COND_EXPR: lower_cond_expr (tsi, data); return; case RETURN_EXPR: lower_return_expr (tsi, data); return; case TRY_FINALLY_EXPR: case TRY_CATCH_EXPR: lower_stmt_body (TREE_OPERAND (stmt, 0), data); lower_stmt_body (TREE_OPERAND (stmt, 1), data); break; case CATCH_EXPR: lower_stmt_body (CATCH_BODY (stmt), data); break; case EH_FILTER_EXPR: lower_stmt_body (EH_FILTER_FAILURE (stmt), data); break; case NOP_EXPR: case ASM_EXPR: case MODIFY_EXPR: case CALL_EXPR: case GOTO_EXPR: case LABEL_EXPR: case SWITCH_EXPR: break; default: #ifdef ENABLE_CHECKING print_node_brief (stderr, "", stmt, 0); internal_error ("unexpected node"); #endif case COMPOUND_EXPR: gcc_unreachable (); } tsi_next (tsi); }
static bool try_catch_may_fallthru (const_tree stmt) { tree_stmt_iterator i; /* If the TRY block can fall through, the whole TRY_CATCH can fall through. */ if (block_may_fallthru (TREE_OPERAND (stmt, 0))) return true; i = tsi_start (TREE_OPERAND (stmt, 1)); switch (TREE_CODE (tsi_stmt (i))) { case CATCH_EXPR: /* We expect to see a sequence of CATCH_EXPR trees, each with a catch expression and a body. The whole TRY_CATCH may fall through iff any of the catch bodies falls through. */ for (; !tsi_end_p (i); tsi_next (&i)) { if (block_may_fallthru (CATCH_BODY (tsi_stmt (i)))) return true; } return false; case EH_FILTER_EXPR: /* The exception filter expression only matters if there is an exception. If the exception does not match EH_FILTER_TYPES, we will execute EH_FILTER_FAILURE, and we will fall through if that falls through. If the exception does match EH_FILTER_TYPES, the stack unwinder will continue up the stack, so we will not fall through. We don't know whether we will throw an exception which matches EH_FILTER_TYPES or not, so we just ignore EH_FILTER_TYPES and assume that we might throw an exception which doesn't match. */ return block_may_fallthru (EH_FILTER_FAILURE (tsi_stmt (i))); default: /* This case represents statements to be executed when an exception occurs. Those statements are implicitly followed by a RESX statement to resume execution after the exception. So in this case the TRY_CATCH never falls through. */ return false; } }