diff options
author | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-06-16 01:21:38 +0000 |
---|---|---|
committer | rth <rth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2004-06-16 01:21:38 +0000 |
commit | 2363ef003652e46b5d1eb1b1bc7a93327168977a (patch) | |
tree | fd045b9b0d56d6e00876348ae58483539fd0ec02 /gcc/c-gimplify.c | |
parent | 53a9841beb1d5b151218420952cd30f98913a93d (diff) | |
download | gcc-2363ef003652e46b5d1eb1b1bc7a93327168977a.tar.gz |
* c-common.c (lang_gimplify_stmt): Remove next_p argument.
(if_elt, if_stack, if_stack_space, c_expand_start_cond, c_finish_then,
c_expand_end_cond, c_expand_start_else, c_finish_else, c_begin_if_stmt,
c_begin_while_stmt, c_finish_while_stmt_cond): Move to c-typeck.c.
(finish_fname_decls, fname_decl): Use statement_lists.
(c_expand_expr_stmt): Don't set last_expr_type.
(c_type_hash): Fix indentation.
(c_safe_from_p): Don't follow TREE_CHAIN.
(c_tree_chain_matters_p): Remove.
* c-common.def (SCOPE_STMT): Remove.
(CLEANUP_STMT): Redefine to contain its own body.
* c-common.h (struct stmt_tree_s): Remove x_last_stmt,
x_last_expr_type, x_last_expr_filename, x_scope_stmt_stack.
Add x_cur_stmt_list.
(last_tree, last_expr_type, last_expr_filename, RECHAIN_STMTS): Remove.
(cur_stmt_list): New.
(STATEMENT_LIST_STMT_EXPR): New.
(SCOPE_BEGIN_P, SCOPE_END_P, SCOPE_STMT_BLOCK, SCOPE_NULLIFIED_P,
SCOPE_NO_CLEANUPS_P, SCOPE_PARTIAL_P, NEW_FOR_SCOPE_P): Remove.
(CLEANUP_BODY): New.
(CLEANUP_DECL): Move to operand 2.
(c_common_stmt_codes): Remove SCOPE_STMT.
(COMPOUND_STMT_NO_SCOPE, COMPOUND_STMT_BODY_BLOCK): Remove.
* c-decl.c (c_scope_stmt_stack, current_scope_stmt_stack): Remove.
(c_push_function_context, c_pop_function_context): Don't save it.
(finish_decl): Set TREE_USED on the decl for a cleanup.
Use push_cleanup.
(store_parm_decls): Use statement lists.
(finish_function): Remove compstmt rule workaround. Use statement
lists. Call finish_fname_decls after finalizing the body.
(c_begin_compound_stmt): Move to c-typeck.c.
* c-dump.c (c_dump_tree): Remove SCOPE_STMT.
* c-gimplify.c (gimplify_cleanup_stmt, gimplify_cleanup_stmts): New.
(c_genericize): Invoke them.
(c_gimplify_stmt): Don't look through TREE_CHAIN. Kill SCOPE_STMT.
(c_build_bind_expr): Export.
(gimplify_block, gimplify_cleanup): Remove.
(gimplify_condition): Use gimplify_stmt.
(gimplify_for_stmt): Remove FOR_INIT_STMT chaining hack.
(gimplify_if_stmt): Remove recursion hack.
(c_gimplify_expr): Remove STMT_EXPR handling.
(stmt_expr_last_stmt, gimplify_stmt_expr): Remove.
(is_last_stmt_of_scope): Remove.
* c-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P): Remove.
* c-mudflap.c (mflang_flush_calls): Use c_begin_compound_stmt,
c_end_compound_stmt.
* c-objc-common.c (build_cdtor): Likewise.
* c-parse.in (primary): Use c_finish_stmt_expr.
(push_scope, pop_scope): Remove.
(c99_block_start, compstmt_start): Use c_begin_compound_stmt.
(c99_block_end, compstmt): Use c_end_compound_stmt.
(c99_block_lineno_labeled_stmt): Likewise.
(compstmt_primary_start): Use c_begin_stmt_expr.
(simple_if, select_or_iter_stmt): Update calls to stmt builders.
(do_stmt_start): Fill in body directly.
(lineno_stmt): Avoid setting lineno on constants.
* c-pretty-print.c (pp_c_statement): Handle STATEMENT_LIST.
Remove SCOPE_STMT.
* c-semantics.c (begin_stmt_tree): Remove.
(push_stmt_list, re_push_stmt_list, pop_stmt_list): New.
(add_stmt): Use statement lists.
(add_scope_stmt, finish_stmt_tree): Remove.
(push_cleanup): New.
* c-tree.h: Move some decls from c-common.h.
* c-typeck.c (c_tree_expr_nonnegative_p): Simplify for statement lists.
(do_case, c_finish_case): Likewise.
(c_finish_then): Take body for then as argument.
(c_finish_else): Similarly.
(c_begin_for_stmt, c_finish_for_stmt_init, c_finish_for_stmt_cond,
c_finish_for_stmt_incr, c_finish_for_stmt): New.
(c_begin_stmt_expr, c_finish_stmt_expr): New.
(c_begin_compound_stmt): Do scope management.
(c_end_compound_stmt): New.
* fold-const.c (tree_expr_nonnegative_p): Fix BIND_EXPR.
* gimplify.c (voidify_wrapper_expr): Accept temporary argument.
Look through exception handling constructs.
(gimplify_bind_expr): Accept temporary argument.
(gimplify_target_expr): Special case BIND_EXPR bodies.
(gimplify_expr): Handle fallback == fb_none like a statement.
* langhooks-def.h (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P): Kill.
* langhooks.c (lhd_tree_inlining_tree_chain_matters_p): Remove.
* langhooks.h (tree_chain_matters_p): Remove.
* stub-objc.c (objc_clear_super_receiver): New.
* tree-gimple.h (voidify_wrapper_expr): Update decl.
(append_to_statement_list, append_to_statement_list_force): Move
to tree-iterator.h.
* tree-inline.c (expand_call_inline): Update call.
(clone_body): Use statement lists.
(walk_tree): Don't check tree_chain_matters_p.
(copy_tree_r): Likewise.
* tree-iterator.c (alloc_stmt_list): Clear lang bits.
(tsi_link_before, tsi_link_after): Set TREE_SIDE_EFFECTS properly.
* tree-iterator.h (append_to_statement_list,
append_to_statement_list_force): Moved from tree-gimple.h.
* tree-pretty-print.c (dump_generic_node): Clean up TARGET_EXPR dump.
* objc/objc-act.c (build_module_descriptor): Use c_begin_compound_stmt.
(objc_enter_block): Likewise.
(objc_exit_block): Use c_end_compound_stmt.
(objc_build_try_enter_fragment): Add #error and comment for
rewriting for OBJCPLUS.
(objc_build_extract_fragment, objc_build_try_epilogue,
objc_build_catch_stmt, objc_build_finally_prologue,
objc_build_finally_epilogue): Update for C statement builders.
* objc/objc-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P):
Remove.
cp/
* call.c (initialize_reference): Don't build CLEANUP_STMT here.
* cp-gimplify.c (cp_gimplify_stmt): Remove next_p argument.
(genericize_try_block): Use gimplify_stmt.
(genericize_catch_block, genericize_eh_spec_block): Likewise.
(cp_gimplify_init_expr): Remove STMT_EXPR special case.
(gimplify_must_not_throw_expr): Update voidify_wrapper_expr call.
* cp-lang.c (LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P): Remove.
(cp_tree_chain_matters_p): Remove.
* cp-tree.h (COMPOUND_STMT_TRY_BLOCK): New.
(COMPOUND_STMT_BODY_BLOCK): New.
(STATEMENT_LIST_NO_SCOPE, STATEMENT_LIST_TRY_BLOCK): New.
(EXPR_STMT_STMT_EXPR_RESULT): New.
(building_stmt_tree): Check cur_stmt_list.
(tf_stmt_expr_cmpd, tf_stmt_expr_body): Remove.
(BCS_NO_SCOPE, BCS_TRY_BLOCK, BCS_FN_BODY): New.
* decl.c (poplevel): Use pop_stmt_list for minding cleanups.
(cp_finish_decl): Use push_cleanup.
(start_function, finish_function): Use statement lists.
(finish_stmt): Do nothing.
* except.c (begin_eh_spec_block): Use statement lists.
(check_handlers_1, check_handlers): Likewise.
* init.c (construct_virtual_base): Don't add extra compound stmts.
(build_vec_init): Likewise.
* name-lookup.c (maybe_push_cleanup_level): Use statement lists.
* name-lookup.h (struct cp_binding_level): Add statement_list.
* parser.c (cp_parser_statement): Take the STMT_EXPR node, not a bool.
(cp_parser_labeled_statement, cp_parser_expression_statement,
cp_parser_statement_seq_opt): Likewise.
(cp_parser_compound_statement): Likewise. Take bool for try block.
(cp_parser_selection_statement): Tidy if processing.
(cp_parser_already_scoped_statement): Rewrite to do what it says.
* pt.c (tsubst_copy): Move STMT_EXPR to tsubst_expr.
(tsubst_expr): Rewrite STMT_EXPR processing. Handle STATEMENT_LIST.
Mind COMPOUND_STMT_TRY_BLOCK, EXPR_STMT_STMT_EXPR_RESULT.
* semantics.c (do_poplevel, do_pushlevel): Use statement lists.
(finish_cond): New, rewritten from FINISH_COND.
(simplify_loop_decl_cond): New.
(finish_expr_stmt): Avoid nested EXPR_STMTs.
(begin_if_stmt, finish_if_stmt_cond, finish_then_clause,
begin_else_clause, finish_else_clause, finish_if_stmt,
begin_while_stmt, finish_while_stmt_cond, finish_while_stmt,
begin_do_stmt, finish_do_body, begin_for_stmt, finish_for_init_stmt,
finish_for_cond, finish_for_stmt, begin_switch_stmt,
finish_switch_cond, finish_switch_stmt, begin_try_block,
finish_try_block, finish_cleanup_try_block, finish_function_try_block,
finish_handler_sequence, finish_function_handler_sequence,
begin_handler, finish_handler_parms, finish_handler,
begin_stmt_expr, finish_stmt_expr_expr, finish_stmt_expr): Rewrite
using statement lists.
(begin_compound_stmt): Replace has_no_scope argument with flags.
Update all callers. Use statement lists.
(finish_compound_stmt): Likewise.
(finish_decl_cleanup, finish_eh_cleanup): Use push_cleanup.
(current_scope_stmt_stack): Remove.
(simplify_aggr_init_expr): Don't muck with TREE_CHAIN.
* typeck2.c (split_nonconstant_init_1, split_nonconstant_init):
Rewrite with statement lists.
testsuite/
* g++.dg/ext/stmtexpr1.C: XFAIL.
* gcc.dg/20030612-1.c: XFAIL.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83221 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-gimplify.c')
-rw-r--r-- | gcc/c-gimplify.c | 516 |
1 files changed, 144 insertions, 372 deletions
diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index d6b24320aa0..484cc7c772f 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -80,17 +80,11 @@ static enum gimplify_status gimplify_do_stmt (tree *); static enum gimplify_status gimplify_if_stmt (tree *); static enum gimplify_status gimplify_switch_stmt (tree *); static enum gimplify_status gimplify_return_stmt (tree *); -static enum gimplify_status gimplify_stmt_expr (tree *); static enum gimplify_status gimplify_compound_literal_expr (tree *); -#if defined ENABLE_CHECKING -static int is_last_stmt_of_scope (tree); -#endif -static enum gimplify_status gimplify_block (tree *, tree *); -static enum gimplify_status gimplify_cleanup (tree *, tree *); +static void gimplify_cleanup_stmts (tree); static tree gimplify_c_loop (tree, tree, tree, bool); static void push_context (void); static void pop_context (void); -static tree c_build_bind_expr (tree, tree); static void add_block_to_enclosing (tree); static void gimplify_condition (tree *); @@ -160,6 +154,7 @@ c_genericize (tree fndecl) /* Go ahead and gimplify for now. */ push_context (); + gimplify_cleanup_stmts (fndecl); gimplify_function_tree (fndecl); pop_context (); @@ -174,14 +169,41 @@ c_genericize (tree fndecl) c_genericize (cgn->decl); } +/* Genericize a CLEANUP_STMT. This just turns into a TRY_FINALLY or + TRY_CATCH depending on whether it's EH-only. */ + +static tree +gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees, + void *data ATTRIBUTE_UNUSED) +{ + tree stmt = *stmt_p; + + if (DECL_P (stmt) || TYPE_P (stmt)) + *walk_subtrees = 0; + else if (TREE_CODE (stmt) == CLEANUP_STMT) + *stmt_p = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR, + void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt)); + + return NULL; +} + +static void +gimplify_cleanup_stmts (tree fndecl) +{ + walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL); +} + /* Entry point for the tree lowering pass. Recursively scan *STMT_P and convert it to a GIMPLE tree. */ int c_gimplify_stmt (tree *stmt_p) { - tree stmt, next; - tree outer_pre = NULL_TREE; + tree stmt = *stmt_p; + tree pre, post; + int saved_stmts_are_full_exprs_p; + location_t stmt_locus; + enum gimplify_status ret; /* PRE and POST are tree chains that contain the side-effects of the gimplified tree. For instance, given the expression tree: @@ -195,152 +217,130 @@ c_gimplify_stmt (tree *stmt_p) c = t1 + b; b = b + 1; <-- POST */ - for (stmt = *stmt_p; stmt && stmt != error_mark_node; stmt = next) - { - tree pre, post; - int saved_stmts_are_full_exprs_p; - location_t stmt_locus; - enum gimplify_status ret; - - /* Set up context appropriately for handling this statement. */ - saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); - prep_stmt (stmt); - stmt_locus = input_location; + /* Set up context appropriately for handling this statement. */ + saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); + prep_stmt (stmt); + stmt_locus = input_location; - pre = NULL_TREE; - post = NULL_TREE; + pre = NULL_TREE; + post = NULL_TREE; - next = TREE_CHAIN (stmt); + switch (TREE_CODE (stmt)) + { + case COMPOUND_STMT: + stmt = COMPOUND_BODY (stmt); + ret = GS_OK; + break; - switch (TREE_CODE (stmt)) - { - case COMPOUND_STMT: - stmt = COMPOUND_BODY (stmt); - ret = GS_OK; - break; + case FOR_STMT: + ret = gimplify_for_stmt (&stmt, &pre); + break; - case SCOPE_STMT: - ret = gimplify_block (&stmt, &next); - break; + case WHILE_STMT: + ret = gimplify_while_stmt (&stmt); + break; - case FOR_STMT: - ret = gimplify_for_stmt (&stmt, &next); - break; + case DO_STMT: + ret = gimplify_do_stmt (&stmt); + break; - case WHILE_STMT: - ret = gimplify_while_stmt (&stmt); - break; + case IF_STMT: + ret = gimplify_if_stmt (&stmt); + break; - case DO_STMT: - ret = gimplify_do_stmt (&stmt); - break; + case SWITCH_STMT: + ret = gimplify_switch_stmt (&stmt); + break; - case IF_STMT: - ret = gimplify_if_stmt (&stmt); - break; + case EXPR_STMT: + ret = gimplify_expr_stmt (&stmt); + break; - case SWITCH_STMT: - ret = gimplify_switch_stmt (&stmt); - break; + case RETURN_STMT: + ret = gimplify_return_stmt (&stmt); + break; - case EXPR_STMT: - ret = gimplify_expr_stmt (&stmt); - break; + case DECL_STMT: + ret = gimplify_decl_stmt (&stmt); + break; - case RETURN_STMT: - ret = gimplify_return_stmt (&stmt); - break; + case LABEL_STMT: + stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt)); + ret = GS_OK; + break; - case DECL_STMT: - ret = gimplify_decl_stmt (&stmt); - break; + case GOTO_STMT: + stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt)); + ret = GS_OK; + break; - case LABEL_STMT: - stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt)); - ret = GS_OK; - break; + case CASE_LABEL: + { + tree label = create_artificial_label (); + stmt = build (CASE_LABEL_EXPR, void_type_node, + CASE_LOW (stmt), CASE_HIGH (stmt), label); + ret = GS_OK; + } + break; - case GOTO_STMT: - stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt)); - ret = GS_OK; - break; + case CONTINUE_STMT: + stmt = build_bc_goto (bc_continue); + ret = GS_OK; + break; - case CASE_LABEL: - { - tree label = create_artificial_label (); - stmt = build (CASE_LABEL_EXPR, void_type_node, - CASE_LOW (stmt), CASE_HIGH (stmt), label); - ret = GS_OK; - } - break; + case BREAK_STMT: + stmt = build_bc_goto (bc_break); + ret = GS_OK; + break; - case CONTINUE_STMT: - stmt = build_bc_goto (bc_continue); - ret = GS_OK; - break; + case ASM_STMT: + { + tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt), + ASM_OUTPUTS (stmt), ASM_INPUTS (stmt), + ASM_CLOBBERS (stmt)); + ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt); + ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt); + stmt = new_stmt; + ret = GS_OK; + } + break; - case BREAK_STMT: - stmt = build_bc_goto (bc_break); + default: + if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt)) + { ret = GS_OK; break; - - case CLEANUP_STMT: - ret = gimplify_cleanup (&stmt, &next); - break; - - case ASM_STMT: - { - tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt), - ASM_OUTPUTS (stmt), ASM_INPUTS (stmt), - ASM_CLOBBERS (stmt)); - ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt); - ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt); - stmt = new_stmt; - ret = GS_OK; - } - break; - - default: - if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next)) - { - ret = GS_OK; - break; - } - - fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n"); - debug_tree (stmt); - abort (); - break; } - switch (ret) - { - case GS_ERROR: - goto cont; - case GS_OK: - gimplify_stmt (&stmt); - break; - case GS_ALL_DONE: - break; - default: - abort (); - } + fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n"); + debug_tree (stmt); + abort (); + break; + } - /* PRE and POST now contain a list of statements for all the - side-effects in STMT. */ + switch (ret) + { + case GS_ERROR: + goto cont; + case GS_OK: + gimplify_stmt (&stmt); + break; + case GS_ALL_DONE: + break; + default: + abort (); + } - append_to_statement_list (stmt, &pre); - append_to_statement_list (post, &pre); - annotate_all_with_locus (&pre, stmt_locus); + /* PRE and POST now contain a list of statements for all the + side-effects in STMT. */ - append_to_statement_list (pre, &outer_pre); - cont: - /* Restore saved state. */ - current_stmt_tree ()->stmts_are_full_exprs_p - = saved_stmts_are_full_exprs_p; - } - append_to_statement_list (stmt, &outer_pre); - *stmt_p = outer_pre; + append_to_statement_list (stmt, &pre); + append_to_statement_list (post, &pre); + annotate_all_with_locus (&pre, stmt_locus); + cont: + /* Restore saved state. */ + current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p; + *stmt_p = pre; return GS_ALL_DONE; } @@ -366,7 +366,7 @@ add_block_to_enclosing (tree block) BODY is a chain of C _STMT nodes for the contents of the scope, to be genericized. */ -static tree +tree c_build_bind_expr (tree block, tree body) { tree decls, bind; @@ -390,99 +390,15 @@ c_build_bind_expr (tree block, tree body) if (!body) body = build_empty_stmt (); - - bind = build (BIND_EXPR, void_type_node, decls, body, block); - TREE_SIDE_EFFECTS (bind) = 1; - - return bind; -} - -/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and - wrapping the intervening code in a BIND_EXPR. This function assumes - that matching SCOPE_STMTs will always appear in the same statement - sequence. */ - -static enum gimplify_status -gimplify_block (tree *stmt_p, tree *next_p) -{ - tree *p; - tree block; - tree bind; - int depth; - location_t stmt_locus; - - if (!SCOPE_BEGIN_P (*stmt_p)) + if (decls || block) { - /* Can wind up mismatched with syntax errors. */ - if (!errorcount && !sorrycount) - abort (); - *stmt_p = NULL; - return GS_ERROR; - } - - block = SCOPE_STMT_BLOCK (*stmt_p); - - /* Find the matching ending SCOPE_STMT. */ - depth = 1; - for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p)) - { - if (*p == NULL) - break; - if (TREE_CODE (*p) == SCOPE_STMT) - { - if (SCOPE_BEGIN_P (*p)) - ++depth; - else if (--depth == 0) - break; - } - } - - stmt_locus = input_location; - if (*p) - { - if (SCOPE_STMT_BLOCK (*p) != block) - abort (); - if (EXPR_LOCUS (*p)) - stmt_locus = *EXPR_LOCUS (*p); - *next_p = TREE_CHAIN (*p); - *p = NULL_TREE; + bind = build (BIND_EXPR, void_type_node, decls, body, block); + TREE_SIDE_EFFECTS (bind) = 1; } else - { - /* Can wind up mismatched with syntax errors. */ - if (!errorcount && !sorrycount) - abort (); - } - - bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p)); - *stmt_p = bind; - input_location = stmt_locus; + bind = body; - return GS_OK; -} - -/* Genericize a CLEANUP_STMT. Just wrap everything from here to the end of - the block in a TRY_FINALLY_EXPR. Or a TRY_CATCH_EXPR, if it's an - EH-only cleanup. */ - -static enum gimplify_status -gimplify_cleanup (tree *stmt_p, tree *next_p) -{ - tree stmt = *stmt_p; - tree body = TREE_CHAIN (stmt); - tree cleanup = CLEANUP_EXPR (stmt); - enum tree_code code - = (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR); - - if (!body) - body = build_empty_stmt (); - if (!cleanup) - cleanup = build_empty_stmt (); - - *stmt_p = build (code, void_type_node, body, cleanup); - *next_p = NULL_TREE; - - return GS_OK; + return bind; } /* Gimplify an EXPR_STMT node. @@ -549,7 +465,7 @@ gimplify_condition (tree *cond_p) { tree decl = TREE_PURPOSE (cond); tree value = TREE_VALUE (cond); - c_gimplify_stmt (&decl); + gimplify_stmt (&decl); *cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value); } } @@ -713,26 +629,17 @@ gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first) prequeue and hand off to gimplify_c_loop. */ static enum gimplify_status -gimplify_for_stmt (tree *stmt_p, tree *next_p) +gimplify_for_stmt (tree *stmt_p, tree *pre_p) { tree stmt = *stmt_p; - tree init = FOR_INIT_STMT (stmt); - if (init) + if (FOR_INIT_STMT (stmt)) { - /* Reorganize the statements so that we do the right thing with a - CLEANUP_STMT. We want the FOR_STMT and nothing else to be in the - scope of the cleanup, so play with pointers to accomplish that. */ - FOR_INIT_STMT (stmt) = NULL_TREE; - chainon (init, stmt); - *stmt_p = init; - *next_p = TREE_CHAIN (stmt); - TREE_CHAIN (stmt) = NULL_TREE; - c_gimplify_stmt (stmt_p); + gimplify_stmt (&FOR_INIT_STMT (stmt)); + append_to_statement_list (FOR_INIT_STMT (stmt), pre_p); } - else - *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt), - FOR_EXPR (stmt), 1); + *stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt), + FOR_EXPR (stmt), 1); return GS_ALL_DONE; } @@ -767,7 +674,6 @@ gimplify_if_stmt (tree *stmt_p) tree stmt, then_, else_; stmt = *stmt_p; - restart: then_ = THEN_CLAUSE (stmt); else_ = ELSE_CLAUSE (stmt); @@ -780,17 +686,6 @@ gimplify_if_stmt (tree *stmt_p) gimplify_condition (& TREE_OPERAND (stmt, 0)); *stmt_p = stmt; - /* Handle properly nested if-else chains via iteration instead of - mutual recursion between gimplify.c and c-simplify.c. */ - annotate_with_locus (stmt, input_location); - if (TREE_CODE (else_) == IF_STMT && !TREE_CHAIN (else_)) - { - stmt_p = &COND_EXPR_ELSE (stmt); - stmt = else_; - prep_stmt (stmt); - goto restart; - } - return GS_OK; } @@ -960,130 +855,7 @@ c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED, case COMPOUND_LITERAL_EXPR: return gimplify_compound_literal_expr (expr_p); - case STMT_EXPR: - return gimplify_stmt_expr (expr_p); - default: return GS_UNHANDLED; } } - -/* Returns the final EXPR_STMT which represents the return value of a - STMT_EXPR, or NULL_TREE if none. */ - -tree -stmt_expr_last_stmt (tree stmt_expr) -{ - tree body = STMT_EXPR_STMT (stmt_expr); - tree last_stmt, substmt; - - /* Splice the last expression out of the STMT chain. */ - last_stmt = NULL_TREE; - for (substmt = COMPOUND_BODY (body); substmt; - substmt = TREE_CHAIN (substmt)) - if (TREE_CODE (substmt) != SCOPE_STMT) - last_stmt = substmt; - - if (last_stmt == NULL_TREE - || TREE_CODE (last_stmt) != EXPR_STMT - || (TREE_TYPE (last_stmt) - && VOID_TYPE_P (TREE_TYPE (last_stmt)))) - { - location_t loc; - if (last_stmt && EXPR_LOCUS (last_stmt)) - loc = *EXPR_LOCUS (last_stmt); - else if (EXPR_LOCUS (stmt_expr)) - loc = *EXPR_LOCUS (stmt_expr); - else - loc = input_location; - warning ("%Hstatement-expressions should end with a " - "non-void expression", &loc); - last_stmt = NULL_TREE; - } - -#if defined ENABLE_CHECKING - if (last_stmt && !is_last_stmt_of_scope (last_stmt)) - abort (); -#endif - - return last_stmt; -} - -/* Gimplify a STMT_EXPR. EXPR_P points to the expression to gimplify. - After gimplification, if the STMT_EXPR returns a value, EXPR_P will - point to a new temporary that holds that value; otherwise it will be - null. - - PRE_P points to the list where side effects that must happen before - *EXPR_P should be stored. */ - -static enum gimplify_status -gimplify_stmt_expr (tree *expr_p) -{ - tree body = STMT_EXPR_STMT (*expr_p); - - if (VOID_TYPE_P (TREE_TYPE (*expr_p))) - { - *expr_p = body; - return c_gimplify_stmt (expr_p); - } - else - { - tree last_stmt = stmt_expr_last_stmt (*expr_p); - tree last_expr = NULL_TREE; - - if (last_stmt) - { - last_expr = EXPR_STMT_EXPR (last_stmt); - - if (stmts_are_full_exprs_p ()) - last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr), - last_expr); - EXPR_STMT_EXPR (last_stmt) = NULL_TREE; - } - - /* Genericize the block. */ - c_gimplify_stmt (&body); - - /* Now retrofit that last expression into the BIND_EXPR. */ - if (last_expr) - { - tree *sub_p; - - if (!STMT_EXPR_NO_SCOPE (*expr_p)) - { - /* Our BIND_EXPR will always be hidden within - a STATEMENT_LIST. Discard that. */ - body = expr_first (body); - sub_p = &BIND_EXPR_BODY (body); - - /* Append the last expression to the end of the BIND_EXPR. - We'll now re-process this, and let voidify_wrapper_expr - do its job. */ - append_to_statement_list_force (last_expr, sub_p); - TREE_TYPE (body) = TREE_TYPE (last_expr); - } - else - append_to_compound_expr (last_expr, &body); - } - - *expr_p = body; - return GS_OK; - } -} - -/* Code generation. */ - -/* Miscellaneous helpers. */ - -#if defined ENABLE_CHECKING -/* Return nonzero if STMT is the last statement of its scope. */ - -static int -is_last_stmt_of_scope (tree stmt) -{ - return (TREE_CHAIN (stmt) == NULL_TREE - || (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT - && SCOPE_END_P (TREE_CHAIN (stmt)))); -} -#endif |