OSDN Git Service

* cp/cp-tree.h (struct cp_language_function): Remove x_result_rtx.
[pf3gnuchains/gcc-fork.git] / gcc / cp / semantics.c
index d93ddd8..28c0f35 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 tree expand_cond PARAMS ((tree));
 static tree maybe_convert_cond PARAMS ((tree));
 static tree simplify_aggr_init_exprs_r PARAMS ((tree *, int *, void *));
 static void deferred_type_access_control PARAMS ((void));
 static void emit_associated_thunks PARAMS ((tree));
-
-/* Record the fact that STMT was the last statement added to the
-   statement tree.  */
-
-#define SET_LAST_STMT(stmt) \
-  (current_stmt_tree->x_last_stmt = (stmt))
-
-/* 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
-   bottom-up.  This macro makes LAST_TREE the indicated SUBSTMT of
-   STMT.  */
-
-#define RECHAIN_STMTS(stmt, substmt)   \
-  do {                                 \
-    substmt = TREE_CHAIN (stmt);       \
-    TREE_CHAIN (stmt) = NULL_TREE;     \
-    SET_LAST_STMT (stmt);              \
-  } while (0)
+static void genrtl_try_block PARAMS ((tree));
+static void genrtl_handler PARAMS ((tree));
+static void genrtl_catch_block PARAMS ((tree));
+static void genrtl_ctor_stmt PARAMS ((tree));
+static void genrtl_subobject PARAMS ((tree));
+static void genrtl_named_return_value PARAMS ((void));
+static void cp_expand_stmt PARAMS ((tree));
+static void genrtl_start_function PARAMS ((tree));
+static void genrtl_finish_function PARAMS ((tree));
 
 /* Finish processing the COND, the SUBSTMT condition for STMT.  */
 
@@ -88,55 +77,52 @@ static void emit_associated_thunks PARAMS ((tree));
       substmt = cond;                                  \
   } while (0)
 
-/* Finish a scope.  */
+/* Returns non-zero if the current statement is a full expression,
+   i.e. temporaries created during that statement should be destroyed
+   at the end of the statement.  */
 
-tree
-do_poplevel ()
+int
+stmts_are_full_exprs_p ()
 {
-  tree block = NULL_TREE;
-
-  if (stmts_are_full_exprs_p)
-    {
-      tree scope_stmts;
-
-      if (!processing_template_decl)
-       scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
+  return current_stmt_tree ()->stmts_are_full_exprs_p;
+}
 
-      block = poplevel (kept_level_p (), 1, 0);
-      if (block && !processing_template_decl)
-       {
-         SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
-         SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
-       }
-    }
+/* Returns the stmt_tree (if any) to which statements are currently
+   being added.  If there is no active statement-tree, NULL is
+   returned.  */
 
-  return block;
+stmt_tree
+current_stmt_tree ()
+{
+  return (cfun 
+         ? &cfun->language->x_stmt_tree 
+         : &scope_chain->x_stmt_tree);
 }
 
-/* Begin a new scope.  */ 
+/* Nonzero if TYPE is an anonymous union or struct type.  We have to use a
+   flag for this because "A union for which objects or pointers are
+   declared is not an anonymous union" [class.union].  */
 
-void
-do_pushlevel ()
+int
+anon_aggr_type_p (node)
+     tree node;
 {
-  if (stmts_are_full_exprs_p)
-    {
-      pushlevel (0);
-      if (!processing_template_decl)
-       add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
-    }
+  return (CLASS_TYPE_P (node) && TYPE_LANG_SPECIFIC(node)->anon_aggr);
 }
 
-/* Helper for generating the RTL at the end of a scope. */
+/* Finish a scope.  */
 
 tree
-genrtl_do_poplevel ()
+do_poplevel ()
 {
   tree block = NULL_TREE;
 
-  if (stmts_are_full_exprs_p)
+  if (stmts_are_full_exprs_p ())
     {
-      tree scope_stmts;
-      scope_stmts = NULL_TREE;
+      tree scope_stmts = NULL_TREE;
+
+      if (!processing_template_decl)
+       scope_stmts = add_scope_stmt (/*begin_p=*/0, /*partial_p=*/0);
 
       block = poplevel (kept_level_p (), 1, 0);
       if (block && !processing_template_decl)
@@ -149,51 +135,19 @@ genrtl_do_poplevel ()
   return block;
 }
 
-/* Helper for generating the RTL at the beginning of a scope. */
-
-void
-genrtl_do_pushlevel ()
-{
-  emit_line_note (input_filename, lineno);
-  clear_last_expr ();
-
-  if (stmts_are_full_exprs_p)
-    {
-      pushlevel (0); // Try to get rid of me.
-      if (!cfun->x_whole_function_mode_p)
-       my_friendly_abort (19991129);
-    }
-}
-
-/* Helper for generating the RTL. */
+/* Begin a new scope.  */ 
 
 void
-genrtl_clear_out_block ()
+do_pushlevel ()
 {
-  /* If COND wasn't a declaration, clear out the
-     block we made for it and start a new one here so the
-     optimization in expand_end_loop will work.  */
-  if (getdecls () == NULL_TREE)
+  if (stmts_are_full_exprs_p ())
     {
-      genrtl_do_poplevel ();
-      genrtl_do_pushlevel ();
+      pushlevel (0);
+      if (!processing_template_decl)
+       add_scope_stmt (/*begin_p=*/1, /*partial_p=*/0);
     }
 }
 
-/* T is a statement.  Add it to the statement-tree.  */
-
-void
-add_tree (t)
-     tree t;
-{
-  /* Add T to the statement-tree.  */
-  TREE_CHAIN (last_tree) = t;
-  SET_LAST_STMT (t);
-  /* When we expand a statement-tree, we must know whether or not the
-     statements are full-expresions.  We record that fact here.  */
-  STMT_IS_FULL_EXPR_P (last_tree) = stmts_are_full_exprs_p;
-}
-
 /* Finish a goto-statement.  */
 
 void
@@ -217,38 +171,13 @@ finish_goto_stmt (destination)
   
   check_goto (destination);
 
-  add_tree (build_min_nt (GOTO_STMT, destination));
-}
-
-/* Generate the RTL for DESTINATION, which is a GOTO_STMT. */
-
-void
-genrtl_goto_stmt (destination)
-     tree destination;
-{
-  if (TREE_CODE (destination) == IDENTIFIER_NODE)
-    destination = lookup_label (destination);
-
-  /* We warn about unused labels with -Wunused.  That means we have to
-     mark the used labels as used.  */
-  if (TREE_CODE (destination) == LABEL_DECL)
-    TREE_USED (destination) = 1;
-    
-  emit_line_note (input_filename, lineno);
-  
-  if (TREE_CODE (destination) == LABEL_DECL)
-    {
-      label_rtx (destination);
-      expand_goto (destination); 
-    }
-  else
-    expand_computed_goto (destination);
+  add_stmt (build_stmt (GOTO_STMT, destination));
 }
 
 /* COND is the condition-expression for an if, while, etc.,
    statement.  Convert it to a boolean value, if appropriate.  */
 
-static tree
+tree
 maybe_convert_cond (cond)
      tree cond;
 {
@@ -274,45 +203,19 @@ finish_expr_stmt (expr)
   if (expr != NULL_TREE)
     {
       if (!processing_template_decl
-         && !stmts_are_full_exprs_p
+         && !(stmts_are_full_exprs_p ())
          && ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
               && lvalue_p (expr))
              || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
        expr = default_conversion (expr);
       
-      if (stmts_are_full_exprs_p)
+      if (stmts_are_full_exprs_p ())
        expr = convert_to_void (expr, "statement");
       
       if (!processing_template_decl)
        expr = break_out_cleanups (expr);
       
-      add_tree (build_min_nt (EXPR_STMT, expr));
-    }
-
-  finish_stmt ();
-
-  /* This was an expression-statement, so we save the type of the
-     expression.  */
-  last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
-}
-
-/* Generate the RTL for EXPR, which is an EXPR_STMT. */
-
-void 
-genrtl_expr_stmt (expr)
-     tree expr;
-{
-  if (expr != NULL_TREE)
-    {
-      emit_line_note (input_filename, lineno);
-      
-      if (stmts_are_full_exprs_p)
-       expand_start_target_temps ();
-      
-      cplus_expand_expr_stmt (expr);
-      
-      if (stmts_are_full_exprs_p)
-       expand_end_target_temps ();
+      add_stmt (build_stmt (EXPR_STMT, expr));
     }
 
   finish_stmt ();
@@ -322,66 +225,6 @@ genrtl_expr_stmt (expr)
   last_expr_type = expr ? TREE_TYPE (expr) : NULL_TREE;
 }
 
-/* Generate the RTL for T, which is a DECL_STMT. */
-
-void
-genrtl_decl_stmt (t)
-     tree t;
-{
-  tree decl;
-  emit_line_note (input_filename, lineno);
-  decl = DECL_STMT_DECL (t);
-  /* If this is a declaration for an automatic local
-     variable, initialize it.  Note that we might also see a
-     declaration for a namespace-scope object (declared with
-     `extern').  We don't have to handle the initialization
-     of those objects here; they can only be declarations,
-     rather than definitions.  */
-  if (TREE_CODE (decl) == VAR_DECL 
-      && !TREE_STATIC (decl)
-      && !DECL_EXTERNAL (decl))
-    {
-      /* Let the back-end know about this variable.  */
-      if (!ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
-       emit_local_var (decl);
-      else
-       expand_anon_union_decl (decl, NULL_TREE, 
-                               DECL_ANON_UNION_ELEMS (decl));
-    }
-  else if (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
-    {
-      if (DECL_ARTIFICIAL (decl) && ! TREE_USED (decl))
-       /* Do not emit unused decls. This is not just an
-          optimization. We really do not want to emit
-          __PRETTY_FUNCTION__ etc, if they're never used.  */
-       DECL_IGNORED_P (decl) = 1;
-      else
-       make_rtl_for_local_static (decl);
-    }
-}
-
-/* Generate the RTL for T, which is an IF_STMT. */
-
-void
-genrtl_if_stmt (t)
-     tree t;
-{
-  tree cond;
-  genrtl_do_pushlevel ();
-  cond = maybe_convert_cond (expand_cond (IF_COND (t)));
-  emit_line_note (input_filename, lineno);
-  expand_start_cond (cond, 0);
-  if (THEN_CLAUSE (t))
-    expand_stmt (THEN_CLAUSE (t));
-  if (ELSE_CLAUSE (t))
-    {
-      expand_start_else ();
-      expand_stmt (ELSE_CLAUSE (t));
-    }
-  expand_end_cond ();
-  genrtl_do_poplevel ();
-  finish_stmt ();
-}
 
 /* Begin an if-statement.  Returns a newly created IF_STMT if
    appropriate.  */
@@ -391,8 +234,8 @@ begin_if_stmt ()
 {
   tree r;
   do_pushlevel ();
-  r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   return r;
 }
 
@@ -416,7 +259,7 @@ finish_then_clause (if_stmt)
      tree if_stmt;
 {
   RECHAIN_STMTS (if_stmt, THEN_CLAUSE (if_stmt));
-  SET_LAST_STMT (if_stmt);
+  last_tree = if_stmt;
   return if_stmt;
 }
 
@@ -459,30 +302,6 @@ clear_out_block ()
     }
 }
 
-/* Generate the RTL for T, which is a WHILE_STMT. */
-
-void
-genrtl_while_stmt (t)
-     tree t;
-{
-  tree cond;
-  emit_nop ();
-  emit_line_note (input_filename, lineno);
-  expand_start_loop (1); 
-  genrtl_do_pushlevel ();
-
-  cond = maybe_convert_cond (expand_cond (WHILE_COND (t)));
-  emit_line_note (input_filename, lineno);
-  expand_exit_loop_if_false (0, cond);
-  genrtl_clear_out_block ();
-  
-  expand_stmt (WHILE_BODY (t));
-
-  genrtl_do_poplevel ();
-  expand_end_loop ();
-  finish_stmt ();
-}
-
 /* Begin a while-statement.  Returns a newly created WHILE_STMT if
    appropriate.  */
 
@@ -490,8 +309,8 @@ tree
 begin_while_stmt ()
 {
   tree r;
-  r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   do_pushlevel ();
   return r;
 }
@@ -520,36 +339,14 @@ finish_while_stmt (while_stmt)
   finish_stmt ();
 }
 
-/* Generate the RTL for T, which is a DO_STMT. */
-
-void
-genrtl_do_stmt (t)
-    tree t;
-{
-  tree cond;
-  emit_nop ();
-  emit_line_note (input_filename, lineno);
-  expand_start_loop_continue_elsewhere (1);
-
-  expand_stmt (DO_BODY (t));
-
-  expand_loop_continue_here ();
-
-  cond = maybe_convert_cond (DO_COND (t));
-  emit_line_note (input_filename, lineno);
-  expand_exit_loop_if_false (0, cond);
-  expand_end_loop ();
-  finish_stmt ();  
-}
-
 /* Begin a do-statement.  Returns a newly created DO_STMT if
    appropriate.  */
 
 tree
 begin_do_stmt ()
 {
-  tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  tree r = build_stmt (DO_STMT, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   return r;
 }
 
@@ -575,17 +372,6 @@ finish_do_stmt (cond, do_stmt)
   finish_stmt ();
 }
 
-/* Generate the RTL for EXPR, which is a RETURN_STMT. */
-
-void
-genrtl_return_stmt (expr)
-     tree expr;
-{
-  emit_line_note (input_filename, lineno);
-  c_expand_return (expr);
-  finish_stmt ();
-}
-
 /* Finish a return-statement.  The EXPRESSION returned, if any, is as
    indicated.  */
 
@@ -618,51 +404,10 @@ finish_return_stmt (expr)
          return;
        }
     }
-  add_tree (build_min_nt (RETURN_STMT, expr));
+  add_stmt (build_stmt (RETURN_STMT, expr));
   finish_stmt ();
 }
 
