c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro.
authorJason Merrill <jason@gcc.gnu.org>
Fri, 14 Dec 2001 03:01:59 +0000 (22:01 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 14 Dec 2001 03:01:59 +0000 (22:01 -0500)
        * c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro.

        * Make-lang.in (parse.h): Separate rule, just depend on parse.c.

        Use cleanups to run base and member destructors.
        * init.c (push_base_cleanups): New function, split out from...
        (build_delete): ...here.  Lose !TYPE_HAS_DESTRUCTOR code.
        * decl.c (finish_destructor_body): Move vbase destruction code to
        push_base_cleanups.
        (begin_function_body, finish_function_body): New fns.
        (finish_function): Move [cd]tor handling and call_poplevel to
        finish_function_body.
        (pushdecl): Skip the new level.
        * semantics.c (genrtl_try_block): Don't call end_protect_partials.
        (setup_vtbl_ptr): Call push_base_cleanups.
        * method.c (synthesize_method): Call {begin,end}_function_body.
        * pt.c (tsubst_expr): Handle COMPOUND_STMT_BODY_BLOCK.
        * cp-tree.h: Declare new fns.
        * parse.y (function_body, .begin_function_body): New nonterminals.
        (fndef, pending_inline, function_try_block): Use function_body.
        (ctor_initializer_opt, function_try_block): No longer has a value.
        (base_init): Remove .set_base_init token.
        (.set_base_init, compstmt_or_error): Remove.
        * Make-lang.in (parse.c): Expect two fewer s/r conflicts.

From-SVN: r47987

12 files changed:
gcc/ChangeLog
gcc/c-common.h
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/semantics.c

index 53e29eba48a49db0a33a5144013dcd566bb5483e..7dc7c8ab7ccdf01740e25def611b59828f4d9a7a 100644 (file)
@@ -1,3 +1,7 @@
+2001-12-13  Jason Merrill  <jason@redhat.com>
+
+       * c-common.h (COMPOUND_STMT_BODY_BLOCK): New macro.
+
 2001-12-13  Aldy Hernandez  <aldyh@redhat.com>
 
        * config/rs6000/rs6000.md (eh_set_lr_di): Change scratch
@@ -20,10 +24,10 @@ Thu Dec 13 20:30:08 2001  Richard Kenner  <kenner@vlsi1.ultra.nyu.edu>
 
 2001-12-12  Aldy Hernandez  <aldyh@redhat.com>
 
-        * config/rs6000/rs6000.c (rs6000_override_options): Add
-        SUBSUBTARGET_OVERRIDE_OPTIONS.
+       * config/rs6000/rs6000.c (rs6000_override_options): Add
+       SUBSUBTARGET_OVERRIDE_OPTIONS.
 
-        * config/rs6000/eabialtivec.h: New file.
+       * config/rs6000/eabialtivec.h: New file.
 
        * config/rs6000/linuxaltivec.h: New file.
 
index 5ce8923d51904c5e1dec211d22764506cab449f1..f6e62908ce14ba14a51702f39427b8df13e4a29b 100644 (file)
@@ -37,6 +37,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
       STMT_IS_FULL_EXPR_P (in _STMT)
    2: STMT_LINENO_FOR_FN_P (in _STMT)
    3: SCOPE_NO_CLEANUPS_P (in SCOPE_STMT)
+      COMPOUND_STMT_BODY_BLOCK (in COMPOUND_STMT)
    4: SCOPE_PARTIAL_P (in SCOPE_STMT)
 */
 
@@ -762,6 +763,10 @@ extern tree build_return_stmt                   PARAMS ((tree));
 
 #define COMPOUND_STMT_NO_SCOPE(NODE)   TREE_LANG_FLAG_0 (NODE)
 
+/* Used by the C++ frontend to mark the block around the member
+   initializers and cleanups.  */
+#define COMPOUND_STMT_BODY_BLOCK(NODE) TREE_LANG_FLAG_3 (NODE)
+
 extern void c_expand_asm_operands              PARAMS ((tree, tree, tree, tree, int, const char *, int));
 
 /* These functions must be defined by each front-end which implements
index 1e70a56a63bf88cd53be44e9076b019bd56dbf65..d0332516331b8a4b768d354ede2be829c2627789 100644 (file)
@@ -1,5 +1,28 @@
 2001-12-13  Jason Merrill  <jason@redhat.com>
 
+       * Make-lang.in (parse.h): Separate rule, just depend on parse.c.
+
+       Use cleanups to run base and member destructors.
+       * init.c (push_base_cleanups): New function, split out from...
+       (build_delete): ...here.  Lose !TYPE_HAS_DESTRUCTOR code.
+       * decl.c (finish_destructor_body): Move vbase destruction code to
+       push_base_cleanups.
+       (begin_function_body, finish_function_body): New fns.
+       (finish_function): Move [cd]tor handling and call_poplevel to
+       finish_function_body.
+       (pushdecl): Skip the new level.
+       * semantics.c (genrtl_try_block): Don't call end_protect_partials.
+       (setup_vtbl_ptr): Call push_base_cleanups.
+       * method.c (synthesize_method): Call {begin,end}_function_body.
+       * pt.c (tsubst_expr): Handle COMPOUND_STMT_BODY_BLOCK.
+       * cp-tree.h: Declare new fns.
+       * parse.y (function_body, .begin_function_body): New nonterminals.
+       (fndef, pending_inline, function_try_block): Use function_body.
+       (ctor_initializer_opt, function_try_block): No longer has a value.
+       (base_init): Remove .set_base_init token.
+       (.set_base_init, compstmt_or_error): Remove.
+       * Make-lang.in (parse.c): Expect two fewer s/r conflicts.
+
        * optimize.c (maybe_clone_body): Fix parameter updating.
 
 2001-12-12  Jason Merrill  <jason@redhat.com>
index eb42decff4fe6139989bbfe801c9047fd1e76b38..d848e3a5182a14e1b17bf2387702fe75cdb7e6ad 100644 (file)
@@ -118,8 +118,9 @@ $(srcdir)/cp/cfns.h: $(srcdir)/cp/cfns.gperf
        gperf -o -C -E -k '1-6,$$' -j1 -D -N 'libc_name_p' \
                $(srcdir)/cp/cfns.gperf > $(srcdir)/cp/cfns.h
 
-$(srcdir)/cp/parse.h $(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
-       @echo "Expect 36 shift/reduce conflicts and 58 reduce/reduce conflicts."
+$(srcdir)/cp/parse.h: $(srcdir)/cp/parse.c
+$(srcdir)/cp/parse.c: $(srcdir)/cp/parse.y
+       @echo "Expect 34 shift/reduce conflicts and 58 reduce/reduce conflicts."
        cd $(srcdir)/cp; $(BISON) $(BISONFLAGS) -d -o p$$$$.c parse.y ; \
        grep '^#define[         ]*YYEMPTY' p$$$$.c >> p$$$$.h ; \
        mv -f p$$$$.c parse.c ; mv -f p$$$$.h parse.h
index 1395301d1d929857968f32e14e9dbbb0bbf82ba9..dbe990a2e11c3ab96755cb26dd030f02bf75c72c 100644 (file)
@@ -234,6 +234,8 @@ DEFTREECODE (CTOR_STMT, "ctor_stmt", 'e', 0)
    constructed.  If, after this point, the CLEANUP_DECL goes out of
    scope, the CLEANUP_EXPR must be run.  */
 DEFTREECODE (CLEANUP_STMT, "cleanup_stmt", 'e', 2)
+/* CTOR_INITIALIZER is a placeholder in template code for a call to
+   setup_vtbl_pointer (and appears in all functions, not just ctors).  */
 DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2)
 DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
 DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2)
index b68e0badb21a5f1e8e3478d411e26799e416d597..70b51102b945dc1dbfc5f5c80b3dc4d3b1b0d0aa 100644 (file)
@@ -3677,6 +3677,8 @@ extern tree start_enum                            PARAMS ((tree));
 extern void finish_enum                                PARAMS ((tree));
 extern void build_enumerator                   PARAMS ((tree, tree, tree));
 extern int start_function                      PARAMS ((tree, tree, tree, int));
+extern tree begin_function_body                        PARAMS ((void));
+extern void finish_function_body               PARAMS ((tree));
 extern tree finish_function                    PARAMS ((int));
 extern tree start_method                       PARAMS ((tree, tree, tree));
 extern tree finish_method                      PARAMS ((tree));
@@ -3849,6 +3851,7 @@ extern tree build_new                             PARAMS ((tree, tree, tree, int));
 extern tree build_vec_init                     PARAMS ((tree, tree, int));
 extern tree build_x_delete                     PARAMS ((tree, int, tree));
 extern tree build_delete                       PARAMS ((tree, tree, special_function_kind, int, int));
+extern void push_base_cleanups                 PARAMS ((void));
 extern tree build_vbase_delete                 PARAMS ((tree, tree));
 extern tree build_vec_delete                   PARAMS ((tree, tree, special_function_kind, int));
 extern tree create_temporary_var                PARAMS ((tree));
index 7e9692dbf8b9da56a595cce9690a5017429a602e..c997535a9d5284ff59b42bc1eb817c872b82c0b3 100644 (file)
@@ -4188,8 +4188,8 @@ pushdecl (x)
                     them there.  */
                  struct binding_level *b = current_binding_level->level_chain;
 
-                 if (cleanup_label)
-                   b = b->level_chain;
+                 /* Skip the ctor/dtor cleanup level.  */
+                 b = b->level_chain;
 
                  /* ARM $8.3 */
                  if (b->parm_flag == 1)
@@ -13920,106 +13920,29 @@ save_function_data (decl)
     }
 }
 
-/* At the end of every constructor we generate to code to return
-   `this'.  Do that now.  */
+/* Add a note to mark the end of the main body of the constructor.  This is
+   used to end the cleanup regions for fully-constructed bases and
+   members.  */
 
 static void
 finish_constructor_body ()
 {
-  /* Mark the end of the constructor.  */
+  /* Mark the end of the cleanups for a partially constructed object.
+
+     ??? These should really be handled automatically by closing the block,
+     as with the destructor cleanups; the only difference is that these are
+     only run if an exception is thrown.  */
   add_stmt (build_stmt (CTOR_STMT));
 }
 
-/* At the end of every destructor we generate code to restore virtual
-   function tables to the values desired by base classes and to call
-   to base class destructors.  Do that now.  */
+/* At the end of every destructor we generate code to delete the object if
+   necessary.  Do that now.  */
 
 static void
 finish_destructor_body ()
 {
-  tree compound_stmt;
   tree exprstmt;
 
-  /* Create a block to contain all the extra code.  */
-  compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
-
-  /* Any return from a destructor will end up here.  */
-  add_stmt (build_stmt (LABEL_STMT, dtor_label));
-
-  /* Generate the code to call destructor on base class.  If this
-     destructor belongs to a class with virtual functions, then set
-     the virtual function table pointer to represent the type of our
-     base class.  */
-
-  /* This side-effect makes call to `build_delete' generate the code
-     we have to have at the end of this destructor.  `build_delete'
-     will set the flag again.  */
-  TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
-
-  exprstmt = build_delete (current_class_type,
-                          current_class_ref,
-                          sfk_base_destructor,
-                          LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
-                          0);
-
-  if (exprstmt != error_mark_node
-      && (TREE_CODE (exprstmt) != NOP_EXPR
-         || TREE_OPERAND (exprstmt, 0) != integer_zero_node
-         || TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
-    {
-      if (exprstmt != void_zero_node)
-       /* Don't call `expand_expr_stmt' if we're not going to do
-          anything, since -Wall will give a diagnostic.  */
-       finish_expr_stmt (exprstmt);
-
-      /* Run destructors for all virtual baseclasses.  */
-      if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
-       {
-         tree vbases;
-         tree if_stmt;
-
-         if_stmt = begin_if_stmt ();
-         finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
-                                     current_in_charge_parm,
-                                     integer_two_node),
-                              if_stmt);
-
-         vbases = CLASSTYPE_VBASECLASSES (current_class_type);
-         /* The CLASSTYPE_VBASECLASSES list is in initialization
-            order, so we have to march through it in reverse order.  */
-         for (vbases = nreverse (copy_list (vbases));
-              vbases;
-              vbases = TREE_CHAIN (vbases))
-           {
-             tree vbase = TREE_VALUE (vbases);
-             tree base_type = BINFO_TYPE (vbase);
-
-             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
-               {
-                  tree base_ptr_type = build_pointer_type (base_type);
-                 tree expr = current_class_ptr;
-                 
-                 /* Convert to the basetype here, as we know the layout is
-                     fixed. What is more, if we let build_method_call do it,
-                     it will use the vtable, which may have been clobbered
-                     by the deletion of our primary base.  */
-                  
-                  expr = build1 (NOP_EXPR, base_ptr_type, expr);
-                 expr = build (PLUS_EXPR, base_ptr_type, expr,
-                               BINFO_OFFSET (vbase));
-                 expr = build_indirect_ref (expr, NULL);
-                 expr = build_method_call (expr, base_dtor_identifier,
-                                           NULL_TREE, vbase,
-                                           LOOKUP_NORMAL);
-                 finish_expr_stmt (expr);
-               }
-           }
-
-         finish_then_clause (if_stmt);
-         finish_if_stmt ();
-       }
-    }
-
   /* In a virtual destructor, we must call delete.  */
   if (DECL_VIRTUAL_P (current_function_decl))
     {
@@ -14028,10 +13951,10 @@ finish_destructor_body ()
 
       /* [class.dtor]
 
-        At the point of definition of a virtual destructor (including
-        an implicit definition), non-placement operator delete shall
-        be looked up in the scope of the destructor's class and if
-        found shall be accessible and unambiguous.  */
+      At the point of definition of a virtual destructor (including
+      an implicit definition), non-placement operator delete shall
+      be looked up in the scope of the destructor's class and if
+      found shall be accessible and unambiguous.  */
       exprstmt = build_op_delete_call
        (DELETE_EXPR, current_class_ptr, virtual_size,
         LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
@@ -14045,20 +13968,58 @@ finish_destructor_body ()
       finish_then_clause (if_stmt);
       finish_if_stmt ();
     }
+}
 
-  /* Close the block we started above.  */
-  finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
+/* Do the necessary processing for the beginning of a function body, which
+   in this case includes member-initializers, but not the catch clauses of
+   a function-try-block.  Currently, this means opening a binding level
+   for the member-initializers (in a ctor) and member cleanups (in a dtor).
+   In other functions, this isn't necessary, but it doesn't hurt.  */
+
+tree
+begin_function_body ()
+{
+  tree stmt = begin_compound_stmt (0);
+  COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
+  return stmt;
 }
 
+/* Do the processing for the end of a function body.  Currently, this means
+   closing out the cleanups for fully-constructed bases and members, and in
+   the case of the destructor, deleting the object if desired.  Again, this
+   is only meaningful for [cd]tors, since they are the only functions where
+   there is a significant distinction between the main body and any
+   function catch clauses.  Handling, say, main() return semantics here
+   would be wrong, as flowing off the end of a function catch clause for
+   main() would also need to return 0.  */
+
+void
+finish_function_body (compstmt)
+     tree compstmt;
+{
+  if (processing_template_decl)
+    /* Do nothing now.  */;
+  else if (DECL_DESTRUCTOR_P (current_function_decl))
+    /* Any return from a destructor will end up here.  Put it before the
+       cleanups so that an explicit return doesn't duplicate them.  */
+    add_stmt (build_stmt (LABEL_STMT, dtor_label));
+
+  /* Close the block; in a destructor, run the member cleanups.  */
+  finish_compound_stmt (0, compstmt);
+
+  if (processing_template_decl)
+    /* Do nothing now.  */;
+  else if (DECL_CONSTRUCTOR_P (current_function_decl))
+    finish_constructor_body ();
+  else if (DECL_DESTRUCTOR_P (current_function_decl))
+    finish_destructor_body ();
+}  
+
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
    for the function definition.
 
    FLAGS is a bitwise or of the following values:
-     1 - CALL_POPLEVEL
-       An extra call to poplevel (and expand_end_bindings) must be
-       made to take care of the binding contour for the base
-       initializers.  This is only relevant for constructors.
      2 - INCLASS_INLINE
        We just finished processing the body of an in-class inline
        function definition.  (This processing will have taken place
@@ -14070,7 +14031,6 @@ finish_function (flags)
 {
   register tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
-  int call_poplevel = (flags & 1) != 0;
   int inclass_inline = (flags & 2) != 0;
   int nested;
 
@@ -14094,15 +14054,7 @@ finish_function (flags)
      there's no need to add any extra bits.  */
   if (!DECL_CLONED_FUNCTION_P (fndecl))
     {
-      if (DECL_CONSTRUCTOR_P (fndecl))
-       {
-         finish_constructor_body ();
-         if (call_poplevel)
-           do_poplevel ();
-       }
-      else if (DECL_DESTRUCTOR_P (fndecl) && !processing_template_decl)
-       finish_destructor_body ();
-      else if (DECL_MAIN_P (fndecl))
+      if (DECL_MAIN_P (current_function_decl))
        {
          /* Make it so that `main' always returns 0 by default.  */
 #ifdef VMS_TARGET
index 098697fa5a7c309206f1d7f40c2559d1b8f9f4f3..c0cc3f300bcb5570cfccb44abf9cd6e3ba64a4e7 100644 (file)
@@ -3078,9 +3078,7 @@ build_dtor_call (exp, dtor_kind, flags)
    sfk_deleting_destructor.
 
    FLAGS is the logical disjunction of zero or more LOOKUP_
-   flags.  See cp-tree.h for more info.
-
-   This function does not delete an object's virtual base classes.  */
+   flags.  See cp-tree.h for more info.  */
 
 tree
 build_delete (type, addr, auto_delete, flags, use_global_delete)
@@ -3089,7 +3087,6 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
      int flags;
      int use_global_delete;
 {
-  tree member;
   tree expr;
 
   if (addr == error_mark_node)
@@ -3157,15 +3154,13 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
         LOOKUP_NORMAL | (use_global_delete * LOOKUP_GLOBAL),
         NULL_TREE);
     }
-
-  /* Below, we will reverse the order in which these calls are made.
-     If we have a destructor, then that destructor will take care
-     of the base classes; otherwise, we must do that here.  */
-  if (TYPE_HAS_DESTRUCTOR (type))
+  else
     {
       tree do_delete = NULL_TREE;
       tree ifexp;
 
+      my_friendly_assert (TYPE_HAS_DESTRUCTOR (type), 20011213);
+
       /* For `::delete x', we must not use the deleting destructor
         since then we would not be sure to get the global `operator
         delete'.  */
@@ -3215,56 +3210,98 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
 
       return expr;
     }
-  else
-    {
-      /* We only get here from finish_function for a destructor.  */
-      tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));
-      int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type);
-      tree base_binfo = n_baseclasses > 0 ? TREE_VEC_ELT (binfos, 0) : NULL_TREE;
-      tree exprstmt = NULL_TREE;
-      tree ref = build_indirect_ref (addr, NULL);
+}
 
-      /* Set this again before we call anything, as we might get called
-        recursively.  */
-      TYPE_HAS_DESTRUCTOR (type) = 1;
+/* At the beginning of a destructor, push cleanups that will call the
+   destructors for our base classes and members.
 
-      /* If we have member delete or vbases, we call delete in
-        finish_function.  */
-      my_friendly_assert (auto_delete == sfk_base_destructor, 20000411);
+   Called from setup_vtbl_ptr.  */
 
-      /* Take care of the remaining baseclasses.  */
-      for (i = 0; i < n_baseclasses; i++)
-       {
-         base_binfo = TREE_VEC_ELT (binfos, i);
-         if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
-             || TREE_VIA_VIRTUAL (base_binfo))
-           continue;
-
-         expr = build_scoped_method_call (ref, base_binfo,
-                                          base_dtor_identifier,
-                                          NULL_TREE);
+void
+push_base_cleanups ()
+{
+  tree binfos;
+  int i, n_baseclasses;
+  tree member;
+  tree expr;
 
-         exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
-       }
+  /* Run destructors for all virtual baseclasses.  */
+  if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
+    {
+      tree vbases;
+      tree cond = (condition_conversion
+                  (build (BIT_AND_EXPR, integer_type_node,
+                          current_in_charge_parm,
+                          integer_two_node)));
 
-      for (member = TYPE_FIELDS (type); member; member = TREE_CHAIN (member))
+      vbases = CLASSTYPE_VBASECLASSES (current_class_type);
+      /* The CLASSTYPE_VBASECLASSES list is in initialization
+        order, which is also the right order for pushing cleanups.  */
+      for (; vbases;
+          vbases = TREE_CHAIN (vbases))
        {
-         if (TREE_CODE (member) != FIELD_DECL)
-           continue;
-         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+         tree vbase = TREE_VALUE (vbases);
+         tree base_type = BINFO_TYPE (vbase);
+
+         if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
            {
-             tree this_member = build_component_ref (ref, DECL_NAME (member), NULL_TREE, 0);
-             tree this_type = TREE_TYPE (member);
-             expr = build_delete (this_type, this_member,
-                                  sfk_complete_destructor, flags, 0);
-             exprstmt = tree_cons (NULL_TREE, expr, exprstmt);
+             tree base_ptr_type = build_pointer_type (base_type);
+             expr = current_class_ptr;
+                 
+             /* Convert to the basetype here, as we know the layout is
+                fixed. What is more, if we let build_method_call do it,
+                it will use the vtable, which may have been clobbered
+                by the deletion of our primary base.  */
+                  
+             expr = build1 (NOP_EXPR, base_ptr_type, expr);
+             expr = build (PLUS_EXPR, base_ptr_type, expr,
+                           BINFO_OFFSET (vbase));
+             expr = build_indirect_ref (expr, NULL);
+             expr = build_method_call (expr, base_dtor_identifier,
+                                       NULL_TREE, vbase,
+                                       LOOKUP_NORMAL);
+             expr = build (COND_EXPR, void_type_node, cond,
+                           expr, void_zero_node);
+             finish_decl_cleanup (NULL_TREE, expr);
            }
        }
+    }
+
+  binfos = BINFO_BASETYPES (TYPE_BINFO (current_class_type));
+  n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
 
-      if (exprstmt)
-       return build_compound_expr (exprstmt);
-      /* Virtual base classes make this function do nothing.  */
-      return void_zero_node;
+  /* Take care of the remaining baseclasses.  */
+  for (i = 0; i < n_baseclasses; i++)
+    {
+      tree base_binfo = TREE_VEC_ELT (binfos, i);
+      if (TYPE_HAS_TRIVIAL_DESTRUCTOR (BINFO_TYPE (base_binfo))
+         || TREE_VIA_VIRTUAL (base_binfo))
+       continue;
+
+      expr = build_scoped_method_call (current_class_ref, base_binfo,
+                                      base_dtor_identifier,
+                                      NULL_TREE);
+
+      finish_decl_cleanup (NULL_TREE, expr);
+    }
+
+  for (member = TYPE_FIELDS (current_class_type); member;
+       member = TREE_CHAIN (member))
+    {
+      if (TREE_CODE (member) != FIELD_DECL)
+       continue;
+      if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (member)))
+       {
+         tree this_member = (build_component_ref
+                             (current_class_ref, DECL_NAME (member),
+                              NULL_TREE, 0));
+         tree this_type = TREE_TYPE (member);
+         expr = build_delete (this_type, this_member,
+                              sfk_complete_destructor,
+                              LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
+                              0);
+         finish_decl_cleanup (NULL_TREE, expr);
+       }
     }
 }
 
index 0cef1e3d5e1b8ddcfde1d58addb1b8d13c97c742..9dbf1e35aa24208b30bc7ba8204c09771a130e8e 100644 (file)
@@ -727,6 +727,7 @@ synthesize_method (fndecl)
   int nested = (current_function_decl != NULL_TREE);
   tree context = decl_function_context (fndecl);
   int need_body = 1;
+  tree stmt;
 
   if (at_eof)
     import_export_decl (fndecl);
@@ -757,6 +758,7 @@ synthesize_method (fndecl)
   interface_unknown = 1;
   start_function (NULL_TREE, fndecl, NULL_TREE, SF_DEFAULT | SF_PRE_PARSED);
   clear_last_expr ();
+  stmt = begin_function_body ();
 
   if (DECL_OVERLOADED_OPERATOR_P (fndecl) == NOP_EXPR)
     {
@@ -783,6 +785,7 @@ synthesize_method (fndecl)
       finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
     }
 
+  finish_function_body (stmt);
   expand_body (finish_function (0));
 
   extract_interface_info ();
index 28a1456663fd00d155ceb351d567f82eb402fc39..b49f6eb87a56fb56a1d4b5e1c725fe8ab145a60b 100644 (file)
@@ -385,7 +385,7 @@ cp_parse_init ()
 %token <pi> PRE_PARSED_FUNCTION_DECL 
 %type <ttype> component_constructor_declarator
 %type <ttype> fn.def2 return_id constructor_declarator
-%type <itype> ctor_initializer_opt function_try_block
+%type <ttype> .begin_function_body
 %type <ttype> named_class_head_sans_basetype
 %type <ftype> class_head named_class_head 
 %type <ftype> named_complex_class_head_sans_basetype 
@@ -747,9 +747,7 @@ datadef:
 
 ctor_initializer_opt:
          nodecls
-               { $$ = 0; }
        | base_init
-               { $$ = 1; }
        ;
 
 maybe_return_init:
@@ -763,11 +761,18 @@ eat_saved_input:
        | END_OF_SAVED_INPUT
        ;
 
+function_body:
+         .begin_function_body ctor_initializer_opt compstmt
+               {
+                 finish_function_body ($1);
+               }
+       ;
+
 fndef:
-         fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
-               { expand_body (finish_function ((int)$3)); }
+         fn.def1 maybe_return_init function_body
+               { expand_body (finish_function (0)); }
        | fn.def1 maybe_return_init function_try_block
-               { expand_body (finish_function ((int)$3)); }
+               { expand_body (finish_function (0)); }
        | fn.def1 maybe_return_init error
                { }
        ;
@@ -890,25 +895,21 @@ return_init:
        ;
 
 base_init:
-         ':' .set_base_init member_init_list
+         ':' member_init_list
                {
-                 if ($3.new_type_flag == 0)
+                 if (! DECL_CONSTRUCTOR_P (current_function_decl))
+                   error ("only constructors take base initializers");
+                 else if ($2.new_type_flag == 0)
                    error ("no base or member initializers given following ':'");
 
-                 finish_mem_initializers ($3.t);
+                 finish_mem_initializers ($2.t);
                }
        ;
 
-.set_base_init:
+.begin_function_body:
          /* empty */
                {
-                 if (DECL_CONSTRUCTOR_P (current_function_decl))
-                   /* Make a contour for the initializer list.  */
-                   do_pushlevel ();
-                 else if (current_class_type == NULL_TREE)
-                   error ("base initializers not allowed for non-member functions");
-                 else if (! DECL_CONSTRUCTOR_P (current_function_decl))
-                   error ("only constructors take base initializers");
+                 $$ = begin_function_body ();
                }
        ;
 
@@ -2208,14 +2209,14 @@ initlist:
        ;
 
 pending_inline:
-         PRE_PARSED_FUNCTION_DECL maybe_return_init ctor_initializer_opt compstmt_or_error
+         PRE_PARSED_FUNCTION_DECL maybe_return_init function_body
                {
-                 expand_body (finish_function ((int)$3 | 2));
+                 expand_body (finish_function (2));
                  process_next_inline ($1);
                }
        | PRE_PARSED_FUNCTION_DECL maybe_return_init function_try_block
                { 
-                 expand_body (finish_function ((int)$3 | 2)); 
+                 expand_body (finish_function (2)); 
                   process_next_inline ($1);
                }
        | PRE_PARSED_FUNCTION_DECL maybe_return_init error
@@ -3328,13 +3329,6 @@ label_decl:
                }
        ;
 
-/* This is the body of a function definition.
-   It causes syntax errors to ignore to the next openbrace.  */
-compstmt_or_error:
-         compstmt
-       | error compstmt
-       ;
-
 compstmt:
          save_lineno '{'
                 { $<ttype>$ = begin_compound_stmt (0); }
@@ -3499,13 +3493,10 @@ simple_stmt:
 function_try_block:
          TRY
                { $<ttype>$ = begin_function_try_block (); }
-         ctor_initializer_opt compstmt
+         function_body
                { finish_function_try_block ($<ttype>2); }
          handler_seq
-               {
-                 finish_function_handler_sequence ($<ttype>2);
-                 $$ = $3;
-               }
+               { finish_function_handler_sequence ($<ttype>2); }
        ;
 
 try_block:
index 48f39518ab4976dad9c3d7acce63af38e5392e52..79a413b27be7bd7216370ef87514f82b46f9e1ab 100644 (file)
@@ -7389,9 +7389,17 @@ tsubst_expr (t, args, complain, in_decl)
     case COMPOUND_STMT:
       {
        prep_stmt (t);
-       stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+       if (COMPOUND_STMT_BODY_BLOCK (t))
+         stmt = begin_function_body ();
+       else
+         stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+
        tsubst_expr (COMPOUND_BODY (t), args, complain, in_decl);
-       finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
+
+       if (COMPOUND_STMT_BODY_BLOCK (t))
+         finish_function_body (stmt);
+       else
+         finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
       }
       break;
 
@@ -7517,7 +7525,7 @@ tsubst_expr (t, args, complain, in_decl)
     case CTOR_STMT:
       add_stmt (copy_node (t));
       break;
-      
+
     default:
       abort ();
     }
index 8dc792adb3127ba7531b9d54185a2fd2116a462e..bbd43e993290a45cc968e81b686bb00ae68b6f0a 100644 (file)
@@ -580,7 +580,6 @@ genrtl_try_block (t)
 
       if (FN_TRY_BLOCK_P (t))
        {
-         end_protect_partials ();
          expand_start_all_catch ();
          in_function_try_handler = 1;
          expand_stmt (TRY_HANDLERS (t));
@@ -1216,6 +1215,10 @@ setup_vtbl_ptr (member_init_list, base_init_list)
       finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
       finish_then_clause (if_stmt);
       finish_if_stmt ();
+
+      /* And insert cleanups for our bases and members so that they
+         will be properly destroyed if we throw.  */
+      push_base_cleanups ();
     }
 
   /* Always keep the BLOCK node associated with the outermost pair of
@@ -2559,8 +2562,6 @@ static void
 genrtl_start_function (fn)
      tree fn;
 {
-  tree parm;
-
   /* Tell everybody what function we're processing.  */
   current_function_decl = fn;
   /* Get the RTL machinery going for this function.  */