From 4f3966770b7445af975cf52b86ddb74139666442 Mon Sep 17 00:00:00 2001 From: mmitchel Date: Thu, 21 Oct 1999 08:05:57 +0000 Subject: [PATCH] * cp-tree.h (SCOPE_PARTIAL_P): New macro. (pushlevel_temporary): Remove. (add_scope_stmt): New function. * decl.c (pushlevel_temporary): Remove. (poplevel): Use add_scope_stmt. (start_decl_1): Likewise. * semantics.c (add_scope_stmt): New function. (do_pushlevel): Use it. (do_poplevel): Use it. (expand_stmt): Check SCOPE_PARTIAL_P. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@30118 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 11 ++++++ gcc/cp/cp-tree.h | 18 ++++++++- gcc/cp/decl.c | 32 ++++++---------- gcc/cp/semantics.c | 55 ++++++++++++++++++++------- gcc/testsuite/g++.old-deja/g++.other/debug5.C | 15 ++++++++ gcc/testsuite/g++.old-deja/g++.other/goto1.C | 21 ++++++++++ 6 files changed, 116 insertions(+), 36 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.other/debug5.C create mode 100644 gcc/testsuite/g++.old-deja/g++.other/goto1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2c146e34a2d..f70308988af 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,16 @@ 1999-10-21 Mark Mitchell + * cp-tree.h (SCOPE_PARTIAL_P): New macro. + (pushlevel_temporary): Remove. + (add_scope_stmt): New function. + * decl.c (pushlevel_temporary): Remove. + (poplevel): Use add_scope_stmt. + (start_decl_1): Likewise. + * semantics.c (add_scope_stmt): New function. + (do_pushlevel): Use it. + (do_poplevel): Use it. + (expand_stmt): Check SCOPE_PARTIAL_P. + * cp-tree.def (EMPTY_CLASS_EXPR): New tree node. * call.c (build_call): Use EMPTY_CLASS_EXPR instead of RTL_EXPR. * expr.c (cplus_expand_expr): Expand it. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 425ca18dcbd..b71c1621019 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -69,6 +69,7 @@ Boston, MA 02111-1307, USA. */ TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, or FIELD_DECL). NEED_TEMPORARY_P (in REF_BIND, BASE_CONV) + SCOPE_PARTIAL_P (in SCOPE_STMT) 5: Not used. 6: Not used. @@ -2651,6 +2652,21 @@ extern int flag_new_for_scope; #define SCOPE_NULLIFIED_P(NODE) \ (TREE_LANG_FLAG_3 (SCOPE_STMT_CHECK (NODE))) +/* Nonzero for a SCOPE_STMT if this statement is for a partial scope. + For example, in: + + S s; + l: + S s2; + goto l; + + there is (implicitly) a new scope after `l', even though there are + no curly braces. In particular, when we hit the goto, we must + destroy s2 and then re-construct it. For the implicit scope, + SCOPE_PARTIAL_P will be set. */ +#define SCOPE_PARTIAL_P(NODE) \ + (TREE_LANG_FLAG_4 (SCOPE_STMT_CHECK (NODE))) + /* Nonzero for an ASM_STMT if the assembly statement is volatile. */ #define ASM_VOLATILE_P(NODE) \ (ASM_CV_QUAL (ASM_STMT_CHECK (NODE)) != NULL_TREE) @@ -3336,7 +3352,6 @@ extern int pseudo_global_level_p PROTO((void)); extern void set_class_shadows PROTO((tree)); extern void pushlevel PROTO((int)); extern void note_level_for_for PROTO((void)); -extern void pushlevel_temporary PROTO((int)); extern void resume_level PROTO((struct binding_level *)); extern void delete_block PROTO((tree)); extern void insert_block PROTO((tree)); @@ -3886,6 +3901,7 @@ extern void expand_body PROTO((tree)); extern void begin_stmt_tree PROTO((tree *)); extern void finish_stmt_tree PROTO((tree *)); extern void prep_stmt PROTO((tree)); +extern void add_scope_stmt PROTO((int, int)); extern void do_pushlevel PROTO((void)); extern tree do_poplevel PROTO((void)); /* Non-zero if we are presently building a statement tree, rather diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 122b0251ac7..746e498e212 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -825,21 +825,6 @@ note_level_for_for () current_binding_level->is_for_scope = 1; } -void -pushlevel_temporary (tag_transparent) - int tag_transparent; -{ - pushlevel (tag_transparent); - current_binding_level->keep = 2; - clear_last_expr (); - - /* Note we don't call push_momentary() here. Otherwise, it would cause - cleanups to be allocated on the momentary obstack, and they will be - overwritten by the next statement. */ - - expand_start_bindings (0); -} - /* For a binding between a name and an entity at a block scope, this is the `struct binding_level' for the block. */ #define BINDING_LEVEL(NODE) \ @@ -1458,13 +1443,13 @@ poplevel (keep, reverse, functionbody) /* Take care of compiler's internal binding structures. */ if (tmp == 2) { - expand_end_bindings (getdecls (), keep, 1); + add_scope_stmt (/*begin_p=*/0, /*partial_p=*/1); /* Each and every BLOCK node created here in `poplevel' is important (e.g. for proper debugging information) so if we created one earlier, mark it as "used". */ if (block) TREE_USED (block) = 1; - block = poplevel (keep, reverse, real_functionbody); + block = poplevel (keep, reverse, functionbody); } /* Each and every BLOCK node created here in `poplevel' is important @@ -6874,12 +6859,17 @@ start_decl_1 (decl) if (type == error_mark_node) return; - /* If this type of object needs a cleanup, and control may - jump past it, make a new binding level so that it is cleaned - up only when it is initialized first. */ + /* If this type of object needs a cleanup, but we're not allowed to + add any more objects with cleanups to the current scope, create a + new binding level. */ if (TYPE_NEEDS_DESTRUCTOR (type) && current_binding_level->more_cleanups_ok == 0) - pushlevel_temporary (1); + { + keep_next_level (2); + pushlevel (1); + clear_last_expr (); + add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1); + } if (initialized) /* Is it valid for this decl to have an initializer at all? diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4c91e168232..d015719c73b 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -1248,6 +1248,43 @@ setup_vtbl_ptr () vtbls_set_up_p = 1; } +/* Add a scope-statement to the statement-tree. BEGIN_P indicates + whether this statements opens or closes a scope. PARTIAL_P is true + for a partial scope, i.e, the scope that begins after a label when + an object that needs a cleanup is created. */ + +void +add_scope_stmt (begin_p, partial_p) + int begin_p; + int partial_p; +{ + tree ss; + + /* Build the statement. */ + ss = build_min_nt (SCOPE_STMT); + SCOPE_BEGIN_P (ss) = begin_p; + SCOPE_PARTIAL_P (ss) = partial_p; + + /* If we're finishing a scope, figure out whether the scope was + really necessary. */ + if (!begin_p) + { + SCOPE_NULLIFIED_P (ss) = !kept_level_p (); + SCOPE_NULLIFIED_P (TREE_VALUE (current_scope_stmt_stack)) + = SCOPE_NULLIFIED_P (ss); + } + + /* Keep the scope stack up to date. */ + if (begin_p) + current_scope_stmt_stack + = tree_cons (NULL_TREE, ss, current_scope_stmt_stack); + else + current_scope_stmt_stack = TREE_CHAIN (current_scope_stmt_stack); + + /* Add the new statement to the statement-tree. */ + add_tree (ss); +} + /* Begin a new scope. */ void @@ -1266,13 +1303,7 @@ do_pushlevel () && !current_function->x_whole_function_mode_p) expand_start_bindings (0); else if (building_stmt_tree () && !processing_template_decl) - { - tree ss = build_min_nt (SCOPE_STMT); - SCOPE_BEGIN_P (ss) = 1; - add_tree (ss); - current_scope_stmt_stack - = tree_cons (NULL_TREE, ss, current_scope_stmt_stack); - } + add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0); } } @@ -1290,12 +1321,7 @@ do_poplevel () expand_end_bindings (getdecls (), kept_level_p (), 0); else if (building_stmt_tree () && !processing_template_decl) { - tree ss = build_min_nt (SCOPE_STMT); - SCOPE_NULLIFIED_P (ss) = !kept_level_p (); - SCOPE_NULLIFIED_P (TREE_VALUE (current_scope_stmt_stack)) - = SCOPE_NULLIFIED_P (ss); - add_tree (ss); - current_scope_stmt_stack = TREE_CHAIN (current_scope_stmt_stack); + add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0); /* When not in function-at-a-time mode, expand_end_bindings will warn about unused variables. But, in @@ -2455,7 +2481,8 @@ expand_stmt (t) if (SCOPE_BEGIN_P (t)) expand_start_bindings (2 * SCOPE_NULLIFIED_P (t)); else if (SCOPE_END_P (t)) - expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0); + expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), + SCOPE_PARTIAL_P (t)); break; case RETURN_INIT: diff --git a/gcc/testsuite/g++.old-deja/g++.other/debug5.C b/gcc/testsuite/g++.old-deja/g++.other/debug5.C new file mode 100644 index 00000000000..bf885347b9e --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/debug5.C @@ -0,0 +1,15 @@ +// Build don't link: +// Special g++ Options: -g +// Origin: Mark Mitchell + +struct S +{ + ~S (); +}; + +void f () +{ + t: + S s3; +} + diff --git a/gcc/testsuite/g++.old-deja/g++.other/goto1.C b/gcc/testsuite/g++.old-deja/g++.other/goto1.C new file mode 100644 index 00000000000..77da8e58b90 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/goto1.C @@ -0,0 +1,21 @@ +// Build don't link: +// Origin: Mark Mitchell + +struct S +{ + S (); + ~S (); +}; + +void f () +{ + { + S s1; + + t: + S s2; + ; + } + + goto t; // ERROR - jump avoids initialization of `s1' +} -- 2.11.4.GIT