OSDN Git Service

* cp/cp-tree.h (struct cp_language_function): Remove x_result_rtx.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 9ac30e4..82ebc36 100644 (file)
@@ -42,13 +42,10 @@ Boston, MA 02111-1307, USA.  */
 #include "except.h"
 #include "toplev.h"
 #include "../hash.h"
-#include "defaults.h"
 #include "ggc.h"
 
 extern int current_class_depth;
 
-extern tree static_ctors, static_dtors;
-
 extern tree global_namespace;
 
 extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
@@ -57,14 +54,6 @@ extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
 
 int ggc_p = 1;
 
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
 #ifndef BOOL_TYPE_SIZE
 #ifdef SLOW_BYTE_ACCESS
 /* In the new ABI, `bool' has size and alignment `1', on all
@@ -170,9 +159,8 @@ static void mark_named_label_lists PARAMS ((void *, void *));
 static void mark_cp_function_context PARAMS ((struct function *));
 static void mark_saved_scope PARAMS ((void *));
 static void mark_lang_function PARAMS ((struct cp_language_function *));
-static void mark_stmt_tree PARAMS ((stmt_tree));
 static void save_function_data PARAMS ((tree));
-static void check_function_type PARAMS ((tree));
+static void check_function_type PARAMS ((tree, tree));
 static void destroy_local_var PARAMS ((tree));
 static void finish_constructor_body PARAMS ((void));
 static void finish_destructor_body PARAMS ((void));
@@ -187,7 +175,7 @@ static tree check_special_function_return_type
   PARAMS ((special_function_kind, tree, tree, tree));
 static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
 static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
-static int case_compare PARAMS ((splay_tree_key, splay_tree_key));
+static void store_parm_decls PARAMS ((tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -456,10 +444,6 @@ struct binding_level
        that were entered and exited one level down.  */
     tree blocks;
 
-    /* The BLOCK node for this level, if one has been preallocated.
-       If 0, the BLOCK is allocated (if needed) when the level is popped.  */
-    tree this_block;
-
     /* The _TYPE node for this level, if parm_flag == 2.  */
     tree this_class;
 
@@ -1297,7 +1281,6 @@ poplevel (keep, reverse, functionbody)
   tree subblocks;
   tree block = NULL_TREE;
   tree decl;
-  int block_previously_created;
   int leaving_for_scope;
 
   if (cfun && !doing_semantic_analysis_p ())
@@ -1405,34 +1388,12 @@ poplevel (keep, reverse, functionbody)
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
   block = NULL_TREE;
-  block_previously_created = (current_binding_level->this_block != NULL_TREE);
-  if (block_previously_created)
-    block = current_binding_level->this_block;
-  else if (keep == 1 || functionbody)
+  if (keep == 1 || functionbody)
     block = make_node (BLOCK);
   if (block != NULL_TREE)
     {
-      if (block_previously_created)
-       {
-         if (decls || tags || subblocks)
-           {
-             if (BLOCK_VARS (block))
-               warning ("internal compiler error: debugging info corrupted");
-
-             BLOCK_VARS (block) = decls;
-
-             /* We can have previous subblocks and new subblocks when
-                doing fixup_gotos with complex cleanups.  We chain the new
-                subblocks onto the end of any pre-existing subblocks.  */
-             BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
-                                                subblocks);
-           }
-       }
-      else
-       {
-         BLOCK_VARS (block) = decls;
-         BLOCK_SUBBLOCKS (block) = subblocks;
-       }
+      BLOCK_VARS (block) = decls;
+      BLOCK_SUBBLOCKS (block) = subblocks;
     }
 
   /* In each subblock, record that this is its superior.  */
@@ -1583,11 +1544,9 @@ poplevel (keep, reverse, functionbody)
   if (functionbody)
     DECL_INITIAL (current_function_decl) = block;
   else if (block)
-    {
-      if (!block_previously_created)
-        current_binding_level->blocks
-          = chainon (current_binding_level->blocks, block);
-    }
+    current_binding_level->blocks
+      = chainon (current_binding_level->blocks, block);
+
   /* If we did not make a block for the level just exited,
      any blocks made for inner levels
      (since they cannot be recorded as subblocks in that level)
@@ -1664,9 +1623,11 @@ insert_block (block)
 
 void
 set_block (block)
-    register tree block;
+    tree block ATTRIBUTE_UNUSED;
 {
-  current_binding_level->this_block = block;
+  /* The RTL expansion machinery requires us to provide this callback,
+     but it is not applicable in function-at-a-time mode.  */
+  my_friendly_assert (cfun && !doing_semantic_analysis_p (), 20000911);
 }
 
 /* Do a pushlevel for class declarations.  */
