c-common.c (lang_gimplify_stmt): Remove next_p argument.

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

From-SVN: r83221
This commit is contained in:
Richard Henderson 2004-06-15 18:21:38 -07:00 committed by Richard Henderson
parent aaab7bb6d7
commit 325c369115
48 changed files with 1528 additions and 1665 deletions

View File

@ -1,3 +1,111 @@
2004-06-15 Richard Henderson <rth@redhat.com>
* 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.
2004-06-15 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
* df.c (df_reg_clobber_gen): Removed.

View File

@ -690,7 +690,7 @@ int (*lang_statement_code_p) (enum tree_code);
/* If non-NULL, the address of a language-specific function that does any
language-specific gimplification for _STMT nodes and returns 1 iff
handled. */
int (*lang_gimplify_stmt) (tree *, tree *);
int (*lang_gimplify_stmt) (tree *);
/* If non-NULL, the address of a language-specific function that takes
any action required right before expand_function_end is called. */
@ -723,27 +723,6 @@ const struct fname_var_t fname_vars[] =
static int constant_fits_type_p (tree, tree);
/* Keep a stack of if statements. We record the number of compound
statements seen up to the if keyword, as well as the line number
and file of the if. If a potentially ambiguous else is seen, that
fact is recorded; the warning is issued when we can be sure that
the enclosing if statement does not have an else branch. */
typedef struct
{
int compstmt_count;
location_t locus;
int needs_warning;
tree if_stmt;
} if_elt;
static if_elt *if_stack;
/* Amount of space in the if statement stack. */
static int if_stack_space = 0;
/* Stack pointer. */
static int if_stack_pointer = 0;
static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
static tree handle_common_attribute (tree *, tree, tree, int, bool *);
@ -876,131 +855,6 @@ const struct attribute_spec c_common_format_attribute_table[] =
{ NULL, 0, 0, false, false, false, NULL }
};
/* Record the start of an if-then, and record the start of it
for ambiguous else detection.
COND is the condition for the if-then statement.
IF_STMT is the statement node that has already been created for
this if-then statement. It is created before parsing the
condition to keep line number information accurate. */
void
c_expand_start_cond (tree cond, int compstmt_count, tree if_stmt)
{
/* Make sure there is enough space on the stack. */
if (if_stack_space == 0)
{
if_stack_space = 10;
if_stack = xmalloc (10 * sizeof (if_elt));
}
else if (if_stack_space == if_stack_pointer)
{
if_stack_space += 10;
if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt));
}
IF_COND (if_stmt) = cond;
add_stmt (if_stmt);
/* Record this if statement. */
if_stack[if_stack_pointer].compstmt_count = compstmt_count;
if_stack[if_stack_pointer].locus = input_location;
if_stack[if_stack_pointer].needs_warning = 0;
if_stack[if_stack_pointer].if_stmt = if_stmt;
if_stack_pointer++;
}
/* Called after the then-clause for an if-statement is processed. */
void
c_finish_then (void)
{
tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
}
/* Record the end of an if-then. Optionally warn if a nested
if statement had an ambiguous else clause. */
void
c_expand_end_cond (void)
{
if_stack_pointer--;
if (if_stack[if_stack_pointer].needs_warning)
warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
&if_stack[if_stack_pointer].locus);
last_expr_type = NULL_TREE;
}
/* Called between the then-clause and the else-clause
of an if-then-else. */
void
c_expand_start_else (void)
{
/* An ambiguous else warning must be generated for the enclosing if
statement, unless we see an else branch for that one, too. */
if (warn_parentheses
&& if_stack_pointer > 1
&& (if_stack[if_stack_pointer - 1].compstmt_count
== if_stack[if_stack_pointer - 2].compstmt_count))
if_stack[if_stack_pointer - 2].needs_warning = 1;
/* Even if a nested if statement had an else branch, it can't be
ambiguous if this one also has an else. So don't warn in that
case. Also don't warn for any if statements nested in this else. */
if_stack[if_stack_pointer - 1].needs_warning = 0;
if_stack[if_stack_pointer - 1].compstmt_count--;
}
/* Called after the else-clause for an if-statement is processed. */
void
c_finish_else (void)
{
tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
}
/* Begin an if-statement. Returns a newly created IF_STMT if
appropriate.
Unlike the C++ front-end, we do not call add_stmt here; it is
probably safe to do so, but I am not very familiar with this
code so I am being extra careful not to change its behavior
beyond what is strictly necessary for correctness. */
tree
c_begin_if_stmt (void)
{
tree r;
r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
return r;
}
/* Begin a while statement. Returns a newly created WHILE_STMT if
appropriate.
Unlike the C++ front-end, we do not call add_stmt here; it is
probably safe to do so, but I am not very familiar with this
code so I am being extra careful not to change its behavior
beyond what is strictly necessary for correctness. */
tree
c_begin_while_stmt (void)
{
tree r;
r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
return r;
}
void
c_finish_while_stmt_cond (tree cond, tree while_stmt)
{
WHILE_COND (while_stmt) = cond;
}
/* Push current bindings for the function name VAR_DECLS. */
void
@ -1026,43 +880,32 @@ start_fname_decls (void)
saved_function_name_decls);
}
/* Finish up the current bindings, adding them into the
current function's statement tree. This is done by wrapping the
function's body in a COMPOUND_STMT containing these decls too. This
must be done _before_ finish_stmt_tree is called. If there is no
current function, we must be at file scope and no statements are
involved. Pop the previous bindings. */
/* Finish up the current bindings, adding them into the current function's
statement tree. This must be done _before_ finish_stmt_tree is called.
If there is no current function, we must be at file scope and no statements
are involved. Pop the previous bindings. */
void
finish_fname_decls (void)
{
unsigned ix;
tree body = NULL_TREE;
tree stmts = NULL_TREE;
tree stack = saved_function_name_decls;
for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
body = chainon (TREE_VALUE (stack), body);
append_to_statement_list (TREE_VALUE (stack), &stmts);
if (body)
if (stmts)
{
/* They were called into existence, so add to statement tree. Add
the DECL_STMTs inside the outermost scope. */
tree *p = &DECL_SAVED_TREE (current_function_decl);
/* Skip the dummy EXPR_STMT and any EH_SPEC_BLOCK. */
while (TREE_CODE (*p) != COMPOUND_STMT)
{
if (TREE_CODE (*p) == EXPR_STMT)
p = &TREE_CHAIN (*p);
else
p = &TREE_OPERAND(*p, 0);
}
tree *bodyp = &DECL_SAVED_TREE (current_function_decl);
p = &COMPOUND_BODY (*p);
if (TREE_CODE (*p) == SCOPE_STMT)
p = &TREE_CHAIN (*p);
if (TREE_CODE (*bodyp) == COMPOUND_STMT)
bodyp = &COMPOUND_BODY (*bodyp);
if (TREE_CODE (*bodyp) == BIND_EXPR)
bodyp = &BIND_EXPR_BODY (*bodyp);
body = chainon (body, *p);
*p = body;
append_to_statement_list (*bodyp, &stmts);
*bodyp = stmts;
}
for (ix = 0; fname_vars[ix].decl; ix++)
@ -1167,30 +1010,23 @@ fname_decl (unsigned int rid, tree id)
decl = *fname_vars[ix].decl;
if (!decl)
{
tree saved_last_tree = last_tree;
/* If a tree is built here, it would normally have the lineno of
the current statement. Later this tree will be moved to the
beginning of the function and this line number will be wrong.
To avoid this problem set the lineno to 0 here; that prevents
it from appearing in the RTL. */
int saved_lineno = input_line;
tree stmts;
location_t saved_locus = input_location;
input_line = 0;
stmts = push_stmt_list ();
decl = (*make_fname_decl) (id, fname_vars[ix].pretty);
if (last_tree != saved_last_tree)
{
/* We created some statement tree for the decl. This belongs
at the start of the function, so remove it now and reinsert
it after the function is complete. */
tree stmts = TREE_CHAIN (saved_last_tree);
TREE_CHAIN (saved_last_tree) = NULL_TREE;
last_tree = saved_last_tree;
saved_function_name_decls = tree_cons (decl, stmts,
saved_function_name_decls);
}
stmts = pop_stmt_list (stmts);
if (!IS_EMPTY_STMT (stmts))
saved_function_name_decls
= tree_cons (decl, stmts, saved_function_name_decls);
*fname_vars[ix].decl = decl;
input_line = saved_lineno;
input_location = saved_locus;
}
if (!ix && !current_function_decl)
pedwarn ("%J'%D' is not defined outside of function scope", decl, decl);
@ -1790,7 +1626,11 @@ c_expand_expr_stmt (tree expr)
&& TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
error ("expression statement has incomplete type");
last_expr_type = TREE_TYPE (expr);
/* As tempting as it might be, we can't diagnose statement with no
effect yet. We have to wait until after statement expressions
have been parsed, and that process modifies the trees we are
creating here. */
return add_stmt (build_stmt (EXPR_STMT, expr));
}
@ -2855,28 +2695,28 @@ c_type_hash (const void *p)
tree t2;
switch (TREE_CODE (t))
{
/* For pointers, hash on pointee type plus some swizzling. */
case POINTER_TYPE:
return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
/* Hash on number of elements and total size. */
case ENUMERAL_TYPE:
shift = 3;
t2 = TYPE_VALUES (t);
break;
case RECORD_TYPE:
shift = 0;
t2 = TYPE_FIELDS (t);
break;
case QUAL_UNION_TYPE:
shift = 1;
t2 = TYPE_FIELDS (t);
break;
case UNION_TYPE:
shift = 2;
t2 = TYPE_FIELDS (t);
break;
default:
abort ();
/* For pointers, hash on pointee type plus some swizzling. */
case POINTER_TYPE:
return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
/* Hash on number of elements and total size. */
case ENUMERAL_TYPE:
shift = 3;
t2 = TYPE_VALUES (t);
break;
case RECORD_TYPE:
shift = 0;
t2 = TYPE_FIELDS (t);
break;
case QUAL_UNION_TYPE:
shift = 1;
t2 = TYPE_FIELDS (t);
break;
case UNION_TYPE:
shift = 2;
t2 = TYPE_FIELDS (t);
break;
default:
abort ();
}
for (; t2; t2 = TREE_CHAIN (t2))
i++;
@ -4287,10 +4127,6 @@ c_safe_from_p (rtx target, tree exp)
return 0;
}
/* For any statement, we must follow the statement-chain. */
if (STATEMENT_CODE_P (TREE_CODE (exp)) && TREE_CHAIN (exp))
return safe_from_p (target, TREE_CHAIN (exp), /*top_p=*/0);
/* Assume everything else is safe. */
return 1;
}
@ -5727,18 +5563,6 @@ c_walk_subtrees (tree *tp, int *walk_subtrees_p ATTRIBUTE_UNUSED,
#undef WALK_SUBTREE
}
/* C implementation of lang_hooks.tree_inlining.tree_chain_matters_p.
Apart from TREE_LISTs, the only trees whose TREE_CHAIN we care about are
_STMT nodes. */
int
c_tree_chain_matters_p (tree t)
{
/* For statements, we also walk the chain so that we cover the
entire statement tree. */
return STATEMENT_CODE_P (TREE_CODE (t));
}
/* Function to help qsort sort FIELD_DECLs by name order. */
int

View File

@ -81,14 +81,6 @@ DEFTREECODE (LABEL_STMT, "label_stmt", 'e', 1)
/* Used to represent an inline assembly statement. */
DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 4)
/* A SCOPE_STMT marks the beginning or end of a scope. If
SCOPE_BEGIN_P holds, then this is the start of a scope. If
SCOPE_END_P holds, then this is the end of a scope. If
SCOPE_NULLIFIED_P holds then there turned out to be no variables in
this scope. The SCOPE_STMT_BLOCK is the BLOCK containing the
variables declared in this scope. */
DEFTREECODE (SCOPE_STMT, "scope_stmt", 'e', 1)
/* Used to represent a CASE_LABEL. The operands are CASE_LOW and
CASE_HIGH, respectively. If CASE_LOW is NULL_TREE, the label is a
'default' label. If CASE_HIGH is NULL_TREE, the label is a normal case
@ -107,9 +99,9 @@ DEFTREECODE (STMT_EXPR, "stmt_expr", 'e', 1)
DEFTREECODE (COMPOUND_LITERAL_EXPR, "compound_literal_expr", 'e', 1)
/* A CLEANUP_STMT marks the point at which a declaration is fully
constructed. If, after this point, the CLEANUP_DECL goes out of
scope, the CLEANUP_EXPR must be run. */
DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 2)
constructed. The CLEANUP_EXPR is run on behalf of CLEANUP_DECL
when CLEANUP_BODY completes. */
DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 3)
/*
Local variables:

View File

@ -27,20 +27,17 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ggc.h"
/* Usage of TREE_LANG_FLAG_?:
0: COMPOUND_STMT_NO_SCOPE (in COMPOUND_STMT).
TREE_NEGATED_INT (in INTEGER_CST).
0: TREE_NEGATED_INT (in INTEGER_CST).
IDENTIFIER_MARKED (used by search routines).
SCOPE_BEGIN_P (in SCOPE_STMT)
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
NEW_FOR_SCOPE_P (in FOR_STMT)
ASM_INPUT_P (in ASM_STMT)
STMT_EXPR_NO_SCOPE (in STMT_EXPR)
1: C_DECLARED_LABEL_FLAG (in LABEL_DECL)
STMT_IS_FULL_EXPR_P (in _STMT)
STATEMENT_LIST_STMT_EXPR (in STATEMENT_LIST)
2: unused
3: SCOPE_NO_CLEANUPS_P (in SCOPE_STMT)
COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT)
4: SCOPE_PARTIAL_P (in SCOPE_STMT)
3: unused
4: unused
*/
/* Reserved identifiers. This is the union of all the keywords for C,
@ -245,13 +242,9 @@ extern c_language_kind c_language;
/* Information about a statement tree. */
struct stmt_tree_s GTY(()) {
/* The last statement added to the tree. */
tree x_last_stmt;
/* The type of the last expression statement. (This information is
needed to implement the statement-expression extension.) */
tree x_last_expr_type;
/* The last filename we recorded. */
const char *x_last_expr_filename;
/* The current statment list being collected. */
tree x_cur_stmt_list;
/* In C++, Nonzero if we should treat statements as full
expressions. In particular, this variable is no-zero if at the
end of a statement we should destroy any temporaries created
@ -278,38 +271,17 @@ struct c_language_function GTY(()) {
/* While we are parsing the function, this contains information
about the statement-tree that we are building. */
struct stmt_tree_s x_stmt_tree;
/* The stack of SCOPE_STMTs for the current function. */
tree x_scope_stmt_stack;
};
/* When building a statement-tree, this is the last statement added to
the tree. */
/* When building a statement-tree, this is the current statment list
being collected. It's TREE_CHAIN is a back-pointer to the previous
statment list. */
#define last_tree (current_stmt_tree ()->x_last_stmt)
/* The type of the last expression-statement we have seen. */
#define last_expr_type (current_stmt_tree ()->x_last_expr_type)
/* The name of the last file we have seen. */
#define last_expr_filename (current_stmt_tree ()->x_last_expr_filename)
/* LAST_TREE contains the last statement parsed. These are chained
together through the TREE_CHAIN field, but often need to be
re-organized since the parse is performed bottom-up. This macro
makes LAST_TREE the indicated SUBSTMT of STMT. */
#define RECHAIN_STMTS(stmt, substmt) \
do { \
substmt = TREE_CHAIN (stmt); \
TREE_CHAIN (stmt) = NULL_TREE; \
last_tree = stmt; \
} while (0)
#define cur_stmt_list (current_stmt_tree ()->x_cur_stmt_list)
/* Language-specific hooks. */
extern int (*lang_gimplify_stmt) (tree *, tree *);
extern int (*lang_gimplify_stmt) (tree *);
extern void (*lang_expand_function_end) (void);
/* Callback that determines if it's ok for a function to have no
@ -320,12 +292,12 @@ extern void push_file_scope (void);
extern void pop_file_scope (void);
extern int yyparse (void);
extern stmt_tree current_stmt_tree (void);
extern tree *current_scope_stmt_stack (void);
extern void begin_stmt_tree (tree *);
extern tree push_stmt_list (void);
extern tree re_push_stmt_list (tree);
extern tree pop_stmt_list (tree);
extern tree add_stmt (tree);
extern void add_decl_stmt (tree);
extern tree add_scope_stmt (int, int);
extern void finish_stmt_tree (tree *);
extern void push_cleanup (tree, tree, bool);
extern tree walk_stmt_tree (tree *, walk_tree_fn, void *);
extern void prep_stmt (tree);
@ -891,11 +863,6 @@ extern void binary_op_error (enum tree_code);
(((EXP) == 0) ? (fancy_abort (__FILE__, __LINE__, __FUNCTION__), 0) : 0)
extern tree c_expand_expr_stmt (tree);
extern void c_expand_start_cond (tree, int, tree);
extern void c_finish_then (void);
extern void c_expand_start_else (void);
extern void c_finish_else (void);
extern void c_expand_end_cond (void);
/* Validate the expression after `case' and apply default promotions. */
extern tree check_case_value (tree);
extern tree fix_string_type (tree);
@ -952,6 +919,11 @@ extern void finish_file (void);
will always be false, since there are no destructors.) */
#define STMT_IS_FULL_EXPR_P(NODE) TREE_LANG_FLAG_1 ((NODE))
/* Nonzero if a given STATEMENT_LIST represents the outermost binding
if a statement expression. */
#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. */
@ -1019,53 +991,15 @@ extern void finish_file (void);
#define COMPOUND_LITERAL_EXPR_DECL(NODE) \
DECL_STMT_DECL (COMPOUND_LITERAL_EXPR_DECL_STMT (NODE))
/* Nonzero if this SCOPE_STMT is for the beginning of a scope. */
#define SCOPE_BEGIN_P(NODE) \
(TREE_LANG_FLAG_0 (SCOPE_STMT_CHECK (NODE)))
/* Nonzero if this SCOPE_STMT is for the end of a scope. */
#define SCOPE_END_P(NODE) \
(!SCOPE_BEGIN_P (SCOPE_STMT_CHECK (NODE)))
/* The BLOCK containing the declarations contained in this scope. */
#define SCOPE_STMT_BLOCK(NODE) \
(TREE_OPERAND (SCOPE_STMT_CHECK (NODE), 0))
/* Nonzero for a SCOPE_STMT if there were no variables in this scope. */
#define SCOPE_NULLIFIED_P(NODE) \
(SCOPE_STMT_BLOCK ((NODE)) == NULL_TREE)
/* Nonzero for a SCOPE_STMT which represents a lexical scope, but
which should be treated as non-existent from the point of view of
running cleanup actions. */
#define SCOPE_NO_CLEANUPS_P(NODE) \
(TREE_LANG_FLAG_3 (SCOPE_STMT_CHECK (NODE)))
/* Nonzero for a SCOPE_STMT if this statement is for a partial scope.
For example, in:
S s;
l:
S s2;
goto l;
there is (implicitly) a new scope after `l', even though there are
no curly braces. In particular, when we hit the goto, we must
destroy s2 and then re-construct it. For the implicit scope,
SCOPE_PARTIAL_P will be set. */
#define SCOPE_PARTIAL_P(NODE) \
(TREE_LANG_FLAG_4 (SCOPE_STMT_CHECK (NODE)))
/* The VAR_DECL to clean up in a CLEANUP_STMT. */
#define CLEANUP_DECL(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)
/* Nonzero if we want the new ISO rules for pushing a new scope for `for'
initialization variables. */
#define NEW_FOR_SCOPE_P(NODE) (TREE_LANG_FLAG_0 (NODE))
/* 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,
@ -1081,7 +1015,7 @@ enum c_tree_code {
CLEANUP_STMT, EXPR_STMT, COMPOUND_STMT, \
DECL_STMT, IF_STMT, FOR_STMT, \
WHILE_STMT, DO_STMT, RETURN_STMT, \
BREAK_STMT, CONTINUE_STMT, SCOPE_STMT, \
BREAK_STMT, CONTINUE_STMT, \
SWITCH_STMT, GOTO_STMT, LABEL_STMT, \
ASM_STMT, CASE_LABEL
@ -1124,12 +1058,6 @@ extern tree build_continue_stmt (void);
extern tree build_break_stmt (void);
extern tree build_return_stmt (tree);
#define COMPOUND_STMT_NO_SCOPE(NODE) TREE_LANG_FLAG_0 (NODE)
/* Used by the C++ frontend to mark the block around the member
initializers and cleanups. */
#define COMPOUND_STMT_BODY_BLOCK(NODE) TREE_LANG_FLAG_3 (NODE)
extern void c_expand_asm_operands (tree, tree, tree, tree, int, location_t);
/* These functions must be defined by each front-end which implements
@ -1204,14 +1132,13 @@ extern bool c_dump_tree (void *, tree);
extern int c_gimplify_expr (tree *, tree *, tree *);
extern tree c_walk_subtrees (tree*, int*, walk_tree_fn, void*, void*);
extern int c_tree_chain_matters_p (tree);
extern void c_warn_unused_result (tree *);
/* In c-simplify.c */
extern void c_genericize (tree);
extern int c_gimplify_stmt (tree *);
extern tree stmt_expr_last_stmt (tree);
extern tree c_build_bind_expr (tree, tree);
extern void pch_init (void);
extern int c_common_valid_pch (cpp_reader *pfile, const char *name, int fd);
@ -1236,6 +1163,7 @@ extern tree objc_message_selector (void);
extern tree lookup_objc_ivar (tree);
extern void *get_current_scope (void);
extern void objc_mark_locals_volatile (void *);
extern void objc_clear_super_receiver (void);
extern int objc_is_public (tree, tree);
/* In c-ppoutput.c */

View File

@ -105,10 +105,6 @@ static location_t current_function_prototype_locus;
static GTY(()) struct stmt_tree_s c_stmt_tree;
/* The current scope statement stack. */
static GTY(()) tree c_scope_stmt_stack;
/* State saving variables. */
int c_in_iteration_stmt;
int c_in_case_stmt;
@ -2999,6 +2995,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
TREE_USED (cleanup_decl) = 1;
/* Initialize EH, if we've been told to do so. */
if (flag_exceptions && !eh_initialized_p)
@ -3011,7 +3008,7 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
using_eh_for_cleanups ();
}
add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
push_cleanup (decl, cleanup, false);
}
}
}
@ -6142,7 +6139,7 @@ store_parm_decls (void)
allocate_struct_function (fndecl);
/* Begin the statement tree for this function. */
begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
/* If this is a nested function, save away the sizes of any
variable-size types so that we can expand them when generating
@ -6214,22 +6211,6 @@ finish_function (void)
{
tree fndecl = current_function_decl;
/* When a function declaration is totally empty, e.g.
void foo(void) { }
(the argument list is irrelevant) the compstmt rule will not
bother calling push_scope/pop_scope, which means we get here with
the scope stack out of sync. Detect this situation by noticing
that current_scope is still as store_parm_decls left it, and do
a dummy push/pop to get back to consistency.
Note that the call to push_scope does not actually push another
scope - see there for details. */
if (current_scope->parm_flag && next_is_function_body)
{
push_scope ();
pop_scope ();
}
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
@ -6273,10 +6254,10 @@ finish_function (void)
}
}
finish_fname_decls ();
/* Tie off the statement tree for this function. */
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
finish_fname_decls ();
/* Complain if there's just no return statement. */
if (warn_return_type
@ -6438,7 +6419,6 @@ c_push_function_context (struct function *f)
f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
p->x_in_iteration_stmt = c_in_iteration_stmt;
p->x_in_case_stmt = c_in_case_stmt;
p->returns_value = current_function_returns_value;
@ -6466,7 +6446,6 @@ c_pop_function_context (struct function *f)
}
c_stmt_tree = p->base.x_stmt_tree;
c_scope_stmt_stack = p->base.x_scope_stmt_stack;
c_in_iteration_stmt = p->x_in_iteration_stmt;
c_in_case_stmt = p->x_in_case_stmt;
current_function_returns_value = p->returns_value;
@ -6518,14 +6497,6 @@ current_stmt_tree (void)
return &c_stmt_tree;
}
/* Returns the stack of SCOPE_STMTs for the current function. */
tree *
current_scope_stmt_stack (void)
{
return &c_scope_stmt_stack;
}
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
C. */
@ -6542,20 +6513,6 @@ extract_interface_info (void)
{
}
/* Return a new COMPOUND_STMT, after adding it to the current
statement tree. */
tree
c_begin_compound_stmt (void)
{
tree stmt;
/* Create the COMPOUND_STMT. */
stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
return stmt;
}
/* Return the global value of T as a symbol. */
tree

