summaryrefslogtreecommitdiffstats
path: root/gcc/cp
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-16 01:21:38 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2004-06-16 01:21:38 +0000
commit2363ef003652e46b5d1eb1b1bc7a93327168977a (patch)
treefd045b9b0d56d6e00876348ae58483539fd0ec02 /gcc/cp
parent53a9841beb1d5b151218420952cd30f98913a93d (diff)
downloadppe42-gcc-2363ef003652e46b5d1eb1b1bc7a93327168977a.tar.gz
ppe42-gcc-2363ef003652e46b5d1eb1b1bc7a93327168977a.zip
* 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/cp')
-rw-r--r--gcc/cp/ChangeLog60
-rw-r--r--gcc/cp/call.c39
-rw-r--r--gcc/cp/cp-gimplify.c25
-rw-r--r--gcc/cp/cp-lang.c9
-rw-r--r--gcc/cp/cp-mudflap.c2
-rw-r--r--gcc/cp/cp-tree.h52
-rw-r--r--gcc/cp/decl.c68
-rw-r--r--gcc/cp/decl2.c6
-rw-r--r--gcc/cp/except.c79
-rw-r--r--gcc/cp/init.c17
-rw-r--r--gcc/cp/method.c4
-rw-r--r--gcc/cp/name-lookup.c2
-rw-r--r--gcc/cp/name-lookup.h4
-rw-r--r--gcc/cp/parser.c90
-rw-r--r--gcc/cp/pt.c91
-rw-r--r--gcc/cp/semantics.c496
-rw-r--r--gcc/cp/typeck2.c27
17 files changed, 568 insertions, 503 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3889e75b7cf..c8a1a1e5e9c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,63 @@
+2004-06-15 Richard Henderson <rth@redhat.com>
+
+ * 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.
+
2004-06-15 Alexandre Oliva <aoliva@redhat.com>
* parser.c: Change all assignments of c_lex_string_translate
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index d1e8298164b..616cf812f92 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6362,9 +6362,9 @@ make_temporary_var_for_ref_to_temp (tree decl, tree type)
the VAR_DECL being initialized with the EXPR. (In that case, the
type of DECL will be TYPE.) If DECL is non-NULL, then CLEANUP must
also be non-NULL, and with *CLEANUP initialized to NULL. Upon
- return, if *CLEANUP is no longer NULL, it will be a CLEANUP_STMT
- that should be inserted after the returned expression is used to
- initialize DECL.
+ return, if *CLEANUP is no longer NULL, it will be an expression
+ that should be pushed as a cleanup after the returned expression
+ is used to initialize DECL.
Return the converted expression. */
@@ -6485,26 +6485,25 @@ initialize_reference (tree type, tree expr, tree decl, tree *cleanup)
{
add_decl_stmt (var);
*cleanup = cxx_maybe_build_cleanup (var);
- if (*cleanup)
- /* We must be careful to destroy the temporary only
- after its initialization has taken place. If the
- initialization throws an exception, then the
- destructor should not be run. We cannot simply
- transform INIT into something like:
+
+ /* We must be careful to destroy the temporary only
+ after its initialization has taken place. If the
+ initialization throws an exception, then the
+ destructor should not be run. We cannot simply
+ transform INIT into something like:
(INIT, ({ CLEANUP_STMT; }))
- because emit_local_var always treats the
- initializer as a full-expression. Thus, the
- destructor would run too early; it would run at the
- end of initializing the reference variable, rather
- than at the end of the block enclosing the
- reference variable.
-
- The solution is to pass back a CLEANUP_STMT which
- the caller is responsible for attaching to the
- statement tree. */
- *cleanup = build_stmt (CLEANUP_STMT, var, *cleanup);
+ because emit_local_var always treats the
+ initializer as a full-expression. Thus, the
+ destructor would run too early; it would run at the
+ end of initializing the reference variable, rather
+ than at the end of the block enclosing the
+ reference variable.
+
+ The solution is to pass back a cleanup expression
+ which the caller is responsible for attaching to
+ the statement tree. */
}
else
{
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index f82ed61eb7a..2884d8b5b2d 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -39,7 +39,7 @@ static void cp_gimplify_init_expr (tree *, tree *, tree *);
/* Genericize a C++ _STMT. Called from c_gimplify_stmt. */
int
-cp_gimplify_stmt (tree *stmt_p, tree *next_p ATTRIBUTE_UNUSED)
+cp_gimplify_stmt (tree *stmt_p)
{
tree stmt = *stmt_p;
switch (TREE_CODE (stmt))
@@ -76,12 +76,12 @@ genericize_try_block (tree *stmt_p)
tree body = TRY_STMTS (*stmt_p);
tree cleanup = TRY_HANDLERS (*stmt_p);
- c_gimplify_stmt (&body);
+ gimplify_stmt (&body);
if (CLEANUP_P (*stmt_p))
/* A cleanup is an expression, so it doesn't need to be genericized. */;
else
- c_gimplify_stmt (&cleanup);
+ gimplify_stmt (&cleanup);
*stmt_p = build (TRY_CATCH_EXPR, void_type_node, body, cleanup);
}
@@ -94,7 +94,7 @@ genericize_catch_block (tree *stmt_p)
tree type = HANDLER_TYPE (*stmt_p);
tree body = HANDLER_BODY (*stmt_p);
- c_gimplify_stmt (&body);
+ gimplify_stmt (&body);
/* FIXME should the caught type go in TREE_TYPE? */
*stmt_p = build (CATCH_EXPR, void_type_node, type, body);
@@ -111,7 +111,7 @@ genericize_eh_spec_block (tree *stmt_p)
tree failure = build_call (call_unexpected_node,
tree_cons (NULL_TREE, build_exc_ptr (),
NULL_TREE));
- c_gimplify_stmt (&body);
+ gimplify_stmt (&body);
*stmt_p = gimple_build_eh_filter (body, allowed, failure);
}
@@ -182,16 +182,8 @@ cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
if (TREE_CODE (from) == TARGET_EXPR)
from = TARGET_EXPR_INITIAL (from);
- sub = from;
-
- /* If we are initializing from a STMT_EXPR, extract the returned
- expression. */
- if (TREE_CODE (from) == STMT_EXPR)
- sub = EXPR_STMT_EXPR (stmt_expr_last_stmt (from));
-
/* Look through any COMPOUND_EXPRs. */
- while (TREE_CODE (sub) == COMPOUND_EXPR)
- sub = TREE_OPERAND (sub, 1);
+ sub = expr_last (from);
/* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
replace the slot operand with our target.
@@ -205,8 +197,7 @@ cp_gimplify_init_expr (tree *expr_p, tree *pre_p, tree *post_p)
*expr_p = from;
/* The initialization is now a side-effect, so the container can
- become void. This is important for a STMT_EXPR, so we don't try
- to voidify it later by creating a temporary. */
+ become void. */
if (from != sub)
TREE_TYPE (from) = void_type_node;
}
@@ -218,7 +209,7 @@ static void
gimplify_must_not_throw_expr (tree *expr_p, tree *pre_p)
{
tree stmt = *expr_p;
- tree temp = voidify_wrapper_expr (stmt);
+ tree temp = voidify_wrapper_expr (stmt, NULL);
tree body = TREE_OPERAND (stmt, 0);
gimplify_stmt (&body);
diff --git a/gcc/cp/cp-lang.c b/gcc/cp/cp-lang.c
index 8a82e4e72ce..eb0e2210624 100644
--- a/gcc/cp/cp-lang.c
+++ b/gcc/cp/cp-lang.c
@@ -138,9 +138,6 @@ static void cxx_initialize_diagnostics (diagnostic_context *);
#undef LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS
#define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \
cp_add_pending_fn_decls
-#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P
-#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
- cp_tree_chain_matters_p
#undef LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P
#define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \
cp_auto_var_in_fn_p
@@ -292,12 +289,6 @@ cp_expr_size (tree exp)
return lhd_expr_size (exp);
}
-int
-cp_tree_chain_matters_p (tree t)
-{
- return cp_is_overload_p (t) || c_tree_chain_matters_p (t);
-}
-
/* Langhook for tree_size: determine size of our 'x' and 'c' nodes. */
static size_t
cp_tree_size (enum tree_code code)
diff --git a/gcc/cp/cp-mudflap.c b/gcc/cp/cp-mudflap.c
index 878dc8a1c85..faa57e2df5e 100644
--- a/gcc/cp/cp-mudflap.c
+++ b/gcc/cp/cp-mudflap.c
@@ -82,7 +82,7 @@ mflang_flush_calls (tree enqueued_call_stmt_chain)
mf_mark (current_function_decl);
/* Generate the body, one statement at a time. */
- body = begin_compound_stmt (/*has_no_scope=*/false);
+ body = begin_compound_stmt (BCS_FN_BODY);
while (enqueued_call_stmt_chain)
{
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 320098b773c..799bbcfe79d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -48,6 +48,9 @@ struct diagnostic_context;
PARMLIST_ELLIPSIS_P (in PARMLIST)
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
KOENIG_LOOKUP_P (in CALL_EXPR)
+ STATEMENT_LIST_NO_SCOPE (in STATEMENT_LIST).
+ EXPR_STMT_STMT_EXPR_RESULT (in EXPR_STMT)
+ COMPOUND_STMT_TRY_BLOCK (in COMPOUND_STMT)
1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE.
@@ -63,6 +66,7 @@ struct diagnostic_context;
BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
+ STATEMENT_LIST_TRY_BLOCK (in STATEMENT_LIST)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED.
@@ -70,6 +74,7 @@ struct diagnostic_context;
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
IDENTIFIER_CTOR_OR_DTOR_P (in IDENTIFIER_NODE)
+ COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT)
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
@@ -266,6 +271,22 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
#define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (TRY_BLOCK_CHECK (NODE))
+#define COMPOUND_STMT_TRY_BLOCK(NODE) \
+ TREE_LANG_FLAG_0 (COMPOUND_STMT_CHECK (NODE))
+
+/* Used to mark the block around the member initializers and cleanups. */
+#define COMPOUND_STMT_BODY_BLOCK(NODE) \
+ TREE_LANG_FLAG_3 (COMPOUND_STMT_CHECK (NODE))
+
+#define STATEMENT_LIST_NO_SCOPE(NODE) \
+ TREE_LANG_FLAG_0 (STATEMENT_LIST_CHECK (NODE))
+#define STATEMENT_LIST_TRY_BLOCK(NODE) \
+ TREE_LANG_FLAG_2 (STATEMENT_LIST_CHECK (NODE))
+
+/* Marks the result of a statement expression. */
+#define EXPR_STMT_STMT_EXPR_RESULT(NODE) \
+ TREE_LANG_FLAG_0 (EXPR_STMT_CHECK (NODE))
+
/* Returns nonzero iff TYPE1 and TYPE2 are the same type, in the usual
sense of `same'. */
#define same_type_p(TYPE1, TYPE2) \
@@ -278,7 +299,7 @@ typedef struct ptrmem_cst * ptrmem_cst_t;
/* Nonzero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */
-#define building_stmt_tree() (last_tree != NULL_TREE)
+#define building_stmt_tree() (cur_stmt_list != NULL_TREE)
/* Returns nonzero iff NODE is a declaration for the global function
`main'. */
@@ -3031,12 +3052,7 @@ typedef enum tsubst_flags_t {
instantiate_type use) */
tf_user = 1 << 5, /* found template must be a user template
(lookup_template_class use) */
- tf_stmt_expr_cmpd = 1 << 6, /* tsubsting the compound statement of
- a statement expr. */
- tf_stmt_expr_body = 1 << 7, /* tsubsting the statements in the
- body of the compound statement of a
- statement expr. */
- tf_conv = 1 << 8 /* We are determining what kind of
+ tf_conv = 1 << 6 /* We are determining what kind of
conversion might be permissible,
not actually performing the
conversion. */
@@ -4004,9 +4020,9 @@ extern tree finish_expr_stmt (tree);
extern tree begin_if_stmt (void);
extern void finish_if_stmt_cond (tree, tree);
extern tree finish_then_clause (tree);
-extern void begin_else_clause (void);
+extern void begin_else_clause (tree);
extern void finish_else_clause (tree);
-extern void finish_if_stmt (void);
+extern void finish_if_stmt (tree);
extern tree begin_while_stmt (void);
extern void finish_while_stmt_cond (tree, tree);
extern void finish_while_stmt (tree);
@@ -4040,8 +4056,15 @@ extern void finish_handler_parms (tree, tree);
extern void begin_catch_block (tree);
extern void finish_handler (tree);
extern void finish_cleanup (tree, tree);
-extern tree begin_compound_stmt (bool);
-extern tree finish_compound_stmt (tree);
+
+enum {
+ BCS_NO_SCOPE = 1,
+ BCS_TRY_BLOCK = 2,
+ BCS_FN_BODY = 4
+};
+extern tree begin_compound_stmt (unsigned int);
+
+extern void finish_compound_stmt (tree);
extern tree finish_asm_stmt (int, tree, tree, tree, tree);
extern tree finish_label_stmt (tree);
extern void finish_label_decl (tree);
@@ -4049,7 +4072,7 @@ extern void finish_subobject (tree);
extern tree finish_parenthesized_expr (tree);
extern tree finish_non_static_data_member (tree, tree, tree);
extern tree begin_stmt_expr (void);
-extern tree finish_stmt_expr_expr (tree);
+extern tree finish_stmt_expr_expr (tree, tree);
extern tree finish_stmt_expr (tree, bool);
extern tree perform_koenig_lookup (tree, tree);
extern tree finish_call_expr (tree, tree, bool, bool);
@@ -4082,8 +4105,6 @@ extern void finish_decl_cleanup (tree, tree);
extern void finish_eh_cleanup (tree);
extern void expand_body (tree);
extern void cxx_expand_function_start (void);
-extern void do_pushlevel (scope_kind);
-extern tree do_poplevel (void);
extern void finish_mem_initializers (tree);
extern void setup_vtbl_ptr (tree, tree);
extern void clear_out_block (void);
@@ -4164,7 +4185,6 @@ extern tree find_tree (tree, tree);
extern linkage_kind decl_linkage (tree);
extern tree cp_walk_subtrees (tree*, int*, walk_tree_fn,
void*, void*);
-extern int cp_tree_chain_matters_p (tree);
extern int cp_cannot_inline_tree_fn (tree*);
extern tree cp_add_pending_fn_decls (void*,tree);
extern int cp_is_overload_p (tree);
@@ -4286,7 +4306,7 @@ extern bool cp_dump_tree (void *, tree);
/* in cp-simplify.c */
extern int cp_gimplify_expr (tree *, tree *, tree *);
-extern int cp_gimplify_stmt (tree *, tree *);
+extern int cp_gimplify_stmt (tree *);
/* -- end of C++ */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 92c6cf03976..84ce0d74e94 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -429,12 +429,15 @@ poplevel (int keep, int reverse, int functionbody)
int tmp = functionbody;
int real_functionbody;
tree subblocks;
- tree block = NULL_TREE;
+ tree block;
tree decl;
int leaving_for_scope;
scope_kind kind;
timevar_push (TV_NAME_LOOKUP);
+ restart:
+
+ block = NULL_TREE;
my_friendly_assert (current_binding_level->kind != sk_class, 19990916);
@@ -657,6 +660,17 @@ poplevel (int keep, int reverse, int functionbody)
}
kind = current_binding_level->kind;
+ if (kind == sk_cleanup)
+ {
+ tree stmt;
+
+ /* If this is a temporary binding created for a cleanup, then we'll
+ have pushed a statement list level. Pop that, create a new
+ BIND_EXPR for the block, and insert it into the stream. */
+ stmt = pop_stmt_list (current_binding_level->statement_list);
+ stmt = c_build_bind_expr (block, stmt);
+ add_stmt (stmt);
+ }
leave_scope ();
if (functionbody)
@@ -680,21 +694,9 @@ poplevel (int keep, int reverse, int functionbody)
if (block)
TREE_USED (block) = 1;
- /* Take care of compiler's internal binding structures. */
+ /* All temporary bindings created for cleanups are popped silently. */
if (kind == sk_cleanup)
- {
- tree scope_stmts;
-
- scope_stmts
- = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1);
- if (block)
- {
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
- SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
- }
-
- block = poplevel (keep, reverse, functionbody);
- }
+ goto restart;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
}
@@ -4938,7 +4940,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
/* If a CLEANUP_STMT was created to destroy a temporary bound to a
reference, insert it in the statement-tree now. */
if (cleanup)
- add_stmt (cleanup);
+ push_cleanup (decl, cleanup, false);
finish_end:
@@ -5174,7 +5176,7 @@ register_dtor_fn (tree decl)
pop_deferring_access_checks ();
/* Create the body of the anonymous function. */
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (BCS_FN_BODY);
finish_expr_stmt (fcall);
finish_compound_stmt (compound_stmt);
end_cleanup_fn ();
@@ -5252,7 +5254,7 @@ expand_static_init (tree decl, tree init)
/* Begin the conditional initialization. */
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
- then_clause = begin_compound_stmt (/*has_no_scope=*/false);
+ then_clause = begin_compound_stmt (0);
/* Do the initialization itself. */
assignment = init ? init : NULL_TREE;
@@ -5278,7 +5280,7 @@ expand_static_init (tree decl, tree init)
finish_compound_stmt (then_clause);
finish_then_clause (if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (if_stmt);
}
else
static_aggregates = tree_cons (init, decl, static_aggregates);
@@ -10225,7 +10227,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
cfun->x_dont_save_pending_sizes_p = 1;
/* Start the statement-tree, start the tree now. */
- begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+ DECL_SAVED_TREE (decl1) = push_stmt_list ();
/* Let the user know we're compiling this function. */
announce_function (decl1);
@@ -10486,8 +10488,7 @@ save_function_data (tree decl)
DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */
- f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
- f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
+ f->base.x_stmt_tree.x_cur_stmt_list = NULL_TREE;
f->x_named_label_uses = NULL;
f->bindings = NULL;
f->x_local_names = NULL;
@@ -10542,7 +10543,7 @@ begin_destructor_body (void)
initialize the vtables.) */
finish_if_stmt_cond (boolean_true_node, if_stmt);
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (0);
/* Make all virtual function table pointers in non-virtual base
classes point to CURRENT_CLASS_TYPE's virtual function
@@ -10551,7 +10552,7 @@ begin_destructor_body (void)
finish_compound_stmt (compound_stmt);
finish_then_clause (if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (if_stmt);
/* And insert cleanups for our bases and members so that they
will be properly destroyed if we throw. */
@@ -10593,7 +10594,7 @@ finish_destructor_body (void)
if_stmt);
finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (if_stmt);
}
}
@@ -10616,7 +10617,7 @@ begin_function_body (void)
operation of dwarfout.c. */
keep_next_level (true);
- stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ stmt = begin_compound_stmt (BCS_FN_BODY);
COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
if (processing_template_decl)
@@ -10716,10 +10717,10 @@ finish_function (int flags)
current_eh_spec_block);
}
- finish_fname_decls ();
-
/* If we're saving up tree structure, tie off the function now. */
- finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+ finish_fname_decls ();
/* If this function can't throw any exceptions, remember that. */
if (!processing_template_decl
@@ -10773,9 +10774,10 @@ finish_function (int flags)
the function so we know that their lifetime always ends with a
return; see g++.dg/opt/nrv6.C. We could be more flexible if
we were to do this optimization in tree-ssa. */
+ && (outer = BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl)))
/* Skip the artificial function body block. */
- && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
- chain_member (r, BLOCK_VARS (outer))))
+ && (outer = BLOCK_SUBBLOCKS (outer))
+ && chain_member (r, BLOCK_VARS (outer)))
finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
current_function_return_value = NULL_TREE;
@@ -11094,10 +11096,6 @@ cxx_maybe_build_cleanup (tree decl)
void
finish_stmt (void)
{
- /* Always assume this statement was not an expression statement. If
- it actually was an expression statement, its our callers
- responsibility to fix this up. */
- last_expr_type = NULL_TREE;
}
/* DECL was originally constructed as a non-static member function,
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 57e3224e91f..8157950371b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -1970,7 +1970,7 @@ start_objects (int method_type, int initp)
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
- body = begin_compound_stmt (/*has_no_scope=*/false);
+ body = begin_compound_stmt (BCS_FN_BODY);
/* We cannot allow these functions to be elided, even if they do not
have external linkage. And, there's no point in deferring
@@ -2127,7 +2127,7 @@ start_static_storage_duration_function (unsigned count)
SF_PRE_PARSED);
/* Set up the scope of the outermost block in the function. */
- body = begin_compound_stmt (/*has_no_scope=*/false);
+ body = begin_compound_stmt (BCS_FN_BODY);
/* This function must not be deferred because we are depending on
its compilation to tell us what is TREE_SYMBOL_REFERENCED. */
@@ -2307,7 +2307,7 @@ static void
finish_static_initialization_or_destruction (tree guard_if_stmt)
{
finish_then_clause (guard_if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (guard_if_stmt);
/* Now that we're done with DECL we don't need to pretend to be a
member of its class any longer. */
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 69813d3ac7b..7e6e54e0def 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -37,6 +37,7 @@ Boston, MA 02111-1307, USA. */
#include "except.h"
#include "toplev.h"
#include "tree-inline.h"
+#include "tree-iterator.h"
static void push_eh_cleanup (tree);
static tree prepare_eh_type (tree);
@@ -51,7 +52,6 @@ static tree wrap_cleanups_r (tree *, int *, void *);
static int complete_ptr_ref_or_void_ptr_p (tree, tree);
static bool is_admissible_throw_operand (tree);
static int can_convert_eh (tree, tree);
-static void check_handlers_1 (tree, tree);
static tree cp_protect_cleanup_actions (void);
/* Sets up all the global eh stuff that needs to be initialized at the
@@ -462,6 +462,7 @@ begin_eh_spec_block (void)
{
tree r = build_stmt (EH_SPEC_BLOCK, NULL_TREE, NULL_TREE);
add_stmt (r);
+ EH_SPEC_STMTS (r) = push_stmt_list ();
return r;
}
@@ -470,7 +471,7 @@ finish_eh_spec_block (tree raw_raises, tree eh_spec_block)
{
tree raises;
- RECHAIN_STMTS (eh_spec_block, EH_SPEC_STMTS (eh_spec_block));
+ EH_SPEC_STMTS (eh_spec_block) = pop_stmt_list (EH_SPEC_STMTS (eh_spec_block));
/* Strip cv quals, etc, from the specification types. */
for (raises = NULL_TREE;
@@ -874,47 +875,57 @@ can_convert_eh (tree to, tree from)
return 0;
}
-/* Check whether any of HANDLERS are shadowed by another handler accepting
- TYPE. Note that the shadowing may not be complete; even if an exception
- of type B would be caught by a handler for A, there could be a derived
- class C for which A is an ambiguous base but B is not, so the handler
- for B would catch an exception of type C. */
+/* Check whether any of the handlers in I are shadowed by another handler
+ accepting TYPE. Note that the shadowing may not be complete; even if
+ an exception of type B would be caught by a handler for A, there could
+ be a derived class C for which A is an ambiguous base but B is not, so
+ the handler for B would catch an exception of type C. */
static void
-check_handlers_1 (tree master, tree handlers)
+check_handlers_1 (tree master, tree_stmt_iterator i)
{
tree type = TREE_TYPE (master);
- tree handler;
- for (handler = handlers; handler; handler = TREE_CHAIN (handler))
- if (TREE_TYPE (handler)
- && can_convert_eh (type, TREE_TYPE (handler)))
- {
- warning ("%Hexception of type `%T' will be caught",
- EXPR_LOCUS (handler), TREE_TYPE (handler));
- warning ("%H by earlier handler for `%T'",
- EXPR_LOCUS (master), type);
- break;
- }
+ for (; !tsi_end_p (i); tsi_next (&i))
+ {
+ tree handler = tsi_stmt (i);
+ if (TREE_TYPE (handler) && can_convert_eh (type, TREE_TYPE (handler)))
+ {
+ warning ("%Hexception of type `%T' will be caught",
+ EXPR_LOCUS (handler), TREE_TYPE (handler));
+ warning ("%H by earlier handler for `%T'",
+ EXPR_LOCUS (master), type);
+ break;
+ }
+ }
}
-/* Given a chain of HANDLERs, make sure that they're OK. */
+/* Given a STATEMENT_LIST of HANDLERs, make sure that they're OK. */
void
check_handlers (tree handlers)
{
- tree handler;
- int save_line = input_line;
-
- for (handler = handlers; handler; handler = TREE_CHAIN (handler))
- {
- if (TREE_CHAIN (handler) == NULL_TREE)
- /* No more handlers; nothing to shadow. */;
- else if (TREE_TYPE (handler) == NULL_TREE)
- pedwarn ("%H`...' handler must be the last handler for"
- " its try block", EXPR_LOCUS (handler));
- else
- check_handlers_1 (handler, TREE_CHAIN (handler));
- }
- input_line = save_line;
+ tree_stmt_iterator i;
+
+ /* If we don't have a STATEMENT_LIST, then we've just got one
+ handler, and thus nothing to warn about. */
+ if (TREE_CODE (handlers) != STATEMENT_LIST)
+ return;
+
+ i = tsi_start (handlers);
+ if (!tsi_end_p (i))
+ while (1)
+ {
+ tree handler = tsi_stmt (i);
+ tsi_next (&i);
+
+ /* No more handlers; nothing to shadow. */
+ if (tsi_end_p (i))
+ break;
+ if (TREE_TYPE (handler) == NULL_TREE)
+ pedwarn ("%H`...' handler must be the last handler for"
+ " its try block", EXPR_LOCUS (handler));
+ else
+ check_handlers_1 (handler, i);
+ }
}
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 1c003566108..6c886238ea5 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -72,7 +72,7 @@ begin_init_stmts (tree *stmt_expr_p, tree *compound_stmt_p)
bool is_global = !building_stmt_tree ();
*stmt_expr_p = begin_stmt_expr ();
- *compound_stmt_p = begin_compound_stmt (/*has_no_scope=*/true);
+ *compound_stmt_p = begin_compound_stmt (BCS_NO_SCOPE);
return is_global;
}
@@ -826,7 +826,6 @@ static void
construct_virtual_base (tree vbase, tree arguments)
{
tree inner_if_stmt;
- tree compound_stmt;
tree exp;
tree flag;
@@ -847,7 +846,6 @@ construct_virtual_base (tree vbase, tree arguments)
flag = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));
inner_if_stmt = begin_if_stmt ();
finish_if_stmt_cond (flag, inner_if_stmt);
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/true);
/* Compute the location of the virtual base. If we're
constructing virtual bases, then we must be the most derived
@@ -857,9 +855,8 @@ construct_virtual_base (tree vbase, tree arguments)
expand_aggr_init_1 (vbase, current_class_ref, exp, arguments,
LOOKUP_COMPLAIN);
- finish_compound_stmt (compound_stmt);
finish_then_clause (inner_if_stmt);
- finish_if_stmt ();
+ finish_if_stmt (inner_if_stmt);
expand_cleanup_for_base (vbase, flag);
}
@@ -2526,7 +2523,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
tree compound_stmt;
int destroy_temps;
tree try_block = NULL_TREE;
- tree try_body = NULL_TREE;
int num_initialized_elts = 0;
bool is_global;
@@ -2605,7 +2601,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
&& from_array != 2)
{
try_block = begin_try_block ();
- try_body = begin_compound_stmt (/*has_no_scope=*/true);
}
if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR)
@@ -2674,7 +2669,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
/* If the ITERATOR is equal to -1, then we don't have to loop;
we've already initialized all the elements. */
tree for_stmt;
- tree for_body;
tree elt_init;
for_stmt = begin_for_stmt ();
@@ -2685,9 +2679,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
finish_for_expr (build_unary_op (PREDECREMENT_EXPR, iterator, 0),
for_stmt);
- /* Otherwise, loop through the elements. */
- for_body = begin_compound_stmt (/*has_no_scope=*/true);
-
if (from_array)
{
tree to = build1 (INDIRECT_REF, type, base);
@@ -2727,7 +2718,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
if (base2)
finish_expr_stmt (build_unary_op (PREINCREMENT_EXPR, base2, 0));
- finish_compound_stmt (for_body);
finish_for_stmt (for_stmt);
}
@@ -2747,7 +2737,6 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
type = strip_array_types (type);
}
- finish_compound_stmt (try_body);
finish_cleanup_try_block (try_block);
e = build_vec_delete_1 (rval, m, type, sfk_base_destructor,
/*use_global_delete=*/0);
@@ -2756,7 +2745,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
/* The value of the array initialization is the array itself, RVAL
is a pointer to the first element. */
- finish_stmt_expr_expr (rval);
+ finish_stmt_expr_expr (rval, stmt_expr);
stmt_expr = finish_init_stmts (is_global, stmt_expr, compound_stmt);
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 01e5313f6de..364cc0688b3 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -621,7 +621,7 @@ do_build_assign_ref (tree fndecl)
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (0);
parm = convert_from_reference (parm);
if (TYPE_HAS_TRIVIAL_ASSIGN_REF (current_class_type)
@@ -778,7 +778,7 @@ synthesize_method (tree fndecl)
if (need_body)
{
tree compound_stmt;
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (BCS_FN_BODY);
finish_compound_stmt (compound_stmt);
}
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 3e42f3b5dce..401f6505d0c 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1433,8 +1433,8 @@ maybe_push_cleanup_level (tree type)
&& current_binding_level->more_cleanups_ok == 0)
{
begin_scope (sk_cleanup, NULL);
+ current_binding_level->statement_list = push_stmt_list ();
clear_last_expr ();
- add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
}
}
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 044f2895c0c..49046e893fe 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -205,6 +205,10 @@ struct cp_binding_level GTY(())
TREE_LIST; the TREE_VALUE is the actual declaration. */
tree dead_vars_from_for;
+ /* STATEMENT_LIST for statements in this binding contour.
+ Only used at present for SK_CLEANUP temporary bindings. */
+ tree statement_list;
+
/* Binding depth at which this level began. */
int binding_depth;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index bc736891fef..428762cb437 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1415,15 +1415,15 @@ static tree cp_parser_builtin_offsetof
/* Statements [gram.stmt.stmt] */
static void cp_parser_statement
- (cp_parser *, bool);
+ (cp_parser *, tree);
static tree cp_parser_labeled_statement
- (cp_parser *, bool);
+ (cp_parser *, tree);
static tree cp_parser_expression_statement
- (cp_parser *, bool);
+ (cp_parser *, tree);
static tree cp_parser_compound_statement
- (cp_parser *, bool);
+ (cp_parser *, tree, bool);
static void cp_parser_statement_seq_opt
- (cp_parser *, bool);
+ (cp_parser *, tree);
static tree cp_parser_selection_statement
(cp_parser *);
static tree cp_parser_condition
@@ -2542,7 +2542,7 @@ cp_parser_primary_expression (cp_parser *parser,
/* Start the statement-expression. */
expr = begin_stmt_expr ();
/* Parse the compound-statement. */
- cp_parser_compound_statement (parser, true);
+ cp_parser_compound_statement (parser, expr, false);
/* Finish up. */
expr = finish_stmt_expr (expr, false);
}
@@ -5615,7 +5615,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
try-block */
static void
-cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_statement (cp_parser* parser, tree in_statement_expr)
{
tree statement;
cp_token *token;
@@ -5638,7 +5638,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
case RID_CASE:
case RID_DEFAULT:
statement = cp_parser_labeled_statement (parser,
- in_statement_expr_p);
+ in_statement_expr);
break;
case RID_IF:
@@ -5675,11 +5675,11 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
labeled-statement. */
token = cp_lexer_peek_nth_token (parser->lexer, 2);
if (token->type == CPP_COLON)
- statement = cp_parser_labeled_statement (parser, in_statement_expr_p);
+ statement = cp_parser_labeled_statement (parser, in_statement_expr);
}
/* Anything that starts with a `{' must be a compound-statement. */
else if (token->type == CPP_OPEN_BRACE)
- statement = cp_parser_compound_statement (parser, false);
+ statement = cp_parser_compound_statement (parser, NULL, false);
/* Everything else must be a declaration-statement or an
expression-statement. Try for the declaration-statement
@@ -5697,7 +5697,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
return;
}
/* Look for an expression-statement instead. */
- statement = cp_parser_expression_statement (parser, in_statement_expr_p);
+ statement = cp_parser_expression_statement (parser, in_statement_expr);
}
/* Set the line number for the statement. */
@@ -5724,7 +5724,7 @@ cp_parser_statement (cp_parser* parser, bool in_statement_expr_p)
an ordinary label, returns a LABEL_STMT. */
static tree
-cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
{
cp_token *token;
tree statement = error_mark_node;
@@ -5792,7 +5792,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
/* Require the `:' token. */
cp_parser_require (parser, CPP_COLON, "`:'");
/* Parse the labeled statement. */
- cp_parser_statement (parser, in_statement_expr_p);
+ cp_parser_statement (parser, in_statement_expr);
/* Return the label, in the case of a `case' or `default' label. */
return statement;
@@ -5809,7 +5809,7 @@ cp_parser_labeled_statement (cp_parser* parser, bool in_statement_expr_p)
expression statement. */
static tree
-cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
{
tree statement = NULL_TREE;
@@ -5821,12 +5821,12 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
- if (in_statement_expr_p
+ if (in_statement_expr
&& cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
{
/* This is the final expression statement of a statement
expression. */
- statement = finish_stmt_expr_expr (statement);
+ statement = finish_stmt_expr_expr (statement, in_statement_expr);
}
else if (statement)
statement = finish_expr_stmt (statement);
@@ -5844,7 +5844,8 @@ cp_parser_expression_statement (cp_parser* parser, bool in_statement_expr_p)
Returns a COMPOUND_STMT representing the statement. */
static tree
-cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
+cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
+ bool in_try)
{
tree compound_stmt;
@@ -5852,9 +5853,9 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
return error_mark_node;
/* Begin the compound-statement. */
- compound_stmt = begin_compound_stmt (/*has_no_scope=*/false);
+ compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
/* Parse an (optional) statement-seq. */
- cp_parser_statement_seq_opt (parser, in_statement_expr_p);
+ cp_parser_statement_seq_opt (parser, in_statement_expr);
/* Finish the compound-statement. */
finish_compound_stmt (compound_stmt);
/* Consume the `}'. */
@@ -5870,7 +5871,7 @@ cp_parser_compound_statement (cp_parser *parser, bool in_statement_expr_p)
statement-seq [opt] statement */
static void
-cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p)
+cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
{
/* Scan statements until there aren't any more. */
while (true)
@@ -5881,7 +5882,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, bool in_statement_expr_p)
break;
/* Parse the statement. */
- cp_parser_statement (parser, in_statement_expr_p);
+ cp_parser_statement (parser, in_statement_expr);
}
}
@@ -5935,35 +5936,30 @@ cp_parser_selection_statement (cp_parser* parser)
if (keyword == RID_IF)
{
- tree then_stmt;
-
/* Add the condition. */
finish_if_stmt_cond (condition, statement);
/* Parse the then-clause. */
- then_stmt = cp_parser_implicitly_scoped_statement (parser);
+ cp_parser_implicitly_scoped_statement (parser);
finish_then_clause (statement);
/* If the next token is `else', parse the else-clause. */
if (cp_lexer_next_token_is_keyword (parser->lexer,
RID_ELSE))
{
- tree else_stmt;
-
/* Consume the `else' keyword. */
cp_lexer_consume_token (parser->lexer);
+ begin_else_clause (statement);
/* Parse the else-clause. */
- else_stmt
- = cp_parser_implicitly_scoped_statement (parser);
+ cp_parser_implicitly_scoped_statement (parser);
finish_else_clause (statement);
}
/* Now we're all done with the if-statement. */
- finish_if_stmt ();
+ finish_if_stmt (statement);
}
else
{
- tree body;
bool in_switch_statement_p;
/* Add the condition. */
@@ -5972,7 +5968,7 @@ cp_parser_selection_statement (cp_parser* parser)
/* Parse the body of the switch-statement. */
in_switch_statement_p = parser->in_switch_statement_p;
parser->in_switch_statement_p = true;
- body = cp_parser_implicitly_scoped_statement (parser);
+ cp_parser_implicitly_scoped_statement (parser);
parser->in_switch_statement_p = in_switch_statement_p;
/* Now we're all done with the switch-statement. */
@@ -6365,7 +6361,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
{
/* Create a compound-statement. */
- statement = begin_compound_stmt (/*has_no_scope=*/false);
+ statement = begin_compound_stmt (0);
/* Parse the dependent-statement. */
cp_parser_statement (parser, false);
/* Finish the dummy compound-statement. */
@@ -6373,7 +6369,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
}
/* Otherwise, we simply parse the statement directly. */
else
- statement = cp_parser_compound_statement (parser, false);
+ statement = cp_parser_compound_statement (parser, NULL, false);
/* Return the statement. */
return statement;
@@ -6387,21 +6383,17 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
static void
cp_parser_already_scoped_statement (cp_parser* parser)
{
- /* If the token is not a `{', then we must take special action. */
- if (cp_lexer_next_token_is_not(parser->lexer, CPP_OPEN_BRACE))
+ /* If the token is a `{', then we must take special action. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+ cp_parser_statement (parser, false);
+ else
{
- tree statement;
-
- /* Create a compound-statement. */
- statement = begin_compound_stmt (/*has_no_scope=*/true);
- /* Parse the dependent-statement. */
- cp_parser_statement (parser, false);
- /* Finish the dummy compound-statement. */
- finish_compound_stmt (statement);
+ /* Avoid calling cp_parser_compound_statement, so that we
+ don't create a new scope. Do everything else by hand. */
+ cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ cp_parser_statement_seq_opt (parser, false);
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
}
- /* Otherwise, we simply parse the statement directly. */
- else
- cp_parser_statement (parser, false);
}
/* Declarations [gram.dcl.dcl] */
@@ -11618,7 +11610,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
static void
cp_parser_function_body (cp_parser *parser)
{
- cp_parser_compound_statement (parser, false);
+ cp_parser_compound_statement (parser, NULL, false);
}
/* Parse a ctor-initializer-opt followed by a function-body. Return
@@ -13265,7 +13257,7 @@ cp_parser_try_block (cp_parser* parser)
cp_parser_require_keyword (parser, RID_TRY, "`try'");
try_block = begin_try_block ();
- cp_parser_compound_statement (parser, false);
+ cp_parser_compound_statement (parser, NULL, true);
finish_try_block (try_block);
cp_parser_handler_seq (parser);
finish_handler_sequence (try_block);
@@ -13341,7 +13333,7 @@ cp_parser_handler (cp_parser* parser)
declaration = cp_parser_exception_declaration (parser);
finish_handler_parms (declaration, handler);
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- cp_parser_compound_statement (parser, false);
+ cp_parser_compound_statement (parser, NULL, false);
finish_handler (handler);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index ff96eaa83c7..c93184aa0c7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "rtl.h"
#include "timevar.h"
+#include "tree-iterator.h"
/* The type of functions taking a tree, and some additional data, and
returning an int. */
@@ -7615,22 +7616,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
in_decl),
NULL_TREE);
- case STMT_EXPR:
- /* This processing should really occur in tsubst_expr. However,
- tsubst_expr does not recurse into expressions, since it
- assumes that there aren't any statements inside them. So, we
- need to expand the STMT_EXPR here. */
- if (!processing_template_decl)
- {
- tree stmt_expr = begin_stmt_expr ();
-
- tsubst_expr (STMT_EXPR_STMT (t), args,
- complain | tf_stmt_expr_cmpd, in_decl);
- return finish_stmt_expr (stmt_expr, false);
- }
-
- return t;
-
case COND_EXPR:
case MODOP_EXPR:
case PSEUDO_DTOR_EXPR:
@@ -7752,20 +7737,26 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
static tree
tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
+ /* Live only within one (recursive) call to tsubst_expr. We use
+ this to pass the statement expression node from the STMT_EXPR
+ to the EXPR_STMT that is its result. */
+ static tree cur_stmt_expr;
+
tree stmt, tmp;
- tsubst_flags_t stmt_expr
- = complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body);
- complain ^= stmt_expr;
if (t == NULL_TREE || t == error_mark_node)
return t;
- if (!STATEMENT_CODE_P (TREE_CODE (t)))
- return tsubst_copy_and_build (t, args, complain, in_decl,
- /*function_p=*/false);
-
switch (TREE_CODE (t))
{
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i;
+ for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
+ tsubst_expr (tsi_stmt (i), args, complain, in_decl);
+ break;
+ }
+
case CTOR_INITIALIZER:
prep_stmt (t);
finish_mem_initializers (tsubst_initializer_list
@@ -7778,6 +7769,19 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
args, complain, in_decl));
break;
+ case STMT_EXPR:
+ {
+ tree old_stmt_expr = cur_stmt_expr;
+ tree stmt_expr = begin_stmt_expr ();
+
+ cur_stmt_expr = stmt_expr;
+ tsubst_expr (STMT_EXPR_STMT (t), args, complain, in_decl);
+ stmt_expr = finish_stmt_expr (stmt_expr, false);
+ cur_stmt_expr = old_stmt_expr;
+
+ return stmt_expr;
+ }
+
case EXPR_STMT:
{
tree r;
@@ -7785,8 +7789,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
prep_stmt (t);
r = tsubst_expr (EXPR_STMT_EXPR (t), args, complain, in_decl);
- if (stmt_expr & tf_stmt_expr_body && !TREE_CHAIN (t))
- finish_stmt_expr_expr (r);
+ if (EXPR_STMT_STMT_EXPR_RESULT (t))
+ finish_stmt_expr_expr (r, cur_stmt_expr);
else
finish_expr_stmt (r);
break;
@@ -7861,12 +7865,9 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
/* A DECL_STMT can also be used as an expression, in the condition
- clause of an if/for/while construct. If we aren't followed by
- another statement, return our decl. */
- if (TREE_CHAIN (t) == NULL_TREE)
- return decl;
+ clause of an if/for/while construct. */
+ return decl;
}
- break;
case FOR_STMT:
{
@@ -7916,21 +7917,17 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
args, complain, in_decl),
stmt);
+ tsubst_expr (THEN_CLAUSE (t), args, complain, in_decl);
+ finish_then_clause (stmt);
- if (tmp = THEN_CLAUSE (t), tmp)
- {
- tsubst_expr (tmp, args, complain, in_decl);
- finish_then_clause (stmt);
- }
-
- if (tmp = ELSE_CLAUSE (t), tmp)
+ if (ELSE_CLAUSE (t))
{
- begin_else_clause ();
- tsubst_expr (tmp, args, complain, in_decl);
+ begin_else_clause (stmt);
+ tsubst_expr (ELSE_CLAUSE (t), args, complain, in_decl);
finish_else_clause (stmt);
}
- finish_if_stmt ();
+ finish_if_stmt (stmt);
}
break;
@@ -7940,11 +7937,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
if (COMPOUND_STMT_BODY_BLOCK (t))
stmt = begin_function_body ();
else
- stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+ stmt = begin_compound_stmt (COMPOUND_STMT_TRY_BLOCK (t)
+ ? BCS_TRY_BLOCK : 0);
- tsubst_expr (COMPOUND_BODY (t), args,
- complain | ((stmt_expr & tf_stmt_expr_cmpd) << 1),
- in_decl);
+ tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
if (COMPOUND_STMT_BODY_BLOCK (t))
finish_function_body (stmt);
@@ -8053,7 +8049,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
stmt = begin_handler ();
if (HANDLER_PARMS (t))
{
- decl = DECL_STMT_DECL (HANDLER_PARMS (t));
+ decl = HANDLER_PARMS (t);
decl = tsubst (decl, args, complain, in_decl);
/* Prevent instantiate_decl from trying to instantiate
this variable. We've already done all that needs to be
@@ -8074,10 +8070,13 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
break;
default:
+ if (!STATEMENT_CODE_P (TREE_CODE (t)))
+ return tsubst_copy_and_build (t, args, complain, in_decl,
+ /*function_p=*/false);
abort ();
}
- return tsubst_expr (TREE_CHAIN (t), args, complain | stmt_expr, in_decl);
+ return NULL_TREE;
}
/* T is a postfix-expression that is not being used in a function
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2fea1c8b86c..eeb66c59559 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -44,6 +44,7 @@
#include "debug.h"
#include "diagnostic.h"
#include "cgraph.h"
+#include "tree-iterator.h"
/* There routines provide a modular interface to perform many parsing
operations. They may therefore be used during actual parsing, or
@@ -60,23 +61,6 @@ static void emit_associated_thunks (tree);
static tree finalize_nrv_r (tree *, int *, void *);
-/* Finish processing the COND, the SUBSTMT condition for STMT. */
-
-#define FINISH_COND(COND, STMT, SUBSTMT) \
- do { \
- if (last_tree != (STMT)) \
- { \
- RECHAIN_STMTS (STMT, SUBSTMT); \
- if (!processing_template_decl) \
- { \
- (COND) = build_tree_list (SUBSTMT, COND); \
- (SUBSTMT) = (COND); \
- } \
- } \
- else \
- (SUBSTMT) = (COND); \
- } while (0)
-
/* Deferred Access Checking Overview
---------------------------------
@@ -332,45 +316,99 @@ anon_aggr_type_p (tree node)
/* Finish a scope. */
-tree
-do_poplevel (void)
+static tree
+do_poplevel (tree stmt_list)
{
- tree block = NULL_TREE;
+ tree block = NULL;
if (stmts_are_full_exprs_p ())
- {
- tree scope_stmts = NULL_TREE;
+ block = poplevel (kept_level_p (), 1, 0);
- block = poplevel (kept_level_p (), 1, 0);
- if (!processing_template_decl)
- {
- /* This needs to come after the poplevel so that partial scopes
- are properly nested. */
- scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
- if (block)
- {
- SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
- SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
- }
- }
+ stmt_list = pop_stmt_list (stmt_list);
+
+ if (!processing_template_decl)
+ {
+ stmt_list = c_build_bind_expr (block, stmt_list);
+ /* ??? See c_end_compound_stmt re statement expressions. */
}
- return block;
+ return stmt_list;
}
/* Begin a new scope. */
-void
+static tree
do_pushlevel (scope_kind sk)
{
+ tree ret = push_stmt_list ();
if (stmts_are_full_exprs_p ())
+ begin_scope (sk, NULL);
+ return ret;
+}
+
+/* Finish processing a conditional. COND contains the raw expression;
+ STMT_P is a stacked statement list that will contain any other stmts
+ emitting during the processing of this conditional. Place the
+ resulting conditional back in STMT_P. */
+
+static void
+finish_cond (tree cond, tree *stmt_p)
+{
+ tree stmt = *stmt_p;
+ stmt = pop_stmt_list (stmt);
+ if (TREE_SIDE_EFFECTS (stmt))
+ {
+ /* If stmt is set, it will be a DECL_STMT. When processing a template,
+ using this is enough, because tsubst_expr considers the result of a
+ DECL_STMT to be the DECL. When generating real code, we build a
+ funny little TREE_LIST thingy that's handled by the gimplifier. */
+ /* ??? The object of this thingy is to get the DECL declared in the
+ proper scope. Seems like this oughtn't be terribly hard with the
+ new explicit uses of BIND_EXPR and such. */
+ if (processing_template_decl)
+ {
+ stmt = expr_only (stmt);
+ if (!stmt)
+ abort ();
+ }
+ else
+ stmt = build_tree_list (stmt, cond);
+ }
+ else
+ stmt = cond;
+ *stmt_p = stmt;
+}
+
+/* If *COND_P specifies a conditional with a declaration, transform the
+ loop such that
+ while (A x = 42) { }
+ for (; A x = 42;) { }
+ becomes
+ while (true) { A x = 42; if (!x) break; }
+ for (;;) { A x = 42; if (!x) break; }
+ The statement list for the loop body should have been pushed. */
+
+static void
+simplify_loop_decl_cond (tree *cond_p)
+{
+ tree cond = *cond_p;
+ if (TREE_CODE (cond) == TREE_LIST)
{
- if (!processing_template_decl)
- add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
- begin_scope (sk, NULL);
+ tree if_stmt;
+
+ *cond_p = boolean_true_node;
+
+ if_stmt = begin_if_stmt ();
+ add_stmt (TREE_PURPOSE (cond));
+ cond = build_unary_op (TRUTH_NOT_EXPR, TREE_VALUE (cond), 0);
+ finish_if_stmt_cond (cond, if_stmt);
+ finish_break_stmt ();
+ finish_then_clause (if_stmt);
+ finish_if_stmt (if_stmt);
}
}
+
/* Finish a goto-statement. */
tree
@@ -432,8 +470,12 @@ finish_expr_stmt (tree expr)
expr = convert_to_void (expr, "statement");
else if (!type_dependent_expression_p (expr))
convert_to_void (build_non_dependent_expr (expr), "statement");
-
- r = add_stmt (build_stmt (EXPR_STMT, expr));
+
+ /* Simplification of inner statement expressions, compound exprs,
+ etc can result in the us already having an EXPR_STMT. */
+ if (TREE_CODE (expr) != EXPR_STMT)
+ expr = build_stmt (EXPR_STMT, expr);
+ r = add_stmt (expr);
}
finish_stmt ();
@@ -448,10 +490,12 @@ finish_expr_stmt (tree expr)
tree
begin_if_stmt (void)
{
- tree r;
- do_pushlevel (sk_block);
+ tree r, scope;
+ scope = do_pushlevel (sk_block);
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+ TREE_CHAIN (r) = scope;
add_stmt (r);
+ IF_COND (r) = push_stmt_list ();
return r;
}
@@ -462,7 +506,8 @@ void
finish_if_stmt_cond (tree cond, tree if_stmt)
{
cond = maybe_convert_cond (cond);
- FINISH_COND (cond, if_stmt, IF_COND (if_stmt));
+ finish_cond (cond, &IF_COND (if_stmt));
+ THEN_CLAUSE (if_stmt) = push_stmt_list ();
}
/* Finish the then-clause of an if-statement, which may be given by
@@ -471,15 +516,16 @@ finish_if_stmt_cond (tree cond, tree if_stmt)
tree
finish_then_clause (tree if_stmt)
{
- RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
+ THEN_CLAUSE (if_stmt) = pop_stmt_list (THEN_CLAUSE (if_stmt));
return if_stmt;
}
/* Begin the else-clause of an if-statement. */
-void
-begin_else_clause (void)
+void
+begin_else_clause (tree if_stmt)
{
+ ELSE_CLAUSE (if_stmt) = push_stmt_list ();
}
/* Finish the else-clause of an if-statement, which may be given by
@@ -488,16 +534,18 @@ begin_else_clause (void)
void
finish_else_clause (tree if_stmt)
{
- RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
+ ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt));
}
/* Finish an if-statement. */
void
-finish_if_stmt (void)
+finish_if_stmt (tree if_stmt)
{
+ tree scope = TREE_CHAIN (if_stmt);
+ TREE_CHAIN (if_stmt) = NULL;
+ add_stmt (do_poplevel (scope));
finish_stmt ();
- do_poplevel ();
}
/* Begin a while-statement. Returns a newly created WHILE_STMT if
@@ -509,7 +557,8 @@ begin_while_stmt (void)
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_stmt (r);
- do_pushlevel (sk_block);
+ WHILE_BODY (r) = do_pushlevel (sk_block);
+ WHILE_COND (r) = push_stmt_list ();
return r;
}
@@ -520,29 +569,8 @@ void
finish_while_stmt_cond (tree cond, tree while_stmt)
{
cond = maybe_convert_cond (cond);
- if (processing_template_decl)
- /* Don't mess with condition decls in a template. */
- FINISH_COND (cond, while_stmt, WHILE_COND (while_stmt));
- else if (getdecls () == NULL_TREE)
- /* It was a simple condition; install it. */
- WHILE_COND (while_stmt) = cond;
- else
- {
- /* If there was a declaration in the condition, we can't leave it
- there; transform
- while (A x = 42) { }
- to
- while (true) { A x = 42; if (!x) break; } */
- tree if_stmt;
- WHILE_COND (while_stmt) = boolean_true_node;
-
- if_stmt = begin_if_stmt ();
- cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
- finish_if_stmt_cond (cond, if_stmt);
- finish_break_stmt ();
- finish_then_clause (if_stmt);
- finish_if_stmt ();
- }
+ finish_cond (cond, &WHILE_COND (while_stmt));
+ simplify_loop_decl_cond (&WHILE_COND (while_stmt));
}
/* Finish a while-statement, which may be given by WHILE_STMT. */
@@ -550,8 +578,7 @@ finish_while_stmt_cond (tree cond, tree while_stmt)
void
finish_while_stmt (tree while_stmt)
{
- do_poplevel ();
- RECHAIN_STMTS (while_stmt, WHILE_BODY (while_stmt));
+ WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt));
finish_stmt ();
}
@@ -563,6 +590,7 @@ begin_do_stmt (void)
{
tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
add_stmt (r);
+ DO_BODY (r) = push_stmt_list ();
return r;
}
@@ -571,7 +599,7 @@ begin_do_stmt (void)
void
finish_do_body (tree do_stmt)
{
- RECHAIN_STMTS (do_stmt, DO_BODY (do_stmt));
+ DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt));
}
/* Finish a do-statement, which may be given by DO_STMT, and whose
@@ -620,10 +648,9 @@ begin_for_stmt (void)
r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
- NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
- if (NEW_FOR_SCOPE_P (r))
- do_pushlevel (sk_for);
- add_stmt (r);
+
+ if (flag_new_for_scope > 0)
+ TREE_CHAIN (r) = do_pushlevel (sk_for);
return r;
}
@@ -634,9 +661,9 @@ begin_for_stmt (void)
void
finish_for_init_stmt (tree for_stmt)
{
- if (last_tree != for_stmt)
- RECHAIN_STMTS (for_stmt, FOR_INIT_STMT (for_stmt));
- do_pushlevel (sk_block);
+ add_stmt (for_stmt);
+ FOR_BODY (for_stmt) = do_pushlevel (sk_block);
+ FOR_COND (for_stmt) = push_stmt_list ();
}
/* Finish the COND of a for-statement, which may be given by
@@ -646,29 +673,9 @@ void
finish_for_cond (tree cond, tree for_stmt)
{
cond = maybe_convert_cond (cond);
- if (processing_template_decl)
- /* Don't mess with condition decls in a template. */
- FINISH_COND (cond, for_stmt, FOR_COND (for_stmt));
- else if (getdecls () == NULL_TREE)
- /* It was a simple condition; install it. */
- FOR_COND (for_stmt) = cond;
- else
- {
- /* If there was a declaration in the condition, we can't leave it
- there; transform
- for (; A x = 42;) { }
- to
- for (;;) { A x = 42; if (!x) break; } */
- tree if_stmt;
- FOR_COND (for_stmt) = NULL_TREE;
-
- if_stmt = begin_if_stmt ();
- cond = build_unary_op (TRUTH_NOT_EXPR, cond, 0);
- finish_if_stmt_cond (cond, if_stmt);
- finish_break_stmt ();
- finish_then_clause (if_stmt);
- finish_if_stmt ();
- }
+ finish_cond (cond, &FOR_COND (for_stmt));
+ if (FOR_COND (for_stmt))
+ simplify_loop_decl_cond (&FOR_COND (for_stmt));
}
/* Finish the increment-EXPRESSION in a for-statement, which may be
@@ -694,11 +701,16 @@ finish_for_expr (tree expr, tree for_stmt)
void
finish_for_stmt (tree for_stmt)
{
+ FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt));
+
/* Pop the scope for the body of the loop. */
- do_poplevel ();
- RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
- if (NEW_FOR_SCOPE_P (for_stmt))
- do_poplevel ();
+ if (flag_new_for_scope > 0)
+ {
+ tree scope = TREE_CHAIN (for_stmt);
+ TREE_CHAIN (for_stmt) = NULL;
+ add_stmt (do_poplevel (scope));
+ }
+
finish_stmt ();
}
@@ -724,10 +736,16 @@ finish_continue_stmt (void)
tree
begin_switch_stmt (void)
{
- tree r;
- do_pushlevel (sk_block);
+ tree r, scope;
+
r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+
+ scope = do_pushlevel (sk_block);
+ TREE_CHAIN (r) = scope;
+
add_stmt (r);
+ SWITCH_COND (r) = push_stmt_list ();
+
return r;
}
@@ -770,9 +788,10 @@ finish_switch_cond (tree cond, tree switch_stmt)
cond = index;
}
}
- FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
+ finish_cond (cond, &SWITCH_COND (switch_stmt));
SWITCH_TYPE (switch_stmt) = orig_type;
push_switch (switch_stmt);
+ SWITCH_BODY (switch_stmt) = push_stmt_list ();
}
/* Finish the body of a switch-statement, which may be given by
@@ -781,10 +800,15 @@ finish_switch_cond (tree cond, tree switch_stmt)
void
finish_switch_stmt (tree switch_stmt)
{
- RECHAIN_STMTS (switch_stmt, SWITCH_BODY (switch_stmt));
+ tree scope;
+
+ SWITCH_BODY (switch_stmt) = pop_stmt_list (SWITCH_BODY (switch_stmt));
pop_switch ();
finish_stmt ();
- do_poplevel ();
+
+ scope = TREE_CHAIN (switch_stmt);
+ TREE_CHAIN (switch_stmt) = NULL;
+ add_stmt (do_poplevel (scope));
}
/* Begin a try-block. Returns a newly-created TRY_BLOCK if
@@ -795,6 +819,7 @@ begin_try_block (void)
{
tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
add_stmt (r);
+ TRY_STMTS (r) = push_stmt_list ();
return r;
}
@@ -803,9 +828,8 @@ begin_try_block (void)
tree
begin_function_try_block (void)
{
- tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
+ tree r = begin_try_block ();
FN_TRY_BLOCK_P (r) = 1;
- add_stmt (r);
return r;
}
@@ -814,7 +838,8 @@ begin_function_try_block (void)
void
finish_try_block (tree try_block)
{
- RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
+ TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block));
+ TRY_HANDLERS (try_block) = push_stmt_list ();
}
/* Finish the body of a cleanup try-block, which may be given by
@@ -823,7 +848,7 @@ finish_try_block (tree try_block)
void
finish_cleanup_try_block (tree try_block)
{
- RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
+ TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block));
}
/* Finish an implicitly generated try-block, with a cleanup is given
@@ -841,16 +866,9 @@ finish_cleanup (tree cleanup, tree try_block)
void
finish_function_try_block (tree try_block)
{
- if (TREE_CHAIN (try_block)
- && TREE_CODE (TREE_CHAIN (try_block)) == CTOR_INITIALIZER)
- {
- /* Chain the compound statement after the CTOR_INITIALIZER. */
- TREE_CHAIN (TREE_CHAIN (try_block)) = last_tree;
- /* And make the CTOR_INITIALIZER the body of the try-block. */
- RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
- }
- else
- RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
+ finish_try_block (try_block);
+ /* FIXME : something queer about CTOR_INITIALIZER somehow following
+ the try block, but moving it inside. */
in_function_try_handler = 1;
}
@@ -860,7 +878,7 @@ finish_function_try_block (tree try_block)
void
finish_handler_sequence (tree try_block)
{
- RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
+ TRY_HANDLERS (try_block) = pop_stmt_list (TRY_HANDLERS (try_block));
check_handlers (TRY_HANDLERS (try_block));
}
@@ -870,8 +888,7 @@ void
finish_function_handler_sequence (tree try_block)
{
in_function_try_handler = 0;
- RECHAIN_STMTS (try_block, TRY_HANDLERS (try_block));
- check_handlers (TRY_HANDLERS (try_block));
+ finish_handler_sequence (try_block);
}
/* Begin a handler. Returns a HANDLER if appropriate. */
@@ -880,11 +897,14 @@ tree
begin_handler (void)
{
tree r;
+
r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
add_stmt (r);
+
/* Create a binding level for the eh_info and the exception object
cleanup. */
- do_pushlevel (sk_catch);
+ HANDLER_BODY (r) = do_pushlevel (sk_catch);
+
return r;
}
@@ -902,8 +922,7 @@ finish_handler_parms (tree decl, tree handler)
{
decl = pushdecl (decl);
decl = push_template_decl (decl);
- add_decl_stmt (decl);
- RECHAIN_STMTS (handler, HANDLER_PARMS (handler));
+ HANDLER_PARMS (handler) = decl;
type = TREE_TYPE (decl);
}
}
@@ -923,8 +942,7 @@ finish_handler (tree handler)
{
if (!processing_template_decl)
expand_end_catch_block ();
- do_poplevel ();
- RECHAIN_STMTS (handler, HANDLER_BODY (handler));
+ HANDLER_BODY (handler) = do_poplevel (HANDLER_BODY (handler));
}
/* Begin a compound-statement. If HAS_NO_SCOPE is true, the
@@ -932,58 +950,50 @@ finish_handler (tree handler)
COMPOUND_STMT. */
tree
-begin_compound_stmt (bool has_no_scope)
+begin_compound_stmt (unsigned int flags)
{
- tree r;
- int is_try = 0;
-
- r = build_stmt (COMPOUND_STMT, NULL_TREE);
-
- if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
- is_try = 1;
-
- add_stmt (r);
- if (has_no_scope)
- COMPOUND_STMT_NO_SCOPE (r) = 1;
+ tree r;
- last_expr_type = NULL_TREE;
+ if (flags & BCS_NO_SCOPE)
+ {
+ r = push_stmt_list ();
+ STATEMENT_LIST_NO_SCOPE (r) = 1;
- if (!has_no_scope)
- do_pushlevel (is_try ? sk_try : sk_block);
+ /* Normally, we try hard to keep the BLOCK for a statement-expression.
+ But, if it's a statement-expression with a scopeless block, there's
+ nothing to keep, and we don't want to accidentally keep a block
+ *inside* the scopeless block. */
+ keep_next_level (false);
+ }
else
- /* Normally, we try hard to keep the BLOCK for a
- statement-expression. But, if it's a statement-expression with
- a scopeless block, there's nothing to keep, and we don't want
- to accidentally keep a block *inside* the scopeless block. */
- keep_next_level (false);
+ r = do_pushlevel (flags & BCS_TRY_BLOCK ? sk_try : sk_block);
+
+ if (flags & BCS_FN_BODY || processing_template_decl)
+ {
+ r = build (COMPOUND_STMT, NULL_TREE, r);
+ COMPOUND_STMT_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0;
+ COMPOUND_STMT_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0;
+ TREE_SIDE_EFFECTS (r) = 1;
+ }
return r;
}
/* Finish a compound-statement, which is given by COMPOUND_STMT. */
-tree
-finish_compound_stmt (tree compound_stmt)
+void
+finish_compound_stmt (tree stmt)
{
- tree r;
- tree t;
-
- if (COMPOUND_STMT_NO_SCOPE (compound_stmt))
- r = NULL_TREE;
+ if (TREE_CODE (stmt) == COMPOUND_STMT)
+ COMPOUND_BODY (stmt) = do_poplevel (COMPOUND_BODY (stmt));
+ else if (STATEMENT_LIST_NO_SCOPE (stmt))
+ stmt = pop_stmt_list (stmt);
else
- r = do_poplevel ();
-
- RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_stmt));
+ stmt = do_poplevel (stmt);
- /* When we call finish_stmt we will lose LAST_EXPR_TYPE. But, since
- the precise purpose of that variable is store the type of the
- last expression statement within the last compound statement, we
- preserve the value. */
- t = last_expr_type;
+ /* ??? See c_end_compound_stmt wrt statement expressions. */
+ add_stmt (stmt);
finish_stmt ();
- last_expr_type = t;
-
- return r;
}
/* Finish an asm-statement, whose components are a STRING, some
@@ -1090,7 +1100,7 @@ finish_label_decl (tree name)
void
finish_decl_cleanup (tree decl, tree cleanup)
{
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ push_cleanup (decl, cleanup, false);
}
/* If the current scope exits with an exception, run CLEANUP. */
@@ -1098,9 +1108,7 @@ finish_decl_cleanup (tree decl, tree cleanup)
void
finish_eh_cleanup (tree cleanup)
{
- tree r = build_stmt (CLEANUP_STMT, NULL_TREE, cleanup);
- CLEANUP_EH_ONLY (r) = 1;
- add_stmt (r);
+ push_cleanup (NULL, cleanup, true);
}
/* The MEM_INITS is a list of mem-initializers, in reverse of the
@@ -1120,14 +1128,6 @@ finish_mem_initializers (tree mem_inits)
emit_mem_initializers (mem_inits);
}
-/* Returns the stack of SCOPE_STMTs for the current function. */
-
-tree *
-current_scope_stmt_stack (void)
-{
- return &cfun->language->base.x_scope_stmt_stack;
-}
-
/* Finish a parenthesized expression EXPR. */
tree
@@ -1348,17 +1348,7 @@ finish_qualified_id_expr (tree qualifying_class, tree expr, bool done,
tree
begin_stmt_expr (void)
{
- /* If we're outside a function, we won't have a statement-tree to
- work with. But, if we see a statement-expression we need to
- create one. */
- if (! cfun && !last_tree)
- begin_stmt_tree (&scope_chain->x_saved_tree);
-
- last_expr_type = NULL_TREE;
-
- keep_next_level (true);
-
- return last_tree;
+ return push_stmt_list ();
}
/* Process the final expression of a statement expression. EXPR can be
@@ -1367,7 +1357,7 @@ begin_stmt_expr (void)
expression. */
tree
-finish_stmt_expr_expr (tree expr)
+finish_stmt_expr_expr (tree expr, tree stmt_expr)
{
tree result = NULL_TREE;
tree type = void_type_node;
@@ -1408,15 +1398,16 @@ finish_stmt_expr_expr (tree expr)
if (expr != error_mark_node)
{
result = build_stmt (EXPR_STMT, expr);
+ EXPR_STMT_STMT_EXPR_RESULT (result) = 1;
add_stmt (result);
}
}
finish_stmt ();
- /* Remember the last expression so that finish_stmt_expr can pull it
- apart. */
- last_expr_type = result ? result : void_type_node;
+ /* Remember the last expression so that finish_stmt_expr
+ can pull it apart. */
+ TREE_TYPE (stmt_expr) = result;
return result;
}
@@ -1426,46 +1417,62 @@ finish_stmt_expr_expr (tree expr)
representing the statement-expression. */
tree
-finish_stmt_expr (tree rtl_expr, bool has_no_scope)
+finish_stmt_expr (tree stmt_expr, bool has_no_scope)
{
- tree result;
- tree result_stmt = last_expr_type;
- tree type;
-
- if (!last_expr_type)
+ tree result, result_stmt, type;
+ tree *result_stmt_p = NULL;
+
+ result_stmt = TREE_TYPE (stmt_expr);
+ TREE_TYPE (stmt_expr) = void_type_node;
+ result = pop_stmt_list (stmt_expr);
+
+ if (!result_stmt || VOID_TYPE_P (result_stmt))
type = void_type_node;
else
{
- if (result_stmt == void_type_node)
+ /* We need to search the statement expression for the result_stmt,
+ since we'll need to replace it entirely. */
+ tree t;
+ result_stmt_p = &result;
+ while (1)
{
- type = void_type_node;
- result_stmt = NULL_TREE;
+ t = *result_stmt_p;
+ if (t == result_stmt)
+ break;
+
+ switch (TREE_CODE (t))
+ {
+ case STATEMENT_LIST:
+ {
+ tree_stmt_iterator i = tsi_last (t);
+ result_stmt_p = tsi_stmt_ptr (i);
+ break;
+ }
+ case BIND_EXPR:
+ result_stmt_p = &BIND_EXPR_BODY (t);
+ break;
+ case COMPOUND_STMT:
+ result_stmt_p = &COMPOUND_BODY (t);
+ break;
+ case TRY_FINALLY_EXPR:
+ case TRY_CATCH_EXPR:
+ case CLEANUP_STMT:
+ result_stmt_p = &TREE_OPERAND (t, 0);
+ break;
+ default:
+ abort ();
+ }
}
- else
- type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt));
+ type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt));
}
-
- result = build_min (STMT_EXPR, type, last_tree);
- TREE_SIDE_EFFECTS (result) = 1;
- STMT_EXPR_NO_SCOPE (result) = has_no_scope;
-
- last_expr_type = NULL_TREE;
-
- /* Remove the compound statement from the tree structure; it is
- now saved in the STMT_EXPR. */
- last_tree = rtl_expr;
- TREE_CHAIN (last_tree) = NULL_TREE;
-
- /* If we created a statement-tree for this statement-expression,
- remove it now. */
- if (! cfun
- && TREE_CHAIN (scope_chain->x_saved_tree) == NULL_TREE)
- finish_stmt_tree (&scope_chain->x_saved_tree);
if (processing_template_decl)
- return result;
-
- if (!VOID_TYPE_P (type))
+ {
+ result = build_min (STMT_EXPR, type, result);
+ TREE_SIDE_EFFECTS (result) = 1;
+ STMT_EXPR_NO_SCOPE (result) = has_no_scope;
+ }
+ else if (!VOID_TYPE_P (type))
{
/* Pull out the TARGET_EXPR that is the final expression. Put
the target's init_expr as the final expression and then put
@@ -1474,10 +1481,24 @@ finish_stmt_expr (tree rtl_expr, bool has_no_scope)
tree last_expr = EXPR_STMT_EXPR (result_stmt);
my_friendly_assert (TREE_CODE (last_expr) == TARGET_EXPR, 20030729);
- EXPR_STMT_EXPR (result_stmt) = TREE_OPERAND (last_expr, 1);
+ *result_stmt_p = TREE_OPERAND (last_expr, 1);
+
+ if (TREE_CODE (result) == BIND_EXPR)
+ {
+ if (VOID_TYPE_P (TREE_TYPE (result)))
+ TREE_TYPE (result) = TREE_TYPE (last_expr);
+ else if (same_type_p (TREE_TYPE (result), TREE_TYPE (last_expr)))
+ ;
+ else
+ abort ();
+ }
+ else if (TREE_CODE (result) == STATEMENT_LIST)
+ result = build (BIND_EXPR, TREE_TYPE (last_expr), NULL, result, NULL);
+
TREE_OPERAND (last_expr, 1) = result;
result = last_expr;
}
+
return result;
}
@@ -2755,11 +2776,8 @@ simplify_aggr_init_expr (tree *tp)
/* We want to use the value of the initialized location as the
result. */
- call_expr = build (COMPOUND_EXPR, type,
- call_expr, slot);
+ call_expr = build (COMPOUND_EXPR, type, call_expr, slot);
- /* Replace the AGGR_INIT_EXPR with the CALL_EXPR. */
- TREE_CHAIN (call_expr) = TREE_CHAIN (aggr_init_expr);
*tp = call_expr;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 5bf6d144cf1..9b998ea47b0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -293,13 +293,10 @@ cxx_incomplete_type_error (tree value, tree type)
/* The recursive part of split_nonconstant_init. DEST is an lvalue
- expression to which INIT should be assigned. INIT is a CONSTRUCTOR.
- PCODE is a pointer to the tail of a chain of statements being emitted.
- The return value is the new tail of that chain after new statements
- are generated. */
+ expression to which INIT should be assigned. INIT is a CONSTRUCTOR. */
-static tree *
-split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
+static void
+split_nonconstant_init_1 (tree dest, tree init)
{
tree *pelt, elt, type = TREE_TYPE (dest);
tree sub, code, inner_type = NULL;
@@ -331,7 +328,7 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
else
sub = build (COMPONENT_REF, inner_type, dest, field_index);
- pcode = split_nonconstant_init_1 (sub, value, pcode);
+ split_nonconstant_init_1 (sub, value);
}
else if (!initializer_constant_valid_p (value, inner_type))
{
@@ -344,11 +341,10 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
code = build (MODIFY_EXPR, inner_type, sub, value);
code = build_stmt (EXPR_STMT, code);
-
- *pcode = code;
- pcode = &TREE_CHAIN (code);
+ add_stmt (code);
continue;
}
+
pelt = &TREE_CHAIN (elt);
}
break;
@@ -359,15 +355,13 @@ split_nonconstant_init_1 (tree dest, tree init, tree *pcode)
CONSTRUCTOR_ELTS (init) = NULL;
code = build (MODIFY_EXPR, type, dest, init);
code = build_stmt (EXPR_STMT, code);
- pcode = &TREE_CHAIN (code);
+ add_stmt (code);
}
break;
default:
abort ();
}
-
- return pcode;
}
/* A subroutine of store_init_value. Splits non-constant static
@@ -382,10 +376,9 @@ split_nonconstant_init (tree dest, tree init)
if (TREE_CODE (init) == CONSTRUCTOR)
{
- code = build_stmt (COMPOUND_STMT, NULL_TREE);
- split_nonconstant_init_1 (dest, init, &COMPOUND_BODY (code));
- code = build1 (STMT_EXPR, void_type_node, code);
- TREE_SIDE_EFFECTS (code) = 1;
+ code = push_stmt_list ();
+ split_nonconstant_init_1 (dest, init);
+ code = pop_stmt_list (code);
DECL_INITIAL (dest) = init;
TREE_READONLY (dest) = 0;
}
OpenPOWER on IntegriCloud