-/* Generate the RTL for T, which is a FOR_STMT. */
-
-void
-genrtl_for_stmt (t)
-     tree t;
-{
-  tree tmp;
-  tree cond;
-  if (flag_new_for_scope > 0)
-    {
-      genrtl_do_pushlevel ();
-      note_level_for_for ();
-    }  
-
-  expand_stmt (FOR_INIT_STMT (t));
-
-  emit_nop ();
-  emit_line_note (input_filename, lineno);
-  expand_start_loop_continue_elsewhere (1); 
-  genrtl_do_pushlevel ();
-  cond = maybe_convert_cond (expand_cond (FOR_COND (t)));
-  emit_line_note (input_filename, lineno);
-  if (cond)
-    expand_exit_loop_if_false (0, cond);
-  genrtl_clear_out_block ();
-  tmp = FOR_EXPR (t);
-
-  expand_stmt (FOR_BODY (t));
-
-  /* Pop the scope for the body of the loop.  */
-  genrtl_do_poplevel ();
-  emit_line_note (input_filename, lineno);
-  expand_loop_continue_here ();
-  if (tmp) 
-    genrtl_expr_stmt (tmp);
-  expand_end_loop ();
-  if (flag_new_for_scope > 0)
-    genrtl_do_poplevel ();
-  finish_stmt (); 
-}
-
 /* Begin a for-statement.  Returns a new FOR_STMT if appropriate.  */
 
 tree
@@ -670,11 +415,11 @@ begin_for_stmt ()
 {
   tree r;
 
-  r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE, 
-                   NULL_TREE, NULL_TREE);
-  add_tree (r);
-  
-  if (flag_new_for_scope > 0)
+  r = build_stmt (FOR_STMT, NULL_TREE, NULL_TREE, 
+                 NULL_TREE, NULL_TREE);
+  NEW_FOR_SCOPE_P (r) = flag_new_for_scope > 0;
+  add_stmt (r);
+  if (NEW_FOR_SCOPE_P (r))
     {
       do_pushlevel ();
       note_level_for_for ();
@@ -730,38 +475,17 @@ finish_for_stmt (for_stmt)
   /* Pop the scope for the body of the loop.  */
   do_poplevel ();
   RECHAIN_STMTS (for_stmt, FOR_BODY (for_stmt));
-  if (flag_new_for_scope > 0)
+  if (NEW_FOR_SCOPE_P (for_stmt))
     do_poplevel ();
   finish_stmt (); 
 }
 
-/* Generate the RTL for a BREAK_STMT. */
-
-void
-genrtl_break_stmt ()
-{
-  emit_line_note (input_filename, lineno);
-  if ( ! expand_exit_something ())
-    cp_error ("break statement not within loop or switch");
-}
-
 /* Finish a break-statement.  */
 
 void
 finish_break_stmt ()
 {
-  emit_line_note (input_filename, lineno);
-  add_tree (build_min_nt (BREAK_STMT));
-}
-
-/* Generate the RTL for a CONTINUE_STMT. */
-
-void
-genrtl_continue_stmt ()
-{
-  emit_line_note (input_filename, lineno);
-  if (! expand_continue_loop (0))
-    cp_error ("continue statement not within a loop");   
+  add_stmt (build_break_stmt ());
 }
 
 /* Finish a continue-statement.  */
@@ -769,62 +493,7 @@ genrtl_continue_stmt ()
 void
 finish_continue_stmt ()
 {
-  emit_line_note (input_filename, lineno);
-  add_tree (build_min_nt (CONTINUE_STMT));
-}
-
-/* Generate the RTL for T, which is a SCOPE_STMT. */
-
-void
-genrtl_scope_stmt (t)
-     tree t;
-{
-  if (!SCOPE_NO_CLEANUPS_P (t))
-    {
-      if (SCOPE_BEGIN_P (t))
-       expand_start_bindings_and_block (2 * SCOPE_NULLIFIED_P (t),
-                                        SCOPE_STMT_BLOCK (t));
-      else if (SCOPE_END_P (t))
-       expand_end_bindings (NULL_TREE, !SCOPE_NULLIFIED_P (t), 0);
-    }
-  else if (!SCOPE_NULLIFIED_P (t))
-    {
-      rtx note = emit_note (NULL,
-                           (SCOPE_BEGIN_P (t) 
-                            ? NOTE_INSN_BLOCK_BEG
-                            : NOTE_INSN_BLOCK_END));
-      NOTE_BLOCK (note) = SCOPE_STMT_BLOCK (t);
-    }
-}
-
-/* Generate the RTL for T, which is a SWITCH_STMT. */
-
-void
-genrtl_switch_stmt (t)
-     tree t;
-{
-  tree cond;
-  genrtl_do_pushlevel ();
-  cond = expand_cond (SWITCH_COND (t));
-  if (cond != error_mark_node)
-    {
-      emit_line_note (input_filename, lineno);
-      c_expand_start_case (cond);
-    }
-  else
-    /* The code is in error, but we don't want expand_end_case to
-       crash. */
-    c_expand_start_case (boolean_false_node);
-
-  push_switch ();
-
-  expand_stmt (SWITCH_BODY (t));
-
-  expand_end_case (cond);
-  pop_switch (); 
-  genrtl_do_poplevel ();
-  finish_stmt ();  
+  add_stmt (build_continue_stmt ());
 }
 
 /* Begin a switch-statement.  Returns a new SWITCH_STMT if
@@ -834,8 +503,8 @@ tree
 begin_switch_stmt ()
 {
   tree r;
-  r = build_min_nt (SWITCH_STMT, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  r = build_stmt (SWITCH_STMT, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   do_pushlevel ();
   return r;
 }
@@ -849,6 +518,9 @@ finish_switch_cond (cond, switch_stmt)
 {
   if (!processing_template_decl)
     {
+      tree type;
+      tree index;
+
       /* Convert the condition to an integer or enumeration type.  */
       cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, 1);
       if (cond == NULL_TREE)
@@ -858,25 +530,22 @@ finish_switch_cond (cond, switch_stmt)
        }
       if (cond != error_mark_node)
        {
-         tree idx;
-         tree type;
-         
          cond = default_conversion (cond);
-         type = TREE_TYPE (cond);
-         idx = get_unwidened (cond, 0);
-         /* We can't strip a conversion from a signed type to an unsigned,
-            because if we did, int_fits_type_p would do the wrong thing
-            when checking case values for being in range,
-            and it's too hard to do the right thing.  */
-         if (TREE_UNSIGNED (TREE_TYPE (cond)) 
-             == TREE_UNSIGNED (TREE_TYPE (idx)))
-           cond = idx;
-         
-         cond = fold (build1 (CLEANUP_POINT_EXPR, type, cond));
+         cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond));
        }
+
+      type = TREE_TYPE (cond);
+      index = get_unwidened (cond, NULL_TREE);
+      /* We can't strip a conversion from a signed type to an unsigned,
+        because if we did, int_fits_type_p would do the wrong thing
+        when checking case values for being in range,
+        and it's too hard to do the right thing.  */
+      if (TREE_UNSIGNED (TREE_TYPE (cond))
+         == TREE_UNSIGNED (TREE_TYPE (index)))
+       cond = index;
     }
   FINISH_COND (cond, switch_stmt, SWITCH_COND (switch_stmt));
-  push_switch ();
+  push_switch (switch_stmt);
 }
 
 /* Finish the body of a switch-statement, which may be given by
@@ -892,34 +561,10 @@ finish_switch_stmt (switch_stmt)
   finish_stmt ();
 }
 
-/* Generate the RTL for a CASE_LABEL. */
-
-void 
-genrtl_case_label (low_value, high_value)
-     tree low_value;
-     tree high_value;
-{
-  do_case (low_value, high_value);
-}
-
-/* Finish a case-label.  */
-
-void 
-finish_case_label (low_value, high_value)
-     tree low_value;
-     tree high_value;
-{
-  /* Add a representation for the case label to the statement
-     tree.  */
-  add_tree (build_min_nt (CASE_LABEL, low_value, high_value));
-  /* And warn about crossing initializations, etc.  */
-  if (!processing_template_decl)
-    define_case_label ();
-}
-
 /* Generate the RTL for T, which is a TRY_BLOCK. */
 
