OSDN Git Service

* cp/cp-tree.h (struct cp_language_function): Remove x_result_rtx.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index d9385f5..82ebc36 100644 (file)
@@ -32,23 +32,20 @@ Boston, MA 02111-1307, USA.  */
 #include "system.h"
 #include "tree.h"
 #include "rtl.h"
+#include "expr.h"
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
 #include "lex.h"
-#include <signal.h>
 #include "defaults.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
 #include "../hash.h"
-#include "defaults.h"
 #include "ggc.h"
 
 extern int current_class_depth;
 
-extern tree static_ctors, static_dtors;
-
 extern tree global_namespace;
 
 extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
@@ -57,14 +54,6 @@ extern int (*valid_lang_attribute) PARAMS ((tree, tree, tree, tree));
 
 int ggc_p = 1;
 
-#ifndef WCHAR_UNSIGNED
-#define WCHAR_UNSIGNED 0
-#endif
-
-#ifndef CHAR_TYPE_SIZE
-#define CHAR_TYPE_SIZE BITS_PER_UNIT
-#endif
-
 #ifndef BOOL_TYPE_SIZE
 #ifdef SLOW_BYTE_ACCESS
 /* In the new ABI, `bool' has size and alignment `1', on all
@@ -104,15 +93,14 @@ static void suspend_binding_level PARAMS ((void));
 static void resume_binding_level PARAMS ((struct binding_level *));
 static struct binding_level *make_binding_level PARAMS ((void));
 static void declare_namespace_level PARAMS ((void));
-static void signal_catch PARAMS ((int)) ATTRIBUTE_NORETURN;
+static int decl_jump_unsafe PARAMS ((tree));
 static void storedecls PARAMS ((tree));
 static void require_complete_types_for_parms PARAMS ((tree));
-static int ambi_op_p PARAMS ((tree));
-static int unary_op_p PARAMS ((tree));
+static int ambi_op_p PARAMS ((enum tree_code));
+static int unary_op_p PARAMS ((enum tree_code));
 static tree store_bindings PARAMS ((tree, tree));
 static tree lookup_tag_reverse PARAMS ((tree, tree));
 static tree obscure_complex_init PARAMS ((tree, tree));
-static tree maybe_build_cleanup_1 PARAMS ((tree, tree));
 static tree lookup_name_real PARAMS ((tree, int, int, int));
 static void warn_extern_redeclared_static PARAMS ((tree, tree));
 static void grok_reference_init PARAMS ((tree, tree, tree));
@@ -126,11 +114,10 @@ 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, tree));
+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));
@@ -152,7 +139,13 @@ static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
 static int walk_globals_r PARAMS ((tree, void *));
 static void add_decl_to_level PARAMS ((tree, struct binding_level *));
 static tree make_label_decl PARAMS ((tree, int));
-static void pop_label PARAMS ((tree));
+static void use_label PARAMS ((tree));
+static void check_previous_goto_1 PARAMS ((tree, struct binding_level *, tree,
+                                          const char *, int));
+static void check_previous_goto PARAMS ((struct named_label_use_list *));
+static void check_switch_goto PARAMS ((struct binding_level *));
+static void check_previous_gotos PARAMS ((tree));
+static void pop_label PARAMS ((tree, tree));
 static void pop_labels PARAMS ((tree));
 static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
 static void layout_var_decl PARAMS ((tree));
@@ -162,12 +155,12 @@ static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
 static void push_cp_function_context PARAMS ((struct function *));
 static void pop_cp_function_context PARAMS ((struct function *));
 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));
@@ -180,6 +173,9 @@ 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 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));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PARAMS ((void));
@@ -193,7 +189,6 @@ tree error_mark_list;
 
    C++ extensions
        tree wchar_decl_node;
-       tree void_zero_node;
 
        tree vtable_entry_type;
        tree delta_type_node;
@@ -211,7 +206,7 @@ tree error_mark_list;
        tree bltn_desc_type_node, ptr_desc_type_node;
        tree ary_desc_type_node, func_desc_type_node, enum_desc_type_node;
        tree class_desc_type_node, si_class_desc_type_node, vmi_class_desc_type_node;
-       tree ptmd_desc_type_node;
+       tree ptm_desc_type_node;
        tree base_desc_type_node;
 #if 0
    Not needed yet?  May be needed one day?
@@ -262,26 +257,19 @@ int in_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.  */
 
-struct named_label_list
+struct named_label_use_list
 {
   struct binding_level *binding_level;
   tree names_in_scope;
   tree label_decl;
   const char *filename_o_goto;
   int lineno_o_goto;
-  struct named_label_list *next;
+  struct named_label_use_list *next;
 };
 
-/* Used only for jumps to as-yet undefined labels, since jumps to
-   defined labels can have their validity checked by stmt.c.  */
-
 #define named_label_uses cp_function_chain->x_named_label_uses
 
 /* A list of objects which have constructors or destructors
@@ -305,10 +293,20 @@ static tree last_function_parm_tags;
 tree last_function_parms;
 static tree current_function_parm_tags;
 
-/* A list (chain of TREE_LIST nodes) of all LABEL_DECLs in the function
-   that have names.  Here so we can clear out their names' definitions
-   at the end of the function.  The TREE_VALUE is a LABEL_DECL; the
-   TREE_PURPOSE is the previous binding of the label.  */
+/* A list of all LABEL_DECLs in the function that have names.  Here so
+   we can clear out their names' definitions at the end of the
+   function, and so we can check the validity of jumps to these labels.  */
+
+struct named_label_list
+{
+  struct binding_level *binding_level;
+  tree names_in_scope;
+  tree old_value;
+  tree label_decl;
+  tree bad_decls;
+  int eh_region;
+  struct named_label_list *next;
+};
 
 #define named_labels cp_function_chain->x_named_labels
 
@@ -319,10 +317,23 @@ static tree current_function_parm_tags;
 
 tree current_function_return_value;
 
+/* Nonzero means use the ISO C94 dialect of C.  */
+
+int flag_isoc94;
+
 /* Nonzero means use the ISO C99 dialect of C.  */
 
 int flag_isoc99;
 
+/* Nonzero means we are a hosted implementation for code shared with C.  */
+
+int flag_hosted = 1;
+
+/* Nonzero means add default format_arg attributes for functions not
+   in ISO C.  */
+
+int flag_noniso_default_format_attributes = 1;
+
 /* Nonzero means give `double' the same size as `float'.  */
 
 extern int flag_short_double;
@@ -356,6 +367,10 @@ tree signed_size_zero_node;
    unit.  */
 tree anonymous_namespace_name;
 
+/* The number of function bodies which we are currently processing.
+   (Zero if we are at namespace scope, one inside the body of a
+   function, two inside the body of a function in a local class, etc.)  */
+int function_depth;
 \f
 /* For each binding contour we allocate a binding_level structure
    which records the names defined in that contour.
@@ -429,10 +444,6 @@ struct binding_level
        that were entered and exited one level down.  */
     tree blocks;
 
-    /* The BLOCK node for this level, if one has been preallocated.
-       If 0, the BLOCK is allocated (if needed) when the level is popped.  */
-    tree this_block;
-
     /* The _TYPE node for this level, if parm_flag == 2.  */
     tree this_class;
 
@@ -482,7 +493,9 @@ struct binding_level
        worry about ambiguous (ARM or ISO) scope rules.  */
     unsigned is_for_scope : 1;
 
-    /* True if this level corresponds to an EH region, as for a try block.  */
+    /* True if this level corresponds to an EH region, as for a try block.
+       Currently this information is only available while building the
+       tree structure.  */
     unsigned eh_region : 1;
 
     /* Four bits left for this word.  */
@@ -549,11 +562,6 @@ push_binding_level (newlevel, tag_transparent, keep)
   newlevel->tag_transparent = tag_transparent;
   newlevel->more_cleanups_ok = 1;
 
-  /* We are called before expand_start_bindings, but after
-     expand_eh_region_start for a try block; so we check this now,
-     before the EH block is covered up.  */
-  newlevel->eh_region = is_eh_region ();
-
   newlevel->keep = keep;
 #if defined(DEBUG_CP_BINDING_LEVELS)
   newlevel->binding_depth = binding_depth;
@@ -928,6 +936,14 @@ note_level_for_for ()
   current_binding_level->is_for_scope = 1;
 }
 
+/* Record that the current binding level represents a try block.  */
+
+void
+note_level_for_eh ()
+{
+  current_binding_level->eh_region = 1;
+}
+
 /* For a binding between a name and an entity at a block scope,
    this is the `struct binding_level' for the block.  */
 #define BINDING_LEVEL(NODE) \
@@ -1007,6 +1023,16 @@ add_binding (id, decl)
         the name of any type declared in that scope to refer to the
         type to which it already refers.  */
     ok = 0;
+  /* There can be two block-scope declarations of the same variable,
+     so long as they are `extern' declarations.  */
+  else if (TREE_CODE (decl) == VAR_DECL
+          && TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
+          && DECL_EXTERNAL (decl)
+          && DECL_EXTERNAL (BINDING_VALUE (binding)))
+    {
+      duplicate_decls (decl, BINDING_VALUE (binding));
+      ok = 0;
+    }
   else
     {
       cp_error ("declaration of `%#D'", decl);
@@ -1181,11 +1207,10 @@ pop_binding (id, decl)
    in a valid manner, and issue any appropriate warnings or errors.  */
 
 static void
-pop_label (link)
-     tree link;
+pop_label (label, old_value)
+     tree label;
+     tree old_value;
 {
-  tree label = TREE_VALUE (link);
-
   if (!processing_template_decl && doing_semantic_analysis_p ())
     {
       if (DECL_INITIAL (label) == NULL_TREE)
@@ -1194,14 +1219,14 @@ pop_label (link)
          /* Avoid crashing later.  */
          define_label (input_filename, 1, DECL_NAME (label));
        }
-      else if (warn_unused && !TREE_USED (label))
+      else if (warn_unused_label && !TREE_USED (label))
        cp_warning_at ("label `%D' defined but not used", label);
     }
 
-  SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), TREE_PURPOSE (link));
+  SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
 }
 
-/* At the end of a function, all labels declared within the fucntion
+/* At the end of a function, all labels declared within the function
    go out of scope.  BLOCK is the top-level block for the
    function.  */
 
@@ -1209,20 +1234,20 @@ static void
 pop_labels (block)
      tree block;
 {
-  tree link;
+  struct named_label_list *link;
 
   /* Clear out the definitions of all label names, since their scopes
      end here.  */
-  for (link = named_labels; link; link = TREE_CHAIN (link))
+  for (link = named_labels; link; link = link->next)
     {
-      pop_label (link);
+      pop_label (link->label_decl, link->old_value);
       /* Put the labels into the "variables" of the top-level block,
         so debugger can see them.  */
-      TREE_CHAIN (TREE_VALUE (link)) = BLOCK_VARS (block);
-      BLOCK_VARS (block) = TREE_VALUE (link);
+      TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
+      BLOCK_VARS (block) = link->label_decl;
     }
 
-  named_labels = NULL_TREE;
+  named_labels = NULL;
 }
 
 /* Exit a binding level.
@@ -1256,7 +1281,6 @@ poplevel (keep, reverse, functionbody)
   tree subblocks;
   tree block = NULL_TREE;
   tree decl;
-  int block_previously_created;
   int leaving_for_scope;
 
   if (cfun && !doing_semantic_analysis_p ())
@@ -1286,6 +1310,40 @@ poplevel (keep, reverse, functionbody)
   if (current_binding_level->keep == 1)
     keep = 1;
 
+  /* Any uses of undefined labels, and any defined labels, now operate
+     under constraints of next binding contour.  */
+  if (cfun && !functionbody)
+    {
+      struct binding_level *level_chain;
+      level_chain = current_binding_level->level_chain;
+      if (level_chain)
+       {
+         struct named_label_use_list *uses;
+         struct named_label_list *labels;
+         for (labels = named_labels; labels; labels = labels->next)
+           if (labels->binding_level == current_binding_level)
+             {
+               tree decl;
+               if (current_binding_level->eh_region)
+                 labels->eh_region = 1;
+               for (decl = labels->names_in_scope; decl;
+                    decl = TREE_CHAIN (decl))
+                 if (decl_jump_unsafe (decl))
+                   labels->bad_decls = tree_cons (NULL_TREE, decl,
+                                                  labels->bad_decls);
+               labels->binding_level = level_chain;
+               labels->names_in_scope = level_chain->names;
+             }
+
+         for (uses = named_label_uses; uses; uses = uses->next)
+           if (uses->binding_level == current_binding_level)
+             {
+               uses->binding_level = level_chain;
+               uses->names_in_scope = level_chain->names;
+             }
+       }
+    }
+
   /* Get the decls in the order they were written.
      Usually current_binding_level->names is in reverse order.
      But parameter decls were previously put in forward order.  */
@@ -1330,34 +1388,12 @@ poplevel (keep, reverse, functionbody)
      or if this level is a function body,
      create a BLOCK to record them for the life of this function.  */
   block = NULL_TREE;
-  block_previously_created = (current_binding_level->this_block != NULL_TREE);
-  if (block_previously_created)
-    block = current_binding_level->this_block;
-  else if (keep == 1 || functionbody)
+  if (keep == 1 || functionbody)
     block = make_node (BLOCK);
   if (block != NULL_TREE)
     {
-      if (block_previously_created)
-       {
-         if (decls || tags || subblocks)
-           {
-             if (BLOCK_VARS (block))
-               warning ("internal compiler error: debugging info corrupted");
-
-             BLOCK_VARS (block) = decls;
-
-             /* We can have previous subblocks and new subblocks when
-                doing fixup_gotos with complex cleanups.  We chain the new
-                subblocks onto the end of any pre-existing subblocks.  */
-             BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
-                                                subblocks);
-           }
-       }
-      else
-       {
-         BLOCK_VARS (block) = decls;
-         BLOCK_SUBBLOCKS (block) = subblocks;
-       }
+      BLOCK_VARS (block) = decls;
+      BLOCK_SUBBLOCKS (block) = subblocks;
     }
 
   /* In each subblock, record that this is its superior.  */
