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>
* 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.
* decl.c (finish_function): Return the function compiled.
* pt.c (instantiate_decl): Don't play games with obstacks.
......
......@@ -63,6 +63,7 @@ Boston, MA 02111-1307, USA. */
BINFO_PUSHDECLS_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
FN_TRY_BLOCK_P (in TRY_BLOCK)
4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL).
......@@ -2429,6 +2430,8 @@ extern int flag_new_for_scope;
#define TRY_STMTS(NODE) TREE_OPERAND (NODE, 0)
#define TRY_HANDLERS(NODE) TREE_OPERAND (NODE, 1)
#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_BODY(NODE) TREE_OPERAND (NODE, 1)
#define COMPOUND_BODY(NODE) TREE_OPERAND (NODE, 0)
......
......@@ -225,10 +225,6 @@ perform_member_init (member, name, init, explicit)
{
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,
explicit);
expr = build_delete (type, expr, integer_zero_node,
......@@ -236,8 +232,6 @@ perform_member_init (member, name, init, explicit)
if (expr != error_mark_node)
finish_subobject (expr);
pop_obstacks ();
}
}
......@@ -699,10 +693,6 @@ expand_cleanup_for_base (binfo, flag)
if (!TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))
return;
/* All cleanups must be on the function_obstack. */
push_obstacks_nochange ();
resume_temporary_allocation ();
/* Call the destructor. */
expr = (build_scoped_method_call
(current_class_ref, binfo, dtor_identifier,
......@@ -712,7 +702,6 @@ expand_cleanup_for_base (binfo, flag)
truthvalue_conversion (flag),
expr, integer_zero_node));
pop_obstacks ();
finish_subobject (expr);
}
......@@ -1009,9 +998,17 @@ finish_init_stmts (stmt_expr, compound_stmt)
tree compound_stmt;
{
pop_momentary ();
return finish_stmt_expr (stmt_expr,
finish_compound_stmt (/*has_no_scope=*/1,
compound_stmt));
stmt_expr
= finish_stmt_expr (stmt_expr,
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
......
......@@ -2147,7 +2147,7 @@ emit_thunk (thunk_fndecl)
t = tree_cons (NULL_TREE, a, t);
t = nreverse (t);
t = build_call (function, TREE_TYPE (TREE_TYPE (function)), t);
c_expand_return (t);
finish_return_stmt (t);
finish_function (lineno, 0);
......@@ -2172,7 +2172,6 @@ do_build_copy_constructor (fndecl)
tree fndecl;
{
tree parm = TREE_CHAIN (DECL_ARGUMENTS (fndecl));
tree compound_stmt;
tree t;
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
......@@ -2249,9 +2248,6 @@ do_build_copy_constructor (fndecl)
current_base_init_list = nreverse (current_base_init_list);
setup_vtbl_ptr ();
}
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
}
static void
......@@ -2290,7 +2286,7 @@ do_build_assign_ref (fndecl)
p = convert_from_reference (p);
p = build_member_call (basetype, ansi_opname [MODIFY_EXPR],
build_expr_list (NULL_TREE, p));
expand_expr_stmt (p);
finish_expr_stmt (p);
}
for (; fields; fields = TREE_CHAIN (fields))
{
......@@ -2342,10 +2338,10 @@ do_build_assign_ref (fndecl)
comp = build (COMPONENT_REF, TREE_TYPE (field), comp, 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);
}
......@@ -2355,6 +2351,7 @@ synthesize_method (fndecl)
{
int nested = (current_function_decl != NULL_TREE);
tree context = hack_decl_function_context (fndecl);
int need_body = 1;
if (at_eof)
import_export_decl (fndecl);
......@@ -2364,13 +2361,25 @@ synthesize_method (fndecl)
else if (nested)
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;
start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
store_parm_decls ();
clear_last_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
......@@ -2381,13 +2390,16 @@ synthesize_method (fndecl)
if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
{
tree compound_stmt;
setup_vtbl_ptr ();
}
setup_vtbl_ptr ();
compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
}
/* If we haven't yet generated the body of the function, just
generate an empty compound statement. */
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);
......
......@@ -7443,16 +7443,32 @@ tsubst_expr (t, args, complain, in_decl)
case TRY_BLOCK:
prep_stmt (t);
stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (stmt);
if (CLEANUP_P (t))
finish_cleanup (tsubst_expr (TRY_HANDLERS (t), args,
complain, in_decl),
stmt);
{
begin_try_block ();
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
{
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))
tsubst_expr (handler, args, complain, in_decl);
finish_handler_sequence (stmt);
......
......@@ -41,7 +41,6 @@
parsing into this file; that will make implementing the new parser
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 tree do_poplevel PROTO((void));
static void finish_expr_stmt_real PROTO((tree, int));
......@@ -650,6 +649,7 @@ begin_function_try_block ()
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
FN_TRY_BLOCK_P (r) = 1;
add_tree (r);
return r;
}
......@@ -674,6 +674,14 @@ finish_try_block (try_block)
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
by CLEANUP. */
......@@ -698,7 +706,18 @@ finish_function_try_block (try_block)
tree try_block;
{
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
{
end_protect_partials ();
......@@ -2025,219 +2044,225 @@ expand_cond (t)
return t;
}
/* Generate RTL for the chain of statements T. */
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. */
/* Generate RTL for the statement T, and its substatements, and any
other statements at its nesting level. */
tree
expand_stmt (t)
tree t;
{
int saved_stmts_are_full_exprs_p;
tree rval;
if (t == NULL_TREE || t == error_mark_node)
return NULL_TREE;
while (t && t != error_mark_node)
{
int saved_stmts_are_full_exprs_p;
/* Assume we'll have nothing to return. */
rval = NULL_TREE;
/* Assume we'll have nothing to return. */
rval = NULL_TREE;
/* Set up context appropriately for handling this statement. */
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
prep_stmt (t);
/* Set up context appropriately for handling this statement. */
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
prep_stmt (t);
switch (TREE_CODE (t))
{
case RETURN_STMT:
finish_return_stmt (RETURN_EXPR (t));
break;
switch (TREE_CODE (t))
{
case RETURN_STMT:
finish_return_stmt (RETURN_EXPR (t));
break;
case EXPR_STMT:
finish_expr_stmt_real (EXPR_STMT_EXPR (t),
EXPR_STMT_ASSIGNS_THIS (t));
break;
case EXPR_STMT:
finish_expr_stmt_real (EXPR_STMT_EXPR (t),
EXPR_STMT_ASSIGNS_THIS (t));
break;
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
case DECL_STMT:
{
/* 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;
/* If we marked this variable as dead when we processed it
before, we must undo that now. The variable has been
resuscitated. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (decl) = 0;
maybe_push_decl (decl);
if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
tree decl;
int i = suspend_momentary ();
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
if (TREE_CODE (decl) == LABEL_DECL)
finish_label_decl (DECL_NAME (decl));
else
{
maybe_inject_for_scope_var (decl);
initialize_local_var (decl, DECL_INITIAL (decl), 0);
/* If we marked this variable as dead when we processed it
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;
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;
break;
case DO_STMT:
{
begin_do_stmt ();
expand_stmt (DO_BODY (t));
finish_do_body (NULL_TREE);
finish_do_stmt (DO_COND (t), NULL_TREE);
}
break;
case IF_STMT:
begin_if_stmt ();
finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE);
if (THEN_CLAUSE (t))
{
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 FOR_STMT:
{
tree tmp;
begin_for_stmt ();
expand_stmt (FOR_INIT_STMT (t));
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 CONTINUE_STMT:
finish_continue_stmt ();
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 SWITCH_STMT:
{
tree cond;
case DO_STMT:
{
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 ();
cond = expand_cond (SWITCH_COND (t));
finish_switch_cond (cond, NULL_TREE);
expand_stmt (SWITCH_BODY (t));
finish_switch_stmt (cond, NULL_TREE);
}
break;
case IF_STMT:
begin_if_stmt ();
finish_if_stmt_cond (expand_cond (IF_COND (t)), NULL_TREE);
if (THEN_CLAUSE (t))
{
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 CASE_LABEL:
finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break;
case COMPOUND_STMT:
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
expand_stmt (COMPOUND_BODY (t));
rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
break;
case LABEL_STMT:
finish_label_stmt (DECL_NAME (LABEL_STMT_LABEL (t)));
break;
case BREAK_STMT:
finish_break_stmt ();
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 CONTINUE_STMT:
finish_continue_stmt ();
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 SWITCH_STMT:
{
tree cond;
case TRY_BLOCK:
if (CLEANUP_P (t))
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
finish_cleanup (TRY_HANDLERS (t), NULL_TREE);
}
else
{
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
begin_switch_stmt ();
cond = expand_cond (SWITCH_COND (t));
finish_switch_cond (cond, NULL_TREE);
expand_stmt (SWITCH_BODY (t));
finish_switch_stmt (cond, NULL_TREE);
}
break;
case CASE_LABEL:
finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break;
case LABEL_STMT:
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:
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;
/* Restore saved state. */
stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
case SUBOBJECT:
finish_subobject (SUBOBJECT_CLEANUP (t));
break;
default:
my_friendly_abort (19990810);
break;
/* Go on to the next statement in this scope. */
t = TREE_CHAIN (t);
}
/* Restore saved state. */
stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
return rval;
}
......@@ -2247,9 +2272,30 @@ void
expand_body (fn)
tree fn;
{
int saved_lineno;
char *saved_input_filename;
tree t;
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);
store_parm_decls ();
......@@ -2292,13 +2338,22 @@ expand_body (fn)
if (try_block)
{
finish_function_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (try_block);
for (; handler; handler = TREE_CHAIN (handler))
expand_stmt (handler);
}
expand_stmt (TRY_HANDLERS (try_block));
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);
/* 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