Commit 62409b39 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (FN_TRY_BLOCK_P): New macro.

	* cp-tree.h (FN_TRY_BLOCK_P): New macro.
	* init.c (perform_member_init): Remove obstack machinations.
	(expand_cleanup_for_base): Likewise.
	(finish_init_stmts): Mark the statement-expression as used.
	* method.c (emit_thunk): Use tree-generating functions, not
	RTL.
	(do_build_copy_constructor): Likewise.
	(do_build_assign_ref): Likewise.
	(synthesize_method): Likewise.  Keep track of line numbers.
	* pt.c (tsubst_expr): Handle various kinds of try blocks.
	* semantics.c (expand_stmts): Remove.
	(begin_function_try_block): Set FN_TRY_BLOCK_P.
	(finish_function_try_block): Be careful rechaining
	function try blocks.
	(expand_stmt): Loop through all the statements at a given level.
	(exapnd_body): Be careful with line-numbers here too.  Prepare for
	being called directly from the parser.

From-SVN: r29263
parent ca5b5533
1999-09-10 Mark Mitchell <mark@codesourcery.com> 1999-09-10 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (FN_TRY_BLOCK_P): New macro.
* init.c (perform_member_init): Remove obstack machinations.
(expand_cleanup_for_base): Likewise.
(finish_init_stmts): Mark the statement-expression as used.
* method.c (emit_thunk): Use tree-generating functions, not
RTL.
(do_build_copy_constructor): Likewise.
(do_build_assign_ref): Likewise.
(synthesize_method): Likewise. Keep track of line numbers.
* pt.c (tsubst_expr): Handle various kinds of try blocks.
* semantics.c (expand_stmts): Remove.
(begin_function_try_block): Set FN_TRY_BLOCK_P.
(finish_function_try_block): Be careful rechaining
function try blocks.
(expand_stmt): Loop through all the statements at a given level.
(exapnd_body): Be careful with line-numbers here too. Prepare for
being called directly from the parser.
* cp-tree.h (finish_function): Adjust prototype. * cp-tree.h (finish_function): Adjust prototype.
* decl.c (finish_function): Return the function compiled. * decl.c (finish_function): Return the function compiled.
* pt.c (instantiate_decl): Don't play games with obstacks. * pt.c (instantiate_decl): Don't play games with obstacks.
......
...@@ -63,6 +63,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -63,6 +63,7 @@ Boston, MA 02111-1307, USA. */
BINFO_PUSHDECLS_MARKED. BINFO_PUSHDECLS_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV) ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
4: BINFO_NEW_VTABLE_MARKED. 4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
...@@ -2429,6 +2430,8 @@ extern int flag_new_for_scope; ...@@ -2429,6 +2430,8 @@ extern int flag_new_for_scope;
#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0) #define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1) #define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1)
#define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (NODE) #define CLEANUP_P(NODE) TREE_LANG_FLAG_0 (NODE)
/* Nonzero if this try block is a function try block. */
#define FN_TRY_BLOCK_P(NODE) TREE_LANG_FLAG_3 (NODE)
#define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0) #define HANDLER_PARMS(NODE) TREE_OPERAND (NODE, 0)
#define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1) #define HANDLER_BODY(NODE) TREE_OPERAND (NODE, 1)
#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0) #define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
......
...@@ -225,10 +225,6 @@ perform_member_init (member, name, init, explicit) ...@@ -225,10 +225,6 @@ perform_member_init (member, name, init, explicit)
{ {
tree expr; tree expr;
/* All cleanups must be on the function_obstack. */
push_obstacks_nochange ();
resume_temporary_allocation ();
expr = build_component_ref (current_class_ref, name, NULL_TREE, expr = build_component_ref (current_class_ref, name, NULL_TREE,
explicit); explicit);
expr = build_delete (type, expr, integer_zero_node, expr = build_delete (type, expr, integer_zero_node,
...@@ -236,8 +232,6 @@ perform_member_init (member, name, init, explicit) ...@@ -236,8 +232,6 @@ perform_member_init (member, name, init, explicit)
if (expr != error_mark_node) if (expr != error_mark_node)
finish_subobject (expr); finish_subobject (expr);
pop_obstacks ();
} }
} }
...@@ -699,10 +693,6 @@ expand_cleanup_for_base (binfo, flag) ...@@ -699,10 +693,6 @@ expand_cleanup_for_base (binfo, flag)
if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo))) if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
return; return;
/* All cleanups must be on the function_obstack. */
push_obstacks_nochange ();
resume_temporary_allocation ();
/* Call the destructor. */ /* Call the destructor. */
expr = (build_scoped_method_call expr = (build_scoped_method_call
(current_class_ref, binfo, dtor_identifier, (current_class_ref, binfo, dtor_identifier,
...@@ -712,7 +702,6 @@ expand_cleanup_for_base (binfo, flag) ...@@ -712,7 +702,6 @@ expand_cleanup_for_base (binfo, flag)
truthvalue_conversion (flag), truthvalue_conversion (flag),
expr, integer_zero_node)); expr, integer_zero_node));
pop_obstacks ();
finish_subobject (expr); finish_subobject (expr);
} }
...@@ -1009,9 +998,17 @@ finish_init_stmts (stmt_expr, compound_stmt) ...@@ -1009,9 +998,17 @@ finish_init_stmts (stmt_expr, compound_stmt)
tree compound_stmt; tree compound_stmt;
{ {
pop_momentary (); pop_momentary ();
return finish_stmt_expr (stmt_expr, stmt_expr
finish_compound_stmt (/*has_no_scope=*/1, = finish_stmt_expr (stmt_expr,
compound_stmt)); finish_compound_stmt (/*has_no_scope=*/1,
compound_stmt));
/* To avoid spurious warnings about unused values, we set
TREE_USED. */
if (stmt_expr)
TREE_USED (stmt_expr) = 1;
return stmt_expr;
} }
/* This is like `expand_member_init', only it stores one aggregate /* This is like `expand_member_init', only it stores one aggregate
......
...@@ -2147,7 +2147,7 @@ emit_thunk (thunk_fndecl) ...@@ -2147,7 +2147,7 @@ emit_thunk (thunk_fndecl)
t = tree_cons (NULL_TREE, a, t); t = tree_cons (NULL_TREE, a, t);
t = nreverse (t); t = nreverse (t);
t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t); t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
c_expand_return (t); finish_return_stmt (t);
finish_function (lineno, 0); finish_function (lineno, 0);
...@@ -2172,7 +2172,6 @@ do_build_copy_constructor (fndecl) ...@@ -2172,7 +2172,6 @@ do_build_copy_constructor (fndecl)
tree fndecl; tree fndecl;
{ {
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
tree t; tree t;
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)) if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
...@@ -2249,9 +2248,6 @@ do_build_copy_constructor (fndecl) ...@@ -2249,9 +2248,6 @@ do_build_copy_constructor (fndecl)
current_base_init_list = nreverse (current_base_init_list); current_base_init_list = nreverse (current_base_init_list);
setup_vtbl_ptr (); setup_vtbl_ptr ();
} }
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
} }
static void static void
...@@ -2290,7 +2286,7 @@ do_build_assign_ref (fndecl) ...@@ -2290,7 +2286,7 @@ do_build_assign_ref (fndecl)
p = convert_from_reference (p); p = convert_from_reference (p);
p = build_member_call (basetype, ansi_opname [MODIFY_EXPR], p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
build_expr_list (NULL_TREE, p)); build_expr_list (NULL_TREE, p));
expand_expr_stmt (p); finish_expr_stmt (p);
} }
for (; fields; fields = TREE_CHAIN (fields)) for (; fields; fields = TREE_CHAIN (fields))
{ {
...@@ -2342,10 +2338,10 @@ do_build_assign_ref (fndecl) ...@@ -2342,10 +2338,10 @@ do_build_assign_ref (fndecl)
comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field); comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);
init = build (COMPONENT_REF, TREE_TYPE (field), init, field); init = build (COMPONENT_REF, TREE_TYPE (field), init, field);
expand_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
} }
} }
c_expand_return (current_class_ref); finish_return_stmt (current_class_ref);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
} }
...@@ -2355,6 +2351,7 @@ synthesize_method (fndecl) ...@@ -2355,6 +2351,7 @@ synthesize_method (fndecl)
{ {
int nested = (current_function_decl != NULL_TREE); int nested = (current_function_decl != NULL_TREE);
tree context = hack_decl_function_context (fndecl); tree context = hack_decl_function_context (fndecl);
int need_body = 1;
if (at_eof) if (at_eof)
import_export_decl (fndecl); import_export_decl (fndecl);
...@@ -2364,13 +2361,25 @@ synthesize_method (fndecl) ...@@ -2364,13 +2361,25 @@ synthesize_method (fndecl)
else if (nested) else if (nested)
push_function_context_to (context); push_function_context_to (context);
/* Put the function definition at the position where it is needed,
rather than within the body of the class. That way, an error
during the generation of the implicit body points at the place
where the attempt to generate the function occurs, giving the
user a hint as to why we are attempting to generate the
function. */
DECL_SOURCE_LINE (fndecl) = lineno;
DECL_SOURCE_FILE (fndecl) = input_filename;
interface_unknown = 1; interface_unknown = 1;
start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED); start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
store_parm_decls (); store_parm_decls ();
clear_last_expr (); clear_last_expr ();
if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR]) if (DECL_NAME (fndecl) == ansi_opname[MODIFY_EXPR])
do_build_assign_ref (fndecl); {
do_build_assign_ref (fndecl);
need_body = 0;
}
else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl))) else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
; ;
else else
...@@ -2381,13 +2390,16 @@ synthesize_method (fndecl) ...@@ -2381,13 +2390,16 @@ synthesize_method (fndecl)
if (arg_chain != void_list_node) if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl); do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
{ setup_vtbl_ptr ();
tree compound_stmt; }
setup_vtbl_ptr (); /* If we haven't yet generated the body of the function, just
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0); generate an empty compound statement. */
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt); if (need_body)
} {
tree compound_stmt;
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
} }
finish_function (lineno, 0); finish_function (lineno, 0);
......
...@@ -7443,16 +7443,32 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7443,16 +7443,32 @@ tsubst_expr (t, args, complain, in_decl)
case TRY_BLOCK: case TRY_BLOCK:
prep_stmt (t); prep_stmt (t);
stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (stmt);
if (CLEANUP_P (t)) if (CLEANUP_P (t))
finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args, {
complain, in_decl), begin_try_block ();
stmt); tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_cleanup_try_block (stmt);
finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
complain, in_decl),
stmt);
}
else else
{ {
tree handler = TRY_HANDLERS (t); tree handler;
if (FN_TRY_BLOCK_P (t))
stmt = begin_function_try_block ();
else
stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
if (FN_TRY_BLOCK_P (t))
finish_function_try_block (stmt);
else
finish_try_block (stmt);
handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler)) for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl); tsubst_expr (handler, args, complain, in_decl);
finish_handler_sequence (stmt); finish_handler_sequence (stmt);
......
...@@ -41,7 +41,6 @@ ...@@ -41,7 +41,6 @@
parsing into this file; that will make implementing the new parser parsing into this file; that will make implementing the new parser
much easier since it will be able to make use of these routines. */ much easier since it will be able to make use of these routines. */
static void expand_stmts PROTO((tree));
static void do_pushlevel PROTO((void)); static void do_pushlevel PROTO((void));
static tree do_poplevel PROTO((void)); static tree do_poplevel PROTO((void));
static void finish_expr_stmt_real PROTO((tree, int)); static void finish_expr_stmt_real PROTO((tree, int));
...@@ -650,6 +649,7 @@ begin_function_try_block () ...@@ -650,6 +649,7 @@ begin_function_try_block ()
{ {
tree r = build_min_nt (TRY_BLOCK, NULL_TREE, tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE); NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
add_tree (r); add_tree (r);
return r; return r;
} }
...@@ -674,6 +674,14 @@ finish_try_block (try_block) ...@@ -674,6 +674,14 @@ finish_try_block (try_block)
expand_start_all_catch (); expand_start_all_catch ();
} }
void
finish_cleanup_try_block (try_block)
tree try_block;
{
if (building_stmt_tree ())
RECHAIN_STMTS (try_block, TRY_STMTS (try_block));
}
/* Finish an implicitly generated try-block, with a cleanup is given /* Finish an implicitly generated try-block, with a cleanup is given
by CLEANUP. */ by CLEANUP. */
...@@ -698,7 +706,18 @@ finish_function_try_block (try_block) ...@@ -698,7 +706,18 @@ finish_function_try_block (try_block)
tree try_block; tree try_block;
{ {
if (building_stmt_tree ()) if (building_stmt_tree ())
RECHAIN_STMTS (try_block, TRY_STMTS (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));
}
else else
{ {
end_protect_partials (); end_protect_partials ();
...@@ -2025,219 +2044,225 @@ expand_cond (t) ...@@ -2025,219 +2044,225 @@ expand_cond (t)
return t; return t;
} }
/* Generate RTL for the chain of statements T. */ /* Generate RTL for the statement T, and its substatements, and any
other statements at its nesting level. */
static void
expand_stmts (t)
tree t;
{
while (t)
{
expand_stmt (t);
t = TREE_CHAIN (t);
}
}
/* Generate RTL for the statement T, and its substatements. */
tree tree
expand_stmt (t) expand_stmt (t)
tree t; tree t;
{ {
int saved_stmts_are_full_exprs_p;
tree rval; tree rval;
if (t == NULL_TREE || t == error_mark_node) while (t && t != error_mark_node)
return NULL_TREE; {
int saved_stmts_are_full_exprs_p;
/* Assume we'll have nothing to return. */ /* Assume we'll have nothing to return. */
rval = NULL_TREE; rval = NULL_TREE;
/* Set up context appropriately for handling this statement. */ /* Set up context appropriately for handling this statement. */
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p; saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
prep_stmt (t); prep_stmt (t);
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case RETURN_STMT: case RETURN_STMT:
finish_return_stmt (RETURN_EXPR (t)); finish_return_stmt (RETURN_EXPR (t));
break; break;
case EXPR_STMT: case EXPR_STMT:
finish_expr_stmt_real (EXPR_STMT_EXPR (t), finish_expr_stmt_real (EXPR_STMT_EXPR (t),
EXPR_STMT_ASSIGNS_THIS (t)); EXPR_STMT_ASSIGNS_THIS (t));
break; break;
case DECL_STMT: case DECL_STMT:
{
tree decl;
int i = suspend_momentary ();
lineno = STMT_LINENO (t);
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{ {
/* We need to clear DECL_CONTEXT so that maybe_push_decl tree decl;
will push it into the current scope. */ int i = suspend_momentary ();
if (DECL_CONTEXT (decl) == current_function_decl)
DECL_CONTEXT (decl) = NULL_TREE; emit_line_note (input_filename, lineno);
/* If we marked this variable as dead when we processed it decl = DECL_STMT_DECL (t);
before, we must undo that now. The variable has been if (TREE_CODE (decl) == LABEL_DECL)
resuscitated. */ finish_label_decl (DECL_NAME (decl));
if (TREE_CODE (decl) == VAR_DECL) else
DECL_DEAD_FOR_LOCAL (decl) = 0;
maybe_push_decl (decl);
if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
{ {
maybe_inject_for_scope_var (decl); /* If we marked this variable as dead when we processed it
initialize_local_var (decl, DECL_INITIAL (decl), 0); before, we must undo that now. The variable has been
resuscitated. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (decl) = 0;
/* We need to clear DECL_CONTEXT so that maybe_push_decl
will push it into the current scope. */
if (DECL_CONTEXT (decl) == current_function_decl)
{
DECL_CONTEXT (decl) = NULL_TREE;
maybe_push_decl (decl);
}
/* If this is a declaration for an automatic local
variable, initialize it. Note that we might also see a
declaration for a namespace-scope object (declared with
`extern') or an object with static storage duration
(declared with `static'). We don't have to handle the
initialization of those objects here; the former can
never be a definition (only a declaration), and the
latter is handled in finish_file. */
if (TREE_CODE (decl) == VAR_DECL
&& !TREE_STATIC (decl)
&& !DECL_EXTERNAL (decl))
{
/* Support the old for-scope rules for backwards
compatibility. */
maybe_inject_for_scope_var (decl);
/* Let the back-end know about this variable. */
initialize_local_var (decl, DECL_INITIAL (decl), 0);
}
} }
resume_momentary (i);
} }
resume_momentary (i); break;
}
break;
case FOR_STMT:
{
tree tmp;
begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
expand_stmt (tmp);
finish_for_init_stmt (NULL_TREE);
finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE);
tmp = FOR_EXPR (t);
finish_for_expr (tmp, NULL_TREE);
expand_stmt (FOR_BODY (t));
finish_for_stmt (tmp, NULL_TREE);
}
break;
case WHILE_STMT:
{
begin_while_stmt ();
finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE);
expand_stmt (WHILE_BODY (t));
finish_while_stmt (NULL_TREE);
}
break;
case DO_STMT: case FOR_STMT:
{ {
begin_do_stmt (); tree tmp;
expand_stmt (DO_BODY (t));
finish_do_body (NULL_TREE); begin_for_stmt ();
finish_do_stmt (DO_COND (t), NULL_TREE); expand_stmt (FOR_INIT_STMT (t));
} finish_for_init_stmt (NULL_TREE);
break; finish_for_cond (expand_cond (FOR_COND (t)), NULL_TREE);
tmp = FOR_EXPR (t);
case IF_STMT: finish_for_expr (tmp, NULL_TREE);
begin_if_stmt (); expand_stmt (FOR_BODY (t));
finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE); finish_for_stmt (tmp, NULL_TREE);
if (THEN_CLAUSE (t)) }
{ break;
expand_stmt (THEN_CLAUSE (t));
finish_then_clause (NULL_TREE);
}
if (ELSE_CLAUSE (t))
{
begin_else_clause ();
expand_stmt (ELSE_CLAUSE (t));
finish_else_clause (NULL_TREE);
}
finish_if_stmt ();
break;
case COMPOUND_STMT:
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
expand_stmts (COMPOUND_BODY (t));
rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
break;
case BREAK_STMT:
finish_break_stmt ();
break;
case CONTINUE_STMT: case WHILE_STMT:
finish_continue_stmt (); {
break; begin_while_stmt ();
finish_while_stmt_cond (expand_cond (WHILE_COND (t)), NULL_TREE);
expand_stmt (WHILE_BODY (t));
finish_while_stmt (NULL_TREE);
}
break;
case SWITCH_STMT: case DO_STMT:
{ {
tree cond; begin_do_stmt ();
expand_stmt (DO_BODY (t));
finish_do_body (NULL_TREE);
finish_do_stmt (DO_COND (t), NULL_TREE);
}
break;
begin_switch_stmt (); case IF_STMT:
cond = expand_cond (SWITCH_COND (t)); begin_if_stmt ();
finish_switch_cond (cond, NULL_TREE); finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE);
expand_stmt (SWITCH_BODY (t)); if (THEN_CLAUSE (t))
finish_switch_stmt (cond, NULL_TREE); {
} expand_stmt (THEN_CLAUSE (t));
break; finish_then_clause (NULL_TREE);
}
if (ELSE_CLAUSE (t))
{
begin_else_clause ();
expand_stmt (ELSE_CLAUSE (t));
finish_else_clause (NULL_TREE);
}
finish_if_stmt ();
break;
case CASE_LABEL: case COMPOUND_STMT:
finish_case_label (CASE_LOW (t), CASE_HIGH (t)); begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
break; expand_stmt (COMPOUND_BODY (t));
rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
break;
case LABEL_STMT: case BREAK_STMT:
finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t))); finish_break_stmt ();
break; break;
case GOTO_STMT: case CONTINUE_STMT:
if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL) finish_continue_stmt ();
finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t))); break;
else
finish_goto_stmt (GOTO_DESTINATION (t));
break;
case ASM_STMT: case SWITCH_STMT:
finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS {
(t), ASM_INPUTS (t), ASM_CLOBBERS (t)); tree cond;
break;
case TRY_BLOCK: begin_switch_stmt ();
if (CLEANUP_P (t)) cond = expand_cond (SWITCH_COND (t));
{ finish_switch_cond (cond, NULL_TREE);
expand_eh_region_start (); expand_stmt (SWITCH_BODY (t));
expand_stmt (TRY_STMTS (t)); finish_switch_stmt (cond, NULL_TREE);
finish_cleanup (TRY_HANDLERS (t), NULL_TREE); }
} break;
else
{ case CASE_LABEL:
begin_try_block (); finish_case_label (CASE_LOW (t), CASE_HIGH (t));
expand_stmt (TRY_STMTS (t)); break;
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t)); case LABEL_STMT:
finish_handler_sequence (NULL_TREE); finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case GOTO_STMT:
if (TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL)
finish_goto_stmt (DECL_NAME (GOTO_DESTINATION (t)));
else
finish_goto_stmt (GOTO_DESTINATION (t));
break;
case ASM_STMT:
finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS
(t), ASM_INPUTS (t), ASM_CLOBBERS (t));
break;
case TRY_BLOCK:
if (CLEANUP_P (t))
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
finish_cleanup_try_block (NULL_TREE);
finish_cleanup (TRY_HANDLERS (t), NULL_TREE);
}
else
{
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmt (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
}
break;
case HANDLER:
begin_handler ();
if (HANDLER_PARMS (t))
expand_start_catch_block (DECL_STMT_DECL (HANDLER_PARMS (t)));
else
expand_start_catch_block (NULL_TREE);
finish_handler_parms (NULL_TREE);
expand_stmt (HANDLER_BODY (t));
finish_handler (NULL_TREE);
break;
case SUBOBJECT:
finish_subobject (SUBOBJECT_CLEANUP (t));
break;
default:
my_friendly_abort (19990810);
break;
} }
break;
case HANDLER: /* Restore saved state. */
begin_handler (); stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
if (HANDLER_PARMS (t))
expand_start_catch_block (DECL_STMT_DECL (HANDLER_PARMS (t)));
else
expand_start_catch_block (NULL_TREE);
finish_handler_parms (NULL_TREE);
expand_stmt (HANDLER_BODY (t));
finish_handler (NULL_TREE);
break;
case SUBOBJECT: /* Go on to the next statement in this scope. */
finish_subobject (SUBOBJECT_CLEANUP (t)); t = TREE_CHAIN (t);
break;
default:
my_friendly_abort (19990810);
break;
} }
/* Restore saved state. */
stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
return rval; return rval;
} }
...@@ -2247,9 +2272,30 @@ void ...@@ -2247,9 +2272,30 @@ void
expand_body (fn) expand_body (fn)
tree fn; tree fn;
{ {
int saved_lineno;
char *saved_input_filename;
tree t; tree t;
tree try_block; tree try_block;
/* When the parser calls us after finishing the body of a template
function, we don't really want to expand the body. When we're
processing an in-class definition of an inline function,
PROCESSING_TEMPLATE_DECL will no longer be set here, so we have
to look at the function itself. */
if (processing_template_decl
|| (DECL_LANG_SPECIFIC (fn)
&& DECL_TEMPLATE_INFO (fn)
&& uses_template_parms (DECL_TI_ARGS (fn))))
return;
/* Save the current file name and line number. When we expand the
body of the funciton, we'll set LINENO and INPUT_FILENAME so that
error-mesages come out in the right places. */
saved_lineno = lineno;
saved_input_filename = input_filename;
lineno = DECL_SOURCE_LINE (fn);
input_filename = DECL_SOURCE_FILE (fn);
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND); start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
store_parm_decls (); store_parm_decls ();
...@@ -2292,13 +2338,22 @@ expand_body (fn) ...@@ -2292,13 +2338,22 @@ expand_body (fn)
if (try_block) if (try_block)
{ {
finish_function_try_block (NULL_TREE); finish_function_try_block (NULL_TREE);
{ expand_stmt (TRY_HANDLERS (try_block));
tree handler = TRY_HANDLERS (try_block);
for (; handler; handler = TREE_CHAIN (handler))
expand_stmt (handler);
}
finish_function_handler_sequence (NULL_TREE); finish_function_handler_sequence (NULL_TREE);
} }
/* Statements should always be full-expressions at the outermost set
of curly braces for a function. */
my_friendly_assert (stmts_are_full_exprs_p, 19990831);
/* The outermost statement for a function contains the line number
recorded when we finished processing the function. */
lineno = STMT_LINENO (DECL_SAVED_TREE (fn));
/* Generate code for the function. */
finish_function (lineno, 0); finish_function (lineno, 0);
/* And restore the current source position. */
lineno = saved_lineno;
input_filename = saved_input_filename;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment