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,
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);
need_body = 0;
}
else if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fndecl)))
;
else
......@@ -2381,14 +2390,17 @@ synthesize_method (fndecl)
if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
setup_vtbl_ptr ();
}
/* If we haven't yet generated the body of the function, just
generate an empty compound statement. */
if (need_body)
{
tree compound_stmt;
setup_vtbl_ptr ();
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))
{
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 ())
{
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,30 +2044,18 @@ 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;
......@@ -2073,26 +2080,40 @@ expand_stmt (t)
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
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))
/* 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);
}
}
......@@ -2105,8 +2126,7 @@ expand_stmt (t)
tree tmp;
begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
expand_stmt (tmp);
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);
......@@ -2153,7 +2173,7 @@ expand_stmt (t)
case COMPOUND_STMT:
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
expand_stmts (COMPOUND_BODY (t));
expand_stmt (COMPOUND_BODY (t));
rval = finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
break;
......@@ -2203,6 +2223,7 @@ expand_stmt (t)
{
expand_eh_region_start ();
expand_stmt (TRY_STMTS (t));
finish_cleanup_try_block (NULL_TREE);
finish_cleanup (TRY_HANDLERS (t), NULL_TREE);
}
else
......@@ -2210,7 +2231,7 @@ expand_stmt (t)
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t));
expand_stmt (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
}
break;
......@@ -2238,6 +2259,10 @@ expand_stmt (t)
/* Restore saved state. */
stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
/* Go on to the next statement in this scope. */
t = TREE_CHAIN (t);
}
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