static void lower_try_catch (gimple_stmt_iterator *gsi, struct lower_data *data) { bool cannot_fallthru; gimple stmt = gsi_stmt (*gsi); gimple_stmt_iterator i; /* We don't handle GIMPLE_TRY_FINALLY. */ gcc_assert (gimple_try_kind (stmt) == GIMPLE_TRY_CATCH); lower_sequence (gimple_try_eval_ptr (stmt), data); cannot_fallthru = data->cannot_fallthru; i = gsi_start (*gimple_try_cleanup_ptr (stmt)); switch (gimple_code (gsi_stmt (i))) { case GIMPLE_CATCH: /* We expect to see a sequence of GIMPLE_CATCH stmts, each with a catch expression and a body. The whole try/catch may fall through iff any of the catch bodies falls through. */ for (; !gsi_end_p (i); gsi_next (&i)) { data->cannot_fallthru = false; lower_sequence (gimple_catch_handler_ptr ( as_a <gcatch *> (gsi_stmt (i))), data); if (!data->cannot_fallthru) cannot_fallthru = false; } break; case GIMPLE_EH_FILTER: /* 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. */ data->cannot_fallthru = false; lower_sequence (gimple_eh_filter_failure_ptr (gsi_stmt (i)), data); if (!data->cannot_fallthru) cannot_fallthru = false; break; default: /* This case represents statements to be executed when an exception occurs. Those statements are implicitly followed by a GIMPLE_RESX to resume execution after the exception. So in this case the try/catch never falls through. */ data->cannot_fallthru = false; lower_sequence (gimple_try_cleanup_ptr (stmt), data); break; } data->cannot_fallthru = cannot_fallthru; gsi_next (gsi); }
tree walk_gimple_stmt (gimple_stmt_iterator *gsi, walk_stmt_fn callback_stmt, walk_tree_fn callback_op, struct walk_stmt_info *wi) { gimple *ret; tree tree_ret; gimple *stmt = gsi_stmt (*gsi); if (wi) { wi->gsi = *gsi; wi->removed_stmt = false; if (wi->want_locations && gimple_has_location (stmt)) input_location = gimple_location (stmt); } ret = NULL; /* Invoke the statement callback. Return if the callback handled all of STMT operands by itself. */ if (callback_stmt) { bool handled_ops = false; tree_ret = callback_stmt (gsi, &handled_ops, wi); if (handled_ops) return tree_ret; /* If CALLBACK_STMT did not handle operands, it should not have a value to return. */ gcc_assert (tree_ret == NULL); if (wi && wi->removed_stmt) return NULL; /* Re-read stmt in case the callback changed it. */ stmt = gsi_stmt (*gsi); } /* If CALLBACK_OP is defined, invoke it on every operand of STMT. */ if (callback_op) { tree_ret = walk_gimple_op (stmt, callback_op, wi); if (tree_ret) return tree_ret; } /* If STMT can have statements inside (e.g. GIMPLE_BIND), walk them. */ switch (gimple_code (stmt)) { case GIMPLE_BIND: ret = walk_gimple_seq_mod (gimple_bind_body_ptr (as_a <gbind *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_CATCH: ret = walk_gimple_seq_mod (gimple_catch_handler_ptr ( as_a <gcatch *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_EH_FILTER: ret = walk_gimple_seq_mod (gimple_eh_filter_failure_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_EH_ELSE: { geh_else *eh_else_stmt = as_a <geh_else *> (stmt); ret = walk_gimple_seq_mod (gimple_eh_else_n_body_ptr (eh_else_stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; ret = walk_gimple_seq_mod (gimple_eh_else_e_body_ptr (eh_else_stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; } break; case GIMPLE_TRY: ret = walk_gimple_seq_mod (gimple_try_eval_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; ret = walk_gimple_seq_mod (gimple_try_cleanup_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_OMP_FOR: ret = walk_gimple_seq_mod (gimple_omp_for_pre_body_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; /* FALL THROUGH. */ case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_MASTER: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS: ret = walk_gimple_seq_mod (gimple_omp_body_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_WITH_CLEANUP_EXPR: ret = walk_gimple_seq_mod (gimple_wce_cleanup_ptr (stmt), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; case GIMPLE_TRANSACTION: ret = walk_gimple_seq_mod (gimple_transaction_body_ptr ( as_a <gtransaction *> (stmt)), callback_stmt, callback_op, wi); if (ret) return wi->callback_result; break; default: gcc_assert (!gimple_has_substatements (stmt)); break; } return NULL; }