-void genrtl_try_block (t)
+static void 
+genrtl_try_block (t)
      tree t;
 {
   if (CLEANUP_P (t))
@@ -930,15 +575,9 @@ void genrtl_try_block (t)
     }
   else
     {
-      if (FN_TRY_BLOCK_P (t)) {
-       if (! current_function_parms_stored)
-         store_parm_decls ();
-       expand_start_early_try_stmts ();
-      }
-      else {
+      if (!FN_TRY_BLOCK_P (t)) 
        emit_line_note (input_filename, lineno);
-       expand_start_try_stmts ();
-      }
+      expand_start_try_stmts ();
 
       expand_stmt (TRY_STMTS (t));
 
@@ -966,8 +605,8 @@ void genrtl_try_block (t)
 tree
 begin_try_block ()
 {
-  tree r = build_min_nt (TRY_BLOCK, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   return r;
 }
 
@@ -976,9 +615,9 @@ begin_try_block ()
 tree
 begin_function_try_block ()
 {
-  tree r = build_min_nt (TRY_BLOCK, NULL_TREE, NULL_TREE);
+  tree r = build_stmt (TRY_BLOCK, NULL_TREE, NULL_TREE);
   FN_TRY_BLOCK_P (r) = 1;
-  add_tree (r);
+  add_stmt (r);
   return r;
 }
 
@@ -1056,7 +695,7 @@ finish_function_handler_sequence (try_block)
 
 /* Generate the RTL for T, which is a HANDLER. */
 
-void
+static void
 genrtl_handler (t)
      tree t;
 {
@@ -1070,8 +709,6 @@ genrtl_handler (t)
       expand_goto (top_label_entry (&caught_return_label_stack));
       end_catch_handler ();
     }
-
-  genrtl_do_poplevel ();  
 }
 
 /* Begin a handler.  Returns a HANDLER if appropriate.  */
@@ -1080,8 +717,8 @@ tree
 begin_handler ()
 {
   tree r;
-  r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
-  add_tree (r);
+  r = build_stmt (HANDLER, NULL_TREE, NULL_TREE);
+  add_stmt (r);
   do_pushlevel ();
   return r;
 }
@@ -1118,7 +755,7 @@ finish_handler_parms (decl, handler)
 
 /* Generate the RTL for a CATCH_BLOCK. */
 
-void
+static void
 genrtl_catch_block (type)
      tree type;
 {
@@ -1133,7 +770,7 @@ void
 begin_catch_block (type)
      tree type;
 {
-  add_tree (build (START_CATCH_STMT, type));
+  add_stmt (build (START_CATCH_STMT, type));
 }
 
 /* Finish a handler, which may be given by HANDLER.  The BLOCKs are
@@ -1152,7 +789,7 @@ finish_handler (blocks, handler)
 
 /* Generate the RTL for T, which is a CTOR_STMT. */
 
-void
+static void
 genrtl_ctor_stmt (t)
      tree t;
 {
@@ -1165,79 +802,6 @@ genrtl_ctor_stmt (t)
     end_protect_partials ();
 }
 
-/* Generate the RTL for the start of a COMPOUND_STMT. */
-
-tree genrtl_begin_compound_stmt (has_no_scope)
-     int has_no_scope;
-{
-  tree r; 
-  int is_try = 0;
-
-  r = NULL_TREE;
-
-  last_expr_type = NULL_TREE;
-
-  if (!has_no_scope)
-    {
-      genrtl_do_pushlevel ();
-      if (is_try)
-       note_level_for_eh ();
-    }
-  else
-    /* Normally, we try hard to keep the BLOCK for a
-       statement-expression.  But, if it's a statement-expression with
-       a scopeless block, there's nothing to keep, and we don't want
-       to accidentally keep a block *inside* the scopeless block.  */ 
-    keep_next_level (0);
-
-  /* If this is the outermost block of the function, declare the
-     variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
-  if (cfun
-      && !current_function_name_declared 
-      && !has_no_scope)
-    {
-      current_function_name_declared = 1;
-      declare_function_name ();
-    }
-
-  return r;
-}
-
-/* Generate the RTL for the end of a COMPOUND_STMT. */
-
-tree genrtl_finish_compound_stmt (has_no_scope)
-     int has_no_scope;
-{
-  tree r;
-  tree t;
-
-  if (!has_no_scope)
-    r = genrtl_do_poplevel ();
-  else
-    r = NULL_TREE;
-
-  /* When we call finish_stmt we will lose 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;
-}
-
-/* Generate the RTL for T, which is a COMPOUND_STMT. */
-
-tree 
-genrtl_compound_stmt (t)
-    tree t;
-{
-  genrtl_begin_compound_stmt (COMPOUND_STMT_NO_SCOPE (t));
-  expand_stmt (COMPOUND_BODY (t));
-  return (genrtl_finish_compound_stmt (COMPOUND_STMT_NO_SCOPE (t)));
-}
-
 /* Begin a compound-statement.  If HAS_NO_SCOPE is non-zero, the
    compound-statement does not define a scope.  Returns a new
    COMPOUND_STMT if appropriate.  */
@@ -1249,12 +813,12 @@ begin_compound_stmt (has_no_scope)
   tree r; 
   int is_try = 0;
 
-  r = build_min_nt (COMPOUND_STMT, NULL_TREE);
+  r = build_stmt (COMPOUND_STMT, NULL_TREE);
 
   if (last_tree && TREE_CODE (last_tree) == TRY_BLOCK)
     is_try = 1;
 
-  add_tree (r);
+  add_stmt (r);
   if (has_no_scope)
     COMPOUND_STMT_NO_SCOPE (r) = 1;
 
@@ -1264,7 +828,7 @@ begin_compound_stmt (has_no_scope)
     {
       do_pushlevel ();
       if (is_try)
-       note_level_for_eh ();
+       note_level_for_eh ();
     }
   else
     /* Normally, we try hard to keep the BLOCK for a
@@ -1276,10 +840,10 @@ begin_compound_stmt (has_no_scope)
   /* If this is the outermost block of the function, declare the
      variables __FUNCTION__, __PRETTY_FUNCTION__, and so forth.  */
   if (cfun
-      && !current_function_name_declared 
+      && !function_name_declared_p
       && !has_no_scope)
     {
-      current_function_name_declared = 1;
+      function_name_declared_p = 1;
       declare_function_name ();
     }
 
@@ -1316,42 +880,6 @@ finish_compound_stmt (has_no_scope, compound_stmt)
   return r;
 }
 
-/* Generate the RTL for an ASM_STMT. */
-
-void
-genrtl_asm_stmt (cv_qualifier, string, output_operands,
-                input_operands, clobbers)
-     tree cv_qualifier;
-     tree string;
-     tree output_operands;
-     tree input_operands;
-     tree clobbers;
-{
-  if (TREE_CHAIN (string))
-    string = combine_strings (string);
-
-  if (cv_qualifier != NULL_TREE
-      && cv_qualifier != ridpointers[(int) RID_VOLATILE])
-    {
-      cp_warning ("%s qualifier ignored on asm",
-                 IDENTIFIER_POINTER (cv_qualifier));
-      cv_qualifier = NULL_TREE;
-    }
-
-  emit_line_note (input_filename, lineno);
-  if (output_operands != NULL_TREE || input_operands != NULL_TREE
-      || clobbers != NULL_TREE)
-    c_expand_asm_operands (string, output_operands,
-                          input_operands, 
-                          clobbers,
-                          cv_qualifier != NULL_TREE,
-                          input_filename, lineno);
-  else
-    expand_asm (string);
-  
-  finish_stmt ();
-}
-
 /* Finish an asm-statement, whose components are a CV_QUALIFIER, a
    STRING, some OUTPUT_OPERANDS, some INPUT_OPERANDS, and some
    CLOBBERS.  */
@@ -1383,10 +911,10 @@ finish_asm_stmt (cv_qualifier, string, output_operands,
     for (t = input_operands; t; t = TREE_CHAIN (t))
       TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
 
-  r = build_min_nt (ASM_STMT, cv_qualifier, string,
-                   output_operands, input_operands,
-                   clobbers);
-  add_tree (r);
+  r = build_stmt (ASM_STMT, cv_qualifier, string,
+                 output_operands, input_operands,
+                 clobbers);
+  add_stmt (r);
 }
 
 /* Finish a label with the indicated NAME.  */
@@ -1396,7 +924,7 @@ finish_label_stmt (name)
      tree name;
 {
   tree decl = define_label (input_filename, lineno, name);
-  add_tree (build_min_nt (LABEL_STMT, decl));
+  add_stmt (build_stmt (LABEL_STMT, decl));
 }
 
 /* Finish a series of declarations for local labels.  G++ allows users
@@ -1411,23 +939,9 @@ finish_label_decl (name)
   add_decl_stmt (decl);
 }
 
-/* Create a declaration statement for the declaration given by the
-   DECL.  */
-
-void
-add_decl_stmt (decl)
-     tree decl;
-{
-  tree decl_stmt;
-
-  /* We need the type to last until instantiation time.  */
-  decl_stmt = build_min_nt (DECL_STMT, decl);
-  add_tree (decl_stmt); 
-}
-
 /* Generate the RTL for a SUBOBJECT. */
 
-void 
+static void 
 genrtl_subobject (cleanup)
      tree cleanup;
 {
@@ -1442,19 +956,8 @@ void
 finish_subobject (cleanup)
      tree cleanup;
 {
-  tree r = build_min_nt (SUBOBJECT, cleanup);
-  add_tree (r);
-}
-
-/* Generate the RTL for a DECL_CLEANUP. */
-
-void 
-genrtl_decl_cleanup (decl, cleanup)
-     tree decl;
-     tree cleanup;
-{
-  if (!decl || (DECL_SIZE (decl) && TREE_TYPE (decl) != error_mark_node))
-    expand_decl_cleanup (decl, cleanup);
+  tree r = build_stmt (SUBOBJECT, cleanup);
+  add_stmt (r);
 }
 
 /* When DECL goes out of scope, make sure that CLEANUP is executed.  */
@@ -1464,61 +967,33 @@ finish_decl_cleanup (decl, cleanup)
      tree decl;
      tree cleanup;
 {
-  add_tree (build_min_nt (CLEANUP_STMT, decl, cleanup));
+  add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
 }
 
 /* Generate the RTL for a RETURN_INIT. */
 
-void
-genrtl_named_return_value (return_id, init)
-     tree return_id, init;
+static void
+genrtl_named_return_value ()
 {
-  tree decl;
-  /* Clear this out so that finish_named_return_value can set it
-     again.  */
-  DECL_NAME (DECL_RESULT (current_function_decl)) = NULL_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 ("ISO 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;
-    }
+  tree decl = DECL_RESULT (current_function_decl);
 
-  /* 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))
     {
-      /* Let `cp_finish_decl' know that this initializer is ok.  */
-      DECL_INITIAL (decl) = init;
-      cp_finish_decl (decl, init, NULL_TREE, 0);
-      store_return_init (decl);
+      /* Note that the mode of the old DECL_RTL may be wider than the
+        mode of DECL_RESULT, depending on the calling conventions for
+        the processor.  For example, on the Alpha, a 32-bit integer
+        is returned in a DImode register -- the DECL_RESULT has
+        SImode but the DECL_RTL for the DECL_RESULT has DImode.  So,
+        here, we use the mode the back-end has already assigned for
+        the return value.  */
+      DECL_RTL (decl) = gen_reg_rtx (GET_MODE (DECL_RTL (decl)));
+      if (TREE_ADDRESSABLE (decl))
+       put_var_into_stack (decl);
     }
 
-  /* Don't use tree-inlining for functions with named return values.
-     That doesn't work properly because we don't do any translation of
-     the RETURN_INITs when they are copied.  */
-  DECL_UNINLINABLE (current_function_decl) = 1;
+  emit_local_var (decl);
 }
 
 /* Bind a name and initialization to the return value of
@@ -1530,11 +1005,12 @@ finish_named_return_value (return_id, init)
 {
   tree decl = DECL_RESULT (current_function_decl);
 
+  /* 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.  */
   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 ("ISO C++ does not permit named return values");
+  cp_deprecated ("the named return value extension");
 
   if (return_id != NULL_TREE)
     {
@@ -1564,7 +1040,13 @@ finish_named_return_value (return_id, init)
       DECL_INITIAL (decl) = init;
       if (doing_semantic_analysis_p ())
        pushdecl (decl);
-      add_tree (build_min_nt (RETURN_INIT, return_id, init));
+      if (!processing_template_decl) 
+       {
+         cp_finish_decl (decl, init, NULL_TREE, 0);
+         add_stmt (build_stmt (RETURN_INIT, NULL_TREE, NULL_TREE));
+       }
+      else
+       add_stmt (build_stmt (RETURN_INIT, return_id, init));
     }
 
   /* Don't use tree-inlining for functions with named return values.
@@ -1650,7 +1132,7 @@ setup_vtbl_ptr (member_init_list, base_init_list)
   if (DECL_CONSTRUCTOR_P (current_function_decl))
     {
       if (processing_template_decl)
-       add_tree (build_min_nt
+       add_stmt (build_min_nt
                  (CTOR_INITIALIZER,
                   member_init_list, base_init_list));
       else
@@ -1658,9 +1140,9 @@ setup_vtbl_ptr (member_init_list, base_init_list)
          tree ctor_stmt;
 
          /* Mark the beginning of the constructor.  */
-         ctor_stmt = build_min_nt (CTOR_STMT);
+         ctor_stmt = build_stmt (CTOR_STMT);
          CTOR_BEGIN_P (ctor_stmt) = 1;
-         add_tree (ctor_stmt);
+         add_stmt (ctor_stmt);
          
          /* And actually initialize the base-classes and members.  */
          emit_base_init (member_init_list, base_init_list);
@@ -1694,10 +1176,10 @@ setup_vtbl_ptr (member_init_list, base_init_list)
 
       /* Don't declare __PRETTY_FUNCTION__ and friends here when we
         open the block for the if-body.  */
-      saved_cfnd = current_function_name_declared;
-      current_function_name_declared = 1;
+      saved_cfnd = function_name_declared_p;
+      function_name_declared_p = 1;
       compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
-      current_function_name_declared = saved_cfnd;
+      function_name_declared_p = saved_cfnd;
 
       /* Make all virtual function table pointers in non-virtual base
         classes point to CURRENT_CLASS_TYPE's virtual function
@@ -1718,48 +1200,12 @@ setup_vtbl_ptr (member_init_list, base_init_list)
   vtbls_set_up_p = 1;
 }
 
+/* Returns the stack of SCOPE_STMTs for the current function.  */
 
-/* Add a scope-statement to the statement-tree.  BEGIN_P indicates
-   whether this statements opens or closes a scope.  PARTIAL_P is true
-   for a partial scope, i.e, the scope that begins after a label when
-   an object that needs a cleanup is created.  If BEGIN_P is nonzero,
-   returns a new TREE_LIST representing the top of the SCOPE_STMT
-   stack.  The TREE_PURPOSE is the new SCOPE_STMT.  If BEGIN_P is
-   zero, returns a TREE_LIST whose TREE_VALUE is the new SCOPE_STMT,
-   and whose TREE_PURPOSE is the matching SCOPE_STMT iwth
-   SCOPE_BEGIN_P set.  */
-
-tree
-add_scope_stmt (begin_p, partial_p)
-     int begin_p;
-     int partial_p;
+tree *
+current_scope_stmt_stack ()
 {
-  tree ss;
-  tree top;
-
-  /* Build the statement.  */
-  ss = build_min_nt (SCOPE_STMT, NULL_TREE);
-  SCOPE_BEGIN_P (ss) = begin_p;
-  SCOPE_PARTIAL_P (ss) = partial_p;
-
-  /* Keep the scope stack up to date.  */
-  if (begin_p)
-    {
-      current_scope_stmt_stack 
-       = tree_cons (ss, NULL_TREE, current_scope_stmt_stack);
-      top = current_scope_stmt_stack;
-    }
-  else
-    {
-      top = current_scope_stmt_stack;
-      TREE_VALUE (top) = ss;
-      current_scope_stmt_stack = TREE_CHAIN (top);
-    }
-
-  /* Add the new statement to the statement-tree.  */
-  add_tree (ss);
-
-  return top;
+  return &cfun->language->x_scope_stmt_stack;
 }
 
 /* Finish a parenthesized expression EXPR.  */
@@ -1772,6 +1218,10 @@ finish_parenthesized_expr (expr)
     /* This inhibits warnings in truthvalue_conversion.  */
     C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK); 
 
+  if (TREE_CODE (expr) == OFFSET_REF)
+    /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be
+       enclosed in parentheses.  */
+    PTRMEM_OK_P (expr) = 0;
   return expr;
 }
 
@@ -1845,7 +1295,7 @@ finish_stmt_expr (rtl_expr)
   
   /* Remove the compound statement from the tree structure; it is
      now saved in the STMT_EXPR.  */
-  SET_LAST_STMT (rtl_expr);
+  last_tree = rtl_expr;
   TREE_CHAIN (last_tree) = NULL_TREE;
 
   /* If we created a statement-tree for this statement-expression,
@@ -1977,7 +1427,7 @@ finish_object_call_expr (fn, object, args)
 }
 
 /* Finish a qualified member function call using OBJECT and ARGS as
-   arguments to FN.  Returns an expressino for the call.  */
+   arguments to FN.  Returns an expression for the call.  */
 
 tree 
 finish_qualified_object_call_expr (fn, object, args)
@@ -2312,6 +1762,7 @@ begin_class_definition (t)
          TYPE_FIELDS (t) = NULL_TREE;
          TYPE_METHODS (t) = NULL_TREE;
          CLASSTYPE_TAGS (t) = NULL_TREE;
+         CLASSTYPE_VBASECLASSES (t) = NULL_TREE;
          TYPE_SIZE (t) = NULL_TREE;
        }
 
