cp-tree.h (SCOPE_PARTIAL_P): New macro.
authorMark Mitchell <mark@codesourcery.com>
Thu, 21 Oct 1999 08:05:57 +0000 (08:05 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 21 Oct 1999 08:05:57 +0000 (08:05 +0000)
* 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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/semantics.c
gcc/testsuite/g++.old-deja/g++.other/debug5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/goto1.C [new file with mode: 0644]

index 2c146e34a2deb720a9e67baf4c6d23faee37f360..f70308988af2e6d04050d0f396067a66ad8f2ef2 100644 (file)
@@ -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.
index 425ca18dcbd8296238050b00d49cb9c670069796..b71c162101998ba46de3cea0c391c150f4baab39 100644 (file)
@@ -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
index 122b0251ac788fec8f63a2a20882466c4322cade..746e498e212a1b367a8896ae94c2d928701afcad 100644 (file)
@@ -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?
index 4c91e168232133610691d1f47cecb7f95dbb8181..d015719c73bced9c2dc799d7fdfda2fbf000b008 100644 (file)
@@ -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 (file)
index 0000000..bf88534
--- /dev/null
@@ -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 (file)
index 0000000..77da8e5
--- /dev/null
@@ -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'
+}