cp-tree.def (STMT_EXPR): New tree node.
authorMark Mitchell <mark@codesourcery.com>
Mon, 16 Aug 1999 19:01:36 +0000 (19:01 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 16 Aug 1999 19:01:36 +0000 (19:01 +0000)
* cp-tree.def (STMT_EXPR): New tree node.
* cp-tree.h (STMT_EXPR_STMT): New macro.
(store_return_init): Change prototype.
(finish_named_return_value): New function.
(expand_stmt): Likewise.
(expand_body): Likewise.
(begin_stmt_tree): Likewise.
(finish_stmt_tree): Likewise.
(expanding_p): New variable.
(last_expr_type): Likewise.
(building_stmt_tree): New macro.
* decl.c (start_function): Use building_stmt_tree, not
processing_template_decl, where appropriate.
(store_parm_decls): Likewise.
(store_return_init): Move most of the body to semantics.c.
(finish_function): Use building_stmt_tree.
(finish_stmt): Clear last_expr_type here.
(cp_function): Add expanding_p, last_tree, last_expr_type.
(push_cp_function_context): Save them.
(pop_cp_function_context): Restore them.
* decl2.c (setup_vtbl_ptr): Move to semantics.c.
* error.c (dump_expr): Handle STMT_EXPR.
* except.c (expand_start_catch_block): Use building_stmt_tree.
Use add_decl_stmt.
* expr.c (cplus_expand_expr): Handle STMT_EXPR.
(do_case): Move add_tree call to semantics.c.
* parse.y (return_init): Use finish_named_return_value.
(for.init.statement): Use finish_expr_stmt.
* parse.c: Regenerated.
* pt.c (do_pushlevel): Move to semantics.c.
(do_poplevel): Likewise.
(tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR.
(tsubst_expr): Don't expand all the way to RTL here.  Handle
RETURN_INIT and CTOR_INITIALIZER.
(instantiate_decl): Call expand_body after tsubst'ing into
DECL_SAVED_TREE.
* semantics.c (expand_stmts): New function.
(expanding_p): New variable.
(last_expr_type): Likewise.
(finish_expr_stmt): Use building_stmt_tree.
(begin_if_stmt): Likewise.
(finish_if_stmt_cond): Likewise.
(finish_then_clause): Likewise.
(begin_else_clause): Likewise.
(finish_else_clause): Likewise.
(begin_while_stmt): Likewise.
(finish_while_stmt_cond): Likewise.
(finish_while_stmt): Likewise.
(finish_do_body): Likewise.
(finish_do_stmt): Likewise.
(finish_return_stmt): Likewise.
(begin_for_stmt): Likewise.
(fnish_for_init_stmt): Likewise.
(finish_for_cond): Likewise.
(finish_for_expr): Likewise.
(finish_for_stmt): Likewise.
(finish_break_stmt): Likewise.
(finish_continue_stmt): Likewise.
(finish_switch_cond): Likewise.
(finish_switch_stmt): Likewise.
(finish_case_label): Call add_tree here if necessary.
(finish_goto_statement): Use building_stmt_tree.
(begin_try_block): Likewise.
(begin_function_try_block): Likewise.
(finish_try_block): Likewise.
(finish_function_try_block): Likewise.
(finish_handler_sequence): Likewise.
(finish_function_handler_sequence): Likewise.
(begin_handler): Likewise.
(finish_handler_parms): Likewise.
(finish_handler): Likewise.
(begin_compound_stmt): Likewise.
(finish_compound_stmt): Likewise.
(finish_asm_stmt): Likewise.
(finish_label_stmt): Likewise.
(finish_named_return_value): New function.
(setup_vtbl_ptr): Moved here from decl2.c.
(do_pushlevel): Moved here from pt.c.
(do_poplevel): Likewise.
(begin_stmt_expr): Use building_stmt_tree.
(finish_stmt_expr): Likewise.  Build a STMT_EXPR, not a BIND_EXPR,
when building_stmt_tree.
(begin_stmt_tree): New function.
(finish_stmt_tree): Likewise.
(expand_stmt): Likewise.
(expand_body): Likewise.
* tree.c (build_cplus_method_type): Make sure the argument types
end up on the same obstack as the METHOD_TYPE.
(search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR,
THROW_EXPR, STMT_EXPR.
(mapcar): Break out common cases.  Handle COMPOUND_EXPR,
MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR.  Abort, rather than
sorry, if an unsupported node is encountered.
* typeck.c (require_complete_type_in_void): Handle BIND_EXPR.
(c_expand_return): Don't call add_tree here.

From-SVN: r28729

14 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/expr.c
gcc/cp/parse.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/cp/tree.c
gcc/cp/typeck.c

index f80f3748415512645bb9692150c6141bb0ff53fa..bf6c0ac1f384cda355758ad188294bd130cf8054 100644 (file)
@@ -1,3 +1,101 @@
+1999-08-16  Mark Mitchell  <mark@codesourcery.com>
+
+       * cp-tree.def (STMT_EXPR): New tree node.
+       * cp-tree.h (STMT_EXPR_STMT): New macro.
+       (store_return_init): Change prototype.
+       (finish_named_return_value): New function.
+       (expand_stmt): Likewise.
+       (expand_body): Likewise.
+       (begin_stmt_tree): Likewise.
+       (finish_stmt_tree): Likewise.
+       (expanding_p): New variable.
+       (last_expr_type): Likewise.
+       (building_stmt_tree): New macro.
+       * decl.c (start_function): Use building_stmt_tree, not
+       processing_template_decl, where appropriate.
+       (store_parm_decls): Likewise.
+       (store_return_init): Move most of the body to semantics.c.
+       (finish_function): Use building_stmt_tree.
+       (finish_stmt): Clear last_expr_type here.
+       (cp_function): Add expanding_p, last_tree, last_expr_type.
+       (push_cp_function_context): Save them.
+       (pop_cp_function_context): Restore them.
+       * decl2.c (setup_vtbl_ptr): Move to semantics.c.
+       * error.c (dump_expr): Handle STMT_EXPR.
+       * except.c (expand_start_catch_block): Use building_stmt_tree.
+       Use add_decl_stmt.
+       * expr.c (cplus_expand_expr): Handle STMT_EXPR.
+       (do_case): Move add_tree call to semantics.c.
+       * parse.y (return_init): Use finish_named_return_value.
+       (for.init.statement): Use finish_expr_stmt.
+       * parse.c: Regenerated.
+       * pt.c (do_pushlevel): Move to semantics.c.
+       (do_poplevel): Likewise.
+       (tsubst_copy): Handle STMT_EXPR instead of BIND_EXPR.
+       (tsubst_expr): Don't expand all the way to RTL here.  Handle
+       RETURN_INIT and CTOR_INITIALIZER.
+       (instantiate_decl): Call expand_body after tsubst'ing into
+       DECL_SAVED_TREE.
+       * semantics.c (expand_stmts): New function.
+       (expanding_p): New variable.
+       (last_expr_type): Likewise.
+       (finish_expr_stmt): Use building_stmt_tree.
+       (begin_if_stmt): Likewise.
+       (finish_if_stmt_cond): Likewise.
+       (finish_then_clause): Likewise.
+       (begin_else_clause): Likewise.
+       (finish_else_clause): Likewise.
+       (begin_while_stmt): Likewise.
+       (finish_while_stmt_cond): Likewise.
+       (finish_while_stmt): Likewise.
+       (finish_do_body): Likewise.
+       (finish_do_stmt): Likewise.
+       (finish_return_stmt): Likewise.
+       (begin_for_stmt): Likewise.
+       (fnish_for_init_stmt): Likewise.
+       (finish_for_cond): Likewise.
+       (finish_for_expr): Likewise.
+       (finish_for_stmt): Likewise.
+       (finish_break_stmt): Likewise.
+       (finish_continue_stmt): Likewise.
+       (finish_switch_cond): Likewise.
+       (finish_switch_stmt): Likewise.
+       (finish_case_label): Call add_tree here if necessary.
+       (finish_goto_statement): Use building_stmt_tree.
+       (begin_try_block): Likewise.
+       (begin_function_try_block): Likewise.
+       (finish_try_block): Likewise.
+       (finish_function_try_block): Likewise.
+       (finish_handler_sequence): Likewise.
+       (finish_function_handler_sequence): Likewise.
+       (begin_handler): Likewise.
+       (finish_handler_parms): Likewise.
+       (finish_handler): Likewise.
+       (begin_compound_stmt): Likewise.
+       (finish_compound_stmt): Likewise.
+       (finish_asm_stmt): Likewise.
+       (finish_label_stmt): Likewise.
+       (finish_named_return_value): New function.
+       (setup_vtbl_ptr): Moved here from decl2.c.
+       (do_pushlevel): Moved here from pt.c.
+       (do_poplevel): Likewise.
+       (begin_stmt_expr): Use building_stmt_tree.
+       (finish_stmt_expr): Likewise.  Build a STMT_EXPR, not a BIND_EXPR,
+       when building_stmt_tree.
+       (begin_stmt_tree): New function.
+       (finish_stmt_tree): Likewise.
+       (expand_stmt): Likewise.
+       (expand_body): Likewise.
+       * tree.c (build_cplus_method_type): Make sure the argument types
+       end up on the same obstack as the METHOD_TYPE.
+       (search_tree): Handle COMPOUND_EXPR, MODIFY_EXPR,
+       THROW_EXPR, STMT_EXPR.
+       (mapcar): Break out common cases.  Handle COMPOUND_EXPR,
+       MODIFY_EXPR, THROW_EXPR, STMT_EXPR, RTL_EXPR.  Abort, rather than
+       sorry, if an unsupported node is encountered.
+       * typeck.c (require_complete_type_in_void): Handle BIND_EXPR.
+       (c_expand_return): Don't call add_tree here.
+       
 1999-08-15  Mark Mitchell  <mark@codesourcery.com>
 
        * pt.c (check_default_tmpl_args): Don't check in local scopes.
index fecbbe5be58cb4e9f363e9d14474d79af37889de..19709222e469b620f9735e6749cad56974c2a399 100644 (file)
@@ -235,6 +235,10 @@ DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
 DEFTREECODE (TRY_BLOCK, "try_stmt", 'e', 2)
 DEFTREECODE (HANDLER, "catch_stmt", 'e', 2)
 
+/* A STMT_EXPR represents a statement-expression.  The
+   STMT_EXPR_STMT is the statement given by the expression.  */
+DEFTREECODE (STMT_EXPR, "cp_stmt_expr", 'e', 1)
+
 DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
 
 /* And some codes for expressing conversions for overload resolution.  */
index 82022fadd3ce7c7f3a446f81326b06a7187c205b..486701324edd49f7406fb3a499cec6c3614c5562 100644 (file)
@@ -2138,6 +2138,7 @@ extern int flag_new_for_scope;
 #define ASM_INPUTS(NODE)        TREE_OPERAND (NODE, 3)
 #define ASM_CLOBBERS(NODE)      TREE_OPERAND (NODE, 4)
 #define DECL_STMT_DECL(NODE)    TREE_OPERAND (NODE, 0)
+#define STMT_EXPR_STMT(NODE)    TREE_OPERAND (NODE, 0)
 
 /* Nonzero for an ASM_STMT if the assembly statement is volatile.  */
 #define ASM_VOLATILE_P(NODE)                   \
@@ -2919,7 +2920,7 @@ extern tree build_enumerator                      PROTO((tree, tree, tree));
 extern int start_function                      PROTO((tree, tree, tree, int));
 extern void expand_start_early_try_stmts       PROTO((void));
 extern void store_parm_decls                   PROTO((void));
-extern void store_return_init                  PROTO((tree, tree));
+extern void store_return_init                  PROTO((tree));
 extern void finish_function                    PROTO((int, int, int));
 extern tree start_method                       PROTO((tree, tree, tree));
 extern tree finish_method                      PROTO((tree));
@@ -3365,6 +3366,17 @@ extern void finish_member_declaration           PROTO((tree));
 extern void check_multiple_declarators          PROTO((void));
 extern tree finish_typeof                      PROTO((tree));
 extern void add_decl_stmt                       PROTO((tree));
+extern void finish_named_return_value           PROTO((tree, tree));
+extern tree expand_stmt                         PROTO((tree));
+extern void expand_body                         PROTO((tree));
+extern void begin_stmt_tree                     PROTO((tree));
+extern void finish_stmt_tree                    PROTO((tree));
+extern int expanding_p;
+extern tree last_expr_type;
+/* Non-zero if we are presently building a statement tree, rather
+   than expanding each statement as we encounter it.  */
+#define building_stmt_tree() \
+  (processing_template_decl || !expanding_p)
 
 /* in spew.c */
 extern void init_spew                          PROTO((void));
index 6fb61f72eb77910233fb1eb4cf72982d7dc98c1c..374717cc1a6d5beaa13b2979e823350b46c82c50 100644 (file)
@@ -4341,7 +4341,7 @@ maybe_push_decl (decl)
        && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
       || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
       || TREE_CODE (type) == UNKNOWN_TYPE
-      /* The declaration of template specializations does not affect
+      /* The declaration of a template specialization does not affect
         the functions available for overload resolution, so we do not
         call pushdecl.  */
       || (TREE_CODE (decl) == FUNCTION_DECL
@@ -12882,7 +12882,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
       && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
     cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
 
-  announce_function (decl1);
+  if (!building_stmt_tree ())
+    announce_function (decl1);
 
   /* Set up current_class_type, and enter the scope of the class, if
      appropriate.  */
@@ -13110,12 +13111,14 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
   pushlevel (0);
   current_binding_level->parm_flag = 1;
 
-  GNU_xref_function (decl1, current_function_parms);
-
   if (attrs)
     cplus_decl_attributes (decl1, NULL_TREE, attrs);
   
-  make_function_rtl (decl1);
+  if (!building_stmt_tree ())
+    {
+      GNU_xref_function (decl1, current_function_parms);
+      make_function_rtl (decl1);
+    }
 
   /* Promote the value to int before returning it.  */
   if (C_PROMOTING_INTEGER_TYPE_P (restype))
@@ -13141,9 +13144,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
   if (! hack_decl_function_context (decl1))
     temporary_allocation ();
 
-  if (processing_template_decl)
-    last_tree = DECL_SAVED_TREE (decl1)
-      = build_nt (EXPR_STMT, void_zero_node);
+  if (building_stmt_tree ())
+    begin_stmt_tree (decl1);
 
   ++function_depth;
 
@@ -13254,7 +13256,7 @@ store_parm_decls ()
 
                  pushdecl (parm);
                }
-             if (! processing_template_decl
+             if (! building_stmt_tree ()
                  && (cleanup = maybe_build_cleanup (parm), cleanup))
                {
                  expand_decl (parm);
@@ -13295,21 +13297,20 @@ store_parm_decls ()
 
   /* Initialize the RTL code for the function.  */
   DECL_SAVED_INSNS (fndecl) = 0;
-  if (! processing_template_decl)
+  if (! building_stmt_tree ())
     expand_function_start (fndecl, parms_have_cleanups);
 
   current_function_parms_stored = 1;
 
   /* If this function is `main', emit a call to `__main'
      to run global initializers, etc.  */
-  if (DECL_MAIN_P (fndecl))
+  if (DECL_MAIN_P (fndecl) && !building_stmt_tree ())
     expand_main_function ();
 
   /* Now that we have initialized the parms, we can start their
      cleanups.  We cannot do this before, since expand_decl_cleanup
      should not be called before the parm can be used.  */
-  if (cleanups
-      && ! processing_template_decl)      
+  if (cleanups && !building_stmt_tree ())
     {
       for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
        {
@@ -13325,10 +13326,11 @@ store_parm_decls ()
   if (parms_have_cleanups)
     {
       pushlevel (0);
-      expand_start_bindings (0);
+      if (!building_stmt_tree ())
+       expand_start_bindings (0);
     }
 
-  if (! processing_template_decl && flag_exceptions)
+  if (! building_stmt_tree () && flag_exceptions)
     {
       /* Do the starting of the exception specifications, if we have any.  */
       if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
@@ -13343,55 +13345,15 @@ store_parm_decls ()
    the current function.  */
 
 void
-store_return_init (return_id, init)
-     tree return_id, init;
+store_return_init (decl)
+     tree decl;
 {
-  tree decl = DECL_RESULT (current_function_decl);
-
-  if (pedantic)
-    /* Give this error as many times as there are occurrences,
-       so that users can use Emacs compilation buffers to find
-       and fix all such places.  */
-    pedwarn ("ANSI C++ does not permit named return values");
-
-  if (return_id != NULL_TREE)
-    {
-      if (DECL_NAME (decl) == NULL_TREE)
-       {
-         DECL_NAME (decl) = return_id;
-         DECL_ASSEMBLER_NAME (decl) = return_id;
-       }
-      else
-       cp_error ("return identifier `%D' already in place", decl);
-    }
-
-  /* Can't let this happen for constructors.  */
-  if (DECL_CONSTRUCTOR_P (current_function_decl))
+  /* If this named return value comes in a register, put it in a
+     pseudo-register.  */
+  if (DECL_REGISTER (decl))
     {
-      error ("can't redefine default return value for constructors");
-      return;
-    }
-
-  /* If we have a named return value, put that in our scope as well.  */
-  if (DECL_NAME (decl) != NULL_TREE)
-    {
-      /* If this named return value comes in a register,
-        put it in a pseudo-register.  */
-      if (DECL_REGISTER (decl))
-       {
-         original_result_rtx = DECL_RTL (decl);
-         DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
-       }
-
-      /* Let `cp_finish_decl' know that this initializer is ok.  */
-      DECL_INITIAL (decl) = init;
-      pushdecl (decl);
-
-      if (processing_template_decl && current_function_decl)
-       add_tree (build_min_nt (RETURN_INIT, return_id,
-                               copy_to_permanent (init)));
-      else
-       cp_finish_decl (decl, init, NULL_TREE, 0, 0);
+      original_result_rtx = DECL_RTL (decl);
+      DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
     }
 }
 
@@ -13430,7 +13392,7 @@ finish_function (lineno, flags, nested)
   tree decls = NULL_TREE;
   int call_poplevel = (flags & 1) != 0;
   int inclass_inline = (flags & 2) != 0;
-  int in_template;
+  int expand_p;
 
   /* When we get some parse errors, we can end up without a
      current_function_decl, so cope.  */
@@ -13453,7 +13415,7 @@ finish_function (lineno, flags, nested)
       store_parm_decls ();
     }
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
        {
@@ -13834,19 +13796,15 @@ finish_function (lineno, flags, nested)
       /* Generate rtl for function exit.  */
       expand_function_end (input_filename, lineno, 1);
     }
+
+  /* We have to save this value here in case
+     maybe_end_member_template_processing decides to pop all the
+     template parameters.  */
+  expand_p = !building_stmt_tree ();
   
-  /* If we're processing a template, squirrel away the definition
-     until we do an instantiation.  */
-  if (processing_template_decl)
-    {
-      DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
-      /* We have to save this value here in case
-        maybe_end_member_template_processing decides to pop all the
-        template parameters.  */
-      in_template = 1;
-    }
-  else
-    in_template = 0;
+  /* If we're saving up tree structure, tie off the function now.  */
+  if (!expand_p)
+    finish_stmt_tree (fndecl);
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
@@ -13880,7 +13838,7 @@ finish_function (lineno, flags, nested)
      to the FUNCTION_DECL node itself.  */
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
-  if (!in_template)
+  if (expand_p)
     {
       int saved_flag_keep_inline_functions =
        flag_keep_inline_functions;
@@ -14285,12 +14243,6 @@ void
 cplus_expand_expr_stmt (exp)
      tree exp;
 {
-  if (processing_template_decl)
-    {
-      add_tree (build_min_nt (EXPR_STMT, exp));
-      return;
-    }
-
   /* Arrange for all temps to disappear.  */
   expand_start_target_temps ();
 
@@ -14324,28 +14276,30 @@ cplus_expand_expr_stmt (exp)
   expand_end_target_temps ();
 }
 
-/* When a stmt has been parsed, this function is called.
-
-   Currently, this function only does something within a
-   constructor's scope: if a stmt has just assigned to this,
-   and we are in a derived class, we call `emit_base_init'.  */
+/* When a stmt has been parsed, this function is called.  */
 
 void
 finish_stmt ()
 {
-  if (current_function_assigns_this
-      || ! current_function_just_assigned_this)
-    return;
-  if (DECL_CONSTRUCTOR_P (current_function_decl))
+  if (!current_function_assigns_this
+      && current_function_just_assigned_this)
     {
-      /* Constructors must wait until we are out of control
-        zones before calling base constructors.  */
-      if (in_control_zone_p ())
-       return;
-      expand_expr_stmt (base_init_expr);
-      check_base_init (current_class_type);
+      if (DECL_CONSTRUCTOR_P (current_function_decl))
+       {
+         /* Constructors must wait until we are out of control
+            zones before calling base constructors.  */
+         if (in_control_zone_p ())
+           return;
+         expand_expr_stmt (base_init_expr);
+         check_base_init (current_class_type);
+       }
+      current_function_assigns_this = 1;
     }
-  current_function_assigns_this = 1;
+
+  /* Always assume this statement was not an expression statement.  If
+     it actually was an expression statement, its our callers
+     responsibility to fix this up.  */
+  last_expr_type = NULL_TREE;
 }
 
 /* Change a static member function definition into a FUNCTION_TYPE, instead
@@ -14408,6 +14362,9 @@ struct cp_function
   struct binding_level *binding_level;
   int static_labelno;
   int in_function_try_handler;
+  int expanding_p;
+  tree last_tree;
+  tree last_expr_type;
 };
 
 static struct cp_function *cp_function_chain;
@@ -14451,6 +14408,13 @@ push_cp_function_context (context)
   p->current_class_ref = current_class_ref;
   p->static_labelno = static_labelno;
   p->in_function_try_handler = in_function_try_handler;
+  p->last_tree = last_tree;
+  p->last_expr_type = last_expr_type;
+  p->expanding_p = expanding_p;
+  
+  /* For now, we always assume we're expanding all the way to RTL
+     unless we're explicitly doing otherwise.  */
+  expanding_p = 1;
 }
 
 /* Restore the variables used during compilation of a C++ function.  */
@@ -14494,6 +14458,9 @@ pop_cp_function_context (context)
   current_class_ref = p->current_class_ref;
   static_labelno = p->static_labelno;
   in_function_try_handler = p->in_function_try_handler;
+  last_tree = p->last_tree;
+  last_expr_type = p->last_expr_type;
+  expanding_p = p->expanding_p;
 
   free (p);
 }
index ab82a8ee667ddf578cad771e726585866b6df9c0..e4d2d0e1120f643824d57faf6bba1557d3a71c28 100644 (file)
@@ -2001,27 +2001,6 @@ constructor_name (thing)
   return t;
 }
 \f
-/* Cache the value of this class's main virtual function table pointer
-   in a register variable.  This will save one indirection if a
-   more than one virtual function call is made this function.  */
-
-void
-setup_vtbl_ptr ()
-{
-  extern tree base_init_expr;
-
-  if (base_init_expr == 0
-      && DECL_CONSTRUCTOR_P (current_function_decl))
-    {
-      if (processing_template_decl)
-       add_tree (build_min_nt
-                 (CTOR_INITIALIZER,
-                  current_member_init_list, current_base_init_list));
-      else
-       emit_base_init (current_class_type, 0);
-    }
-}
-
 /* Record the existence of an addressable inline function.  */
 
 void
index 9c911ada7b8218b957b46c8be4017a06bb165a2a..ce0ffbf11b66e1f4eee57ea71d3480277b19f1b9 100644 (file)
@@ -1780,6 +1780,12 @@ dump_expr (t, nop)
       dump_decl (t, 0);
       break;
 
+    case STMT_EXPR:
+      /* We don't yet have a way of dumping statements in a
+        human-readable format.  */
+      OB_PUTS ("{ ... }");
+      break;
+
     case BIND_EXPR:
       OB_PUTS ("{ ");
       dump_expr (TREE_OPERAND (t, 1), nop);
index 0ef6e82795bcccc90a5a5b3c105b85b3343a8fa8..2dbdbd3b91f6df418ad218b61744a13d206fae26 100644 (file)
@@ -558,17 +558,14 @@ expand_start_catch_block (declspecs, declarator)
 {
   tree decl;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (declspecs)
        {
          decl = grokdeclarator (declarator, declspecs, CATCHPARM,
                                 1, NULL_TREE);
          pushdecl (decl);
-         decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
-                              copy_to_permanent (declspecs),
-                              NULL_TREE);
-         add_tree (decl);
+         add_decl_stmt (decl);
        }
       return;
     }
@@ -579,7 +576,6 @@ expand_start_catch_block (declspecs, declarator)
   process_start_catch_block (declspecs, declarator);
 }
 
-
 /* This function performs the expand_start_catch_block functionality for 
    exceptions implemented in the new style. __throw determines whether
    a handler needs to be called or not, so the handler itself has to do
index d5250ae603ff7b12d7864fe88857843fb2a80a99..42fb75798611306c1b0081b067695311bfee5e7f 100644 (file)
@@ -246,6 +246,15 @@ cplus_expand_expr (exp, target, tmode, modifier)
     case NEW_EXPR:
       return expand_expr (build_new_1 (exp), target, tmode, modifier);
 
+    case STMT_EXPR:
+      {
+       tree rtl_expr = begin_stmt_expr ();
+       tree block = expand_stmt (STMT_EXPR_STMT (exp));
+       finish_stmt_expr (rtl_expr, block);
+       return expand_expr (rtl_expr, target, tmode, modifier);
+      }
+      break;
+
     default:
       break;
     }
@@ -388,12 +397,6 @@ do_case (start, end)
   if (end && pedantic)
     pedwarn ("ANSI C++ forbids range expressions in switch statement");
 
-  if (processing_template_decl)
-    {
-      add_tree (build_min_nt (CASE_LABEL, start, end));
-      return;
-    }
-
   if (start)
     value1 = check_cp_case_value (start);
   if (end)
index b2b85c94a62437d00b2700fc147f1ee8f21a9158..c5d435c02930783c36e8268393a2cb3619578138 100644 (file)
@@ -4912,15 +4912,15 @@ case 122:
     break;}
 case 123:
 #line 770 "parse.y"
-{ store_return_init (yyval.ttype, yyvsp[0].ttype); ;
+{ finish_named_return_value (yyval.ttype, yyvsp[0].ttype); ;
     break;}
 case 124:
 #line 772 "parse.y"
-{ store_return_init (yyval.ttype, yyvsp[-1].ttype); ;
+{ finish_named_return_value (yyval.ttype, yyvsp[-1].ttype); ;
     break;}
 case 125:
 #line 774 "parse.y"
-{ store_return_init (yyval.ttype, NULL_TREE); ;
+{ finish_named_return_value (yyval.ttype, NULL_TREE); ;
     break;}
 case 126:
 #line 779 "parse.y"
@@ -7732,7 +7732,7 @@ case 783:
     break;}
 case 784:
 #line 3411 "parse.y"
-{ if (yyvsp[-1].ttype) cplus_expand_expr_stmt (yyvsp[-1].ttype); ;
+{ finish_expr_stmt (yyvsp[-1].ttype); ;
     break;}
 case 786:
 #line 3414 "parse.y"
index 5698789e35b38842736f9fa1c53e5a70cbb9bf26..d735aa785c6a402535e58ee1c4a9e15b4bda159b 100644 (file)
@@ -767,11 +767,11 @@ return_id:
 
 return_init:
          return_id maybe_init
-               { store_return_init ($<ttype>$, $2); }
+               { finish_named_return_value ($<ttype>$, $2); }
        | return_id '(' nonnull_exprlist ')'
-               { store_return_init ($<ttype>$, $3); }
+               { finish_named_return_value ($<ttype>$, $3); }
        | return_id LEFT_RIGHT
-               { store_return_init ($<ttype>$, NULL_TREE); }
+               { finish_named_return_value ($<ttype>$, NULL_TREE); }
        ;
 
 base_init:
@@ -3408,7 +3408,7 @@ label_colon:
 
 for.init.statement:
          xexpr ';'
-               { if ($1) cplus_expand_expr_stmt ($1); }
+                { finish_expr_stmt ($1); }
        | decl
        | '{' compstmtend
                { if (pedantic)
index 4087ef3a29d8446d471344fb9bacd0bcdaa61f53..674834b9ae0be8e107c16f78fd65e793c38c33e2 100644 (file)
@@ -6839,35 +6839,6 @@ tsubst (t, args, complain, in_decl)
     }
 }
 
-void
-do_pushlevel ()
-{
-  emit_line_note (input_filename, lineno);
-  pushlevel (0);
-  clear_last_expr ();
-  push_momentary ();
-  expand_start_bindings (0);
-}  
-
-tree
-do_poplevel ()
-{
-  tree t;
-  int saved_warn_unused = 0;
-
-  if (processing_template_decl)
-    {
-      saved_warn_unused = warn_unused;
-      warn_unused = 0;
-    }
-  expand_end_bindings (getdecls (), kept_level_p (), 0);
-  if (processing_template_decl)
-    warn_unused = saved_warn_unused;
-  t = poplevel (kept_level_p (), 1, 0);
-  pop_momentary ();
-  return t;
-}
-
 /* Like tsubst, but deals with expressions.  This function just replaces
    template parms; to finish processing the resultant expression, use
    tsubst_expr.  */
@@ -7083,7 +7054,21 @@ tsubst_copy (t, args, complain, in_decl)
           NULL_TREE);
       }
 
-    case BIND_EXPR:
+    case STMT_EXPR:
+      /* This processing should really occur in tsubst_expr, However,
+        tsubst_expr does not recurse into expressions, since it
+        assumes that there aren't any statements inside them.
+        Instead, it simply calls build_expr_from_tree.  So, we need
+        to expand the STMT_EXPR here.  */
+      if (!processing_template_decl)
+       {
+         tree rtl_expr = begin_stmt_expr ();
+         tree block = tsubst_expr (STMT_EXPR_STMT (t), args,
+                                   complain, in_decl);
+         r = finish_stmt_expr (rtl_expr, block);
+       }
+      return r;
+
     case COND_EXPR:
     case MODOP_EXPR:
       {
@@ -7091,21 +7076,6 @@ tsubst_copy (t, args, complain, in_decl)
          (code, tsubst_copy (TREE_OPERAND (t, 0), args, complain, in_decl),
           tsubst_copy (TREE_OPERAND (t, 1), args, complain, in_decl),
           tsubst_copy (TREE_OPERAND (t, 2), args, complain, in_decl));
-
-       if (code == BIND_EXPR && !processing_template_decl)
-         {
-           /* This processing should really occur in tsubst_expr,
-              However, tsubst_expr does not recurse into expressions,
-              since it assumes that there aren't any statements
-              inside them.  Instead, it simply calls
-              build_expr_from_tree.  So, we need to expand the
-              BIND_EXPR here.  */ 
-           tree rtl_expr = begin_stmt_expr ();
-           tree block = tsubst_expr (TREE_OPERAND (r, 1), args,
-                                     complain, in_decl);
-           r = finish_stmt_expr (rtl_expr, block);
-         }
-
        return r;
       }
 
@@ -7218,7 +7188,7 @@ tsubst_copy (t, args, complain, in_decl)
     }
 }
 
-/* Like tsubst_copy, but also does semantic processing and RTL expansion.  */
+/* Like tsubst_copy, but also does semantic processing.  */
 
 tree
 tsubst_expr (t, args, complain, in_decl)
@@ -7226,6 +7196,8 @@ tsubst_expr (t, args, complain, in_decl)
      int complain;
      tree in_decl;
 {
+  tree stmt;
+
   if (t == NULL_TREE || t == error_mark_node)
     return t;
 
@@ -7234,6 +7206,22 @@ tsubst_expr (t, args, complain, in_decl)
 
   switch (TREE_CODE (t))
     {
+    case RETURN_INIT:
+      finish_named_return_value
+       (TREE_OPERAND (t, 0),
+        tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, in_decl));
+      tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+      break;
+
+    case CTOR_INITIALIZER:
+      current_member_init_list
+       = tsubst_expr_values (TREE_OPERAND (t, 0), args);
+      current_base_init_list
+       = tsubst_expr_values (TREE_OPERAND (t, 1), args);
+      setup_vtbl_ptr ();
+      tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
+      break;
+
     case RETURN_STMT:
       lineno = STMT_LINENO (t);
       finish_return_stmt (tsubst_expr (RETURN_EXPR (t),
@@ -7253,18 +7241,19 @@ tsubst_expr (t, args, complain, in_decl)
        tree init;
 
        lineno = STMT_LINENO (t);
-       emit_line_note (input_filename, lineno);
        decl = DECL_STMT_DECL (t);
        init = DECL_INITIAL (decl);
        decl = tsubst (decl, args, complain, in_decl);
        init = tsubst_expr (init, args, complain, in_decl);
        DECL_INITIAL (decl) = init;
-       maybe_push_decl (decl);
+       /* 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;
-       start_decl_1 (decl);
-       cp_finish_decl
-         (decl, init, NULL_TREE, 0, /*init ? LOOKUP_ONLYCONVERTING :*/ 0);
+       maybe_push_decl (decl);
+       add_decl_stmt (decl);
        resume_momentary (i);
        return decl;
       }
@@ -7274,41 +7263,41 @@ tsubst_expr (t, args, complain, in_decl)
        tree tmp;
        lineno = STMT_LINENO (t);
 
-       begin_for_stmt ();
+       stmt = begin_for_stmt ();
        for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
          tsubst_expr (tmp, args, complain, in_decl);
-       finish_for_init_stmt (NULL_TREE);
+       finish_for_init_stmt (stmt);
        finish_for_cond (tsubst_expr (FOR_COND (t), args,
                                      complain, in_decl),
-                        NULL_TREE);
+                        stmt);
        tmp = tsubst_expr (FOR_EXPR (t), args, complain, in_decl);
-       finish_for_expr (tmp, NULL_TREE);
+       finish_for_expr (tmp, stmt);
        tsubst_expr (FOR_BODY (t), args, complain, in_decl);
-       finish_for_stmt (tmp, NULL_TREE);
+       finish_for_stmt (tmp, stmt);
       }
       break;
 
     case WHILE_STMT:
       {
        lineno = STMT_LINENO (t);
-       begin_while_stmt ();
+       stmt = begin_while_stmt ();
        finish_while_stmt_cond (tsubst_expr (WHILE_COND (t),
                                             args, complain, in_decl),
-                               NULL_TREE);
+                               stmt);
        tsubst_expr (WHILE_BODY (t), args, complain, in_decl);
-       finish_while_stmt (NULL_TREE);
+       finish_while_stmt (stmt);
       }
       break;
 
     case DO_STMT:
       {
        lineno = STMT_LINENO (t);
-       begin_do_stmt ();
+       stmt = begin_do_stmt ();
        tsubst_expr (DO_BODY (t), args, complain, in_decl);
-       finish_do_body (NULL_TREE);
+       finish_do_body (stmt);
        finish_do_stmt (tsubst_expr (DO_COND (t), args,
                                     complain, in_decl),
-                       NULL_TREE);
+                       stmt);
       }
       break;
 
@@ -7317,22 +7306,22 @@ tsubst_expr (t, args, complain, in_decl)
        tree tmp;
 
        lineno = STMT_LINENO (t);
-       begin_if_stmt ();
+       stmt = begin_if_stmt ();
        finish_if_stmt_cond (tsubst_expr (IF_COND (t),
                                          args, complain, in_decl),
-                            NULL_TREE);
+                            stmt);
 
        if (tmp = THEN_CLAUSE (t), tmp)
          {
            tsubst_expr (tmp, args, complain, in_decl);
-           finish_then_clause (NULL_TREE);
+           finish_then_clause (stmt);
          }
 
        if (tmp = ELSE_CLAUSE (t), tmp)
          {
            begin_else_clause ();
            tsubst_expr (tmp, args, complain, in_decl);
-           finish_else_clause (NULL_TREE);
+           finish_else_clause (stmt);
          }
 
        finish_if_stmt ();
@@ -7344,13 +7333,12 @@ tsubst_expr (t, args, complain, in_decl)
        tree substmt;
 
        lineno = STMT_LINENO (t);
-       begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+       stmt = begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
        for (substmt = COMPOUND_BODY (t); 
             substmt != NULL_TREE;
             substmt = TREE_CHAIN (substmt))
          tsubst_expr (substmt, args, complain, in_decl);
-       return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), 
-                                    NULL_TREE);
+       return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), stmt);
       }
       break;
 
@@ -7366,17 +7354,14 @@ tsubst_expr (t, args, complain, in_decl)
 
     case SWITCH_STMT:
       {
-       tree val, tmp;
+       tree val;
 
        lineno = STMT_LINENO (t);
        begin_switch_stmt ();
        val = tsubst_expr (SWITCH_COND (t), args, complain, in_decl);
-       finish_switch_cond (val);
-       
-       if (tmp = TREE_OPERAND (t, 1), tmp)
-         tsubst_expr (tmp, args, complain, in_decl);
-
-       finish_switch_stmt (val, NULL_TREE);
+       stmt = finish_switch_cond (val);
+       tsubst_expr (SWITCH_BODY (t), args, complain, in_decl);
+       finish_switch_stmt (val, stmt);
       }
       break;
 
@@ -7414,20 +7399,20 @@ tsubst_expr (t, args, complain, in_decl)
 
     case TRY_BLOCK:
       lineno = STMT_LINENO (t);
-      begin_try_block ();
+      stmt = begin_try_block ();
       tsubst_expr (TRY_STMTS (t), args, complain, in_decl);
-      finish_try_block (NULL_TREE);
+      finish_try_block (stmt);
       {
        tree handler = TRY_HANDLERS (t);
        for (; handler; handler = TREE_CHAIN (handler))
          tsubst_expr (handler, args, complain, in_decl);
       }
-      finish_handler_sequence (NULL_TREE);
+      finish_handler_sequence (stmt);
       break;
 
     case HANDLER:
       lineno = STMT_LINENO (t);
-      begin_handler ();
+      stmt = begin_handler ();
       if (HANDLER_PARMS (t))
        {
          tree d = HANDLER_PARMS (t);
@@ -7437,9 +7422,9 @@ tsubst_expr (t, args, complain, in_decl)
        }
       else
        expand_start_catch_block (NULL_TREE, NULL_TREE);
-      finish_handler_parms (NULL_TREE);
+      finish_handler_parms (stmt);
       tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
-      finish_handler (NULL_TREE);
+      finish_handler (stmt);
       break;
 
     case TAG_DEFN:
@@ -9654,57 +9639,39 @@ instantiate_decl (d)
     }
   else if (TREE_CODE (d) == FUNCTION_DECL)
     {
-      tree t = DECL_SAVED_TREE (code_pattern);
-      tree try_block = NULL_TREE;
+      extern struct obstack *saveable_obstack;
+      extern struct obstack *rtl_obstack;
+      int saved_expanding_p = expanding_p;
+
+      /* We're not expanding all the way to RTL here.  */
+      expanding_p = 0;
 
+      /* Set up context.  */
       start_function (NULL_TREE, d, NULL_TREE, 1);
       store_parm_decls ();
 
-      if (t && TREE_CODE (t) == TRY_BLOCK)
-       {
-         try_block = t;
-         begin_function_try_block ();
-         t = TRY_STMTS (try_block);
-       }
-
-      if (t && TREE_CODE (t) == RETURN_INIT)
-       {
-         store_return_init
-           (TREE_OPERAND (t, 0),
-            tsubst_expr (TREE_OPERAND (t, 1), args, /*complain=*/1, tmpl));
-         t = TREE_CHAIN (t);
-       }
-
-      if (t && TREE_CODE (t) == CTOR_INITIALIZER)
-       {
-         current_member_init_list
-           = tsubst_expr_values (TREE_OPERAND (t, 0), args);
-         current_base_init_list
-           = tsubst_expr_values (TREE_OPERAND (t, 1), args);
-         t = TREE_CHAIN (t);
-       }
-
-      setup_vtbl_ptr ();
-      /* Always keep the BLOCK node associated with the outermost
-        pair of curly braces of a function.  These are needed
-        for correct operation of dwarfout.c.  */
-      keep_next_level ();
-
-      my_friendly_assert (TREE_CODE (t) == COMPOUND_STMT, 42);
-      tsubst_expr (t, args, /*complain=*/1, tmpl);
-
-      if (try_block)
-       {
-         finish_function_try_block (NULL_TREE);
-         {
-           tree handler = TRY_HANDLERS (try_block);
-           for (; handler; handler = TREE_CHAIN (handler))
-             tsubst_expr (handler, args, /*complain=*/1, tmpl);
-         }
-         finish_function_handler_sequence (NULL_TREE);
-       }
-
+      /* Anything we might
+        want to save is going to have to be saved forever.  Note that
+        we don't want to save all kinds of temporary clutter that
+        might end up on the temporary obstack so we don't want to
+        call push_permanent_obstack.  */
+      push_obstacks_nochange ();
+      saveable_obstack = &permanent_obstack;
+      /* We only need this because of the cases where we generate
+        RTL_EXPRs.  We should really be generating RTL_EXPRs until
+        final expansion time; when that is fixed, this can go.  */
+      rtl_obstack = &permanent_obstack;
+      /* Substitute into the body of the function.  */
+      tsubst_expr (DECL_SAVED_TREE (code_pattern), args,
+                  /*complain=*/1, tmpl);
+
+      /* Clean up.  */
+      pop_obstacks ();
       finish_function (lineno, 0, nested);
+      expanding_p = saved_expanding_p;
+
+      /* Now, generate RTL for the function.  */
+      expand_body (d);
     }
 
 out:
index 0711da3df608e3b6d6fd32f6f51d9e79e223dabe..dc6b54144b0c255d1139499067db8472631560bf 100644 (file)
    parsing into this file; that will make implementing the new parser
    much easier since it will be able to make use of these routines.  */
 
+static void expand_stmts PROTO((tree));
+
+/* Non-zero if we should generate RTL for functions that we process.
+   When this is zero, we just accumulate tree structure, without
+   interacting with the back end.  */
+int expanding_p = 1;
+
+/* The type of the last expression-statement we have seen.  This is
+   required because the type of a statement-expression is the type of
+   the last expression statement.  */
+tree last_expr_type;
+
 /* When parsing a template, LAST_TREE contains the last statement
    parsed.  These are chained together through the TREE_CHAIN field,
    but often need to be re-organized since the parse is performed
@@ -68,7 +80,9 @@ finish_expr_stmt (expr)
 {
   if (expr != NULL_TREE)
     {
-      if (!processing_template_decl)
+      if (building_stmt_tree ())
+       add_tree (build_min_nt (EXPR_STMT, expr));
+      else
        {
          emit_line_note (input_filename, lineno);
          /* Do default conversion if safe and possibly important,
@@ -77,13 +91,17 @@ finish_expr_stmt (expr)
               && lvalue_p (expr))
              || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
            expr = default_conversion (expr);
+         cplus_expand_expr_stmt (expr);
        }
-      
-      cplus_expand_expr_stmt (expr);
+
       clear_momentary ();
     }
 
   finish_stmt ();
+
+  /* This was an expression-statement, so we save the type of the
+     expression.  */
+  last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
 }
 
 /* Begin an if-statement.  Returns a newly created IF_STMT if
@@ -94,7 +112,7 @@ begin_if_stmt ()
 {
   tree r;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
       add_tree (r);
@@ -115,7 +133,7 @@ finish_if_stmt_cond (cond, if_stmt)
      tree cond;
      tree if_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (last_tree != if_stmt)
        RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
@@ -136,7 +154,7 @@ tree
 finish_then_clause (if_stmt)
      tree if_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       RECHAIN_STMTS_FROM_CHAIN (if_stmt, 
                                THEN_CLAUSE (if_stmt));
@@ -152,7 +170,7 @@ finish_then_clause (if_stmt)
 void 
 begin_else_clause ()
 {
-  if (!processing_template_decl)
+  if (!building_stmt_tree ())
     expand_start_else ();
 }
 
@@ -163,7 +181,7 @@ void
 finish_else_clause (if_stmt)
      tree if_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
 }
 
@@ -172,7 +190,7 @@ finish_else_clause (if_stmt)
 void 
 finish_if_stmt ()
 {
-  if (!processing_template_decl)
+  if (!building_stmt_tree ())
     expand_end_cond ();
 
   do_poplevel ();
@@ -187,7 +205,7 @@ begin_while_stmt ()
 {
   tree r;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
       add_tree (r);
@@ -213,11 +231,10 @@ finish_while_stmt_cond (cond, while_stmt)
      tree cond;
      tree while_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (last_tree != while_stmt)
-       RECHAIN_STMTS_FROM_LAST (while_stmt, 
-                                     WHILE_COND (while_stmt)); 
+       RECHAIN_STMTS_FROM_LAST (while_stmt, WHILE_COND (while_stmt)); 
       else
        TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
     }
@@ -245,7 +262,7 @@ finish_while_stmt (while_stmt)
 {
   do_poplevel ();
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
   else
     expand_end_loop ();
@@ -258,7 +275,7 @@ finish_while_stmt (while_stmt)
 tree
 begin_do_stmt ()
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
       add_tree (r);
@@ -279,7 +296,7 @@ void
 finish_do_body (do_stmt)
      tree do_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
   else
     expand_loop_continue_here ();
@@ -293,7 +310,7 @@ finish_do_stmt (cond, do_stmt)
      tree cond;
      tree do_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     DO_COND (do_stmt) = copy_to_permanent (cond);
   else
     {
@@ -313,8 +330,14 @@ void
 finish_return_stmt (expr)
      tree expr;
 {
-  emit_line_note (input_filename, lineno);
-  c_expand_return (expr);
+  if (building_stmt_tree ())
+    add_tree (build_min_nt (RETURN_STMT, expr));
+  else
+    {
+      emit_line_note (input_filename, lineno);
+      c_expand_return (expr);
+    }
+
   finish_stmt ();
 }
 
@@ -325,7 +348,7 @@ begin_for_stmt ()
 {
   tree r;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, 
                        NULL_TREE, NULL_TREE);
@@ -350,7 +373,7 @@ void
 finish_for_init_stmt (for_stmt)
      tree for_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (last_tree != for_stmt)
        RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
@@ -373,7 +396,7 @@ finish_for_cond (cond, for_stmt)
      tree cond;
      tree for_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       if (last_tree != for_stmt)
        RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
@@ -405,8 +428,8 @@ finish_for_expr (expr, for_stmt)
      tree expr;
      tree for_stmt;
 {
-  if (processing_template_decl)
-    FOR_EXPR (for_stmt) = expr;
+  if (building_stmt_tree ())
+    FOR_EXPR (for_stmt) = copy_to_permanent (expr);
 
   /* Don't let the tree nodes for EXPR be discarded
      by clear_momentary during the parsing of the next stmt.  */
@@ -425,7 +448,7 @@ finish_for_stmt (expr, for_stmt)
   /* Pop the scope for the body of the loop.  */
   do_poplevel ();
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
   else
     {
@@ -450,7 +473,7 @@ void
 finish_break_stmt ()
 {
   emit_line_note (input_filename, lineno);
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     add_tree (build_min_nt (BREAK_STMT));
   else if ( ! expand_exit_something ())
     cp_error ("break statement not within loop or switch");
@@ -462,7 +485,7 @@ void
 finish_continue_stmt ()
 {
   emit_line_note (input_filename, lineno);
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     add_tree (build_min_nt (CONTINUE_STMT));
   else if (! expand_continue_loop (0))
     cp_error ("continue statement not within a loop");   
@@ -485,7 +508,7 @@ finish_switch_cond (cond)
 {
   tree r;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
       add_tree (r);
@@ -521,7 +544,7 @@ finish_switch_stmt (cond, switch_stmt)
      tree cond;
      tree switch_stmt;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
   else
     expand_end_case (cond);
@@ -538,17 +561,22 @@ finish_case_label (low_value, high_value)
      tree low_value;
      tree high_value;
 {
+  if (building_stmt_tree ())
+    {
+      add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
+      return;
+    }
+
   do_case (low_value, high_value);
 }
 
-
 /* Finish a goto-statement.  */
 
 void
 finish_goto_stmt (destination)
      tree destination;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     add_tree (build_min_nt (GOTO_STMT, destination));
   else
     {
@@ -571,7 +599,7 @@ finish_goto_stmt (destination)
 tree
 begin_try_block ()
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
                             NULL_TREE);
@@ -591,7 +619,7 @@ begin_try_block ()
 tree
 begin_function_try_block ()
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
                             NULL_TREE);
@@ -613,12 +641,10 @@ void
 finish_try_block (try_block)
      tree try_block;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
   else
-    {
-      expand_start_all_catch ();  
-    }
+    expand_start_all_catch ();  
 }
 
 /* Likewise, for a function-try-block.  */
@@ -627,7 +653,7 @@ void
 finish_function_try_block (try_block)
      tree try_block;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
   else
     {
@@ -644,7 +670,7 @@ void
 finish_handler_sequence (try_block)
      tree try_block;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
   else
     {
@@ -658,7 +684,7 @@ void
 finish_function_handler_sequence (try_block)
      tree try_block;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
   else
     {
@@ -674,7 +700,7 @@ begin_handler ()
 {
   tree r;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
       add_tree (r);
@@ -694,7 +720,7 @@ void
 finish_handler_parms (handler)
      tree handler;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
 }
 
@@ -704,7 +730,7 @@ void
 finish_handler (handler)
      tree handler;
 {
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
   else
     expand_end_catch_block ();
@@ -722,7 +748,7 @@ begin_compound_stmt (has_no_scope)
 {
   tree r; 
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       r = build_min_nt (COMPOUND_STMT, NULL_TREE);
       add_tree (r);
@@ -732,6 +758,8 @@ begin_compound_stmt (has_no_scope)
   else
     r = NULL_TREE;
 
+  last_expr_type = NULL_TREE;
+
   if (!has_no_scope)
     do_pushlevel ();
 
@@ -749,17 +777,24 @@ finish_compound_stmt (has_no_scope, compound_stmt)
      tree compound_stmt;
 {
   tree r;
+  tree t;
 
   if (!has_no_scope)
     r = do_poplevel ();
   else
     r = NULL_TREE;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     RECHAIN_STMTS_FROM_CHAIN (compound_stmt, 
                              COMPOUND_BODY (compound_stmt));
 
+  /* When we call finish_stmt we will lost LAST_EXPR_TYPE.  But, since
+     the precise purpose of that variable is store the type of the
+     last expression statement within the last compound statement, we
+     preserve the value.  */
+  t = last_expr_type;
   finish_stmt ();
+  last_expr_type = t;
 
   return r;
 }
@@ -779,14 +814,14 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
 {
   if (TREE_CHAIN (string))
     {
-      if (processing_template_decl)
+      if (building_stmt_tree ())
        /* We need to build the combined string on the permanent
           obstack so that we can use it during instantiations.  */
        push_permanent_obstack ();
 
       string = combine_strings (string);
 
-      if (processing_template_decl)
+      if (building_stmt_tree ())
        pop_obstacks ();
     }
 
@@ -798,7 +833,7 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
       cv_qualifier = NULL_TREE;
     }
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
                             output_operands, input_operands,
@@ -837,7 +872,7 @@ finish_label_stmt (name)
 {
   tree decl;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       push_permanent_obstack ();
       decl = build_decl (LABEL_DECL, name, void_type_node);
@@ -869,6 +904,111 @@ add_decl_stmt (decl)
   add_tree (decl_stmt);
 }
 
+/* Bind a name and initialization to the return value of
+   the current function.  */
+
+void
+finish_named_return_value (return_id, init)
+     tree return_id, init;
+{
+  tree decl = DECL_RESULT (current_function_decl);
+
+  if (pedantic)
+    /* Give this error as many times as there are occurrences,
+       so that users can use Emacs compilation buffers to find
+       and fix all such places.  */
+    pedwarn ("ANSI C++ does not permit named return values");
+
+  if (return_id != NULL_TREE)
+    {
+      if (DECL_NAME (decl) == NULL_TREE)
+       {
+         DECL_NAME (decl) = return_id;
+         DECL_ASSEMBLER_NAME (decl) = return_id;
+       }
+      else
+       {
+         cp_error ("return identifier `%D' already in place", return_id);
+         return;
+       }
+    }
+
+  /* Can't let this happen for constructors.  */
+  if (DECL_CONSTRUCTOR_P (current_function_decl))
+    {
+      error ("can't redefine default return value for constructors");
+      return;
+    }
+
+  /* If we have a named return value, put that in our scope as well.  */
+  if (DECL_NAME (decl) != NULL_TREE)
+    {
+      /* Let `cp_finish_decl' know that this initializer is ok.  */
+      DECL_INITIAL (decl) = init;
+      pushdecl (decl);
+
+      if (building_stmt_tree ())
+       add_tree (build_min_nt (RETURN_INIT, return_id,
+                               copy_to_permanent (init)));
+      else
+       {
+         cp_finish_decl (decl, init, NULL_TREE, 0, 0);
+         store_return_init (decl);
+       }
+    }
+}
+
+/* Cache the value of this class's main virtual function table pointer
+   in a register variable.  This will save one indirection if a
+   more than one virtual function call is made this function.  */
+
+void
+setup_vtbl_ptr ()
+{
+  extern tree base_init_expr;
+
+  if (base_init_expr == 0
+      && DECL_CONSTRUCTOR_P (current_function_decl))
+    {
+      if (building_stmt_tree ())
+       add_tree (build_min_nt
+                 (CTOR_INITIALIZER,
+                  current_member_init_list, current_base_init_list));
+      else
+       emit_base_init (current_class_type, 0);
+    }
+}
+
+/* Begin a new scope.  */
+
+void
+do_pushlevel ()
+{
+  if (!building_stmt_tree ())
+    {
+      emit_line_note (input_filename, lineno);
+      clear_last_expr ();
+    }
+  pushlevel (0);
+  push_momentary ();
+  if (!building_stmt_tree ())
+    expand_start_bindings (0);
+}  
+
+/* Finish a scope.  */
+
+tree
+do_poplevel ()
+{
+  tree t;
+
+  if (!building_stmt_tree ())
+    expand_end_bindings (getdecls (), kept_level_p (), 0);
+  t = poplevel (kept_level_p (), 1, 0);
+  pop_momentary ();
+  return t;
+}
+
 /* Finish a parenthesized expression EXPR.  */
 
 tree
@@ -889,11 +1029,11 @@ tree
 begin_stmt_expr ()
 {
   keep_next_level ();
-  /* If we're processing_template_decl, then the upcoming compound
+  /* If we're building a statement tree, then the upcoming compound
      statement will be chained onto the tree structure, starting at
      last_tree.  We return last_tree so that we can later unhook the
      compound statement.  */
-  return processing_template_decl ? last_tree : expand_start_stmt_expr(); 
+  return building_stmt_tree () ? last_tree : expand_start_stmt_expr(); 
 }
 
 /* Finish a statement-expression.  RTL_EXPR should be the value
@@ -908,7 +1048,7 @@ finish_stmt_expr (rtl_expr, expr)
 {
   tree result;
 
-  if (!processing_template_decl)
+  if (!building_stmt_tree ())
     {
       rtl_expr = expand_end_stmt_expr (rtl_expr);
       /* The statements have side effects, so the group does.  */
@@ -917,26 +1057,29 @@ finish_stmt_expr (rtl_expr, expr)
 
   if (TREE_CODE (expr) == BLOCK)
     {
-      /* Make a BIND_EXPR for the BLOCK already made.  */
-      if (processing_template_decl)
-       result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
-                              NULL_TREE);
+      /* Make a CP_BIND_EXPR for the BLOCK already made.  */
+      if (building_stmt_tree ())
+       {
+         result = build_min (STMT_EXPR, last_expr_type, last_tree);
+         /* FIXME: Do we need this?  */
+         TREE_SIDE_EFFECTS (result) = 1;
+       }
       else
        result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
                        NULL_TREE, rtl_expr, expr);
       
-      /* Remove the block from the tree at this point.
-        It gets put back at the proper place
-        when the BIND_EXPR is expanded.  */
+      /* Remove the block from the tree at this point.  It gets put
+        back at the proper place when the STMT_EXPR or BIND_EXPR is
+        expanded.  */
       delete_block (expr);
     }
   else
     result = expr;
 
-  if (processing_template_decl)
+  if (building_stmt_tree ())
     {
       /* Remove the compound statement from the tree structure; it is
-        now saved in the BIND_EXPR.  */
+        now saved in the STMT_EXPR.  */
       last_tree = rtl_expr;
       TREE_CHAIN (last_tree) = NULL_TREE;
     }
@@ -1746,3 +1889,300 @@ finish_typeof (expr)
 
   return TREE_TYPE (expr);
 }
+
+/* Create an empty statement tree for FN.  */
+
+void
+begin_stmt_tree (fn)
+     tree fn;
+{
+  /* We create a trivial EXPR_STMT so that last_tree is never NULL in
+     what follows.  We remove the extraneous statement in
+     finish_stmt_tree.  */
+  DECL_SAVED_TREE (fn) = build_nt (EXPR_STMT, void_zero_node);
+  last_tree = DECL_SAVED_TREE (fn);
+  last_expr_type = NULL_TREE;
+}
+
+/* Finish the statement tree for FN.  */
+
+void
+finish_stmt_tree (fn)
+     tree fn;
+{
+  DECL_SAVED_TREE (fn) = TREE_CHAIN (DECL_SAVED_TREE (fn));
+}
+
+/* Generate RTL for the chain of statements T.  */
+
+static void 
+expand_stmts (t)
+     tree t;
+{
+  while (t)
+    {
+      expand_stmt (t);
+      t = TREE_CHAIN (t);
+    }
+}
+
+/* Generate RTL for the statement T, and its substatements.  */
+
+tree
+expand_stmt (t)
+     tree t;
+{
+  if (t == NULL_TREE || t == error_mark_node)
+    return NULL_TREE;
+
+  switch (TREE_CODE (t))
+    {
+    case RETURN_STMT:
+      lineno = STMT_LINENO (t);
+      finish_return_stmt (RETURN_EXPR (t));
+      break;
+
+    case EXPR_STMT:
+      lineno = STMT_LINENO (t);
+      finish_expr_stmt (EXPR_STMT_EXPR (t));
+      break;
+
+    case DECL_STMT:
+      {
+       tree decl;
+       int i = suspend_momentary ();
+
+       lineno = STMT_LINENO (t);
+       emit_line_note (input_filename, lineno);
+       decl = DECL_STMT_DECL (t);
+       /* We need to clear DECL_CONTEXT so that maybe_push_decl
+          will push it into the current scope.  */
+       if (DECL_CONTEXT (decl) == current_function_decl)
+         DECL_CONTEXT (decl) = NULL_TREE;
+       /* If we marked this variable as dead when we processed it
+          before, we must undo that now.  The variable has been
+          resuscitated.  */
+       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);
+       resume_momentary (i);
+      }
+      break;
+
+    case FOR_STMT:
+      {
+       tree tmp;
+
+       lineno = STMT_LINENO (t);
+       begin_for_stmt ();
+       for (tmp = FOR_INIT_STMT (t); tmp; tmp = TREE_CHAIN (tmp))
+         expand_stmt (tmp);
+       finish_for_init_stmt (NULL_TREE);
+       finish_for_cond (FOR_COND (t), NULL_TREE);
+       tmp = FOR_EXPR (t);
+       finish_for_expr (tmp, NULL_TREE);
+       expand_stmt (FOR_BODY (t));
+       finish_for_stmt (tmp, NULL_TREE);
+      }
+      break;
+
+    case WHILE_STMT:
+      {
+       lineno = STMT_LINENO (t);
+       begin_while_stmt ();
+       finish_while_stmt_cond (WHILE_COND (t), NULL_TREE);
+       expand_stmt (WHILE_BODY (t));
+       finish_while_stmt (NULL_TREE);
+      }
+      break;
+
+    case DO_STMT:
+      {
+       lineno = STMT_LINENO (t);
+       begin_do_stmt ();
+       expand_stmt (DO_BODY (t));
+       finish_do_body (NULL_TREE);
+       finish_do_stmt (DO_COND (t), NULL_TREE);
+      }
+      break;
+
+    case IF_STMT:
+      lineno = STMT_LINENO (t);
+      begin_if_stmt ();
+      finish_if_stmt_cond (IF_COND (t), NULL_TREE);
+      if (THEN_CLAUSE (t))
+       {
+         expand_stmt (THEN_CLAUSE (t));
+         finish_then_clause (NULL_TREE);
+       }
+      if (ELSE_CLAUSE (t))
+       {
+         begin_else_clause ();
+         expand_stmt (ELSE_CLAUSE (t));
+         finish_else_clause (NULL_TREE);
+       }
+      finish_if_stmt ();
+      break;
+
+    case COMPOUND_STMT:
+      lineno = STMT_LINENO (t);
+      begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
+      expand_stmts (COMPOUND_BODY (t));
+      return finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t), 
+                                  NULL_TREE);
+
+    case BREAK_STMT:
+      lineno = STMT_LINENO (t);
+      finish_break_stmt ();
+      break;
+
+    case CONTINUE_STMT:
+      lineno = STMT_LINENO (t);
+      finish_continue_stmt ();
+      break;
+
+    case SWITCH_STMT:
+      lineno = STMT_LINENO (t);
+      begin_switch_stmt ();
+      finish_switch_cond (SWITCH_COND (t));
+      if (TREE_OPERAND (t, 1))
+       expand_stmt (SWITCH_BODY (t));
+      finish_switch_stmt (SWITCH_COND (t), NULL_TREE);
+      break;
+
+    case CASE_LABEL:
+      finish_case_label (CASE_LOW (t), CASE_HIGH (t));
+      break;
+
+    case LABEL_DECL:
+      t = define_label (DECL_SOURCE_FILE (t), DECL_SOURCE_LINE (t),
+                       DECL_NAME (t));
+      if (t)
+       expand_label (t);
+      break;
+
+    case GOTO_STMT:
+      lineno = STMT_LINENO (t);
+      finish_goto_stmt (GOTO_DESTINATION (t));
+      break;
+
+    case ASM_STMT:
+      lineno = STMT_LINENO (t);
+      finish_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t), ASM_OUTPUTS
+                      (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
+      break;
+
+    case TRY_BLOCK:
+      lineno = STMT_LINENO (t);
+      begin_try_block ();
+      expand_stmt (TRY_STMTS (t));
+      finish_try_block (NULL_TREE);
+      expand_stmts (TRY_HANDLERS (t));
+      finish_handler_sequence (NULL_TREE);
+      break;
+
+    case HANDLER:
+      lineno = STMT_LINENO (t);
+      begin_handler ();
+      if (HANDLER_PARMS (t))
+       {
+         tree d = HANDLER_PARMS (t);
+         expand_start_catch_block (TREE_OPERAND (d, 1),
+                                   TREE_OPERAND (d, 0));
+       }
+      else
+       expand_start_catch_block (NULL_TREE, NULL_TREE);
+      finish_handler_parms (NULL_TREE);
+      expand_stmt (HANDLER_BODY (t));
+      finish_handler (NULL_TREE);
+      break;
+
+    default:
+      my_friendly_abort (19990810);
+      break;
+    }
+
+  return NULL_TREE;
+}
+
+/* Generate RTL for FN.  */
+
+void
+expand_body (fn)
+     tree fn;
+{
+  int saved_expanding_p;
+  int nested; 
+  tree t;
+  tree try_block;
+
+  /* Remember whether we're already processing a function definition
+     so that we can tell finish_function.  */
+  nested = in_function_p ();
+
+  /* Let the compiler know that now is the time to really generate
+     actualy RTL.  */
+  saved_expanding_p = expanding_p;
+  expanding_p = 1;
+
+  start_function (NULL_TREE, fn, NULL_TREE, 1);
+  store_parm_decls ();
+
+  /* There are a few things that we do not handle recursively.  For
+     example, a function try-block is handled differently from an
+     ordinary try-block, so we must handle it here.  */
+  t = DECL_SAVED_TREE (fn);
+  try_block = NULL_TREE;
+  if (t && TREE_CODE (t) == TRY_BLOCK)
+    {
+      try_block = t;
+      begin_function_try_block ();
+      t = TRY_STMTS (try_block);
+    }
+
+  if (t && TREE_CODE (t) == RETURN_INIT)
+    {
+      /* Clear this out so that finish_named_return_value can set it
+        again.  */
+      DECL_NAME (DECL_RESULT (fn)) = NULL_TREE;
+      finish_named_return_value (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
+      t = TREE_CHAIN (t);
+    }
+
+  if (t && TREE_CODE (t) == CTOR_INITIALIZER)
+    {
+      current_member_init_list = TREE_OPERAND (t, 0);
+      current_base_init_list = TREE_OPERAND (t, 1);
+      t = TREE_CHAIN (t);
+    }
+
+  /* If this is a constructor, we need to initialize our members and
+     base-classes.  */
+  setup_vtbl_ptr ();
+
+  /* Always keep the BLOCK node associated with the outermost pair of
+     curly braces of a function.  These are needed for correct
+     operation of dwarfout.c.  */
+  keep_next_level ();
+
+  /* Expand the body.  */
+  expand_stmt (t);
+
+  /* If there was a function try-block, expand the handlers.  */
+  if (try_block)
+    {
+      finish_function_try_block (NULL_TREE);
+      {
+       tree handler = TRY_HANDLERS (try_block);
+       for (; handler; handler = TREE_CHAIN (handler))
+         expand_stmt (handler);
+      }
+      finish_function_handler_sequence (NULL_TREE);
+    }
+
+  finish_function (lineno, 0, nested);
+
+  /* Restore EXPANDING_P.  */
+  expanding_p = saved_expanding_p;
+}
index f2e8257b30b622be224fb32455c2ea03452d17e4..b9732b3a738a2dc58a260aad8a0efe6459fde0af 100644 (file)
@@ -412,15 +412,20 @@ build_cplus_method_type (basetype, rettype, argtypes)
   ptype = build_pointer_type (basetype);
 
   /* The actual arglist for this function includes a "hidden" argument
-     which is "this".  Put it into the list of argument types.  */
-
+     which is "this".  Put it into the list of argument types.  Make
+     sure that the new argument list is allocated on the same obstack
+     as the type.  */
+  push_obstacks (TYPE_OBSTACK (t), TYPE_OBSTACK (t));
   argtypes = tree_cons (NULL_TREE, ptype, argtypes);
   TYPE_ARG_TYPES (t) = argtypes;
   TREE_SIDE_EFFECTS (argtypes) = 1;  /* Mark first argtype as "artificial".  */
+  pop_obstacks ();
 
   /* If we already have such a type, use the old one and free this one.
      Note that it also frees up the above cons cell if found.  */
-  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) + type_hash_list (argtypes);
+  hashcode = TYPE_HASH (basetype) + TYPE_HASH (rettype) +
+    type_hash_list (argtypes);
+
   t = type_hash_canon (hashcode, t);
 
   if (TYPE_SIZE (t) == 0)
@@ -1646,6 +1651,8 @@ search_tree (t, func)
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
     case CALL_EXPR:
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
       TRY (TREE_OPERAND (t, 0));
       TRY (TREE_OPERAND (t, 1));
       break;
@@ -1657,6 +1664,7 @@ search_tree (t, func)
     case COMPONENT_REF:
     case CLEANUP_POINT_EXPR:
     case LOOKUP_EXPR:
+    case THROW_EXPR:
       TRY (TREE_OPERAND (t, 0));
       break;
 
@@ -1681,6 +1689,7 @@ search_tree (t, func)
       break;
 
     case BIND_EXPR:
+    case STMT_EXPR:
       break;
 
     case REAL_TYPE:
@@ -1774,6 +1783,7 @@ mapcar (t, func)
      tree (*func) PROTO((tree));
 {
   tree tmp;
+  enum tree_code code; 
 
   if (t == NULL_TREE)
     return t;
@@ -1785,6 +1795,24 @@ mapcar (t, func)
        return tmp;
     }
 
+  /* Handle some common cases up front.  */
+  code = TREE_CODE (t);
+  if (TREE_CODE_CLASS (code) == '1')
+    {
+      t = copy_node (t);
+      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+      return t;
+    }
+  else if (TREE_CODE_CLASS (code) == '2' || TREE_CODE_CLASS (code) == '<')
+    {
+      t = copy_node (t);
+      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+      TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+      return t;
+    }
+
   switch (TREE_CODE (t))
     {
     case ERROR_MARK:
@@ -1871,40 +1899,8 @@ mapcar (t, func)
       TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
       return t;
 
-    case SAVE_EXPR:
-      t = copy_node (t);
-      TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
-      return t;
-
-    case MODIFY_EXPR:
-    case PLUS_EXPR:
-    case MINUS_EXPR:
-    case MULT_EXPR:
-    case TRUNC_DIV_EXPR:
-    case TRUNC_MOD_EXPR:
-    case MIN_EXPR:
-    case MAX_EXPR:
-    case LSHIFT_EXPR:
-    case RSHIFT_EXPR:
-    case BIT_IOR_EXPR:
-    case BIT_XOR_EXPR:
-    case BIT_AND_EXPR:
-    case BIT_ANDTC_EXPR:
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
-    case LT_EXPR:
-    case LE_EXPR:
-    case GT_EXPR:
-    case GE_EXPR:
-    case EQ_EXPR:
-    case NE_EXPR:
-    case CEIL_DIV_EXPR:
-    case FLOOR_DIV_EXPR:
-    case ROUND_DIV_EXPR:
-    case CEIL_MOD_EXPR:
-    case FLOOR_MOD_EXPR:
-    case ROUND_MOD_EXPR:
-    case COMPOUND_EXPR:
     case PREDECREMENT_EXPR:
     case PREINCREMENT_EXPR:
     case POSTDECREMENT_EXPR:
@@ -1913,6 +1909,8 @@ mapcar (t, func)
     case SCOPE_REF:
     case TRY_CATCH_EXPR:
     case WITH_CLEANUP_EXPR:
+    case COMPOUND_EXPR:
+    case MODIFY_EXPR:
       t = copy_node (t);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
@@ -1933,16 +1931,14 @@ mapcar (t, func)
        TREE_OPERAND (t, 2) = NULL_TREE;
       return t;
 
-    case CONVERT_EXPR:
+    case SAVE_EXPR:
     case ADDR_EXPR:
     case INDIRECT_REF:
-    case NEGATE_EXPR:
-    case BIT_NOT_EXPR:
     case TRUTH_NOT_EXPR:
-    case NOP_EXPR:
     case COMPONENT_REF:
     case CLEANUP_POINT_EXPR:
-    case NON_LVALUE_EXPR:
+    case THROW_EXPR:
+    case STMT_EXPR:
       t = copy_node (t);
       TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
@@ -2009,19 +2005,19 @@ mapcar (t, func)
       TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
       return t;
 
+    case RTL_EXPR:
+      t = copy_node (t);
+      TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+      return t;
+
     case RECORD_TYPE:
       if (TYPE_PTRMEMFUNC_P (t))
        return build_ptrmemfunc_type
          (mapcar (TYPE_PTRMEMFUNC_FN_TYPE (t), func));
       /* else fall through */
-      
-      /*  This list is incomplete, but should suffice for now.
-         It is very important that `sorry' not call
-         `report_error_function'.  That could cause an infinite loop.  */
-    default:
-      sorry ("initializer contains unrecognized tree code");
-      return error_mark_node;
 
+    default:
+      my_friendly_abort (19990815);
     }
   my_friendly_abort (107);
   /* NOTREACHED */
index 044f48fdaa83665d69d127bdcef4655e660d6126..5d12bee3ada6601a7ae5fc1ad245489f57cc2162 100644 (file)
@@ -197,6 +197,7 @@ require_complete_type_in_void (expr)
     case EXIT_EXPR:   /* have no return */
     case LOOP_EXPR:   /* have no return */
     case BIND_EXPR:   /* have no return */
+    case STMT_EXPR: /* have no return */
     case THROW_EXPR:  /* have no return */
     case MODIFY_EXPR: /* sometimes this has a void type, but that's ok */
     case CONVERT_EXPR:  /* sometimes has a void type */
@@ -6801,12 +6802,6 @@ c_expand_return (retval)
       return;
     }
 
-  if (processing_template_decl)
-    {
-      add_tree (build_min_nt (RETURN_STMT, retval));
-      return;
-    }
-
   if (dtor_label)
     {
       if (retval)