View File

@ -169,19 +169,6 @@ c_dump_tree (void *dump_info, tree t)
dump_next_stmt (di, t);
break;
case SCOPE_STMT:
dump_stmt (di, t);
if (SCOPE_BEGIN_P (t))
dump_string (di, "begn");
else
dump_string (di, "end");
if (SCOPE_NULLIFIED_P (t))
dump_string (di, "null");
if (!SCOPE_NO_CLEANUPS_P (t))
dump_string (di, "clnp");
dump_next_stmt (di, t);
break;
case STMT_EXPR:
dump_child ("stmt", STMT_EXPR_STMT (t));
break;

View File

@ -80,17 +80,11 @@ static enum gimplify_status gimplify_do_stmt (tree *);
static enum gimplify_status gimplify_if_stmt (tree *);
static enum gimplify_status gimplify_switch_stmt (tree *);
static enum gimplify_status gimplify_return_stmt (tree *);
static enum gimplify_status gimplify_stmt_expr (tree *);
static enum gimplify_status gimplify_compound_literal_expr (tree *);
#if defined ENABLE_CHECKING
static int is_last_stmt_of_scope (tree);
#endif
static enum gimplify_status gimplify_block (tree *, tree *);
static enum gimplify_status gimplify_cleanup (tree *, tree *);
static void gimplify_cleanup_stmts (tree);
static tree gimplify_c_loop (tree, tree, tree, bool);
static void push_context (void);
static void pop_context (void);
static tree c_build_bind_expr (tree, tree);
static void add_block_to_enclosing (tree);
static void gimplify_condition (tree *);
@ -160,6 +154,7 @@ c_genericize (tree fndecl)
/* Go ahead and gimplify for now. */
push_context ();
gimplify_cleanup_stmts (fndecl);
gimplify_function_tree (fndecl);
pop_context ();
@ -174,14 +169,41 @@ c_genericize (tree fndecl)
c_genericize (cgn->decl);
}
/* Genericize a CLEANUP_STMT. This just turns into a TRY_FINALLY or
TRY_CATCH depending on whether it's EH-only. */
static tree
gimplify_cleanup_stmt (tree *stmt_p, int *walk_subtrees,
void *data ATTRIBUTE_UNUSED)
{
tree stmt = *stmt_p;
if (DECL_P (stmt) || TYPE_P (stmt))
*walk_subtrees = 0;
else if (TREE_CODE (stmt) == CLEANUP_STMT)
*stmt_p = build (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR,
void_type_node, CLEANUP_BODY (stmt), CLEANUP_EXPR (stmt));
return NULL;
}
static void
gimplify_cleanup_stmts (tree fndecl)
{
walk_tree (&DECL_SAVED_TREE (fndecl), gimplify_cleanup_stmt, NULL, NULL);
}
/* Entry point for the tree lowering pass. Recursively scan
*STMT_P and convert it to a GIMPLE tree. */
int
c_gimplify_stmt (tree *stmt_p)
{
tree stmt, next;
tree outer_pre = NULL_TREE;
tree stmt = *stmt_p;
tree pre, post;
int saved_stmts_are_full_exprs_p;
location_t stmt_locus;
enum gimplify_status ret;
/* PRE and POST are tree chains that contain the side-effects of the
gimplified tree. For instance, given the expression tree:
@ -195,152 +217,130 @@ c_gimplify_stmt (tree *stmt_p)
c = t1 + b;
b = b + 1; <-- POST */
for (stmt = *stmt_p; stmt && stmt != error_mark_node; stmt = next)
/* Set up context appropriately for handling this statement. */
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
prep_stmt (stmt);
stmt_locus = input_location;
pre = NULL_TREE;
post = NULL_TREE;
switch (TREE_CODE (stmt))
{
tree pre, post;
int saved_stmts_are_full_exprs_p;
location_t stmt_locus;
enum gimplify_status ret;
case COMPOUND_STMT:
stmt = COMPOUND_BODY (stmt);
ret = GS_OK;
break;
/* Set up context appropriately for handling this statement. */
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
prep_stmt (stmt);
stmt_locus = input_location;
case FOR_STMT:
ret = gimplify_for_stmt (&stmt, &pre);
break;
pre = NULL_TREE;
post = NULL_TREE;
case WHILE_STMT:
ret = gimplify_while_stmt (&stmt);
break;
next = TREE_CHAIN (stmt);
case DO_STMT:
ret = gimplify_do_stmt (&stmt);
break;
switch (TREE_CODE (stmt))
case IF_STMT:
ret = gimplify_if_stmt (&stmt);
break;
case SWITCH_STMT:
ret = gimplify_switch_stmt (&stmt);
break;
case EXPR_STMT:
ret = gimplify_expr_stmt (&stmt);
break;
case RETURN_STMT:
ret = gimplify_return_stmt (&stmt);
break;
case DECL_STMT:
ret = gimplify_decl_stmt (&stmt);
break;
case LABEL_STMT:
stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
ret = GS_OK;
break;
case GOTO_STMT:
stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
ret = GS_OK;
break;
case CASE_LABEL:
{
tree label = create_artificial_label ();
stmt = build (CASE_LABEL_EXPR, void_type_node,
CASE_LOW (stmt), CASE_HIGH (stmt), label);
ret = GS_OK;
}
break;
case CONTINUE_STMT:
stmt = build_bc_goto (bc_continue);
ret = GS_OK;
break;
case BREAK_STMT:
stmt = build_bc_goto (bc_break);
ret = GS_OK;
break;
case ASM_STMT:
{
tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
ASM_CLOBBERS (stmt));
ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
stmt = new_stmt;
ret = GS_OK;
}
break;
default:
if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt))
{
case COMPOUND_STMT:
stmt = COMPOUND_BODY (stmt);
ret = GS_OK;
break;
case SCOPE_STMT:
ret = gimplify_block (&stmt, &next);
break;
case FOR_STMT:
ret = gimplify_for_stmt (&stmt, &next);
break;
case WHILE_STMT:
ret = gimplify_while_stmt (&stmt);
break;
case DO_STMT:
ret = gimplify_do_stmt (&stmt);
break;
case IF_STMT:
ret = gimplify_if_stmt (&stmt);
break;
case SWITCH_STMT:
ret = gimplify_switch_stmt (&stmt);
break;
case EXPR_STMT:
ret = gimplify_expr_stmt (&stmt);
break;
case RETURN_STMT:
ret = gimplify_return_stmt (&stmt);
break;
case DECL_STMT:
ret = gimplify_decl_stmt (&stmt);
break;
case LABEL_STMT:
stmt = build1 (LABEL_EXPR, void_type_node, LABEL_STMT_LABEL (stmt));
ret = GS_OK;
break;
case GOTO_STMT:
stmt = build1 (GOTO_EXPR, void_type_node, GOTO_DESTINATION (stmt));
ret = GS_OK;
break;
case CASE_LABEL:
{
tree label = create_artificial_label ();
stmt = build (CASE_LABEL_EXPR, void_type_node,
CASE_LOW (stmt), CASE_HIGH (stmt), label);
ret = GS_OK;
}
break;
case CONTINUE_STMT:
stmt = build_bc_goto (bc_continue);
ret = GS_OK;
break;
case BREAK_STMT:
stmt = build_bc_goto (bc_break);
ret = GS_OK;
break;
case CLEANUP_STMT:
ret = gimplify_cleanup (&stmt, &next);
break;
case ASM_STMT:
{
tree new_stmt = build (ASM_EXPR, void_type_node, ASM_STRING (stmt),
ASM_OUTPUTS (stmt), ASM_INPUTS (stmt),
ASM_CLOBBERS (stmt));
ASM_INPUT_P (new_stmt) = ASM_INPUT_P (stmt);
ASM_VOLATILE_P (new_stmt) = ASM_VOLATILE_P (stmt);
stmt = new_stmt;
ret = GS_OK;
}
break;
default:
if (lang_gimplify_stmt && (*lang_gimplify_stmt) (&stmt, &next))
{
ret = GS_OK;
break;
}
fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
debug_tree (stmt);
abort ();
break;
}
switch (ret)
{
case GS_ERROR:
goto cont;
case GS_OK:
gimplify_stmt (&stmt);
break;
case GS_ALL_DONE:
break;
default:
abort ();
}
/* PRE and POST now contain a list of statements for all the
side-effects in STMT. */
append_to_statement_list (stmt, &pre);
append_to_statement_list (post, &pre);
annotate_all_with_locus (&pre, stmt_locus);
append_to_statement_list (pre, &outer_pre);
cont:
/* Restore saved state. */
current_stmt_tree ()->stmts_are_full_exprs_p
= saved_stmts_are_full_exprs_p;
fprintf (stderr, "unhandled statement node in c_gimplify_stmt:\n");
debug_tree (stmt);
abort ();
break;
}
append_to_statement_list (stmt, &outer_pre);
*stmt_p = outer_pre;
switch (ret)
{
case GS_ERROR:
goto cont;
case GS_OK:
gimplify_stmt (&stmt);
break;
case GS_ALL_DONE:
break;
default:
abort ();
}
/* PRE and POST now contain a list of statements for all the
side-effects in STMT. */
append_to_statement_list (stmt, &pre);
append_to_statement_list (post, &pre);
annotate_all_with_locus (&pre, stmt_locus);
cont:
/* Restore saved state. */
current_stmt_tree ()->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
*stmt_p = pre;
return GS_ALL_DONE;
}
@ -366,7 +366,7 @@ add_block_to_enclosing (tree block)
BODY is a chain of C _STMT nodes for the contents of the scope, to be
genericized. */
static tree
tree
c_build_bind_expr (tree block, tree body)
{
tree decls, bind;
@ -390,99 +390,15 @@ c_build_bind_expr (tree block, tree body)
if (!body)
body = build_empty_stmt ();
bind = build (BIND_EXPR, void_type_node, decls, body, block);
TREE_SIDE_EFFECTS (bind) = 1;
return bind;
}
/* Genericize a syntactic block by removing the bracketing SCOPE_STMTs and
wrapping the intervening code in a BIND_EXPR. This function assumes
that matching SCOPE_STMTs will always appear in the same statement
sequence. */
static enum gimplify_status
gimplify_block (tree *stmt_p, tree *next_p)
{
tree *p;
tree block;
tree bind;
int depth;
location_t stmt_locus;
if (!SCOPE_BEGIN_P (*stmt_p))
if (decls || block)
{
/* Can wind up mismatched with syntax errors. */
if (!errorcount && !sorrycount)
abort ();
*stmt_p = NULL;
return GS_ERROR;
}
block = SCOPE_STMT_BLOCK (*stmt_p);
/* Find the matching ending SCOPE_STMT. */
depth = 1;
for (p = &TREE_CHAIN (*stmt_p);; p = &TREE_CHAIN (*p))
{
if (*p == NULL)
break;
if (TREE_CODE (*p) == SCOPE_STMT)
{
if (SCOPE_BEGIN_P (*p))
++depth;
else if (--depth == 0)
break;
}
}
stmt_locus = input_location;
if (*p)
{
if (SCOPE_STMT_BLOCK (*p) != block)
abort ();
if (EXPR_LOCUS (*p))
stmt_locus = *EXPR_LOCUS (*p);
*next_p = TREE_CHAIN (*p);
*p = NULL_TREE;
bind = build (BIND_EXPR, void_type_node, decls, body, block);
TREE_SIDE_EFFECTS (bind) = 1;
}
else
{
/* Can wind up mismatched with syntax errors. */
if (!errorcount && !sorrycount)
abort ();
}
bind = body;
bind = c_build_bind_expr (block, TREE_CHAIN (*stmt_p));
*stmt_p = bind;
input_location = stmt_locus;
return GS_OK;
}
/* Genericize a CLEANUP_STMT. Just wrap everything from here to the end of
the block in a TRY_FINALLY_EXPR. Or a TRY_CATCH_EXPR, if it's an
EH-only cleanup. */
static enum gimplify_status
gimplify_cleanup (tree *stmt_p, tree *next_p)
{
tree stmt = *stmt_p;
tree body = TREE_CHAIN (stmt);
tree cleanup = CLEANUP_EXPR (stmt);
enum tree_code code
= (CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR);
if (!body)
body = build_empty_stmt ();
if (!cleanup)
cleanup = build_empty_stmt ();
*stmt_p = build (code, void_type_node, body, cleanup);
*next_p = NULL_TREE;
return GS_OK;
return bind;
}
/* Gimplify an EXPR_STMT node.
@ -549,7 +465,7 @@ gimplify_condition (tree *cond_p)
{
tree decl = TREE_PURPOSE (cond);
tree value = TREE_VALUE (cond);
c_gimplify_stmt (&decl);
gimplify_stmt (&decl);
*cond_p = build (COMPOUND_EXPR, TREE_TYPE (value), decl, value);
}
}
@ -713,26 +629,17 @@ gimplify_c_loop (tree cond, tree body, tree incr, bool cond_is_first)
prequeue and hand off to gimplify_c_loop. */
static enum gimplify_status
gimplify_for_stmt (tree *stmt_p, tree *next_p)
gimplify_for_stmt (tree *stmt_p, tree *pre_p)
{
tree stmt = *stmt_p;
tree init = FOR_INIT_STMT (stmt);
if (init)
if (FOR_INIT_STMT (stmt))
{
/* Reorganize the statements so that we do the right thing with a
CLEANUP_STMT. We want the FOR_STMT and nothing else to be in the
scope of the cleanup, so play with pointers to accomplish that. */
FOR_INIT_STMT (stmt) = NULL_TREE;
chainon (init, stmt);
*stmt_p = init;
*next_p = TREE_CHAIN (stmt);
TREE_CHAIN (stmt) = NULL_TREE;
c_gimplify_stmt (stmt_p);
gimplify_stmt (&FOR_INIT_STMT (stmt));
append_to_statement_list (FOR_INIT_STMT (stmt), pre_p);
}
else
*stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
FOR_EXPR (stmt), 1);
*stmt_p = gimplify_c_loop (FOR_COND (stmt), FOR_BODY (stmt),
FOR_EXPR (stmt), 1);
return GS_ALL_DONE;
}
@ -767,7 +674,6 @@ gimplify_if_stmt (tree *stmt_p)
tree stmt, then_, else_;
stmt = *stmt_p;
restart:
then_ = THEN_CLAUSE (stmt);
else_ = ELSE_CLAUSE (stmt);
@ -780,17 +686,6 @@ gimplify_if_stmt (tree *stmt_p)
gimplify_condition (& TREE_OPERAND (stmt, 0));
*stmt_p = stmt;
/* Handle properly nested if-else chains via iteration instead of
mutual recursion between gimplify.c and c-simplify.c. */
annotate_with_locus (stmt, input_location);
if (TREE_CODE (else_) == IF_STMT && !TREE_CHAIN (else_))
{
stmt_p = &COND_EXPR_ELSE (stmt);
stmt = else_;
prep_stmt (stmt);
goto restart;
}
return GS_OK;
}
@ -960,130 +855,7 @@ c_gimplify_expr (tree *expr_p, tree *pre_p ATTRIBUTE_UNUSED,
case COMPOUND_LITERAL_EXPR:
return gimplify_compound_literal_expr (expr_p);
case STMT_EXPR:
return gimplify_stmt_expr (expr_p);
default:
return GS_UNHANDLED;
}
}
/* Returns the final EXPR_STMT which represents the return value of a
STMT_EXPR, or NULL_TREE if none. */
tree
stmt_expr_last_stmt (tree stmt_expr)
{
tree body = STMT_EXPR_STMT (stmt_expr);
tree last_stmt, substmt;
/* Splice the last expression out of the STMT chain. */
last_stmt = NULL_TREE;
for (substmt = COMPOUND_BODY (body); substmt;
substmt = TREE_CHAIN (substmt))
if (TREE_CODE (substmt) != SCOPE_STMT)
last_stmt = substmt;
if (last_stmt == NULL_TREE
|| TREE_CODE (last_stmt) != EXPR_STMT
|| (TREE_TYPE (last_stmt)
&& VOID_TYPE_P (TREE_TYPE (last_stmt))))
{
location_t loc;
if (last_stmt && EXPR_LOCUS (last_stmt))
loc = *EXPR_LOCUS (last_stmt);
else if (EXPR_LOCUS (stmt_expr))
loc = *EXPR_LOCUS (stmt_expr);
else
loc = input_location;
warning ("%Hstatement-expressions should end with a "
"non-void expression", &loc);
last_stmt = NULL_TREE;
}
#if defined ENABLE_CHECKING
if (last_stmt && !is_last_stmt_of_scope (last_stmt))
abort ();
#endif
return last_stmt;
}
/* Gimplify a STMT_EXPR. EXPR_P points to the expression to gimplify.
After gimplification, if the STMT_EXPR returns a value, EXPR_P will
point to a new temporary that holds that value; otherwise it will be
null.
PRE_P points to the list where side effects that must happen before
*EXPR_P should be stored. */
static enum gimplify_status
gimplify_stmt_expr (tree *expr_p)
{
tree body = STMT_EXPR_STMT (*expr_p);
if (VOID_TYPE_P (TREE_TYPE (*expr_p)))
{
*expr_p = body;
return c_gimplify_stmt (expr_p);
}
else
{
tree last_stmt = stmt_expr_last_stmt (*expr_p);
tree last_expr = NULL_TREE;
if (last_stmt)
{
last_expr = EXPR_STMT_EXPR (last_stmt);
if (stmts_are_full_exprs_p ())
last_expr = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (last_expr),
last_expr);
EXPR_STMT_EXPR (last_stmt) = NULL_TREE;
}
/* Genericize the block. */
c_gimplify_stmt (&body);
/* Now retrofit that last expression into the BIND_EXPR. */
if (last_expr)
{
tree *sub_p;
if (!STMT_EXPR_NO_SCOPE (*expr_p))
{
/* Our BIND_EXPR will always be hidden within
a STATEMENT_LIST. Discard that. */
body = expr_first (body);
sub_p = &BIND_EXPR_BODY (body);
/* Append the last expression to the end of the BIND_EXPR.
We'll now re-process this, and let voidify_wrapper_expr
do its job. */
append_to_statement_list_force (last_expr, sub_p);
TREE_TYPE (body) = TREE_TYPE (last_expr);
}
else
append_to_compound_expr (last_expr, &body);
}
*expr_p = body;
return GS_OK;
}
}
/* Code generation. */
/* Miscellaneous helpers. */
#if defined ENABLE_CHECKING
/* Return nonzero if STMT is the last statement of its scope. */
static int
is_last_stmt_of_scope (tree stmt)
{
return (TREE_CHAIN (stmt) == NULL_TREE
|| (TREE_CODE (TREE_CHAIN (stmt)) == SCOPE_STMT
&& SCOPE_END_P (TREE_CHAIN (stmt))));
}
#endif

