aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-10-21 08:05:57 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-10-21 08:05:57 +0000
commit8f471b0d0f739afb82360cfef9fc44479bea3c50 (patch)
treea7226b57f6affb547543c6a726c4112b3877d63f /gcc
parent070cd782ac3d0c321937088b45b142c7831eec44 (diff)
downloadgcc-8f471b0d0f739afb82360cfef9fc44479bea3c50.zip
gcc-8f471b0d0f739afb82360cfef9fc44479bea3c50.tar.gz
gcc-8f471b0d0f739afb82360cfef9fc44479bea3c50.tar.bz2
cp-tree.h (SCOPE_PARTIAL_P): New macro.
* 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. From-SVN: r30118
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog11
-rw-r--r--gcc/cp/cp-tree.h18
-rw-r--r--gcc/cp/decl.c32
-rw-r--r--gcc/cp/semantics.c55
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/debug5.C15
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/goto1.C21
6 files changed, 116 insertions, 36 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2c146e3..f703089 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,16 @@
1999-10-21 Mark Mitchell <mark@codesourcery.com>
+ * 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 425ca18..b71c162 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 122b025..746e498 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 4c91e16..d015719 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 0000000..bf88534
--- /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 <mark@codesourcery.com>
+
+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 0000000..77da8e5
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/goto1.C
@@ -0,0 +1,21 @@
+// Build don't link:
+// Origin: Mark Mitchell <mark@codesourcery.com>
+
+struct S
+{
+ S ();
+ ~S ();
+};
+
+void f ()
+{
+ {
+ S s1;
+
+ t:
+ S s2;
+ ;
+ }
+
+ goto t; // ERROR - jump avoids initialization of `s1'
+}