@@ -2020,7 +1981,6 @@ mark_binding_level (arg)
       ggc_mark_tree (lvl->type_shadowed);
       ggc_mark_tree (lvl->shadowed_labels);
       ggc_mark_tree (lvl->blocks);
-      ggc_mark_tree (lvl->this_block);
       ggc_mark_tree (lvl->this_class);
       ggc_mark_tree (lvl->incomplete);
       ggc_mark_tree (lvl->dead_vars_from_for);
@@ -2449,16 +2409,6 @@ pop_nested_namespace (ns)
    scope isn't enough, because more binding levels may be pushed.  */
 struct saved_scope *scope_chain;
 
-/* Mark ST for GC.  */
-
-static void
-mark_stmt_tree (st)
-     stmt_tree st;
-{
-  ggc_mark_tree (st->x_last_stmt);
-  ggc_mark_tree (st->x_last_expr_type);
-}
-
 /* Mark ARG (which is really a struct saved_scope **) for GC.  */
 
 static void
@@ -2478,7 +2428,6 @@ mark_saved_scope (arg)
       if (t->lang_base)
        ggc_mark_tree_varray (t->lang_base);
       ggc_mark_tree (t->lang_name);
-      ggc_mark_tree (t->x_function_parms);
       ggc_mark_tree (t->template_parms);
       ggc_mark_tree (t->x_previous_class_type);
       ggc_mark_tree (t->x_previous_class_values);
@@ -5195,21 +5144,6 @@ struct cp_switch
    
 static struct cp_switch *switch_stack;
 
-static int
-case_compare (k1, k2)
-     splay_tree_key k1;
-     splay_tree_key k2;
-{
-  /* Consider a NULL key (such as arises with a `default' label) to be
-     smaller than anything else.  */
-  if (!k1)
-    return k2 ? -1 : 0;
-  else if (!k2)
-    return k1 ? 1 : 0;
-
-  return tree_int_cst_compare ((tree) k1, (tree) k2);
-}
-
 /* Called right after a switch-statement condition is parsed.
    SWITCH_STMT is the switch statement being parsed.  */
 
