mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 10:10:39 +08:00
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
This commit is contained in:
parent
f84300c426
commit
b7b8bcd23a
@ -1,3 +1,26 @@
|
||||
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>
|
||||
|
||||
* cp-tree.h (fndecl_as_string, type_as_string,
|
||||
|
@ -1690,13 +1690,6 @@ extern int flag_new_for_scope;
|
||||
/* Nonzero for _TYPE means that the _TYPE defines a destructor. */
|
||||
#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
|
||||
an initializer list. */
|
||||
#define CLASSTYPE_NON_AGGREGATE(NODE) \
|
||||
@ -2936,6 +2929,8 @@ extern tree start_decl PROTO((tree, tree, int, tree, tree));
|
||||
extern void start_decl_1 PROTO((tree));
|
||||
extern void cp_finish_decl PROTO((tree, tree, tree, int, int));
|
||||
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 int complete_array_type PROTO((tree, tree, int));
|
||||
extern tree build_ptrmemfunc_type PROTO((tree));
|
||||
|
142
gcc/cp/decl.c
142
gcc/cp/decl.c
@ -196,8 +196,6 @@ static void pop_labels PROTO((tree));
|
||||
static void maybe_deduce_size_from_array_init PROTO((tree, tree));
|
||||
static void layout_var_decl PROTO((tree, 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 void check_initializer PROTO((tree, tree *));
|
||||
static void make_rtl_for_nonlocal_decl PROTO((tree, tree, const char *));
|
||||
@ -7669,16 +7667,16 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
|
||||
tree init;
|
||||
const char *asmspec;
|
||||
{
|
||||
int was_temp;
|
||||
int toplev;
|
||||
tree type;
|
||||
|
||||
type = TREE_TYPE (decl);
|
||||
toplev = toplevel_bindings_p ();
|
||||
was_temp = (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
|
||||
&& allocation_temporary_p ());
|
||||
if (was_temp)
|
||||
end_temporary_allocation ();
|
||||
push_obstacks_nochange ();
|
||||
if (TREE_STATIC (decl)
|
||||
&& TYPE_NEEDS_DESTRUCTOR (type)
|
||||
&& allocation_temporary_p ())
|
||||
end_temporary_allocation ();
|
||||
|
||||
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
|
||||
make_decl_rtl (decl, NULL_PTR, toplev);
|
||||
@ -7747,8 +7745,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
|
||||
else
|
||||
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
|
||||
|
||||
if (was_temp)
|
||||
resume_temporary_allocation ();
|
||||
pop_obstacks ();
|
||||
}
|
||||
|
||||
/* The old ARM scoping rules injected variables declared in the
|
||||
@ -7757,7 +7754,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
|
||||
DECL is a just-declared VAR_DECL; if necessary inject its
|
||||
declaration into the surrounding scope. */
|
||||
|
||||
static void
|
||||
void
|
||||
maybe_inject_for_scope_var (decl)
|
||||
tree decl;
|
||||
{
|
||||
@ -7794,16 +7791,34 @@ maybe_inject_for_scope_var (decl)
|
||||
|
||||
/* Generate code to initialized DECL (a local variable). */
|
||||
|
||||
static void
|
||||
initialize_local_var (decl, init, cleanup, flags)
|
||||
void
|
||||
initialize_local_var (decl, init, flags)
|
||||
tree decl;
|
||||
tree init;
|
||||
tree cleanup;
|
||||
int flags;
|
||||
{
|
||||
tree type;
|
||||
tree cleanup;
|
||||
|
||||
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 ();
|
||||
|
||||
if (DECL_SIZE (decl) && type != error_mark_node)
|
||||
@ -7811,7 +7826,6 @@ initialize_local_var (decl, init, cleanup, flags)
|
||||
int already_used;
|
||||
|
||||
/* Compute and store the initial value. */
|
||||
expand_decl_init (decl);
|
||||
already_used = TREE_USED (decl) || TREE_USED (type);
|
||||
|
||||
if (init || TYPE_NEEDS_CONSTRUCTING (type))
|
||||
@ -7829,39 +7843,33 @@ initialize_local_var (decl, init, cleanup, flags)
|
||||
finish_expr_stmt (build_aggr_init (decl, init, flags));
|
||||
pop_momentary ();
|
||||
}
|
||||
else
|
||||
expand_decl_init (decl);
|
||||
|
||||
/* 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
|
||||
destructor, so we don't complain about the 'resource
|
||||
allocation is initialization' idiom. */
|
||||
/* Now set attribute((unused)) on types so decls of that type
|
||||
will be marked used. (see TREE_USED, above.) This avoids the
|
||||
warning problems this particular code tried to work
|
||||
around. */
|
||||
|
||||
allocation is initialization' idiom. Now set
|
||||
attribute((unused)) on types so decls of that type will be
|
||||
marked used. (see TREE_USED, above.) */
|
||||
if (TYPE_NEEDS_CONSTRUCTING (type)
|
||||
&& ! already_used
|
||||
&& cleanup == NULL_TREE
|
||||
&& DECL_NAME (decl))
|
||||
TREE_USED (decl) = 0;
|
||||
|
||||
if (already_used)
|
||||
else if (already_used)
|
||||
TREE_USED (decl) = 1;
|
||||
}
|
||||
|
||||
/* Cleanup any temporaries needed for the initial value. */
|
||||
expand_end_target_temps ();
|
||||
|
||||
if (DECL_SIZE (decl) && type != error_mark_node)
|
||||
{
|
||||
/* Store the cleanup, if there was one. */
|
||||
if (cleanup)
|
||||
{
|
||||
if (! expand_decl_cleanup (decl, cleanup))
|
||||
cp_error ("parser lost in parsing declaration of `%D'",
|
||||
decl);
|
||||
}
|
||||
}
|
||||
/* Record the cleanup required for this declaration. */
|
||||
if (DECL_SIZE (decl)
|
||||
&& type != error_mark_node
|
||||
&& cleanup
|
||||
&& !expand_decl_cleanup (decl, cleanup))
|
||||
cp_error ("parser lost in parsing declaration of `%D'", decl);
|
||||
}
|
||||
|
||||
/* Finish processing of a declaration;
|
||||
@ -7895,7 +7903,6 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|
||||
{
|
||||
register tree type;
|
||||
tree ttype = NULL_TREE;
|
||||
int was_incomplete;
|
||||
int temporary = allocation_temporary_p ();
|
||||
const char *asmspec = NULL;
|
||||
int was_readonly = 0;
|
||||
@ -7935,13 +7942,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|
||||
pop_decl_namespace ();
|
||||
}
|
||||
|
||||
/* If the type of the thing we are declaring either has
|
||||
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);
|
||||
type = complete_type (TREE_TYPE (decl));
|
||||
|
||||
if (type == error_mark_node)
|
||||
{
|
||||
@ -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,
|
||||
unless the type is an undefined structure or union.
|
||||
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
|
||||
|| TREE_CODE (decl) == RESULT_DECL)
|
||||
{
|
||||
@ -8078,44 +8076,15 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
|
||||
}
|
||||
else if (! toplev)
|
||||
{
|
||||
tree cleanup = build_cleanup_on_safe_obstack (decl);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a local declaration. */
|
||||
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:
|
||||
|
||||
@ -8195,6 +8164,7 @@ expand_static_init (decl, init)
|
||||
{
|
||||
/* Emit code to perform this initialization but once. */
|
||||
tree temp;
|
||||
tree if_stmt;
|
||||
tree assignment;
|
||||
tree temp_init;
|
||||
|
||||
@ -8229,8 +8199,10 @@ expand_static_init (decl, init)
|
||||
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
|
||||
|
||||
/* Begin the conditional initialization. */
|
||||
expand_start_cond (build_binary_op (EQ_EXPR, temp,
|
||||
integer_zero_node), 0);
|
||||
if_stmt = begin_if_stmt ();
|
||||
finish_if_stmt_cond (build_binary_op (EQ_EXPR, temp,
|
||||
integer_zero_node),
|
||||
if_stmt);
|
||||
|
||||
/* Do the initialization itself. */
|
||||
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|
||||
@ -8325,10 +8297,12 @@ expand_static_init (decl, init)
|
||||
expr_tree_cons (NULL_TREE,
|
||||
cleanup,
|
||||
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. */
|
||||
pop_obstacks ();
|
||||
}
|
||||
|
@ -2070,7 +2070,8 @@ get_temp_name (type, staticp)
|
||||
if (! toplev)
|
||||
{
|
||||
expand_decl (decl);
|
||||
expand_decl_init (decl);
|
||||
my_friendly_assert (DECL_INITIAL (decl) == NULL_TREE,
|
||||
19990826);
|
||||
}
|
||||
pop_obstacks ();
|
||||
|
||||
|
@ -2706,8 +2706,6 @@ create_temporary_var (type)
|
||||
|
||||
if (building_stmt_tree ())
|
||||
add_decl_stmt (decl);
|
||||
else
|
||||
DECL_RTL (decl) = assign_temp (type, 2, 0, 1);
|
||||
|
||||
return decl;
|
||||
}
|
||||
@ -2727,6 +2725,8 @@ get_temp_regvar (type, init)
|
||||
|
||||
decl = create_temporary_var (type);
|
||||
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));
|
||||
|
||||
return decl;
|
||||
|
10
gcc/cp/pt.c
10
gcc/cp/pt.c
@ -7272,13 +7272,15 @@ tsubst_expr (t, args, complain, in_decl)
|
||||
decl = tsubst (decl, args, complain, in_decl);
|
||||
init = tsubst_expr (init, args, complain, in_decl);
|
||||
DECL_INITIAL (decl) = init;
|
||||
/* 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. */
|
||||
/* 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;
|
||||
maybe_push_decl (decl);
|
||||
cp_finish_decl (decl, DECL_INITIAL (decl), NULL_TREE, 0, 0);
|
||||
add_decl_stmt (decl);
|
||||
}
|
||||
resume_momentary (i);
|
||||
|
@ -2046,7 +2046,11 @@ expand_stmt (t)
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
25
gcc/testsuite/g++.old-deja/g++.pt/crash52.C
Normal file
25
gcc/testsuite/g++.old-deja/g++.pt/crash52.C
Normal file
@ -0,0 +1,25 @@
|
||||
// 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);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user