@@ -1375,7 +1411,8 @@ poplevel (keep, reverse, functionbody)
   /* Remove declarations for all the DECLs in this level.  */
   for (link = decls; link; link = TREE_CHAIN (link))
     {
-      if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
+      if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
+          && DECL_NAME (link))
        {
          tree outer_binding
            = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
@@ -1469,7 +1506,7 @@ poplevel (keep, reverse, functionbody)
   for (link = current_binding_level->shadowed_labels;
        link;
        link = TREE_CHAIN (link))
-    pop_label (link);
+    pop_label (TREE_VALUE (link), TREE_PURPOSE (link));
 
   /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
      list if a `using' declaration put them there.  The debugging
@@ -1501,35 +1538,15 @@ poplevel (keep, reverse, functionbody)
       pop_labels (block);
     }
 
-  /* Any uses of undefined labels now operate under constraints
-     of next binding contour.  */
-  if (cfun)
-    {
-      struct binding_level *level_chain;
-      level_chain = current_binding_level->level_chain;
-      if (level_chain)
-       {
-         struct named_label_list *labels;
-         for (labels = named_label_uses; labels; labels = labels->next)
-           if (labels->binding_level == current_binding_level)
-             {
-               labels->binding_level = level_chain;
-               labels->names_in_scope = level_chain->names;
-             }
-       }
-    }
-
   tmp = current_binding_level->keep;
 
   pop_binding_level ();
   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)
@@ -1606,9 +1623,11 @@ insert_block (block)
 
 void
 set_block (block)
-    register tree block;
+    tree block ATTRIBUTE_UNUSED;
 {
-  current_binding_level->this_block = block;
+  /* The RTL expansion machinery requires us to provide this callback,
+     but it is not applicable in function-at-a-time mode.  */
+  my_friendly_assert (cfun && !doing_semantic_analysis_p (), 20000911);
 }
 
 /* Do a pushlevel for class declarations.  */
@@ -1952,7 +1971,7 @@ mark_binding_level (arg)
 {
   struct binding_level *lvl = *(struct binding_level **)arg;
 
-  while (lvl)
+  for (; lvl; lvl = lvl->level_chain)
     {
       ggc_mark_tree (lvl->names);
       ggc_mark_tree (lvl->tags);
@@ -1962,13 +1981,31 @@ 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);
+    }
+}
 
-      lvl = lvl->level_chain;
+static void
+mark_named_label_lists (labs, uses)
+     void *labs;
+     void *uses;
+{
+  struct named_label_list *l = *(struct named_label_list **)labs;
+  struct named_label_use_list *u = *(struct named_label_use_list **)uses;
+
+  for (; l; l = l->next)
+    {
+      ggc_mark (l);
+      mark_binding_level (l->binding_level);
+      ggc_mark_tree (l->old_value);
+      ggc_mark_tree (l->label_decl);
+      ggc_mark_tree (l->bad_decls);
     }
+
+  for (; u; u = u->next)
+    ggc_mark (u);
 }
 \f
 /* For debugging.  */
@@ -2300,6 +2337,7 @@ push_namespace (name)
         level is set elsewhere.  */
       if (!global)
        {
+         DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
          d = pushdecl (d);
          pushlevel (0);
          declare_namespace_level ();
@@ -2371,16 +2409,6 @@ pop_nested_namespace (ns)
    scope isn't enough, because more binding levels may be pushed.  */
 struct saved_scope *scope_chain;
 
-/* Mark ST for GC.  */
-
-static void
-mark_stmt_tree (st)
-     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
@@ -2400,7 +2428,6 @@ mark_saved_scope (arg)
       if (t->lang_base)
        ggc_mark_tree_varray (t->lang_base);
       ggc_mark_tree (t->lang_name);
-      ggc_mark_tree (t->x_function_parms);
       ggc_mark_tree (t->template_parms);
       ggc_mark_tree (t->x_previous_class_type);
       ggc_mark_tree (t->x_previous_class_values);
@@ -2519,7 +2546,6 @@ maybe_push_to_top_level (pseudo)
   VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
   current_lang_stack = &VARRAY_TREE (current_lang_base, 0);
   current_lang_name = lang_name_cplusplus;
-  strict_prototype = strict_prototypes_lang_cplusplus;
   current_namespace = global_namespace;
 }
 
@@ -2553,11 +2579,6 @@ pop_from_top_level ()
        }
     }
 
-  if (current_lang_name == lang_name_cplusplus)
-    strict_prototype = strict_prototypes_lang_cplusplus;
-  else if (current_lang_name == lang_name_c)
-    strict_prototype = strict_prototypes_lang_c;
-
   /* If we were in the middle of compiling a function, restore our
      state.  */
   if (s->need_pop_function_context)
@@ -2735,7 +2756,7 @@ create_implicit_typedef (name, type)
   tree decl;
 
   decl = build_decl (TYPE_DECL, name, type);
-  SET_DECL_ARTIFICIAL (decl);
+  DECL_ARTIFICIAL (decl) = 1;
   /* There are other implicit type declarations, like the one *within*
      a class that allows you to write `S::S'.  We must distinguish
      amongst these.  */
@@ -2822,9 +2843,25 @@ pushtag (name, type, globalize)
 
          TYPE_CONTEXT (type) = DECL_CONTEXT (d);
          DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
-         if (!uses_template_parms (type))
-           DECL_ASSEMBLER_NAME (d)
-             = get_identifier (build_overload_name (type, 1, 1));
+
+         /* If this is a local class, keep track of it.  We need this
+            information for name-mangling, and so that it is possible to find
+            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) 
+             && 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 (b->parm_flag == 2)
        {
@@ -2927,8 +2964,8 @@ decls_match (newdecl, olddecl)
       tree p2 = TYPE_ARG_TYPES (f2);
 
       if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
-         && ! (DECL_LANGUAGE (newdecl) == lang_c
-               && DECL_LANGUAGE (olddecl) == lang_c))
+         && ! (DECL_EXTERN_C_P (newdecl)
+               && DECL_EXTERN_C_P (olddecl)))
        return 0;
 
       if (TREE_CODE (f1) != TREE_CODE (f2))
@@ -2936,20 +2973,31 @@ decls_match (newdecl, olddecl)
 
       if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
        {
-         if ((! strict_prototypes_lang_c || DECL_BUILT_IN (olddecl))
-             && DECL_LANGUAGE (olddecl) == lang_c
-             && p2 == NULL_TREE)
+         if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
+             && (DECL_BUILT_IN (olddecl)
+#ifndef NO_IMPLICIT_EXTERN_C
+                 || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
+                 || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
+#endif
+             ))
            {
              types_match = self_promoting_args_p (p1);
              if (p1 == void_list_node)
                TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
            }
-         else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
-                  && DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
+#ifndef NO_IMPLICIT_EXTERN_C
+         else if (p1 == NULL_TREE
+                  && (DECL_EXTERN_C_P (olddecl)
+                      && DECL_IN_SYSTEM_HEADER (olddecl)
+                      && !DECL_CLASS_SCOPE_P (olddecl))
+                  && (DECL_EXTERN_C_P (newdecl)
+                      && DECL_IN_SYSTEM_HEADER (newdecl)
+                      && !DECL_CLASS_SCOPE_P (newdecl)))
            {
              types_match = self_promoting_args_p (p2);
              TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
            }
+#endif
          else
            types_match = compparms (p1, p2);
        }
@@ -2962,6 +3010,10 @@ decls_match (newdecl, olddecl)
                                DECL_TEMPLATE_PARMS (olddecl)))
        return 0;
 
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
+         != TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
+       return 0;
+
       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
        types_match = 1;
       else
@@ -3006,7 +3058,8 @@ warn_extern_redeclared_static (newdecl, olddecl)
   tree name;
 
   if (TREE_CODE (newdecl) == TYPE_DECL
-      || TREE_CODE (newdecl) == TEMPLATE_DECL)
+      || TREE_CODE (newdecl) == TEMPLATE_DECL
+      || TREE_CODE (newdecl) == CONST_DECL)
     return;
 
   /* Don't get confused by static member functions; that's a different
@@ -3094,8 +3147,8 @@ duplicate_decls (newdecl, olddecl)
        }
       else if (!types_match)
        {
-         if ((DECL_LANGUAGE (newdecl) == lang_c
-              && DECL_LANGUAGE (olddecl) == lang_c)
+         if ((DECL_EXTERN_C_P (newdecl)
+              && DECL_EXTERN_C_P (olddecl))
              || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
                            TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
            {
@@ -3124,9 +3177,9 @@ duplicate_decls (newdecl, olddecl)
          DECL_THIS_STATIC (olddecl) = 1;
          TREE_PUBLIC (olddecl) = 0;
 
-         /* Make the olddeclaration consistent with the new one so that
-            all remnants of the builtin-ness of this function will be
-            banished.  */
+         /* Make the old declaration consistent with the new one so
+            that all remnants of the builtin-ness of this function
+            will be banished.  */
          DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
          DECL_RTL (olddecl) = DECL_RTL (newdecl);
          DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
@@ -3203,8 +3256,7 @@ duplicate_decls (newdecl, olddecl)
        }
       if (TREE_CODE (newdecl) == FUNCTION_DECL)
        {
-         if (DECL_LANGUAGE (newdecl) == lang_c
-             && DECL_LANGUAGE (olddecl) == lang_c)
+         if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
            {
              cp_error ("declaration of C function `%#D' conflicts with",
                        newdecl);
@@ -3361,7 +3413,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);
@@ -3369,6 +3421,7 @@ 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;
       new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
       /* Optionally warn about more than one declaration for the same
@@ -3399,6 +3452,8 @@ duplicate_decls (newdecl, olddecl)
          CLASSTYPE_FRIEND_CLASSES (newtype)
            = CLASSTYPE_FRIEND_CLASSES (oldtype);
        }
+
+      DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
     }
 
   /* Copy all the DECL_... slots specified in the new decl
@@ -3408,9 +3463,6 @@ duplicate_decls (newdecl, olddecl)
 
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
-                            DECL_TEMPLATE_RESULT (olddecl)))
-       cp_error ("invalid redeclaration of %D", newdecl);
       TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
       DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
@@ -3428,6 +3480,11 @@ duplicate_decls (newdecl, olddecl)
       /* Merge the data types specified in the two decls.  */
       newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
 
+      /* If common_type produces a non-typedef type, just use the old type.  */
+      if (TREE_CODE (newdecl) == TYPE_DECL
+         && newtype == DECL_ORIGINAL_TYPE (newdecl))
+       newtype = oldtype;
+
       if (TREE_CODE (newdecl) == VAR_DECL)
        DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
       /* Do this after calling `common_type' so that default
@@ -3724,7 +3781,6 @@ pushdecl (x)
   my_friendly_assert (!cfun || doing_semantic_analysis_p (),
                      19990913);
 
-  name = DECL_ASSEMBLER_NAME (x);
   need_new_binding = 1;
 
   if (DECL_TEMPLATE_PARM_P (x))
@@ -3738,13 +3794,11 @@ 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))
        DECL_CONTEXT (x) = current_function_decl;
-      if (!DECL_CONTEXT (x))
-       DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
 
       /* If this is the declaration for a namespace-scope function,
         but the declaration itself is in a local scope, mark the
@@ -3756,43 +3810,87 @@ pushdecl (x)
        DECL_LOCAL_FUNCTION_P (x) = 1;
     }
 
-  /* Type are looked up using the DECL_NAME, as that is what the rest of the
-     compiler wants to use.  */
-  if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
-      || TREE_CODE (x) == NAMESPACE_DECL)
-    name = DECL_NAME (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?  */
+         if (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
+        there is one, we have to merge our declaration with the
+        previous declaration.)  */
+      if (t && TREE_CODE (t) == OVERLOAD)
+       {
+         tree match;
+
+         if (TREE_CODE (x) == FUNCTION_DECL)
+           for (match = t; match; match = OVL_NEXT (match))
+             {
+               if (DECL_ASSEMBLER_NAME (OVL_CURRENT (t))
+                   == DECL_ASSEMBLER_NAME (x))
+                 break;
+             }
+         else
+           /* Just choose one.  */
+           match = t;
+
+         if (match)
+           t = OVL_CURRENT (match);
+         else
+           t = NULL_TREE;
+       }
+
       if (t == error_mark_node)
        {
          /* error_mark_node is 0 for a while during initialization!  */
          t = NULL_TREE;
          cp_error_at ("`%#D' used prior to declaration", x);
        }
-
       else if (t != NULL_TREE)
        {
-#if 0
-         /* This is turned off until I have time to do it right (bpk).  */
-         /* With the code below that uses it...  */
-         file = DECL_SOURCE_FILE (t);
-         line = DECL_SOURCE_LINE (t);
-#endif
-         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");
@@ -3801,7 +3899,7 @@ pushdecl (x)
              if (duplicate_decls (x, t))
                return t;
            }
-         else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
+         else if ((DECL_EXTERN_C_FUNCTION_P (x)
                    || DECL_FUNCTION_TEMPLATE_P (x))
                   && is_overloaded_fn (t))
            /* Don't do anything just yet. */;
@@ -3820,36 +3918,6 @@ pushdecl (x)
            }
          else if (duplicate_decls (x, t))
            {
-#if 0
-             /* This is turned off until I have time to do it right (bpk).  */
-
-             /* Also warn if they did a prototype with `static' on it, but
-                then later left the `static' off.  */
-             if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
-               {
-                 if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
-                   return t;
-
-                 if (extra_warnings)
-                   {
-                     cp_warning ("`static' missing from declaration of `%D'",
-                                 t);
-                     warning_with_file_and_line (file, line,
-                                                 "previous declaration of `%s'",
-                                                 decl_as_string (t, 0));
-                   }
-
-                 /* Now fix things so it'll do what they expect.  */
-                 if (current_function_decl)
-                   TREE_PUBLIC (current_function_decl) = 0;
-               }
-             /* Due to interference in memory reclamation (X may be
-                obstack-deallocated at this point), we must guard against
-                one really special case.  [jason: This should be handled
-                by start_function]  */
-             if (current_function_decl == x)
-               current_function_decl = t;
-#endif
              if (TREE_CODE (t) == TYPE_DECL)
                SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
              else if (TREE_CODE (t) == FUNCTION_DECL)
@@ -3877,14 +3945,13 @@ pushdecl (x)
 
       /* If this is a function conjured up by the backend, massage it
         so it looks friendly.  */
-      if (TREE_CODE (x) == FUNCTION_DECL
-         && ! DECL_LANG_SPECIFIC (x))
+      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
        {
          retrofit_lang_decl (x);
          DECL_LANGUAGE (x) = lang_c;
        }
 
-      if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
+      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
        {
          t = push_overloaded_decl (x, PUSH_LOCAL);
          if (t != x)
@@ -3909,7 +3976,7 @@ pushdecl (x)
       if (TREE_CODE (x) == TYPE_DECL)
        {
          tree type = TREE_TYPE (x);
-          if (DECL_SOURCE_LINE (x) == 0)
+         if (DECL_SOURCE_LINE (x) == 0)
             {
              if (TYPE_NAME (type) == 0)
                TYPE_NAME (type) = x;
@@ -3946,14 +4013,12 @@ pushdecl (x)
        {
          tree decl;
 
-         if (IDENTIFIER_NAMESPACE_VALUE (name) != NULL_TREE
-             && (DECL_EXTERNAL (IDENTIFIER_NAMESPACE_VALUE (name))
-                 || TREE_PUBLIC (IDENTIFIER_NAMESPACE_VALUE (name))))
-           decl = IDENTIFIER_NAMESPACE_VALUE (name);
-         else
-           decl = NULL_TREE;
+         decl = IDENTIFIER_NAMESPACE_VALUE (name);
+         if (decl && TREE_CODE (decl) == OVERLOAD)
+           decl = OVL_FUNCTION (decl);
 
-         if (decl
+         if (decl && decl != error_mark_node
+             && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
              /* If different sort of thing, we already gave an error.  */
              && TREE_CODE (decl) == TREE_CODE (x)
              && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
@@ -3973,21 +4038,32 @@ 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
+            need to be aware.  */
          if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
                && t != NULL_TREE)
              /* For an ordinary function, we create a binding from
                 the mangled name (i.e., NAME) to the DECL.  But, for
                 an `extern "C"' function, the mangled name and the
                 ordinary name are the same so we need not do this.  */
-             && !(TREE_CODE (x) == FUNCTION_DECL &&
-                  DECL_LANGUAGE (x) == lang_c))
+             && !DECL_EXTERN_C_FUNCTION_P (x))
            {
+             tree mangled_name;
+
+             if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
+                 || TREE_CODE (x) == NAMESPACE_DECL)
+               mangled_name = name;
+             else
+               mangled_name = DECL_ASSEMBLER_NAME (x);
+
              if (TREE_CODE (x) == FUNCTION_DECL)
                my_friendly_assert
-                 ((IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
-                 || (IDENTIFIER_GLOBAL_VALUE (name) == x), 378);
-             SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
+                 ((IDENTIFIER_GLOBAL_VALUE (mangled_name) == NULL_TREE)
+                 || (IDENTIFIER_GLOBAL_VALUE (mangled_name) == x), 378);
+             SET_IDENTIFIER_NAMESPACE_VALUE (mangled_name, x);
            }
 
          /* Don't forget if the function was used via an implicit decl.  */
@@ -4387,9 +4463,10 @@ push_class_level_binding (name, x)
     }
 }
 
-/* Insert another USING_DECL into the current binding level,
-   returning this declaration. If this is a redeclaration,
-   do nothing and return NULL_TREE.  */
+/* Insert another USING_DECL into the current binding level, returning
+   this declaration. If this is a redeclaration, do nothing, and
+   return NULL_TREE if this not in namespace scope (in namespace
+   scope, a using decl might extend any previous bindings).  */
 
 tree
 push_using_decl (scope, name)
@@ -4404,7 +4481,7 @@ push_using_decl (scope, name)
     if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
       break;
   if (decl)
-    return NULL_TREE;
+    return namespace_bindings_p () ? decl : NULL_TREE;
   decl = build_lang_decl (USING_DECL, name, void_type_node);
   DECL_INITIAL (decl) = scope;
   TREE_CHAIN (decl) = current_binding_level->usings;
@@ -4502,6 +4579,9 @@ push_overloaded_decl (decl, flags)
                return fn;
            }
        }
+      else if (old == error_mark_node)
+       /* Ignore the undefined symbol marker.  */
+       old = NULL_TREE;
       else
        {
          cp_error_at ("previous non-function declaration `%#D'", old);
@@ -4654,6 +4734,8 @@ 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 (olddecl))
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
           && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
          || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
@@ -4708,17 +4790,25 @@ make_label_decl (id, local_p)
   /* Record the fact that this identifier is bound to this label.  */
   SET_IDENTIFIER_LABEL_VALUE (id, decl);
 
-  /* Record this label on the list of used labels so that we can check
-     at the end of the function to see whether or not the label was
-     actually defined.  */
-  if ((named_label_uses == NULL || named_label_uses->label_decl != decl)
-      && (named_label_uses == NULL
-         || named_label_uses->names_in_scope != current_binding_level->names
-         || named_label_uses->label_decl != decl))
-    {
-      struct named_label_list *new_ent;
-      new_ent
-       = (struct named_label_list*)oballoc (sizeof (struct named_label_list));
+  return decl;
+}
+
+/* Record this label on the list of used labels so that we can check
+   at the end of the function to see whether or not the label was
+   actually defined, and so we can check when the label is defined whether
+   this use is valid.  */
+
+static void
+use_label (decl)
+     tree decl;
+{
+  if (named_label_uses == NULL
+      || named_label_uses->names_in_scope != current_binding_level->names
+      || named_label_uses->label_decl != decl)
+    {
+      struct named_label_use_list *new_ent;
+      new_ent = ((struct named_label_use_list *)
+                ggc_alloc (sizeof (struct named_label_use_list)));
       new_ent->label_decl = decl;
       new_ent->names_in_scope = current_binding_level->names;
       new_ent->binding_level = current_binding_level;
@@ -4727,8 +4817,6 @@ make_label_decl (id, local_p)
       new_ent->next = named_label_uses;
       named_label_uses = new_ent;
     }
-
-  return decl;
 }
 
 /* Look for a label named ID in the current function.  If one cannot
@@ -4740,6 +4828,7 @@ lookup_label (id)
      tree id;
 {
   tree decl;
+  struct named_label_list *ent;
 
   /* You can't use labels at global scope.  */
   if (current_function_decl == NULL_TREE)
@@ -4757,12 +4846,17 @@ lookup_label (id)
   /* Record this label on the list of labels used in this function.
      We do this before calling make_label_decl so that we get the
      IDENTIFIER_LABEL_VALUE before the new label is declared.  */
-  named_labels = tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
-                           named_labels);
+  ent = ((struct named_label_list *)
+        ggc_alloc_cleared (sizeof (struct named_label_list)));
+  ent->old_value = IDENTIFIER_LABEL_VALUE (id);
+  ent->next = named_labels;
+  named_labels = ent;
+
   /* We need a new label.  */
   decl = make_label_decl (id, /*local_p=*/0);
+
   /* Now fill in the information we didn't have before.  */
-  TREE_VALUE (named_labels) = decl;
+  ent->label_decl = decl;
 
   return decl;
 }
@@ -4789,17 +4883,214 @@ declare_local_label (id)
   return decl;
 }
 
+/* Returns nonzero if it is ill-formed to jump past the declaration of
+   DECL.  Returns 2 if it's also a real problem.  */
+
+static int
+decl_jump_unsafe (decl)
+     tree decl;
+{
+  if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
+    return 0;
+
+  if (DECL_INITIAL (decl) == NULL_TREE
+      && pod_type_p (TREE_TYPE (decl)))
+    return 0;
+
+  /* This is really only important if we're crossing an initialization.
+     The POD stuff is just pedantry; why should it matter if the class
+     contains a field of pointer to member type?  */
+  if (DECL_INITIAL (decl)
+      || (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
+    return 2;
+  return 1;
+}
+
+/* Check that a single previously seen jump to a newly defined label
+   is OK.  DECL is the LABEL_DECL or 0; LEVEL is the binding_level for
+   the jump context; NAMES are the names in scope in LEVEL at the jump
+   context; FILE and LINE are the source position of the jump or 0.  */
+
+static void
+check_previous_goto_1 (decl, level, names, file, line)
+     tree decl;
+     struct binding_level *level;
+     tree names;
+     const char *file;
+     int line;
+{
+  int identified = 0;
+  int saw_eh = 0;
+  struct binding_level *b = current_binding_level;
+  for (; b; b = b->level_chain)
+    {
+      tree new_decls = b->names;
+      tree old_decls = (b == level ? names : NULL_TREE);
+      for (; new_decls != old_decls;
+          new_decls = TREE_CHAIN (new_decls))
+       {
+         int problem = decl_jump_unsafe (new_decls);
+         if (! problem)
+           continue;
+
+         if (! identified)
+           {
+             if (decl)
+               cp_pedwarn ("jump to label `%D'", decl);
+             else
+               pedwarn ("jump to case label");
+
+             if (file)
+               pedwarn_with_file_and_line (file, line, "  from here");
+             identified = 1;
+           }
+
+         if (problem > 1 && DECL_ARTIFICIAL (new_decls))
+           /* Can't skip init of __exception_info.  */
+           cp_error_at ("  enters catch block", new_decls);
+         else if (problem > 1)
+           cp_error_at ("  crosses initialization of `%#D'",
+                        new_decls);
+         else
+           cp_pedwarn_at ("  enters scope of non-POD `%#D'",
+                          new_decls);
+       }
+
+      if (b == level)
+       break;
+      if (b->eh_region && ! saw_eh)
+       {
+         if (! identified)
+           {
+             if (decl)
+               cp_pedwarn ("jump to label `%D'", decl);
+             else
+               pedwarn ("jump to case label");
+
+             if (file)
+               pedwarn_with_file_and_line (file, line, "  from here");
+             identified = 1;
+           }
+         error ("  enters try block");
+         saw_eh = 1;
+       }
+    }
+}
+
+static void
+check_previous_goto (use)
+     struct named_label_use_list *use;
+{
+  check_previous_goto_1 (use->label_decl, use->binding_level,
+                        use->names_in_scope, use->filename_o_goto,
+                        use->lineno_o_goto);
+}
+
+static void
+check_switch_goto (level)
+     struct binding_level *level;
+{
+  check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
+}
+
+/* Check that any previously seen jumps to a newly defined label DECL
+   are OK.  Called by define_label.  */
+
+static void
+check_previous_gotos (decl)
+     tree decl;
+{
+  struct named_label_use_list **usep;
+
+  if (! TREE_USED (decl))
+    return;
+
+  for (usep = &named_label_uses; *usep; )
+    {
+      struct named_label_use_list *use = *usep;
+      if (use->label_decl == decl)
+       {
+         check_previous_goto (use);
+         *usep = use->next;
+       }
+      else
+       usep = &(use->next);
+    }
+}
+
+/* Check that a new jump to a label DECL is OK.  Called by
+   finish_goto_stmt.  */
+
+void
+check_goto (decl)
+     tree decl;
+{
+  int identified = 0;
+  tree bad;
+  struct named_label_list *lab;
+
+  /* We can't know where a computed goto is jumping.  So we assume
+     that it's OK.  */
+  if (! DECL_P (decl))
+    return;
+
+  /* If the label hasn't been defined yet, defer checking.  */
+  if (! DECL_INITIAL (decl))
+    {
+      use_label (decl);
+      return;
+    }
+
+  for (lab = named_labels; lab; lab = lab->next)
+    if (decl == lab->label_decl)
+      break;
+
+  /* If the label is not on named_labels it's a gcc local label, so
+     it must be in an outer scope, so jumping to it is always OK.  */
+  if (lab == 0)
+    return;
+
+  if ((lab->eh_region || lab->bad_decls) && !identified)
+    {
+      cp_pedwarn_at ("jump to label `%D'", decl);
+      pedwarn ("  from here");
+      identified = 1;
+    }
+
+  for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
+    {
+      tree b = TREE_VALUE (bad);
+      int u = decl_jump_unsafe (b);
+
+      if (u > 1 && DECL_ARTIFICIAL (b))
+       /* Can't skip init of __exception_info.  */
+       cp_error_at ("  enters catch block", b);
+      else if (u > 1)
+       cp_error_at ("  skips initialization of `%#D'", b);
+      else
+       cp_pedwarn_at ("  enters scope of non-POD `%#D'", b);
+    }
+
+  if (lab->eh_region)
+    error ("  enters try block");
+}
+
 /* Define a label, specifying the location in the source file.
    Return the LABEL_DECL node for the label, if the definition is valid.
    Otherwise return 0.  */
 
 tree
 define_label (filename, line, name)
-     char *filename;
+     const char *filename;
      int line;
      tree name;
 {
   tree decl = lookup_label (name);
+  struct named_label_list *ent;
+
+  for (ent = named_labels; ent; ent = ent->next)
+    if (ent->label_decl == decl)
+      break;
 
   /* After labels, make any new cleanups go into their
      own new (temporary) binding contour.  */
@@ -4815,104 +5106,17 @@ define_label (filename, line, name)
     }
   else
     {
-      struct named_label_list *uses, *prev;
-      int identified = 0;
-      int saw_eh = 0;
-
       /* Mark label as having been defined.  */
       DECL_INITIAL (decl) = error_mark_node;
       /* Say where in the source.  */
       DECL_SOURCE_FILE (decl) = filename;
       DECL_SOURCE_LINE (decl) = line;
-
-      prev = NULL;
-      uses = named_label_uses;
-      while (uses != NULL)
-       if (uses->label_decl == decl)
-         {
-           struct binding_level *b = current_binding_level;
-           while (b)
-             {
-               tree new_decls = b->names;
-               tree old_decls = (b == uses->binding_level)
-                                 ? uses->names_in_scope : NULL_TREE;
-               while (new_decls != old_decls)
-                 {
-                   if (TREE_CODE (new_decls) == VAR_DECL
-                       /* Don't complain about crossing initialization
-                          of internal entities.  They can't be accessed,
-                          and they should be cleaned up
-                          by the time we get to the label.  */
-                       && ! DECL_ARTIFICIAL (new_decls)
-                       && !(DECL_INITIAL (new_decls) == NULL_TREE
-                            && pod_type_p (TREE_TYPE (new_decls))))
-                     {
-                       /* This is really only important if we're crossing
-                          an initialization.  The POD stuff is just
-                          pedantry; why should it matter if the class
-                          contains a field of pointer to member type?  */
-                       int problem = (DECL_INITIAL (new_decls)
-                                      || (TYPE_NEEDS_CONSTRUCTING
-                                          (TREE_TYPE (new_decls))));
-
-                       if (! identified)
-                         {
-                           if (problem)
-                             {
-                               cp_error ("jump to label `%D'", decl);
-                               error_with_file_and_line
-                                 (uses->filename_o_goto,
-                                  uses->lineno_o_goto, "  from here");
-                             }
-                           else
-                             {
-                               cp_pedwarn ("jump to label `%D'", decl);
-                               pedwarn_with_file_and_line
-                                 (uses->filename_o_goto,
-                                  uses->lineno_o_goto, "  from here");
-                             }
-                           identified = 1;
-                         }
-
-                       if (problem)
-                         cp_error_at ("  crosses initialization of `%#D'",
-                                      new_decls);
-                       else
-                         cp_pedwarn_at ("  enters scope of non-POD `%#D'",
-                                        new_decls);
-                     }
-                   new_decls = TREE_CHAIN (new_decls);
-                 }
-               if (b == uses->binding_level)
-                 break;
-               if (b->eh_region && ! saw_eh)
-                 {
-                   if (! identified)
-                     {
-                       cp_error ("jump to label `%D'", decl);
-                       error_with_file_and_line
-                         (uses->filename_o_goto,
-                          uses->lineno_o_goto, "  from here");
-                       identified = 1;
-                     }
-                   error ("  enters exception handling block");
-                   saw_eh = 1;
-                 }
-               b = b->level_chain;
-             }
-
-           if (prev != NULL)
-             prev->next = uses->next;
-           else
-             named_label_uses = uses->next;
-
-           uses = uses->next;
-         }
-       else
-         {
-           prev = uses;
-           uses = uses->next;
-         }
+      if (ent)
+       {
+         ent->names_in_scope = current_binding_level->names;
+         ent->binding_level = current_binding_level;
+       }
+      check_previous_gotos (decl);
       current_function_return_value = NULL_TREE;
       return decl;
     }
@@ -4922,17 +5126,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;
 }
 
@@ -4942,6 +5166,7 @@ pop_switch ()
   struct cp_switch *cs;
   
   cs = switch_stack;
+  splay_tree_delete (cs->cases);
   switch_stack = switch_stack->next;
   free (cs);
 }
@@ -4950,56 +5175,46 @@ pop_switch ()
    is a bad place for one.  */
 
 void
-define_case_label ()
+finish_case_label (low_value, high_value)
+     tree low_value;
+     tree high_value;
 {
-  tree cleanup = last_cleanup_this_contour ();
-  struct binding_level *b = current_binding_level;
-  int identified = 0;
+  tree cond;
 
   if (! switch_stack)
-    /* Don't crash; we'll complain in do_case.  */
-    return;
-
-  if (cleanup)
     {
-      static int explained = 0;
-      cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
-      warning ("where case label appears here");
-      if (!explained)
-       {
-         warning ("(enclose actions of previous case statements requiring");
-         warning ("destructors in their own binding contours.)");
-         explained = 1;
-       }
+      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;
     }
 
-  for (; b && b != switch_stack->level; b = b->level_chain)
+  if (processing_template_decl)
     {
-      tree new_decls = b->names;
-      for (; new_decls; new_decls = TREE_CHAIN (new_decls))
-       {
-         if (TREE_CODE (new_decls) == VAR_DECL
-             /* Don't complain about crossing initialization
-                of internal entities.  They can't be accessed,
-                and they should be cleaned up
-                by the time we get to the label.  */
-             && ! DECL_ARTIFICIAL (new_decls)
-             && ((DECL_INITIAL (new_decls) != NULL_TREE
-                  && DECL_INITIAL (new_decls) != error_mark_node)
-                 || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
-           {
-             if (! identified)
-               error ("jump to case label");
-             identified = 1;
-             cp_error_at ("  crosses initialization of `%#D'",
-                          new_decls);
-           }
-       }
+      tree label;
+
+      /* For templates, just add the case label; we'll do semantic
+        analysis at instantiation-time.  */
+      label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+      add_stmt (build_case_label (low_value, high_value, label));
+      return;
     }
 
+  /* 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);
+
+  c_add_case_label (switch_stack->cases, cond, low_value, high_value);
+
+  check_switch_goto (switch_stack->level);
+
   /* After labels, make any new cleanups go into their
      own new (temporary) binding contour.  */
-
   current_binding_level->more_cleanups_ok = 0;
   current_function_return_value = NULL_TREE;
 }
@@ -5687,7 +5902,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;
@@ -5697,6 +5912,13 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
            {
              val = lookup_member (type, name, 0, prefer_type);
              type_access_control (type, val);
+
+             /* Restore the containing TYPENAME_TYPE if we looked
+                through it before.  */
+             if (got_scope && got_scope != type
+                 && val && TREE_CODE (val) == TYPE_DECL
+                 && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE)
+               TYPE_CONTEXT (TREE_TYPE (val)) = got_scope;
            }
        }
       else
@@ -5910,35 +6132,8 @@ end_only_namespace_names ()
   only_namespace_names = 0;
 }
 \f
-/* Arrange for the user to get a source line number, even when the
-   compiler is going down in flames, so that she at least has a
-   chance of working around problems in the compiler.  We used to
-   call error(), but that let the segmentation fault continue
-   through; now, it's much more passive by asking them to send the
-   maintainers mail about the problem.  */
-
-static void
-signal_catch (sig)
-     int sig ATTRIBUTE_UNUSED;
-{
-  signal (SIGSEGV, SIG_DFL);
-#ifdef SIGIOT
-  signal (SIGIOT, SIG_DFL);
-#endif
-#ifdef SIGILL
-  signal (SIGILL, SIG_DFL);
-#endif
-#ifdef SIGABRT
-  signal (SIGABRT, SIG_DFL);
-#endif
-#ifdef SIGBUS
-  signal (SIGBUS, SIG_DFL);
-#endif
-  my_friendly_abort (0);
-}
-
 /* Push the declarations of builtin types into the namespace.
-   RID_INDEX, if < 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.  */
 
@@ -6030,6 +6225,7 @@ record_unknown_type (type, name)
   TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
   TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
   TYPE_ALIGN (type) = 1;
+  TYPE_USER_ALIGN (type) = 0;
   TYPE_MODE (type) = TYPE_MODE (void_type_node);
 }
 
@@ -6075,6 +6271,8 @@ initialize_predefined_identifiers ()
     { "__pfn_or_delta2", &pfn_or_delta2_identifier, 0 },
     { "_vptr", &vptr_identifier, 0 },
     { "__cp_push_exception", &cp_push_exception_identifier, 0 },
+    { "__vtt_parm", &vtt_parm_identifier, 0 },
+    { "std", &std_identifier, 0 },
     { NULL, NULL, 0 }
   };
 
@@ -6106,11 +6304,11 @@ init_decl_processing ()
   /* Create all the identifiers we need.  */
   initialize_predefined_identifiers ();
 
-  /* Let the back-end now how to save and restore language-specific
-     per-function globals.  */
+  /* Fill in back-end hooks.  */
   init_lang_status = &push_cp_function_context;
   free_lang_status = &pop_cp_function_context;
   mark_lang_status = &mark_cp_function_context;
+  lang_safe_from_p = &c_safe_from_p;
 
   cp_parse_init ();
   init_decl2 ();
@@ -6126,15 +6324,11 @@ init_decl_processing ()
   current_lang_name = NULL_TREE;
 
   /* Adjust various flags based on command-line settings.  */
-  if (flag_strict_prototype == 2)
-    flag_strict_prototype = pedantic;
   if (! flag_permissive && ! pedantic)
     flag_pedantic_errors = 1;
   if (!flag_no_inline)
     flag_inline_trees = 1;
 
-  strict_prototypes_lang_c = flag_strict_prototype;
-
   /* Initially, C.  */
   current_lang_name = lang_name_c;
 
@@ -6142,28 +6336,6 @@ init_decl_processing ()
   current_binding_level = NULL_BINDING_LEVEL;
   free_binding_level = NULL_BINDING_LEVEL;
 
-  /* Because most segmentation signals can be traced back into user
-     code, catch them and at least give the user a chance of working
-     around compiler bugs.  */
-  signal (SIGSEGV, signal_catch);
-
-  /* We will also catch aborts in the back-end through signal_catch and
-     give the user a chance to see where the error might be, and to defeat
-     aborts in the back-end when there have been errors previously in their
-     code.  */
-#ifdef SIGIOT
-  signal (SIGIOT, signal_catch);
-#endif
-#ifdef SIGILL
-  signal (SIGILL, signal_catch);
-#endif
-#ifdef SIGABRT
-  signal (SIGABRT, signal_catch);
-#endif
-#ifdef SIGBUS
-  signal (SIGBUS, signal_catch);
-#endif
-
   build_common_tree_nodes (flag_signed_char);
 
   error_mark_list = build_tree_list (error_mark_node, error_mark_node);
@@ -6184,16 +6356,20 @@ init_decl_processing ()
   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 (RID_MAX, "long unsigned int", long_unsigned_type_node);
+  record_builtin_type (RID_MAX, "long unsigned int",
+                      long_unsigned_type_node);
   record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
-  record_builtin_type (RID_MAX, "long long int", long_long_integer_type_node);
+  record_builtin_type (RID_MAX, "long long int",
+                      long_long_integer_type_node);
   record_builtin_type (RID_MAX, "long long unsigned int",
                       long_long_unsigned_type_node);
   record_builtin_type (RID_MAX, "long long unsigned",
                       long_long_unsigned_type_node);
   record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
-  record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node);
-  record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node);
+  record_builtin_type (RID_MAX, "short unsigned int",
+                      short_unsigned_type_node); 
+  record_builtin_type (RID_MAX, "unsigned short",
+                      short_unsigned_type_node);
 
   ptrdiff_type_node
     = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
@@ -6280,10 +6456,6 @@ init_decl_processing ()
   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,
@@ -6303,6 +6475,7 @@ init_decl_processing ()
      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);
@@ -6326,6 +6499,7 @@ init_decl_processing ()
   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;
 
@@ -6353,12 +6527,10 @@ init_decl_processing ()
                                    : WCHAR_TYPE);
   wchar_type_node = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (wchar_type_node));
   wchar_type_size = TYPE_PRECISION (wchar_type_node);
-  signed_wchar_type_node = make_signed_type (wchar_type_size);
-  unsigned_wchar_type_node = make_unsigned_type (wchar_type_size);
-  wchar_type_node
-    = TREE_UNSIGNED (wchar_type_node)
-      ? unsigned_wchar_type_node
-      : signed_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 */
@@ -6384,12 +6556,12 @@ init_decl_processing ()
   else
     {
       vtable_entry_type = make_aggr_type (RECORD_TYPE);
-      fields[0] = build_lang_decl (FIELD_DECL, delta_identifier,
-                                  delta_type_node);
-      fields[1] = build_lang_decl (FIELD_DECL, index_identifier,
-                                  delta_type_node);
-      fields[2] = build_lang_decl (FIELD_DECL, pfn_identifier,
-                                  ptr_type_node);
+      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_identifier,
+                             ptr_type_node);
       finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
                           double_type_node);
 
@@ -6417,7 +6589,8 @@ init_decl_processing ()
   record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
 
   std_node = build_decl (NAMESPACE_DECL,
-                        get_identifier (flag_honor_std ? "fake std":"std"),
+                        flag_honor_std 
+                        ? get_identifier ("fake std") : std_identifier,
                         void_type_node);
   pushdecl (std_node);
   
@@ -6445,11 +6618,10 @@ init_decl_processing ()
     newtype = build_exception_variant
       (ptr_ftype_sizetype, add_exception_specifier (NULL_TREE, bad_alloc_type_node, -1));
     deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
-    push_cp_library_fn (ansi_opname[(int) NEW_EXPR], newtype);
-    push_cp_library_fn (ansi_opname[(int) VEC_NEW_EXPR], newtype);
-    global_delete_fndecl = push_cp_library_fn (ansi_opname[(int) DELETE_EXPR],
-                                              deltype);
-    push_cp_library_fn (ansi_opname[(int) VEC_DELETE_EXPR], deltype);
+    push_cp_library_fn (NEW_EXPR, newtype);
+    push_cp_library_fn (VEC_NEW_EXPR, newtype);
+    global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
+    push_cp_library_fn (VEC_DELETE_EXPR, deltype);
   }
 
   abort_fndecl
@@ -6472,6 +6644,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 ();
 
@@ -6481,8 +6657,6 @@ init_decl_processing ()
   /* Show we use EH for cleanups.  */
   using_eh_for_cleanups ();
 
-  print_error_function = lang_print_error_function;
-  lang_get_alias_set = &c_get_alias_set;
   valid_lang_attribute = cp_valid_lang_attribute;
 
   /* Maintain consistency.  Perhaps we should just complain if they
@@ -6507,7 +6681,6 @@ init_decl_processing ()
 
   ggc_add_tree_root (&last_function_parm_tags, 1);
   ggc_add_tree_root (&current_function_return_value, 1);
-  ggc_add_tree_root (&current_function_parms, 1);
   ggc_add_tree_root (&current_function_parm_tags, 1);
   ggc_add_tree_root (&last_function_parms, 1);
   ggc_add_tree_root (&error_mark_list, 1);
@@ -6576,16 +6749,6 @@ cp_make_fname_decl (id, name, type_dep)
   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
@@ -6605,7 +6768,7 @@ builtin_function (name, type, code, class, libname)
      enum built_in_class class;
      const char *libname;
 {
-  tree decl = build_library_fn_1 (get_identifier (name), type);
+  tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
   DECL_BUILT_IN_CLASS (decl) = class;
   DECL_FUNCTION_CODE (decl) = code;
 
@@ -6618,6 +6781,12 @@ builtin_function (name, type, code, class, libname)
   if (libname)
     DECL_ASSEMBLER_NAME (decl) = get_identifier (libname);
   make_function_rtl (decl);
+
+  /* Warn if a function in the namespace for users
+     is used without an occasion to consider it declared.  */
+  if (name[0] != '_' || name[1] != '_')
+    DECL_ANTICIPATED (decl) = 1;
+
   return decl;
 }
 
@@ -6625,8 +6794,9 @@ builtin_function (name, type, code, class, libname)
    function.  Not called directly.  */
 
 static tree
-build_library_fn_1 (name, type)
+build_library_fn_1 (name, operator_code, type)
      tree name;
+     enum tree_code operator_code;
      tree type;
 {
   tree fn = build_lang_decl (FUNCTION_DECL, name, type);
@@ -6634,6 +6804,7 @@ build_library_fn_1 (name, type)
   TREE_PUBLIC (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
   TREE_NOTHROW (fn) = 1;
+  SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
   return fn;
 }
 
@@ -6646,20 +6817,22 @@ build_library_fn (name, type)
      tree name;
      tree type;
 {
-  tree fn = build_library_fn_1 (name, type);
+  tree fn = build_library_fn_1 (name, ERROR_MARK, type);
   make_function_rtl (fn);
   return fn;
 }
 
 /* Returns the _DECL for a library function with C++ linkage.  */
 
-tree
-build_cp_library_fn (name, type)
+static tree
+build_cp_library_fn (name, operator_code, type)
      tree name;
+     enum tree_code operator_code;
      tree type;
 {
-  tree fn = build_library_fn_1 (name, type);
+  tree fn = build_library_fn_1 (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);
   return fn;
@@ -6684,7 +6857,7 @@ build_cp_library_fn_ptr (name, type)
      const char *name;
      tree type;
 {
-  return build_cp_library_fn (get_identifier (name), type);
+  return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
 }
 
 /* Like build_library_fn, but also pushes the function so that we will
@@ -6702,12 +6875,14 @@ push_library_fn (name, type)
 /* Like build_cp_library_fn, but also pushes the function so that it
    will be found by normal lookup.  */
 
-tree
-push_cp_library_fn (name, type)
-     tree name;
+static tree
+push_cp_library_fn (operator_code, type)
+     enum tree_code operator_code;
      tree type;
 {
-  tree fn = build_cp_library_fn (name, type);
+  tree fn = build_cp_library_fn (ansi_opname (operator_code), 
+                                operator_code,
+                                type);
   pushdecl (fn);
   return fn;
 }
@@ -6802,7 +6977,8 @@ check_tag_decl (declspecs)
        {
          ++found_type;
 
-         if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
+         if ((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;
@@ -7076,7 +7252,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       /* cp_finish_decl sets DECL_EXTERNAL if DECL_IN_AGGR_P is set.  */
       DECL_IN_AGGR_P (decl) = 0;
       if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
-         || CLASSTYPE_USE_TEMPLATE (context))
+         || CLASSTYPE_TEMPLATE_INSTANTIATION (context))
        {
          SET_DECL_TEMPLATE_SPECIALIZATION (decl);
          /* [temp.expl.spec] An explicit specialization of a static data
@@ -7246,7 +7422,8 @@ grok_reference_init (decl, type, init)
      first.  */
   tmp = convert_to_reference
     (type, init, CONV_IMPLICIT,
-     LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
+     LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
+     decl);
 
   if (tmp == error_mark_node)
     return;
@@ -7319,12 +7496,9 @@ maybe_deduce_size_from_array_init (decl, init)
       && TYPE_DOMAIN (type) == NULL_TREE
       && TREE_CODE (decl) != TYPE_DECL)
     {
-      int do_default
-       = (TREE_STATIC (decl)
-          /* Even if pedantic, an external linkage array
-             may have incomplete type at first.  */
-          ? pedantic && ! DECL_EXTERNAL (decl)
-          : !DECL_EXTERNAL (decl));
+      /* do_default is really a C-ism to deal with tentative definitions.
+        But let's leave it here to ease the eventual merge.  */
+      int do_default = !DECL_EXTERNAL (decl);
       tree initializer = init ? init : DECL_INITIAL (decl);
       int failure = complete_array_type (type, initializer, do_default);
 
@@ -7617,11 +7791,8 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
      tree init;
      const char *asmspec;
 {
-  int toplev;
-  tree type;
-
-  type = TREE_TYPE (decl);
-  toplev = toplevel_bindings_p ();
+  int toplev = toplevel_bindings_p ();
+  int defer_p;
 
   /* Handle non-variables up front.  */
   if (TREE_CODE (decl) != VAR_DECL)
@@ -7630,80 +7801,56 @@ make_rtl_for_nonlocal_decl (decl, init, asmspec)
       return;
     }
 
-  /* Set the DECL_ASSEMBLER_NAME for the variable.  */
-  if (asmspec)
-    DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
-
-  if (DECL_VIRTUAL_P (decl))
-    make_decl_rtl (decl, NULL_PTR, toplev);
-  else if (TREE_READONLY (decl)
-          && DECL_INITIAL (decl) != NULL_TREE
-          && DECL_INITIAL (decl) != error_mark_node
-          && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
-    {
-      DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
-
-      if (toplev && ! TREE_PUBLIC (decl))
-       {
-         /* If this is a static const, change its apparent linkage
-            if it belongs to a #pragma interface.  */
-         if (!interface_unknown)
-           {
-             TREE_PUBLIC (decl) = 1;
-             DECL_EXTERNAL (decl) = interface_only;
-           }
-         make_decl_rtl (decl, asmspec, toplev);
-       }
-      else if (toplev)
-       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
-    }
-  else if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
+  /* If we see a class member here, it should be a static data
+     member.  */
+  if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
     {
       my_friendly_assert (TREE_STATIC (decl), 19990828);
-
-      if (init == NULL_TREE
-#ifdef DEFAULT_STATIC_DEFS
-         /* If this code is dead, then users must
-            explicitly declare static member variables
-            outside the class def'n as well.  */
-         && TYPE_NEEDS_CONSTRUCTING (type)
-#endif
-         )
-       {
-         DECL_EXTERNAL (decl) = 1;
-         make_decl_rtl (decl, asmspec, 1);
-       }
-      else
-       rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
+      /* An in-class declaration of a static data member should be
+        external; it is only a declaration, and not a definition.  */
+      if (init == NULL_TREE)
+       my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
     }
-  else if (TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL
-          || (TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)))
-    rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
-}
-
-/* Create RTL for the local static variable DECL.  */
 
-void
-make_rtl_for_local_static (decl)
-     tree decl;
-{
-  const char *asmspec = NULL;
+  /* Set the DECL_ASSEMBLER_NAME for the variable.  */
+  if (asmspec)
+    DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
 
-  /* If we inlined this variable, we could see it's declaration
-     again.  */
-  if (DECL_RTL (decl))
+  /* We don't create any RTL for local variables.  */
+  if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
     return;
 
-  if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
+  /* We defer emission of local statics until the corresponding
+     DECL_STMT is expanded.  */
+  defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
+
+  /* We try to defer namespace-scope static constants so that they are
+     not emitted into the object file unncessarily.  */
+  if (!DECL_VIRTUAL_P (decl)
+      && TREE_READONLY (decl)
+      && DECL_INITIAL (decl) != NULL_TREE
+      && DECL_INITIAL (decl) != error_mark_node
+      && ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
+      && toplev
+      && !TREE_PUBLIC (decl))
     {
-      /* The only way this situaton can occur is if the
-        user specified a name for this DECL using the
-        `attribute' syntax.  */
-      asmspec = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-      DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
+      /* Fool with the linkage according to #pragma interface.  */
+      if (!interface_unknown)
+       {
+         TREE_PUBLIC (decl) = 1;
+         DECL_EXTERNAL (decl) = interface_only;
+       }
+
+      defer_p = 1;
     }
 
-  rest_of_decl_compilation (decl, asmspec, /*top_level=*/0, /*at_end=*/0);
+  /* If we're deferring the variable, just make RTL.  Do not actually
+     emit the variable.  */
+  if (defer_p)
+    make_decl_rtl (decl, asmspec, toplev);
+  /* If we're not deferring, go ahead and assemble the variable.  */
+  else
+    rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
 }
 
 /* The old ARM scoping rules injected variables declared in the
@@ -7716,6 +7863,9 @@ void
 maybe_inject_for_scope_var (decl)
      tree decl;
 {
+  if (!DECL_NAME (decl))
+    return;
+  
   if (current_binding_level->is_for_scope)
     {
       struct binding_level *outer
@@ -7789,12 +7939,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));
-         saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p;
-         stmts_are_full_exprs_p = 1;
+         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;
          finish_expr_stmt (build_aggr_init (decl, init, flags));
-         stmts_are_full_exprs_p = saved_stmts_are_full_exprs_p;
+         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
@@ -7827,7 +7977,8 @@ destroy_local_var (decl)
     return;
 
   /* And only things with destructors need cleaning up.  */
-  if (TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
+  if (type == error_mark_node
+      || TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
     return;
 
   if (TREE_CODE (decl) == VAR_DECL &&
@@ -7846,42 +7997,12 @@ destroy_local_var (decl)
     finish_decl_cleanup (decl, cleanup);
 }
 
-/* Let the back-end know about DECL.  */
-
-void
-emit_local_var (decl)
-     tree decl;
-{
-  /* Create RTL for this variable.  */
-  if (DECL_RTL (decl))
-    /* Only a RESULT_DECL should have non-NULL RTL when arriving here.
-       All other local variables are assigned RTL in this function.  */
-    my_friendly_assert (TREE_CODE (decl) == RESULT_DECL,
-                       19990828);
-  else
-    {
-      if (DECL_ASSEMBLER_NAME (decl) != DECL_NAME (decl))
-       /* The user must have specified an assembler name for this
-          variable.  Set that up now.  */
-       rest_of_decl_compilation
-         (decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
-          /*top_level=*/0, /*at_end=*/0);
-      else
-       expand_decl (decl);
-    }
-
-  /* Actually do the initialization.  */
-  expand_start_target_temps ();
-  expand_decl_init (decl);
-  expand_end_target_temps ();
-}
-
 /* Finish processing of a declaration;
    install its line number and initial value.
    If the length of an array type is not known before,
    it must be determined now, from the initial value, or it is an error.
 
-   INIT0 holds the value of an initializer that should be allowed to escape
+   INIT holds the value of an initializer that should be allowed to escape
    the normal rules.
 
    FLAGS is LOOKUP_ONLYCONVERTING if the = init syntax was used, else 0
@@ -7938,7 +8059,9 @@ cp_finish_decl (decl, init, asmspec_tree, flags)
     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))
@@ -8061,8 +8184,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.  */
@@ -8258,6 +8380,11 @@ start_cleanup_fn ()
      compiler.  */
   TREE_PUBLIC (fndecl) = 0;
   DECL_ARTIFICIAL (fndecl) = 1;
+  /* Make the function `inline' so that it is only emitted if it is
+     actually needed.  It is unlikely that it will be inlined, since
+     it is only called via a function pointer, but we avoid unncessary
+     emissions this way.  */
+  DECL_INLINE (fndecl) = 1;
   /* Build the parameter.  */
   if (flag_use_cxa_atexit)
     {
@@ -8362,19 +8489,19 @@ expand_static_init (decl, init)
   else if (! toplevel_bindings_p ())
     {
       /* Emit code to perform this initialization but once.  */
-      tree temp;
       tree if_stmt;
       tree then_clause;
       tree assignment;
-      tree temp_init;
+      tree guard;
+      tree guard_init;
 
       /* Emit code to perform this initialization but once.  This code
         looks like:
 
-           static int temp = 0;
-           if (!temp) {
+           static int guard = 0;
+           if (!guard) {
              // Do initialization.
-            temp = 1;
+            guard = 1;
             // Register variable for destruction at end of program.
           }
 
@@ -8392,14 +8519,13 @@ expand_static_init (decl, init)
          In theory, this process should be thread-safe, too; multiple
         threads should not be able to initialize the variable more
         than once.  We don't yet attempt to ensure thread-safety.  */
-      temp = get_temp_name (integer_type_node, 1);
-      rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+      /* Create the guard variable.  */
+      guard = get_guard (decl);
 
       /* Begin the conditional initialization.  */
       if_stmt = begin_if_stmt ();
-      finish_if_stmt_cond (build_binary_op (EQ_EXPR, temp,
-                                           integer_zero_node),
-                          if_stmt);
+      finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
       then_clause = begin_compound_stmt (/*has_no_scope=*/0);
 
       /* Do the initialization itself.  */
@@ -8421,16 +8547,16 @@ expand_static_init (decl, init)
         the assignment to TEMP into a single expression, ensuring
         that when we call finish_expr_stmt the cleanups will not be
         run until after TEMP is set to 1.  */
-      temp_init = build_modify_expr (temp, NOP_EXPR, integer_one_node);
+      guard_init = set_guard (guard);
       if (assignment)
        {
          assignment = tree_cons (NULL_TREE, assignment,
                                  build_tree_list (NULL_TREE,
-                                                  temp_init));
+                                                  guard_init));
          assignment = build_compound_expr (assignment);
        }
       else
-       assignment = temp_init;
+       assignment = guard_init;
       finish_expr_stmt (assignment);
 
       /* Use atexit to register a function for destroying this static
@@ -8481,8 +8607,18 @@ complete_array_type (type, initial_value, do_default)
 
   if (initial_value)
     {
-      /* Note MAXINDEX  is really the maximum index,
-        one less than the size.  */
+      /* An array of character type can be initialized from a
+        brace-enclosed string constant.  */
+      if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
+         && TREE_CODE (initial_value) == CONSTRUCTOR
+         && CONSTRUCTOR_ELTS (initial_value)
+         && (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)))
+             == STRING_CST)
+         && TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE)
+       initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (initial_value));
+
+      /* Note MAXINDEX is really the maximum index, one less than the
+        size.  */
       if (TREE_CODE (initial_value) == STRING_CST)
        {
          int eltsize
@@ -8566,11 +8702,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;
@@ -8652,7 +8788,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
   /* If this decl has namespace scope, set that up.  */
   if (in_namespace)
     set_decl_namespace (decl, in_namespace, friendp);
-  else if (publicp && ! ctype)
+  else if (!ctype)
     DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
 
   /* `main' and builtins have implicit 'C' linkage.  */
@@ -8683,8 +8819,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;
     }
@@ -8707,7 +8846,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
        {
          if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
            {
-             if (DECL_LANGUAGE (decl) == lang_c)
+             if (DECL_EXTERN_C_P (decl))
                /* Allow this; it's pretty common in C.  */;
              else
                cp_pedwarn ("non-local function `%#D' uses anonymous type",
@@ -8798,7 +8937,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
   /* Plain overloading: will not be grok'd by grokclassfn.  */
   if (! ctype && ! processing_template_decl
-      && DECL_LANGUAGE (decl) != lang_c
+      && !DECL_EXTERN_C_P (decl)
       && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
     set_mangled_name_for_decl (decl);
 
@@ -8911,7 +9050,16 @@ grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
       type = TREE_TYPE (type);
       decl = build_lang_decl (VAR_DECL, declarator, type);
       DECL_CONTEXT (decl) = basetype;
-      DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
+      /* 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);
+       }
     }
   else
     {
@@ -8935,8 +9083,14 @@ 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)
-       DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
+      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 (in_namespace)
@@ -9027,24 +9181,24 @@ build_ptrmemfunc_type (type)
     {
       u = make_aggr_type (UNION_TYPE);
       SET_IS_AGGR_TYPE (u, 0);
-      fields[0] = build_lang_decl (FIELD_DECL, pfn_identifier, type);
-      fields[1] = build_lang_decl (FIELD_DECL, delta2_identifier,
-                                  delta_type_node);
+      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_lang_decl (FIELD_DECL, delta_identifier,
-                                  delta_type_node);
-      fields[1] = build_lang_decl (FIELD_DECL, index_identifier,
-                                  delta_type_node);
-      fields[2] = build_lang_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
+      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_lang_decl (FIELD_DECL, pfn_identifier, type);
-      fields[1] = build_lang_decl (FIELD_DECL, delta_identifier,
-                                  delta_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);
     }
 
@@ -9161,7 +9315,7 @@ compute_array_index_type (name, size)
     }
 
   /* Normally, the array-bound will be a constant.  */
-  if (TREE_CONSTANT (size))
+  if (TREE_CODE (size) == INTEGER_CST)
     {
       /* Check to see if the array bound overflowed.  Make that an
         error, no matter how generous we're being.  */
@@ -9192,14 +9346,23 @@ compute_array_index_type (name, size)
            cp_pedwarn ("ISO C++ forbids zero-size array");
        }
     }
+  else if (TREE_CONSTANT (size))
+    {
+      /* `(int) &fn' is not a valid array bound.  */
+      if (name)
+       cp_error ("size of array `%D' is not an integral constant-expression",
+                 name);
+      else
+       cp_error ("size of array is not an integral constant-expression");
+    }
 
   /* Compute the index of the largest element in the array.  It is
      one less than the number of elements in the array.  */
   itype
-    = fold (build_binary_op (MINUS_EXPR,
-                            cp_convert (ssizetype, size),
-                            cp_convert (ssizetype,
-                                        integer_one_node)));
+    = fold (cp_build_binary_op (MINUS_EXPR,
+                               cp_convert (ssizetype, size),
+                               cp_convert (ssizetype,
+                                           integer_one_node)));
 
   /* Check for variable-sized arrays.  We allow such things as an
      extension, even though they are not allowed in ANSI/ISO C++.  */
@@ -9633,26 +9796,26 @@ 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);
                name = IDENTIFIER_POINTER (dname);
              }
-           if (! IDENTIFIER_OPNAME_P (dname)
-               /* GNU/Linux headers use '__op'.  Arrgh.  */
-               || (IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)))
+           else if (!IDENTIFIER_TYPENAME_P (dname))
              name = IDENTIFIER_POINTER (dname);
            else
              {
-               if (IDENTIFIER_TYPENAME_P (dname))
-                 {
-                   my_friendly_assert (flags == NO_SPECIAL, 154);
-                   flags = TYPENAME_FLAG;
-                   ctor_return_type = TREE_TYPE (dname);
-                   sfk = sfk_conversion;
-                 }
-               name = operator_name_string (dname);
+               my_friendly_assert (flags == NO_SPECIAL, 154);
+               flags = TYPENAME_FLAG;
+               ctor_return_type = TREE_TYPE (dname);
+               sfk = sfk_conversion;
+               if (IDENTIFIER_GLOBAL_VALUE (dname)
+                   && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (dname)) 
+                       == TYPE_DECL))
+                 name = IDENTIFIER_POINTER (dname);
+               else
+                 name = "<invalid operator>";
              }
            break;
 
@@ -9677,7 +9840,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));
@@ -9885,7 +10048,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            }
        }
       /* C++ aggregate types.  */
-      else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL)
+      else if (TREE_CODE (id) == TYPE_DECL)
        {
          if (type)
            cp_error ("multiple declarations `%T' and `%T'", type,
@@ -10216,10 +10379,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  else
                    tmp = TREE_OPERAND (declarator, 0);
                  op = IDENTIFIER_OPNAME_P (tmp);
+                 if (IDENTIFIER_TYPENAME_P (tmp))
+                   {
+                     if (IDENTIFIER_GLOBAL_VALUE (tmp)
+                         && (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (tmp)) 
+                             == TYPE_DECL))
+                       name = IDENTIFIER_POINTER (tmp);
+                     else
+                       name = "<invalid operator>";
+                   }
                }
              error ("storage class specified for %s `%s'",
                     op ? "member operator" : "field",
-                    op ? operator_name_string (tmp) : name);
+                    name);
            }
          else
            {
@@ -10531,10 +10703,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                if (TREE_CODE (declarator) == BIT_NOT_EXPR)
                  declarator = TREE_OPERAND (declarator, 0);
 
-               if (strict_prototype == 0 && arg_types == NULL_TREE)
-                 arg_types = void_list_node;
-               else if (arg_types == NULL_TREE
-                        || arg_types != void_list_node)
+                if (arg_types != void_list_node)
                  {
                    cp_error ("destructors may not have parameters");
                    arg_types = void_list_node;
@@ -10962,19 +11131,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
              = TYPE_IDENTIFIER (type);
 
-         /* 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;
+         if (flag_new_abi) 
+           DECL_ASSEMBLER_NAME (decl) = mangle_type (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;
+           {
+             /* 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;
+           }
 
          /* FIXME remangle member functions; member functions of a
             type with external linkage have external linkage.  */
@@ -11047,6 +11221,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              inlinep = 0;
            }
 
+         /* Until core issue 180 is resolved, allow 'friend typename A::B'.
+            But don't allow implicit typenames.  */
+         if (!current_aggr && (TREE_CODE (type) != TYPENAME_TYPE
+                               || IMPLICIT_TYPENAME_P (type)))
+           {
+             if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+               cp_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_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)
            {
@@ -11054,8 +11246,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              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;
            }
        }
@@ -11203,10 +11395,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    return void_type_node;
                  }
 
-               if (declarator == ansi_opname[(int) NEW_EXPR]
-                   || declarator == ansi_opname[(int) VEC_NEW_EXPR]
-                   || declarator == ansi_opname[(int) DELETE_EXPR]
-                   || declarator == ansi_opname[(int) VEC_DELETE_EXPR])
+               if (declarator == ansi_opname (NEW_EXPR)
+                   || declarator == ansi_opname (VEC_NEW_EXPR)
+                   || declarator == ansi_opname (DELETE_EXPR)
+                   || declarator == ansi_opname (VEC_DELETE_EXPR))
                  {
                    if (virtualp)
                      {
@@ -11390,11 +11582,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            /* 9.2p13 [class.mem] */
            if (declarator == constructor_name (current_class_type)
-               /* Divergence from the standard:  In extern "C", we
-                  allow non-static data members here, because C does
-                  and /usr/include/netinet/in.h uses that.  */
-               && (staticp || ! in_system_header))
-             cp_pedwarn ("ISO C++ forbids data member `%D' with same name as enclosing class",
+               /* The standard does not allow non-static data members
+                  here either, but we agreed at the 10/99 meeting
+                  to change that in TC 1 so that they are allowed in
+                  classes with no user-defined constructors.  */
+               && staticp)
+             cp_pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
                          declarator);
 
            if (staticp)
@@ -11408,7 +11601,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
              }
            else
              {
-               decl = build_lang_decl (FIELD_DECL, declarator, type);
+               decl = build_decl (FIELD_DECL, declarator, type);
+               DECL_NONADDRESSABLE_P (decl) = bitfield;
                if (RIDBIT_SETP (RID_MUTABLE, specbits))
                  {
                    DECL_MUTABLE_P (decl) = 1;
@@ -11730,7 +11924,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'",
@@ -12071,30 +12266,30 @@ grok_ctor_properties (ctype, decl)
   return 1;
 }
 
-/* An operator with this name can be either unary or binary.  */
+/* An operator with this code is unary, but can also be binary.  */
 
 static int
-ambi_op_p (name)
-     tree name;
+ambi_op_p (code)
+     enum tree_code code;
 {
-  return (name == ansi_opname [(int) INDIRECT_REF]
-         || name == ansi_opname [(int) ADDR_EXPR]
-         || name == ansi_opname [(int) NEGATE_EXPR]
-         || name == ansi_opname[(int) POSTINCREMENT_EXPR]
-         || name == ansi_opname[(int) POSTDECREMENT_EXPR]
-         || name == ansi_opname [(int) CONVERT_EXPR]);
+  return (code == INDIRECT_REF
+         || code == ADDR_EXPR
+         || code == CONVERT_EXPR
+         || code == NEGATE_EXPR
+         || code == PREINCREMENT_EXPR
+         || code == PREDECREMENT_EXPR);
 }
 
 /* An operator with this name can only be unary.  */
 
 static int
-unary_op_p (name)
-     tree name;
+unary_op_p (code)
+     enum tree_code code;
 {
-  return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
-         || name == ansi_opname [(int) BIT_NOT_EXPR]
-         || name == ansi_opname [(int) COMPONENT_REF]
-         || IDENTIFIER_TYPENAME_P (name));
+  return (code == TRUTH_NOT_EXPR
+         || code == BIT_NOT_EXPR
+         || code == COMPONENT_REF
+         || code == TYPE_EXPR);
 }
 
 /* Do a little sanity-checking on how they declared their operator.  */
@@ -12105,43 +12300,87 @@ grok_op_properties (decl, virtualp, friendp)
      int virtualp, friendp;
 {
   tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+  tree argtype;
   int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
   tree name = DECL_NAME (decl);
+  enum tree_code operator_code;
+  int arity;
+
+  /* Count the number of arguments.  */
+  for (argtype = argtypes, arity = 0;
+       argtype && argtype != void_list_node;
+       argtype = TREE_CHAIN (argtype))
+    ++arity;
 
   if (current_class_type == NULL_TREE)
     friendp = 1;
 
+  if (DECL_CONV_FN_P (decl))
+    operator_code = TYPE_EXPR;
+  else
+    do
+      {
+#define DEF_OPERATOR(NAME, CODE, NEW_MANGLING, OLD_MANGING, ARITY, ASSN_P)  \
+       if (ansi_opname (CODE) == name)                                     \
+         {                                                                 \
+           operator_code = CODE;                                           \
+           break;                                                          \
+         }                                                                 \
+       else if (ansi_assopname (CODE) == name)                             \
+         {                                                                 \
+           operator_code = CODE;                                           \
+           DECL_ASSIGNMENT_OPERATOR_P (decl) = 1;                          \
+           break;                                                          \
+         }
+
+#include "operators.def"
+#undef DEF_OPERATOR
+
+       my_friendly_abort (20000527);
+      }
+    while (0);
+  my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
+  SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+
   if (! friendp)
     {
-      /* [class.copy]
+      switch (operator_code)
+       {
+       case CALL_EXPR:
+         TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
+         break;
+         
+       case ARRAY_REF:
+         TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
+         break;
 
-        A user-declared copy assignment operator X::operator= is a
-        non-static non-template member function of class X with
-        exactly one parameter of type X, X&, const X&, volatile X& or
-        const volatile X&.  */
-      if (name == ansi_opname[(int) MODIFY_EXPR]
-         && !(DECL_TEMPLATE_INSTANTIATION (decl)
-              && is_member_template (DECL_TI_TEMPLATE (decl))))
-       ;
-      else if (name == ansi_opname[(int) CALL_EXPR])
-       TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) ARRAY_REF])
-       TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
-      else if (name == ansi_opname[(int) COMPONENT_REF]
-              || name == ansi_opname[(int) MEMBER_REF])
-       TYPE_OVERLOADS_ARROW (current_class_type) = 1;
-      else if (name == ansi_opname[(int) NEW_EXPR])
-       TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) DELETE_EXPR])
-       TYPE_GETS_DELETE (current_class_type) |= 1;
-      else if (name == ansi_opname[(int) VEC_NEW_EXPR])
-       TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
-      else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
-       TYPE_GETS_DELETE (current_class_type) |= 2;
-    }
-
-  if (name == ansi_opname[(int) NEW_EXPR]
-      || name == ansi_opname[(int) VEC_NEW_EXPR])
+       case COMPONENT_REF:
+       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;
+
+       default:
+         break;
+       }
+    }
+
+  if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
     {
       /* When the compiler encounters the definition of A::operator new, it
         doesn't look at the class declaration to find out if it's static.  */
@@ -12157,8 +12396,7 @@ grok_op_properties (decl, virtualp, friendp)
       else
        TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
     }
-  else if (name == ansi_opname[(int) DELETE_EXPR]
-          || name == ansi_opname[(int) VEC_DELETE_EXPR])
+  else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
     {
       if (methodp)
        revert_static_member_fn (decl);
@@ -12178,11 +12416,11 @@ grok_op_properties (decl, virtualp, friendp)
         an enumeration, or a reference to an enumeration.  13.4.0.6 */
       if (! methodp || DECL_STATIC_FUNCTION_P (decl))
        {
-         if (IDENTIFIER_TYPENAME_P (name)
-             || name == ansi_opname[(int) CALL_EXPR]
-             || name == ansi_opname[(int) MODIFY_EXPR]
-             || name == ansi_opname[(int) COMPONENT_REF]
-             || name == ansi_opname[(int) ARRAY_REF])
+         if (operator_code == TYPE_EXPR
+             || operator_code == CALL_EXPR
+             || operator_code == COMPONENT_REF
+             || operator_code == ARRAY_REF
+             || operator_code == NOP_EXPR)
            cp_error ("`%D' must be a nonstatic member function", decl);
          else
            {
@@ -12202,7 +12440,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
@@ -12213,7 +12451,7 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
 
-      if (name == ansi_opname[(int) CALL_EXPR])
+      if (operator_code == CALL_EXPR)
        return;                 /* No restrictions on args. */
 
       if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
@@ -12243,18 +12481,27 @@ grok_op_properties (decl, virtualp, friendp)
            }
        }
 
-      if (name == ansi_opname[(int) MODIFY_EXPR])
+      if (DECL_ASSIGNMENT_OPERATOR_P (decl) 
+         && operator_code == NOP_EXPR)
        {
          tree parmtype;
 
-         if (list_length (argtypes) != 3 && methodp)
+         if (arity != 2 && methodp)
            {
              cp_error ("`%D' must take exactly one argument", decl);
              return;
            }
          parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
 
+         /* [class.copy]
+
+            A user-declared copy assignment operator X::operator= is
+            a non-static non-template member function of class X with
+            exactly one parameter of type X, X&, const X&, volatile
+            X& or const volatile X&.  */
          if (copy_assignment_arg_p (parmtype, virtualp)
+             && !(DECL_TEMPLATE_INSTANTIATION (decl)
+                  && is_member_template (DECL_TI_TEMPLATE (decl)))
              && ! friendp)
            {
              TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
@@ -12263,19 +12510,55 @@ grok_op_properties (decl, virtualp, friendp)
                TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
            }
        }
-      else if (name == ansi_opname[(int) COND_EXPR])
+      else if (operator_code == COND_EXPR)
        {
          /* 13.4.0.3 */
          cp_error ("ISO C++ prohibits overloading operator ?:");
        }
-      else if (ambi_op_p (name))
+      else if (ambi_op_p (operator_code))
        {
-         if (list_length (argtypes) == 2)
-           /* prefix */;
-         else if (list_length (argtypes) == 3)
+         if (arity == 1)
+           /* We pick the one-argument operator codes by default, so
+              we don't have to change anything.  */
+           ;
+         else if (arity == 2)
            {
-             if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
-                  || name == ansi_opname[(int) POSTDECREMENT_EXPR])
+             /* If we thought this was a unary operator, we now know
+                it to be a binary operator.  */
+             switch (operator_code)
+               {
+               case INDIRECT_REF:
+                 operator_code = MULT_EXPR;
+                 break;
+
+               case ADDR_EXPR:
+                 operator_code = BIT_AND_EXPR;
+                 break;
+
+               case CONVERT_EXPR:
+                 operator_code = PLUS_EXPR;
+                 break;
+
+               case NEGATE_EXPR:
+                 operator_code = MINUS_EXPR;
+                 break;
+
+               case PREINCREMENT_EXPR:
+                 operator_code = POSTINCREMENT_EXPR;
+                 break;
+
+               case PREDECREMENT_EXPR:
+                 operator_code = POSTDECREMENT_EXPR;
+                 break;
+
+               default:
+                 my_friendly_abort (20000527);
+               }
+
+             SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
+
+             if ((operator_code == POSTINCREMENT_EXPR
+                  || operator_code == POSTDECREMENT_EXPR)
                  && ! processing_template_decl
                  && ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
                {
@@ -12298,15 +12581,18 @@ grok_op_properties (decl, virtualp, friendp)
 
          /* More Effective C++ rule 6.  */
          if (warn_ecpp
-             && (name == ansi_opname[(int) POSTINCREMENT_EXPR]
-                 || name == ansi_opname[(int) POSTDECREMENT_EXPR]))
+             && (operator_code == POSTINCREMENT_EXPR
+                 || operator_code == POSTDECREMENT_EXPR
+                 || operator_code == PREINCREMENT_EXPR
+                 || operator_code == PREDECREMENT_EXPR))
            {
              tree arg = TREE_VALUE (argtypes);
              tree ret = TREE_TYPE (TREE_TYPE (decl));
              if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
                arg = TREE_TYPE (arg);
              arg = TYPE_MAIN_VARIANT (arg);
-             if (list_length (argtypes) == 2)
+             if (operator_code == PREINCREMENT_EXPR
+                 || operator_code == PREDECREMENT_EXPR)
                {
                  if (TREE_CODE (ret) != REFERENCE_TYPE
                      || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
@@ -12321,9 +12607,9 @@ grok_op_properties (decl, virtualp, friendp)
                }
            }
        }
-      else if (unary_op_p (name))
+      else if (unary_op_p (operator_code))
        {
-         if (list_length (argtypes) != 2)
+         if (arity != 1)
            {
              if (methodp)
                cp_error ("`%D' must take `void'", decl);
@@ -12331,9 +12617,9 @@ grok_op_properties (decl, virtualp, friendp)
                cp_error ("`%D' must take exactly one argument", decl);
            }
        }
-      else /* if (binary_op_p (name)) */
+      else /* if (binary_op_p (operator_code)) */
        {
-         if (list_length (argtypes) != 3)
+         if (arity != 2)
            {
              if (methodp)
                cp_error ("`%D' must take exactly one argument", decl);
@@ -12343,20 +12629,20 @@ grok_op_properties (decl, virtualp, friendp)
 
          /* More Effective C++ rule 7.  */
          if (warn_ecpp
-             && (name == ansi_opname [TRUTH_ANDIF_EXPR]
-                 || name == ansi_opname [TRUTH_ORIF_EXPR]
-                 || name == ansi_opname [COMPOUND_EXPR]))
+             && (operator_code == TRUTH_ANDIF_EXPR
+                 || operator_code == TRUTH_ORIF_EXPR
+                 || operator_code == COMPOUND_EXPR))
            cp_warning ("user-defined `%D' always evaluates both arguments",
                        decl);
        }
 
       /* Effective C++ rule 23.  */
       if (warn_ecpp
-         && list_length (argtypes) == 3
-         && (name == ansi_opname [PLUS_EXPR]
-             || name == ansi_opname [MINUS_EXPR]
-             || name == ansi_opname [TRUNC_DIV_EXPR]
-             || name == ansi_opname [MULT_EXPR])
+         && arity == 2
+         && (operator_code == PLUS_EXPR
+             || operator_code == MINUS_EXPR
+             || operator_code == TRUNC_DIV_EXPR
+             || operator_code == MULT_EXPR)
          && TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
        cp_warning ("`%D' should return by value", decl);
 
@@ -12366,8 +12652,8 @@ grok_op_properties (decl, virtualp, friendp)
         if (TREE_PURPOSE (argtypes))
           {
             TREE_PURPOSE (argtypes) = NULL_TREE;
-            if (name == ansi_opname[(int) POSTINCREMENT_EXPR] 
-                || name == ansi_opname[(int) POSTDECREMENT_EXPR])   
+            if (operator_code == POSTINCREMENT_EXPR
+               || operator_code == POSTDECREMENT_EXPR)
               {
                 if (pedantic)
                   cp_pedwarn ("`%D' cannot have default arguments", decl);
@@ -12460,8 +12746,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)
@@ -12572,6 +12874,7 @@ xref_tag (code_type_node, name, globalize)
             to avoid crashing if it does not get defined.  */
          TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
          TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
+         TYPE_USER_ALIGN (ref) = 0;
          TREE_UNSIGNED (ref) = 1;
          TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
          TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
@@ -12706,7 +13009,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));
@@ -12942,7 +13245,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
     {
@@ -12985,6 +13288,7 @@ finish_enum (enumtype)
          TYPE_MODE (tem) = TYPE_MODE (enumtype);
          TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
          TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+         TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
          TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
        }
 
@@ -13043,9 +13347,9 @@ build_enumerator (name, value, enumtype)
              /* The next value is the previous value ... */
              prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
              /* ... plus one.  */
-             value = build_binary_op (PLUS_EXPR,
-                                      prev_value,
-                                      integer_one_node);
+             value = cp_build_binary_op (PLUS_EXPR,
+                                         prev_value,
+                                         integer_one_node);
 
              if (tree_int_cst_lt (value, prev_value))
                cp_error ("overflow in enumeration values at `%D'", name);
@@ -13095,7 +13399,7 @@ build_enumerator (name, value, enumtype)
 
   if (context && context == current_class_type)
     /* This enum declaration is local to the class.  We need the full
-      lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
+       lang_decl so that we can record DECL_CLASS_CONTEXT, for example.  */
     decl = build_lang_decl (CONST_DECL, name, type);
   else
     /* It's a global enum, or it's local to a function.  (Note local to
@@ -13122,13 +13426,12 @@ build_enumerator (name, value, enumtype)
 }
 
 \f
-static int function_depth;
-
 /* 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));
@@ -13170,9 +13473,7 @@ check_function_type (decl)
    FLAGS is a bitwise or of SF_PRE_PARSED (indicating that the
    DECLARATOR is really the DECL for the function we are about to
    process and that DECLSPECS should be ignored), SF_INCLASS_INLINE
-   indicating that the function is an inline defined in-class, and
-   SF_EXPAND indicating that we should generate RTL for this
-   function.
+   indicating that the function is an inline defined in-class.
 
    This function creates a binding context for the function body
    as well as setting up the FUNCTION_DECL in current_function_decl.
@@ -13199,6 +13500,7 @@ start_function (declspecs, declarator, attrs, flags)
   extern int used_extern_spec;
   int doing_friend = 0;
   struct binding_level *bl;
+  tree current_function_parms;
 
   /* Sanity check.  */
   my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
@@ -13308,9 +13610,9 @@ 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_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
+      && DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
       && TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
     cp_warning ("`operator=' should return a reference to `*this'");
 
@@ -13346,7 +13648,7 @@ start_function (declspecs, declarator, attrs, flags)
      you declare a function, these types can be incomplete, but they
      must be complete when you define the function.  */
   if (! processing_template_decl)
-    check_function_type (decl1);
+    check_function_type (decl1, current_function_parms);
 
   /* Build the return declaration for the function.  */
   restype = TREE_TYPE (fntype);
@@ -13371,7 +13673,6 @@ start_function (declspecs, declarator, attrs, flags)
   bl = current_binding_level;
   init_function_start (decl1, input_filename, lineno);
   current_binding_level = bl;
-  expanding_p = (flags & SF_EXPAND) != 0;
 
   /* Even though we're inside a function body, we still don't want to
      call expand_expr to calculate the size of a variable-sized array.
@@ -13380,13 +13681,11 @@ 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.  */
-  if (processing_template_decl || !building_stmt_tree ())
-    announce_function (decl1);
+  announce_function (decl1);
 
   /* Record the decl so that the function name is defined.
      If we already have a decl for this name, and it is a FUNCTION_DECL,
@@ -13394,8 +13693,7 @@ start_function (declspecs, declarator, attrs, flags)
   if (!processing_template_decl && !(flags & SF_PRE_PARSED))
     {
       /* A specialization is not used to guide overload resolution.  */
-      if ((flag_guiding_decls
-          || !DECL_TEMPLATE_SPECIALIZATION (decl1))
+      if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
          && ! DECL_FUNCTION_MEMBER_P (decl1))
        decl1 = pushdecl (decl1);
       else
@@ -13413,29 +13711,16 @@ start_function (declspecs, declarator, attrs, flags)
   current_function_decl = decl1;
   cfun->decl = decl1;
 
-  /* Initialize the per-function data.  */
-  if (!DECL_PENDING_INLINE_P (decl1) && DECL_SAVED_FUNCTION_DATA (decl1))
+  /* If we are (erroneously) defining a function that we have already
+     defined before, wipe out what we knew before.  */
+  if (!DECL_PENDING_INLINE_P (decl1) 
+      && DECL_SAVED_FUNCTION_DATA (decl1))
     {
-      /* If we already parsed this function, and we're just expanding it
-        now, restore saved state.  */
-      struct binding_level *bl = current_binding_level;
-      *cp_function_chain = *DECL_SAVED_FUNCTION_DATA (decl1);
-      current_binding_level = bl;
-
-      /* This function is being processed in whole-function mode; we
-        already did semantic analysis.  */
-      cfun->x_whole_function_mode_p = 1;
-
-      /* If we decided that we didn't want to inline this function,
-        make sure the back-end knows that.  */
-      if (!current_function_cannot_inline)
-       current_function_cannot_inline = cp_function_chain->cannot_inline;
-
-      /* We don't need the saved data anymore.  */
       free (DECL_SAVED_FUNCTION_DATA (decl1));
       DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
     }
-  else if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
+
+  if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
     {
       /* We know that this was set up by `grokclassfn'.  We do not
         wait until `store_parm_decls', since evil parse errors may
@@ -13523,20 +13808,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_function_rtl (decl1);
 
   /* Promote the value to int before returning it.  */
   if (C_PROMOTING_INTEGER_TYPE_P (restype))
@@ -13573,25 +13853,20 @@ start_function (declspecs, declarator, attrs, flags)
       DECL_CONTEXT (ctor_label) = current_function_decl;
     }
 
+  store_parm_decls (current_function_parms);
+
   return 1;
 }
 \f
-/* Called after store_parm_decls for a function-try-block.  */
-
-void
-expand_start_early_try_stmts ()
-{
-  expand_start_try_stmts ();
-}
-
 /* Store the parameter declarations into the current function declaration.
    This is called after parsing the parameter declarations, before
    digesting the body of the function.
 
    Also install to binding contour return value identifier, if any.  */
 
-void
-store_parm_decls ()
+static void
+store_parm_decls (current_function_parms)
+     tree current_function_parms;
 {
   register tree fndecl = current_function_decl;
   register tree parm;
@@ -13606,10 +13881,6 @@ store_parm_decls ()
      then CONST_DECLs for foo and bar are put here.  */
   tree nonparms = NULL_TREE;
 
-  /* Create a binding level for the parms.  */
-  if (!building_stmt_tree ())
-    expand_start_bindings (2);
-
   if (current_function_parms)
     {
       /* This case is when the function was defined with an ANSI prototype.
@@ -13620,45 +13891,34 @@ store_parm_decls ()
       tree specparms = current_function_parms;
       tree next;
 
-      if (doing_semantic_analysis_p ())
-       {
-         /* Must clear this because it might contain TYPE_DECLs declared
+      /* Must clear this because it might contain TYPE_DECLs declared
             at class level.  */
-         storedecls (NULL_TREE);
+      storedecls (NULL_TREE);
 
-         /* If we're doing semantic analysis, then we'll call pushdecl
+      /* If we're doing semantic analysis, then we'll call pushdecl
             for each of these.  We must do them in reverse order so that
             they end in the correct forward order.  */
-         specparms = nreverse (specparms);
-       }
+      specparms = nreverse (specparms);
 
       for (parm = specparms; parm; parm = next)
        {
          next = TREE_CHAIN (parm);
          if (TREE_CODE (parm) == PARM_DECL)
            {
-             tree type = TREE_TYPE (parm);
-
-             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
            {
@@ -13669,14 +13929,11 @@ store_parm_decls ()
            }
        }
 
-      if (doing_semantic_analysis_p ())
-       {
-         /* Get the decls in their original chain order
-            and record in the function.  This is all and only the
-            PARM_DECLs that were pushed into scope by the loop above.  */
-         DECL_ARGUMENTS (fndecl) = getdecls ();
-         storetags (chainon (parmtags, gettags ()));
-       }
+      /* Get the decls in their original chain order and record in the
+        function.  This is all and only the PARM_DECLs that were
+        pushed into scope by the loop above.  */
+      DECL_ARGUMENTS (fndecl) = getdecls ();
+      storetags (chainon (parmtags, gettags ()));
     }
   else
     DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -13685,20 +13942,7 @@ store_parm_decls ()
      as the decl-chain of the current lexical scope.
      Put the enumerators in as well, at the front so that
      DECL_ARGUMENTS is not modified.  */
-  if (doing_semantic_analysis_p ())
-    storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
-
-  /* Initialize the RTL code for the function.  */
-  DECL_SAVED_INSNS (fndecl) = 0;
-  if (! building_stmt_tree ())
-    expand_function_start (fndecl, parms_have_cleanups);
-
-  current_function_parms_stored = 1;
-
-  /* If this function is `main', emit a call to `__main'
-     to run global initializers, etc.  */
-  if (DECL_MAIN_P (fndecl) && !building_stmt_tree ())
-    expand_main_function ();
+  storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
 
   /* Now that we have initialized the parms, we can start their
      cleanups.  We cannot do this before, since expand_decl_cleanup
@@ -13711,46 +13955,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));
-    }
-}
-
 \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
@@ -13760,7 +13975,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.  */
@@ -13768,18 +13983,15 @@ save_function_data (decl)
                      19990908);
 
   /* Make a copy.  */
-  f = ((struct language_function *)
-       xmalloc (sizeof (struct language_function)));
+  f = ((struct cp_language_function *)
+       xmalloc (sizeof (struct cp_language_function)));
   bcopy ((char *) cp_function_chain, (char *) f,
-        sizeof (struct language_function));
+        sizeof (struct cp_language_function));
   DECL_SAVED_FUNCTION_DATA (decl) = f;
 
   /* Clear out the bits we don't need.  */
-  f->x_base_init_list = NULL_TREE;
-  f->x_member_init_list = NULL_TREE;
-  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;
 
@@ -13800,7 +14012,7 @@ finish_constructor_body ()
 {
   /* Any return from a constructor will end up here.  */
   if (ctor_label)
-    add_tree (build_min_nt (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.  */
@@ -13809,7 +14021,7 @@ finish_constructor_body ()
      constructor to a return of `this'.  */
   finish_return_stmt (NULL_TREE);
   /* Mark the end of the constructor.  */
-  add_tree (build_min_nt (CTOR_STMT));
+  add_stmt (build_stmt (CTOR_STMT));
 }
 
 /* At the end of every destructor we generate code to restore virtual
@@ -13828,7 +14040,7 @@ finish_destructor_body ()
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
 
   /* Any return from a destructor will end up here.  */
-  add_tree (build_min_nt (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
@@ -13842,7 +14054,7 @@ finish_destructor_body ()
 
   exprstmt = build_delete (current_class_type,
                           current_class_ref,
-                          integer_zero_node,
+                          sfk_base_destructor,
                           LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL,
                           0);
 
@@ -13859,26 +14071,34 @@ finish_destructor_body ()
       /* Run destructors for all virtual baseclasses.  */
       if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
        {
-         tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
-         tree if_stmt = begin_if_stmt ();
+         tree vbases;
+         tree if_stmt;
+
+         if_stmt = begin_if_stmt ();
          finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
                                      current_in_charge_parm,
                                      integer_two_node),
                               if_stmt);
 
-         while (vbases)
+         vbases = CLASSTYPE_VBASECLASSES (current_class_type);
+         /* The CLASSTYPE_VBASECLASSES list is in initialization
+            order, so we have to march through it in reverse order.  */
+         for (vbases = nreverse (copy_list (vbases));
+              vbases;
+              vbases = TREE_CHAIN (vbases))
            {
-             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbases)))
+             tree vbase = TREE_VALUE (vbases);
+
+             if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (BINFO_TYPE (vbase)))
                {
                  tree vb = get_vbase
-                   (BINFO_TYPE (vbases),
+                   (BINFO_TYPE (vbase),
                     TYPE_BINFO (current_class_type));
                  finish_expr_stmt
                    (build_scoped_method_call
                     (current_class_ref, vb, base_dtor_identifier,
                      NULL_TREE));
                }
-             vbases = TREE_CHAIN (vbases);
            }
 
          finish_then_clause (if_stmt);
@@ -13936,13 +14156,9 @@ finish_function (flags)
 {
   register tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
-  /* Label to use if this function is supposed to return a value.  */
-  tree no_return_label = NULL_TREE;
   int call_poplevel = (flags & 1) != 0;
   int inclass_inline = (flags & 2) != 0;
-  int expand_p;
   int nested;
-  int current_line = lineno;
 
   /* When we get some parse errors, we can end up without a
      current_function_decl, so cope.  */
@@ -13956,18 +14172,11 @@ finish_function (flags)
       This caused &foo to be of type ptr-to-const-function
       which then got a warning when stored in a ptr-to-function variable.  */
 
-  /* This happens on strange parse errors.  */
-  if (! current_function_parms_stored)
-    {
-      call_poplevel = 0;
-      store_parm_decls ();
-    }
+  my_friendly_assert (building_stmt_tree (), 20000911);
 
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
-  if (building_stmt_tree () && DECL_CLONED_FUNCTION_P (fndecl))
-    ;
-  else if (building_stmt_tree ())
+  if (!DECL_CLONED_FUNCTION_P (fndecl))
     {
       if (DECL_CONSTRUCTOR_P (fndecl))
        {
@@ -13995,132 +14204,16 @@ finish_function (flags)
                            (TREE_TYPE (current_function_decl)),
                            current_eh_spec_try_block);
     }
-  else
-    {
-#if 0
-      if (write_symbols != NO_DEBUG /*&& TREE_CODE (fntype) != METHOD_TYPE*/)
-       {
-         /* Keep this code around in case we later want to control debug info
-            based on whether a type is "used".  (jason 1999-11-11) */
-
-         tree ttype = target_type (fntype);
-         tree parmdecl;
-
-         if (IS_AGGR_TYPE (ttype))
-           /* Let debugger know it should output info for this type.  */
-           note_debug_info_needed (ttype);
-
-         for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
-           {
-             ttype = target_type (TREE_TYPE (parmdecl));
-             if (IS_AGGR_TYPE (ttype))
-               /* Let debugger know it should output info for this type.  */
-               note_debug_info_needed (ttype);
-           }
-       }
-#endif
-
-      /* Clean house because we will need to reorder insns here.  */
-      do_pending_stack_adjust ();
-
-      if (dtor_label)
-       ;
-      else if (DECL_CONSTRUCTOR_P (fndecl))
-       {
-         if (call_poplevel)
-           do_poplevel ();
-       }
-      else if (return_label != NULL_RTX
-              && flag_this_is_variable <= 0
-              && current_function_return_value == NULL_TREE
-              && ! DECL_NAME (DECL_RESULT (current_function_decl)))
-       no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-
-      if (flag_exceptions)
-       expand_exception_blocks ();
-
-      /* If this function is supposed to return a value, ensure that
-        we do not fall into the cleanups by mistake.  The end of our
-        function will look like this:
-
-        user code (may have return stmt somewhere)
-        goto no_return_label
-        cleanup_label:
-        cleanups
-        goto return_label
-        no_return_label:
-        NOTE_INSN_FUNCTION_END
-        return_label:
-        things for return
-
-        If the user omits a return stmt in the USER CODE section, we
-        will have a control path which reaches NOTE_INSN_FUNCTION_END.
-        Otherwise, we won't.  */
-      if (no_return_label)
-       {
-         DECL_CONTEXT (no_return_label) = fndecl;
-         DECL_INITIAL (no_return_label) = error_mark_node;
-         DECL_SOURCE_FILE (no_return_label) = input_filename;
-         DECL_SOURCE_LINE (no_return_label) = current_line;
-         expand_goto (no_return_label);
-       }
-
-      if (cleanup_label)
-       {
-         /* Remove the binding contour which is used
-            to catch cleanup-generated temporaries.  */
-         expand_end_bindings (0, 0, 0);
-         poplevel (0, 0, 0);
-
-         /* Emit label at beginning of cleanup code for parameters.  */
-         emit_label (cleanup_label);
-       }
-
-      /* Get return value into register if that's where it's supposed
-        to be.  */
-      if (original_result_rtx)
-       fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
-
-      /* Finish building code that will trigger warnings if users forget
-        to make their functions return values.  */
-      if (no_return_label || cleanup_label)
-       emit_jump (return_label);
-      if (no_return_label)
-       {
-         /* We don't need to call `expand_*_return' here because we
-            don't need any cleanups here--this path of code is only
-            for error checking purposes.  */
-         expand_label (no_return_label);
-       }
-
-      /* We hard-wired immediate_size_expand to zero in
-        start_function.  Expand_function_end will decrement this
-        variable.  So, we set the variable to one here, so that after
-        the decrement it will remain zero.  */
-      immediate_size_expand = 1;
-
-      /* Generate rtl for function exit.  */
-      expand_function_end (input_filename, current_line, 1);
-    }
-
-  /* We have to save this value here in case
-     maybe_end_member_template_processing decides to pop all the
-     template parameters.  */
-  expand_p = !building_stmt_tree ();
 
   /* If we're saving up tree structure, tie off the function now.  */
-  if (!expand_p)
-    finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+  finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
      this function's blocks.  */
-  if (doing_semantic_analysis_p ())
-    {
-      if (current_binding_level->parm_flag != 1)
-       my_friendly_abort (122);
-      poplevel (1, 0, 1);
-    }
+  if (current_binding_level->parm_flag != 1)
+    my_friendly_abort (122);
+  poplevel (1, 0, 1);
 
   /* Remember that we were in class scope.  */
   if (current_class_name)
@@ -14134,7 +14227,7 @@ finish_function (flags)
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
 
   /* Save away current state, if appropriate.  */
-  if (!expanding_p && !processing_template_decl)
+  if (!processing_template_decl)
     save_function_data (fndecl);
 
   /* If this function calls `setjmp' it cannot be inlined.  When
@@ -14146,90 +14239,15 @@ finish_function (flags)
      this function to modify local variables in `c', but their
      addresses may have been stored somewhere accessible to this
      function.)  */
-  if (!expanding_p && !processing_template_decl && calls_setjmp_p (fndecl))
+  if (!processing_template_decl && calls_setjmp_p (fndecl))
     DECL_UNINLINABLE (fndecl) = 1;
 
-  if (expand_p)
-    {
-      int returns_null;
-      int returns_value;
-
-      /* So we can tell if jump_optimize sets it to 1.  */
-      can_reach_end = 0;
-
-      /* Before we call rest_of_compilation (which will pop the
-        CURRENT_FUNCTION), we must save these values.  */
-      returns_null = current_function_returns_null;
-      returns_value = current_function_returns_value;
-
-      /* If this is a nested function (like a template instantiation
-        that we're compiling in the midst of compiling something
-        else), push a new GC context.  That will keep local variables
-        on the stack from being collected while we're doing the
-        compilation of this function.  */
-      if (function_depth > 1)
-       ggc_push_context ();
-
-      /* Run the optimizers and output the assembler code for this
-         function.  */
-      rest_of_compilation (fndecl);
-
-      /* Undo the call to ggc_push_context above.  */
-      if (function_depth > 1)
-       ggc_pop_context ();
-
-      if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
-       {
-         /* Set DECL_EXTERNAL so that assemble_external will be called as
-            necessary.  We'll clear it again in finish_file.  */
-         if (! DECL_EXTERNAL (fndecl))
-           DECL_NOT_REALLY_EXTERN (fndecl) = 1;
-         DECL_EXTERNAL (fndecl) = 1;
-         defer_fn (fndecl);
-       }
-
-#if 0
-      /* Keep this code around in case we later want to control debug info
-        based on whether a type is "used".  (jason 1999-11-11) */
-
-      if (ctype && TREE_ASM_WRITTEN (fndecl))
-       note_debug_info_needed (ctype);
-#endif
-
-      returns_null |= can_reach_end;
-
-      /* Since we don't normally go through c_expand_return for constructors,
-        this normally gets the wrong value.
-        Also, named return values have their return codes emitted after
-        NOTE_INSN_FUNCTION_END, confusing jump.c.  */
-      if (DECL_CONSTRUCTOR_P (fndecl)
-         || DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
-       returns_null = 0;
-
-      if (TREE_THIS_VOLATILE (fndecl) && returns_null)
-       cp_warning ("`noreturn' function `%D' does return", fndecl);
-      else if ((warn_return_type || pedantic)
-              && returns_null
-              && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
-       {
-         /* If this function returns non-void and control can drop through,
-            complain.  */
-         cp_warning ("control reaches end of non-void function `%D'", fndecl);
-       }
-      /* With just -W, complain only if function returns both with
-        and without a value.  */
-      else if (extra_warnings && returns_value && returns_null)
-       warning ("this function may return with or without a value");
-    }
-  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
@@ -14244,24 +14262,6 @@ finish_function (flags)
 
   --function_depth;
 
-  if (!DECL_SAVED_INSNS (fndecl) && !DECL_SAVED_FUNCTION_DATA (fndecl)
-      && !(flag_inline_trees && DECL_INLINE (fndecl)))
-    {
-      tree t;
-
-      /* Stop pointing to the local nodes about to be freed.  */
-      /* But DECL_INITIAL must remain nonzero so we know this
-        was an actual function definition.  */
-      DECL_INITIAL (fndecl) = error_mark_node;
-      for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
-       DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
-    }
-
-  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)
     {
@@ -14323,8 +14323,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;
     }
@@ -14502,14 +14502,15 @@ hack_incomplete_structures (type)
     }
 }
 
-/* If DECL is of a type which needs a cleanup, build that cleanup here.
-   See build_delete for information about AUTO_DELETE.  */
+/* If DECL is of a type which needs a cleanup, build that cleanup
+   here.  */
 
-static tree
-maybe_build_cleanup_1 (decl, auto_delete)
-     tree decl, auto_delete;
+tree
+maybe_build_cleanup (decl)
+     tree decl;
 {
   tree type = TREE_TYPE (decl);
+
   if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
     {
       int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
@@ -14528,7 +14529,8 @@ maybe_build_cleanup_1 (decl, auto_delete)
          || flag_expensive_optimizations)
        flags |= LOOKUP_NONVIRTUAL;
 
-      rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0);
+      rval = build_delete (TREE_TYPE (rval), rval,
+                          sfk_complete_destructor, flags, 0);
 
       if (TYPE_USES_VIRTUAL_BASECLASSES (type)
          && ! TYPE_HAS_DESTRUCTOR (type))
@@ -14539,42 +14541,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
     }
   return 0;
 }
-
-/* If DECL is of a type which needs a cleanup, build that cleanup
-   here.  The cleanup does not free the storage with a call a delete.  */
-
-tree
-maybe_build_cleanup (decl)
-     tree decl;
-{
-  return maybe_build_cleanup_1 (decl, integer_two_node);
-}
 \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
@@ -14620,10 +14587,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.  */
@@ -14631,7 +14598,7 @@ push_cp_function_context (f)
 
   /* Whenever we start a new function, we destroy temporaries in the
      usual way.  */
-  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
@@ -14650,24 +14617,20 @@ pop_cp_function_context (f)
 
 static void
 mark_lang_function (p)
-     struct language_function *p;
+     struct cp_language_function *p;
 {
   if (!p)
     return;
 
-  ggc_mark_tree (p->x_named_labels);
+  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_base_init_list);
-  ggc_mark_tree (p->x_member_init_list);
   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_stmt_tree (&p->x_stmt_tree);
+  mark_named_label_lists (&p->x_named_labels, &p->x_named_label_uses);
   mark_binding_level (&p->bindings);
 }
 
@@ -14677,15 +14640,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
@@ -14728,9 +14683,13 @@ lang_mark_tree (t)
       if (ld)
        {
          ggc_mark (ld);
-         if (!DECL_GLOBAL_CTOR_P (t) && !DECL_GLOBAL_DTOR_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);
-         ggc_mark_tree (ld->decl_flags.context);
+         else if (DECL_THUNK_P (t))
+           ggc_mark_tree (ld->decl_flags.u2.vcall_offset);
          if (TREE_CODE (t) != NAMESPACE_DECL)
            ggc_mark_tree (ld->decl_flags.u.template_info);
          else
@@ -14738,8 +14697,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 (TREE_CODE (t) == TYPE_DECL)
                ggc_mark_tree (ld->u.sorted_fields);
              else if (TREE_CODE (t) == FUNCTION_DECL
@@ -14756,10 +14717,10 @@ lang_mark_tree (t)
                  && TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE))
        {
          ggc_mark (lt);
+         ggc_mark_tree (lt->primary_base);
          ggc_mark_tree (lt->vfields);
          ggc_mark_tree (lt->vbases);
          ggc_mark_tree (lt->tags);
-         ggc_mark_tree (lt->search_slot);
          ggc_mark_tree (lt->size);
          ggc_mark_tree (lt->pure_virtuals);
          ggc_mark_tree (lt->friend_classes);