aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorRichard Henderson <rth@redhat.com>2004-06-20 02:18:13 -0700
committerRichard Henderson <rth@gcc.gnu.org>2004-06-20 02:18:13 -0700
commit5a5086621e8751f9666cf0a3d5956149202e1487 (patch)
tree5f34633f30f7aaefd64e454886114b31df3b8155 /gcc/cp
parent500e12641f0f7fb4fde1221f7f8052ef351de5f7 (diff)
downloadgcc-5a5086621e8751f9666cf0a3d5956149202e1487.zip
gcc-5a5086621e8751f9666cf0a3d5956149202e1487.tar.gz
gcc-5a5086621e8751f9666cf0a3d5956149202e1487.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/cp-gimplify.c55
-rw-r--r--gcc/cp/cp-tree.def14
-rw-r--r--gcc/cp/cp-tree.h17
-rw-r--r--gcc/cp/cxx-pretty-print.c37
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/dump.c18
-rw-r--r--gcc/cp/semantics.c13
8 files changed, 169 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index e3048d3..b01e1f8 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 9901643..8bdf5f4 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 3b4c6e6e..4f7961b 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 1838c82..ae62adc 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 a50ecc4..cd08611 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 dfdfe56..84f3b84 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 17b30c9..fd0a847 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 74a513a..e53222f 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