2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-13 13:01:02 +08:00

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
This commit is contained in:
Richard Henderson 2004-06-20 02:18:13 -07:00 committed by Richard Henderson
parent 500e12641f
commit 5a5086621e
17 changed files with 218 additions and 192 deletions

@ -1,3 +1,20 @@
2004-06-20 Richard Henderson <rth@redhat.com>
* 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 <zack@codesourcery.com>
* c-common.h (has_c_linkage): New interface.

@ -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

@ -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

@ -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));

@ -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);

@ -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;
}
}

@ -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. */

@ -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.

@ -1,3 +1,19 @@
2004-06-20 Richard Henderson <rth@redhat.com>
* 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 <zack@codesourcery.com>
* cp-lang.c (has_c_linkage): Implement.

@ -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);
}

@ -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.

@ -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++ */

@ -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;

@ -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));

@ -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;
}

@ -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

@ -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