View File

@ -112,9 +112,6 @@ enum c_language_kind c_language = clk_c;
#undef LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS
#define LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS \
c_disregard_inline_limits
#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P
#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
c_tree_chain_matters_p
#undef LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P
#define LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P \
anon_aggr_type_p

View File

@ -67,7 +67,7 @@ mflang_lookup_decl (const char* name)
void
mflang_flush_calls (tree enqueued_call_stmt_chain)
{
tree fnname, t1, t2, body, block, scope;
tree fnname, t1, t2, cs;
/* Short-circuit! */
if (enqueued_call_stmt_chain == NULL_TREE)
@ -84,17 +84,9 @@ mflang_flush_calls (tree enqueued_call_stmt_chain)
TREE_USED (current_function_decl) = 1;
mf_mark (current_function_decl);
body = c_begin_compound_stmt ();
push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
cs = c_begin_compound_stmt (true);
c_expand_expr_stmt (enqueued_call_stmt_chain);
add_stmt (c_end_compound_stmt (cs, true));
scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
block = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block;
RECHAIN_STMTS (body, COMPOUND_BODY (body));
finish_function ();
}

View File

@ -188,9 +188,7 @@ static void
build_cdtor (int method_type, tree cdtors)
{
tree fnname = get_file_function_name (method_type);
tree body;
tree scope;
tree block;
tree cs;
start_function (void_list_node,
build_nt (CALL_EXPR, fnname,
@ -199,20 +197,12 @@ build_cdtor (int method_type, tree cdtors)
NULL_TREE);
store_parm_decls ();
body = c_begin_compound_stmt ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
cs = c_begin_compound_stmt (true);
for (; cdtors; cdtors = TREE_CHAIN (cdtors))
add_stmt (build_stmt (EXPR_STMT,
build_function_call (TREE_VALUE (cdtors), 0)));
add_stmt (build_function_call (TREE_VALUE (cdtors), 0));
scope = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
block = make_node (BLOCK);
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope)) = block;
RECHAIN_STMTS (body, COMPOUND_BODY (body));
add_stmt (c_end_compound_stmt (cs, true));
finish_function ();
}

View File

