Commit 24bef158 by Mark Mitchell Committed by Mark Mitchell

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

	* cp-tree.def (CLEANUP_STMT): New node.
	* cp-tree.h (language_function): Add name_declared.
	(current_function_name_declared): New macro.
	(CLEANUP_DECL): New macro.
	(CLEANUP_EXPR): Likewise.
	(emit_local_var): Likewise.
	(finish_decl_cleanup): New function.
	* cvt.c (build_up_reference): Simplify.
	(ocp_convert): Remove dead code.
	* decl.c (start_decl): Remove call to add_decl_stmt.
	(grok_reference_init): Adjust, to handle bindings temporaries to
	references.  Remove dead code.
	(initialize_local_var): Don't generate RTL for
	declarations here, or build cleanups here.  Don't fuss with
	obstacks.  Replace expand_start_target_temps calls with explicit
	setting of stms_are_full_exprs_p.
	(destroy_local_var): New function.
	(emit_local_var): Likewise.
	(cp_finish_decl): Use them, as appropriate.
	(start_function): Announce template functions.
	(store_parm_decls): Don't call declare_function_name here.
	(finish_stmt): Don't start emit base-initialization code when just
	building the statement-tree.
	* init.c (create_temporary_var): Move add_decl_stmt call ...
	(get_temp_regvar): Here.
	* pt.c (tsubst_expr): Make DECL_INITIAL look like what
	cp_finish_decl would expect.  Don't call add_decl_stmt.
	* semantics.c (begin_compound_stmt): Call declare_function_name,
	if appropriate.
	(finish_decl_cleanup): New function.
	(expand_stmt): Use emit_local_var to output variables.
	(expand_body): Set current_funtion_name_declared.

