cp-tree.def (STMT_EXPR): New tree node.

* cp-tree.def (STMT_EXPR): New tree node.
	* cp-tree.h (STMT_EXPR_STMT): New macro.
	(store_return_init): Change prototype.
	(finish_named_return_value): New function.
	(expand_stmt): Likewise.
	(expand_body): Likewise.
	(begin_stmt_tree): Likewise.
	(finish_stmt_tree): Likewise.
	(expanding_p): New variable.
	(last_expr_type): Likewise.
	(building_stmt_tree): New macro.
	* decl.c (start_function): Use building_stmt_tree, not
	processing_template_decl, where appropriate.
	(store_parm_decls): Likewise.
	(store_return_init): Move most of the body to semantics.c.
	(finish_function): Use building_stmt_tree.
	(finish_stmt): Clear last_expr_type here.
	(cp_function): Add expanding_p, last_tree, last_expr_type.
	(push_cp_function_context): Save them.
	(pop_cp_function_context): Restore them.
	* decl2.c (setup_vtbl_ptr): Move to semantics.c.
	* error.c (dump_expr): Handle STMT_EXPR.
	* except.c (expand_start_catch_block): Use building_stmt_tree.
	Use add_decl_stmt.
	* expr.c (cplus_expand_expr): Handle STMT_EXPR.
	(do_case): Move add_tree call to semantics.c.
	* parse.y (return_init): Use finish_named_return_value.
	(for.init.statement): Use finish_expr_stmt.
	* parse.c: Regenerated.
	* pt.c (do_pushlevel): Move to semantics.c.
	(do_poplevel): Likewise.
	(tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR.
	(tsubst_expr): Don't expand all the way to RTL here.  Handle
	RETURN_INIT and CTOR_INITIALIZER.
	(instantiate_decl): Call expand_body after tsubst'ing into
	DECL_SAVED_TREE.
	* semantics.c (expand_stmts): New function.
	(expanding_p): New variable.
	(last_expr_type): Likewise.
	(finish_expr_stmt): Use building_stmt_tree.
	(begin_if_stmt): Likewise.
	(finish_if_stmt_cond): Likewise.
	(finish_then_clause): Likewise.
	(begin_else_clause): Likewise.
	(finish_else_clause): Likewise.
	(begin_while_stmt): Likewise.
	(finish_while_stmt_cond): Likewise.
	(finish_while_stmt): Likewise.
	(finish_do_body): Likewise.
	(finish_do_stmt): Likewise.
	(finish_return_stmt): Likewise.
	(begin_for_stmt): Likewise.
	(fnish_for_init_stmt): Likewise.
	(finish_for_cond): Likewise.
	(finish_for_expr): Likewise.
	(finish_for_stmt): Likewise.
	(finish_break_stmt): Likewise.
	(finish_continue_stmt): Likewise.
	(finish_switch_cond): Likewise.
	(finish_switch_stmt): Likewise.
	(finish_case_label): Call add_tree here if necessary.
	(finish_goto_statement): Use building_stmt_tree.
	(begin_try_block): Likewise.
	(begin_function_try_block): Likewise.
	(finish_try_block): Likewise.
	(finish_function_try_block): Likewise.
	(finish_handler_sequence): Likewise.
	(finish_function_handler_sequence): Likewise.
	(begin_handler): Likewise.
	(finish_handler_parms): Likewise.
	(finish_handler): Likewise.
	(begin_compound_stmt): Likewise.
	(finish_compound_stmt): Likewise.
	(finish_asm_stmt): Likewise.
	(finish_label_stmt): Likewise.
	(finish_named_return_value): New function.
	(setup_vtbl_ptr): Moved here from decl2.c.
	(do_pushlevel): Moved here from pt.c.
	(do_poplevel): Likewise.
	(begin_stmt_expr): Use building_stmt_tree.
	(finish_stmt_expr): Likewise.  Build a STMT_EXPR, not a BIND_EXPR,
	when building_stmt_tree.
	(begin_stmt_tree): New function.
	(finish_stmt_tree): Likewise.
	(expand_stmt): Likewise.
	(expand_body): Likewise.
	* tree.c (build_cplus_method_type): Make sure the argument types
	end up on the same obstack as the METHOD_TYPE.
	(search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR,
	THROW_EXPR, STMT_EXPR.
	(mapcar): Break out common cases.  Handle COMPOUND_EXPR,
	MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR.  Abort, rather than
	sorry, if an unsupported node is encountered.
	* typeck.c (require_complete_type_in_void): Handle BIND_EXPR.
	(c_expand_return): Don't call add_tree here.

From-SVN: r28729
This commit is contained in:
Mark Mitchell 1999-08-16 19:01:36 +00:00 committed by Mark Mitchell
parent 63ebc27560
commit 558475f07c
14 changed files with 845 additions and 382 deletions

View File

@ -1,3 +1,101 @@
1999-08-16 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (STMT_EXPR): New tree node.
* cp-tree.h (STMT_EXPR_STMT): New macro.
(store_return_init): Change prototype.
(finish_named_return_value): New function.
(expand_stmt): Likewise.
(expand_body): Likewise.
(begin_stmt_tree): Likewise.
(finish_stmt_tree): Likewise.
(expanding_p): New variable.
(last_expr_type): Likewise.
(building_stmt_tree): New macro.
* decl.c (start_function): Use building_stmt_tree, not
processing_template_decl, where appropriate.
(store_parm_decls): Likewise.
(store_return_init): Move most of the body to semantics.c.
(finish_function): Use building_stmt_tree.
(finish_stmt): Clear last_expr_type here.
(cp_function): Add expanding_p, last_tree, last_expr_type.
(push_cp_function_context): Save them.
(pop_cp_function_context): Restore them.
* decl2.c (setup_vtbl_ptr): Move to semantics.c.
* error.c (dump_expr): Handle STMT_EXPR.
* except.c (expand_start_catch_block): Use building_stmt_tree.
Use add_decl_stmt.
* expr.c (cplus_expand_expr): Handle STMT_EXPR.
(do_case): Move add_tree call to semantics.c.
* parse.y (return_init): Use finish_named_return_value.
(for.init.statement): Use finish_expr_stmt.
* parse.c: Regenerated.
* pt.c (do_pushlevel): Move to semantics.c.
(do_poplevel): Likewise.
(tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR.
(tsubst_expr): Don't expand all the way to RTL here. Handle
RETURN_INIT and CTOR_INITIALIZER.
(instantiate_decl): Call expand_body after tsubst'ing into
DECL_SAVED_TREE.
* semantics.c (expand_stmts): New function.
(expanding_p): New variable.
(last_expr_type): Likewise.
(finish_expr_stmt): Use building_stmt_tree.
(begin_if_stmt): Likewise.
(finish_if_stmt_cond): Likewise.
(finish_then_clause): Likewise.
(begin_else_clause): Likewise.
(finish_else_clause): Likewise.
(begin_while_stmt): Likewise.
(finish_while_stmt_cond): Likewise.
(finish_while_stmt): Likewise.
(finish_do_body): Likewise.
(finish_do_stmt): Likewise.
(finish_return_stmt): Likewise.
(begin_for_stmt): Likewise.
(fnish_for_init_stmt): Likewise.
(finish_for_cond): Likewise.
(finish_for_expr): Likewise.
(finish_for_stmt): Likewise.
(finish_break_stmt): Likewise.
(finish_continue_stmt): Likewise.
(finish_switch_cond): Likewise.
(finish_switch_stmt): Likewise.
(finish_case_label): Call add_tree here if necessary.
(finish_goto_statement): Use building_stmt_tree.
(begin_try_block): Likewise.
(begin_function_try_block): Likewise.
(finish_try_block): Likewise.
(finish_function_try_block): Likewise.
(finish_handler_sequence): Likewise.
(finish_function_handler_sequence): Likewise.
(begin_handler): Likewise.
(finish_handler_parms): Likewise.
(finish_handler): Likewise.
(begin_compound_stmt): Likewise.
(finish_compound_stmt): Likewise.
(finish_asm_stmt): Likewise.
(finish_label_stmt): Likewise.
(finish_named_return_value): New function.
(setup_vtbl_ptr): Moved here from decl2.c.
(do_pushlevel): Moved here from pt.c.
(do_poplevel): Likewise.
(begin_stmt_expr): Use building_stmt_tree.
(finish_stmt_expr): Likewise. Build a STMT_EXPR, not a BIND_EXPR,
when building_stmt_tree.
(begin_stmt_tree): New function.
(finish_stmt_tree): Likewise.
(expand_stmt): Likewise.
(expand_body): Likewise.
* tree.c (build_cplus_method_type): Make sure the argument types
end up on the same obstack as the METHOD_TYPE.
(search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR,
THROW_EXPR, STMT_EXPR.
(mapcar): Break out common cases. Handle COMPOUND_EXPR,
MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR. Abort, rather than
sorry, if an unsupported node is encountered.
* typeck.c (require_complete_type_in_void): Handle BIND_EXPR.
(c_expand_return): Don't call add_tree here.
1999-08-15 Mark Mitchell <mark@codesourcery.com>
* pt.c (check_default_tmpl_args): Don't check in local scopes.

View File

@ -235,6 +235,10 @@ DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2)
DEFTREECODE (HANDLER, "catch_stmt", 'e', 2)
/* A STMT_EXPR represents a statement-expression. The
STMT_EXPR_STMT is the statement given by the expression. */
DEFTREECODE (STMT_EXPR, "cp_stmt_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/* And some codes for expressing conversions for overload resolution. */

View File

@ -2138,6 +2138,7 @@ extern int flag_new_for_scope;
#define ASM_INPUTS(NODE) TREE_OPERAND (NODE, 3)
#define ASM_CLOBBERS(NODE) TREE_OPERAND (NODE, 4)
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */
#define ASM_VOLATILE_P(NODE) \
@ -2919,7 +2920,7 @@ extern tree build_enumerator PROTO((tree, tree, tree));
extern int start_function PROTO((tree, tree, tree, int));
extern void expand_start_early_try_stmts PROTO((void));
extern void store_parm_decls PROTO((void));
extern void store_return_init PROTO((tree, tree));
extern void store_return_init PROTO((tree));
extern void finish_function PROTO((int, int, int));
extern tree start_method PROTO((tree, tree, tree));
extern tree finish_method PROTO((tree));
@ -3365,6 +3366,17 @@ extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree));
extern void finish_named_return_value PROTO((tree, tree));
extern tree expand_stmt PROTO((tree));
extern void expand_body PROTO((tree));
extern void begin_stmt_tree PROTO((tree));
extern void finish_stmt_tree PROTO((tree));
extern int expanding_p;
extern tree last_expr_type;
/* Non-zero if we are presently building a statement tree, rather
than expanding each statement as we encounter it. */
#define building_stmt_tree() \
(processing_template_decl || !expanding_p)
/* in spew.c */
extern void init_spew PROTO((void));

View File

@ -4341,7 +4341,7 @@ maybe_push_decl (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == UNKNOWN_TYPE
/* The declaration of template specializations does not affect
/* The declaration of a template specialization does not affect
the functions available for overload resolution, so we do not
call pushdecl. */
|| (TREE_CODE (decl) == FUNCTION_DECL
@ -12882,7 +12882,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
announce_function (decl1);
if (!building_stmt_tree ())
announce_function (decl1);
/* Set up current_class_type, and enter the scope of the class, if
appropriate. */
@ -13110,12 +13111,14 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
pushlevel (0);
current_binding_level->parm_flag = 1;
GNU_xref_function (decl1, current_function_parms);
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
make_function_rtl (decl1);
if (!building_stmt_tree ())
{
GNU_xref_function (decl1, current_function_parms);
make_function_rtl (decl1);
}
/* Promote the value to int before returning it. */
if (C_PROMOTING_INTEGER_TYPE_P (restype))
@ -13141,9 +13144,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
if (! hack_decl_function_context (decl1))
temporary_allocation ();
if (processing_template_decl)
last_tree = DECL_SAVED_TREE (decl1)
= build_nt (EXPR_STMT, void_zero_node);
if (building_stmt_tree ())
begin_stmt_tree (decl1);
++function_depth;
@ -13254,7 +13256,7 @@ store_parm_decls ()
pushdecl (parm);
}
if (! processing_template_decl
if (! building_stmt_tree ()
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
@ -13295,21 +13297,20 @@ store_parm_decls ()
/* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = 0;
if (! processing_template_decl)
if (! building_stmt_tree ())
expand_function_start (fndecl, parms_have_cleanups);
current_function_parms_stored = 1;
/* If this function is `main', emit a call to `__main'
to run global initializers, etc. */
if (DECL_MAIN_P (fndecl))
if (DECL_MAIN_P (fndecl) && !building_stmt_tree ())
expand_main_function ();
/* Now that we have initialized the parms, we can start their
cleanups. We cannot do this before, since expand_decl_cleanup
should not be called before the parm can be used. */
if (cleanups
&& ! processing_template_decl)
if (cleanups && !building_stmt_tree ())
{
for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
{
@ -13325,10 +13326,11 @@ store_parm_decls ()
if (parms_have_cleanups)
{
pushlevel (0);
expand_start_bindings (0);
if (!building_stmt_tree ())
expand_start_bindings (0);
}
if (! processing_template_decl && flag_exceptions)
if (! building_stmt_tree () && flag_exceptions)
{
/* Do the starting of the exception specifications, if we have any. */
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
@ -13343,55 +13345,15 @@ store_parm_decls ()
the current function. */
void
store_return_init (return_id, init)
tree return_id, init;
store_return_init (decl)
tree decl;
{
tree decl = DECL_RESULT (current_function_decl);
if (pedantic)
/* Give this error as many times as there are occurrences,
so that users can use Emacs compilation buffers to find
and fix all such places. */
pedwarn ("ANSI C++ does not permit named return values");
if (return_id != NULL_TREE)
/* If this named return value comes in a register, put it in a
pseudo-register. */
if (DECL_REGISTER (decl))
{
if (DECL_NAME (decl) == NULL_TREE)
{
DECL_NAME (decl) = return_id;
DECL_ASSEMBLER_NAME (decl) = return_id;
}
else
cp_error ("return identifier `%D' already in place", decl);
}
/* Can't let this happen for constructors. */
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
error ("can't redefine default return value for constructors");
return;
}
/* If we have a named return value, put that in our scope as well. */
if (DECL_NAME (decl) != NULL_TREE)
{
/* If this named return value comes in a register,
put it in a pseudo-register. */
if (DECL_REGISTER (decl))
{
original_result_rtx = DECL_RTL (decl);
DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
}
/* Let `cp_finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
pushdecl (decl);
if (processing_template_decl && current_function_decl)
add_tree (build_min_nt (RETURN_INIT, return_id,
copy_to_permanent (init)));
else
cp_finish_decl (decl, init, NULL_TREE, 0, 0);
original_result_rtx = DECL_RTL (decl);
DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
}
}
@ -13430,7 +13392,7 @@ finish_function (lineno, flags, nested)
tree decls = NULL_TREE;
int call_poplevel = (flags & 1) != 0;
int inclass_inline = (flags & 2) != 0;
int in_template;
int expand_p;
/* When we get some parse errors, we can end up without a
current_function_decl, so cope. */
@ -13453,7 +13415,7 @@ finish_function (lineno, flags, nested)
store_parm_decls ();
}
if (processing_template_decl)
if (building_stmt_tree ())
{
if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
{
@ -13834,19 +13796,15 @@ finish_function (lineno, flags, nested)
/* Generate rtl for function exit. */
expand_function_end (input_filename, lineno, 1);
}
/* We have to save this value here in case
maybe_end_member_template_processing decides to pop all the
template parameters. */
expand_p = !building_stmt_tree ();
/* If we're processing a template, squirrel away the definition
until we do an instantiation. */
if (processing_template_decl)
{
DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
/* We have to save this value here in case
maybe_end_member_template_processing decides to pop all the
template parameters. */
in_template = 1;
}
else
in_template = 0;
/* If we're saving up tree structure, tie off the function now. */
if (!expand_p)
finish_stmt_tree (fndecl);
/* This must come after expand_function_end because cleanups might
have declarations (from inline functions) that need to go into
@ -13880,7 +13838,7 @@ finish_function (lineno, flags, nested)
to the FUNCTION_DECL node itself. */
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
if (!in_template)
if (expand_p)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
@ -14285,12 +14243,6 @@ void
cplus_expand_expr_stmt (exp)
tree exp;
{
if (processing_template_decl)
{
add_tree (build_min_nt (EXPR_STMT, exp));
return;
}
/* Arrange for all temps to disappear. */
expand_start_target_temps ();
@ -14324,28 +14276,30 @@ cplus_expand_expr_stmt (exp)
expand_end_target_temps ();
}
/* When a stmt has been parsed, this function is called.
Currently, this function only does something within a
constructor's scope: if a stmt has just assigned to this,
and we are in a derived class, we call `emit_base_init'. */
/* When a stmt has been parsed, this function is called. */
void
finish_stmt ()
{
if (current_function_assigns_this
|| ! current_function_just_assigned_this)
return;
if (DECL_CONSTRUCTOR_P (current_function_decl))
if (!current_function_assigns_this
&& current_function_just_assigned_this)
{
/* Constructors must wait until we are out of control
zones before calling base constructors. */
if (in_control_zone_p ())
return;
expand_expr_stmt (base_init_expr);
check_base_init (current_class_type);
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
/* Constructors must wait until we are out of control
zones before calling base constructors. */
if (in_control_zone_p ())
return;
expand_expr_stmt (base_init_expr);
check_base_init (current_class_type);
}
current_function_assigns_this = 1;
}
current_function_assigns_this = 1;
/* 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;
}
/* Change a static member function definition into a FUNCTION_TYPE, instead
@ -14408,6 +14362,9 @@ struct cp_function
struct binding_level *binding_level;
int static_labelno;
int in_function_try_handler;
int expanding_p;
tree last_tree;
tree last_expr_type;
};
static struct cp_function *cp_function_chain;
@ -14451,6 +14408,13 @@ push_cp_function_context (context)
p->current_class_ref = current_class_ref;
p->static_labelno = static_labelno;
p->in_function_try_handler = in_function_try_handler;
p->last_tree = last_tree;
p->last_expr_type = last_expr_type;
p->expanding_p = expanding_p;
/* For now, we always assume we're expanding all the way to RTL
unless we're explicitly doing otherwise. */
expanding_p = 1;
}
/* Restore the variables used during compilation of a C++ function. */
@ -14494,6 +14458,9 @@ pop_cp_function_context (context)
current_class_ref = p->current_class_ref;
static_labelno = p->static_labelno;
in_function_try_handler = p->in_function_try_handler;
last_tree = p->last_tree;
last_expr_type = p->last_expr_type;
expanding_p = p->expanding_p;
free (p);
}

View File

@ -2001,27 +2001,6 @@ constructor_name (thing)
return t;
}
/* Cache the value of this class's main virtual function table pointer
in a register variable. This will save one indirection if a
more than one virtual function call is made this function. */
void
setup_vtbl_ptr ()
{
extern tree base_init_expr;
if (base_init_expr == 0
&& DECL_CONSTRUCTOR_P (current_function_decl))
{
if (processing_template_decl)
add_tree (build_min_nt
(CTOR_INITIALIZER,
current_member_init_list, current_base_init_list));
else
emit_base_init (current_class_type, 0);
}
}
/* Record the existence of an addressable inline function. */
void

View File

@ -1780,6 +1780,12 @@ dump_expr (t, nop)
dump_decl (t, 0);
break;
case STMT_EXPR:
/* We don't yet have a way of dumping statements in a
human-readable format. */
OB_PUTS ("{ ... }");
break;
case BIND_EXPR:
OB_PUTS ("{ ");
dump_expr (TREE_OPERAND (t, 1), nop);

View File

@ -558,17 +558,14 @@ expand_start_catch_block (declspecs, declarator)
{
tree decl;
if (processing_template_decl)
if (building_stmt_tree ())
{
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
1, NULL_TREE);
pushdecl (decl);
decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
copy_to_permanent (declspecs),
NULL_TREE);
add_tree (decl);
add_decl_stmt (decl);
}
return;
}
@ -579,7 +576,6 @@ expand_start_catch_block (declspecs, declarator)
process_start_catch_block (declspecs, declarator);
}
/* This function performs the expand_start_catch_block functionality for
exceptions implemented in the new style. __throw determines whether
a handler needs to be called or not, so the handler itself has to do

View File

@ -246,6 +246,15 @@ cplus_expand_expr (exp, target, tmode, modifier)
case NEW_EXPR:
return expand_expr (build_new_1 (exp), target, tmode, modifier);
case STMT_EXPR:
{
tree rtl_expr = begin_stmt_expr ();
tree block = expand_stmt (STMT_EXPR_STMT (exp));
finish_stmt_expr (rtl_expr, block);
return expand_expr (rtl_expr, target, tmode, modifier);
}
break;
default:
break;
}
@ -388,12 +397,6 @@ do_case (start, end)
if (end && pedantic)
pedwarn ("ANSI C++ forbids range expressions in switch statement");
if (processing_template_decl)
{
add_tree (build_min_nt (CASE_LABEL, start, end));
return;
}
if (start)
value1 = check_cp_case_value (start);
if (end)

View File

@ -4912,15 +4912,15 @@ case 122:
break;}
case 123:
#line 770 "parse.y"
{ store_return_init (yyval.ttype, yyvsp[0].ttype); ;
{ finish_named_return_value (yyval.ttype, yyvsp[0].ttype); ;
break;}
case 124:
#line 772 "parse.y"
{ store_return_init (yyval.ttype, yyvsp[-1].ttype); ;
{ finish_named_return_value (yyval.ttype, yyvsp[-1].ttype); ;
break;}
case 125:
#line 774 "parse.y"
{ store_return_init (yyval.ttype, NULL_TREE); ;
{ finish_named_return_value (yyval.ttype, NULL_TREE); ;
break;}
case 126:
#line 779 "parse.y"
@ -7732,7 +7732,7 @@ case 783:
break;}
case 784:
#line 3411 "parse.y"
{ if (yyvsp[-1].ttype) cplus_expand_expr_stmt (yyvsp[-1].ttype); ;
{ finish_expr_stmt (yyvsp[-1].ttype); ;
break;}
case 786:
#line 3414 "parse.y"

View File

@ -767,11 +767,11 @@ return_id:
return_init:
return_id maybe_init
{ store_return_init ($<ttype>$, $2); }
{ finish_named_return_value ($<ttype>$, $2); }
| return_id '(' nonnull_exprlist ')'
{ store_return_init ($<ttype>$, $3); }
{ finish_named_return_value ($<ttype>$, $3); }
| return_id LEFT_RIGHT
{ store_return_init ($<ttype>$, NULL_TREE); }
{ finish_named_return_value ($<ttype>$, NULL_TREE); }
;
base_init:
@ -3408,7 +3408,7 @@ label_colon:
for.init.statement:
xexpr ';'
{ if ($1) cplus_expand_expr_stmt ($1); }
{ finish_expr_stmt ($1); }
| decl
| '{' compstmtend
{ if (pedantic)

View File

@ -6839,35 +6839,6 @@ tsubst (t, args, complain, in_decl)
}
}
void
do_pushlevel ()
{
emit_line_note (input_filename, lineno);
pushlevel (0);
clear_last_expr ();
push_momentary ();
expand_start_bindings (0);
}
tree
do_poplevel ()
{
tree t;
int saved_warn_unused = 0;
if (processing_template_decl)
{
saved_warn_unused = warn_unused;
warn_unused = 0;
}
expand_end_bindings (getdecls (), kept_level_p (), 0);
if (processing_template_decl)
warn_unused = saved_warn_unused;
t = poplevel (kept_level_p (), 1, 0);
pop_momentary ();
return t;
}
/* Like tsubst, but deals with expressions. This function just replaces
template parms; to finish processing the resultant expression, use
tsubst_expr. */
@ -7083,7 +7054,21 @@ tsubst_copy (t, args, complain, in_decl)
NULL_TREE);
}
case BIND_EXPR:
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.
Instead, it simply calls build_expr_from_tree. So, we need
to expand the STMT_EXPR here. */
if (!processing_template_decl)
{
tree rtl_expr = begin_stmt_expr ();
tree block = tsubst_expr (STMT_EXPR_STMT (t), args,
complain, in_decl);
r = finish_stmt_expr (rtl_expr, block);
}
return r;
case COND_EXPR:
case MODOP_EXPR:
{
@ -7091,21 +7076,6 @@ tsubst_copy (t, args, complain, in_decl)
(code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
if (code == BIND_EXPR && !processing_template_decl)
{
/* 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. Instead, it simply calls
build_expr_from_tree. So, we need to expand the
BIND_EXPR here. */
tree rtl_expr = begin_stmt_expr ();
tree block = tsubst_expr (TREE_OPERAND (r, 1), args,
complain, in_decl);
r = finish_stmt_expr (rtl_expr, block);
}
return r;
}
@ -7218,7 +7188,7 @@ tsubst_copy (t, args, complain, in_decl)
}
}
/* Like tsubst_copy, but also does semantic processing and RTL expansion. */
/* Like tsubst_copy, but also does semantic processing. */
tree
tsubst_expr (t, args, complain, in_decl)
@ -7226,6 +7196,8 @@ tsubst_expr (t, args, complain, in_decl)
int complain;
tree in_decl;
{
tree stmt;
if (t == NULL_TREE || t == error_mark_node)
return t;
@ -7234,6 +7206,22 @@ tsubst_expr (t, args, complain, in_decl)
switch (TREE_CODE (t))
{
case RETURN_INIT:
finish_named_return_value
(TREE_OPERAND (t, 0),
tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl));
tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
case CTOR_INITIALIZER:
current_member_init_list
= tsubst_expr_values (TREE_OPERAND (t, 0), args);
current_base_init_list
= tsubst_expr_values (TREE_OPERAND (t, 1), args);
setup_vtbl_ptr ();
tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
case RETURN_STMT:
lineno = STMT_LINENO (t);
finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
@ -7253,18 +7241,19 @@ tsubst_expr (t, args, complain, in_decl)
tree init;
lineno = STMT_LINENO (t);
emit_line_note (input_filename, lineno);
decl = DECL_STMT_DECL (t);
init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl);
DECL_INITIAL (decl) = init;
maybe_push_decl (decl);
/* By marking the declaration as instantiated, we avoid trying
to instantiate it. Since instantiate_decl can't handle
local variables, and since we've already done all that
needs to be done, that's the right thing to do. */
if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1;
start_decl_1 (decl);
cp_finish_decl
(decl, init, NULL_TREE, 0, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
maybe_push_decl (decl);
add_decl_stmt (decl);
resume_momentary (i);
return decl;
}
@ -7274,41 +7263,41 @@ tsubst_expr (t, args, complain, in_decl)
tree tmp;
lineno = STMT_LINENO (t);
begin_for_stmt ();
stmt = begin_for_stmt ();
for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
tsubst_expr (tmp, args, complain, in_decl);
finish_for_init_stmt (NULL_TREE);
finish_for_init_stmt (stmt);
finish_for_cond (tsubst_expr (FOR_COND (t), args,
complain, in_decl),
NULL_TREE);
stmt);
tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
finish_for_expr (tmp, NULL_TREE);
finish_for_expr (tmp, stmt);
tsubst_expr (FOR_BODY (t), args, complain, in_decl);
finish_for_stmt (tmp, NULL_TREE);
finish_for_stmt (tmp, stmt);
}
break;
case WHILE_STMT:
{
lineno = STMT_LINENO (t);
begin_while_stmt ();
stmt = begin_while_stmt ();
finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
args, complain, in_decl),
NULL_TREE);
stmt);
tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
finish_while_stmt (NULL_TREE);
finish_while_stmt (stmt);
}
break;
case DO_STMT:
{
lineno = STMT_LINENO (t);
begin_do_stmt ();
stmt = begin_do_stmt ();
tsubst_expr (DO_BODY (t), args, complain, in_decl);
finish_do_body (NULL_TREE);
finish_do_body (stmt);
finish_do_stmt (tsubst_expr (DO_COND (t), args,
complain, in_decl),
NULL_TREE);
stmt);
}
break;
@ -7317,22 +7306,22 @@ tsubst_expr (t, args, complain, in_decl)
tree tmp;
lineno = STMT_LINENO (t);
begin_if_stmt ();
stmt = begin_if_stmt ();
finish_if_stmt_cond (tsubst_expr (IF_COND (t),
args, complain, in_decl),
NULL_TREE);
stmt);
if (tmp = THEN_CLAUSE (t), tmp)
{
tsubst_expr (tmp, args, complain, in_decl);
finish_then_clause (NULL_TREE);
finish_then_clause (stmt);
}
if (tmp = ELSE_CLAUSE (t), tmp)
{
begin_else_clause ();
tsubst_expr (tmp, args, complain, in_decl);
finish_else_clause (NULL_TREE);
finish_else_clause (stmt);
}
finish_if_stmt ();
@ -7344,13 +7333,12 @@ tsubst_expr (t, args, complain, in_decl)
tree substmt;
lineno = STMT_LINENO (t);
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
for (substmt = COMPOUND_BODY (t);
substmt != NULL_TREE;
substmt = TREE_CHAIN (substmt))
tsubst_expr (substmt, args, complain, in_decl);
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
}
break;
@ -7366,17 +7354,14 @@ tsubst_expr (t, args, complain, in_decl)
case SWITCH_STMT:
{
tree val, tmp;
tree val;
lineno = STMT_LINENO (t);
begin_switch_stmt ();
val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
finish_switch_cond (val);
if (tmp = TREE_OPERAND (t, 1), tmp)
tsubst_expr (tmp, args, complain, in_decl);
finish_switch_stmt (val, NULL_TREE);
stmt = finish_switch_cond (val);
tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
finish_switch_stmt (val, stmt);
}
break;
@ -7414,20 +7399,20 @@ tsubst_expr (t, args, complain, in_decl)
case TRY_BLOCK:
lineno = STMT_LINENO (t);
begin_try_block ();
stmt = begin_try_block ();
tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
finish_try_block (NULL_TREE);
finish_try_block (stmt);
{
tree handler = TRY_HANDLERS (t);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, complain, in_decl);
}
finish_handler_sequence (NULL_TREE);
finish_handler_sequence (stmt);
break;
case HANDLER:
lineno = STMT_LINENO (t);
begin_handler ();
stmt = begin_handler ();
if (HANDLER_PARMS (t))
{
tree d = HANDLER_PARMS (t);
@ -7437,9 +7422,9 @@ tsubst_expr (t, args, complain, in_decl)
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
finish_handler_parms (NULL_TREE);
finish_handler_parms (stmt);
tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
finish_handler (NULL_TREE);
finish_handler (stmt);
break;
case TAG_DEFN:
@ -9654,57 +9639,39 @@ instantiate_decl (d)
}
else if (TREE_CODE (d) == FUNCTION_DECL)
{
tree t = DECL_SAVED_TREE (code_pattern);
tree try_block = NULL_TREE;
extern struct obstack *saveable_obstack;
extern struct obstack *rtl_obstack;
int saved_expanding_p = expanding_p;
/* We're not expanding all the way to RTL here. */
expanding_p = 0;
/* Set up context. */
start_function (NULL_TREE, d, NULL_TREE, 1);
store_parm_decls ();
if (t && TREE_CODE (t) == TRY_BLOCK)
{
try_block = t;
begin_function_try_block ();
t = TRY_STMTS (try_block);
}
if (t && TREE_CODE (t) == RETURN_INIT)
{
store_return_init
(TREE_OPERAND (t, 0),
tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, tmpl));
t = TREE_CHAIN (t);
}
if (t && TREE_CODE (t) == CTOR_INITIALIZER)
{
current_member_init_list
= tsubst_expr_values (TREE_OPERAND (t, 0), args);
current_base_init_list
= tsubst_expr_values (TREE_OPERAND (t, 1), args);
t = TREE_CHAIN (t);
}
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost
pair of curly braces of a function. These are needed
for correct operation of dwarfout.c. */
keep_next_level ();
my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
tsubst_expr (t, args, /*complain=*/1, tmpl);
if (try_block)
{
finish_function_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (try_block);
for (; handler; handler = TREE_CHAIN (handler))
tsubst_expr (handler, args, /*complain=*/1, tmpl);
}
finish_function_handler_sequence (NULL_TREE);
}
/* Anything we might
want to save is going to have to be saved forever. Note that
we don't want to save all kinds of temporary clutter that
might end up on the temporary obstack so we don't want to
call push_permanent_obstack. */
push_obstacks_nochange ();
saveable_obstack = &permanent_obstack;
/* We only need this because of the cases where we generate
RTL_EXPRs. We should really be generating RTL_EXPRs until
final expansion time; when that is fixed, this can go. */
rtl_obstack = &permanent_obstack;
/* Substitute into the body of the function. */
tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
/*complain=*/1, tmpl);
/* Clean up. */
pop_obstacks ();
finish_function (lineno, 0, nested);
expanding_p = saved_expanding_p;
/* Now, generate RTL for the function. */
expand_body (d);
}
out:

View File

@ -41,6 +41,18 @@
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));
/* Non-zero if we should generate RTL for functions that we process.
When this is zero, we just accumulate tree structure, without
interacting with the back end. */
int expanding_p = 1;
/* The type of the last expression-statement we have seen. This is
required because the type of a statement-expression is the type of
the last expression statement. */
tree last_expr_type;
/* When parsing a template, 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
@ -68,7 +80,9 @@ finish_expr_stmt (expr)
{
if (expr != NULL_TREE)
{
if (!processing_template_decl)
if (building_stmt_tree ())
add_tree (build_min_nt (EXPR_STMT, expr));
else
{
emit_line_note (input_filename, lineno);
/* Do default conversion if safe and possibly important,
@ -77,13 +91,17 @@ finish_expr_stmt (expr)
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr);
cplus_expand_expr_stmt (expr);
}
cplus_expand_expr_stmt (expr);
clear_momentary ();
}
finish_stmt ();
/* This was an expression-statement, so we save the type of the
expression. */
last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
}
/* Begin an if-statement. Returns a newly created IF_STMT if
@ -94,7 +112,7 @@ begin_if_stmt ()
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_tree (r);
@ -115,7 +133,7 @@ finish_if_stmt_cond (cond, if_stmt)
tree cond;
tree if_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
{
if (last_tree != if_stmt)
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
@ -136,7 +154,7 @@ tree
finish_then_clause (if_stmt)
tree if_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
{
RECHAIN_STMTS_FROM_CHAIN (if_stmt,
THEN_CLAUSE (if_stmt));
@ -152,7 +170,7 @@ finish_then_clause (if_stmt)
void
begin_else_clause ()
{
if (!processing_template_decl)
if (!building_stmt_tree ())
expand_start_else ();
}
@ -163,7 +181,7 @@ void
finish_else_clause (if_stmt)
tree if_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
}
@ -172,7 +190,7 @@ finish_else_clause (if_stmt)
void
finish_if_stmt ()
{
if (!processing_template_decl)
if (!building_stmt_tree ())
expand_end_cond ();
do_poplevel ();
@ -187,7 +205,7 @@ begin_while_stmt ()
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
@ -213,11 +231,10 @@ finish_while_stmt_cond (cond, while_stmt)
tree cond;
tree while_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
{
if (last_tree != while_stmt)
RECHAIN_STMTS_FROM_LAST (while_stmt,
WHILE_COND (while_stmt));
RECHAIN_STMTS_FROM_LAST (while_stmt, WHILE_COND (while_stmt));
else
TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
}
@ -245,7 +262,7 @@ finish_while_stmt (while_stmt)
{
do_poplevel ();
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
else
expand_end_loop ();
@ -258,7 +275,7 @@ finish_while_stmt (while_stmt)
tree
begin_do_stmt ()
{
if (processing_template_decl)
if (building_stmt_tree ())
{
tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
@ -279,7 +296,7 @@ void
finish_do_body (do_stmt)
tree do_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
else
expand_loop_continue_here ();
@ -293,7 +310,7 @@ finish_do_stmt (cond, do_stmt)
tree cond;
tree do_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
DO_COND (do_stmt) = copy_to_permanent (cond);
else
{
@ -313,8 +330,14 @@ void
finish_return_stmt (expr)
tree expr;
{
emit_line_note (input_filename, lineno);
c_expand_return (expr);
if (building_stmt_tree ())
add_tree (build_min_nt (RETURN_STMT, expr));
else
{
emit_line_note (input_filename, lineno);
c_expand_return (expr);
}
finish_stmt ();
}
@ -325,7 +348,7 @@ begin_for_stmt ()
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
@ -350,7 +373,7 @@ void
finish_for_init_stmt (for_stmt)
tree for_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
@ -373,7 +396,7 @@ finish_for_cond (cond, for_stmt)
tree cond;
tree for_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
@ -405,8 +428,8 @@ finish_for_expr (expr, for_stmt)
tree expr;
tree for_stmt;
{
if (processing_template_decl)
FOR_EXPR (for_stmt) = expr;
if (building_stmt_tree ())
FOR_EXPR (for_stmt) = copy_to_permanent (expr);
/* Don't let the tree nodes for EXPR be discarded
by clear_momentary during the parsing of the next stmt. */
@ -425,7 +448,7 @@ finish_for_stmt (expr, for_stmt)
/* Pop the scope for the body of the loop. */
do_poplevel ();
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
else
{
@ -450,7 +473,7 @@ void
finish_break_stmt ()
{
emit_line_note (input_filename, lineno);
if (processing_template_decl)
if (building_stmt_tree ())
add_tree (build_min_nt (BREAK_STMT));
else if ( ! expand_exit_something ())
cp_error ("break statement not within loop or switch");
@ -462,7 +485,7 @@ void
finish_continue_stmt ()
{
emit_line_note (input_filename, lineno);
if (processing_template_decl)
if (building_stmt_tree ())
add_tree (build_min_nt (CONTINUE_STMT));
else if (! expand_continue_loop (0))
cp_error ("continue statement not within a loop");
@ -485,7 +508,7 @@ finish_switch_cond (cond)
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
add_tree (r);
@ -521,7 +544,7 @@ finish_switch_stmt (cond, switch_stmt)
tree cond;
tree switch_stmt;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
else
expand_end_case (cond);
@ -538,17 +561,22 @@ finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
if (building_stmt_tree ())
{
add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
return;
}
do_case (low_value, high_value);
}
/* Finish a goto-statement. */
void
finish_goto_stmt (destination)
tree destination;
{
if (processing_template_decl)
if (building_stmt_tree ())
add_tree (build_min_nt (GOTO_STMT, destination));
else
{
@ -571,7 +599,7 @@ finish_goto_stmt (destination)
tree
begin_try_block ()
{
if (processing_template_decl)
if (building_stmt_tree ())
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
@ -591,7 +619,7 @@ begin_try_block ()
tree
begin_function_try_block ()
{
if (processing_template_decl)
if (building_stmt_tree ())
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
@ -613,12 +641,10 @@ void
finish_try_block (try_block)
tree try_block;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
{
expand_start_all_catch ();
}
expand_start_all_catch ();
}
/* Likewise, for a function-try-block. */
@ -627,7 +653,7 @@ void
finish_function_try_block (try_block)
tree try_block;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
{
@ -644,7 +670,7 @@ void
finish_handler_sequence (try_block)
tree try_block;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
@ -658,7 +684,7 @@ void
finish_function_handler_sequence (try_block)
tree try_block;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
@ -674,7 +700,7 @@ begin_handler ()
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
add_tree (r);
@ -694,7 +720,7 @@ void
finish_handler_parms (handler)
tree handler;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
}
@ -704,7 +730,7 @@ void
finish_handler (handler)
tree handler;
{
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
else
expand_end_catch_block ();
@ -722,7 +748,7 @@ begin_compound_stmt (has_no_scope)
{
tree r;
if (processing_template_decl)
if (building_stmt_tree ())
{
r = build_min_nt (COMPOUND_STMT, NULL_TREE);
add_tree (r);
@ -732,6 +758,8 @@ begin_compound_stmt (has_no_scope)
else
r = NULL_TREE;
last_expr_type = NULL_TREE;
if (!has_no_scope)
do_pushlevel ();
@ -749,17 +777,24 @@ finish_compound_stmt (has_no_scope, compound_stmt)
tree compound_stmt;
{
tree r;
tree t;
if (!has_no_scope)
r = do_poplevel ();
else
r = NULL_TREE;
if (processing_template_decl)
if (building_stmt_tree ())
RECHAIN_STMTS_FROM_CHAIN (compound_stmt,
COMPOUND_BODY (compound_stmt));
/* When we call finish_stmt we will lost 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;
finish_stmt ();
last_expr_type = t;
return r;
}
@ -779,14 +814,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
{
if (TREE_CHAIN (string))
{
if (processing_template_decl)
if (building_stmt_tree ())
/* We need to build the combined string on the permanent
obstack so that we can use it during instantiations. */
push_permanent_obstack ();
string = combine_strings (string);
if (processing_template_decl)
if (building_stmt_tree ())
pop_obstacks ();
}
@ -798,7 +833,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
cv_qualifier = NULL_TREE;
}
if (processing_template_decl)
if (building_stmt_tree ())
{
tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
@ -837,7 +872,7 @@ finish_label_stmt (name)
{
tree decl;
if (processing_template_decl)
if (building_stmt_tree ())
{
push_permanent_obstack ();
decl = build_decl (LABEL_DECL, name, void_type_node);
@ -869,6 +904,111 @@ add_decl_stmt (decl)
add_tree (decl_stmt);
}
/* Bind a name and initialization to the return value of
the current function. */
void
finish_named_return_value (return_id, init)
tree return_id, init;
{
tree decl = DECL_RESULT (current_function_decl);
if (pedantic)
/* Give this error as many times as there are occurrences,
so that users can use Emacs compilation buffers to find
and fix all such places. */
pedwarn ("ANSI C++ does not permit named return values");
if (return_id != NULL_TREE)
{
if (DECL_NAME (decl) == NULL_TREE)
{
DECL_NAME (decl) = return_id;
DECL_ASSEMBLER_NAME (decl) = return_id;
}
else
{
cp_error ("return identifier `%D' already in place", return_id);
return;
}
}
/* Can't let this happen for constructors. */
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
error ("can't redefine default return value for constructors");
return;
}
/* If we have a named return value, put that in our scope as well. */
if (DECL_NAME (decl) != NULL_TREE)
{
/* Let `cp_finish_decl' know that this initializer is ok. */
DECL_INITIAL (decl) = init;
pushdecl (decl);
if (building_stmt_tree ())
add_tree (build_min_nt (RETURN_INIT, return_id,
copy_to_permanent (init)));
else
{
cp_finish_decl (decl, init, NULL_TREE, 0, 0);
store_return_init (decl);
}
}
}
/* Cache the value of this class's main virtual function table pointer
in a register variable. This will save one indirection if a
more than one virtual function call is made this function. */
void
setup_vtbl_ptr ()
{
extern tree base_init_expr;
if (base_init_expr == 0
&& DECL_CONSTRUCTOR_P (current_function_decl))
{
if (building_stmt_tree ())
add_tree (build_min_nt
(CTOR_INITIALIZER,
current_member_init_list, current_base_init_list));
else
emit_base_init (current_class_type, 0);
}
}
/* Begin a new scope. */
void
do_pushlevel ()
{
if (!building_stmt_tree ())
{
emit_line_note (input_filename, lineno);
clear_last_expr ();
}
pushlevel (0);
push_momentary ();
if (!building_stmt_tree ())
expand_start_bindings (0);
}
/* Finish a scope. */
tree
do_poplevel ()
{
tree t;
if (!building_stmt_tree ())
expand_end_bindings (getdecls (), kept_level_p (), 0);
t = poplevel (kept_level_p (), 1, 0);
pop_momentary ();
return t;
}
/* Finish a parenthesized expression EXPR. */
tree
@ -889,11 +1029,11 @@ tree
begin_stmt_expr ()
{
keep_next_level ();
/* If we're processing_template_decl, then the upcoming compound
/* If we're building a statement tree, then the upcoming compound
statement will be chained onto the tree structure, starting at
last_tree. We return last_tree so that we can later unhook the
compound statement. */
return processing_template_decl ? last_tree : expand_start_stmt_expr();
return building_stmt_tree () ? last_tree : expand_start_stmt_expr();
}
/* Finish a statement-expression. RTL_EXPR should be the value
@ -908,7 +1048,7 @@ finish_stmt_expr (rtl_expr, expr)
{
tree result;
if (!processing_template_decl)
if (!building_stmt_tree ())
{
rtl_expr = expand_end_stmt_expr (rtl_expr);
/* The statements have side effects, so the group does. */
@ -917,26 +1057,29 @@ finish_stmt_expr (rtl_expr, expr)
if (TREE_CODE (expr) == BLOCK)
{
/* Make a BIND_EXPR for the BLOCK already made. */
if (processing_template_decl)
result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
NULL_TREE);
/* Make a CP_BIND_EXPR for the BLOCK already made. */
if (building_stmt_tree ())
{
result = build_min (STMT_EXPR, last_expr_type, last_tree);
/* FIXME: Do we need this? */
TREE_SIDE_EFFECTS (result) = 1;
}
else
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
/* Remove the block from the tree at this point.
It gets put back at the proper place
when the BIND_EXPR is expanded. */
/* Remove the block from the tree at this point. It gets put
back at the proper place when the STMT_EXPR or BIND_EXPR is
expanded. */
delete_block (expr);
}
else
result = expr;
if (processing_template_decl)
if (building_stmt_tree ())
{
/* Remove the compound statement from the tree structure; it is
now saved in the BIND_EXPR. */
now saved in the STMT_EXPR. */
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
}
@ -1746,3 +1889,300 @@ finish_typeof (expr)
return TREE_TYPE (expr);
}
/* Create an empty statement tree for FN. */
void
begin_stmt_tree (fn)
tree fn;
{
/* 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. */
DECL_SAVED_TREE (fn) = build_nt (EXPR_STMT, void_zero_node);
last_tree = DECL_SAVED_TREE (fn);
last_expr_type = NULL_TREE;
}
/* Finish the statement tree for FN. */
void
finish_stmt_tree (fn)
tree fn;
{
DECL_SAVED_TREE (fn) = TREE_CHAIN (DECL_SAVED_TREE (fn));
}
/* 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. */
tree
expand_stmt (t)
tree t;
{
if (t == NULL_TREE || t == error_mark_node)
return NULL_TREE;
switch (TREE_CODE (t))
{
case RETURN_STMT:
lineno = STMT_LINENO (t);
finish_return_stmt (RETURN_EXPR (t));
break;
case EXPR_STMT:
lineno = STMT_LINENO (t);
finish_expr_stmt (EXPR_STMT_EXPR (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);
/* 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);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
resume_momentary (i);
}
break;
case FOR_STMT:
{
tree tmp;
lineno = STMT_LINENO (t);
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 (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:
{
lineno = STMT_LINENO (t);
begin_while_stmt ();
finish_while_stmt_cond (WHILE_COND (t), NULL_TREE);
expand_stmt (WHILE_BODY (t));
finish_while_stmt (NULL_TREE);
}
break;
case DO_STMT:
{
lineno = STMT_LINENO (t);
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:
lineno = STMT_LINENO (t);
begin_if_stmt ();
finish_if_stmt_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:
lineno = STMT_LINENO (t);
begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
expand_stmts (COMPOUND_BODY (t));
return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t),
NULL_TREE);
case BREAK_STMT:
lineno = STMT_LINENO (t);
finish_break_stmt ();
break;
case CONTINUE_STMT:
lineno = STMT_LINENO (t);
finish_continue_stmt ();
break;
case SWITCH_STMT:
lineno = STMT_LINENO (t);
begin_switch_stmt ();
finish_switch_cond (SWITCH_COND (t));
if (TREE_OPERAND (t, 1))
expand_stmt (SWITCH_BODY (t));
finish_switch_stmt (SWITCH_COND (t), NULL_TREE);
break;
case CASE_LABEL:
finish_case_label (CASE_LOW (t), CASE_HIGH (t));
break;
case LABEL_DECL:
t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
DECL_NAME (t));
if (t)
expand_label (t);
break;
case GOTO_STMT:
lineno = STMT_LINENO (t);
finish_goto_stmt (GOTO_DESTINATION (t));
break;
case ASM_STMT:
lineno = STMT_LINENO (t);
finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS
(t), ASM_INPUTS (t), ASM_CLOBBERS (t));
break;
case TRY_BLOCK:
lineno = STMT_LINENO (t);
begin_try_block ();
expand_stmt (TRY_STMTS (t));
finish_try_block (NULL_TREE);
expand_stmts (TRY_HANDLERS (t));
finish_handler_sequence (NULL_TREE);
break;
case HANDLER:
lineno = STMT_LINENO (t);
begin_handler ();
if (HANDLER_PARMS (t))
{
tree d = HANDLER_PARMS (t);
expand_start_catch_block (TREE_OPERAND (d, 1),
TREE_OPERAND (d, 0));
}
else
expand_start_catch_block (NULL_TREE, NULL_TREE);
finish_handler_parms (NULL_TREE);
expand_stmt (HANDLER_BODY (t));
finish_handler (NULL_TREE);
break;
default:
my_friendly_abort (19990810);
break;
}
return NULL_TREE;
}
/* Generate RTL for FN. */
void
expand_body (fn)
tree fn;
{
int saved_expanding_p;
int nested;
tree t;
tree try_block;
/* Remember whether we're already processing a function definition
so that we can tell finish_function. */
nested = in_function_p ();
/* Let the compiler know that now is the time to really generate
actualy RTL. */
saved_expanding_p = expanding_p;
expanding_p = 1;
start_function (NULL_TREE, fn, NULL_TREE, 1);
store_parm_decls ();
/* There are a few things that we do not handle recursively. For
example, a function try-block is handled differently from an
ordinary try-block, so we must handle it here. */
t = DECL_SAVED_TREE (fn);
try_block = NULL_TREE;
if (t && TREE_CODE (t) == TRY_BLOCK)
{
try_block = t;
begin_function_try_block ();
t = TRY_STMTS (try_block);
}
if (t && TREE_CODE (t) == RETURN_INIT)
{
/* Clear this out so that finish_named_return_value can set it
again. */
DECL_NAME (DECL_RESULT (fn)) = NULL_TREE;
finish_named_return_value (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
t = TREE_CHAIN (t);
}
if (t && TREE_CODE (t) == CTOR_INITIALIZER)
{
current_member_init_list = TREE_OPERAND (t, 0);
current_base_init_list = TREE_OPERAND (t, 1);
t = TREE_CHAIN (t);
}
/* If this is a constructor, we need to initialize our members and
base-classes. */
setup_vtbl_ptr ();
/* Always keep the BLOCK node associated with the outermost pair of
curly braces of a function. These are needed for correct
operation of dwarfout.c. */
keep_next_level ();
/* Expand the body. */
expand_stmt (t);
/* If there was a function try-block, expand the handlers. */
if (try_block)
{
finish_function_try_block (NULL_TREE);
{
tree handler = TRY_HANDLERS (try_block);
for (; handler; handler = TREE_CHAIN (handler))
expand_stmt (handler);
}
finish_function_handler_sequence (NULL_TREE);
}
finish_function (lineno, 0, nested);
/* Restore EXPANDING_P. */
expanding_p = saved_expanding_p;
}

View File

@ -412,15 +412,20 @@ build_cplus_method_type (basetype, rettype, argtypes)
ptype = build_pointer_type (basetype);
/* The actual arglist for this function includes a "hidden" argument
which is "this". Put it into the list of argument types. */
which is "this". Put it into the list of argument types. Make
sure that the new argument list is allocated on the same obstack
as the type. */
push_obstacks (TYPE_OBSTACK (t), TYPE_OBSTACK (t));
argtypes = tree_cons (NULL_TREE, ptype, argtypes);
TYPE_ARG_TYPES (t) = argtypes;
TREE_SIDE_EFFECTS (argtypes) = 1; /* Mark first argtype as "artificial". */
pop_obstacks ();
/* If we already have such a type, use the old one and free this one.
Note that it also frees up the above cons cell if found. */
hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
type_hash_list (argtypes);
t = type_hash_canon (hashcode, t);
if (TYPE_SIZE (t) == 0)
@ -1646,6 +1651,8 @@ search_tree (t, func)
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case CALL_EXPR:
case COMPOUND_EXPR:
case MODIFY_EXPR:
TRY (TREE_OPERAND (t, 0));
TRY (TREE_OPERAND (t, 1));
break;
@ -1657,6 +1664,7 @@ search_tree (t, func)
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
case LOOKUP_EXPR:
case THROW_EXPR:
TRY (TREE_OPERAND (t, 0));
break;
@ -1681,6 +1689,7 @@ search_tree (t, func)
break;
case BIND_EXPR:
case STMT_EXPR:
break;
case REAL_TYPE:
@ -1774,6 +1783,7 @@ mapcar (t, func)
tree (*func) PROTO((tree));
{
tree tmp;
enum tree_code code;
if (t == NULL_TREE)
return t;
@ -1785,6 +1795,24 @@ mapcar (t, func)
return tmp;
}
/* Handle some common cases up front. */
code = TREE_CODE (t);
if (TREE_CODE_CLASS (code) == '1')
{
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
}
else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
{
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
return t;
}
switch (TREE_CODE (t))
{
case ERROR_MARK:
@ -1871,40 +1899,8 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
return t;
case SAVE_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case MODIFY_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case TRUNC_MOD_EXPR:
case MIN_EXPR:
case MAX_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case LT_EXPR:
case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case CEIL_MOD_EXPR:
case FLOOR_MOD_EXPR:
case ROUND_MOD_EXPR:
case COMPOUND_EXPR:
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
@ -1913,6 +1909,8 @@ mapcar (t, func)
case SCOPE_REF:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
case COMPOUND_EXPR:
case MODIFY_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@ -1933,16 +1931,14 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = NULL_TREE;
return t;
case CONVERT_EXPR:
case SAVE_EXPR:
case ADDR_EXPR:
case INDIRECT_REF:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
case NON_LVALUE_EXPR:
case THROW_EXPR:
case STMT_EXPR:
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
@ -2009,19 +2005,19 @@ mapcar (t, func)
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case RTL_EXPR:
t = copy_node (t);
TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
return t;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
(mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func));
/* else fall through */
/* This list is incomplete, but should suffice for now.
It is very important that `sorry' not call
`report_error_function'. That could cause an infinite loop. */
default:
sorry ("initializer contains unrecognized tree code");
return error_mark_node;
default:
my_friendly_abort (19990815);
}
my_friendly_abort (107);
/* NOTREACHED */

View File

@ -197,6 +197,7 @@ require_complete_type_in_void (expr)
case EXIT_EXPR: /* have no return */
case LOOP_EXPR: /* have no return */
case BIND_EXPR: /* have no return */
case STMT_EXPR: /* have no return */
case THROW_EXPR: /* have no return */
case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
case CONVERT_EXPR: /* sometimes has a void type */
@ -6801,12 +6802,6 @@ c_expand_return (retval)
return;
}
if (processing_template_decl)
{
add_tree (build_min_nt (RETURN_STMT, retval));
return;
}
if (dtor_label)
{
if (retval)