@ -208,10 +208,10 @@ do { \
%type <ttype> maybe_attribute attributes attribute attribute_list attrib
%type <ttype> any_word
%type <ttype> compstmt compstmt_start compstmt_nostart compstmt_primary_start
%type <ttype> do_stmt_start pop_scope stmt label
%type <ttype> compstmt compstmt_start compstmt_primary_start
%type <ttype> do_stmt_start stmt label
%type <ttype> c99_block_start c99_block_end
%type <ttype> c99_block_start c99_block_lineno_labeled_stmt
%type <ttype> declarator
%type <ttype> notype_declarator after_type_declarator
%type <ttype> parm_declarator
@ -650,24 +650,12 @@ primary:
| '(' error ')'
{ $$ = error_mark_node; }
| compstmt_primary_start compstmt_nostart ')'
{ tree saved_last_tree;
if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions");
saved_last_tree = COMPOUND_BODY ($1);
RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
last_tree = saved_last_tree;
TREE_CHAIN (last_tree) = NULL_TREE;
if (!last_expr_type)
last_expr_type = void_type_node;
$$ = build1 (STMT_EXPR, last_expr_type, $1);
TREE_SIDE_EFFECTS ($$) = 1;
annotate_with_locus ($$, input_location);
{ if (pedantic)
pedwarn ("ISO C forbids braced-groups within expressions");
$$ = c_finish_stmt_expr ($1);
}
| compstmt_primary_start error ')'
{
last_tree = COMPOUND_BODY ($1);
TREE_CHAIN (last_tree) = NULL_TREE;
{ c_finish_stmt_expr ($1);
$$ = error_mark_node;
}
| primary '(' exprlist ')' %prec '.'
@ -2010,51 +1998,9 @@ lineno_stmt_decl_or_labels:
errstmt: error ';'
;
push_scope: /* empty */
{ push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
}
;
pop_scope: /* empty */
{
@@ifobjc
if (c_dialect_objc ())
objc_clear_super_receiver ();
@@end_ifobjc
$$ = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
}
;
/* Start and end blocks created for the new scopes of C99. */
c99_block_start: /* empty */
{ if (flag_isoc99)
{
$$ = c_begin_compound_stmt ();
push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
}
else
$$ = NULL_TREE;
}
;
/* Productions using c99_block_start and c99_block_end will need to do what's
in compstmt: RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); $$ = $2; where
$1 is the value of c99_block_start and $2 of c99_block_end. */
c99_block_end: /* empty */
{ if (flag_isoc99)
{
tree scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
$$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
= $$;
}
else
$$ = NULL_TREE; }
{ $$ = c_begin_compound_stmt (flag_isoc99); }
;
/* Read zero or more forward-declarations for labels
@ -2092,16 +2038,11 @@ compstmt_or_error:
;
compstmt_start: '{' { compstmt_count++;
$$ = c_begin_compound_stmt (); }
$$ = c_begin_compound_stmt (true); }
;
compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); }
| push_scope maybe_label_decls compstmt_contents_nonempty '}' pop_scope
{ $$ = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
= SCOPE_STMT_BLOCK (TREE_VALUE ($5))
= $$; }
| maybe_label_decls compstmt_contents_nonempty '}'
;
compstmt_contents_nonempty:
@ -2113,30 +2054,24 @@ compstmt_primary_start:
'(' '{'
{ if (current_function_decl == 0)
{
error ("braced-group within expression allowed only inside a function");
error ("braced-group within expression allowed "
"only inside a function");
YYERROR;
}
/* We must force a BLOCK for this level
so that, if it is not expanded later,
there is a way to turn off the entire subtree of blocks
that are contained in it. */
keep_next_level ();
compstmt_count++;
$$ = add_stmt (build_stmt (COMPOUND_STMT, last_tree));
last_expr_type = NULL_TREE;
$$ = c_begin_stmt_expr ();
}
;
compstmt: compstmt_start compstmt_nostart
{ RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
last_expr_type = NULL_TREE;
$$ = $1; }
{ add_stmt (c_end_compound_stmt ($1, true));
$$ = NULL_TREE; }
;
/* Value is number of statements counted as of the closeparen. */
simple_if:
if_prefix c99_block_lineno_labeled_stmt
{ c_finish_then (); }
{ c_finish_then ($2); }
/* Make sure c_expand_end_cond is run once
for each call to c_expand_start_cond.
Otherwise a crash is likely. */
@ -2179,7 +2114,7 @@ do_stmt_start:
DO_COND ($<ttype>$) = error_mark_node; }
c99_block_lineno_labeled_stmt WHILE
{ $$ = $<ttype>2;
RECHAIN_STMTS ($$, DO_BODY ($$));
DO_BODY ($$) = $3;
c_in_iteration_stmt--; }
;
@ -2200,14 +2135,24 @@ lineno_labeled_stmt:
/* Like lineno_labeled_stmt, but a block in C99. */
c99_block_lineno_labeled_stmt:
c99_block_start lineno_labeled_stmt c99_block_end
{ if (flag_isoc99)
RECHAIN_STMTS ($1, COMPOUND_BODY ($1)); }
c99_block_start lineno_labeled_stmt
{ $$ = c_end_compound_stmt ($1, flag_isoc99); }
;
lineno_stmt:
save_location stmt
{ if ($2)
{
/* Two cases cannot and do not have line numbers associated:
If stmt is degenerate, such as "2;", then stmt is an
INTEGER_CST, which cannot hold line numbers. But that's
ok because the statement will either be changed to a
MODIFY_EXPR during gimplification of the statement expr,
or discarded. If stmt was compound, but without new
variables, we will have skipped the creation of a BIND
and will have a bare STATEMENT_LIST. But that's ok
because (recursively) all of the component statments
should already have line numbers assigned. */
if ($2 && EXPR_P ($2))
{
SET_EXPR_LOCUS ($2, NULL);
annotate_with_locus ($2, $1);
@ -2230,7 +2175,7 @@ select_or_iter_stmt:
{ c_expand_start_else ();
$<itype>1 = stmt_count; }
c99_block_lineno_labeled_stmt
{ c_finish_else ();
{ c_finish_else ($4);
c_expand_end_cond ();
if (extra_warnings && stmt_count == $<itype>1)
warning ("empty body in an else-statement"); }
@ -2261,41 +2206,34 @@ select_or_iter_stmt:
$<ttype>$ = c_begin_while_stmt (); }
'(' expr ')'
{ c_in_iteration_stmt++;
$4 = lang_hooks.truthvalue_conversion ($4);
c_finish_while_stmt_cond
(lang_hooks.truthvalue_conversion ($4), $<ttype>2);
$<ttype>$ = add_stmt ($<ttype>2); }
c_finish_while_stmt_cond ($4, $<ttype>2); }
c99_block_lineno_labeled_stmt
{ c_in_iteration_stmt--;
RECHAIN_STMTS ($<ttype>6, WHILE_BODY ($<ttype>6)); }
c_finish_while_stmt ($7, $<ttype>2); }
| do_stmt_start
'(' expr ')' ';'
{ DO_COND ($1) = lang_hooks.truthvalue_conversion ($3); }
| do_stmt_start error
{ }
| FOR
{ $<ttype>$ = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
add_stmt ($<ttype>$); }
{ $<ttype>$ = c_begin_for_stmt (); }
'(' for_init_stmt
{ stmt_count++;
RECHAIN_STMTS ($<ttype>2, FOR_INIT_STMT ($<ttype>2)); }
c_finish_for_stmt_init ($<ttype>2); }
xexpr ';'
{ if ($6)
FOR_COND ($<ttype>2)
= lang_hooks.truthvalue_conversion ($6); }
{ c_finish_for_stmt_cond ($6, $<ttype>2); }
xexpr ')'
{ c_in_iteration_stmt++;
FOR_EXPR ($<ttype>2) = $9; }
c_finish_for_stmt_incr ($9, $<ttype>2); }
c99_block_lineno_labeled_stmt
{ RECHAIN_STMTS ($<ttype>2, FOR_BODY ($<ttype>2));
c_in_iteration_stmt--;}
{ c_finish_for_stmt ($12, $<ttype>2);
c_in_iteration_stmt--; }
| SWITCH '(' expr ')'
{ stmt_count++;
$<ttype>$ = c_start_case ($3);
c_in_case_stmt++; }
c99_block_lineno_labeled_stmt
{ c_finish_case ();
{ c_finish_case ($6);
c_in_case_stmt--; }
;
@ -2319,28 +2257,27 @@ stmt:
| expr ';'
{ stmt_count++;
$$ = c_expand_expr_stmt ($1); }
| c99_block_start select_or_iter_stmt c99_block_end
{ if (flag_isoc99)
RECHAIN_STMTS ($1, COMPOUND_BODY ($1));
| c99_block_start select_or_iter_stmt
{ add_stmt (c_end_compound_stmt ($1, flag_isoc99));
$$ = NULL_TREE; }
| BREAK ';'
{ stmt_count++;
if (!(c_in_iteration_stmt || c_in_case_stmt))
{
error ("break statement not within loop or switch");
$$ = NULL_TREE;
}
else
$$ = add_stmt (build_break_stmt ()); }
if (!(c_in_iteration_stmt || c_in_case_stmt))
{
error ("break statement not within loop or switch");
$$ = NULL_TREE;
}
else
$$ = add_stmt (build_break_stmt ()); }
| CONTINUE ';'
{ stmt_count++;
if (!c_in_iteration_stmt)
{
error ("continue statement not within a loop");
$$ = NULL_TREE;
}
else
$$ = add_stmt (build_continue_stmt ()); }
if (!c_in_iteration_stmt)
{
error ("continue statement not within a loop");
$$ = NULL_TREE;
}
else
$$ = add_stmt (build_continue_stmt ()); }
| RETURN ';'
{ stmt_count++;
$$ = c_expand_return (NULL_TREE); }

View File

@ -26,6 +26,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "real.h"
#include "c-pretty-print.h"
#include "c-tree.h"
#include "tree-iterator.h"
#include "diagnostic.h"
/* The pretty-printer code is primarily designed to closely follow
@ -1892,6 +1893,22 @@ pp_c_statement (c_pretty_printer *pp, tree stmt)
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;
/* labeled-statement:
identifier : statement
case constant-expression : statement
@ -1940,8 +1957,7 @@ pp_c_statement (c_pretty_printer *pp, tree stmt)
pp_newline_and_indent (pp, 0);
pp_c_left_brace (pp);
pp_newline_and_indent (pp, 3);
for (stmt = COMPOUND_BODY (stmt); stmt; stmt = TREE_CHAIN (stmt))
pp_statement (pp, stmt);
pp_statement (pp, COMPOUND_BODY (stmt));
pp_newline_and_indent (pp, -3);
pp_c_right_brace (pp);
pp_needs_newline (pp) = true;
@ -2103,27 +2119,6 @@ pp_c_statement (c_pretty_printer *pp, tree stmt)
}
break;
case SCOPE_STMT:
if (!SCOPE_NULLIFIED_P (stmt) && SCOPE_NO_CLEANUPS_P (stmt))
{
int i = 0;
if (pp_needs_newline (pp))
pp_newline_and_indent (pp, 0);
if (SCOPE_BEGIN_P (stmt))
{
pp_left_brace (pp);
i = 3;
}
else if (SCOPE_END_P (stmt))
{
pp_right_brace (pp);
i = -3;
}
pp_indentation (pp) += i;
pp_needs_newline (pp) = true;
}
break;
case DECL_STMT:
if (pp_needs_newline (pp))
pp_newline_and_indent (pp, 0);

View File

@ -43,20 +43,84 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "timevar.h"
#include "predict.h"
#include "tree-inline.h"
#include "tree-gimple.h"
#include "langhooks.h"
/* Create an empty statement tree rooted at T. */
void
begin_stmt_tree (tree *t)
tree
push_stmt_list (void)
{
/* We create a trivial EXPR_STMT so that last_tree is never NULL in
what follows. We remove the extraneous statement in
finish_stmt_tree. */
*t = build_nt (EXPR_STMT, void_zero_node);
last_tree = *t;
last_expr_type = NULL_TREE;
last_expr_filename = input_filename;
tree t;
t = alloc_stmt_list ();
TREE_CHAIN (t) = cur_stmt_list;
cur_stmt_list = t;
return t;
}
/* Similarly, except that T may have already been pushed/popped, and
thus may already contain statement(s). Arrage for new statements
to be appended. */
tree
re_push_stmt_list (tree t)
{
if (t)
{
if (TREE_CODE (t) != STATEMENT_LIST)
{
tree u = alloc_stmt_list ();
append_to_statement_list_force (t, &u);
t = u;
}
}
else
t = alloc_stmt_list ();
TREE_CHAIN (t) = cur_stmt_list;
cur_stmt_list = t;
return t;
}
/* Finish the statement tree rooted at T. */
tree
pop_stmt_list (tree t)
{
tree u = cur_stmt_list, chain;
/* Pop statement lists until we reach the target level. The extra
nestings will be due to outstanding cleanups. */
while (1)
{
chain = TREE_CHAIN (u);
TREE_CHAIN (u) = NULL_TREE;
if (t == u)
break;
u = chain;
}
cur_stmt_list = chain;
/* If the statement list is completely empty, just return it. This is
just as good small as build_empty_stmt, with the advantage that
statement lists are merged when they appended to one another. So
using the STATEMENT_LIST avoids pathological buildup of EMPTY_STMT_P
statements. */
if (TREE_SIDE_EFFECTS (t))
{
tree_stmt_iterator i = tsi_start (t);
/* If the statement list contained exactly one statement, then
extract it immediately. */
if (tsi_one_before_end_p (i))
{
u = tsi_stmt (i);
tsi_delink (&i);
free_stmt_list (t);
t = u;
}
}
return t;
}
/* T is a statement. Add it to the statement-tree. */
@ -64,16 +128,19 @@ begin_stmt_tree (tree *t)
tree
add_stmt (tree t)
{
if (!EXPR_LOCUS (t))
annotate_with_locus (t, input_location);
if (EXPR_P (t) || STATEMENT_CODE_P (TREE_CODE (t)))
{
if (!EXPR_LOCUS (t))
annotate_with_locus (t, input_location);
/* Add T to the statement-tree. */
TREE_CHAIN (last_tree) = t;
last_tree = t;
/* When we expand a statement-tree, we must know whether or not the
statements are full-expressions. We record that fact here. */
STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p ();
}
/* When we expand a statement-tree, we must know whether or not the
statements are full-expressions. We record that fact here. */
STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p ();
/* Add T to the statement-tree. Non-side-effect statements need to be
recorded during statement expressions. */
append_to_statement_list_force (t, &cur_stmt_list);
return t;
}
@ -91,59 +158,17 @@ add_decl_stmt (tree decl)
add_stmt (decl_stmt);
}
/* Add a scope-statement to the statement-tree. BEGIN_P indicates
whether this statements opens or closes a scope. PARTIAL_P is true
for a partial scope, i.e, the scope that begins after a label when
an object that needs a cleanup is created. If BEGIN_P is nonzero,
returns a new TREE_LIST representing the top of the SCOPE_STMT
stack. The TREE_PURPOSE is the new SCOPE_STMT. If BEGIN_P is
zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
and whose TREE_PURPOSE is the matching SCOPE_STMT with
SCOPE_BEGIN_P set. */
tree
add_scope_stmt (int begin_p, int partial_p)
{
tree *stack_ptr = current_scope_stmt_stack ();
tree ss;
tree top = *stack_ptr;
/* Build the statement. */
ss = build_stmt (SCOPE_STMT, NULL_TREE);
SCOPE_BEGIN_P (ss) = begin_p;
SCOPE_PARTIAL_P (ss) = partial_p;
/* Keep the scope stack up to date. */
if (begin_p)
{
top = tree_cons (ss, NULL_TREE, top);
*stack_ptr = top;
}
else
{
if (partial_p != SCOPE_PARTIAL_P (TREE_PURPOSE (top)))
abort ();
TREE_VALUE (top) = ss;
*stack_ptr = TREE_CHAIN (top);
}
/* Add the new statement to the statement-tree. */
add_stmt (ss);
return top;
}
/* Finish the statement tree rooted at T. */
/* 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
finish_stmt_tree (tree *t)
push_cleanup (tree decl, tree cleanup, bool eh_only)
{
tree stmt;
/* Remove the fake extra statement added in begin_stmt_tree. */
stmt = TREE_CHAIN (*t);
*t = stmt;
last_tree = NULL_TREE;
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

View File

@ -191,7 +191,7 @@ extern tree start_decl (tree, tree, int, tree);
extern tree start_struct (enum tree_code, tree);
extern void store_parm_decls (void);
extern tree xref_tag (enum tree_code, tree);
extern tree c_begin_compound_stmt (void);
extern int c_expand_decl (tree);
extern void c_static_assembler_name (tree);
extern tree make_pointer_declarator (tree, tree);
@ -249,11 +249,29 @@ extern tree build_compound_literal (tree, tree);
extern void pedwarn_c90 (const char *, ...) ATTRIBUTE_PRINTF_1;
extern void pedwarn_c99 (const char *, ...) ATTRIBUTE_PRINTF_1;
extern tree c_start_case (tree);
extern void c_finish_case (void);
extern void c_finish_case (tree);
extern tree build_asm_expr (tree, tree, tree, tree, bool);
extern tree build_asm_stmt (tree, tree);
extern tree c_convert_parm_for_inlining (tree, tree, tree, int);
extern int c_types_compatible_p (tree, tree);
extern tree c_begin_compound_stmt (bool);
extern tree c_end_compound_stmt (tree, bool);
extern void c_expand_start_cond (tree, int, tree);
extern void c_finish_then (tree);
extern void c_expand_start_else (void);
extern void c_finish_else (tree);
extern void c_expand_end_cond (void);
extern tree c_begin_if_stmt (void);
extern tree c_begin_while_stmt (void);
extern void c_finish_while_stmt_cond (tree, tree);
extern void c_finish_while_stmt (tree, tree);
extern tree c_begin_for_stmt (void);
extern void c_finish_for_stmt_init (tree);
extern void c_finish_for_stmt_cond (tree, tree);
extern void c_finish_for_stmt_incr (tree, tree);
extern void c_finish_for_stmt (tree, tree);
extern tree c_begin_stmt_expr (void);
extern tree c_finish_stmt_expr (tree);
extern tree build_offsetof (tree, tree);
/* Set to 0 at beginning of a function definition, set to 1 if

View File

@ -45,6 +45,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "intl.h"
#include "ggc.h"
#include "target.h"
#include "tree-iterator.h"
/* Nonzero if we've already printed a "missing braces around initializer"
message within this initializer. */
@ -2206,16 +2208,7 @@ int
c_tree_expr_nonnegative_p (tree t)
{
if (TREE_CODE (t) == STMT_EXPR)
{
t = COMPOUND_BODY (STMT_EXPR_STMT (t));
/* Find the last statement in the chain, ignoring the final
* scope statement */
while (TREE_CHAIN (t) != NULL_TREE
&& TREE_CODE (TREE_CHAIN (t)) != SCOPE_STMT)
t = TREE_CHAIN (t);
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
}
t = expr_last (COMPOUND_BODY (STMT_EXPR_STMT (t)));
return tree_expr_nonnegative_p (t);
}
@ -6435,19 +6428,11 @@ do_case (tree low_value, tree high_value)
if (switch_stack)
{
bool switch_was_empty_p = (SWITCH_BODY (switch_stack->switch_stmt) == NULL_TREE);
label = c_add_case_label (switch_stack->cases,
SWITCH_COND (switch_stack->switch_stmt),
low_value, high_value);
if (label == error_mark_node)
label = NULL_TREE;
else if (switch_was_empty_p)
{
/* Attach the first case label to the SWITCH_BODY. */
SWITCH_BODY (switch_stack->switch_stmt) = TREE_CHAIN (switch_stack->switch_stmt);
TREE_CHAIN (switch_stack->switch_stmt) = NULL_TREE;
}
}
else if (low_value)
error ("case label not within a switch statement");
@ -6460,22 +6445,325 @@ do_case (tree low_value, tree high_value)
/* Finish the switch statement. */
void
c_finish_case (void)
c_finish_case (tree body)
{
struct c_switch *cs = switch_stack;
SWITCH_BODY (cs->switch_stmt) = body;
/* Emit warnings as needed. */
c_do_switch_warnings (cs->cases, cs->switch_stmt);
/* Rechain the next statements to the SWITCH_STMT. */
last_tree = cs->switch_stmt;
/* Pop the stack. */
switch_stack = switch_stack->next;
splay_tree_delete (cs->cases);
free (cs);
}
/* Keep a stack of if statements. We record the number of compound
statements seen up to the if keyword, as well as the line number
and file of the if. If a potentially ambiguous else is seen, that
fact is recorded; the warning is issued when we can be sure that
the enclosing if statement does not have an else branch. */
typedef struct
{
int compstmt_count;
location_t locus;
int needs_warning;
tree if_stmt;
} if_elt;
static if_elt *if_stack;
/* Amount of space in the if statement stack. */
static int if_stack_space = 0;
/* Stack pointer. */
static int if_stack_pointer = 0;
/* Begin an if-statement. Returns a newly created IF_STMT if
appropriate. */
tree
c_begin_if_stmt (void)
{
tree r;
r = add_stmt (build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE));
return r;
}
/* Record the start of an if-then, and record the start of it
for ambiguous else detection.
COND is the condition for the if-then statement.
IF_STMT is the statement node that has already been created for
this if-then statement. It is created before parsing the
condition to keep line number information accurate. */
void
c_expand_start_cond (tree cond, int compstmt_count, tree if_stmt)
{
/* Make sure there is enough space on the stack. */
if (if_stack_space == 0)
{
if_stack_space = 10;
if_stack = xmalloc (10 * sizeof (if_elt));
}
else if (if_stack_space == if_stack_pointer)
{
if_stack_space += 10;
if_stack = xrealloc (if_stack, if_stack_space * sizeof (if_elt));
}
IF_COND (if_stmt) = cond;
/* Record this if statement. */
if_stack[if_stack_pointer].compstmt_count = compstmt_count;
if_stack[if_stack_pointer].locus = input_location;
if_stack[if_stack_pointer].needs_warning = 0;
if_stack[if_stack_pointer].if_stmt = if_stmt;
if_stack_pointer++;
}
/* Called after the then-clause for an if-statement is processed. */
void
c_finish_then (tree then_stmt)
{
tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
THEN_CLAUSE (if_stmt) = then_stmt;
}
/* Record the end of an if-then. Optionally warn if a nested
if statement had an ambiguous else clause. */
void
c_expand_end_cond (void)
{
if_stack_pointer--;
if (if_stack[if_stack_pointer].needs_warning)
warning ("%Hsuggest explicit braces to avoid ambiguous `else'",
&if_stack[if_stack_pointer].locus);
}
/* Called between the then-clause and the else-clause
of an if-then-else. */
void
c_expand_start_else (void)
{
/* An ambiguous else warning must be generated for the enclosing if
statement, unless we see an else branch for that one, too. */
if (warn_parentheses
&& if_stack_pointer > 1
&& (if_stack[if_stack_pointer - 1].compstmt_count
== if_stack[if_stack_pointer - 2].compstmt_count))
if_stack[if_stack_pointer - 2].needs_warning = 1;
/* Even if a nested if statement had an else branch, it can't be
ambiguous if this one also has an else. So don't warn in that
case. Also don't warn for any if statements nested in this else. */
if_stack[if_stack_pointer - 1].needs_warning = 0;
if_stack[if_stack_pointer - 1].compstmt_count--;
}
/* Called after the else-clause for an if-statement is processed. */
void
c_finish_else (tree else_stmt)
{
tree if_stmt = if_stack[if_stack_pointer - 1].if_stmt;
ELSE_CLAUSE (if_stmt) = else_stmt;
}
/* Begin a while statement. Returns a newly created WHILE_STMT if
appropriate. */
tree
c_begin_while_stmt (void)
{
tree r;
r = add_stmt (build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE));
return r;
}
void
c_finish_while_stmt_cond (tree cond, tree while_stmt)
{
WHILE_COND (while_stmt) = (*lang_hooks.truthvalue_conversion) (cond);
}
void
c_finish_while_stmt (tree body, tree while_stmt)
{
WHILE_BODY (while_stmt) = body;
}
/* Create a for statement. */
tree
c_begin_for_stmt (void)
{
tree r;
r = add_stmt (build_stmt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE));
FOR_INIT_STMT (r) = push_stmt_list ();
return r;
}
void
c_finish_for_stmt_init (tree for_stmt)
{
FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt));
}
void
c_finish_for_stmt_cond (tree cond, tree for_stmt)
{
if (cond)
FOR_COND (for_stmt) = lang_hooks.truthvalue_conversion (cond);
}
void
c_finish_for_stmt_incr (tree expr, tree for_stmt)
{
FOR_EXPR (for_stmt) = expr;
}
void
c_finish_for_stmt (tree body, tree for_stmt)
{
FOR_BODY (for_stmt) = body;
}
/* Create a statement expression. */
tree
c_begin_stmt_expr (void)
{
tree ret;
/* We must force a BLOCK for this level so that, if it is not expanded
later, there is a way to turn off the entire subtree of blocks that
are contained in it. */
keep_next_level ();
ret = c_begin_compound_stmt (true);
/* Mark the current statement list as belonging to a statement list. */
STATEMENT_LIST_STMT_EXPR (ret) = 1;
return ret;
}
tree
c_finish_stmt_expr (tree body)
{
tree ret, last, type;
tree *last_p;
body = c_end_compound_stmt (body, true);
/* Locate the last statement in BODY. */
last = body, last_p = &body;
if (TREE_CODE (last) == BIND_EXPR)
{
last_p = &BIND_EXPR_BODY (last);
last = BIND_EXPR_BODY (last);
}
if (TREE_CODE (last) == STATEMENT_LIST)
{
tree_stmt_iterator i = tsi_last (last);
if (tsi_end_p (i))
{
type = void_type_node;
/* ??? Warn */
goto no_expr;
}
else
{
last_p = tsi_stmt_ptr (i);
last = *last_p;
}
}
/* If the last statement is an EXPR_STMT, then unwrap it. Otherwise
voidify_wrapper_expr will stuff it inside a MODIFY_EXPR and we'll
fail gimplification. */
/* ??? Should we go ahead and perform voidify_wrapper_expr here?
We've got about all the information we need here. All we'd have
to do even for proper type safety is to create, in effect,
( ({ ...; tmp = last; }), tmp )
I.e. a COMPOUND_EXPR with the rhs being the compiler temporary.
Not going to try this now, since it's not clear what should
happen (wrt bindings) with new temporaries at this stage. It's
easier once we begin gimplification. */
if (TREE_CODE (last) == EXPR_STMT)
*last_p = last = EXPR_STMT_EXPR (last);
/* Extract the type of said expression. */
type = TREE_TYPE (last);
if (!type)
type = void_type_node;
no_expr:
/* If what's left is compound, make sure we've got a BIND_EXPR, and
that it has the proper type. */
ret = body;
if (TREE_CODE (ret) == STATEMENT_LIST)
ret = build (BIND_EXPR, type, NULL, ret, NULL);
else if (TREE_CODE (ret) == BIND_EXPR)
TREE_TYPE (ret) = type;
return ret;
}
/* Begin and end compound statements. This is as simple as pushing
and popping new statement lists from the tree. */
tree
c_begin_compound_stmt (bool do_scope)
{
tree stmt = push_stmt_list ();
if (do_scope)
{
push_scope ();
clear_last_expr ();
}
return stmt;
}
tree
c_end_compound_stmt (tree stmt, bool do_scope)
{
tree block = NULL;
if (do_scope)
{
if (c_dialect_objc ())
objc_clear_super_receiver ();
block = pop_scope ();
}
stmt = pop_stmt_list (stmt);
stmt = c_build_bind_expr (block, stmt);
/* If this compound statement is nested immediately inside a statement
expression, then force a BIND_EXPR to be created. Otherwise we'll
do the wrong thing for ({ { 1; } }) or ({ 1; { } }). In particular,
STATEMENT_LISTs merge, and thus we can lose track of what statement
was really last. */
if (cur_stmt_list
&& STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
&& TREE_CODE (stmt) != BIND_EXPR)
{
stmt = build (BIND_EXPR, void_type_node, NULL, stmt, NULL);
TREE_SIDE_EFFECTS (stmt) = 1;
}
return stmt;
}
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
This function differs from `build' in several ways:

View File

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

View File

@ -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.
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);
The solution is to pass back a cleanup expression
which the caller is responsible for attaching to
the statement tree. */
}
else
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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))
{
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);
}
/* Otherwise, we simply parse the statement directly. */
else
/* 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
{
/* 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, "`}'");
}
}
/* 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);
}

View File

@ -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)
{
tree stmt, tmp;
tsubst_flags_t stmt_expr
= complain & (tf_stmt_expr_cmpd | tf_stmt_expr_body);
/* 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;
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)
if (ELSE_CLAUSE (t))
{
tsubst_expr (tmp, args, complain, in_decl);
finish_then_clause (stmt);
}
if (tmp = ELSE_CLAUSE (t), tmp)
{
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

View File

@ -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 (!processing_template_decl)
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
begin_scope (sk, NULL);
/* 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)
{
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;
tree r;
r = build_stmt (COMPOUND_STMT, NULL_TREE);
if (flags & BCS_NO_SCOPE)
{
r = push_stmt_list ();
STATEMENT_LIST_NO_SCOPE (r) = 1;
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;
last_expr_type = NULL_TREE;
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 ();
stmt = do_poplevel (stmt);
RECHAIN_STMTS (compound_stmt, COMPOUND_BODY (compound_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;
}
else
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;
t = *result_stmt_p;
if (t == result_stmt)
break;
/* 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);
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 ();
}
}
type = TREE_TYPE (EXPR_STMT_EXPR (result_stmt));
}
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;
}

View File

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

View File

@ -9015,7 +9015,7 @@ tree_expr_nonnegative_p (tree t)
case MODIFY_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
case BIND_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 1));
return tree_expr_nonnegative_p (expr_last (TREE_OPERAND (t, 1)));
case SAVE_EXPR:
return tree_expr_nonnegative_p (TREE_OPERAND (t, 0));
case NON_LVALUE_EXPR:

View File

@ -754,23 +754,23 @@ gimple_build_eh_filter (tree body, tree allowed, tree failure)
WRAPPER was already void. */
tree
voidify_wrapper_expr (tree wrapper)
voidify_wrapper_expr (tree wrapper, tree temp)
{
if (!VOID_TYPE_P (TREE_TYPE (wrapper)))
{
tree *p;
tree temp;
tree *p, sub = wrapper;
restart:
/* Set p to point to the body of the wrapper. */
switch (TREE_CODE (wrapper))
switch (TREE_CODE (sub))
{
case BIND_EXPR:
/* For a BIND_EXPR, the body is operand 1. */
p = &BIND_EXPR_BODY (wrapper);
p = &BIND_EXPR_BODY (sub);
break;
default:
p = &TREE_OPERAND (wrapper, 0);
p = &TREE_OPERAND (sub, 0);
break;
}
@ -789,15 +789,22 @@ voidify_wrapper_expr (tree wrapper)
}
}
if (p && TREE_CODE (*p) == INIT_EXPR)
if (p == NULL || IS_EMPTY_STMT (*p))
;
/* Look through exception handling. */
else if (TREE_CODE (*p) == TRY_FINALLY_EXPR
|| TREE_CODE (*p) == TRY_CATCH_EXPR)
{
/* The C++ frontend already did this for us. */;
temp = TREE_OPERAND (*p, 0);
sub = *p;
goto restart;
}
else if (p && TREE_CODE (*p) == INDIRECT_REF)
/* The C++ frontend already did this for us. */
else if (TREE_CODE (*p) == INIT_EXPR)
temp = TREE_OPERAND (*p, 0);
/* If we're returning a dereference, move the dereference
outside the wrapper. */
else if (TREE_CODE (*p) == INDIRECT_REF)
{
/* If we're returning a dereference, move the dereference outside
the wrapper. */
tree ptr = TREE_OPERAND (*p, 0);
temp = create_tmp_var (TREE_TYPE (ptr), "retval");
*p = build (MODIFY_EXPR, TREE_TYPE (ptr), temp, ptr);
@ -808,12 +815,10 @@ voidify_wrapper_expr (tree wrapper)
}
else
{
temp = create_tmp_var (TREE_TYPE (wrapper), "retval");
if (p && !IS_EMPTY_STMT (*p))
{
*p = build (MODIFY_EXPR, TREE_TYPE (temp), temp, *p);
TREE_SIDE_EFFECTS (wrapper) = 1;
}
if (!temp)
temp = create_tmp_var (TREE_TYPE (wrapper), "retval");
*p = build (MODIFY_EXPR, TREE_TYPE (temp), temp, *p);
TREE_SIDE_EFFECTS (wrapper) = 1;
}
TREE_TYPE (wrapper) = void_type_node;
@ -845,13 +850,14 @@ build_stack_save_restore (tree *save, tree *restore)
/* Gimplify a BIND_EXPR. Just voidify and recurse. */
static enum gimplify_status
gimplify_bind_expr (tree *expr_p, tree *pre_p)
gimplify_bind_expr (tree *expr_p, tree temp, tree *pre_p)
{
tree bind_expr = *expr_p;
tree temp = voidify_wrapper_expr (bind_expr);
bool old_save_stack = gimplify_ctxp->save_stack;
tree t;
temp = voidify_wrapper_expr (bind_expr, temp);
/* Mark variables seen in this bind expr. */
for (t = BIND_EXPR_VARS (bind_expr); t ; t = TREE_CHAIN (t))
t->decl.seen_in_bind_expr = 1;
@ -2872,7 +2878,7 @@ gimplify_cleanup_point_expr (tree *expr_p, tree *pre_p)
tree_stmt_iterator iter;
tree body;
tree temp = voidify_wrapper_expr (*expr_p);
tree temp = voidify_wrapper_expr (*expr_p, NULL);
/* We only care about the number of conditions between the innermost
CLEANUP_POINT_EXPR and the cleanup. So save and reset the count. */
@ -3006,12 +3012,17 @@ gimplify_target_expr (tree *expr_p, tree *pre_p, tree *post_p)
temps list. */
gimple_add_tmp_var (temp);
/* Build up the initialization and add it to pre_p. */
init = build (MODIFY_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
if (ret == GS_ERROR)
return GS_ERROR;
/* Build up the initialization and add it to pre_p. Special handling
for BIND_EXPR can result in fewer temporaries created. */
if (TREE_CODE (init) == BIND_EXPR)
gimplify_bind_expr (&init, temp, pre_p);
if (init != temp)
{
init = build (MODIFY_EXPR, void_type_node, temp, init);
ret = gimplify_expr (&init, pre_p, post_p, is_gimple_stmt, fb_none);
if (ret == GS_ERROR)
return GS_ERROR;
}
append_to_statement_list (init, pre_p);
/* If needed, push the cleanup for the temp. */
@ -3286,7 +3297,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
break;
case BIND_EXPR:
ret = gimplify_bind_expr (expr_p, pre_p);
ret = gimplify_bind_expr (expr_p, NULL, pre_p);
break;
case LOOP_EXPR:
@ -3530,7 +3541,7 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p,
/* If we are gimplifying at the statement level, we're done. Tack
everything together and replace the original statement with the
gimplified form. */
if (is_statement)
if (fallback == fb_none || is_statement)
{
if (internal_pre || internal_post)
{

View File

@ -78,7 +78,6 @@ extern tree lhd_tree_inlining_walk_subtrees (tree *, int *, walk_tree_fn,
extern int lhd_tree_inlining_cannot_inline_tree_fn (tree *);
extern int lhd_tree_inlining_disregard_inline_limits (tree);
extern tree lhd_tree_inlining_add_pending_fn_decls (void *, tree);
extern int lhd_tree_inlining_tree_chain_matters_p (tree);
extern int lhd_tree_inlining_auto_var_in_fn_p (tree, tree);
extern tree lhd_tree_inlining_copy_res_decl_for_inlining (tree, tree, tree,
void *, int *, tree);
@ -151,8 +150,6 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
lhd_tree_inlining_disregard_inline_limits
#define LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS \
lhd_tree_inlining_add_pending_fn_decls
#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
lhd_tree_inlining_tree_chain_matters_p
#define LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P \
lhd_tree_inlining_auto_var_in_fn_p
#define LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING \
@ -175,7 +172,6 @@ extern int lhd_gimplify_expr (tree *, tree *, tree *);
LANG_HOOKS_TREE_INLINING_CANNOT_INLINE_TREE_FN, \
LANG_HOOKS_TREE_INLINING_DISREGARD_INLINE_LIMITS, \
LANG_HOOKS_TREE_INLINING_ADD_PENDING_FN_DECLS, \
LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P, \
LANG_HOOKS_TREE_INLINING_AUTO_VAR_IN_FN_P, \
LANG_HOOKS_TREE_INLINING_COPY_RES_DECL_FOR_INLINING, \
LANG_HOOKS_TREE_INLINING_ANON_AGGR_TYPE_P, \

View File

@ -365,16 +365,6 @@ lhd_tree_inlining_add_pending_fn_decls (void *vafnp ATTRIBUTE_UNUSED, tree pfn)
return pfn;
}
/* lang_hooks.tree_inlining.tree_chain_matters_p indicates whether the
TREE_CHAIN of a language-specific tree node is relevant, i.e.,
whether it should be walked, copied and preserved across copies. */
int
lhd_tree_inlining_tree_chain_matters_p (tree t ATTRIBUTE_UNUSED)
{
return 0;
}
/* lang_hooks.tree_inlining.auto_var_in_fn_p is called to determine
whether VT is an automatic variable defined in function FT. */

View File

@ -39,7 +39,6 @@ struct lang_hooks_for_tree_inlining
int (*cannot_inline_tree_fn) (tree *);
int (*disregard_inline_limits) (tree);
tree (*add_pending_fn_decls) (void *, tree);
int (*tree_chain_matters_p) (tree);
int (*auto_var_in_fn_p) (tree, tree);
tree (*copy_res_decl_for_inlining) (tree, tree, tree,
void *, int *, tree);

View File

@ -1875,7 +1875,7 @@ build_module_descriptor (void)
{
tree parms, execclass_decl, decelerator, void_list_node_1;
tree init_function_name, init_function_decl;
tree init_function_name, init_function_decl, compound;
/* Declare void __objc_execClass (void *); */
@ -1903,6 +1903,7 @@ build_module_descriptor (void)
NULL_TREE),
NULL_TREE);
store_parm_decls ();
compound = c_begin_compound_stmt (true);
init_function_decl = current_function_decl;
TREE_PUBLIC (init_function_decl) = ! targetm.have_ctors_dtors;
@ -1917,6 +1918,7 @@ build_module_descriptor (void)
decelerator = build_function_call (execclass_decl, parms);
c_expand_expr_stmt (decelerator);
add_stmt (c_end_compound_stmt (compound, true));
finish_function ();
@ -2687,10 +2689,7 @@ objc_enter_block (void)
#ifdef OBJCPLUS
block = begin_compound_stmt (0);
#else
block = c_begin_compound_stmt ();
push_scope ();
clear_last_expr ();
add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
block = c_begin_compound_stmt (1);
#endif
objc_exception_block_stack = tree_cons (NULL_TREE, block,
@ -2704,24 +2703,14 @@ static tree
objc_exit_block (void)
{
tree block = TREE_VALUE (objc_exception_block_stack);
#ifndef OBJCPLUS
tree scope_stmt, inner;
#endif
objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack);
objc_clear_super_receiver ();
#ifdef OBJCPLUS
finish_compound_stmt (0, block);
finish_compound_stmt (block);
#else
scope_stmt = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
inner = pop_scope ();
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmt))
= SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmt))
= inner;
RECHAIN_STMTS (block, COMPOUND_BODY (block));
block = c_end_compound_stmt (block, 1);
#endif
last_expr_type = NULL_TREE;
objc_exception_block_stack = TREE_CHAIN (objc_exception_block_stack);
blk_nesting_count--;
return block;
@ -2804,6 +2793,15 @@ objc_build_try_enter_fragment (void)
c_expand_expr_stmt (build_function_call
(objc_exception_try_enter_decl, func_params));
#ifdef OBJCPLUS
/* Um, C and C++ have very different statement construction functions.
Partly because different scoping rules are in effect, but partly
because of how their parsers are constructed. I highly recommend
simply constructing the statements by hand here. You don't need
any of the ancilliary tracking necessary for user parsing bits anyway. */
#error
#endif
if_stmt = c_begin_if_stmt ();
if_nesting_count++;
/* If <setjmp.h> has been included, the _setjmp prototype has
@ -2865,8 +2863,7 @@ objc_build_extract_fragment (void)
_rethrowException = objc_exception_extract(&_stackExceptionData);
} */
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_start_else ();
objc_enter_block ();
@ -2874,8 +2871,7 @@ objc_build_extract_fragment (void)
(TREE_VALUE (objc_rethrow_exception),
NOP_EXPR,
objc_build_extract_expr ()));
objc_exit_block ();
c_finish_else ();
c_finish_else (objc_exit_block ());
c_expand_end_cond ();
if_nesting_count--;
}
@ -2934,8 +2930,7 @@ objc_build_try_epilogue (int also_catch_prologue)
tree if_stmt;
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_start_else ();
objc_enter_block ();
@ -3017,8 +3012,7 @@ objc_build_catch_stmt (tree catch_expr)
objc_catch_type = tree_cons (NULL_TREE, var_type, objc_catch_type);
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_start_else ();
catch_count_stack->val++;
@ -3061,8 +3055,7 @@ objc_build_catch_epilogue (void)
} // end TRY-CATCH scope
*/
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_start_else ();
objc_enter_block ();
@ -3075,7 +3068,8 @@ objc_build_catch_epilogue (void)
objc_exit_block ();
while (catch_count_stack->val--)
{
c_finish_else (); /* close off all the nested ifs ! */
/* FIXME. Need to have the block of each else that was opened. */
c_finish_else ((abort (), NULL)); /* close off all the nested ifs ! */
c_expand_end_cond ();
if_nesting_count--;
}
@ -3084,8 +3078,7 @@ objc_build_catch_epilogue (void)
objc_build_extract_fragment ();
objc_exit_block ();
c_finish_else ();
c_finish_else (objc_exit_block ());
c_expand_end_cond ();
if_nesting_count--;
objc_exit_block ();
@ -3116,8 +3109,7 @@ objc_build_finally_prologue (void)
0, if_stmt);
objc_enter_block ();
objc_build_try_exit_fragment ();
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_end_cond ();
if_nesting_count--;
@ -3141,8 +3133,7 @@ objc_build_finally_epilogue (void)
0, if_stmt);
objc_enter_block ();
objc_build_throw_stmt (TREE_VALUE (objc_rethrow_exception));
objc_exit_block ();
c_finish_then ();
c_finish_then (objc_exit_block ());
c_expand_end_cond ();
if_nesting_count--;

