aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-08-29 19:03:31 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-08-29 19:03:31 +0000
commitb7b8bcd23a2ed4c571242d5e06fa975857948e11 (patch)
tree99bba146483ca359f5f8c34914144ca70c2b4ae4
parentf84300c4269026fbbdda49b114bfa311e5d71001 (diff)
downloadgcc-b7b8bcd23a2ed4c571242d5e06fa975857948e11.zip
gcc-b7b8bcd23a2ed4c571242d5e06fa975857948e11.tar.gz
gcc-b7b8bcd23a2ed4c571242d5e06fa975857948e11.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog23
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/decl.c142
-rw-r--r--gcc/cp/decl2.c3
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/cp/pt.c10
-rw-r--r--gcc/cp/semantics.c6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash52.C25
8 files changed, 123 insertions, 99 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 61cee8c..0fa5c60 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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,
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2761324..9fca595 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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));
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 8ca2f57..c7b511c 100644
--- a/gcc/cp/decl.c
+++ b/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 ();
}
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index b36abf2..5eb4a67 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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 ();
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index eba001c..9265ff9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index bb34296..e321c34 100644
--- a/gcc/cp/pt.c
+++ b/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);
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 382258b..6e0c5b2 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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);
}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash52.C b/gcc/testsuite/g++.old-deja/g++.pt/crash52.C
new file mode 100644
index 0000000..4d2de61
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash52.C
@@ -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);
+}
+