* 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
+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.
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)
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
#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)
#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 {
#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
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));
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));
/* Local declarations. */
-static void gimplify_cleanup_stmts (tree);
-
enum bc_t { bc_break = 0, bc_continue = 1 };
static struct c_gimplify_ctx
/* Go ahead and gimplify for now. */
push_context ();
- gimplify_cleanup_stmts (fndecl);
gimplify_function_tree (fndecl);
pop_context ();
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)
{
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
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);
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);
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);
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));
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);
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;
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)
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;
}
}
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. */
/* 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)
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++];
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. */
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;
}
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;
}
{
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));
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 ();
+}
\f
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
+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.
*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
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;
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);
+}
/* 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
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.
#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 };
#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)))
/* in cp-simplify.c */
extern int cp_gimplify_expr (tree *, tree *, tree *);
+extern void cp_genericize (tree);
/* -- end of C++ */
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;
/* 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));
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;
}
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
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
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