@@ -5245,12 +5179,7 @@ finish_case_label (low_value, high_value)
      tree low_value;
      tree high_value;
 {
-  tree label;
-  tree cleanup;
-  tree type;
   tree cond;
-  tree case_label;
-  splay_tree_node node;
 
   if (! switch_stack)
     {
@@ -5264,12 +5193,13 @@ finish_case_label (low_value, high_value)
       return;
     }
 
-  label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
   if (processing_template_decl)
     {
+      tree label;
+
       /* For templates, just add the case label; we'll do semantic
         analysis at instantiation-time.  */
+      label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       add_stmt (build_case_label (low_value, high_value, label));
       return;
     }
@@ -5278,124 +5208,8 @@ finish_case_label (low_value, high_value)
   cond = SWITCH_COND (switch_stack->switch_stmt);
   if (cond && TREE_CODE (cond) == TREE_LIST)
     cond = TREE_VALUE (cond);
-  /* If there was an error processing the switch condition, bail now
-     before we get more confused.  */
-  if (!cond || cond == error_mark_node)
-    return;
-  type = TREE_TYPE (cond);
-
-  if ((low_value && TREE_TYPE (low_value) 
-       && POINTER_TYPE_P (TREE_TYPE (low_value))) 
-      || (high_value && TREE_TYPE (high_value)
-         && POINTER_TYPE_P (TREE_TYPE (high_value))))
-    error ("pointers are not permitted as case values");
-
-  /* Case ranges are a GNU extension.  */
-  if (high_value && pedantic)
-    pedwarn ("ISO C++ forbids range expressions in switch statement");
-
-  if (low_value)
-    {
-      low_value = check_case_value (low_value);
-      low_value = convert_and_check (type, low_value);
-    }
-  if (high_value)
-    {
-      high_value = check_case_value (high_value);
-      high_value = convert_and_check (type, high_value);
-    }
-
-  /* If an error has occurred, bail out now.  */
-  if (low_value == error_mark_node || high_value == error_mark_node)
-    return;
-
-  /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
-     really a case range, even though it was written that way.  Remove
-     the HIGH_VALUE to simplify later processing.  */
-  if (tree_int_cst_equal (low_value, high_value))
-    high_value = NULL_TREE;
-  if (low_value && high_value 
-      && !tree_int_cst_lt (low_value, high_value)) 
-    warning ("empty range specified");
-
-  /* Look up the LOW_VALUE in the table of case labels we already
-     have.  */
-  node = splay_tree_lookup (switch_stack->cases, (splay_tree_key) low_value);
-  /* If there was not an exact match, check for overlapping ranges.
-     There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
-     that's a `default' label and the only overlap is an exact match.  */
-  if (!node && (low_value || high_value))
-    {
-      splay_tree_node low_bound;
-      splay_tree_node high_bound;
-
-      /* Even though there wasn't an exact match, there might be an
-        overlap between this case range and another case range.
-        Since we've (inductively) not allowed any overlapping case
-        ranges, we simply need to find the greatest low case label
-        that is smaller that LOW_VALUE, and the smallest low case
-        label that is greater than LOW_VALUE.  If there is an overlap
-        it will occur in one of these two ranges.  */
-      low_bound = splay_tree_predecessor (switch_stack->cases,
-                                         (splay_tree_key) low_value);
-      high_bound = splay_tree_successor (switch_stack->cases,
-                                        (splay_tree_key) low_value);
-
-      /* Check to see if the LOW_BOUND overlaps.  It is smaller than
-        the LOW_VALUE, so there is no need to check unless the
-        LOW_BOUND is in fact itself a case range.  */
-      if (low_bound
-         && CASE_HIGH ((tree) low_bound->value)
-         && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
-                                   low_value) >= 0)
-       node = low_bound;
-      /* Check to see if the HIGH_BOUND overlaps.  The low end of that
-        range is bigger than the low end of the current range, so we
-        are only interested if the current range is a real range, and
-        not an ordinary case label.  */
-      else if (high_bound 
-              && high_value
-              && (tree_int_cst_compare ((tree) high_bound->key,
-                                        high_value)
-                  <= 0))
-       node = high_bound;
-    }
-  /* If there was an overlap, issue an error.  */
-  if (node)
-    {
-      tree duplicate = CASE_LABEL_DECL ((tree) node->value);
-
-      if (high_value)
-       {
-         error ("duplicate (or overlapping) case value");
-         cp_error_at ("this is the first entry overlapping that value",
-                      duplicate);
-       }
-      else if (low_value)
-       {
-         cp_error ("duplicate case value `%E'", low_value) ;
-         cp_error_at ("previously used here", duplicate);
-       }
-      else
-       {
-         error ("multiple default labels in one switch");
-         cp_error_at ("this is the first default label", duplicate);
-       }
-      return;
-    }
 
-  cleanup = last_cleanup_this_contour ();
-  if (cleanup)
-    {
-      static int explained = 0;
-      cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
-      warning ("where case label appears here");
-      if (!explained)
-       {
-         warning ("(enclose actions of previous case statements requiring destructors in their own scope.)");
-         explained = 1;
-       }
-    }
+  c_add_case_label (switch_stack->cases, cond, low_value, high_value);
 
   check_switch_goto (switch_stack->level);
 
@@ -5403,16 +5217,6 @@ finish_case_label (low_value, high_value)
      own new (temporary) binding contour.  */
   current_binding_level->more_cleanups_ok = 0;
   current_function_return_value = NULL_TREE;
-
-  /* Add a representation for the case label to the statement
-     tree.  */
-  case_label = build_case_label (low_value, high_value, label);
-  add_stmt (case_label);
-
-  /* Register this case label in the splay tree.  */
-  splay_tree_insert (switch_stack->cases, 
-                    (splay_tree_key) low_value,
-                    (splay_tree_value) case_label);
 }
 \f
 /* Return the list of declarations of the current level.
@@ -6500,11 +6304,11 @@ init_decl_processing ()
   /* Create all the identifiers we need.  */
   initialize_predefined_identifiers ();
 
-  /* Let the back-end now how to save and restore language-specific
-     per-function globals.  */
+  /* Fill in back-end hooks.  */
   init_lang_status = &push_cp_function_context;
   free_lang_status = &pop_cp_function_context;
   mark_lang_status = &mark_cp_function_context;
+  lang_safe_from_p = &c_safe_from_p;
 
   cp_parse_init ();
   init_decl2 ();
@@ -6877,7 +6681,6 @@ init_decl_processing ()
 
   ggc_add_tree_root (&last_function_parm_tags, 1);
   ggc_add_tree_root (&current_function_return_value, 1);
-  ggc_add_tree_root (&current_function_parms, 1);
   ggc_add_tree_root (&current_function_parm_tags, 1);
   ggc_add_tree_root (&last_function_parms, 1);
   ggc_add_tree_root (&error_mark_list, 1);
@@ -7693,12 +7496,9 @@ maybe_deduce_size_from_array_init (decl, init)
       && TYPE_DOMAIN (type) == NULL_TREE
       && TREE_CODE (decl) != TYPE_DECL)
     {
-      int do_default
-       = (TREE_STATIC (decl)
-          /* Even if pedantic, an external linkage array
-             may have incomplete type at first.  */
-          ? pedantic && ! DECL_EXTERNAL (decl)
-          : !DECL_EXTERNAL (decl));
+      /* do_default is really a C-ism to deal with tentative definitions.
+        But let's leave it here to ease the eventual merge.  */
+      int do_default = !DECL_EXTERNAL (decl);
       tree initializer = init ? init : DECL_INITIAL (decl);
       int failure = complete_array_type (type, initializer, do_default);
 
@@ -11420,12 +11220,23 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              cp_error ("`inline' specified for friend class declaration");
              inlinep = 0;
            }
-         if (!current_aggr && TREE_CODE (type) != TYPENAME_TYPE)
+
+         /* Until core issue 180 is resolved, allow 'friend typename A::B'.
+            But don't allow implicit typenames.  */
+         if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
+                               || IMPLICIT_TYPENAME_P (type)))
            {
              if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
-               cp_error ("template parameters cannot be friends");
+               cp_pedwarn ("template parameters cannot be friends");
+             else if (TREE_CODE (type) == TYPENAME_TYPE)
+               cp_pedwarn ("\
+friend declaration requires class-key, i.e. `friend class %T::%T'",
+                           constructor_name (current_class_type),
+                           TYPE_IDENTIFIER (type));
              else
-               cp_error ("friend declaration requires `%#T'", type);
+               cp_pedwarn ("\
+friend declaration requires class-key, i.e. `friend %#T'",
+                           type);
            }
 
          /* Only try to do this stuff if we didn't already give up.  */
@@ -12935,6 +12746,22 @@ xref_tag (code_type_node, name, globalize)
   else
     t = IDENTIFIER_TYPE_VALUE (name);
 
+  /* Warn about 'friend struct Inherited;' doing the wrong thing.  */
+  if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
+    {
+      static int explained;
+
+      cp_warning ("`%s %T' declares a new type at namespace scope;\n\
+to refer to the inherited type, say `%s %T::%T'%s",
+                 tag_name (tag_code), name, tag_name (tag_code),
+                 constructor_name (current_class_type), TYPE_IDENTIFIER (t),
+                 (!explained ? "\n\
+(names from dependent base classes are not visible to unqualified name lookup)"
+                  : ""));
+
+      explained = 1;
+    }
+
   if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
       && TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
     t = NULL_TREE;
@@ -13572,7 +13399,7 @@ build_enumerator (name, value, enumtype)
 
   if (context && context == current_class_type)
     /* This enum declaration is local to the class.  We need the full
-      lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
+       lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
     decl = build_lang_decl (CONST_DECL, name, type);
   else
     /* It's a global enum, or it's local to a function.  (Note local to
@@ -13602,8 +13429,9 @@ build_enumerator (name, value, enumtype)
 /* We're defining DECL.  Make sure that it's type is OK.  */
 
 static void
-check_function_type (decl)
+check_function_type (decl, current_function_parms)
      tree decl;
+     tree current_function_parms;
 {
   tree fntype = TREE_TYPE (decl);
   tree return_type = complete_type (TREE_TYPE (fntype));
@@ -13645,9 +13473,7 @@ check_function_type (decl)
    FLAGS is a bitwise or of SF_PRE_PARSED (indicating that the
    DECLARATOR is really the DECL for the function we are about to
    process and that DECLSPECS should be ignored), SF_INCLASS_INLINE
-   indicating that the function is an inline defined in-class, and
-   SF_EXPAND indicating that we should generate RTL for this
-   function.
+   indicating that the function is an inline defined in-class.
 
    This function creates a binding context for the function body
    as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -13674,6 +13500,7 @@ start_function (declspecs, declarator, attrs, flags)
   extern int used_extern_spec;
   int doing_friend = 0;
   struct binding_level *bl;
+  tree current_function_parms;
 
   /* Sanity check.  */
   my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
@@ -13821,7 +13648,7 @@ start_function (declspecs, declarator, attrs, flags)
      you declare a function, these types can be incomplete, but they
      must be complete when you define the function.  */
   if (! processing_template_decl)
-    check_function_type (decl1);
+    check_function_type (decl1, current_function_parms);
 
   /* Build the return declaration for the function.  */
   restype = TREE_TYPE (fntype);
@@ -13846,7 +13673,6 @@ start_function (declspecs, declarator, attrs, flags)
   bl = current_binding_level;
   init_function_start (decl1, input_filename, lineno);
   current_binding_level = bl;
-  expanding_p = (flags & SF_EXPAND) != 0;
 
   /* 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.
@@ -13855,9 +13681,8 @@ start_function (declspecs, declarator, attrs, flags)
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
 
-  /* If we're building a statement-tree, start the tree now.  */
-  if (processing_template_decl || !expanding_p)
-    begin_stmt_tree (&DECL_SAVED_TREE (decl1));
+  /* Start the statement-tree, start the tree now.  */
+  begin_stmt_tree (&DECL_SAVED_TREE (decl1));
 
   /* Let the user know we're compiling this function.  */
   announce_function (decl1);
@@ -13886,29 +13711,16 @@ start_function (declspecs, declarator, attrs, flags)
   current_function_decl = decl1;
   cfun->decl = decl1;
 
-  /* Initialize the per-function data.  */
-  if (!DECL_PENDING_INLINE_P (decl1) && DECL_SAVED_FUNCTION_DATA (decl1))
+  /* If we are (erroneously) defining a function that we have already
+     defined before, wipe out what we knew before.  */
+  if (!DECL_PENDING_INLINE_P (decl1) 
+      && DECL_SAVED_FUNCTION_DATA (decl1))
     {
-      /* If we already parsed this function, and we're just expanding it
-        now, restore saved state.  */
-      struct binding_level *bl = current_binding_level;
-      *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (decl1);
-      current_binding_level = bl;
-
-      /* 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 (decl1));
       DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
     }
-  else if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
+
+  if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
     {
       /* We know that this was set up by `grokclassfn'.  We do not
         wait until `store_parm_decls', since evil parse errors may
@@ -13996,18 +13808,12 @@ start_function (declspecs, declarator, attrs, flags)
        DECL_INTERFACE_KNOWN (decl1) = 1;
     }
 
-  if (doing_semantic_analysis_p ())
-    {
-      pushlevel (0);
-      current_binding_level->parm_flag = 1;
-    }
+  pushlevel (0);
+  current_binding_level->parm_flag = 1;
 
   if (attrs)
     cplus_decl_attributes (decl1, NULL_TREE, attrs);
 
-  if (!building_stmt_tree ())
-    GNU_xref_function (decl1, current_function_parms);
-
   /* We need to do this even if we aren't expanding yet so that
      assemble_external works.  */
   make_function_rtl (decl1);
@@ -14047,25 +13853,20 @@ start_function (declspecs, declarator, attrs, flags)
       DECL_CONTEXT (ctor_label) = current_function_decl;
     }
 
+  store_parm_decls (current_function_parms);
+
   return 1;
 }
 \f
-/* Called after store_parm_decls for a function-try-block.  */
-
-void
-expand_start_early_try_stmts ()
-{
-  expand_start_try_stmts ();
-}
-
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
    digesting the body of the function.
 
    Also install to binding contour return value identifier, if any.  */
 
-void
-store_parm_decls ()
+static void
+store_parm_decls (current_function_parms)
+     tree current_function_parms;
 {
   register tree fndecl = current_function_decl;
   register tree parm;
@@ -14080,10 +13881,6 @@ store_parm_decls ()
      then CONST_DECLs for foo and bar are put here.  */
   tree nonparms = NULL_TREE;
 
-  /* Create a binding level for the parms.  */
-  if (!building_stmt_tree ())
-    expand_start_bindings (2);
-
   if (current_function_parms)
     {
       /* This case is when the function was defined with an ANSI prototype.
@@ -14094,45 +13891,34 @@ store_parm_decls ()
       tree specparms = current_function_parms;
       tree next;
 
-      if (doing_semantic_analysis_p ())
-       {
-         /* Must clear this because it might contain TYPE_DECLs declared
+      /* Must clear this because it might contain TYPE_DECLs declared
             at class level.  */
-         storedecls (NULL_TREE);
+      storedecls (NULL_TREE);
 
-         /* If we're doing semantic analysis, then we'll call pushdecl
+      /* If we're doing semantic analysis, then we'll call pushdecl
             for each of these.  We must do them in reverse order so that
             they end in the correct forward order.  */
-         specparms = nreverse (specparms);
-       }
+      specparms = nreverse (specparms);
 
       for (parm = specparms; parm; parm = next)
        {
          next = TREE_CHAIN (parm);
          if (TREE_CODE (parm) == PARM_DECL)
            {
-             tree type = TREE_TYPE (parm);
+             tree cleanup;
 
-             if (doing_semantic_analysis_p ())
-               {
-                 tree cleanup;
-
-                 if (DECL_NAME (parm) == NULL_TREE
-                     || TREE_CODE (parm) != VOID_TYPE)
-                   pushdecl (parm);
-                 else
-                   cp_error ("parameter `%D' declared void", parm);
+             if (DECL_NAME (parm) == NULL_TREE
+                 || TREE_CODE (parm) != VOID_TYPE)
+               pushdecl (parm);
+             else
+               cp_error ("parameter `%D' declared void", parm);
 
-                 cleanup = (processing_template_decl 
-                            ? NULL_TREE
-                            : maybe_build_cleanup (parm));
+             cleanup = (processing_template_decl 
+                        ? NULL_TREE
+                        : maybe_build_cleanup (parm));
 
-                 if (cleanup)
-                   cleanups = tree_cons (parm, cleanup, cleanups);
-               }
-             else if (type != error_mark_node
-                      && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
-               parms_have_cleanups = 1;
+             if (cleanup)
+               cleanups = tree_cons (parm, cleanup, cleanups);
            }
          else
            {
@@ -14143,14 +13929,11 @@ store_parm_decls ()
            }
        }
 
-      if (doing_semantic_analysis_p ())
-       {
-         /* Get the decls in their original chain order
-            and record in the function.  This is all and only the
-            PARM_DECLs that were pushed into scope by the loop above.  */
-         DECL_ARGUMENTS (fndecl) = getdecls ();
-         storetags (chainon (parmtags, gettags ()));
-       }
+      /* Get the decls in their original chain order and record in the
+        function.  This is all and only the PARM_DECLs that were
+        pushed into scope by the loop above.  */
+      DECL_ARGUMENTS (fndecl) = getdecls ();
+      storetags (chainon (parmtags, gettags ()));
     }
   else
     DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -14159,20 +13942,7 @@ store_parm_decls ()
      as the decl-chain of the current lexical scope.
      Put the enumerators in as well, at the front so that
      DECL_ARGUMENTS is not modified.  */
-  if (doing_semantic_analysis_p ())
-    storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
-
-  /* Initialize the RTL code for the function.  */
-  DECL_SAVED_INSNS (fndecl) = 0;
-  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) && !building_stmt_tree ())
-    expand_main_function ();
+  storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
 
   /* Now that we have initialized the parms, we can start their
      cleanups.  We cannot do this before, since expand_decl_cleanup
@@ -14185,19 +13955,13 @@ store_parm_decls ()
     }
 
   /* Create a binding contour which can be used to catch
-     cleanup-generated temporaries.  Also, if the return value needs or
-     has initialization, deal with that now.  */
+     cleanup-generated temporaries.  */
   if (parms_have_cleanups)
-    {
-      pushlevel (0);
-      if (!building_stmt_tree ())
-       expand_start_bindings (2);
-    }
+    pushlevel (0);
 
   /* Do the starting of the exception specifications, if we have any.  */
   if (flag_exceptions && !processing_template_decl
       && flag_enforce_eh_specs
-      && building_stmt_tree ()
       && TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
     current_eh_spec_try_block = expand_start_eh_spec ();
 }
@@ -14228,7 +13992,6 @@ save_function_data (decl)
   /* Clear out the bits we don't need.  */
   f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
   f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
-  f->x_result_rtx = NULL_RTX;
   f->x_named_label_uses = NULL;
   f->bindings = NULL;
 
@@ -14393,13 +14156,9 @@ finish_function (flags)
 {
   register tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
-  /* Label to use if this function is supposed to return a value.  */
-  tree no_return_label = NULL_TREE;
   int call_poplevel = (flags & 1) != 0;
   int inclass_inline = (flags & 2) != 0;
-  int expand_p;
   int nested;
-  int current_line = lineno;
 
   /* When we get some parse errors, we can end up without a
      current_function_decl, so cope.  */
@@ -14413,18 +14172,11 @@ finish_function (flags)
       This caused &foo to be of type ptr-to-const-function
       which then got a warning when stored in a ptr-to-function variable.  */
 
-  /* This happens on strange parse errors.  */
-  if (! current_function_parms_stored)
-    {
-      call_poplevel = 0;
-      store_parm_decls ();
-    }
+  my_friendly_assert (building_stmt_tree (), 20000911);
 
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
-  if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
-    ;
-  else if (building_stmt_tree ())
+  if (!DECL_CLONED_FUNCTION_P (fndecl))
     {
       if (DECL_CONSTRUCTOR_P (fndecl))
        {
@@ -14452,132 +14204,16 @@ finish_function (flags)
                            (TREE_TYPE (current_function_decl)),
                            current_eh_spec_try_block);
     }
-  else
-    {
-#if 0
-      if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
-       {
-         /* 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)
-       ;
-      else if (DECL_CONSTRUCTOR_P (fndecl))
-       {
-         if (call_poplevel)
-           do_poplevel ();
-       }
-      else if (return_label != NULL_RTX
-              && flag_this_is_variable <= 0
-              && 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) = fndecl;
-         DECL_INITIAL (no_return_label) = error_mark_node;
-         DECL_SOURCE_FILE (no_return_label) = input_filename;
-         DECL_SOURCE_LINE (no_return_label) = current_line;
-         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);
-       }
-
-      /* Get return value into register if that's where it's supposed
-        to be.  */
-      if (original_result_rtx)
-       fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
-
-      /* Finish building code that will trigger warnings if users forget
-        to make their functions return values.  */
-      if (no_return_label || cleanup_label)
-       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, current_line, 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 saving up tree structure, tie off the function now.  */
-  if (!expand_p)
-    finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
      this function's blocks.  */
-  if (doing_semantic_analysis_p ())
-    {
-      if (current_binding_level->parm_flag != 1)
-       my_friendly_abort (122);
-      poplevel (1, 0, 1);
-    }
+  if (current_binding_level->parm_flag != 1)
+    my_friendly_abort (122);
+  poplevel (1, 0, 1);
 
   /* Remember that we were in class scope.  */
   if (current_class_name)
@@ -14591,7 +14227,7 @@ finish_function (flags)
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
   /* Save away current state, if appropriate.  */
-  if (!expanding_p && !processing_template_decl)
+  if (!processing_template_decl)
     save_function_data (fndecl);
 
   /* If this function calls `setjmp' it cannot be inlined.  When
@@ -14603,96 +14239,15 @@ finish_function (flags)
      this function to modify local variables in `c', but their
      addresses may have been stored somewhere accessible to this
      function.)  */
-  if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl))
+  if (!processing_template_decl && calls_setjmp_p (fndecl))
     DECL_UNINLINABLE (fndecl) = 1;
 
-  if (expand_p)
-    {
-      int returns_null;
-      int returns_value;
-
-      /* So we can tell if jump_optimize sets it to 1.  */
-      can_reach_end = 0;
-
-      /* Before we call rest_of_compilation (which will pop the
-        CURRENT_FUNCTION), we must save these values.  */
-      returns_null = current_function_returns_null;
-      returns_value = current_function_returns_value;
-
-      /* 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 (fndecl);
-
-      /* Undo the call to ggc_push_context above.  */
-      if (function_depth > 1)
-       ggc_pop_context ();
-
-      if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
-       {
-         /* Set DECL_EXTERNAL so that assemble_external will be called as
-            necessary.  We'll clear it again in finish_file.  */
-         if (! DECL_EXTERNAL (fndecl))
-           DECL_NOT_REALLY_EXTERN (fndecl) = 1;
-         DECL_EXTERNAL (fndecl) = 1;
-         defer_fn (fndecl);
-       }
-
-#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 (fndecl))
-       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 (fndecl))
-       static_ctors = tree_cons (NULL_TREE, fndecl, 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 (fndecl))
-       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-
-      if (DECL_NAME (DECL_RESULT (fndecl)))
-       returns_value |= can_reach_end;
-      else
-       returns_null |= can_reach_end;
-
-      if (TREE_THIS_VOLATILE (fndecl) && returns_null)
-       warning ("`noreturn' function does return");
-      else if (returns_null
-              && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
-       {
-         /* Always complain if there's just no return statement.  */
-         if (!returns_value)
-           warning ("no return statement in function returning non-void");
-         else if (warn_return_type || pedantic)
-           /* If this function returns non-void and control can drop through,
-              complain.  */
-           warning ("control reaches end of non-void function");
-       }
-    }
-  else
-    {
-      /* Clear out memory we no longer need.  */
-      free_after_parsing (cfun);
-      /* Since we never call rest_of_compilation, we never clear
-        CFUN.  Do so explicitly.  */
-      free_after_compilation (cfun);
-      cfun = NULL;
-    }
+  /* Clear out memory we no longer need.  */
+  free_after_parsing (cfun);
+  /* Since we never call rest_of_compilation, we never clear
+     CFUN.  Do so explicitly.  */
+  free_after_compilation (cfun);
+  cfun = NULL;
 
   /* If this is a in-class inline definition, we may have to pop the
      bindings for the template parameters that we added in
@@ -14707,19 +14262,6 @@ finish_function (flags)
 
   --function_depth;
 
-  if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl)
-      && !(flag_inline_trees && DECL_INLINE (fndecl)))
-    {
-      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 (fndecl) = error_mark_node;
-      for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
-       DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
-    }
-
   /* Clean up.  */
   if (! nested)
     {
@@ -15000,31 +14542,6 @@ maybe_build_cleanup (decl)
   return 0;
 }
 \f
-/* Expand a C++ expression at the statement level.
-   This is needed to ferret out nodes which have UNKNOWN_TYPE.
-   The C++ type checker should get all of these out when
-   expressions are combined with other, type-providing, expressions,
-   leaving only orphan expressions, such as:
-
-   &class::bar;                / / takes its address, but does nothing with it.  */
-
-void
-cplus_expand_expr_stmt (exp)
-     tree exp;
-{
-#if 0
-  /* We should do this eventually, but right now this causes regex.o from
-     libg++ to miscompile, and tString to core dump.  */
-  exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
-#endif
-
-  /* If we don't do this, we end up down inside expand_expr
-     trying to do TYPE_MODE on the ERROR_MARK, and really
-     go outside the bounds of the type.  */
-  if (exp != error_mark_node)
-    expand_expr_stmt (exp);
-}
-
 /* When a stmt has been parsed, this function is called.  */
 
 void
@@ -15105,17 +14622,15 @@ mark_lang_function (p)
   if (!p)
     return;
 
+  mark_c_language_function (&p->base);
+
   ggc_mark_tree (p->x_ctor_label);
   ggc_mark_tree (p->x_dtor_label);
   ggc_mark_tree (p->x_current_class_ptr);
   ggc_mark_tree (p->x_current_class_ref);
   ggc_mark_tree (p->x_eh_spec_try_block);
-  ggc_mark_tree (p->x_scope_stmt_stack);
-
-  ggc_mark_rtx (p->x_result_rtx);
 
   mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
-  mark_stmt_tree (&p->base.x_stmt_tree);
   mark_binding_level (&p->bindings);
 }
 
@@ -15129,14 +14644,6 @@ mark_cp_function_context (f)
 }
 
 void
-lang_mark_false_label_stack (l)
-     struct label_node *l;
-{
-  /* C++ doesn't use false_label_stack.  It better be NULL.  */
-  my_friendly_assert (l == NULL, 19990904);
-}
-
-void
 lang_mark_tree (t)
      tree t;
 {
@@ -15176,13 +14683,13 @@ lang_mark_tree (t)
       if (ld)
        {
          ggc_mark (ld);
+         c_mark_lang_decl (&ld->decl_flags.base);
          if (!DECL_GLOBAL_CTOR_P (t) 
              && !DECL_GLOBAL_DTOR_P (t)
              && !DECL_THUNK_P (t))
            ggc_mark_tree (ld->decl_flags.u2.access);
          else if (DECL_THUNK_P (t))
            ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
-         ggc_mark_tree (ld->decl_flags.context);
          if (TREE_CODE (t) != NAMESPACE_DECL)
            ggc_mark_tree (ld->decl_flags.u.template_info);
          else
@@ -15190,7 +14697,7 @@ lang_mark_tree (t)
          if (CAN_HAVE_FULL_LANG_DECL_P (t))
            {
              ggc_mark_tree (ld->befriending_classes);
-             ggc_mark_tree (ld->saved_tree);
+             ggc_mark_tree (ld->context);
              ggc_mark_tree (ld->cloned_function);
              if (!DECL_OVERLOADED_OPERATOR_P (t))
                ggc_mark_tree (ld->u2.vtt_parm);