View File

@ -112,9 +112,6 @@ enum c_language_kind c_language = clk_objc;
#undef LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING
#define LANG_HOOKS_TREE_INLINING_CONVERT_PARM_FOR_INLINING \
c_convert_parm_for_inlining
#undef LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P
#define LANG_HOOKS_TREE_INLINING_TREE_CHAIN_MATTERS_P \
c_tree_chain_matters_p
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION c_expand_body

View File

@ -69,6 +69,11 @@ objc_message_selector (void)
return 0;
}
void
objc_clear_super_receiver (void)
{
}
int
objc_is_public (tree expr ATTRIBUTE_UNUSED, tree identifier ATTRIBUTE_UNUSED)
{

View File

@ -1,3 +1,8 @@
2004-06-15 Richard Henderson <rth@redhat.com>
* g++.dg/ext/stmtexpr1.C: XFAIL.
* gcc.dg/20030612-1.c: XFAIL.
2004-06-15 Eric Christopher <echristo@redhat.com>
* g++.dg/charset/asm5.c: New.

View File

@ -1,4 +1,4 @@
// { dg-do run }
// { dg-do run { xfail *-*-* } }
// { dg-options "" }
// Copyright (C) 2003 Free Software Foundation, Inc.

View File

@ -8,7 +8,7 @@ void foo()
long x = 3;
(void)({
A = B + x + ((1) - 1);
return; /* { dg-warning "statement-expressions should end with a non-void expression" } */
return; /* { dg-warning "statement-expressions should end with a non-void expression" "" { xfail *-*-* } } */
});
}

View File

@ -80,8 +80,6 @@ tree get_call_expr_in (tree t);
void recalculate_side_effects (tree);
void append_to_statement_list (tree, tree *);
void append_to_statement_list_force (tree, tree *);
void append_to_compound_expr (tree, tree *);
/* FIXME we should deduce this from the predicate. */
@ -116,7 +114,7 @@ tree gimple_current_bind_expr (void);
void gimple_push_bind_expr (tree);
void gimple_pop_bind_expr (void);
void unshare_all_trees (tree);
tree voidify_wrapper_expr (tree);
tree voidify_wrapper_expr (tree, tree);
tree gimple_build_eh_filter (tree, tree, tree);
tree build_and_jump (tree *);
tree alloc_stmt_list (void);

View File

@ -1657,7 +1657,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
restoring of current_function_decl. */
save_decl = current_function_decl;
current_function_decl = id->node->decl;
inline_result = voidify_wrapper_expr (expr);
inline_result = voidify_wrapper_expr (expr, NULL);
current_function_decl = save_decl;
/* If the inlined function returns a result that we care about,
@ -1906,7 +1906,7 @@ clone_body (tree clone, tree fn, void *arg_map)
id.cloning_p = true;
/* Actually copy the body. */
TREE_CHAIN (DECL_SAVED_TREE (clone)) = copy_body (&id);
append_to_statement_list_force (copy_body (&id), &DECL_SAVED_TREE (clone));
}
/* Save duplicate of body in FN. MAP is used to pass around splay tree
@ -2006,8 +2006,7 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
interesting below this point in the tree. */
if (!walk_subtrees)
{
if (code == TREE_LIST
|| lang_hooks.tree_inlining.tree_chain_matters_p (*tp))
if (code == TREE_LIST)
/* But we still need to check our siblings. */
WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
else
@ -2052,10 +2051,6 @@ walk_tree (tree *tp, walk_tree_fn func, void *data, void *htab_)
WALK_SUBTREE (TREE_OPERAND (*tp, len - 1));
}
#endif
if (lang_hooks.tree_inlining.tree_chain_matters_p (*tp))
/* Check our siblings. */
WALK_SUBTREE_TAIL (TREE_CHAIN (*tp));
}
else if (TREE_CODE_CLASS (code) == 'd')
{
@ -2226,8 +2221,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
|| TREE_CODE_CLASS (code) == 'c'
|| code == TREE_LIST
|| code == TREE_VEC
|| code == TYPE_DECL
|| lang_hooks.tree_inlining.tree_chain_matters_p (*tp))
|| code == TYPE_DECL)
{
/* Because the chain gets clobbered when we make a copy, we save it
here. */
@ -2245,8 +2239,7 @@ copy_tree_r (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
/* Now, restore the chain, if appropriate. That will cause
walk_tree to walk into the chain as well. */
if (code == PARM_DECL || code == TREE_LIST
|| lang_hooks.tree_inlining.tree_chain_matters_p (*tp))
if (code == PARM_DECL || code == TREE_LIST)
TREE_CHAIN (*tp) = chain;
/* For now, we don't update BLOCKs when we make copies. So, we

View File

@ -40,14 +40,12 @@ alloc_stmt_list (void)
if (list)
{
stmt_list_cache = TREE_CHAIN (list);
TREE_CHAIN (list) = NULL;
TREE_SIDE_EFFECTS (list) = 0;
memset (list, 0, sizeof(struct tree_common));
TREE_SET_CODE (list, STATEMENT_LIST);
}
else
{
list = make_node (STATEMENT_LIST);
TREE_TYPE (list) = void_type_node;
}
list = make_node (STATEMENT_LIST);
TREE_TYPE (list) = void_type_node;
return list;
}
@ -73,8 +71,6 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
if (t == i->container)
abort ();
TREE_SIDE_EFFECTS (i->container) = 1;
if (TREE_CODE (t) == STATEMENT_LIST)
{
head = STATEMENT_LIST_HEAD (t);
@ -101,6 +97,8 @@ tsi_link_before (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
tail = head;
}
TREE_SIDE_EFFECTS (i->container) = 1;
cur = i->ptr;
/* Link it into the list. */
@ -151,8 +149,6 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
if (t == i->container)
abort ();
TREE_SIDE_EFFECTS (i->container) = 1;
if (TREE_CODE (t) == STATEMENT_LIST)
{
head = STATEMENT_LIST_HEAD (t);
@ -179,6 +175,8 @@ tsi_link_after (tree_stmt_iterator *i, tree t, enum tsi_iterator_update mode)
tail = head;
}
TREE_SIDE_EFFECTS (i->container) = 1;
cur = i->ptr;
/* Link it into the list. */

View File

@ -117,4 +117,7 @@ void tsi_delink (tree_stmt_iterator *);
tree tsi_split_statement_list_after (const tree_stmt_iterator *);
tree tsi_split_statement_list_before (tree_stmt_iterator *);
void append_to_statement_list (tree, tree *);
void append_to_statement_list_force (tree, tree *);
#endif /* GCC_TREE_ITERATOR_H */

View File

@ -741,10 +741,12 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case TARGET_EXPR:
dump_generic_node (buffer, TYPE_NAME (TREE_TYPE (node)), spc, flags, false);
pp_character (buffer, '(');
pp_string (buffer, "TARGET_EXPR <");
dump_generic_node (buffer, TARGET_EXPR_SLOT (node), spc, flags, false);
pp_character (buffer, ',');
pp_space (buffer);
dump_generic_node (buffer, TARGET_EXPR_INITIAL (node), spc, flags, false);
pp_character (buffer, ')');
pp_character (buffer, '>');
break;
case COND_EXPR: