From 5a5086621e8751f9666cf0a3d5956149202e1487 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Sun, 20 Jun 2004 02:18:13 -0700 Subject: [PATCH] c-common.def (IF_STMT, [...]): Move to cp-tree.def. * c-common.def (IF_STMT, CLEANUP_STMT): Move to cp-tree.def. * c-common.h (IF_COND, THEN_CLAUSE, ELSE_CLAUSE, CLEANUP_BODY, CLEANUP_EXPR, CLEANUP_DECL): Move to cp-tree.h. (c_common_stmt_codes): Remove IF_STMT, CLEANUP_STMT. * c-dump.c (c_dump_tree): Move IF_STMT, CLEANUP_STMT to cp_dump_tree. * c-pretty-print.c (pp_c_statement): Similarly. * c-gimplify.c (gimplify_cleanup_stmt, gimplify_cleanup_stmts, gimplify_if_stmt): Move to cp-gimplify.c. (c_genericize, c_gimplify_expr): Don't call them. * c-semantics.c (push_cleanup): Move to cp/semantics.c. * c-typeck.c (push_cleanup): New. (c_begin_if_stmt, c_finish_if_cond, c_finish_then, c_finish_else, c_finish_if_stmt): Use COND_EXPR. * tree.h (CLEANUP_EH_ONLY): Update documentation. cp/ * cp-tree.def (CLEANUP_STMT, IF_STMT): Move from c-common.def. * cp-gimplify.c (gimplify_if_stmt): Move from c-gimplify.c. (cp_gimplify_expr): Call it. (gimplify_cleanup_stmt): Move from c-gimplify.c. (cp_genericize): New. * decl.c (finish_function): Call it. * cp-tree.h (cp_stmt_codes): Add CLEANUP_STMT, IF_STMT. (CLEANUP_BODY, CLEANUP_EXPR, CLEANUP_DECL): Move from c-common.h. (IF_COND, THEN_CLAUSE, ELSE_CLAUSE): Likewise. (cp_genericize): Declare. * cxx-pretty-print.c (pp_cxx_statement): Add CLEANUP_STMT, IF_STMT. * dump.c (cp_dump_tree): Likewise. * semantics.c (push_cleanup): Move from c-semantics.c. From-SVN: r83407 --- gcc/ChangeLog | 17 +++++++++ gcc/c-common.def | 9 ----- gcc/c-common.h | 20 +---------- gcc/c-dump.c | 15 -------- gcc/c-gimplify.c | 52 --------------------------- gcc/c-pretty-print.c | 76 ++++----------------------------------- gcc/c-semantics.c | 13 ------- gcc/c-typeck.c | 27 ++++++++++---- gcc/cp/ChangeLog | 16 +++++++++ gcc/cp/cp-gimplify.c | 55 ++++++++++++++++++++++++++++ gcc/cp/cp-tree.def | 14 ++++++++ gcc/cp/cp-tree.h | 17 ++++++++- gcc/cp/cxx-pretty-print.c | 37 +++++++++++++++++++ gcc/cp/decl.c | 2 +- gcc/cp/dump.c | 18 +++++++++- gcc/cp/semantics.c | 13 +++++++ gcc/tree.h | 9 +++-- 17 files changed, 218 insertions(+), 192 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index acb2bffd3f5..fd9f0ac0ee1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2004-06-20 Richard Henderson + + * c-common.def (IF_STMT, CLEANUP_STMT): Move to cp-tree.def. + * c-common.h (IF_COND, THEN_CLAUSE, ELSE_CLAUSE, CLEANUP_BODY, + CLEANUP_EXPR, CLEANUP_DECL): Move to cp-tree.h. + (c_common_stmt_codes): Remove IF_STMT, CLEANUP_STMT. + * c-dump.c (c_dump_tree): Move IF_STMT, CLEANUP_STMT to cp_dump_tree. + * c-pretty-print.c (pp_c_statement): Similarly. + * c-gimplify.c (gimplify_cleanup_stmt, gimplify_cleanup_stmts, + gimplify_if_stmt): Move to cp-gimplify.c. + (c_genericize, c_gimplify_expr): Don't call them. + * c-semantics.c (push_cleanup): Move to cp/semantics.c. + * c-typeck.c (push_cleanup): New. + (c_begin_if_stmt, c_finish_if_cond, c_finish_then, c_finish_else, + c_finish_if_stmt): Use COND_EXPR. + * tree.h (CLEANUP_EH_ONLY): Update documentation. + 2004-06-20 Zack Weinberg * c-common.h (has_c_linkage): New interface. diff --git a/gcc/c-common.def b/gcc/c-common.def index b66098a3a27..62dd05703cf 100644 --- a/gcc/c-common.def +++ b/gcc/c-common.def @@ -37,10 +37,6 @@ DEFTREECODE (EXPR_STMT, "expr_stmt", 'e', 1) DECL_STMT_DECL. */ DEFTREECODE (DECL_STMT, "decl_stmt", 'e', 1) -/* Represents an 'if' statement. The operands are IF_COND, - THEN_CLAUSE, and ELSE_CLAUSE, respectively. */ -DEFTREECODE (IF_STMT, "if_stmt", 'e', 3) - /* Used to represent a `for' statement. The operands are FOR_INIT_STMT, FOR_COND, FOR_EXPR, and FOR_BODY, respectively. */ DEFTREECODE (FOR_STMT, "for_stmt", 'e', 4) @@ -78,11 +74,6 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", 'e', 1) the compound literal. */ DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", 'e', 1) -/* A CLEANUP_STMT marks the point at which a declaration is fully - constructed. The CLEANUP_EXPR is run on behalf of CLEANUP_DECL - when CLEANUP_BODY completes. */ -DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 3) - /* Local variables: mode:c diff --git a/gcc/c-common.h b/gcc/c-common.h index 91a18869b2d..073ff70e4ec 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -922,13 +922,6 @@ extern void finish_file (void); #define STATEMENT_LIST_STMT_EXPR(NODE) \ TREE_LANG_FLAG_1 (STATEMENT_LIST_CHECK (NODE)) -/* IF_STMT accessors. These give access to the condition of the if - statement, the then block of the if statement, and the else block - of the if statement if it exists. */ -#define IF_COND(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 0) -#define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) -#define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) - /* WHILE_STMT accessors. These give access to the condition of the while statement and the body of the while statement, respectively. */ #define WHILE_COND(NODE) TREE_OPERAND (WHILE_STMT_CHECK (NODE), 0) @@ -975,16 +968,6 @@ extern void finish_file (void); #define COMPOUND_LITERAL_EXPR_DECL(NODE) \ DECL_STMT_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE)) -/* The body of the CLEANUP_STMT. */ -#define CLEANUP_BODY(NODE) \ - TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 0) -/* The cleanup to run in a CLEANUP_STMT. */ -#define CLEANUP_EXPR(NODE) \ - TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 1) -/* The VAR_DECL to clean up in a CLEANUP_STMT. */ -#define CLEANUP_DECL(NODE) \ - TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 2) - #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, enum c_tree_code { @@ -996,8 +979,7 @@ enum c_tree_code { #undef DEFTREECODE #define c_common_stmt_codes \ - CLEANUP_STMT, EXPR_STMT, \ - DECL_STMT, IF_STMT, FOR_STMT, \ + EXPR_STMT, DECL_STMT, FOR_STMT, \ WHILE_STMT, DO_STMT, RETURN_STMT, \ BREAK_STMT, CONTINUE_STMT, SWITCH_STMT diff --git a/gcc/c-dump.c b/gcc/c-dump.c index 74ef44db032..18a8887295f 100644 --- a/gcc/c-dump.c +++ b/gcc/c-dump.c @@ -69,13 +69,6 @@ c_dump_tree (void *dump_info, tree t) dump_next_stmt (di, t); break; - case CLEANUP_STMT: - dump_stmt (di, t); - dump_child ("decl", CLEANUP_DECL (t)); - dump_child ("expr", CLEANUP_EXPR (t)); - dump_next_stmt (di, t); - break; - case DECL_STMT: dump_stmt (di, t); dump_child ("decl", DECL_STMT_DECL (t)); @@ -104,14 +97,6 @@ c_dump_tree (void *dump_info, tree t) dump_next_stmt (di, t); break; - case IF_STMT: - dump_stmt (di, t); - dump_child ("cond", IF_COND (t)); - dump_child ("then", THEN_CLAUSE (t)); - dump_child ("else", ELSE_CLAUSE (t)); - dump_next_stmt (di, t); - break; - case RETURN_STMT: dump_stmt (di, t); dump_child ("expr", RETURN_STMT_EXPR (t)); diff --git a/gcc/c-gimplify.c b/gcc/c-gimplify.c index 1f8ce647b9d..fa3ea299cc4 100644 --- a/gcc/c-gimplify.c +++ b/gcc/c-gimplify.c @@ -72,8 +72,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA /* Local declarations. */ -static void gimplify_cleanup_stmts (tree); - enum bc_t { bc_break = 0, bc_continue = 1 }; static struct c_gimplify_ctx @@ -137,7 +135,6 @@ c_genericize (tree fndecl) /* Go ahead and gimplify for now. */ push_context (); - gimplify_cleanup_stmts (fndecl); gimplify_function_tree (fndecl); pop_context (); @@ -152,30 +149,6 @@ 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); -} - static void add_block_to_enclosing (tree block) { @@ -479,28 +452,6 @@ gimplify_do_stmt (tree *stmt_p) return GS_ALL_DONE; } -/* Genericize an IF_STMT by turning it into a COND_EXPR. */ - -static enum gimplify_status -gimplify_if_stmt (tree *stmt_p) -{ - tree stmt, then_, else_; - - stmt = *stmt_p; - then_ = THEN_CLAUSE (stmt); - else_ = ELSE_CLAUSE (stmt); - - if (!then_) - then_ = build_empty_stmt (); - if (!else_) - else_ = build_empty_stmt (); - - stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_); - *stmt_p = stmt; - - return GS_OK; -} - /* Genericize a SWITCH_STMT by turning it into a SWITCH_EXPR. */ static enum gimplify_status @@ -670,9 +621,6 @@ c_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p ATTRIBUTE_UNUSED) case DO_STMT: return gimplify_do_stmt (expr_p); - case IF_STMT: - return gimplify_if_stmt (expr_p); - case SWITCH_STMT: return gimplify_switch_stmt (expr_p); diff --git a/gcc/c-pretty-print.c b/gcc/c-pretty-print.c index 490cf809800..7ecbe6b08da 100644 --- a/gcc/c-pretty-print.c +++ b/gcc/c-pretty-print.c @@ -1889,75 +1889,22 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) if (stmt == NULL) return; + + if (pp_needs_newline (pp)) + pp_newline_and_indent (pp, 0); code = TREE_CODE (stmt); switch (code) { - case STATEMENT_LIST: - { - tree_stmt_iterator tsi; - - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); - pp_c_left_brace (pp); - pp_newline_and_indent (pp, 3); - for (tsi = tsi_start (stmt); !tsi_end_p (tsi); tsi_next (&tsi)) - pp_statement (pp, tsi_stmt (tsi)); - pp_newline_and_indent (pp, -3); - pp_c_right_brace (pp); - pp_needs_newline (pp) = true; - } - break; - /* expression-statement: expression(opt) ; */ case EXPR_STMT: - case CLEANUP_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); - { - tree e = code == EXPR_STMT - ? EXPR_STMT_EXPR (stmt) - : CLEANUP_EXPR (stmt); - if (e) - pp_expression (pp, e); - } + pp_expression (pp, EXPR_STMT_EXPR (stmt)); pp_c_semicolon (pp); pp_needs_newline (pp) = true; break; - /* selection-statement: - if ( expression ) statement - if ( expression ) statement else statement - switch ( expression ) statement */ - case IF_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); - pp_c_identifier (pp, "if"); - pp_c_whitespace (pp); - pp_c_left_paren (pp); - pp_expression (pp, IF_COND (stmt)); - pp_c_right_paren (pp); - pp_newline_and_indent (pp, 3); - pp_statement (pp, THEN_CLAUSE (stmt)); - pp_newline_and_indent (pp, -3); - if (ELSE_CLAUSE (stmt)) - { - tree else_clause = ELSE_CLAUSE (stmt); - pp_c_identifier (pp, "else"); - if (TREE_CODE (else_clause) == IF_STMT) - pp_c_whitespace (pp); - else - pp_newline_and_indent (pp, 3); - pp_statement (pp, else_clause); - if (TREE_CODE (else_clause) != IF_STMT) - pp_newline_and_indent (pp, -3); - } - break; - case SWITCH_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_c_identifier (pp, "switch"); pp_space (pp); pp_c_left_paren (pp); @@ -1975,8 +1922,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) for ( expression(opt) ; expression(opt) ; expression(opt) ) statement for ( declaration expression(opt) ; expression(opt) ) statement */ case WHILE_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_c_identifier (pp, "while"); pp_space (pp); pp_c_left_paren (pp); @@ -1989,8 +1934,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) break; case DO_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_c_identifier (pp, "do"); pp_newline_and_indent (pp, 3); pp_statement (pp, DO_BODY (stmt)); @@ -2005,8 +1948,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) break; case FOR_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_c_identifier (pp, "for"); pp_space (pp); pp_c_left_paren (pp); @@ -2036,8 +1977,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) return expression(opt) ; */ case BREAK_STMT: case CONTINUE_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_identifier (pp, code == BREAK_STMT ? "break" : "continue"); pp_c_semicolon (pp); pp_needs_newline (pp) = true; @@ -2046,8 +1985,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) case RETURN_STMT: { tree e = RETURN_STMT_EXPR (stmt); - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_c_identifier (pp, "return"); pp_c_whitespace (pp); if (e) @@ -2063,14 +2000,13 @@ pp_c_statement (c_pretty_printer *pp, tree stmt) break; case DECL_STMT: - if (pp_needs_newline (pp)) - pp_newline_and_indent (pp, 0); pp_declaration (pp, DECL_STMT_DECL (stmt)); pp_needs_newline (pp) = true; break; default: - pp_unsupported_tree (pp, stmt); + dump_generic_node (pp_base (pp), stmt, pp_indentation (pp), 0, true); + break; } } diff --git a/gcc/c-semantics.c b/gcc/c-semantics.c index 8a98e07b3a3..ba4e90b4911 100644 --- a/gcc/c-semantics.c +++ b/gcc/c-semantics.c @@ -158,19 +158,6 @@ add_decl_stmt (tree decl) add_stmt (decl_stmt); } -/* Queue a cleanup. CLEANUP is an expression/statement to be executed - when the current scope is exited. EH_ONLY is true when this is not - meant to apply to normal control flow transfer. */ - -void -push_cleanup (tree decl, tree cleanup, bool eh_only) -{ - tree stmt = build_stmt (CLEANUP_STMT, NULL, cleanup, decl); - CLEANUP_EH_ONLY (stmt) = eh_only; - add_stmt (stmt); - CLEANUP_BODY (stmt) = push_stmt_list (); -} - /* Build a generic statement based on the given type of node and arguments. Similar to `build_nt', except that we set EXPR_LOCUS to be the current source location. */ diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index b2718b6b79a..201c5f1c114 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -6483,8 +6483,7 @@ static int if_stack_space = 0; /* Stack pointer. */ static int if_stack_pointer = 0; -/* Begin an if-statement. Returns a newly created IF_STMT if - appropriate. */ +/* Begin an if-statement. */ void c_begin_if_stmt (void) @@ -6504,7 +6503,7 @@ c_begin_if_stmt (void) if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt)); } - r = add_stmt (build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE)); + r = add_stmt (build_stmt (COND_EXPR, NULL_TREE, NULL_TREE, NULL_TREE)); /* Record this if statement. */ elt = &if_stack[if_stack_pointer++]; @@ -6527,7 +6526,7 @@ c_finish_if_cond (tree cond, int compstmt_count, int stmt_count) if_elt *elt = &if_stack[if_stack_pointer - 1]; elt->compstmt_count = compstmt_count; elt->stmt_count = stmt_count; - IF_COND (elt->if_stmt) = lang_hooks.truthvalue_conversion (cond); + COND_EXPR_COND (elt->if_stmt) = lang_hooks.truthvalue_conversion (cond); } /* Called after the then-clause for an if-statement is processed. */ @@ -6536,7 +6535,7 @@ void c_finish_then (tree then_stmt) { if_elt *elt = &if_stack[if_stack_pointer - 1]; - THEN_CLAUSE (elt->if_stmt) = then_stmt; + COND_EXPR_THEN (elt->if_stmt) = then_stmt; elt->empty_locus = input_location; } @@ -6570,7 +6569,7 @@ void c_finish_else (tree else_stmt) { if_elt *elt = &if_stack[if_stack_pointer - 1]; - ELSE_CLAUSE (elt->if_stmt) = else_stmt; + COND_EXPR_ELSE (elt->if_stmt) = else_stmt; elt->empty_locus = input_location; } @@ -6582,6 +6581,9 @@ c_finish_if_stmt (int stmt_count) { if_elt *elt = &if_stack[--if_stack_pointer]; + if (COND_EXPR_ELSE (elt->if_stmt) == NULL) + COND_EXPR_ELSE (elt->if_stmt) = build_empty_stmt (); + if (elt->needs_warning) warning ("%Hsuggest explicit braces to avoid ambiguous `else'", EXPR_LOCUS (elt->if_stmt)); @@ -6781,6 +6783,19 @@ c_end_compound_stmt (tree stmt, bool do_scope) return stmt; } + +/* Queue a cleanup. CLEANUP is an expression/statement to be executed + when the current scope is exited. EH_ONLY is true when this is not + meant to apply to normal control flow transfer. */ + +void +push_cleanup (tree decl ATTRIBUTE_UNUSED, tree cleanup, bool eh_only) +{ + enum tree_code code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR; + tree stmt = build_stmt (code, NULL, cleanup); + add_stmt (stmt); + TREE_OPERAND (stmt, 0) = push_stmt_list (); +} /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e3048d3dba0..b01e1f8b49d 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2004-06-20 Richard Henderson + + * cp-tree.def (CLEANUP_STMT, IF_STMT): Move from c-common.def. + * cp-gimplify.c (gimplify_if_stmt): Move from c-gimplify.c. + (cp_gimplify_expr): Call it. + (gimplify_cleanup_stmt): Move from c-gimplify.c. + (cp_genericize): New. + * decl.c (finish_function): Call it. + * cp-tree.h (cp_stmt_codes): Add CLEANUP_STMT, IF_STMT. + (CLEANUP_BODY, CLEANUP_EXPR, CLEANUP_DECL): Move from c-common.h. + (IF_COND, THEN_CLAUSE, ELSE_CLAUSE): Likewise. + (cp_genericize): Declare. + * cxx-pretty-print.c (pp_cxx_statement): Add CLEANUP_STMT, IF_STMT. + * dump.c (cp_dump_tree): Likewise. + * semantics.c (push_cleanup): Move from c-semantics.c. + 2004-06-20 Zack Weinberg * cp-lang.c (has_c_linkage): Implement. diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 99016434e42..8bdf5f4fcc5 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -79,6 +79,26 @@ genericize_eh_spec_block (tree *stmt_p) *stmt_p = gimple_build_eh_filter (body, allowed, failure); } +/* Genericize an IF_STMT by turning it into a COND_EXPR. */ + +static void +gimplify_if_stmt (tree *stmt_p) +{ + tree stmt, then_, else_; + + stmt = *stmt_p; + then_ = THEN_CLAUSE (stmt); + else_ = ELSE_CLAUSE (stmt); + + if (!then_) + then_ = build_empty_stmt (); + if (!else_) + else_ = build_empty_stmt (); + + stmt = build (COND_EXPR, void_type_node, IF_COND (stmt), then_, else_); + *stmt_p = stmt; +} + /* Gimplify initialization from an AGGR_INIT_EXPR. */ static void @@ -224,6 +244,11 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) ret = GS_ALL_DONE; break; + case IF_STMT: + gimplify_if_stmt (expr_p); + ret = GS_OK; + break; + default: ret = c_gimplify_expr (expr_p, pre_p, post_p); break; @@ -236,3 +261,33 @@ cp_gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p) return ret; } + +/* 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; +} + +void +cp_genericize (tree fndecl) +{ + /* Due to the way voidify_wrapper_expr is written, we don't get a chance + to lower this construct before scanning it. So we need to lower these + before doing anything else. */ + walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL); + + /* Do everything else. */ + c_genericize (fndecl); +} diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 3b4c6e6eb5a..4f7961b7b8a 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -243,8 +243,11 @@ DEFTREECODE (NON_DEPENDENT_EXPR, "non_dependent_expr", 'e', 1) /* CTOR_INITIALIZER is a placeholder in template code for a call to setup_vtbl_pointer (and appears in all functions, not just ctors). */ DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1) + DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2) + DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2) + /* A HANDLER wraps a catch handler for the HANDLER_TYPE. If this is CATCH_ALL_TYPE, then the handler catches all types. The declaration of the catch variable is in HANDLER_PARMS, and the body block in @@ -255,6 +258,17 @@ DEFTREECODE (HANDLER, "handler", 'e', 2) throw, and must call terminate if it does. */ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1) +/* A CLEANUP_STMT marks the point at which a declaration is fully + constructed. The CLEANUP_EXPR is run on behalf of CLEANUP_DECL + when CLEANUP_BODY completes. */ +DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 3) + +/* Represents an 'if' statement. The operands are IF_COND, + THEN_CLAUSE, and ELSE_CLAUSE, respectively. */ +/* ??? It is currently still necessary to distinguish between IF_STMT + and COND_EXPR for the benefit of templates. */ +DEFTREECODE (IF_STMT, "if_stmt", 'e', 3) + DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0) /* Template instantiation level node. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1838c8288f9..ae62adc70dd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -892,7 +892,8 @@ enum cplus_tree_code { #define cp_stmt_codes \ CTOR_INITIALIZER, TRY_BLOCK, HANDLER, \ - EH_SPEC_BLOCK, USING_STMT, TAG_DEFN + EH_SPEC_BLOCK, USING_STMT, TAG_DEFN, \ + IF_STMT, CLEANUP_STMT enum languages { lang_c, lang_cplusplus, lang_java }; @@ -2939,6 +2940,19 @@ struct lang_decl GTY(()) #define HANDLER_BODY(NODE) TREE_OPERAND (HANDLER_CHECK (NODE), 1) #define HANDLER_TYPE(NODE) TREE_TYPE (HANDLER_CHECK (NODE)) +/* CLEANUP_STMT accessors. The statement(s) covered, the cleanup to run + and the VAR_DECL for which this cleanup exists. */ +#define CLEANUP_BODY(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 0) +#define CLEANUP_EXPR(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 1) +#define CLEANUP_DECL(NODE) TREE_OPERAND (CLEANUP_STMT_CHECK (NODE), 2) + +/* IF_STMT accessors. These give access to the condition of the if + statement, the then block of the if statement, and the else block + of the if statement if it exists. */ +#define IF_COND(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 0) +#define THEN_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 1) +#define ELSE_CLAUSE(NODE) TREE_OPERAND (IF_STMT_CHECK (NODE), 2) + /* The parameters for a call-declarator. */ #define CALL_DECLARATOR_PARMS(NODE) \ (TREE_PURPOSE (TREE_OPERAND (NODE, 1))) @@ -4304,6 +4318,7 @@ extern bool cp_dump_tree (void *, tree); /* in cp-simplify.c */ extern int cp_gimplify_expr (tree *, tree *, tree *); +extern void cp_genericize (tree); /* -- end of C++ */ diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index a50ecc4114c..cd086117634 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1517,6 +1517,43 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t) pp_needs_newline (pp) = true; break; + /* selection-statement: + if ( expression ) statement + if ( expression ) statement else statement */ + case IF_STMT: + pp_cxx_identifier (pp, "if"); + pp_cxx_whitespace (pp); + pp_cxx_left_paren (pp); + pp_cxx_expression (pp, IF_COND (t)); + pp_cxx_right_paren (pp); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, THEN_CLAUSE (t)); + pp_newline_and_indent (pp, -2); + if (ELSE_CLAUSE (t)) + { + tree else_clause = ELSE_CLAUSE (t); + pp_cxx_identifier (pp, "else"); + if (TREE_CODE (else_clause) == IF_STMT) + pp_cxx_whitespace (pp); + else + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, else_clause); + if (TREE_CODE (else_clause) != IF_STMT) + pp_newline_and_indent (pp, -2); + } + break; + + case CLEANUP_STMT: + pp_cxx_identifier (pp, "try"); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, CLEANUP_BODY (t)); + pp_newline_and_indent (pp, -2); + pp_cxx_identifier (pp, CLEANUP_EH_ONLY (t) ? "catch" : "finally"); + pp_newline_and_indent (pp, 2); + pp_cxx_statement (pp, CLEANUP_EXPR (t)); + pp_newline_and_indent (pp, -2); + break; + default: pp_c_statement (pp_c_base (pp), t); break; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index dfdfe564991..84f3b8459af 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -10812,7 +10812,7 @@ finish_function (int flags) /* Genericize before inlining. */ if (!processing_template_decl) { - c_genericize (fndecl); + cp_genericize (fndecl); /* Handle attribute((warn_unused_result)). Relies on gimple input. */ c_warn_unused_result (&DECL_SAVED_TREE (fndecl)); diff --git a/gcc/cp/dump.c b/gcc/cp/dump.c index 17b30c94367..fd0a847a409 100644 --- a/gcc/cp/dump.c +++ b/gcc/cp/dump.c @@ -411,7 +411,23 @@ cp_dump_tree (void* dump_info, tree t) dump_child ("nmsp", USING_STMT_NAMESPACE (t)); dump_next_stmt (di, t); break; - + + case CLEANUP_STMT: + dump_stmt (di, t); + dump_child ("decl", CLEANUP_DECL (t)); + dump_child ("expr", CLEANUP_EXPR (t)); + dump_child ("body", CLEANUP_BODY (t)); + dump_next_stmt (di, t); + break; + + case IF_STMT: + dump_stmt (di, t); + dump_child ("cond", IF_COND (t)); + dump_child ("then", THEN_CLAUSE (t)); + dump_child ("else", ELSE_CLAUSE (t)); + dump_next_stmt (di, t); + break; + default: break; } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 74a513a9cd6..e53222f48b2 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -346,6 +346,19 @@ do_pushlevel (scope_kind sk) return ret; } +/* Queue a cleanup. CLEANUP is an expression/statement to be executed + when the current scope is exited. EH_ONLY is true when this is not + meant to apply to normal control flow transfer. */ + +void +push_cleanup (tree decl, tree cleanup, bool eh_only) +{ + tree stmt = build_stmt (CLEANUP_STMT, NULL, cleanup, decl); + CLEANUP_EH_ONLY (stmt) = eh_only; + add_stmt (stmt); + CLEANUP_BODY (stmt) = push_stmt_list (); +} + /* Begin a conditional that might contain a declaration. When generating normal code, we want the declaration to appear before the statement containing the conditional. When generating template code, we want the diff --git a/gcc/tree.h b/gcc/tree.h index facd4217f10..6babb197c59 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -209,8 +209,7 @@ struct tree_common GTY(()) TREE_SYMBOL_REFERENCED in IDENTIFIER_NODE CLEANUP_EH_ONLY in - TARGET_EXPR, WITH_CLEANUP_EXPR, CLEANUP_STMT, - TREE_LIST elements of a block's cleanup list. + TARGET_EXPR, WITH_CLEANUP_EXPR ASM_INPUT_P in ASM_EXPR EH_FILTER_MUST_NOT_THROW in EH_FILTER_EXPR @@ -690,9 +689,9 @@ extern void tree_operand_check_failed (int, enum tree_code, should be cleaned up some day. */ #define TREE_STATIC(NODE) ((NODE)->common.static_flag) -/* In a TARGET_EXPR, WITH_CLEANUP_EXPR, CLEANUP_STMT, or element of a - block's cleanup list, means that the pertinent cleanup should only be - executed if an exception is thrown, not on normal exit of its scope. */ +/* In a TARGET_EXPR, WITH_CLEANUP_EXPR, means that the pertinent cleanup + should only be executed if an exception is thrown, not on normal exit + of its scope. */ #define CLEANUP_EH_ONLY(NODE) ((NODE)->common.static_flag) /* In an expr node (usually a conversion) this means the node was made -- 2.30.2