Commit b7b8bcd2 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.

	* cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.
	(maybe_inject_for_scope_var): Declare it.
	(initialize_local_var): Likewise.
	* decl.c (maybe_inject_for_scope_var): Make it global.
	(initialize_local_var): Likewise.  Move cleanup handling here,
	from cp_finish_decl.
	(make_rtl_for_nonlocal_decl): Use
	push_obstacks_nochange/pop_obstacks, rather than
	end_temporary_allocation/resume_temporary_allocation.
	(cp_finish_decl): Try to complete the type of a variable when it
	is declared.  Move cleanup-handling to initialize_local_var.
	(expand_static_init): Use tree-building code, rather than
	RTL-building code.
	* decl2.c (get_temp_name): Assert non-initializedness of
	temporaries.
	* init.c (create_temporary_var): Move RTL-assigning code to ...
	(get_temp_regvar): Here.
	* pt.c (tsbust_expr): Fix indentation.  Call cp_finish_decl here.
	* semantics.c (expand_stmt): Don't call cp_finish_decl here.  Just
	call initialize_local_var to generate initialization code.

From-SVN: r28973
parent f84300c4
1999-08-29 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (TYPE_NEEDS_CONSTRUCTING): Remove #if 0'd definition.
(maybe_inject_for_scope_var): Declare it.
(initialize_local_var): Likewise.
* decl.c (maybe_inject_for_scope_var): Make it global.
(initialize_local_var): Likewise. Move cleanup handling here,
from cp_finish_decl.
(make_rtl_for_nonlocal_decl): Use
push_obstacks_nochange/pop_obstacks, rather than
end_temporary_allocation/resume_temporary_allocation.
(cp_finish_decl): Try to complete the type of a variable when it
is declared. Move cleanup-handling to initialize_local_var.
(expand_static_init): Use tree-building code, rather than
RTL-building code.
* decl2.c (get_temp_name): Assert non-initializedness of
temporaries.
* init.c (create_temporary_var): Move RTL-assigning code to ...
(get_temp_regvar): Here.
* pt.c (tsbust_expr): Fix indentation. Call cp_finish_decl here.
* semantics.c (expand_stmt): Don't call cp_finish_decl here. Just
call initialize_local_var to generate initialization code.
1999-08-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 1999-08-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* cp-tree.h (fndecl_as_string, type_as_string, * cp-tree.h (fndecl_as_string, type_as_string,
......
...@@ -1690,13 +1690,6 @@ extern int flag_new_for_scope; ...@@ -1690,13 +1690,6 @@ extern int flag_new_for_scope;
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */ /* Nonzero for _TYPE means that the _TYPE defines a destructor. */
#define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE)) #define TYPE_HAS_DESTRUCTOR(NODE) (TYPE_LANG_FLAG_2(NODE))
#if 0
/* Nonzero for _TYPE node means that creating an object of this type
will involve a call to a constructor. This can apply to objects
of ARRAY_TYPE if the type of the elements needs a constructor. */
#define TYPE_NEEDS_CONSTRUCTING(NODE) ... defined in ../tree.h ...
#endif
/* Nonzero means that an object of this type can not be initialized using /* Nonzero means that an object of this type can not be initialized using
an initializer list. */ an initializer list. */
#define CLASSTYPE_NON_AGGREGATE(NODE) \ #define CLASSTYPE_NON_AGGREGATE(NODE) \
...@@ -2936,6 +2929,8 @@ extern tree start_decl PROTO((tree, tree, int, tree, tree)); ...@@ -2936,6 +2929,8 @@ extern tree start_decl PROTO((tree, tree, int, tree, tree));
extern void start_decl_1 PROTO((tree)); extern void start_decl_1 PROTO((tree));
extern void cp_finish_decl PROTO((tree, tree, tree, int, int)); extern void cp_finish_decl PROTO((tree, tree, tree, int, int));
extern void finish_decl PROTO((tree, tree, tree)); extern void finish_decl PROTO((tree, tree, tree));
extern void maybe_inject_for_scope_var PROTO((tree));
extern void initialize_local_var PROTO((tree, tree, int));
extern void expand_static_init PROTO((tree, tree)); extern void expand_static_init PROTO((tree, tree));
extern int complete_array_type PROTO((tree, tree, int)); extern int complete_array_type PROTO((tree, tree, int));
extern tree build_ptrmemfunc_type PROTO((tree)); extern tree build_ptrmemfunc_type PROTO((tree));
......
...@@ -196,8 +196,6 @@ static void pop_labels PROTO((tree)); ...@@ -196,8 +196,6 @@ static void pop_labels PROTO((tree));
static void maybe_deduce_size_from_array_init PROTO((tree, tree)); static void maybe_deduce_size_from_array_init PROTO((tree, tree));
static void layout_var_decl PROTO((tree, tree *)); static void layout_var_decl PROTO((tree, tree *));
static void maybe_commonize_var PROTO((tree)); static void maybe_commonize_var PROTO((tree));
static void maybe_inject_for_scope_var PROTO((tree));
static void initialize_local_var PROTO((tree, tree, tree, int));
static tree build_cleanup_on_safe_obstack PROTO((tree)); static tree build_cleanup_on_safe_obstack PROTO((tree));
static void check_initializer PROTO((tree, tree *)); static void check_initializer PROTO((tree, tree *));
static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *)); static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *));
...@@ -7669,15 +7667,15 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec) ...@@ -7669,15 +7667,15 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
tree init; tree init;
const char *asmspec; const char *asmspec;
{ {
int was_temp;
int toplev; int toplev;
tree type; tree type;
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
toplev = toplevel_bindings_p (); toplev = toplevel_bindings_p ();
was_temp = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type) push_obstacks_nochange ();
&& allocation_temporary_p ()); if (TREE_STATIC (decl)
if (was_temp) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ())
end_temporary_allocation (); end_temporary_allocation ();
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl)) if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
...@@ -7747,8 +7745,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec) ...@@ -7747,8 +7745,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
else else
rest_of_decl_compilation (decl, asmspec, toplev, at_eof); rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
if (was_temp) pop_obstacks ();
resume_temporary_allocation ();
} }
/* The old ARM scoping rules injected variables declared in the /* The old ARM scoping rules injected variables declared in the
...@@ -7757,7 +7754,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec) ...@@ -7757,7 +7754,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
DECL is a just-declared VAR_DECL; if necessary inject its DECL is a just-declared VAR_DECL; if necessary inject its
declaration into the surrounding scope. */ declaration into the surrounding scope. */
static void void
maybe_inject_for_scope_var (decl) maybe_inject_for_scope_var (decl)
tree decl; tree decl;
{ {
...@@ -7794,16 +7791,34 @@ maybe_inject_for_scope_var (decl) ...@@ -7794,16 +7791,34 @@ maybe_inject_for_scope_var (decl)
/* Generate code to initialized DECL (a local variable). */ /* Generate code to initialized DECL (a local variable). */
static void void
initialize_local_var (decl, init, cleanup, flags) initialize_local_var (decl, init, flags)
tree decl; tree decl;
tree init; tree init;
tree cleanup;
int flags; int flags;
{ {
tree type; tree type;
tree cleanup;
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
cleanup = build_cleanup_on_safe_obstack (decl);
if (DECL_SIZE (decl) == NULL_TREE && !TREE_STATIC (decl))
{
/* If we used it already as memory, it must stay in memory. */
DECL_INITIAL (decl) = NULL_TREE;
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 (); expand_start_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node) if (DECL_SIZE (decl) && type != error_mark_node)
...@@ -7811,7 +7826,6 @@ initialize_local_var (decl, init, cleanup, flags) ...@@ -7811,7 +7826,6 @@ initialize_local_var (decl, init, cleanup, flags)
int already_used; int already_used;
/* Compute and store the initial value. */ /* Compute and store the initial value. */
expand_decl_init (decl);
already_used = TREE_USED (decl) || TREE_USED (type); already_used = TREE_USED (decl) || TREE_USED (type);
if (init || TYPE_NEEDS_CONSTRUCTING (type)) if (init || TYPE_NEEDS_CONSTRUCTING (type))
...@@ -7829,39 +7843,33 @@ initialize_local_var (decl, init, cleanup, flags) ...@@ -7829,39 +7843,33 @@ initialize_local_var (decl, init, cleanup, flags)
finish_expr_stmt (build_aggr_init (decl, init, flags)); finish_expr_stmt (build_aggr_init (decl, init, flags));
pop_momentary (); pop_momentary ();
} }
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
destructor, so we don't complain about the 'resource destructor, so we don't complain about the 'resource
allocation is initialization' idiom. */ allocation is initialization' idiom. Now set
/* Now set attribute((unused)) on types so decls of that type attribute((unused)) on types so decls of that type will be
will be marked used. (see TREE_USED, above.) This avoids the marked used. (see TREE_USED, above.) */
warning problems this particular code tried to work
around. */
if (TYPE_NEEDS_CONSTRUCTING (type) if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used && ! already_used
&& cleanup == NULL_TREE && cleanup == NULL_TREE
&& DECL_NAME (decl)) && DECL_NAME (decl))
TREE_USED (decl) = 0; TREE_USED (decl) = 0;
else if (already_used)
if (already_used)
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
} }
/* Cleanup any temporaries needed for the initial value. */ /* Cleanup any temporaries needed for the initial value. */
expand_end_target_temps (); expand_end_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node) /* Record the cleanup required for this declaration. */
{ if (DECL_SIZE (decl)
/* Store the cleanup, if there was one. */ && type != error_mark_node
if (cleanup) && cleanup
{ && !expand_decl_cleanup (decl, cleanup))
if (! expand_decl_cleanup (decl, cleanup)) cp_error ("parser lost in parsing declaration of `%D'", decl);
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
}
} }
/* Finish processing of a declaration; /* Finish processing of a declaration;
...@@ -7895,7 +7903,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7895,7 +7903,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
{ {
register tree type; register tree type;
tree ttype = NULL_TREE; tree ttype = NULL_TREE;
int was_incomplete;
int temporary = allocation_temporary_p (); int temporary = allocation_temporary_p ();
const char *asmspec = NULL; const char *asmspec = NULL;
int was_readonly = 0; int was_readonly = 0;
...@@ -7935,13 +7942,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -7935,13 +7942,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
pop_decl_namespace (); pop_decl_namespace ();
} }
/* If the type of the thing we are declaring either has type = complete_type (TREE_TYPE (decl));
a constructor, or has a virtual function table pointer,
AND its initialization was accepted by `start_decl',
then we stayed on the permanent obstack through the
declaration, otherwise, changed obstacks as GCC would. */
type = TREE_TYPE (decl);
if (type == error_mark_node) if (type == error_mark_node)
{ {
...@@ -8039,9 +8040,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -8039,9 +8040,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
/* Output the assembler code and/or RTL code for variables and functions, /* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union. unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */ If not, it will get done when the type is completed. */
was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == RESULT_DECL) || TREE_CODE (decl) == RESULT_DECL)
{ {
...@@ -8078,44 +8076,15 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags) ...@@ -8078,44 +8076,15 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
} }
else if (! toplev) else if (! toplev)
{ {
tree cleanup = build_cleanup_on_safe_obstack (decl); /* This is a local declaration. */
/* This is a declared decl which must live until the
end of the binding contour. It may need a cleanup. */
/* Recompute the RTL of a local array now
if it used to be an incomplete type. */
if (was_incomplete && ! TREE_STATIC (decl))
{
/* If we used it already as memory, it must stay in memory. */
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
/* If it's still incomplete now, no init will save it. */
if (DECL_SIZE (decl) == NULL_TREE)
DECL_INITIAL (decl) = NULL_TREE;
expand_decl (decl);
}
else if (! TREE_ASM_WRITTEN (decl)
&& (TYPE_SIZE (type) != NULL_TREE
|| TREE_CODE (type) == ARRAY_TYPE))
{
/* Do this here, because we did not expand this decl's
rtl in start_decl. */
if (DECL_RTL (decl) == NULL_RTX)
expand_decl (decl);
else if (cleanup)
{
/* XXX: Why don't we use decl here? */
/* Ans: Because it was already expanded? */
if (! expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
/* Cleanup used up here. */
cleanup = NULL_TREE;
}
}
maybe_inject_for_scope_var (decl); maybe_inject_for_scope_var (decl);
initialize_local_var (decl, init, cleanup, flags); /* Initialize the local variable. But, if we're building a
statement-tree, we'll do the initialization when we
expand the tree. */
if (!building_stmt_tree ())
initialize_local_var (decl, init, flags);
else if (init || DECL_INITIAL (decl) == error_mark_node)
DECL_INITIAL (decl) = init;
} }
finish_end0: finish_end0:
...@@ -8195,6 +8164,7 @@ expand_static_init (decl, init) ...@@ -8195,6 +8164,7 @@ expand_static_init (decl, init)
{ {
/* Emit code to perform this initialization but once. */ /* Emit code to perform this initialization but once. */
tree temp; tree temp;
tree if_stmt;
tree assignment; tree assignment;
tree temp_init; tree temp_init;
...@@ -8229,8 +8199,10 @@ expand_static_init (decl, init) ...@@ -8229,8 +8199,10 @@ expand_static_init (decl, init)
rest_of_decl_compilation (temp, NULL_PTR, 0, 0); rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
/* Begin the conditional initialization. */ /* Begin the conditional initialization. */
expand_start_cond (build_binary_op (EQ_EXPR, temp, if_stmt = begin_if_stmt ();
integer_zero_node), 0); finish_if_stmt_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node),
if_stmt);
/* Do the initialization itself. */ /* Do the initialization itself. */
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)) if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
...@@ -8325,10 +8297,12 @@ expand_static_init (decl, init) ...@@ -8325,10 +8297,12 @@ expand_static_init (decl, init)
expr_tree_cons (NULL_TREE, expr_tree_cons (NULL_TREE,
cleanup, cleanup,
NULL_TREE)); NULL_TREE));
expand_expr_stmt (fcall); finish_expr_stmt (fcall);
} }
expand_end_cond (); finish_then_clause (if_stmt);
finish_if_stmt ();
/* Resume old (possibly temporary) allocation. */ /* Resume old (possibly temporary) allocation. */
pop_obstacks (); pop_obstacks ();
} }
......
...@@ -2070,7 +2070,8 @@ get_temp_name (type, staticp) ...@@ -2070,7 +2070,8 @@ get_temp_name (type, staticp)
if (! toplev) if (! toplev)
{ {
expand_decl (decl); expand_decl (decl);
expand_decl_init (decl); my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE,
19990826);
} }
pop_obstacks (); pop_obstacks ();
......
...@@ -2706,8 +2706,6 @@ create_temporary_var (type) ...@@ -2706,8 +2706,6 @@ create_temporary_var (type)
if (building_stmt_tree ()) if (building_stmt_tree ())
add_decl_stmt (decl); add_decl_stmt (decl);
else
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
return decl; return decl;
} }
...@@ -2727,6 +2725,8 @@ get_temp_regvar (type, init) ...@@ -2727,6 +2725,8 @@ get_temp_regvar (type, init)
decl = create_temporary_var (type); decl = create_temporary_var (type);
DECL_REGISTER (decl) = 1; DECL_REGISTER (decl) = 1;
if (!building_stmt_tree ())
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init)); finish_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));
return decl; return decl;
......
...@@ -7272,13 +7272,15 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7272,13 +7272,15 @@ tsubst_expr (t, args, complain, in_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; DECL_INITIAL (decl) = init;
/* By marking the declaration as instantiated, we avoid trying /* By marking the declaration as instantiated, we avoid
to instantiate it. Since instantiate_decl can't handle trying to instantiate it. Since instantiate_decl can't
local variables, and since we've already done all that handle local variables, and since we've already done
needs to be done, that's the right thing to do. */ all that needs to be done, that's the right thing to
do. */
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);
add_decl_stmt (decl); add_decl_stmt (decl);
} }
resume_momentary (i); resume_momentary (i);
......
...@@ -2046,7 +2046,11 @@ expand_stmt (t) ...@@ -2046,7 +2046,11 @@ expand_stmt (t)
if (TREE_CODE (decl) == VAR_DECL) if (TREE_CODE (decl) == VAR_DECL)
DECL_DEAD_FOR_LOCAL (decl) = 0; DECL_DEAD_FOR_LOCAL (decl) = 0;
maybe_push_decl (decl); maybe_push_decl (decl);
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0); if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
{
maybe_inject_for_scope_var (decl);
initialize_local_var (decl, DECL_INITIAL (decl), 0);
}
} }
resume_momentary (i); resume_momentary (i);
} }
......
// Build don't link:
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T>
struct S1
{
template <class U>
struct S2
{
S2(U);
};
template <class U>
void f(U u)
{
S2<U> s2u(u);
}
};
void g()
{
S1<int> s1;
s1.f(3.0);
}
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