@@ -2409,7 +1860,7 @@ finish_member_declaration (decl)
     {
       /* We also need to add this function to the
         CLASSTYPE_METHOD_VEC.  */
-      add_method (current_class_type, 0, decl);
+      add_method (current_class_type, decl, /*error_p=*/0);
 
       TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
       TYPE_METHODS (current_class_type) = decl;
@@ -2494,8 +1945,7 @@ finish_class_definition (t, attributes, semi, pop_scope_p)
 void
 begin_inline_definitions ()
 {
-  if (pending_inlines 
-      && current_scope () == current_function_decl)
+  if (current_scope () == current_function_decl)
     do_pending_inlines ();
 }
 
@@ -2554,7 +2004,7 @@ finish_template_decl (parms)
     end_specialization ();
 }
 
-/* Finish processing a template-id (which names a type) of the form
+/* Finish processing a template-id (which names a type) of the form
    NAME < ARGS >.  Return the TYPE_DECL for the type named by the
    template-id.  If ENTERING_SCOPE is non-zero we are about to enter
    the scope of template-id indicated.  */
@@ -2677,201 +2127,47 @@ finish_typeof (expr)
   return TREE_TYPE (expr);
 }
 
-/* Create an empty statement tree rooted at T.  */
-
-void
-begin_stmt_tree (t)
-     tree *t;
-{
-  /* 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.  */
-  *t = build_nt (EXPR_STMT, void_zero_node);
-  SET_LAST_STMT (*t);
-  last_expr_type = NULL_TREE;
-}
-
-/* Finish the statement tree rooted at T.  */
-
-void
-finish_stmt_tree (t)
-     tree *t;
-{
-  tree stmt;
-  
-  /* Remove the fake extra statement added in begin_stmt_tree.  */
-  stmt = TREE_CHAIN (*t);
-  *t = stmt;
-  SET_LAST_STMT (NULL_TREE);
-
-  if (cfun)
-    {
-      /* The line-number recorded in the outermost statement in a function
-        is the line number of the end of the function.  */
-      STMT_LINENO (stmt) = lineno;
-      STMT_LINENO_FOR_FN_P (stmt) = 1;
-    }
-}
-
-/* We're about to expand T, a statement.  Set up appropriate context
-   for the substitution.  */
-
-void
-prep_stmt (t)
-     tree t;
-{
-  if (!STMT_LINENO_FOR_FN_P (t))
-    lineno = STMT_LINENO (t);
-  stmts_are_full_exprs_p = STMT_IS_FULL_EXPR_P (t);
-}
-
-/* Some statements, like for-statements or if-statements, require a
-   condition.  This condition can be a declaration.  If T is such a
-   declaration it is processed, and an expression appropriate to use
-   as the condition is returned.  Otherwise, T itself is returned.  */
-
-static tree
-expand_cond (t)
-     tree t;
-{
-  if (t && TREE_CODE (t) == TREE_LIST)
-    {
-      expand_stmt (TREE_PURPOSE (t));
-      return TREE_VALUE (t);
-    }
-  else 
-    return t;
-}
-
 /* Generate RTL for the statement T, and its substatements, and any
    other statements at its nesting level.  */
 
-tree
-expand_stmt (t)
+static void
+cp_expand_stmt (t)
      tree t;
 {
-  tree rval = NULL_TREE;
-
-  while (t && t != error_mark_node)
+  switch (TREE_CODE (t))
     {
-      int saved_stmts_are_full_exprs_p;
+    case CLEANUP_STMT:
+      genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
+      break;
 
-      /* Assume we'll have nothing to return.  */
-      rval = NULL_TREE;
+    case START_CATCH_STMT:
+      genrtl_catch_block (TREE_TYPE (t));
+      break;
 
-      /* Set up context appropriately for handling this statement.  */
-      saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
-      prep_stmt (t);
+    case CTOR_STMT:
+      genrtl_ctor_stmt (t);
+      break;
 
-      switch (TREE_CODE (t))
-       {
-       case RETURN_STMT:
-         genrtl_return_stmt (RETURN_EXPR (t));
-         break;
-
-       case EXPR_STMT:
-         genrtl_expr_stmt (EXPR_STMT_EXPR (t));
-         break;
-
-       case DECL_STMT:
-         genrtl_decl_stmt (t);
-         break;
-
-       case CLEANUP_STMT:
-         genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t));
-         break;
-
-       case START_CATCH_STMT:
-         genrtl_catch_block (TREE_TYPE (t));
-         break;
-
-       case CTOR_STMT:
-         genrtl_ctor_stmt (t);
-         break;
-
-       case FOR_STMT:
-         genrtl_for_stmt (t);
-         break;
-
-       case WHILE_STMT:
-         genrtl_while_stmt (t);
-         break;
-
-       case DO_STMT:
-         genrtl_do_stmt (t);
-         break;
-
-       case IF_STMT:
-         genrtl_if_stmt (t);
-         break;
-
-       case COMPOUND_STMT:
-         rval = genrtl_compound_stmt (t);
-         break;
-
-       case BREAK_STMT:
-         genrtl_break_stmt ();
-         break;
-
-       case CONTINUE_STMT:
-         genrtl_continue_stmt ();
-         break;
-
-       case SWITCH_STMT:
-         genrtl_switch_stmt (t);
-         break;
-
-       case CASE_LABEL:
-         genrtl_case_label (CASE_LOW (t), CASE_HIGH (t));
-         break;
-
-       case LABEL_STMT:
-         expand_label (LABEL_STMT_LABEL (t));
-         break;
-
-       case GOTO_STMT:
-         genrtl_goto_stmt (GOTO_DESTINATION (t));
-         break;
-
-       case ASM_STMT:
-         genrtl_asm_stmt (ASM_CV_QUAL (t), ASM_STRING (t),
-                          ASM_OUTPUTS (t), ASM_INPUTS (t), ASM_CLOBBERS (t));
-         break;
-
-       case TRY_BLOCK:
-         genrtl_try_block (t);
-         break;
-
-       case HANDLER:
-         genrtl_handler (t);
-         break;
-
-       case SUBOBJECT:
-         genrtl_subobject (SUBOBJECT_CLEANUP (t));
-         break;
-
-       case SCOPE_STMT:
-         genrtl_scope_stmt (t);
-         break;
-
-       case RETURN_INIT:
-         genrtl_named_return_value (TREE_OPERAND (t, 0), 
-                                    TREE_OPERAND (t, 1));
-         break;
-
-       default:
-         my_friendly_abort (19990810);
-         break;
-       }
+    case TRY_BLOCK:
+      genrtl_try_block (t);
+      break;
 
-      /* Restore saved state.  */
-      stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
+    case HANDLER:
+      genrtl_handler (t);
+      break;
 
-      /* Go on to the next statement in this scope.  */
-      t = TREE_CHAIN (t);
-    }
+    case SUBOBJECT:
+      genrtl_subobject (SUBOBJECT_CLEANUP (t));
+      break;
+
+    case RETURN_INIT:
+      genrtl_named_return_value ();
+      break;
 
-  return rval;
+    default:
+      my_friendly_abort (19990810);
+      break;
+    }
 }
 
 /* Called from expand_body via walk_tree.  Replace all AGGR_INIT_EXPRs
@@ -3005,7 +2301,6 @@ emit_associated_thunks (fn)
     }
 }
 
-
 /* Generate RTL for FN.  */
 
 void
@@ -3034,7 +2329,9 @@ expand_body (fn)
     }
 
   /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs.  */
-  walk_tree (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, NULL);
+  walk_tree_without_duplicates (&DECL_SAVED_TREE (fn),
+                               simplify_aggr_init_exprs_r,
+                               NULL);
 
   /* If this is a constructor or destructor body, we have to clone it
      under the new ABI.  */
@@ -3100,28 +2397,27 @@ expand_body (fn)
   lineno = DECL_SOURCE_LINE (fn);
   input_filename = DECL_SOURCE_FILE (fn);
 
-  start_function (NULL_TREE, fn, NULL_TREE, SF_PRE_PARSED | SF_EXPAND);
-  store_parm_decls ();
+  genrtl_start_function (fn);
   current_function_is_thunk = DECL_THUNK_P (fn);
 
   /* We don't need to redeclare __FUNCTION__, __PRETTY_FUNCTION__, or
      any of the other magic variables we set up when starting a
      function body.  */
-  current_function_name_declared = 1;
+  function_name_declared_p = 1;
 
   /* Expand the body.  */
   expand_stmt (DECL_SAVED_TREE (fn));
 
   /* Statements should always be full-expressions at the outermost set
      of curly braces for a function.  */
-  my_friendly_assert (stmts_are_full_exprs_p, 19990831);
+  my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
 
   /* The outermost statement for a function contains the line number
      recorded when we finished processing the function.  */
   lineno = STMT_LINENO (DECL_SAVED_TREE (fn));
 
   /* Generate code for the function.  */
-  finish_function (0);
+  genrtl_finish_function (fn);
 
   /* If possible, obliterate the body of the function so that it can
      be garbage collected.  */
@@ -3139,6 +2435,261 @@ expand_body (fn)
   /* And restore the current source position.  */
   lineno = saved_lineno;
   input_filename = saved_input_filename;
+  extract_interface_info ();
 
   timevar_pop (TV_EXPAND);
 }
