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:
parent
63ebc27560
commit
558475f07c
|
@ -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.
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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));
|
||||
|
|
165
gcc/cp/decl.c
165
gcc/cp/decl.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
221
gcc/cp/pt.c
221
gcc/cp/pt.c
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue