cp-tree.h (struct lang_decl_inlined_fns): New.
[gcc.git] / gcc / cp / decl.c
index e41562809b5327580a9d4536f2480ac381a5ad92..39008956f4af09d8b6d3e3db84b0511c97430be6 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C compiler.
-   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000
-   Free Software Foundation, Inc.
+   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001  Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GNU CC.
@@ -37,64 +37,26 @@ Boston, MA 02111-1307, USA.  */
 #include "cp-tree.h"
 #include "decl.h"
 #include "lex.h"
-#include "defaults.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
 #include "../hash.h"
-#include "defaults.h"
 #include "ggc.h"
+#include "tm_p.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));
 
-/* Use garbage collection.  */
-
-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
    platforms.  */
-#define BOOL_TYPE_SIZE \
-  ((SLOW_BYTE_ACCESS && !flag_new_abi) ? (POINTER_SIZE) : (CHAR_TYPE_SIZE))
-#else
 #define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
 #endif
-#endif
-
-/* We let tm.h override the types used here, to handle trivial differences
-   such as the choice of unsigned int or long unsigned int for size_t.
-   When machines start needing nontrivial differences in the size type,
-   it would be best to do something here to figure out automatically
-   from other information what type to use.  */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
 
-static tree grokparms                          PARAMS ((tree, int));
+static tree grokparms                          PARAMS ((tree));
 static const char *redeclaration_error_message PARAMS ((tree, tree));
 
 static void push_binding_level PARAMS ((struct binding_level *, int,
@@ -123,13 +85,11 @@ static tree lookup_tag PARAMS ((enum tree_code, tree,
                              struct binding_level *, int));
 static void set_identifier_type_value_with_scope
        PARAMS ((tree, tree, struct binding_level *));
-static void record_builtin_type PARAMS ((enum rid, const char *, tree));
 static void record_unknown_type PARAMS ((tree, const char *));
 static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
 static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
 static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
                                  int));
-static void lang_print_error_function PARAMS ((const char *));
 static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct binding_level*));
 static void check_for_uninitialized_const_var PARAMS ((tree));
 static unsigned long typename_hash PARAMS ((hash_table_key));
@@ -170,10 +130,9 @@ static void mark_binding_level PARAMS ((void *));
 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 language_function *));
-static void mark_stmt_tree PARAMS ((struct stmt_tree *));
+static void mark_lang_function PARAMS ((struct cp_language_function *));
 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));
@@ -184,10 +143,12 @@ static tree start_cleanup_fn PARAMS ((void));
 static void end_cleanup_fn PARAMS ((void));
 static tree cp_make_fname_decl PARAMS ((tree, const char *, int));
 static void initialize_predefined_identifiers PARAMS ((void));
-static tree check_special_function_return_type 
-  PARAMS ((special_function_kind, tree, tree, tree));
+static tree check_special_function_return_type
+  PARAMS ((special_function_kind, 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 void store_parm_decls PARAMS ((tree));
+static int cp_missing_noreturn_ok_p PARAMS ((tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -201,7 +162,6 @@ tree error_mark_list;
 
    C++ extensions
        tree wchar_decl_node;
-       tree void_zero_node;
 
        tree vtable_entry_type;
        tree delta_type_node;
@@ -264,19 +224,14 @@ tree cp_global_trees[CPTI_MAX];
 
 static tree global_type_node;
 
-/* Namespace std.  */
-int in_std;
+/* If non-zero, this is the number of times we have entered the `std'
+   namespace when we are treating that namespace as an alias for the
+   global namespace.  */
+static int in_fake_std;
 
 /* Expect only namespace names now. */
 static int only_namespace_names;
 
-/* If original DECL_RESULT of current function was a register,
-   but due to being an addressable named return value, would up
-   on the stack, this variable holds the named return value's
-   original location.  */
-
-#define original_result_rtx cp_function_chain->x_result_rtx
-
 /* Used only for jumps to as-yet undefined labels, since jumps to
    defined labels can have their validity checked immediately.  */
 
@@ -345,18 +300,14 @@ int flag_isoc94;
 
 int flag_isoc99;
 
-/* Nonzero means give `double' the same size as `float'.  */
-
-extern int flag_short_double;
+/* Nonzero means we are a hosted implementation for code shared with C.  */
 
-/* Nonzero means don't recognize any builtin functions.  */
+int flag_hosted = 1;
 
-extern int flag_no_builtin;
+/* Nonzero means add default format_arg attributes for functions not
+   in ISO C.  */
 
-/* Nonzero means don't recognize the non-ANSI builtin functions.
-   -ansi sets this.  */
-
-extern int flag_no_nonansi_builtin;
+int flag_noniso_default_format_attributes = 1;
 
 /* Nonzero if we want to conserve space in the .o files.  We do this
    by putting uninitialized data and runtime initialized data into
@@ -434,15 +385,13 @@ struct binding_level
 
     /* If this binding level is the binding level for a class, then
        class_shadowed is a TREE_LIST.  The TREE_PURPOSE of each node
-       is the name of an entity bound in the class; the TREE_VALUE is
-       the IDENTIFIER_CLASS_VALUE before we entered the class.  Thus,
-       when leaving class scope, we can restore the
-       IDENTIFIER_CLASS_VALUE by walking this list.  The TREE_TYPE is
+       is the name of an entity bound in the class.  The TREE_TYPE is
        the DECL bound by this name in the class.  */
     tree class_shadowed;
 
     /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
-       is used for all binding levels.  */
+       is used for all binding levels. In addition the TREE_VALUE is the
+       IDENTIFIER_TYPE_VALUE before we entered the class.  */
     tree type_shadowed;
 
     /* A TREE_LIST.  Each TREE_VALUE is the LABEL_DECL for a local
@@ -455,10 +404,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;
 
@@ -496,7 +441,7 @@ struct binding_level
        replaced with a TEMPLATE_DECL.  */
     unsigned template_parms_p : 1;
 
-    /* Nonzero if this scope corresponds to the `<>' in a 
+    /* Nonzero if this scope corresponds to the `<>' in a
        `template <>' clause.  Whenever this flag is set,
        TEMPLATE_PARMS_P will be set as well.  */
     unsigned template_spec_p : 1;
@@ -527,7 +472,7 @@ struct binding_level
 
 #define current_binding_level                  \
   (cfun                                                \
-   ? cp_function_chain->bindings               \
+   ? cp_function_chain->bindings               \
    : scope_chain->bindings)
 
 /* The binding level of the current class, if any.  */
@@ -571,7 +516,7 @@ push_binding_level (newlevel, tag_transparent, keep)
 {
   /* Add this level to the front of the chain (stack) of levels that
      are active.  */
-  bzero ((char*) newlevel, sizeof (struct binding_level));
+  memset ((char*) newlevel, 0, sizeof (struct binding_level));
   newlevel->level_chain = current_binding_level;
   current_binding_level = newlevel;
   newlevel->tag_transparent = tag_transparent;
@@ -913,6 +858,24 @@ pushlevel (tag_transparent)
   keep_next_level_flag = 0;
 }
 
+/* We're defining an object of type TYPE.  If it needs a cleanup, but
+   we're not allowed to add any more objects with cleanups to the current
+   scope, create a new binding level.  */
+
+void
+maybe_push_cleanup_level (type)
+     tree type;
+{
+  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+      && current_binding_level->more_cleanups_ok == 0)
+    {
+      keep_next_level (2);
+      pushlevel (1);
+      clear_last_expr ();
+      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
+    }
+}
+  
 /* Enter a new scope.  The KIND indicates what kind of scope is being
    created.  */
 
@@ -964,6 +927,11 @@ note_level_for_eh ()
 #define BINDING_LEVEL(NODE) \
    (((struct tree_binding*)NODE)->scope.level)
 
+/* A free list of CPLUS_BINDING nodes, connected by their
+   TREE_CHAINs.  */
+
+static tree free_bindings;
+
 /* Make DECL the innermost binding for ID.  The LEVEL is the binding
    level at which this declaration is being bound.  */
 
@@ -975,7 +943,13 @@ push_binding (id, decl, level)
 {
   tree binding;
 
-  binding = make_node (CPLUS_BINDING);
+  if (free_bindings)
+    {
+      binding = free_bindings;
+      free_bindings = TREE_CHAIN (binding);
+    }
+  else
+    binding = make_node (CPLUS_BINDING);
 
   /* Now, fill in the binding information.  */
   BINDING_VALUE (binding) = decl;
@@ -1163,7 +1137,7 @@ push_class_binding (id, decl)
          else
            {
              my_friendly_assert (DECL_P (decl), 0);
-             context = CP_DECL_CONTEXT (decl);
+             context = context_for_name_lookup (decl);
            }
 
          if (is_properly_derived_from (current_class_type, context))
@@ -1213,9 +1187,19 @@ pop_binding (id, decl)
     my_friendly_abort (0);
 
   if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
-    /* We're completely done with the innermost binding for this
-       identifier.  Unhook it from the list of bindings.  */
-    IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+    {
+      /* We're completely done with the innermost binding for this
+        identifier.  Unhook it from the list of bindings.  */
+      IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+      /* Add it to the free list.  */
+      TREE_CHAIN (binding) = free_bindings;
+      free_bindings = binding;
+
+      /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
+        it.  */
+      BINDING_LEVEL (binding) = NULL;
+    }
 }
 
 /* When a label goes out of scope, check to see if that label was used
@@ -1296,7 +1280,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 ())
@@ -1404,34 +1387,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.  */
@@ -1582,11 +1543,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)
@@ -1663,9 +1622,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.  */
@@ -1851,7 +1812,7 @@ walk_namespaces_r (namespace, f, data)
       if (!DECL_LANG_SPECIFIC (current))
        {
          /* Hmm. std. */
-         my_friendly_assert (current == std_node, 393);
+         my_friendly_assert (current == fake_std_node, 393);
          continue;
        }
 
@@ -1954,20 +1915,8 @@ wrapup_globals_for_namespace (namespace, data)
 
   /* Process the decls in reverse order--earliest first.
      Put them into VEC from back to front, then take out from front.  */
-
   for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
-    {
-      /* Pretend we've output an unused static variable.  This ensures
-         that the toplevel __FUNCTION__ etc won't be emitted, unless
-         needed. */
-      if (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)
-         && !TREE_PUBLIC (decl) && !TREE_USED (decl))
-       {
-         TREE_ASM_WRITTEN (decl) = 1;
-         DECL_IGNORED_P (decl) = 1;
-       }
-      vec[len - i - 1] = decl;
-    }
+    vec[len - i - 1] = decl;
 
   if (last_time)
     {
@@ -2019,7 +1968,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);
@@ -2347,9 +2295,10 @@ push_namespace (name)
       implicit_use = 1;
     }
   else if (current_namespace == global_namespace
-          && name == DECL_NAME (std_node))
+          && !flag_honor_std
+          && name == std_identifier)
     {
-      in_std++;
+      in_fake_std++;
       return;
     }
   else
@@ -2399,8 +2348,8 @@ pop_namespace ()
 {
   if (current_namespace == global_namespace)
     {
-      my_friendly_assert (in_std>0, 980421);
-      in_std--;
+      my_friendly_assert (in_fake_std > 0, 980421);
+      in_fake_std--;
       return;
     }
   current_namespace = CP_DECL_CONTEXT (current_namespace);
@@ -2448,16 +2397,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)
-     struct 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
@@ -2477,7 +2416,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);
@@ -2496,6 +2434,8 @@ store_bindings (names, old_bindings)
      tree names, old_bindings;
 {
   tree t;
+  tree search_bindings = old_bindings;
+
   for (t = names; t; t = TREE_CHAIN (t))
     {
       tree binding, t1, id;
@@ -2512,22 +2452,18 @@ store_bindings (names, old_bindings)
          || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
        continue;
 
-      for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
+      for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
        if (TREE_VEC_ELT (t1, 0) == id)
          goto skip_it;
 
+      my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
       binding = make_tree_vec (4);
-
-      if (id)
-       {
-         my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
-         TREE_VEC_ELT (binding, 0) = id;
-         TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
-         TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
-         TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
-         IDENTIFIER_BINDING (id) = NULL_TREE;
-         IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
-       }
+      TREE_VEC_ELT (binding, 0) = id;
+      TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
+      TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
+      TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
+      IDENTIFIER_BINDING (id) = NULL_TREE;
+      IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
       TREE_CHAIN (binding) = old_bindings;
       old_bindings = binding;
     skip_it:
@@ -2621,12 +2557,10 @@ pop_from_top_level ()
   for (t = s->old_bindings; t; t = TREE_CHAIN (t))
     {
       tree id = TREE_VEC_ELT (t, 0);
-      if (id)
-       {
-         SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
-         IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
-         IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
-       }
+
+      SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
+      IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
+      IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
     }
 
   /* If we were in the middle of compiling a function, restore our
@@ -2899,19 +2833,13 @@ pushtag (name, type, globalize)
             all function definitions in a translation unit in a convenient
             way.  (It's otherwise tricky to find a member function definition
             it's only pointed to from within a local class.)  */
-         if (TYPE_CONTEXT (type) 
+         if (TYPE_CONTEXT (type)
              && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL
              && !processing_template_decl)
            VARRAY_PUSH_TREE (local_classes, type);
 
-         if (!uses_template_parms (type)) 
-           {
-             if (flag_new_abi)
-               DECL_ASSEMBLER_NAME (d) = mangle_type (type);
-             else
-               DECL_ASSEMBLER_NAME (d)
-                 = get_identifier (build_overload_name (type, 1, 1));
-           }
+         if (!uses_template_parms (type))
+           DECL_ASSEMBLER_NAME (d) = mangle_type (type);
         }
       if (b->parm_flag == 2)
        {
@@ -3463,7 +3391,7 @@ duplicate_decls (newdecl, olddecl)
        DECL_VIRTUAL_CONTEXT (newdecl) = DECL_VIRTUAL_CONTEXT (olddecl);
       if (DECL_CONTEXT (olddecl))
        DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
-      if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
+      if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
        DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
       DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
       DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
@@ -3471,7 +3399,9 @@ duplicate_decls (newdecl, olddecl)
       DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
       DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
       DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
-      DECL_LANG_SPECIFIC (newdecl)->u2 = DECL_LANG_SPECIFIC (olddecl)->u2;
+      if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
+       SET_OVERLOADED_OPERATOR_CODE
+         (newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -3651,6 +3581,8 @@ duplicate_decls (newdecl, olddecl)
       DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+      DECL_INITIALIZED_IN_CLASS_P (newdecl)
+        |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
       olddecl_friend = DECL_FRIEND_P (olddecl);
 
       /* Only functions have DECL_BEFRIENDING_CLASSES.  */
@@ -3694,6 +3626,9 @@ duplicate_decls (newdecl, olddecl)
        DECL_INLINE (olddecl) = 1;
       DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
 
+      /* Preserve abstractness on cloned [cd]tors.  */
+      DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
+
       if (! types_match)
        {
          DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
@@ -3844,7 +3779,7 @@ pushdecl (x)
              nesting.  */
          && !(TREE_CODE (x) == FUNCTION_DECL && !DECL_INITIAL (x))
          /* A local declaration for an `extern' variable is in the
-            scoped of the current namespace, not the current
+            scope of the current namespace, not the current
             function.  */
          && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
          && !DECL_CONTEXT (x))
@@ -3863,20 +3798,41 @@ pushdecl (x)
   name = DECL_NAME (x);
   if (name)
     {
-#if 0
-      /* Not needed...see below.  */
-      char *file;
-      int line;
-#endif
+      int different_binding_level = 0;
+
       if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
        name = TREE_OPERAND (name, 0);
 
-      /* Namespace-scoped variables are not found in the current level. */
-      if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
+      /* In case this decl was explicitly namespace-qualified, look it
+        up in its namespace context.  */
+      if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)
+         && namespace_bindings_p ())
        t = namespace_binding (name, DECL_CONTEXT (x));
       else
        t = lookup_name_current_level (name);
 
+      /* [basic.link] If there is a visible declaration of an entity
+        with linkage having the same name and type, ignoring entities
+        declared outside the innermost enclosing namespace scope, the
+        block scope declaration declares that same entity and
+        receives the linkage of the previous declaration.  */
+      if (! t && current_function_decl && x != current_function_decl
+         && (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
+         && DECL_EXTERNAL (x))
+       {
+         /* Look in block scope.  */
+         t = IDENTIFIER_VALUE (name);
+         /* Or in the innermost namespace.  */
+         if (! t)
+           t = namespace_binding (name, DECL_CONTEXT (x));
+         /* Does it have linkage?  Note that if this isn't a DECL, it's an
+            OVERLOAD, which is OK.  */
+         if (t && DECL_P (t) && ! (TREE_STATIC (t) || DECL_EXTERNAL (t)))
+           t = NULL_TREE;
+         if (t)
+           different_binding_level = 1;
+       }
+
       /* If we are declaring a function, and the result of name-lookup
         was an OVERLOAD, look for an overloaded instance that is
         actually the same as the function we are declaring.  (If
@@ -3911,10 +3867,21 @@ pushdecl (x)
        }
       else if (t != NULL_TREE)
        {
-         if (TREE_CODE (t) == PARM_DECL)
+         if (different_binding_level)
+           {
+             if (decls_match (x, t))
+               /* The standard only says that the local extern
+                  inherits linkage from the previous decl; in
+                  particular, default args are not shared.  It would
+                  be nice to propagate inlining info, though.  FIXME.  */
+               TREE_PUBLIC (x) = TREE_PUBLIC (t);
+           }
+         else if (TREE_CODE (t) == PARM_DECL)
            {
              if (DECL_CONTEXT (t) == NULL_TREE)
-               fatal ("parse errors have confused me too much");
+               /* This is probaby caused by too many errors, but calling
+                  abort will say that if errors have occurred.  */
+               abort ();
 
              /* Check for duplicate params.  */
              if (duplicate_decls (x, t))
@@ -4059,7 +4026,7 @@ pushdecl (x)
             warn if we later see static one.  */
          if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
            TREE_PUBLIC (name) = 1;
-         
+
          /* Bind the mangled name for the entity.  In the future, we
             should not need to do this; mangled names are an
             implementation detail of which the front-end should not
@@ -4454,9 +4421,8 @@ push_class_level_binding (name, x)
       else
        old_decl = BINDING_VALUE (binding);
 
-      /* There was already a binding for X containing fewer
-        functions than are named in X.  Find the previous
-        declaration of X on the class-shadowed list, and update it.  */
+      /* Find the previous binding of name on the class-shadowed
+         list, and update it.  */
       for (shadow = class_binding_level->class_shadowed;
           shadow;
           shadow = TREE_CHAIN (shadow))
@@ -4466,17 +4432,17 @@ push_class_level_binding (name, x)
            BINDING_VALUE (binding) = x;
            INHERITED_VALUE_BINDING_P (binding) = 0;
            TREE_TYPE (shadow) = x;
+           IDENTIFIER_CLASS_VALUE (name) = x;
            return;
          }
     }
 
   /* If we didn't replace an existing binding, put the binding on the
-     stack of bindings for the identifier, and update
-     IDENTIFIER_CLASS_VALUE.  */
+     stack of bindings for the identifier, and update the shadowed list.  */
   if (push_class_binding (name, x))
     {
       class_binding_level->class_shadowed
-       = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+       = tree_cons (name, NULL,
                     class_binding_level->class_shadowed);
       /* Record the value we are binding NAME to so that we can know
         what to pop later.  */
@@ -4755,7 +4721,7 @@ redeclaration_error_message (newdecl, olddecl)
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
       if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
-          && (DECL_TEMPLATE_RESULT (newdecl) 
+          && (DECL_TEMPLATE_RESULT (newdecl)
               != DECL_TEMPLATE_RESULT (olddecl))
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
@@ -5108,14 +5074,16 @@ define_label (filename, line, name)
 {
   tree decl = lookup_label (name);
   struct named_label_list *ent;
+  register struct binding_level *p;
 
   for (ent = named_labels; ent; ent = ent->next)
     if (ent->label_decl == decl)
       break;
 
-  /* After labels, make any new cleanups go into their
+  /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-  current_binding_level->more_cleanups_ok = 0;
+  for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
+    p->more_cleanups_ok = 0;
 
   if (name == get_identifier ("wchar_t"))
     cp_pedwarn ("label named wchar_t");
@@ -5147,17 +5115,37 @@ struct cp_switch
 {
   struct binding_level *level;
   struct cp_switch *next;
+  /* The SWITCH_STMT being built.  */
+  tree switch_stmt;
+  /* A splay-tree mapping the low element of a case range to the high
+     element, or NULL_TREE if there is no high element.  Used to
+     determine whether or not a new case label duplicates an old case
+     label.  We need a tree, rather than simply a hash table, because
+     of the GNU case range extension.  */
+  splay_tree cases;
 };
 
+/* A stack of the currently active switch statements.  The innermost
+   switch statement is on the top of the stack.  There is no need to
+   mark the stack for garbage collection because it is only active
+   during the processing of the body of a function, and we never
+   collect at that point.  */
+
 static struct cp_switch *switch_stack;
 
+/* Called right after a switch-statement condition is parsed.
+   SWITCH_STMT is the switch statement being parsed.  */
+
 void
-push_switch ()
+push_switch (switch_stmt)
+     tree switch_stmt;
 {
   struct cp_switch *p
     = (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
   p->level = current_binding_level;
   p->next = switch_stack;
+  p->switch_stmt = switch_stmt;
+  p->cases = splay_tree_new (case_compare, NULL, NULL);
   switch_stack = p;
 }
 
@@ -5165,8 +5153,9 @@ void
 pop_switch ()
 {
   struct cp_switch *cs;
-  
+
   cs = switch_stack;
+  splay_tree_delete (cs->cases);
   switch_stack = switch_stack->next;
   free (cs);
 }
@@ -5174,35 +5163,54 @@ pop_switch ()
 /* Note that we've seen a definition of a case label, and complain if this
    is a bad place for one.  */
 
-void
-define_case_label ()
+tree
+finish_case_label (low_value, high_value)
+     tree low_value;
+     tree high_value;
 {
-  tree cleanup = last_cleanup_this_contour ();
+  tree cond, r;
+  register struct binding_level *p;
 
   if (! switch_stack)
-    /* Don't crash; we'll complain in do_case.  */
-    return;
+    {
+      if (high_value)
+       error ("case label not within a switch statement");
+      else if (low_value)
+       cp_error ("case label `%E' not within a switch statement",
+                 low_value);
+      else
+       error ("`default' label not within a switch statement");
+      return NULL_TREE;
+    }
 
-  if (cleanup)
+  if (processing_template_decl)
     {
-      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");
-         warning ("destructors in their own binding contours.)");
-         explained = 1;
-       }
+      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);
+      return add_stmt (build_case_label (low_value, high_value, label));
     }
 
+  /* Find the condition on which this switch statement depends.  */
+  cond = SWITCH_COND (switch_stack->switch_stmt);
+  if (cond && TREE_CODE (cond) == TREE_LIST)
+    cond = TREE_VALUE (cond);
+
+  r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
+  if (r == error_mark_node)
+    r = NULL_TREE;
+
   check_switch_goto (switch_stack->level);
 
-  /* After labels, make any new cleanups go into their
+  /* After labels, make any new cleanups in the function go into their
      own new (temporary) binding contour.  */
-
-  current_binding_level->more_cleanups_ok = 0;
+  for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
+    p->more_cleanups_ok = 0;
   current_function_return_value = NULL_TREE;
+
+  return r;
 }
 \f
 /* Return the list of declarations of the current level.
@@ -5444,7 +5452,8 @@ lookup_namespace_name (namespace, name)
                                         TREE_OPERAND (template_id, 1),
                                         /*in_decl=*/NULL_TREE,
                                         /*context=*/NULL_TREE,
-                                        /*entering_scope=*/0);
+                                        /*entering_scope=*/0,
+                                        /*complain=*/1);
          else if (DECL_FUNCTION_TEMPLATE_P (val)
                   || TREE_CODE (val) == OVERLOAD)
            val = lookup_template_function (val,
@@ -5525,16 +5534,15 @@ build_typename_type (context, name, fullname, base_type)
 {
   tree t;
   tree d;
-  struct hash_entrye;
+  struct hash_entry *e;
 
   static struct hash_table ht;
 
   if (!ht.table)
     {
       static struct hash_table *h = &ht;
-      if (!hash_table_init (&ht, &hash_newfunc, &typename_hash,
-                           &typename_compare))
-       fatal ("virtual memory exhausted");
+
+      hash_table_init (&ht, &hash_newfunc, &typename_hash, &typename_compare);
       ggc_add_tree_hash_table_root (&h, 1);
     }
 
@@ -5628,7 +5636,8 @@ make_typename_type (context, name, complain)
          return lookup_template_class (tmpl,
                                        TREE_OPERAND (fullname, 1),
                                        NULL_TREE, context,
-                                       /*entering_scope=*/0);
+                                       /*entering_scope=*/0,
+                                       /*complain=*/1);
        }
       else
        {
@@ -5669,6 +5678,15 @@ select_decl (binding, flags)
 {
   tree val;
   val = BINDING_VALUE (binding);
+
+  /* When we implicitly declare some builtin entity, we mark it
+     DECL_ANTICIPATED, so that we know to ignore it until it is
+     really declared.  */
+  if (val && DECL_P (val)
+      && DECL_LANG_SPECIFIC (val)
+      && DECL_ANTICIPATED (val))
+    return NULL_TREE;
+
   if (LOOKUP_NAMESPACES_ONLY (flags))
     {
       /* We are not interested in types. */
@@ -5858,7 +5876,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
         flags |= LOOKUP_TEMPLATES_EXPECTED;
 
       /* std:: becomes :: for now.  */
-      if (got_scope == std_node)
+      if (got_scope && got_scope == fake_std_node)
        got_scope = void_type_node;
 
       if (got_scope)
@@ -5888,7 +5906,7 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
            }
          else if (! IS_AGGR_TYPE (type)
                   || TREE_CODE (type) == TEMPLATE_TYPE_PARM
-                  || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
+                  || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM
                   || TREE_CODE (type) == TYPENAME_TYPE)
            /* Someone else will give an error about this if needed.  */
            val = NULL_TREE;
@@ -5913,7 +5931,10 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       if (got_scope)
        goto done;
       else if (got_object && val)
-       from_obj = val;
+       {
+         from_obj = val;
+         val = NULL_TREE;
+       }
     }
   else
     {
@@ -5982,13 +6003,11 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
        {
          if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
              && TREE_CODE (val) == TYPE_DECL
-             && TREE_TYPE (from_obj) != TREE_TYPE (val))
-           {
-             cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')",
-                         name, got_object, TREE_TYPE (from_obj));
-             cp_pedwarn ("  does not match lookup in the current scope (`%#T')",
-                         TREE_TYPE (val));
-           }
+             && ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val)))
+           cp_pedwarn ("\
+lookup of `%D' in the scope of `%#T' (`%#D') \
+does not match lookup in the current scope (`%#D')",
+                       name, got_object, from_obj, val);
 
          /* We don't change val to from_obj if got_object depends on
             template parms because that breaks implicit typename for
@@ -6119,11 +6138,11 @@ end_only_namespace_names ()
 }
 \f
 /* Push the declarations of builtin types into the namespace.
-   RID_INDEX, if < CP_RID_MAX is the index of the builtin type
+   RID_INDEX is the index of the builtin type
    in the array RID_POINTERS.  NAME is the name used when looking
    up the builtin type.  TYPE is the _TYPE node for the builtin type.  */
 
-static void
+void
 record_builtin_type (rid_index, name, type)
      enum rid rid_index;
      const char *name;
@@ -6132,7 +6151,7 @@ record_builtin_type (rid_index, name, type)
   tree rname = NULL_TREE, tname = NULL_TREE;
   tree tdecl = NULL_TREE;
 
-  if ((int) rid_index < (int) CP_RID_MAX)
+  if ((int) rid_index < (int) RID_MAX)
     rname = ridpointers[(int) rid_index];
   if (name)
     tname = get_identifier (name);
@@ -6143,7 +6162,7 @@ record_builtin_type (rid_index, name, type)
     {
       tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
       set_identifier_type_value (tname, NULL_TREE);
-      if ((int) rid_index < (int) CP_RID_MAX)
+      if ((int) rid_index < (int) RID_MAX)
        /* Built-in types live in the global namespace. */
        SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
     }
@@ -6186,7 +6205,7 @@ record_builtin_java_type (name, size)
       TYPE_PRECISION (type) = - size;
       layout_type (type);
     }
-  record_builtin_type (CP_RID_MAX, name, type);
+  record_builtin_type (RID_MAX, name, type);
   decl = TYPE_NAME (type);
 
   /* Suppress generate debug symbol entries for these types,
@@ -6231,7 +6250,7 @@ typedef struct predefined_identifier
 /* Create all the predefined identifiers.  */
 
 static void
-initialize_predefined_identifiers () 
+initialize_predefined_identifiers ()
 {
   struct predefined_identifier *pid;
 
@@ -6279,22 +6298,22 @@ void
 init_decl_processing ()
 {
   tree fields[20];
-  int wchar_type_size;
-  tree array_domain_type;
 
   /* Check to see that the user did not specify an invalid combination
      of command-line options.  */
-  if (flag_new_abi && !flag_vtable_thunks)
-    fatal ("the new ABI requires vtable thunks");
+  if (!flag_vtable_thunks)
+    error ("the ABI requires vtable thunks");
 
   /* 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;
+  lang_dump_tree = &cp_dump_tree;
+  lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
 
   cp_parse_init ();
   init_decl2 ();
@@ -6334,68 +6353,23 @@ init_decl_processing ()
   NAMESPACE_LEVEL (global_namespace) = global_binding_level;
   declare_namespace_level ();
 
-  /* Define `int' and `char' first so that dbx will output them first.  */
-  record_builtin_type (RID_INT, NULL_PTR, integer_type_node);
-  record_builtin_type (RID_CHAR, "char", char_type_node);
-
-  /* `signed' is the same as `int' */
-  record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
-  record_builtin_type (RID_LONG, "long int", long_integer_type_node);
-  record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
-  record_builtin_type (CP_RID_MAX, "long unsigned int",
-                      long_unsigned_type_node);
-  record_builtin_type (CP_RID_MAX, "unsigned long", long_unsigned_type_node);
-  record_builtin_type (CP_RID_MAX, "long long int",
-                      long_long_integer_type_node);
-  record_builtin_type (CP_RID_MAX, "long long unsigned int",
-                      long_long_unsigned_type_node);
-  record_builtin_type (CP_RID_MAX, "long long unsigned",
-                      long_long_unsigned_type_node);
-  record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
-  record_builtin_type (CP_RID_MAX, "short unsigned int",
-                      short_unsigned_type_node); 
-  record_builtin_type (CP_RID_MAX, "unsigned short",
-                      short_unsigned_type_node);
-
-  ptrdiff_type_node
-    = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
-
-  /* Define both `signed char' and `unsigned char'.  */
-  record_builtin_type (CP_RID_MAX, "signed char", signed_char_type_node);
-  record_builtin_type (CP_RID_MAX, "unsigned char", unsigned_char_type_node);
-
-  /* `unsigned long' is the standard type for sizeof.
-     Note that stddef.h uses `unsigned long',
-     and this must agree, even if long and int are the same size.  */
-  set_sizetype
-    (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
-
-  /* Create the widest literal types. */
-  widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE,
-                       widest_integer_literal_type_node));
-
-  widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE,
-                       widest_unsigned_literal_type_node));
-
-  /* These are types that type_for_size and type_for_mode use.  */
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
-#if HOST_BITS_PER_WIDE_INT >= 64
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
-#endif
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
-#if HOST_BITS_PER_WIDE_INT >= 64
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
-#endif
+  /* Create the `std' namespace.  */
+  if (flag_honor_std)
+    {
+      push_namespace (std_identifier);
+      std_node = current_namespace;
+      pop_namespace ();
+      fake_std_node = error_mark_node;
+    }
+  else
+    {
+      fake_std_node = build_decl (NAMESPACE_DECL,
+                                 std_identifier,
+                                 void_type_node);
+      pushdecl (fake_std_node);
+    }
 
-  build_common_tree_nodes_2 (flag_short_double);
+  c_common_nodes_and_builtins ();
 
   java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
   java_short_type_node = record_builtin_java_type ("__java_short", 16);
@@ -6423,74 +6397,18 @@ init_decl_processing ()
   TREE_TYPE (boolean_true_node) = boolean_type_node;
 
   signed_size_zero_node = build_int_2 (0, 0);
-  record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
-  record_builtin_type (RID_DOUBLE, NULL_PTR, double_type_node);
-  record_builtin_type (CP_RID_MAX, "long double", long_double_type_node);
-
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
-                       complex_integer_type_node));
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
-                       complex_float_type_node));
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
-                       complex_double_type_node));
-  pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
-                       complex_long_double_type_node));
-
   TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype));
 
-  record_builtin_type (RID_VOID, NULL_PTR, void_type_node);
-  void_list_node = build_tree_list (NULL_TREE, void_type_node);
-  TREE_PARMLIST (void_list_node) = 1;
-
-  /* Used for expressions that do nothing, but are not errors.  */
-  void_zero_node = build_int_2 (0, 0);
-  TREE_TYPE (void_zero_node) = void_type_node;
-
-  string_type_node = build_pointer_type (char_type_node);
-  const_string_type_node
-    = build_pointer_type (build_qualified_type (char_type_node,
-                                               TYPE_QUAL_CONST));
   empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
+
 #if 0
-  record_builtin_type (CP_RID_MAX, NULL_PTR, string_type_node);
+  record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
 #endif
 
-  /* Make a type to be the domain of a few array types
-     whose domains don't really matter.
-     200 is small enough that it always fits in size_t.  */
-  array_domain_type = build_index_type (build_int_2 (200, 0));
-
-  /* Make a type for arrays of characters.
-     With luck nothing will ever really depend on the length of this
-     array type.  */
-  char_array_type_node
-    = build_array_type (char_type_node, array_domain_type);
-
-  /* Likewise for arrays of ints.  */
-  int_array_type_node
-    = build_array_type (integer_type_node, array_domain_type);
-
-  if (flag_new_abi)
-    delta_type_node = ptrdiff_type_node;
-  else if (flag_huge_objects)
-    delta_type_node = long_integer_type_node;
-  else
-    delta_type_node = short_integer_type_node;
-
-  if (flag_new_abi)
-    vtable_index_type = ptrdiff_type_node;
-  else
-    vtable_index_type = delta_type_node;
-
-  default_function_type
-    = build_function_type (integer_type_node, NULL_TREE);
+  delta_type_node = ptrdiff_type_node;
+  vtable_index_type = ptrdiff_type_node;
 
-  ptr_type_node = build_pointer_type (void_type_node);
-  const_ptr_type_node
-    = build_pointer_type (build_qualified_type (void_type_node,
-                                               TYPE_QUAL_CONST));
   vtt_parm_type = build_pointer_type (const_ptr_type_node);
-  c_common_nodes_and_builtins (1, flag_no_builtin, flag_no_nonansi_builtin);
   lang_type_promotes_to = convert_type_from_ellipsis;
 
   void_ftype_ptr
@@ -6511,27 +6429,6 @@ init_decl_processing ()
   TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
   TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
 
-  /* This is special for C++ so functions can be overloaded.  */
-  wchar_type_node = get_identifier (flag_short_wchar
-                                   ? "short unsigned int"
-                                   : WCHAR_TYPE);
-  wchar_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (wchar_type_node));
-  wchar_type_size = TYPE_PRECISION (wchar_type_node);
-  if (TREE_UNSIGNED (wchar_type_node))
-    wchar_type_node = make_signed_type (wchar_type_size);
-  else
-    wchar_type_node = make_unsigned_type (wchar_type_size);
-  record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node);
-
-  /* Artificial declaration of wchar_t -- can be bashed */
-  wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"),
-                               wchar_type_node);
-  pushdecl (wchar_decl_node);
-
-  /* This is for wide string constants.  */
-  wchar_array_type_node
-    = build_array_type (wchar_type_node, array_domain_type);
-
   if (flag_vtable_thunks)
     {
       /* Make sure we get a unique function type, so we can give
@@ -6567,29 +6464,20 @@ init_decl_processing ()
       vtable_entry_type = build_qualified_type (vtable_entry_type,
                                                TYPE_QUAL_CONST);
     }
-  record_builtin_type (CP_RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
+  record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
 
   vtbl_type_node
     = build_cplus_array_type (vtable_entry_type, NULL_TREE);
   layout_type (vtbl_type_node);
   vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
-  record_builtin_type (CP_RID_MAX, NULL_PTR, vtbl_type_node);
+  record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
   vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
   layout_type (vtbl_ptr_type_node);
-  record_builtin_type (CP_RID_MAX, NULL_PTR, vtbl_ptr_type_node);
+  record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
 
-  std_node = build_decl (NAMESPACE_DECL,
-                        flag_honor_std 
-                        ? get_identifier ("fake std") : std_identifier,
-                        void_type_node);
-  pushdecl (std_node);
-  
-  if (flag_new_abi)
-    {
-      push_namespace (get_identifier ("__cxxabiv1"));
-      abi_node = current_namespace;
-      pop_namespace ();
-    }
+  push_namespace (get_identifier ("__cxxabiv1"));
+  abi_node = current_namespace;
+  pop_namespace ();
 
   global_type_node = make_node (LANG_TYPE);
   record_unknown_type (global_type_node, "global type");
@@ -6600,7 +6488,7 @@ init_decl_processing ()
   {
     tree bad_alloc_type_node, newtype, deltype;
     if (flag_honor_std)
-      push_namespace (get_identifier ("std"));
+      push_namespace (std_identifier);
     bad_alloc_type_node = xref_tag
       (class_type_node, get_identifier ("bad_alloc"), 1);
     if (flag_honor_std)
@@ -6615,7 +6503,7 @@ init_decl_processing ()
   }
 
   abort_fndecl
-    = build_library_fn_ptr ("__pure_virtual", void_ftype);
+    = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
 
   /* Perform other language dependent initializations.  */
   init_class_processing ();
@@ -6634,6 +6522,10 @@ init_decl_processing ()
     flag_weak = 0;
 
   /* Create the global bindings for __FUNCTION__ and __PRETTY_FUNCTION__.  */
+  function_id_node = get_identifier ("__FUNCTION__");
+  pretty_function_id_node = get_identifier ("__PRETTY_FUNCTION__");
+  func_id_node = get_identifier ("__func__");
+
   make_fname_decl = cp_make_fname_decl;
   declare_function_name ();
 
@@ -6643,7 +6535,6 @@ init_decl_processing ()
   /* Show we use EH for cleanups.  */
   using_eh_for_cleanups ();
 
-  print_error_function = lang_print_error_function;
   valid_lang_attribute = cp_valid_lang_attribute;
 
   /* Maintain consistency.  Perhaps we should just complain if they
@@ -6668,7 +6559,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);
@@ -6682,6 +6572,7 @@ init_decl_processing ()
 
   ggc_add_tree_root (&current_lang_name, 1);
   ggc_add_tree_root (&static_aggregates, 1);
+  ggc_add_tree_root (&free_bindings, 1);
 }
 
 /* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
@@ -6701,11 +6592,11 @@ cp_make_fname_decl (id, name, type_dep)
   tree decl, type, init;
   size_t length = strlen (name);
   tree domain = NULL_TREE;
-  
+
   if (!processing_template_decl)
     type_dep = 0;
   if (!type_dep)
-    domain = build_index_type (build_int_2 (length, 0));
+    domain = build_index_type (size_int (length));
 
   type =  build_cplus_array_type
           (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
@@ -6732,21 +6623,11 @@ cp_make_fname_decl (id, name, type_dep)
     }
   DECL_INITIAL (decl) = init;
   cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
-  
+
   /* We will have to make sure we only emit this, if it is actually used. */
   return decl;
 }
 
-/* Function to print any language-specific context for an error message.  */
-
-static void
-lang_print_error_function (file)
-     const char *file;
-{
-  default_print_error_function (file);
-  maybe_print_template_context ();
-}
-
 /* Entry point for the benefit of c_common_nodes_and_builtins.
 
    Make a definition for a builtin function named NAME and whose data type
@@ -6772,13 +6653,23 @@ builtin_function (name, type, code, class, libname)
 
   my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
 
+  /* All builtins that don't begin with an `_' should go in the `std'
+     namespace.  */
+  if (flag_honor_std && name[0] != '_')
+    {
+      push_namespace (std_identifier);
+      DECL_CONTEXT (decl) = std_node;
+    }
+  pushdecl (decl);
+  if (flag_honor_std && name[0] != '_')
+    pop_namespace ();
+
   /* Since `pushdecl' relies on DECL_ASSEMBLER_NAME instead of DECL_NAME,
      we cannot change DECL_ASSEMBLER_NAME until we have installed this
      function in the namespace.  */
-  pushdecl (decl);
   if (libname)
     DECL_ASSEMBLER_NAME (decl) = get_identifier (libname);
-  make_function_rtl (decl);
+  make_decl_rtl (decl, NULL);
 
   /* Warn if a function in the namespace for users
      is used without an occasion to consider it declared.  */
@@ -6816,7 +6707,7 @@ build_library_fn (name, type)
      tree type;
 {
   tree fn = build_library_fn_1 (name, ERROR_MARK, type);
-  make_function_rtl (fn);
+  make_decl_rtl (fn, NULL);
   return fn;
 }
 
@@ -6832,7 +6723,7 @@ build_cp_library_fn (name, operator_code, type)
   TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
   DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
   set_mangled_name_for_decl (fn);
-  make_function_rtl (fn);
+  make_decl_rtl (fn, NULL);
   return fn;
 }
 
@@ -6878,7 +6769,7 @@ push_cp_library_fn (operator_code, type)
      enum tree_code operator_code;
      tree type;
 {
-  tree fn = build_cp_library_fn (ansi_opname (operator_code), 
+  tree fn = build_cp_library_fn (ansi_opname (operator_code),
                                 operator_code,
                                 type);
   pushdecl (fn);
@@ -6946,7 +6837,7 @@ fixup_anonymous_aggr (t)
 
   /* ISO C++ 9.5.3.  Anonymous unions may not have function members.  */
   if (TYPE_METHODS (t))
-    error ("an anonymous union cannot have function members");
+    cp_error_at ("an anonymous union cannot have function members", t);
 }
 
 /* Make sure that a declaration with no declarator is well-formed, i.e.
@@ -6960,6 +6851,7 @@ check_tag_decl (declspecs)
 {
   int found_type = 0;
   int saw_friend = 0;
+  int saw_typedef = 0;
   tree ob_modifier = NULL_TREE;
   register tree link;
   register tree t = NULL_TREE;
@@ -6969,19 +6861,30 @@ check_tag_decl (declspecs)
       register tree value = TREE_VALUE (link);
 
       if (TYPE_P (value)
+         || TREE_CODE (value) == TYPE_DECL
          || (TREE_CODE (value) == IDENTIFIER_NODE
              && IDENTIFIER_GLOBAL_VALUE (value)
-             && TYPE_P (IDENTIFIER_GLOBAL_VALUE (value))))
+             && TREE_CODE (IDENTIFIER_GLOBAL_VALUE (value)) == TYPE_DECL))
        {
          ++found_type;
 
-         if ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))
-             || TREE_CODE (value) == ENUMERAL_TYPE)
+         if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
+           {
+             if (! in_system_header)
+               cp_pedwarn ("redeclaration of C++ built-in type `%T'", value);
+             return NULL_TREE;
+           }
+
+         if (TYPE_P (value)
+             && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))
+                 || TREE_CODE (value) == ENUMERAL_TYPE))
            {
              my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
              t = value;
            }
        }
+      else if (value == ridpointers[(int) RID_TYPEDEF])
+        saw_typedef = 1;
       else if (value == ridpointers[(int) RID_FRIEND])
        {
          if (current_class_type == NULL_TREE
@@ -7015,6 +6918,27 @@ check_tag_decl (declspecs)
           && TYPE_NAME (t)
           && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
     {
+      /* 7/3 In a simple-declaration, the optional init-declarator-list
+         can be omitted only when declaring a class (clause 9) or
+         enumeration (7.2), that is, when the decl-specifier-seq contains
+         either a class-specifier, an elaborated-type-specifier with
+         a class-key (9.1), or an enum-specifier.  In these cases and
+         whenever a class-specifier or enum-specifier is present in the
+         decl-specifier-seq, the identifiers in these specifiers are among
+         the names being declared by the declaration (as class-name,
+         enum-names, or enumerators, depending on the syntax).  In such
+         cases, and except for the declaration of an unnamed bit-field (9.6),
+         the decl-specifier-seq shall introduce one or more names into the
+         program, or shall redeclare a name introduced by a previous
+         declaration.  [Example:
+             enum { };            // ill-formed
+             typedef class { };   // ill-formed
+         --end example]  */
+      if (saw_typedef)
+        {
+          error ("Missing type-name in typedef-declaration.");
+          return NULL_TREE;
+        }
       /* Anonymous unions are objects, so they can have specifiers.  */;
       SET_ANON_AGGR_TYPE_P (t);
 
@@ -7127,8 +7051,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   /* This should only be done once on the top most decl.  */
   if (have_extern_spec && !used_extern_spec)
     {
-      declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"),
-                                 declspecs);
+      declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
+                            declspecs);
       used_extern_spec = 1;
     }
 
@@ -7299,17 +7223,7 @@ start_decl_1 (decl)
   if (type == error_mark_node)
     return;
 
-  /* If this type of object needs a cleanup, but we're not allowed to
-     add any more objects with cleanups to the current scope, create a
-     new binding level.  */
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
-      && current_binding_level->more_cleanups_ok == 0)
-    {
-      keep_next_level (2);
-      pushlevel (1);
-      clear_last_expr ();
-      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
-    }
+  maybe_push_cleanup_level (type);
 
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
@@ -7340,7 +7254,7 @@ start_decl_1 (decl)
       && TREE_CODE (decl) != TYPE_DECL
       && TREE_CODE (decl) != TEMPLATE_DECL
       && type != error_mark_node
-      && IS_AGGR_TYPE (type) 
+      && IS_AGGR_TYPE (type)
       && ! DECL_EXTERNAL (decl))
     {
       if ((! processing_template_decl || ! uses_template_parms (type))
@@ -7494,12 +7408,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);
 
@@ -7603,6 +7514,7 @@ maybe_commonize_var (decl)
         inlining of such functions.  */
       current_function_cannot_inline
        = "function with static variable cannot be inline";
+      DECL_UNINLINABLE (current_function_decl) = 1;
 
       /* If flag_weak, we don't need to mess with this, as we can just
         make the function weak, and let it refer to its unique local
@@ -7625,8 +7537,7 @@ maybe_commonize_var (decl)
             which we can't if it has been initialized.  */
 
          if (TREE_PUBLIC (decl))
-           DECL_ASSEMBLER_NAME (decl)
-             = build_static_name (current_function_decl, DECL_NAME (decl));
+           DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
          else
            {
              cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
@@ -7714,14 +7625,13 @@ check_initializer (decl, init)
 
       DECL_INITIAL (decl) = init;
 
-      /* This will keep us from needing to worry about our obstacks.  */
       my_friendly_assert (init != NULL_TREE, 149);
       init = NULL_TREE;
     }
   else if (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
     {
       if (TREE_STATIC (decl))
-       make_decl_rtl (decl, NULL_PTR, toplevel_bindings_p ());
+       make_decl_rtl (decl, NULL_PTR);
       grok_reference_init (decl, type, init);
       init = NULL_TREE;
     }
@@ -7848,7 +7758,7 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
   /* If we're deferring the variable, just make RTL.  Do not actually
      emit the variable.  */
   if (defer_p)
-    make_decl_rtl (decl, asmspec, toplev);
+    make_decl_rtl (decl, asmspec);
   /* If we're not deferring, go ahead and assemble the variable.  */
   else
     rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
@@ -7866,7 +7776,7 @@ maybe_inject_for_scope_var (decl)
 {
   if (!DECL_NAME (decl))
     return;
-  
+
   if (current_binding_level->is_for_scope)
     {
       struct binding_level *outer
@@ -7940,15 +7850,12 @@ initialize_local_var (decl, init, flags)
        {
          int saved_stmts_are_full_exprs_p;
 
-         emit_line_note (DECL_SOURCE_FILE (decl),
-                         DECL_SOURCE_LINE (decl));
+         my_friendly_assert (building_stmt_tree (), 20000906);
          saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
-         current_stmt_tree->stmts_are_full_exprs_p = 1;
-         if (building_stmt_tree ())
-           finish_expr_stmt (build_aggr_init (decl, init, flags));
-         else
-           genrtl_expr_stmt (build_aggr_init (decl, init, flags));
-         current_stmt_tree->stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
+         current_stmt_tree ()->stmts_are_full_exprs_p = 1;
+         finish_expr_stmt (build_aggr_init (decl, init, flags));
+         current_stmt_tree ()->stmts_are_full_exprs_p =
+           saved_stmts_are_full_exprs_p;
        }
 
       /* Set this to 0 so we can tell whether an aggregate which was
@@ -8045,7 +7952,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
       && CP_DECL_CONTEXT (decl) == current_class_type
       && TYPE_BEING_DEFINED (current_class_type)
       && (DECL_INITIAL (decl) || init))
-    DECL_DEFINED_IN_CLASS_P (decl) = 1;
+    DECL_INITIALIZED_IN_CLASS_P (decl) = 1;
 
   if (TREE_CODE (decl) == VAR_DECL
       && DECL_CONTEXT (decl)
@@ -8061,9 +7968,11 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
 
   if (type == error_mark_node)
     return;
-  
+
   /* Add this declaration to the statement-tree.  */
-  if (building_stmt_tree () && at_function_scope_p ())
+  if (building_stmt_tree ()
+      && at_function_scope_p ()
+      && TREE_CODE (decl) != RESULT_DECL)
     add_decl_stmt (decl);
 
   if (TYPE_HAS_MUTABLE_P (type))
@@ -8130,7 +8039,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
         grokclassfn.  Lay this out fresh.  */
       DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
       DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-      make_decl_rtl (decl, asmspec, 0);
+      make_decl_rtl (decl, asmspec);
     }
 
   /* Deduce size of array from initialization, if not already known.  */
@@ -8186,8 +8095,7 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
            {
              /* If we're not building RTL, then we need to do so
                 now.  */
-             if (!building_stmt_tree ())
-               emit_local_var (decl);
+             my_friendly_assert (building_stmt_tree (), 20000906);
              /* Initialize the variable.  */
              initialize_local_var (decl, init, flags);
              /* Clean up the variable.  */
@@ -8705,11 +8613,11 @@ member_function_or_else (ctype, cur_type, flags)
   if (ctype && ctype != cur_type)
     {
       if (flags == DTOR_FLAG)
-       error ("destructor for alien class `%s' cannot be a member",
-              TYPE_NAME_STRING (ctype));
+       cp_error ("destructor for alien class `%T' cannot be a member",
+                 ctype);
       else
-       error ("constructor for alien class `%s' cannot be a member",
-              TYPE_NAME_STRING (ctype));
+       cp_error ("constructor for alien class `%T' cannot be a member",
+                 ctype);
       return 0;
     }
   return 1;
@@ -8735,7 +8643,8 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
              object, type);
   if (friendp)
     cp_error_at ("`%D' declared as a friend", object);
-  if (raises)
+  if (raises && !TYPE_PTRFN_P (TREE_TYPE (object))
+      && !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))
     cp_error_at ("`%D' declared with an exception specification", object);
 }
 
@@ -8822,8 +8731,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
        error ("cannot declare `::main' to be a template");
       if (inlinep)
        error ("cannot declare `::main' to be inline");
-      else if (! publicp)
+      if (!publicp)
        error ("cannot declare `::main' to be static");
+      if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+                       integer_type_node))
+       error ("`main' must return `int'");
       inlinep = 0;
       publicp = 1;
     }
@@ -8899,6 +8811,9 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
           orig_declarator);
       else
        {
+         tree fns = TREE_OPERAND (orig_declarator, 0);
+         tree args = TREE_OPERAND (orig_declarator, 1);
+
          if (PROCESSING_REAL_TEMPLATE_DECL_P ())
            {
              /* Something like `template <class T> friend void f<T>()'.  */
@@ -8911,10 +8826,22 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
          /* A friend declaration of the form friend void f<>().  Record
             the information in the TEMPLATE_ID_EXPR.  */
          SET_DECL_IMPLICIT_INSTANTIATION (decl);
-         DECL_TEMPLATE_INFO (decl)
-           = tree_cons (TREE_OPERAND (orig_declarator, 0),
-                        TREE_OPERAND (orig_declarator, 1),
-                        NULL_TREE);
+
+          if (TREE_CODE (fns) == COMPONENT_REF)
+            {
+              /* Due to bison parser ickiness, we will have already looked
+                 up an operator_name or PFUNCNAME within the current class
+                 (see template_id in parse.y). If the current class contains
+                 such a name, we'll get a COMPONENT_REF here. Undo that. */
+
+              my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+                                  == current_class_type, 20001120);
+              fns = TREE_OPERAND (fns, 1);
+            }
+         my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+                             || TREE_CODE (fns) == LOOKUP_EXPR
+                             || TREE_CODE (fns) == OVERLOAD, 20001120);
+         DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
 
          if (has_default_arg)
            {
@@ -8937,8 +8864,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
   /* Plain overloading: will not be grok'd by grokclassfn.  */
   if (! ctype && ! processing_template_decl
-      && !DECL_EXTERN_C_P (decl)
-      && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
+      && (! DECL_EXTERN_C_P (decl) || DECL_OVERLOADED_OPERATOR_P (decl))
+      && ! DECL_USE_TEMPLATE (decl))
     set_mangled_name_for_decl (decl);
 
   if (funcdef_flag)
@@ -9018,12 +8945,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
     return decl;
 
   if (virtualp)
-    {
-      DECL_VIRTUAL_P (decl) = 1;
-      if (DECL_VINDEX (decl) == NULL_TREE)
-       DECL_VINDEX (decl) = error_mark_node;
-      IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
-    }
+    DECL_VIRTUAL_P (decl) = 1;
 
   return decl;
 }
@@ -9053,13 +8975,7 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
       /* DECL_ASSEMBLER_NAME is needed only for full-instantiated
         templates.  */
       if (!uses_template_parms (decl))
-       {
-         if (flag_new_abi)
-           DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
-         else
-           DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype,
-                                                           declarator);
-       }
+       DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
     }
   else
     {
@@ -9083,14 +8999,8 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
        set_decl_namespace (decl, context, 0);
 
       context = DECL_CONTEXT (decl);
-      if (declarator && context && current_lang_name != lang_name_c) 
-       {
-         if (flag_new_abi)
-           DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
-         else
-           DECL_ASSEMBLER_NAME (decl) 
-             = build_static_name (context, declarator);
-       }
+      if (declarator && context && current_lang_name != lang_name_c)
+       DECL_ASSEMBLER_NAME (decl) = mangle_decl (decl);
     }
 
   if (in_namespace)
@@ -9155,9 +9065,11 @@ build_ptrmemfunc_type (type)
 {
   tree fields[4];
   tree t;
-  tree u;
   tree unqualified_variant = NULL_TREE;
 
+  if (type == error_mark_node)
+    return type;
+
   /* If a canonical type already exists for this type, use it.  We use
      this method instead of type_hash_canon, because it only does a
      simple equality check on the list of field members.  */
@@ -9177,30 +9089,10 @@ build_ptrmemfunc_type (type)
   /* ... and not really an aggregate.  */
   SET_IS_AGGR_TYPE (t, 0);
 
-  if (!flag_new_abi)
-    {
-      u = make_aggr_type (UNION_TYPE);
-      SET_IS_AGGR_TYPE (u, 0);
-      fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
-      fields[1] = build_decl (FIELD_DECL, delta2_identifier,
-                             delta_type_node);
-      finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
-      TYPE_NAME (u) = NULL_TREE;
-
-      fields[0] = build_decl (FIELD_DECL, delta_identifier,
-                             delta_type_node);
-      fields[1] = build_decl (FIELD_DECL, index_identifier,
-                             delta_type_node);
-      fields[2] = build_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
-      finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
-    }
-  else
-    {
-      fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
-      fields[1] = build_decl (FIELD_DECL, delta_identifier,
-                             delta_type_node);
-      finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
-    }
+  fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
+  fields[1] = build_decl (FIELD_DECL, delta_identifier,
+                         delta_type_node);
+  finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
 
   /* Zap out the name so that the back-end will give us the debugging
      information for this anonymous RECORD_TYPE.  */
@@ -9472,17 +9364,15 @@ create_array_type_for_decl (name, type, size)
 
 /* Check that it's OK to declare a function with the indicated TYPE.
    SFK indicates the kind of special function (if any) that this
-   function is.  CTYPE is the class of which this function is a
-   member.  OPTYPE is the type given in a conversion operator
+   function is.  OPTYPE is the type given in a conversion operator
    declaration.  Returns the actual return type of the function; that
    may be different than TYPE if an error occurs, or for certain
    special functions.  */
 
 static tree
-check_special_function_return_type (sfk, type, ctype, optype)
+check_special_function_return_type (sfk, type, optype)
      special_function_kind sfk;
      tree type;
-     tree ctype;
      tree optype;
 {
   switch (sfk)
@@ -9490,10 +9380,9 @@ check_special_function_return_type (sfk, type, ctype, optype)
     case sfk_constructor:
       if (type)
        cp_error ("return type specification for constructor invalid");
-       
-      /* In the old ABI, we return `this'; in the new ABI we don't
-        bother.  */
-      type = flag_new_abi ? void_type_node : build_pointer_type        (ctype);
+
+      /* In the new ABI constructors do not return a value.  */
+      type = void_type_node;
       break;
 
     case sfk_destructor:
@@ -9796,7 +9685,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            next = 0;
 
-           if (is_rid (dname))
+           if (C_IS_RESERVED_WORD (dname))
              {
                cp_error ("declarator-id missing; using reserved word `%D'",
                          dname);
@@ -9811,7 +9700,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                ctor_return_type = TREE_TYPE (dname);
                sfk = sfk_conversion;
                if (IDENTIFIER_GLOBAL_VALUE (dname)
-                   && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (dname)) 
+                   && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (dname))
                        == TYPE_DECL))
                  name = IDENTIFIER_POINTER (dname);
                else
@@ -9840,7 +9729,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                       && TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
                ctype = cname;
              else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
-                      || TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM)
+                      || TREE_CODE (cname) == BOUND_TEMPLATE_TEMPLATE_PARM)
                {
                  cp_error ("`%T::%D' is not a valid declarator", cname,
                            TREE_OPERAND (decl, 1));
@@ -10103,7 +9992,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
   if (sfk != sfk_none)
     type = check_special_function_return_type (sfk, type,
-                                              ctor_return_type,
                                               ctor_return_type);
   else if (type == NULL_TREE)
     {
@@ -10359,10 +10247,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
        ;
       else if (decl_context == FIELD
-              /* C++ allows static class elements  */
-              && RIDBIT_SETP (RID_STATIC, specbits))
-       /* C++ also allows inlines and signed and unsigned elements,
-          but in those cases we don't come in here.  */
+              /* C++ allows static class elements  */
+              && RIDBIT_SETP (RID_STATIC, specbits))
+       /* C++ also allows inlines and signed and unsigned elements,
+          but in those cases we don't come in here.  */
        ;
       else
        {
@@ -10382,7 +10270,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  if (IDENTIFIER_TYPENAME_P (tmp))
                    {
                      if (IDENTIFIER_GLOBAL_VALUE (tmp)
-                         && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (tmp)) 
+                         && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (tmp))
                              == TYPE_DECL))
                        name = IDENTIFIER_POINTER (tmp);
                      else
@@ -10525,7 +10413,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            type = create_array_type_for_decl (dname, type, size);
 
            /* VLAs never work as fields. */
-           if (decl_context == FIELD && !processing_template_decl 
+           if (decl_context == FIELD && !processing_template_decl
                && TREE_CODE (type) == ARRAY_TYPE
                && TYPE_DOMAIN (type) != NULL_TREE
                && !TREE_CONSTANT (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
@@ -10644,10 +10532,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                        cp_error ("constructors may not be `%s'",
                                  IDENTIFIER_POINTER (TREE_VALUE (quals)));
                        quals = NULL_TREE;
-                     }
+                     }
                    {
                      RID_BIT_TYPE tmp_bits;
-                     bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof (RID_BIT_TYPE));
+                     memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE));
                      RIDBIT_RESET (RID_INLINE, tmp_bits);
                      RIDBIT_RESET (RID_STATIC, tmp_bits);
                      if (RIDBIT_ANY_SET (tmp_bits))
@@ -10693,7 +10581,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            /* FIXME: This is where default args should be fully
               processed.  */
 
-           arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
+           arg_types = grokparms (inner_parms);
 
            if (declarator && flags == DTOR_FLAG)
              {
@@ -10888,7 +10776,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            t = ctype;
            while (t != NULL_TREE && CLASS_TYPE_P (t))
              {
-               /* You're supposed to have one `template <...>' 
+               /* You're supposed to have one `template <...>'
                   for every template class, but you don't need one
                   for a full specialization.  For example:
 
@@ -10900,14 +10788,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                   the definition of `S<int>::f'.  */
                if (CLASSTYPE_TEMPLATE_INFO (t)
                    && (CLASSTYPE_TEMPLATE_INSTANTIATION (t)
-                       || uses_template_parms (CLASSTYPE_TI_ARGS (t))))
+                       || uses_template_parms (CLASSTYPE_TI_ARGS (t)))
+                   && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
                  template_count += 1;
 
                t = TYPE_MAIN_DECL (t);
-               if (DECL_LANG_SPECIFIC (t))
-                 t = DECL_CONTEXT (t);
-               else
-                 t = NULL_TREE;
+               t = DECL_CONTEXT (t);
              }
 
            if (sname == NULL_TREE)
@@ -10932,8 +10818,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  }
                else if (TREE_CODE (type) == FUNCTION_TYPE)
                  {
-                   if (current_class_type == NULL_TREE
-                       || friendp)
+                   if (current_class_type == NULL_TREE || friendp)
                      type = build_cplus_method_type (ctype, TREE_TYPE (type),
                                                      TYPE_ARG_TYPES (type));
                    else
@@ -10959,17 +10844,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                      }
                    type = build_offset_type (ctype, type);
                  }
-               else if (uses_template_parms (ctype))
-                 {
-                    if (TREE_CODE (type) == FUNCTION_TYPE)
-                     type
-                       = build_cplus_method_type (ctype, TREE_TYPE (type),
-                                                  TYPE_ARG_TYPES (type));
-                 }
                else
-                 {
-                   cp_error ("structure `%T' not yet defined", ctype);
-                   return error_mark_node;
+                 {
+                   incomplete_type_error (NULL_TREE, ctype);
+                   return error_mark_node;
                  }
 
                declarator = sname;
@@ -11022,7 +10900,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       else if (attrlist)
        TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
       else
-       attrlist = build_decl_list (NULL_TREE, inner_attrs);
+       attrlist = build_tree_list (NULL_TREE, inner_attrs);
     }
 
   /* Now TYPE has the actual type.  */
@@ -11131,24 +11009,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
              = TYPE_IDENTIFIER (type);
 
-         if (flag_new_abi) 
-           DECL_ASSEMBLER_NAME (decl) = mangle_type (type);
-         else
-           {
-             /* XXX Temporarily set the scope.
-                When returning, start_decl expects it as NULL_TREE,
-                and will then then set it using pushdecl. */
-             my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404);
-             if (current_class_type)
-               DECL_CONTEXT (decl) = current_class_type;
-             else
-               DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
-             
-             DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
-             DECL_ASSEMBLER_NAME (decl)
-               = get_identifier (build_overload_name (type, 1, 1));
-             DECL_CONTEXT (decl) = NULL_TREE;
-           }
+         DECL_ASSEMBLER_NAME (decl) = mangle_type (type);
 
          /* FIXME remangle member functions; member functions of a
             type with external linkage have external linkage.  */
@@ -11220,23 +11081,37 @@ 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 except with a class-key.  */
+         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.  */
          if (type != integer_type_node)
            {
+             decl_type_access_control (TYPE_NAME (type));
+
              /* A friendly class?  */
              if (current_class_type)
                make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
              else
-               error ("trying to make class `%s' a friend of global scope",
-                      TYPE_NAME_STRING (type));
+               cp_error ("trying to make class `%T' a friend of global scope",
+                         type);
+
              type = void_type_node;
            }
        }
@@ -11311,11 +11186,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        type = build_pointer_type (type);
       else if (TREE_CODE (type) == OFFSET_TYPE)
        type = build_pointer_type (type);
-      else if (TREE_CODE (type) == VOID_TYPE && declarator)
-       {
-         error ("declaration of `%s' as void", name);
-         return NULL_TREE;
-       }
     }
 
   {
@@ -11435,15 +11305,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                /* The constructor can be called with exactly one
                   parameter if there is at least one parameter, and
                   any subsequent parameters have default arguments.
-                  We don't look at the first parameter, which is
-                  really just the `this' parameter for the new
-                  object.  */
-               tree arg_types =
-                 TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
-
-               /* Skip the `in_chrg' argument too, if present.  */
-               if (DECL_HAS_IN_CHARGE_PARM_P (decl))
-                 arg_types = TREE_CHAIN (arg_types);
+                  Ignore any compiler-added parms.  */
+               tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
 
                if (arg_types == void_list_node
                    || (arg_types
@@ -11781,25 +11644,13 @@ require_complete_types_for_parms (parms)
 {
   for (; parms; parms = TREE_CHAIN (parms))
     {
-      tree type = TREE_TYPE (parms);
-
-      /* Try to complete the TYPE.  */
-      type = complete_type (type);
-
-      if (type == error_mark_node)
-       continue;
-
-      if (!COMPLETE_TYPE_P (type))
-       {
-         if (DECL_NAME (parms))
-           error ("parameter `%s' has incomplete type",
-                  IDENTIFIER_POINTER (DECL_NAME (parms)));
-         else
-           error ("parameter has incomplete type");
-         TREE_TYPE (parms) = error_mark_node;
-       }
-      else
+      if (VOID_TYPE_P (TREE_TYPE (parms)))
+        /* grokparms will have already issued an error */
+        TREE_TYPE (parms) = error_mark_node;
+      else if (complete_type_or_else (TREE_TYPE (parms), parms))
        layout_decl (parms, 0);
+      else
+        TREE_TYPE (parms) = error_mark_node;
     }
 }
 
@@ -11913,7 +11764,8 @@ check_default_argument (decl, arg)
 
      The keyword `this' shall not be used in a default argument of a
      member function.  */
-  var = walk_tree (&arg, local_variable_p_walkfn, NULL);
+  var = walk_tree_without_duplicates (&arg, local_variable_p_walkfn,
+                                     NULL);
   if (var)
     {
       cp_error ("default argument `%E' uses local variable `%D'",
@@ -11929,224 +11781,132 @@ check_default_argument (decl, arg)
    Given the list of things declared inside the parens,
    return a list of types.
 
-   The list we receive can have three kinds of elements:
-   an IDENTIFIER_NODE for names given without types,
-   a TREE_LIST node for arguments given as typespecs or names with typespecs,
-   or void_type_node, to mark the end of an argument list
-   when additional arguments are not permitted (... was not used).
-
-   FUNCDEF_FLAG is nonzero for a function definition, 0 for
-   a mere declaration.  A nonempty identifier-list gets an error message
-   when FUNCDEF_FLAG is zero.
-   If FUNCDEF_FLAG is 1, then parameter types must be complete.
-   If FUNCDEF_FLAG is -1, then parameter types may be incomplete.
-
-   If all elements of the input list contain types,
-   we return a list of the types.
-   If all elements contain no type (except perhaps a void_type_node
-   at the end), we return a null list.
-   If some have types and some do not, it is an error, and we
-   return a null list.
-
-   Also set last_function_parms to either
-   a list of names (IDENTIFIER_NODEs) or a chain of PARM_DECLs.
-   A list of names is converted to a chain of PARM_DECLs
-   by store_parm_decls so that ultimately it is always a chain of decls.
-
-   Note that in C++, parameters can take default values.  These default
-   values are in the TREE_PURPOSE field of the TREE_LIST.  It is
-   an error to specify default values which are followed by parameters
-   that have no default values, or an ELLIPSES.  For simplicities sake,
-   only parameters which are specified with their types can take on
-   default values.  */
+   We determine whether ellipsis parms are used by PARMLIST_ELLIPSIS_P
+   flag. If unset, we append void_list_node. A parmlist declared
+   as `(void)' is accepted as the empty parmlist.
+
+   Also set last_function_parms to the chain of PARM_DECLs.  */
 
 static tree
-grokparms (first_parm, funcdef_flag)
+grokparms (first_parm)
      tree first_parm;
-     int funcdef_flag;
 {
   tree result = NULL_TREE;
   tree decls = NULL_TREE;
+  int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
+  tree parm, chain;
+  int any_error = 0;
 
-  if (first_parm != NULL_TREE
-      && TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
-    {
-      if (! funcdef_flag)
-       pedwarn ("parameter names (without types) in function declaration");
-      last_function_parms = first_parm;
-      return NULL_TREE;
-    }
-  else if (first_parm != NULL_TREE
-          && TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST
-          && TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE)
-    my_friendly_abort (145);
-  else
-    {
-      /* Types were specified.  This is a list of declarators
-        each represented as a TREE_LIST node.  */
-      register tree parm, chain;
-      int any_init = 0, any_error = 0;
-
-      if (first_parm != NULL_TREE)
-       {
-         tree last_result = NULL_TREE;
-         tree last_decl = NULL_TREE;
+  my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
 
-         for (parm = first_parm; parm != NULL_TREE; parm = chain)
-           {
-             tree type = NULL_TREE, list_node = parm;
-             register tree decl = TREE_VALUE (parm);
-             tree init = TREE_PURPOSE (parm);
-
-             chain = TREE_CHAIN (parm);
-             /* @@ weak defense against parse errors.  */
-             if (TREE_CODE (decl) != VOID_TYPE
-                 && TREE_CODE (decl) != TREE_LIST)
-               {
-                 /* Give various messages as the need arises.  */
-                 if (TREE_CODE (decl) == STRING_CST)
-                   cp_error ("invalid string constant `%E'", decl);
-                 else if (TREE_CODE (decl) == INTEGER_CST)
-                   error ("invalid integer constant in parameter list, did you forget to give parameter name?");
-                 continue;
-               }
+  for (parm = first_parm; parm != NULL_TREE; parm = chain)
+    {
+      tree type = NULL_TREE;
+      register tree decl = TREE_VALUE (parm);
+      tree init = TREE_PURPOSE (parm);
+
+      chain = TREE_CHAIN (parm);
+      /* @@ weak defense against parse errors.  */
+      if (TREE_CODE (decl) != VOID_TYPE
+         && TREE_CODE (decl) != TREE_LIST)
+       {
+         /* Give various messages as the need arises.  */
+         if (TREE_CODE (decl) == STRING_CST)
+           cp_error ("invalid string constant `%E'", decl);
+         else if (TREE_CODE (decl) == INTEGER_CST)
+           error ("invalid integer constant in parameter list, did you forget to give parameter name?");
+         continue;
+       }
 
-             if (TREE_CODE (decl) != VOID_TYPE)
-               {
-                 decl = grokdeclarator (TREE_VALUE (decl),
-                                        TREE_PURPOSE (decl),
-                                        PARM, init != NULL_TREE,
-                                        NULL_TREE);
-                 if (! decl || TREE_TYPE (decl) == error_mark_node)
-                   continue;
-
-                 /* Top-level qualifiers on the parameters are
-                    ignored for function types.  */
-                 type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
-
-                 if (TREE_CODE (type) == VOID_TYPE)
-                   decl = void_type_node;
-                 else if (TREE_CODE (type) == METHOD_TYPE)
-                   {
-                     if (DECL_NAME (decl))
-                       /* Cannot use the decl here because
-                          we don't have DECL_CONTEXT set up yet.  */
-                       cp_error ("parameter `%D' invalidly declared method type",
-                                 DECL_NAME (decl));
-                     else
-                       error ("parameter invalidly declared method type");
-                     type = build_pointer_type (type);
-                     TREE_TYPE (decl) = type;
-                   }
-                 else if (TREE_CODE (type) == OFFSET_TYPE)
-                   {
-                     if (DECL_NAME (decl))
-                       cp_error ("parameter `%D' invalidly declared offset type",
-                                 DECL_NAME (decl));
-                     else
-                       error ("parameter invalidly declared offset type");
-                     type = build_pointer_type (type);
-                     TREE_TYPE (decl) = type;
-                   }
-                  else if (abstract_virtuals_error (decl, type))
-                   any_error = 1;  /* Seems like a good idea. */
-                 else if (POINTER_TYPE_P (type))
-                   {
-                     tree t = type;
-                     while (POINTER_TYPE_P (t)
-                            || (TREE_CODE (t) == ARRAY_TYPE
-                                && TYPE_DOMAIN (t) != NULL_TREE))
-                       t = TREE_TYPE (t);
-                     if (TREE_CODE (t) == ARRAY_TYPE)
-                       cp_error ("parameter type `%T' includes %s to array of unknown bound",
-                                 type,
-                                 TYPE_PTR_P (type) ? "pointer" : "reference");
-                   }
-               }
+      if (parm == void_list_node)
+        break;
 
-             if (TREE_CODE (decl) == VOID_TYPE)
-               {
-                 if (result == NULL_TREE)
-                   {
-                     result = void_list_node;
-                     last_result = result;
-                   }
-                 else
-                   {
-                     TREE_CHAIN (last_result) = void_list_node;
-                     last_result = void_list_node;
-                   }
-                 if (chain
-                     && (chain != void_list_node || TREE_CHAIN (chain)))
-                   error ("`void' in parameter list must be entire list");
-                 break;
-               }
+      decl = grokdeclarator (TREE_VALUE (decl), TREE_PURPOSE (decl),
+                    PARM, init != NULL_TREE, NULL_TREE);
+      if (! decl || TREE_TYPE (decl) == error_mark_node)
+        continue;
 
-             /* Since there is a prototype, args are passed in their own types.  */
-             DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
-             if (PROMOTE_PROTOTYPES
-                 && (TREE_CODE (type) == INTEGER_TYPE
-                     || TREE_CODE (type) == ENUMERAL_TYPE)
-                 && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-               DECL_ARG_TYPE (decl) = integer_type_node;
-             if (!any_error && init)
-               {
-                 any_init++;
-                 init = check_default_argument (decl, init);
-               }
-             else
-               init = NULL_TREE;
+      type = TREE_TYPE (decl);
+      if (VOID_TYPE_P (type))
+        {
+          if (same_type_p (type, void_type_node)
+              && !DECL_NAME (decl) && !result && !chain && !ellipsis)
+            /* this is a parmlist of `(void)', which is ok.  */
+            break;
+          incomplete_type_error (decl, type);
+         /* It's not a good idea to actually create parameters of
+            type `void'; other parts of the compiler assume that a
+            void type terminates the parameter list.  */
+         type = error_mark_node;
+         TREE_TYPE (decl) = error_mark_node;
+        }
 
-             if (decls == NULL_TREE)
-               {
-                 decls = decl;
-                 last_decl = decls;
-               }
-             else
-               {
-                 TREE_CHAIN (last_decl) = decl;
-                 last_decl = decl;
-               }
-             list_node = tree_cons (init, type, NULL_TREE);
-             if (result == NULL_TREE)
-               {
-                 result = list_node;
-                 last_result = result;
-               }
-             else
-               {
-                 TREE_CHAIN (last_result) = list_node;
-                 last_result = list_node;
-               }
+      if (type != error_mark_node)
+       {
+         /* Top-level qualifiers on the parameters are
+            ignored for function types.  */
+         type = TYPE_MAIN_VARIANT (type);
+         if (TREE_CODE (type) == METHOD_TYPE)
+           {
+             cp_error ("parameter `%D' invalidly declared method type", decl);
+             type = build_pointer_type (type);
+             TREE_TYPE (decl) = type;
+           }
+         else if (TREE_CODE (type) == OFFSET_TYPE)
+           {
+             cp_error ("parameter `%D' invalidly declared offset type", decl);
+             type = build_pointer_type (type);
+             TREE_TYPE (decl) = type;
+           }
+         else if (abstract_virtuals_error (decl, type))
+           any_error = 1;  /* Seems like a good idea. */
+         else if (POINTER_TYPE_P (type))
+           {
+             /* [dcl.fct]/6, parameter types cannot contain pointers
+                (references) to arrays of unknown bound.  */
+             tree t = TREE_TYPE (type);
+             int ptr = TYPE_PTR_P (type);
+
+              while (1)
+                {
+                  if (TYPE_PTR_P (t))
+                    ptr = 1;
+                  else if (TREE_CODE (t) != ARRAY_TYPE)
+                    break;
+                  else if (!TYPE_DOMAIN (t))
+                   break;
+                 t = TREE_TYPE (t);
+               }
+             if (TREE_CODE (t) == ARRAY_TYPE)
+               cp_error ("parameter `%D' includes %s to array of unknown bound `%T'",
+                         decl, ptr ? "pointer" : "reference", t);
            }
-         if (last_result)
-           TREE_CHAIN (last_result) = NULL_TREE;
-         /* If there are no parameters, and the function does not end
-            with `...', then last_decl will be NULL_TREE.  */
-         if (last_decl != NULL_TREE)
-           TREE_CHAIN (last_decl) = NULL_TREE;
+
+         DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+         if (PROMOTE_PROTOTYPES
+             && (TREE_CODE (type) == INTEGER_TYPE
+                 || TREE_CODE (type) == ENUMERAL_TYPE)
+             && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+           DECL_ARG_TYPE (decl) = integer_type_node;
+         if (!any_error && init)
+           init = check_default_argument (decl, init);
+         else
+           init = NULL_TREE;
        }
-    }
 
+      TREE_CHAIN (decl) = decls;
+      decls = decl;
+      result = tree_cons (init, type, result);
+    }
+  decls = nreverse (decls);
+  result = nreverse (result);
+  if (!ellipsis)
+    result = chainon (result, void_list_node);
   last_function_parms = decls;
 
   return result;
 }
 
-/* Called from the parser to update an element of TYPE_ARG_TYPES for some
-   FUNCTION_TYPE with the newly parsed version of its default argument, which
-   was previously digested as text.  See snarf_defarg et al in lex.c.  */
-
-void
-replace_defarg (arg, init)
-     tree arg, init;
-{
-  if (! processing_template_decl
-      && ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
-    cp_pedwarn ("invalid type `%T' for default argument to `%T'",
-               TREE_TYPE (init), TREE_VALUE (arg));
-  TREE_PURPOSE (arg) = init;
-}
 \f
 /* D is a constructor or overloaded `operator='.  Returns non-zero if
    D's arguments allow it to be a copy constructor, or copy assignment
@@ -12161,9 +11921,7 @@ copy_args_p (d)
   if (!DECL_FUNCTION_MEMBER_P (d))
     return 0;
 
-  t = FUNCTION_ARG_CHAIN (d);
-  if (DECL_CONSTRUCTOR_P (d) && DECL_HAS_IN_CHARGE_PARM_P (d))
-    t = TREE_CHAIN (t);
+  t = FUNCTION_FIRST_USER_PARMTYPE (d);
   if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
       && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
          == DECL_CONTEXT (d))
@@ -12186,22 +11944,9 @@ int
 grok_ctor_properties (ctype, decl)
      tree ctype, decl;
 {
-  tree parmtypes = FUNCTION_ARG_CHAIN (decl);
+  tree parmtypes = FUNCTION_FIRST_USER_PARMTYPE (decl);
   tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
 
-  /* When a type has virtual baseclasses, a magical first int argument is
-     added to any ctor so we can tell if the class has been initialized
-     yet.  This could screw things up in this function, so we deliberately
-     ignore the leading int if we're in that situation.  */
-  if (DECL_HAS_IN_CHARGE_PARM_P (decl))
-    {
-      my_friendly_assert (parmtypes
-                         && TREE_VALUE (parmtypes) == integer_type_node,
-                         980529);
-      parmtypes = TREE_CHAIN (parmtypes);
-      parmtype = TREE_VALUE (parmtypes);
-    }
-
   /* [class.copy]
 
      A non-template constructor for class X is a copy constructor if
@@ -12210,9 +11955,7 @@ grok_ctor_properties (ctype, decl)
      other parameters have default arguments.  */
   if (TREE_CODE (parmtype) == REFERENCE_TYPE
       && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
-      && (TREE_CHAIN (parmtypes) == NULL_TREE
-         || TREE_CHAIN (parmtypes) == void_list_node
-         || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+      && sufficient_parms_p (TREE_CHAIN (parmtypes))
       && !(DECL_TEMPLATE_INSTANTIATION (decl)
           && is_member_template (DECL_TI_TEMPLATE (decl))))
     {
@@ -12236,9 +11979,7 @@ grok_ctor_properties (ctype, decl)
      existence.  Theoretically, they should never even be
      instantiated, but that's hard to forestall.  */
   else if (TYPE_MAIN_VARIANT (parmtype) == ctype
-          && (TREE_CHAIN (parmtypes) == NULL_TREE
-              || TREE_CHAIN (parmtypes) == void_list_node
-              || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+          && sufficient_parms_p (TREE_CHAIN (parmtypes))
           && !(DECL_TEMPLATE_INSTANTIATION (decl)
                && is_member_template (DECL_TI_TEMPLATE (decl))))
     {
@@ -12337,7 +12078,7 @@ grok_op_properties (decl, virtualp, friendp)
        case CALL_EXPR:
          TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
          break;
-         
+
        case ARRAY_REF:
          TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
          break;
@@ -12346,19 +12087,19 @@ grok_op_properties (decl, virtualp, friendp)
        case MEMBER_REF:
          TYPE_OVERLOADS_ARROW (current_class_type) = 1;
          break;
-         
+
        case NEW_EXPR:
          TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
          break;
-         
+
        case DELETE_EXPR:
          TYPE_GETS_DELETE (current_class_type) |= 1;
          break;
-         
+
        case VEC_NEW_EXPR:
          TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
          break;
-         
+
        case VEC_DELETE_EXPR:
          TYPE_GETS_DELETE (current_class_type) |= 2;
          break;
@@ -12375,27 +12116,14 @@ grok_op_properties (decl, virtualp, friendp)
       if (methodp)
        revert_static_member_fn (decl);
 
-      /* Take care of function decl if we had syntax errors.  */
-      if (argtypes == NULL_TREE)
-       TREE_TYPE (decl)
-         = build_function_type (ptr_type_node,
-                                hash_tree_chain (integer_type_node,
-                                                 void_list_node));
-      else
-       TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
+      TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
     }
   else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
     {
       if (methodp)
        revert_static_member_fn (decl);
 
-      if (argtypes == NULL_TREE)
-       TREE_TYPE (decl)
-         = build_function_type (void_type_node,
-                                hash_tree_chain (ptr_type_node,
-                                                 void_list_node));
-      else
-       TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
+      TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
     }
   else
     {
@@ -12428,7 +12156,7 @@ grok_op_properties (decl, virtualp, friendp)
                    if (IS_AGGR_TYPE (arg)
                        || TREE_CODE (arg) == ENUMERAL_TYPE
                        || TREE_CODE (arg) == TEMPLATE_TYPE_PARM
-                       || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
+                       || TREE_CODE (arg) == BOUND_TEMPLATE_TEMPLATE_PARM)
                      goto foundaggr;
                  }
              cp_error
@@ -12449,7 +12177,7 @@ grok_op_properties (decl, virtualp, friendp)
            {
              int ref = (TREE_CODE (t) == REFERENCE_TYPE);
              const char *what = 0;
-             
+
              if (ref)
                t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
 
@@ -12469,7 +12197,7 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
 
-      if (DECL_ASSIGNMENT_OPERATOR_P (decl) 
+      if (DECL_ASSIGNMENT_OPERATOR_P (decl)
          && operator_code == NOP_EXPR)
        {
          tree parmtype;
@@ -12734,8 +12462,24 @@ 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) != TEMPLATE_TEMPLATE_PARM)
+      && TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
     t = NULL_TREE;
 
   if (! globalize)
@@ -12981,7 +12725,7 @@ xref_basetypes (code_type_node, name, ref, binfo)
          || (TREE_CODE (basetype) != RECORD_TYPE
              && TREE_CODE (basetype) != TYPENAME_TYPE
              && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
-             && TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM))
+             && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
        {
          cp_error ("base type `%T' fails to be a struct or class type",
                    TREE_VALUE (binfo));
@@ -13053,9 +12797,9 @@ xref_basetypes (code_type_node, name, ref, binfo)
 
          if (CLASS_TYPE_P (basetype))
            {
-             TYPE_HAS_NEW_OPERATOR (ref) 
+             TYPE_HAS_NEW_OPERATOR (ref)
                |= TYPE_HAS_NEW_OPERATOR (basetype);
-             TYPE_HAS_ARRAY_NEW_OPERATOR (ref) 
+             TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
                |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
              TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
              /* If the base-class uses multiple inheritance, so do we.  */
@@ -13217,7 +12961,7 @@ finish_enum (enumtype)
     {
       tree scope = current_scope ();
       if (scope && TREE_CODE (scope) == FUNCTION_DECL)
-       add_tree (build_min (TAG_DEFN, enumtype));
+       add_stmt (build_min (TAG_DEFN, enumtype));
     }
   else
     {
@@ -13371,7 +13115,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
@@ -13401,8 +13145,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));
@@ -13444,9 +13189,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.
@@ -13473,6 +13216,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);
@@ -13481,7 +13225,7 @@ start_function (declspecs, declarator, attrs, flags)
   /* This should only be done once on the top most decl.  */
   if (have_extern_spec && !used_extern_spec)
     {
-      declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
+      declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
       used_extern_spec = 1;
     }
 
@@ -13582,7 +13326,7 @@ start_function (declspecs, declarator, attrs, flags)
   if (flags & SF_INCLASS_INLINE)
     maybe_begin_member_template_processing (decl1);
 
-  /* Effective C++ rule 15.  See also c_expand_return.  */
+  /* Effective C++ rule 15.  */
   if (warn_ecpp
       && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
@@ -13620,7 +13364,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);
@@ -13641,11 +13385,11 @@ start_function (declspecs, declarator, attrs, flags)
   /* Initialize RTL machinery.  We cannot do this until
      CURRENT_FUNCTION_DECL and DECL_RESULT are set up.  We do this
      even when processing a template; this is how we get
-     CFUN set up, and our per-function variables initialized.  */
+     CFUN set up, and our per-function variables initialized.
+     FIXME factor out the non-RTL stuff.  */
   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.
@@ -13654,9 +13398,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);
@@ -13685,29 +13428,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
@@ -13726,8 +13456,18 @@ start_function (declspecs, declarator, attrs, flags)
 
       /* Constructors and destructors need to know whether they're "in
         charge" of initializing virtual base classes.  */
+      t = TREE_CHAIN (t);
       if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
-       current_in_charge_parm = TREE_CHAIN (t);
+       {
+         current_in_charge_parm = t;
+         t = TREE_CHAIN (t);
+       }
+      if (DECL_HAS_VTT_PARM_P (decl1))
+       {
+         if (DECL_NAME (t) != vtt_parm_identifier)
+           abort ();
+         current_vtt_parm = t;
+       }
     }
 
   if (DECL_INTERFACE_KNOWN (decl1))
@@ -13795,20 +13535,15 @@ 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);
-      make_function_rtl (decl1);
-    }
+  /* We need to do this even if we aren't expanding yet so that
+     assemble_external works.  */
+  make_decl_rtl (decl1, NULL);
 
   /* Promote the value to int before returning it.  */
   if (C_PROMOTING_INTEGER_TYPE_P (restype))
@@ -13834,36 +13569,21 @@ start_function (declspecs, declarator, attrs, flags)
       dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
       DECL_CONTEXT (dtor_label) = current_function_decl;
     }
-  /* Under the old ABI we return `this' from constructors, so we make
-     ordinary `return' statements in constructors jump to CTOR_LABEL;
-     from there we return `this'.  Under the new ABI, we don't bother
-     with any of this.  By not setting CTOR_LABEL the remainder of the
-     machinery is automatically disabled.  */
-  else if (!flag_new_abi && DECL_CONSTRUCTOR_P (decl1))
-    {
-      ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-      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;
@@ -13878,10 +13598,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.
@@ -13892,45 +13608,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);
-
-             if (doing_semantic_analysis_p ())
-               {
-                 tree cleanup;
+             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
            {
@@ -13941,14 +13646,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;
@@ -13957,20 +13659,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
@@ -13983,48 +13672,17 @@ 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 ();
 }
 
-/* Bind a name and initialization to the return value of
-   the current function.  */
-
-void
-store_return_init (decl)
-     tree decl;
-{
-  /* If this named return value comes in a register, put it in a
-     pseudo-register.  */
-  if (DECL_REGISTER (decl))
-    {
-      original_result_rtx = DECL_RTL (decl);
-      /* 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 (original_result_rtx));
-      if (TREE_ADDRESSABLE (decl))
-       put_var_into_stack (decl);
-    }
-}
-
 \f
 /* We have finished doing semantic analysis on DECL, but have not yet
    generated RTL for its body.  Save away our current state, so that
@@ -14034,7 +13692,7 @@ static void
 save_function_data (decl)
      tree decl;
 {
-  struct language_function *f;
+  struct cp_language_function *f;
 
   /* Save the language-specific per-function data so that we can
      get it back when we really expand this function.  */
@@ -14042,16 +13700,14 @@ save_function_data (decl)
                      19990908);
 
   /* Make a copy.  */
-  f = ((struct language_function *)
-       xmalloc (sizeof (struct language_function)));
-  bcopy ((char *) cp_function_chain, (char *) f,
-        sizeof (struct language_function));
+  f = ((struct cp_language_function *)
+       xmalloc (sizeof (struct cp_language_function)));
+  memcpy (f, cp_function_chain, sizeof (struct cp_language_function));
   DECL_SAVED_FUNCTION_DATA (decl) = f;
 
   /* Clear out the bits we don't need.  */
-  f->x_stmt_tree.x_last_stmt = NULL_TREE;
-  f->x_stmt_tree.x_last_expr_type = NULL_TREE;
-  f->x_result_rtx = NULL_RTX;
+  f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
+  f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
   f->x_named_label_uses = NULL;
   f->bindings = NULL;
 
@@ -14072,7 +13728,7 @@ finish_constructor_body ()
 {
   /* Any return from a constructor will end up here.  */
   if (ctor_label)
-    add_tree (build_stmt (LABEL_STMT, ctor_label));
+    add_stmt (build_stmt (LABEL_STMT, ctor_label));
 
   /* Clear CTOR_LABEL so that finish_return_stmt knows to really
      generate the return, rather than a goto to CTOR_LABEL.  */
@@ -14081,7 +13737,7 @@ finish_constructor_body ()
      constructor to a return of `this'.  */
   finish_return_stmt (NULL_TREE);
   /* Mark the end of the constructor.  */
-  add_tree (build_stmt (CTOR_STMT));
+  add_stmt (build_stmt (CTOR_STMT));
 }
 
 /* At the end of every destructor we generate code to restore virtual
@@ -14092,15 +13748,13 @@ static void
 finish_destructor_body ()
 {
   tree compound_stmt;
-  tree virtual_size;
   tree exprstmt;
-  tree if_stmt;
 
   /* Create a block to contain all the extra code.  */
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
 
   /* Any return from a destructor will end up here.  */
-  add_tree (build_stmt (LABEL_STMT, dtor_label));
+  add_stmt (build_stmt (LABEL_STMT, dtor_label));
 
   /* Generate the code to call destructor on base class.  If this
      destructor belongs to a class with virtual functions, then set
@@ -14148,16 +13802,26 @@ finish_destructor_body ()
               vbases = TREE_CHAIN (vbases))
            {
              tree vbase = TREE_VALUE (vbases);
+             tree base_type = BINFO_TYPE (vbase);
 
-             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbase)))
+             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
                {
-                 tree vb = get_vbase
-                   (BINFO_TYPE (vbase),
-                    TYPE_BINFO (current_class_type));
-                 finish_expr_stmt
-                   (build_scoped_method_call
-                    (current_class_ref, vb, base_dtor_identifier,
-                     NULL_TREE));
+                  tree base_ptr_type = build_pointer_type (base_type);
+                 tree expr = current_class_ptr;
+                 
+                 /* Convert to the basetype here, as we know the layout is
+                     fixed. What is more, if we let build_method_call do it,
+                     it will use the vtable, which may have been clobbered
+                     by the deletion of our primary base.  */
+                  
+                  expr = build1 (NOP_EXPR, base_ptr_type, expr);
+                 expr = build (PLUS_EXPR, base_ptr_type, expr,
+                               BINFO_OFFSET (vbase));
+                 expr = build_indirect_ref (expr, NULL);
+                 expr = build_method_call (expr, base_dtor_identifier,
+                                           NULL_TREE, vbase,
+                                           LOOKUP_NORMAL);
+                 finish_expr_stmt (expr);
                }
            }
 
@@ -14166,31 +13830,31 @@ finish_destructor_body ()
        }
     }
 
-  virtual_size = c_sizeof (current_class_type);
-
-  /* At the end, call delete if that's what's requested.  */
+  /* In a virtual destructor, we must call delete.  */
+  if (DECL_VIRTUAL_P (current_function_decl))
+    {
+      tree if_stmt;
+      tree virtual_size = c_sizeof (current_class_type);
 
-  /* FDIS sez: At the point of definition of a virtual destructor
-     (including an implicit definition), non-placement operator delete
-     shall be looked up in the scope of the destructor's class and if
-     found shall be accessible and unambiguous.
+      /* [class.dtor]
 
-     This is somewhat unclear, but I take it to mean that if the class
-     only defines placement deletes we don't do anything here.  So we
-     pass LOOKUP_SPECULATIVELY; delete_sanity will complain for us if
-     they ever try to delete one of these.  */
-  exprstmt = build_op_delete_call
-    (DELETE_EXPR, current_class_ptr, virtual_size,
-     LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+        At the point of definition of a virtual destructor (including
+        an implicit definition), non-placement operator delete shall
+        be looked up in the scope of the destructor's class and if
+        found shall be accessible and unambiguous.  */
+      exprstmt = build_op_delete_call
+       (DELETE_EXPR, current_class_ptr, virtual_size,
+        LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
 
-  if_stmt = begin_if_stmt ();
-  finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
-                             current_in_charge_parm,
-                             integer_one_node),
-                      if_stmt);
-  finish_expr_stmt (exprstmt);
-  finish_then_clause (if_stmt);
-  finish_if_stmt ();
+      if_stmt = begin_if_stmt ();
+      finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
+                                 current_in_charge_parm,
+                                 integer_one_node),
+                          if_stmt);
+      finish_expr_stmt (exprstmt);
+      finish_then_clause (if_stmt);
+      finish_if_stmt ();
+    }
 
   /* Close the block we started above.  */
   finish_compound_stmt (/*has_no_scope=*/0, compound_stmt);
@@ -14216,13 +13880,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.  */
@@ -14236,18 +13896,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))
        {
@@ -14275,132 +13928,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)
@@ -14414,7 +13951,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
@@ -14426,84 +13963,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 (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
@@ -14518,35 +13986,12 @@ 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;
-    }
-
-  if (DECL_STATIC_CONSTRUCTOR (fndecl))
-    static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
-  if (DECL_STATIC_DESTRUCTOR (fndecl))
-    static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
-
   /* Clean up.  */
   if (! nested)
-    {
-      /* 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;
-      /* We don't really care about obstacks, but the middle-end
-        sometimes cares on what obstck things are located.  */
-      permanent_allocation (1);
-    }
+    /* 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;
 
   return fndecl;
 }
@@ -14597,8 +14042,8 @@ start_method (declspecs, declarator, attrlist)
        {
          if (DECL_CONTEXT (fndecl)
              && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
-           cp_error ("`%D' is already defined in class %s", fndecl,
-                            TYPE_NAME_STRING (DECL_CONTEXT (fndecl)));
+           cp_error ("`%D' is already defined in class `%T'", fndecl,
+                     DECL_CONTEXT (fndecl));
        }
       return void_type_node;
     }
@@ -14816,31 +14261,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
@@ -14866,7 +14286,7 @@ revert_static_member_fn (decl)
   if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
       != TYPE_UNQUALIFIED)
     cp_error ("static member function `%#D' declared with type qualifiers",
-             *decl);
+             decl);
 
   args = TREE_CHAIN (args);
   tmp = build_function_type (TREE_TYPE (function), args);
@@ -14886,10 +14306,10 @@ static void
 push_cp_function_context (f)
      struct function *f;
 {
-  struct language_function *p
-    = ((struct language_function *)
-       xcalloc (1, sizeof (struct language_function)));
-  f->language = p;
+  struct cp_language_function *p
+    = ((struct cp_language_function *)
+       xcalloc (1, sizeof (struct cp_language_function)));
+  f->language = (struct language_function *) p;
 
   /* It takes an explicit call to expand_body to generate RTL for a
      function.  */
@@ -14897,7 +14317,7 @@ push_cp_function_context (f)
 
   /* Whenever we start a new function, we destroy temporaries in the
      usual way.  */
-  current_stmt_tree->stmts_are_full_exprs_p = 1;
+  current_stmt_tree ()->stmts_are_full_exprs_p = 1;
 }
 
 /* Free the language-specific parts of F, now that we've finished
@@ -14912,26 +14332,37 @@ pop_cp_function_context (f)
   f->language = 0;
 }
 
+/* Mark I for GC.  */
+
+static void
+mark_inlined_fns (i)
+     struct lang_decl_inlined_fns *i;
+{
+  int n;
+
+  for (n = i->num_fns - 1; n >= 0; n--)
+    ggc_mark_tree (i->fns [n]);
+  ggc_set_mark (i);
+}
+
 /* Mark P for GC.  */
 
 static void
 mark_lang_function (p)
-     struct language_function *p;
+     struct cp_language_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->x_stmt_tree);
   mark_binding_level (&p->bindings);
 }
 
@@ -14941,15 +14372,7 @@ static void
 mark_cp_function_context (f)
      struct function *f;
 {
-  mark_lang_function (f->language);
-}
-
-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);
+  mark_lang_function ((struct cp_language_function *) f->language);
 }
 
 void
@@ -14992,13 +14415,13 @@ lang_mark_tree (t)
       if (ld)
        {
          ggc_mark (ld);
-         if (!DECL_GLOBAL_CTOR_P (t) 
+         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
@@ -15006,10 +14429,10 @@ 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);
+             if (ld->inlined_fns)
+               mark_inlined_fns (ld->inlined_fns);
              if (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
@@ -15044,3 +14467,30 @@ lang_mark_tree (t)
        ggc_mark_tree ((tree) lt);
     }
 }
+
+/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
+   the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++.  */
+
+tree
+identifier_global_value        (t)
+     tree t;
+{
+  return IDENTIFIER_GLOBAL_VALUE (t);
+}
+
+/* Build the void_list_node (void_type_node having been created).  */
+tree
+build_void_list_node ()
+{
+  tree t = build_tree_list (NULL_TREE, void_type_node);
+  TREE_PARMLIST (t) = 1;
+  return t;
+}
+
+static int
+cp_missing_noreturn_ok_p (decl)
+     tree decl;
+{
+  /* A missing noreturn is ok for the `main' function.  */
+  return MAIN_NAME_P (DECL_ASSEMBLER_NAME (decl));
+}