+
+/* Start generating the RTL for FN.  */
+
+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.  */
+  init_function_start (fn, DECL_SOURCE_FILE (fn), DECL_SOURCE_LINE (fn));
+  /* Let everybody know that we're expanding this function, not doing
+     semantic analysis.  */
+  expanding_p = 1;
+
+  /* Even though we're inside a function body, we still don't want to
+     call expand_expr to calculate the size of a variable-sized array.
+     We haven't necessarily assigned RTL to all variables yet, so it's
+     not safe to try to expand expressions involving them.  */
+  immediate_size_expand = 0;
+  cfun->x_dont_save_pending_sizes_p = 1;
+
+  /* Let the user know we're compiling this function.  */
+  announce_function (fn);
+
+  /* Initialize the per-function data.  */
+  my_friendly_assert (!DECL_PENDING_INLINE_P (fn), 20000911);
+  if (DECL_SAVED_FUNCTION_DATA (fn))
+    {
+      /* If we already parsed this function, and we're just expanding it
+        now, restore saved state.  */
+      *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (fn);
+
+      /* This function is being processed in whole-function mode; we
+        already did semantic analysis.  */
+      cfun->x_whole_function_mode_p = 1;
+
+      /* If we decided that we didn't want to inline this function,
+        make sure the back-end knows that.  */
+      if (!current_function_cannot_inline)
+       current_function_cannot_inline = cp_function_chain->cannot_inline;
+
+      /* We don't need the saved data anymore.  */
+      free (DECL_SAVED_FUNCTION_DATA (fn));
+      DECL_SAVED_FUNCTION_DATA (fn) = NULL;
+    }
+
+  /* Tell the cross-reference machinery that we're defining this
+     function.  */
+  GNU_xref_function (fn, DECL_ARGUMENTS (fn));
+
+  /* Keep track of how many functions we're presently expanding.  */
+  ++function_depth;
+
+  /* Create a binding level for the parameters.  */
+  expand_start_bindings (2);
+  /* Clear out any previously saved instructions for this function, in
+     case it was defined more than once.  */
+  DECL_SAVED_INSNS (fn) = NULL;
+  /* Go through the PARM_DECLs for this function to see if any need
+     cleanups.  */
+  for (parm = DECL_ARGUMENTS (fn); parm; parm = TREE_CHAIN (parm))
+    if (TREE_TYPE (parm) != error_mark_node
+       && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (parm)))
+      {
+       expand_function_start (fn, /*parms_have_cleanups=*/1);
+       break;
+      }
+  if (!parm)
+    expand_function_start (fn, /*parms_have_cleanups=*/0);
+  /* If this function is `main'.  */
+  if (DECL_MAIN_P (fn))
+    expand_main_function ();
+  /* Create a binding contour which can be used to catch
+     cleanup-generated temporaries.  */
+  expand_start_bindings (2);
+}
+
+/* Finish generating the RTL for FN.  */
+
+static void
+genrtl_finish_function (fn)
+     tree fn;
+{
+  tree no_return_label = NULL_TREE;
+
+#if 0
+  if (write_symbols != NO_DEBUG)
+    {
+      /* Keep this code around in case we later want to control debug info
+        based on whether a type is "used".  (jason 1999-11-11) */
+
+      tree ttype = target_type (fntype);
+      tree parmdecl;
+
+      if (IS_AGGR_TYPE (ttype))
+       /* Let debugger know it should output info for this type.  */
+       note_debug_info_needed (ttype);
+
+      for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
+       {
+         ttype = target_type (TREE_TYPE (parmdecl));
+         if (IS_AGGR_TYPE (ttype))
+           /* Let debugger know it should output info for this type.  */
+           note_debug_info_needed (ttype);
+       }
+    }
+#endif
+
+  /* Clean house because we will need to reorder insns here.  */
+  do_pending_stack_adjust ();
+
+  if (!dtor_label && !DECL_CONSTRUCTOR_P (fn)
+      && return_label != NULL_RTX
+      && current_function_return_value == NULL_TREE
+      && ! DECL_NAME (DECL_RESULT (current_function_decl)))
+    no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+
+  if (flag_exceptions)
+    expand_exception_blocks ();
+
+  /* If this function is supposed to return a value, ensure that
+     we do not fall into the cleanups by mistake.  The end of our
+     function will look like this:
+
+     user code (may have return stmt somewhere)
+     goto no_return_label
+     cleanup_label:
+     cleanups
+     goto return_label
+     no_return_label:
+     NOTE_INSN_FUNCTION_END
+     return_label:
+     things for return
+
+     If the user omits a return stmt in the USER CODE section, we
+     will have a control path which reaches NOTE_INSN_FUNCTION_END.
+     Otherwise, we won't.  */
+  if (no_return_label)
+    {
+      DECL_CONTEXT (no_return_label) = fn;
+      DECL_INITIAL (no_return_label) = error_mark_node;
+      DECL_SOURCE_FILE (no_return_label) = input_filename;
+      DECL_SOURCE_LINE (no_return_label) = lineno;
+      expand_goto (no_return_label);
+    }
+
+  if (cleanup_label)
+    {
+      /* Remove the binding contour which is used to catch
+        cleanup-generated temporaries.  */
+      expand_end_bindings (0, 0, 0);
+      poplevel (0, 0, 0);
+
+      /* Emit label at beginning of cleanup code for parameters.  */
+      emit_label (cleanup_label);
+    }
+
+  /* Finish building code that will trigger warnings if users forget
+     to make their functions return values.  */
+  emit_jump (return_label);
+  if (no_return_label)
+    {
+      /* We don't need to call `expand_*_return' here because we don't
+        need any cleanups here--this path of code is only for error
+        checking purposes.  */
+      expand_label (no_return_label);
+    }
+
+  /* We hard-wired immediate_size_expand to zero in start_function.
+     Expand_function_end will decrement this variable.  So, we set the
+     variable to one here, so that after the decrement it will remain
+     zero.  */
+  immediate_size_expand = 1;
+
+  /* Generate rtl for function exit.  */
+  expand_function_end (input_filename, lineno, 1);
+
+  /* If this is a nested function (like a template instantiation that
+     we're compiling in the midst of compiling something else), push a
+     new GC context.  That will keep local variables on the stack from
+     being collected while we're doing the compilation of this
+     function.  */
+  if (function_depth > 1)
+    ggc_push_context ();
+
+  /* Run the optimizers and output the assembler code for this
+     function.  */
+  rest_of_compilation (fn);
+
+  /* Undo the call to ggc_push_context above.  */
+  if (function_depth > 1)
+    ggc_pop_context ();
+
+  if (DECL_SAVED_INSNS (fn) && ! TREE_ASM_WRITTEN (fn))
+    {
+      /* Set DECL_EXTERNAL so that assemble_external will be called as
+        necessary.  We'll clear it again in finish_file.  */
+      if (! DECL_EXTERNAL (fn))
+       DECL_NOT_REALLY_EXTERN (fn) = 1;
+      DECL_EXTERNAL (fn) = 1;
+      defer_fn (fn);
+    }
+
+#if 0
+  /* Keep this code around in case we later want to control debug info
+     based on whether a type is "used".  (jason 1999-11-11) */
+
+  if (ctype && TREE_ASM_WRITTEN (fn))
+    note_debug_info_needed (ctype);
+#endif
+
+  /* If this function is marked with the constructor attribute, add it
+     to the list of functions to be called along with constructors
+     from static duration objects.  */
+  if (DECL_STATIC_CONSTRUCTOR (fn))
+    static_ctors = tree_cons (NULL_TREE, fn, static_ctors);
+
+  /* If this function is marked with the destructor attribute, add it
+     to the list of functions to be called along with destructors from
+     static duration objects.  */
+  if (DECL_STATIC_DESTRUCTOR (fn))
+    static_dtors = tree_cons (NULL_TREE, fn, static_dtors);
+
+  --function_depth;
+
+  if (!DECL_SAVED_INSNS (fn)
+      && !(flag_inline_trees && DECL_INLINE (fn)))
+    {
+      tree t;
+
+      /* Stop pointing to the local nodes about to be freed.  */
+      /* But DECL_INITIAL must remain nonzero so we know this
+        was an actual function definition.  */
+      DECL_INITIAL (fn) = error_mark_node;
+      for (t = DECL_ARGUMENTS (fn); t; t = TREE_CHAIN (t))
+       DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
+    }
+
+  /* Let the error reporting routines know that we're outside a
+     function.  For a nested function, this value is used in
+     pop_cp_function_context and then reset via pop_function_context.  */
+  current_function_decl = NULL_TREE;
+}
+
+/* Perform initialization related to this module.  */
+
+void
+init_cp_semantics ()
+{
+  lang_expand_stmt = cp_expand_stmt;
+}