From b7b8bcd23a2ed4c571242d5e06fa975857948e11 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sun, 29 Aug 1999 19:03:31 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 23 ++++ gcc/cp/cp-tree.h | 9 +- gcc/cp/decl.c | 142 ++++++++------------ gcc/cp/decl2.c | 3 +- gcc/cp/init.c | 4 +- gcc/cp/pt.c | 10 +- gcc/cp/semantics.c | 6 +- gcc/testsuite/g++.old-deja/g++.pt/crash52.C | 25 ++++ 8 files changed, 123 insertions(+), 99 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/crash52.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 61cee8c03b3b..0fa5c6071276 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,26 @@ +1999-08-29 Mark Mitchell + + * 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 * cp-tree.h (fndecl_as_string, type_as_string, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 2761324d1853..9fca5954794a 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 8ca2f57a7ecc..c7b511c4a161 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 b36abf2bd106..5eb4a673f29c 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 eba001cfe207..9265ff9fe8d1 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 bb3429612076..e321c348e9b9 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 382258b3b89f..6e0c5b23afc8 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 000000000000..4d2de6198a36 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/crash52.C @@ -0,0 +1,25 @@ +// Build don't link: +// Origin: Mark Mitchell + +template +struct S1 +{ + template + struct S2 + { + S2(U); + }; + + template + void f(U u) + { + S2 s2u(u); + } +}; + +void g() +{ + S1 s1; + s1.f(3.0); +} +