From-SVN: r29348
parent fcf6eeb6
1999-09-11 Mark Mitchell <mark@codesourcery.com>
* cp-tree.def (CLEANUP_STMT): New node.
* cp-tree.h (language_function): Add name_declared.
(current_function_name_declared): New macro.
(CLEANUP_DECL): New macro.
(CLEANUP_EXPR): Likewise.
(emit_local_var): Likewise.
(finish_decl_cleanup): New function.
* cvt.c (build_up_reference): Simplify.
(ocp_convert): Remove dead code.
* decl.c (start_decl): Remove call to add_decl_stmt.
(grok_reference_init): Adjust, to handle bindings temporaries to
references. Remove dead code.
(initialize_local_var): Don't generate RTL for
declarations here, or build cleanups here. Don't fuss with
obstacks. Replace expand_start_target_temps calls with explicit
setting of stms_are_full_exprs_p.
(destroy_local_var): New function.
(emit_local_var): Likewise.
(cp_finish_decl): Use them, as appropriate.
(start_function): Announce template functions.
(store_parm_decls): Don't call declare_function_name here.
(finish_stmt): Don't start emit base-initialization code when just
building the statement-tree.
* init.c (create_temporary_var): Move add_decl_stmt call ...
(get_temp_regvar): Here.
* pt.c (tsubst_expr): Make DECL_INITIAL look like what
cp_finish_decl would expect. Don't call add_decl_stmt.
* semantics.c (begin_compound_stmt): Call declare_function_name,
if appropriate.
(finish_decl_cleanup): New function.
(expand_stmt): Use emit_local_var to output variables.
(expand_body): Set current_funtion_name_declared.
1999-09-10 Mark Mitchell <mark@codesourcery.com> 1999-09-10 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (finish_cleanup_try_block): New function. * cp-tree.h (finish_cleanup_try_block): New function.
......
...@@ -235,6 +235,10 @@ DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5) ...@@ -235,6 +235,10 @@ DEFTREECODE (ASM_STMT, "asm_stmt", 'e', 5)
run if an exception is thrown before the end of the enclosing run if an exception is thrown before the end of the enclosing
function. */ function. */
DEFTREECODE (SUBOBJECT, "subobject", 'e', 1) DEFTREECODE (SUBOBJECT, "subobject", 'e', 1)
/* A CLEANUP_STMT marks the point at which a declaration is fully
constructed. If, after this point, the CLEANUP_DECL goes out of
scope, the CLEANUP_EXPR must be run. */
DEFTREECODE (CLEANUP_STMT, "cleanup", 'e', 2)
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
DEFTREECODE (CASE_LABEL, "case_label", 'e', 2) DEFTREECODE (CASE_LABEL, "case_label", 'e', 2)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
......
...@@ -636,6 +636,7 @@ struct language_function ...@@ -636,6 +636,7 @@ struct language_function
int in_function_try_handler; int in_function_try_handler;
int x_expanding_p; int x_expanding_p;
int stmts_are_full_exprs_p; int stmts_are_full_exprs_p;
int name_declared;
struct named_label_list *x_named_label_uses; struct named_label_list *x_named_label_uses;
struct binding_level *bindings; struct binding_level *bindings;
...@@ -708,6 +709,12 @@ struct language_function ...@@ -708,6 +709,12 @@ struct language_function
#define current_function_parms_stored \ #define current_function_parms_stored \
cp_function_chain->parms_stored cp_function_chain->parms_stored
/* Non-zero if we have already declared __FUNCTION__ (and related
variables) in the current function. */
#define current_function_name_declared \
cp_function_chain->name_declared
/* Used to help generate temporary names which are unique within /* Used to help generate temporary names which are unique within
a function. Reset to 0 by start_function. */ a function. Reset to 0 by start_function. */
...@@ -2437,6 +2444,8 @@ extern int flag_new_for_scope; ...@@ -2437,6 +2444,8 @@ extern int flag_new_for_scope;
#define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0) #define DECL_STMT_DECL(NODE) TREE_OPERAND (NODE, 0)
#define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0) #define STMT_EXPR_STMT(NODE) TREE_OPERAND (NODE, 0)
#define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0) #define SUBOBJECT_CLEANUP(NODE) TREE_OPERAND (NODE, 0)
#define CLEANUP_DECL(NODE) TREE_OPERAND (NODE, 0)
#define CLEANUP_EXPR(NODE) TREE_OPERAND (NODE, 1)
#define LABEL_STMT_LABEL(NODE) TREE_OPERAND (NODE, 0) #define LABEL_STMT_LABEL(NODE) TREE_OPERAND (NODE, 0)
/* Nonzero for an ASM_STMT if the assembly statement is volatile. */ /* Nonzero for an ASM_STMT if the assembly statement is volatile. */
...@@ -3237,6 +3246,7 @@ extern int wrapup_globals_for_namespace PROTO((tree, void *)); ...@@ -3237,6 +3246,7 @@ extern int wrapup_globals_for_namespace PROTO((tree, void *));
extern tree cp_namespace_decls PROTO((tree)); extern tree cp_namespace_decls PROTO((tree));
extern tree create_implicit_typedef PROTO((tree, tree)); extern tree create_implicit_typedef PROTO((tree, tree));
extern tree maybe_push_decl PROTO((tree)); extern tree maybe_push_decl PROTO((tree));
extern void emit_local_var PROTO((tree));
/* in decl2.c */ /* in decl2.c */
extern void init_decl2 PROTO((void)); extern void init_decl2 PROTO((void));
...@@ -3651,6 +3661,7 @@ extern void finish_member_declaration PROTO((tree)); ...@@ -3651,6 +3661,7 @@ extern void finish_member_declaration PROTO((tree));
extern void check_multiple_declarators PROTO((void)); extern void check_multiple_declarators PROTO((void));
extern tree finish_typeof PROTO((tree)); extern tree finish_typeof PROTO((tree));
extern void add_decl_stmt PROTO((tree)); extern void add_decl_stmt PROTO((tree));
extern void finish_decl_cleanup PROTO((tree, tree));
extern void finish_named_return_value PROTO((tree, tree)); extern void finish_named_return_value PROTO((tree, tree));
extern tree expand_stmt PROTO((tree)); extern tree expand_stmt PROTO((tree));
extern void expand_body PROTO((tree)); extern void expand_body PROTO((tree));
......
...@@ -345,8 +345,6 @@ build_up_reference (type, arg, flags) ...@@ -345,8 +345,6 @@ build_up_reference (type, arg, flags)
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg)) if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{ {
tree compound_stmt;
/* Create a new temporary variable. */ /* Create a new temporary variable. */
tree targ = arg; tree targ = arg;
if (toplevel_bindings_p ()) if (toplevel_bindings_p ())
...@@ -355,25 +353,12 @@ build_up_reference (type, arg, flags) ...@@ -355,25 +353,12 @@ build_up_reference (type, arg, flags)
{ {
arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype)); arg = pushdecl (build_decl (VAR_DECL, NULL_TREE, argtype));
DECL_ARTIFICIAL (arg) = 1; DECL_ARTIFICIAL (arg) = 1;
/* Generate code to initialize it. We wrap it in a
statement-expression so that when we are building a
statement-tree we will have a representation of this
declaration. */
begin_init_stmts (&stmt_expr, &compound_stmt);
} }
/* Process the initializer for the declaration. */ /* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ; DECL_INITIAL (arg) = targ;
cp_finish_decl (arg, targ, NULL_TREE, 0, cp_finish_decl (arg, targ, NULL_TREE, 0,
LOOKUP_ONLYCONVERTING|DIRECT_BIND); LOOKUP_ONLYCONVERTING|DIRECT_BIND);
/* And wrap up the statement-expression, if necessary. */
if (!toplevel_bindings_p ())
{
if (building_stmt_tree ())
add_decl_stmt (arg);
stmt_expr = finish_init_stmts (stmt_expr, compound_stmt);
}
} }
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg)) else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
{ {
...@@ -719,13 +704,6 @@ ocp_convert (type, expr, convtype, flags) ...@@ -719,13 +704,6 @@ ocp_convert (type, expr, convtype, flags)
return e; return e;
} }
#if 0
/* This is incorrect. A truncation can't be stripped this way.
Extensions will be stripped by the use of get_unwidened. */
if (TREE_CODE (e) == NOP_EXPR)
return cp_convert (type, TREE_OPERAND (e, 0));
#endif
/* Just convert to the type of the member. */ /* Just convert to the type of the member. */
if (code == OFFSET_TYPE) if (code == OFFSET_TYPE)
{ {
...@@ -733,13 +711,6 @@ ocp_convert (type, expr, convtype, flags) ...@@ -733,13 +711,6 @@ ocp_convert (type, expr, convtype, flags)
code = TREE_CODE (type); code = TREE_CODE (type);
} }
#if 0
if (code == REFERENCE_TYPE)
return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));
else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
e = convert_from_reference (e);
#endif
if (TREE_CODE (e) == OFFSET_REF) if (TREE_CODE (e) == OFFSET_REF)
e = resolve_offset_ref (e); e = resolve_offset_ref (e);
......
...@@ -179,6 +179,7 @@ static void mark_cp_function_context PROTO((struct function *)); ...@@ -179,6 +179,7 @@ static void mark_cp_function_context PROTO((struct function *));
static void mark_saved_scope PROTO((void *)); static void mark_saved_scope PROTO((void *));
static void check_function_type PROTO((tree)); static void check_function_type PROTO((tree));
static void destroy_local_static PROTO((tree)); static void destroy_local_static PROTO((tree));
static void destroy_local_var PROTO((tree));
#if defined (DEBUG_CP_BINDING_LEVELS) #if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void)); static void indent PROTO((void));
...@@ -6843,16 +6844,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes) ...@@ -6843,16 +6844,10 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
{ {
if (at_function_scope_p ()) if (at_function_scope_p ())
push_permanent_obstack (); push_permanent_obstack ();
tem = push_template_decl (tem); tem = push_template_decl (tem);
/* In a a local scope, add a representation of this declaration
to the statement tree. */
if (at_function_scope_p ()) if (at_function_scope_p ())
{
add_decl_stmt (decl);
pop_obstacks (); pop_obstacks ();
} }
}
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
...@@ -6988,6 +6983,13 @@ grok_reference_init (decl, type, init) ...@@ -6988,6 +6983,13 @@ grok_reference_init (decl, type, init)
init = default_conversion (init); init = default_conversion (init);
} }
/* Convert INIT to the reference type TYPE. This may involve the
creation of a temporary, whose lifetime must be the same as that
of the reference. If so, a DECL_STMT for the temporary will be
added just after the DECL_STMT for DECL. That's why we don't set
DECL_INITIAL for local references (instead assigning to them
explicitly); we need to allow the temporary to be initialized
first. */
tmp = convert_to_reference tmp = convert_to_reference
(type, init, CONV_IMPLICIT, (type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl); LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
...@@ -6997,7 +6999,18 @@ grok_reference_init (decl, type, init) ...@@ -6997,7 +6999,18 @@ grok_reference_init (decl, type, init)
else if (tmp != NULL_TREE) else if (tmp != NULL_TREE)
{ {
init = tmp; init = tmp;
DECL_INITIAL (decl) = save_expr (init); tmp = save_expr (tmp);
if (building_stmt_tree ())
{
/* Initialize the declaration. */
tmp = build (INIT_EXPR, TREE_TYPE (decl), decl, tmp);
/* Setting TREE_SIDE_EFFECTS prevents expand_expr from
omitting this expression entirely. */
TREE_SIDE_EFFECTS (tmp) = 1;
finish_expr_stmt (tmp);
}
else
DECL_INITIAL (decl) = tmp;
} }
else else
{ {
...@@ -7005,11 +7018,6 @@ grok_reference_init (decl, type, init) ...@@ -7005,11 +7018,6 @@ grok_reference_init (decl, type, init)
return; return;
} }
/* ?? Can this be optimized in some cases to
hand back the DECL_INITIAL slot?? */
if (TYPE_SIZE (TREE_TYPE (type)))
init = convert_from_reference (decl);
if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl))) if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
{ {
expand_static_init (decl, DECL_INITIAL (decl)); expand_static_init (decl, DECL_INITIAL (decl));
...@@ -7526,12 +7534,9 @@ initialize_local_var (decl, init, flags) ...@@ -7526,12 +7534,9 @@ initialize_local_var (decl, init, flags)
int flags; int flags;
{ {
tree type; tree type;
tree cleanup;
type = complete_type (TREE_TYPE (decl)); type = complete_type (TREE_TYPE (decl));
cleanup = build_cleanup_on_safe_obstack (decl);
if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl)) if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
{ {
/* If we used it already as memory, it must stay in memory. */ /* If we used it already as memory, it must stay in memory. */
...@@ -7539,16 +7544,6 @@ initialize_local_var (decl, init, flags) ...@@ -7539,16 +7544,6 @@ initialize_local_var (decl, init, flags)
TREE_ADDRESSABLE (decl) = TREE_USED (decl); TREE_ADDRESSABLE (decl) = TREE_USED (decl);
} }
if (DECL_RTL (decl))
/* Only a RESULT_DECL should have non-NULL RTL when arriving here.
All other local variables are assigned RTL in this function. */
my_friendly_assert (TREE_CODE (decl) == RESULT_DECL, 19990828);
else
/* Create RTL for this variable. */
expand_decl (decl);
expand_start_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node) if (DECL_SIZE (decl) && type != error_mark_node)
{ {
int already_used; int already_used;
...@@ -7558,21 +7553,15 @@ initialize_local_var (decl, init, flags) ...@@ -7558,21 +7553,15 @@ initialize_local_var (decl, init, flags)
if (init || TYPE_NEEDS_CONSTRUCTING (type)) if (init || TYPE_NEEDS_CONSTRUCTING (type))
{ {
int saved_stmts_are_full_exprs_p;
emit_line_note (DECL_SOURCE_FILE (decl), emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl)); DECL_SOURCE_LINE (decl));
/* We call push_momentary here so that when saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
finish_expr_stmt clears the momentary obstack it stmts_are_full_exprs_p = 1;
doesn't destory any momentary expressions we may
have lying around. Although cp_finish_decl is
usually called at the end of a declaration
statement, it may also be called for a temporary
object in the middle of an expression. */
push_momentary ();
finish_expr_stmt (build_aggr_init (decl, init, flags)); finish_expr_stmt (build_aggr_init (decl, init, flags));
pop_momentary (); stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
} }
else
expand_decl_init (decl);
/* Set this to 0 so we can tell whether an aggregate which was /* Set this to 0 so we can tell whether an aggregate which was
initialized was ever used. Don't do this if it has a initialized was ever used. Don't do this if it has a
...@@ -7582,22 +7571,48 @@ initialize_local_var (decl, init, flags) ...@@ -7582,22 +7571,48 @@ initialize_local_var (decl, init, flags)
marked used. (see TREE_USED, above.) */ marked used. (see TREE_USED, above.) */
if (TYPE_NEEDS_CONSTRUCTING (type) if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used && ! already_used
&& cleanup == NULL_TREE && !TYPE_NEEDS_DESTRUCTOR (type)
&& DECL_NAME (decl)) && DECL_NAME (decl))
TREE_USED (decl) = 0; TREE_USED (decl) = 0;
else if (already_used) else if (already_used)
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
} }
}
/* Cleanup any temporaries needed for the initial value. */ /* Generate code to destroy DECL (a local variable). */
expand_end_target_temps ();
void
destroy_local_var (decl)
tree decl;
{
tree cleanup = build_cleanup_on_safe_obstack (decl);
/* Record the cleanup required for this declaration. */ /* Record the cleanup required for this declaration. */
if (DECL_SIZE (decl) if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node
&& type != error_mark_node && cleanup)
&& cleanup finish_decl_cleanup (decl, cleanup);
&& !expand_decl_cleanup (decl, cleanup)) }
cp_error ("parser lost in parsing declaration of `%D'", decl);
/* Let the back-end know about DECL. */
void
emit_local_var (decl)
tree decl;
{
/* Create RTL for this variable. */
if (DECL_RTL (decl))
/* Only a RESULT_DECL should have non-NULL RTL when
arriving here. All other local variables are
assigned RTL in this function. */
my_friendly_assert (TREE_CODE (decl) == RESULT_DECL,
19990828);
else
expand_decl (decl);
/* Actually do the initialization. */
expand_start_target_temps ();
expand_decl_init (decl);
expand_end_target_temps ();
} }
/* Finish processing of a declaration; /* Finish processing of a declaration;
...@@ -7680,6 +7695,11 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7680,6 +7695,11 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
return; return;
} }
/* Add this declaration to the statement-tree. */
if (building_stmt_tree ()
&& TREE_CODE (current_scope ()) == FUNCTION_DECL)
add_decl_stmt (decl);
if (TYPE_HAS_MUTABLE_P (type)) if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0; TREE_READONLY (decl) = 0;
...@@ -7808,10 +7828,19 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7808,10 +7828,19 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Initialize the local variable. But, if we're building a /* Initialize the local variable. But, if we're building a
statement-tree, we'll do the initialization when we statement-tree, we'll do the initialization when we
expand the tree. */ expand the tree. */
if (processing_template_decl)
{
if (init || DECL_INITIAL (decl) == error_mark_node)
DECL_INITIAL (decl) = init;
}
else
{
if (!building_stmt_tree ()) if (!building_stmt_tree ())
emit_local_var (decl);
initialize_local_var (decl, init, flags); initialize_local_var (decl, init, flags);
else if (init || DECL_INITIAL (decl) == error_mark_node) /* Clean up the variable. */
DECL_INITIAL (decl) = init; destroy_local_var (decl);
}
} }
finish_end0: finish_end0:
...@@ -12900,7 +12929,7 @@ start_function (declspecs, declarator, attrs, flags) ...@@ -12900,7 +12929,7 @@ start_function (declspecs, declarator, attrs, flags)
get_pending_sizes (); get_pending_sizes ();
/* Let the user know we're compiling this function. */ /* Let the user know we're compiling this function. */
if (!building_stmt_tree ()) if (processing_template_decl || !building_stmt_tree ())
announce_function (decl1); announce_function (decl1);
/* Record the decl so that the function name is defined. /* Record the decl so that the function name is defined.
...@@ -13210,9 +13239,6 @@ store_parm_decls () ...@@ -13210,9 +13239,6 @@ store_parm_decls ()
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl))); storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
/* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function. */
declare_function_name ();
/* Initialize the RTL code for the function. */ /* Initialize the RTL code for the function. */
DECL_SAVED_INSNS (fndecl) = 0; DECL_SAVED_INSNS (fndecl) = 0;
if (! building_stmt_tree ()) if (! building_stmt_tree ())
...@@ -14222,7 +14248,8 @@ finish_stmt () ...@@ -14222,7 +14248,8 @@ finish_stmt ()
if (!current_function_assigns_this if (!current_function_assigns_this
&& current_function_just_assigned_this) && current_function_just_assigned_this)
{ {
if (DECL_CONSTRUCTOR_P (current_function_decl)) if (DECL_CONSTRUCTOR_P (current_function_decl)
&& !building_stmt_tree ())
{ {
/* Constructors must wait until we are out of control /* Constructors must wait until we are out of control
zones before calling base constructors. */ zones before calling base constructors. */
......
...@@ -2668,9 +2668,6 @@ create_temporary_var (type) ...@@ -2668,9 +2668,6 @@ create_temporary_var (type)
DECL_SOURCE_LINE (decl) = lineno; DECL_SOURCE_LINE (decl) = lineno;
DECL_IGNORED_P (decl) = 1; DECL_IGNORED_P (decl) = 1;
if (building_stmt_tree ())
add_decl_stmt (decl);
return decl; return decl;
} }
...@@ -2688,6 +2685,8 @@ get_temp_regvar (type, init) ...@@ -2688,6 +2685,8 @@ get_temp_regvar (type, init)
tree decl; tree decl;
decl = create_temporary_var (type); decl = create_temporary_var (type);
if (building_stmt_tree ())
add_decl_stmt (decl);
DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ()) if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1); DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
......
...@@ -7284,7 +7284,8 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7284,7 +7284,8 @@ tsubst_expr (t, args, complain, in_decl)
init = DECL_INITIAL (decl); init = DECL_INITIAL (decl);
decl = tsubst (decl, args, complain, in_decl); decl = tsubst (decl, args, complain, in_decl);
init = tsubst_expr (init, args, complain, in_decl); init = tsubst_expr (init, args, complain, in_decl);
DECL_INITIAL (decl) = init; if (init)
DECL_INITIAL (decl) = error_mark_node;
/* By marking the declaration as instantiated, we avoid /* By marking the declaration as instantiated, we avoid
trying to instantiate it. Since instantiate_decl can't trying to instantiate it. Since instantiate_decl can't
handle local variables, and since we've already done handle local variables, and since we've already done
...@@ -7293,8 +7294,7 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7293,8 +7294,7 @@ tsubst_expr (t, args, complain, in_decl)
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
DECL_TEMPLATE_INSTANTIATED (decl) = 1; DECL_TEMPLATE_INSTANTIATED (decl) = 1;
maybe_push_decl (decl); maybe_push_decl (decl);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); cp_finish_decl (decl, init, NULL_TREE, 0, 0);
add_decl_stmt (decl);
} }
resume_momentary (i); resume_momentary (i);
return decl; return decl;
......
...@@ -869,6 +869,14 @@ begin_compound_stmt (has_no_scope) ...@@ -869,6 +869,14 @@ begin_compound_stmt (has_no_scope)
to accidentally keep a block *inside* the scopeless block. */ to accidentally keep a block *inside* the scopeless block. */
keep_next_level (0); keep_next_level (0);
/* If this is the outermost block of the function, declare the
variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth. */
if (!current_function_name_declared && !processing_template_decl)
{
declare_function_name ();
current_function_name_declared = 1;
}
return r; return r;
} }
...@@ -1027,6 +1035,19 @@ finish_subobject (cleanup) ...@@ -1027,6 +1035,19 @@ finish_subobject (cleanup)
add_partial_entry (cleanup); add_partial_entry (cleanup);
} }
/* When DECL goes out of scope, make sure that CLEANUP is executed. */
void
finish_decl_cleanup (decl, cleanup)
tree decl;
tree cleanup;
{
if (building_stmt_tree ())
add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
else if (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node)
expand_decl_cleanup (decl, cleanup);
}
/* Bind a name and initialization to the return value of /* Bind a name and initialization to the return value of
the current function. */ the current function. */
...@@ -2153,13 +2174,17 @@ expand_stmt (t) ...@@ -2153,13 +2174,17 @@ expand_stmt (t)
compatibility. */ compatibility. */
maybe_inject_for_scope_var (decl); maybe_inject_for_scope_var (decl);
/* Let the back-end know about this variable. */ /* Let the back-end know about this variable. */
initialize_local_var (decl, DECL_INITIAL (decl), 0); emit_local_var (decl);
} }
} }
resume_momentary (i); resume_momentary (i);
} }
break; break;
case CLEANUP_STMT:
finish_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
break;
case FOR_STMT: case FOR_STMT:
{ {
tree tmp; tree tmp;
...@@ -2338,6 +2363,11 @@ expand_body (fn) ...@@ -2338,6 +2363,11 @@ expand_body (fn)
start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND); start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
store_parm_decls (); store_parm_decls ();
/* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
any of the other magic variables we set up when starting a
function body. */
current_function_name_declared = 1;
/* There are a few things that we do not handle recursively. For /* There are a few things that we do not handle recursively. For
example, a function try-block is handled differently from an example, a function try-block is handled differently from an
ordinary try-block, so we must handle it here. */ ordinary try-block, so we must handle it here. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment