OSDN Git Service

For gcc:
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index cf7ce61..1b6b268 100644 (file)
@@ -61,9 +61,8 @@ extern tree current_namespace;
 extern tree global_namespace;
 
 extern void (*print_error_function) PROTO((char *));
+extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
 
-/* Stack of places to restore the search obstack back to.  */
-   
 /* Obstack used for remembering local class declarations (like
    enums and static (const) members.  */
 #include "stack.h"
@@ -134,7 +133,7 @@ static struct stack_level *decl_stack;
 
 static tree grokparms                          PROTO((tree, int));
 static tree lookup_nested_type                 PROTO((tree, tree));
-static char *redeclaration_error_message       PROTO((tree, tree));
+static const char *redeclaration_error_message PROTO((tree, tree));
 
 static struct stack_level *push_decl_level PROTO((struct stack_level *,
                                                  struct obstack *));
@@ -147,7 +146,6 @@ static struct binding_level *make_binding_level PROTO((void));
 static void declare_namespace_level PROTO((void));
 static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
 static void storedecls PROTO((tree));
-static void storetags PROTO((tree));
 static void require_complete_types_for_parms PROTO((tree));
 static void push_overloaded_decl_1 PROTO((tree));
 static int ambi_op_p PROTO((tree));
@@ -161,16 +159,16 @@ static void warn_extern_redeclared_static PROTO((tree, tree));
 static void grok_reference_init PROTO((tree, tree, tree));
 static tree grokfndecl PROTO((tree, tree, tree, tree, int,
                              enum overload_flags, tree,
-                             tree, tree, int, int, int, int, int, int, tree));
+                             tree, int, int, int, int, int, int, tree));
 static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
 static tree lookup_tag PROTO((enum tree_code, tree,
                              struct binding_level *, int));
 static void set_identifier_type_value_with_scope
        PROTO((tree, tree, struct binding_level *));
-static void record_builtin_type PROTO((enum rid, char *, tree));
-static void record_unknown_type PROTO((tree, char *));
-static int member_function_or_else PROTO((tree, tree, char *));
-static void bad_specifiers PROTO((tree, char *, int, int, int, int,
+static void record_builtin_type PROTO((enum rid, const char *, tree));
+static void record_unknown_type PROTO((tree, const char *));
+static int member_function_or_else PROTO((tree, tree, const char *));
+static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
                                  int));
 static void lang_print_error_function PROTO((char *));
 static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
@@ -178,9 +176,22 @@ static void check_for_uninitialized_const_var PROTO((tree));
 static unsigned long typename_hash PROTO((hash_table_key));
 static boolean typename_compare PROTO((hash_table_key, hash_table_key));
 static void push_binding PROTO((tree, tree, struct binding_level*));
-static void add_binding PROTO((tree, tree));
+static int add_binding PROTO((tree, tree));
 static void pop_binding PROTO((tree, tree));
 static tree local_variable_p PROTO((tree));
+static tree find_binding PROTO((tree, tree));
+static tree select_decl PROTO((tree, int));
+static tree unqualified_namespace_lookup PROTO((tree, int));
+static int lookup_flags PROTO((int, int));
+static tree qualify_lookup PROTO((tree, int));
+static tree record_builtin_java_type PROTO((const char *, int));
+static const char *tag_name PROTO((enum tag_types code));
+static void find_class_binding_level PROTO((void));
+static struct binding_level *innermost_nonclass_level PROTO((void));
+static tree poplevel_class PROTO((void));
+static void warn_about_implicit_typename_lookup PROTO((tree, tree));
+static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
+static int walk_globals_r PROTO((tree, void *));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -209,6 +220,14 @@ tree unsigned_type_node;
 tree long_unsigned_type_node;
 tree long_long_unsigned_type_node;
 
+/* These are used for integer literals that are larger than 
+   a long long.  The largest integer literals we can handle
+   are the width of two HOST_WIDE_INTs.  If two HOST_WIDE_INTs
+   are not larger than the target's long long, then these
+   will never be used. */
+tree widest_integer_literal_type_node;
+tree widest_unsigned_literal_type_node;
+
 tree ptrdiff_type_node;
 
 tree unsigned_char_type_node;
@@ -709,7 +728,7 @@ struct binding_level
 
 #define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
   
-/* The (non-class) binding level currently in effect.  */
+/* The binding level currently in effect.  */
 
 static struct binding_level *current_binding_level;
 
@@ -717,11 +736,6 @@ static struct binding_level *current_binding_level;
 
 static struct binding_level *class_binding_level;
 
-/* The current (class or non-class) binding level currently in effect.  */
-
-#define inner_binding_level \
-  (class_binding_level ? class_binding_level : current_binding_level)
-
 /* A chain of binding_level structures awaiting reuse.  */
 
 static struct binding_level *free_binding_level;
@@ -764,15 +778,7 @@ push_binding_level (newlevel, tag_transparent, keep)
   /* Add this level to the front of the chain (stack) of levels that
      are active.  */
   *newlevel = clear_binding_level;
-  if (class_binding_level)
-    {
-      newlevel->level_chain = class_binding_level;
-      class_binding_level = (struct binding_level *)0;
-    }
-  else
-    {
-      newlevel->level_chain = current_binding_level;
-    }
+  newlevel->level_chain = current_binding_level;
   current_binding_level = newlevel;
   newlevel->tag_transparent = tag_transparent;
   newlevel->more_cleanups_ok = 1;
@@ -787,12 +793,25 @@ push_binding_level (newlevel, tag_transparent, keep)
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
 }
 
+/* Find the innermost enclosing class scope, and reset
+   CLASS_BINDING_LEVEL appropriately.  */
+
 static void
-pop_binding_level ()
+find_class_binding_level ()
 {
-  if (class_binding_level)
-    current_binding_level = class_binding_level;
+  struct binding_level *level = current_binding_level;
+
+  while (level && level->parm_flag != 2)
+    level = level->level_chain;
+  if (level && level->parm_flag == 2)
+    class_binding_level = level;
+  else
+    class_binding_level = 0;
+}
 
+static void
+pop_binding_level ()
+{
   if (global_binding_level)
     {
       /* Cannot pop a level, if there are none left to pop.  */
@@ -821,13 +840,8 @@ pop_binding_level ()
     if (level->binding_depth != binding_depth)
       abort ();
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-      free_binding_level = level;
-
-    class_binding_level = current_binding_level;
-    if (class_binding_level->parm_flag != 2)
-      class_binding_level = 0;
-    while (current_binding_level->parm_flag == 2)
-      current_binding_level = current_binding_level->level_chain;
+    free_binding_level = level;
+    find_class_binding_level ();
   }
 }
 
@@ -857,14 +871,8 @@ suspend_binding_level ()
     }
   is_class_level = 0;
 #endif /* defined(DEBUG_CP_BINDING_LEVELS) */
-  {
-    current_binding_level = current_binding_level->level_chain;
-    class_binding_level = current_binding_level;
-    if (class_binding_level->parm_flag != 2)
-      class_binding_level = 0;
-    while (current_binding_level->parm_flag == 2)
-      current_binding_level = current_binding_level->level_chain;
-  }
+  current_binding_level = current_binding_level->level_chain;
+  find_class_binding_level ();
 }
 
 static void
@@ -905,25 +913,44 @@ global_bindings_p ()
   return current_binding_level == global_binding_level;
 }
 
+/* Return the innermost binding level that is not for a class scope.  */
+
+static struct binding_level *
+innermost_nonclass_level ()
+{
+  struct binding_level *b;
+
+  b = current_binding_level;
+  while (b->parm_flag == 2)
+    b = b->level_chain;
+
+  return b;
+}
+
 /* Nonzero if we are currently in a toplevel binding level.  This
    means either the global binding level or a namespace in a toplevel
-   binding level.
-   Since there are no non-toplevel namespace levels, this really
-   means any namespace or pseudo-global level.  */
+   binding level.  Since there are no non-toplevel namespace levels,
+   this really means any namespace or pseudo-global level.  We also
+   include a class whose context is toplevel.  */
 
 int
 toplevel_bindings_p ()
 {
-  return current_binding_level->namespace_p 
-    || current_binding_level->pseudo_global;
+  struct binding_level *b = innermost_nonclass_level ();
+
+  return b->namespace_p || b->pseudo_global;
 }
 
-/* Nonzero if this is a namespace scope.  */
+/* Nonzero if this is a namespace scope, or if we are defining a class
+   which is itself at namespace scope, or whose enclosing class is
+   such a class, etc.  */
 
 int
 namespace_bindings_p ()
 {
-  return current_binding_level->namespace_p;
+  struct binding_level *b = innermost_nonclass_level ();
+
+  return b->namespace_p;
 }
 
 void
@@ -967,7 +994,9 @@ declare_namespace_level ()
 int
 pseudo_global_level_p ()
 {
-  return current_binding_level->pseudo_global;
+  struct binding_level *b = innermost_nonclass_level ();
+
+  return b->pseudo_global;
 }
 
 void
@@ -1078,9 +1107,10 @@ push_binding (id, decl, level)
   BINDING_VALUE (binding) = decl;
   BINDING_TYPE (binding) = NULL_TREE;
   BINDING_LEVEL (binding) = level;
+  INHERITED_VALUE_BINDING_P (binding) = 0;
   LOCAL_BINDING_P (binding) = (level != class_binding_level);
 
-  /* And put it on the front of the ilst of bindings for ID.  */
+  /* And put it on the front of the list of bindings for ID.  */
   TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
   IDENTIFIER_BINDING (id) = binding;
 }
@@ -1090,31 +1120,58 @@ push_binding (id, decl, level)
    stat' hack whereby a non-typedef class-name or enum-name can be
    bound at the same level as some other kind of entity.  It's the
    responsibility of the caller to check that inserting this name is
-   legal here.  */
-static void
+   legal here.  Returns nonzero if the new binding was successful.  */
+static int
 add_binding (id, decl)
      tree id;
      tree decl;
 {
   tree binding = IDENTIFIER_BINDING (id);
+  int ok = 1;
 
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
     /* The new name is the type name.  */
     BINDING_TYPE (binding) = decl;
-  else 
-    {
-      /* The old name must be the type name.  It was placed in
-        IDENTIFIER_VALUE because it was thought, at the point it
-        was declared, to be the only entity with such a name.  */
-      my_friendly_assert (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
-                         && DECL_ARTIFICIAL (BINDING_VALUE (binding)),
-                         0);
-
-      /* Move the type name into the type slot; it is now hidden by
-        the new binding.  */
+  else if (!BINDING_VALUE (binding))
+    /* This situation arises when push_class_level_binding moves an
+       inherited type-binding out of the way to make room for a new
+       value binding.  */
+    BINDING_VALUE (binding) = decl;
+  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+          && DECL_ARTIFICIAL (BINDING_VALUE (binding)))
+    {
+      /* The old binding was a type name.  It was placed in
+        BINDING_VALUE because it was thought, at the point it was
+        declared, to be the only entity with such a name.  Move the
+        type name into the type slot; it is now hidden by the new
+        binding.  */
       BINDING_TYPE (binding) = BINDING_VALUE (binding);
       BINDING_VALUE (binding) = decl;
+      INHERITED_VALUE_BINDING_P (binding) = 0;
+    }
+  else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+          && TREE_CODE (decl) == TYPE_DECL
+          && DECL_NAME (decl) == DECL_NAME (BINDING_VALUE (binding))
+          && same_type_p (TREE_TYPE (decl),
+                          TREE_TYPE (BINDING_VALUE (binding))))
+    /* We have two typedef-names, both naming the same type to have
+       the same name.  This is OK because of:
+
+         [dcl.typedef]
+
+        In a given scope, a typedef specifier can be used to redefine
+        the name of any type declared in that scope to refer to the
+        type to which it already refers.  */
+    ok = 0;
+  else
+    {
+      cp_error ("declaration of `%#D'", decl);
+      cp_error_at ("conflicts with previous declaration `%#D'",
+                  BINDING_VALUE (binding));
+      ok = 0;
     }
+
+  return ok;
 }
 
 /* Bind DECL to ID in the current_binding_level.
@@ -1127,14 +1184,26 @@ push_local_binding (id, decl, flags)
      tree decl;
      int flags;
 {
-  tree d = decl;
+  struct binding_level *b;
+
+  /* Skip over any local classes.  This makes sense if we call
+     push_local_binding with a friend decl of a local class.  */
+  b = current_binding_level;
+  while (b->parm_flag == 2)
+    b = b->level_chain;
 
   if (lookup_name_current_level (id))
-    /* Supplement the existing binding.  */
-    add_binding (id, d);
+    {
+      /* Supplement the existing binding.  */
+      if (!add_binding (id, decl))
+       /* It didn't work.  Something else must be bound at this
+          level.  Do not add DECL to the list of things to pop
+          later.  */
+       return;
+    }
   else
     /* Create a new binding.  */
-    push_binding (id, d, current_binding_level);
+    push_binding (id, decl, b);
 
   if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
     /* We must put the OVERLOAD into a TREE_LIST since the
@@ -1144,21 +1213,30 @@ push_local_binding (id, decl, flags)
 
   /* And put DECL on the list of things declared by the current
      binding level.  */
-  TREE_CHAIN (decl) = current_binding_level->names;
-  current_binding_level->names = decl;
+  TREE_CHAIN (decl) = b->names;
+  b->names = decl;
 }
 
-/* Bind DECL to ID in the class_binding_level.  */
+/* Bind DECL to ID in the class_binding_level.  Returns nonzero if the
+   binding was successful.  */
 
-void
+int
 push_class_binding (id, decl)
      tree id;
      tree decl;
 {
-  if (IDENTIFIER_BINDING (id)
-      && BINDING_LEVEL (IDENTIFIER_BINDING (id)) == class_binding_level)
+  int result = 1;
+  tree binding = IDENTIFIER_BINDING (id);
+  tree context;
+
+  /* Note that we declared this value so that we can issue an error if
+     this an illegal redeclaration of a name already used for some
+     other purpose.  */
+  note_name_declared_in_class (id, decl);
+
+  if (binding && BINDING_LEVEL (binding) == class_binding_level)
     /* Supplement the existing binding.  */
-    add_binding (id, decl);
+    result = add_binding (id, decl);
   else
     /* Create a new binding.  */
     push_binding (id, decl, class_binding_level);
@@ -1169,6 +1247,42 @@ push_class_binding (id, decl)
      a class-name or enum-name we might prefer a field-name, or some
      such.  */
   IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
+
+  /* If this is a binding from a base class, mark it as such.  */
+  binding = IDENTIFIER_BINDING (id);
+  if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
+    {
+      /* Any implicit typename must be from a base-class.  The
+        context for an implicit typename declaration is always
+        the derived class in which the lookup was done, so the checks
+        based on the context of DECL below will not trigger.  */
+      if (TREE_CODE (decl) == TYPE_DECL 
+         && IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
+       INHERITED_VALUE_BINDING_P (binding) = 1;
+      else
+       {
+         if (TREE_CODE (decl) == OVERLOAD)
+           context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
+         else
+           {
+             my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
+                                 0);
+             context = DECL_REAL_CONTEXT (decl);
+           }
+
+         if (is_properly_derived_from (current_class_type, context))
+           INHERITED_VALUE_BINDING_P (binding) = 1;
+         else
+           INHERITED_VALUE_BINDING_P (binding) = 0;
+       }
+    }
+  else if (BINDING_VALUE (binding) == decl)
+    /* We only encounter a TREE_LIST when push_class_decls detects an
+       ambiguity.  Such an ambiguity can be overridden by a definition
+       in this class.  */
+    INHERITED_VALUE_BINDING_P (binding) = 1;
+
+  return result;
 }
 
 /* Remove the binding for DECL which should be the innermost binding
@@ -1249,11 +1363,11 @@ poplevel (keep, reverse, functionbody)
   int block_previously_created;
   int leaving_for_scope;
 
-  if (current_binding_level->parm_flag == 2
-      || current_binding_level->class_shadowed)
-    /* We should not be using poplevel to pop a class binding level.
-       Use poplevel_class instead.  */
-    my_friendly_abort (0);
+  if (current_binding_level->parm_flag == 2)
+    return poplevel_class ();
+
+  my_friendly_assert (!current_binding_level->class_shadowed,
+                     19990414);
 
   /* We used to use KEEP == 2 to indicate that the new block should go
      at the beginning of the list of blocks at this binding level,
@@ -1640,25 +1754,14 @@ pushlevel_class ()
   decl_stack = push_decl_level (decl_stack, &decl_obstack);
   class_binding_level = current_binding_level;
   class_binding_level->parm_flag = 2;
-  /* We have just pushed into a new binding level.  Now, fake out the rest
-     of the compiler.  Set the `current_binding_level' back to point to
-     the most closely containing non-class binding level.  */
-  do
-    {
-      current_binding_level = current_binding_level->level_chain;
-    }
-  while (current_binding_level->parm_flag == 2);
 }
 
-/* ...and a poplevel for class declarations.  FORCE is used to force
-   clearing out of CLASS_VALUEs after a class definition.  */
+/* ...and a poplevel for class declarations.  */
 
-tree
-poplevel_class (force)
-     int force;
+static tree
+poplevel_class ()
 {
   register struct binding_level *level = class_binding_level;
-  tree block = NULL_TREE;
   tree shadowed;
 
   my_friendly_assert (level != 0, 354);
@@ -1669,11 +1772,38 @@ poplevel_class (force)
      shouldn't even be used when current_class_type isn't set, and second,
      if we don't touch it here, we're able to use the cache effect if the
      next time we're entering a class scope, it is the same class.  */
-  if (current_class_depth != 1 || force)
-    for (shadowed = level->class_shadowed;
-        shadowed;
-        shadowed = TREE_CHAIN (shadowed))
-      IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
+  if (current_class_depth != 1)
+    {
+      struct binding_level* b;
+
+      /* Clear out our IDENTIFIER_CLASS_VALUEs.  */
+      for (shadowed = level->class_shadowed;
+          shadowed;
+          shadowed = TREE_CHAIN (shadowed))
+       IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
+       
+      /* Find the next enclosing class, and recreate
+        IDENTIFIER_CLASS_VALUEs appropriate for that class.  */
+      b = level->level_chain;
+      while (b && b->parm_flag != 2)
+       b = b->level_chain;
+
+      if (b)
+       for (shadowed = b->class_shadowed; 
+            shadowed; 
+            shadowed = TREE_CHAIN (shadowed))
+         {
+           tree t;
+
+           t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+           while (t && BINDING_LEVEL (t) != b)
+             t = TREE_CHAIN (t);
+      
+           if (t)
+             IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) 
+               = BINDING_VALUE (t);
+         }
+    }
   else
     /* Remember to save what IDENTIFIER's were bound in this scope so we
        can recover from cache misses.  */
@@ -1697,9 +1827,6 @@ poplevel_class (force)
                      class_binding_level->parm_flag,
                      class_binding_level->keep);
 
-  if (class_binding_level->parm_flag != 2)
-    class_binding_level = (struct binding_level *)0;
-
   /* Now, pop out of the binding level which we created up in the
      `pushlevel_class' routine.  */
 #if defined(DEBUG_CP_BINDING_LEVELS)
@@ -1708,8 +1835,224 @@ poplevel_class (force)
 
   pop_binding_level ();
 
-  return block;
+  return NULL_TREE;
+}
+
+/* We are entering the scope of a class.  Clear IDENTIFIER_CLASS_VALUE
+   for any names in enclosing classes.  */
+
+void
+clear_identifier_class_values ()
+{
+  tree t;
+
+  if (!class_binding_level)
+    return;
+
+  for (t = class_binding_level->class_shadowed;
+       t;
+       t = TREE_CHAIN (t))
+    IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
+}
+
+/* Returns non-zero if T is a virtual function table.  */
+
+int
+vtable_decl_p (t, data)
+     tree t;
+     void *data ATTRIBUTE_UNUSED;
+{
+  return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
+}
+
+/* Returns non-zero if T is a TYPE_DECL for a type with virtual
+   functions.  */
+
+int
+vtype_decl_p (t, data)
+     tree t;
+     void *data ATTRIBUTE_UNUSED;
+{
+  return (TREE_CODE (t) == TYPE_DECL
+         && TREE_TYPE (t) != error_mark_node
+         && TYPE_LANG_SPECIFIC (TREE_TYPE (t))
+         && CLASSTYPE_VSIZE (TREE_TYPE (t)));
+}
+
+/* Returns non-zero if T is a signature table.  */
+
+int 
+sigtable_decl_p (t, data)
+     tree t;
+     void *data ATTRIBUTE_UNUSED;
+{
+  return (TREE_CODE (t) == VAR_DECL
+         && TREE_TYPE (t) != error_mark_node
+         && IS_SIGNATURE (TREE_TYPE (t)));
+}
+
+/* Walk all the namespaces contained NAMESPACE, including NAMESPACE
+   itself, calling F for each.  The DATA is passed to F as well.  */
+
+static int
+walk_namespaces_r (namespace, f, data)
+     tree namespace;
+     walk_namespaces_fn f;
+     void *data;
+{
+  tree current;
+  int result = 0;
+
+  result |= (*f) (namespace, data);
+
+  for (current = NAMESPACE_LEVEL (namespace)->names;
+       current;
+       current = TREE_CHAIN (current))
+    {
+      if (TREE_CODE (current) != NAMESPACE_DECL
+         || DECL_NAMESPACE_ALIAS (current))
+       continue;
+      if (!DECL_LANG_SPECIFIC (current))
+       {
+         /* Hmm. std. */
+         my_friendly_assert (current == std_node, 393);
+         continue;
+       }
+
+      /* We found a namespace.  */
+      result |= walk_namespaces_r (current, f, data);
+    }
+
+  return result;
+}
+
+/* Walk all the namespaces, calling F for each.  The DATA is passed to
+   F as well.  */
+
+int
+walk_namespaces (f, data)
+     walk_namespaces_fn f;
+     void *data;
+{
+  return walk_namespaces_r (global_namespace, f, data);
+}
+
+struct walk_globals_data {
+  walk_globals_pred p;
+  walk_globals_fn f;
+  void *data;
+};
+
+/* Walk the global declarations in NAMESPACE.  Whenever one is found
+   for which P returns non-zero, call F with its address.  If any call
+   to F returns a non-zero value, return a non-zero value.  */
+
+static int 
+walk_globals_r (namespace, data)
+     tree namespace;
+     void *data;
+{
+  struct walk_globals_data* wgd = (struct walk_globals_data *) data;
+  walk_globals_pred p = wgd->p;
+  walk_globals_fn f = wgd->f;
+  void *d = wgd->data;
+  tree *t;
+  int result = 0;
+
+  t = &NAMESPACE_LEVEL (namespace)->names;
+
+  while (*t)
+    {
+      tree glbl = *t;
+
+      if ((*p) (glbl, d))
+       result |= (*f) (t, d);
+
+      /* If F changed *T, then *T still points at the next item to
+        examine.  */
+      if (*t == glbl)
+       t = &TREE_CHAIN (*t);
+    }
+
+  return result;
+}
+
+/* Walk the global declarations.  Whenever one is found for which P
+   returns non-zero, call F with its address.  If any call to F
+   returns a non-zero value, return a non-zero value.  */
+
+int
+walk_globals (p, f, data)
+     walk_globals_pred p;
+     walk_globals_fn f;
+     void *data;
+{
+  struct walk_globals_data wgd;
+  wgd.p = p;
+  wgd.f = f;
+  wgd.data = data;
+
+  return walk_namespaces (walk_globals_r, &wgd);
 }
+
+/* Call wrapup_globals_declarations for the globals in NAMESPACE.  If
+   DATA is non-NULL, this is the last time we will call
+   wrapup_global_declarations for this NAMESPACE.  */
+
+int
+wrapup_globals_for_namespace (namespace, data)
+     tree namespace;
+     void *data;
+{
+  tree globals = NAMESPACE_LEVEL (namespace)->names;
+  int len = list_length (globals);
+  tree *vec = (tree *) alloca (sizeof (tree) * len);
+  int i;
+  int result;
+  tree decl;
+  int last_time = (data != 0);
+
+  if (last_time && namespace == global_namespace)
+    /* Let compile_file handle the global namespace.  */
+    return 0;
+
+  /* Process the decls in reverse order--earliest first.
+     Put them into VEC from back to front, then take out from front.  */
+  
+  for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
+    vec[len - i - 1] = decl;
+  
+  if (last_time)
+    {
+      check_global_declarations (vec, len);
+      return 0;
+    }
+
+  /* Temporarily mark vtables as external.  That prevents
+     wrapup_global_declarations from writing them out; we must process
+     them ourselves in finish_vtable_vardecl.  */
+  for (i = 0; i < len; ++i)
+    if (vtable_decl_p (vec[i], /*data=*/0) && !DECL_EXTERNAL (vec[i]))
+      {
+       DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
+       DECL_EXTERNAL (vec[i]) = 1;
+      }
+
+  /* Write out any globals that need to be output.  */
+  result = wrapup_global_declarations (vec, len);
+
+  /* Undo the hack to DECL_EXTERNAL above.  */
+  for (i = 0; i < len; ++i)
+    if (vtable_decl_p (vec[i], /*data=*/0)
+       && DECL_NOT_REALLY_EXTERN (vec[i]))
+      {
+       DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
+       DECL_EXTERNAL (vec[i]) = 0;
+      }
+
+  return result;
+}
+
 \f
 /* For debugging.  */
 static int no_print_functions = 0;
@@ -2073,38 +2416,38 @@ pop_namespace ()
   suspend_binding_level ();
 }
 
-/* Concatenate the binding levels of all namespaces. */
+/* Push into the scope of the namespace NS, even if it is deeply
+   nested within another namespace.  */
 
 void
-cat_namespace_levels()
+push_nested_namespace (ns)
+     tree ns;
 {
-  tree current;
-  tree last;
-  struct binding_level *b;
-
-  last = NAMESPACE_LEVEL (global_namespace) -> names;
-  /* The nested namespaces appear in the names list of their ancestors. */
-  for (current = last; current; current = TREE_CHAIN (current))
+  if (ns == global_namespace)
+    push_to_top_level ();
+  else
     {
-      /* Catch simple infinite loops.  */
-      if (TREE_CHAIN (current) == current)
-       my_friendly_abort (990126);
+      push_nested_namespace (CP_DECL_CONTEXT (ns));
+      push_namespace (DECL_NAME (ns));
+    }
+}
 
-      if (TREE_CODE (current) != NAMESPACE_DECL
-          || DECL_NAMESPACE_ALIAS (current))
-       continue;
-      if (!DECL_LANG_SPECIFIC (current))
-       {
-         /* Hmm. std. */
-         my_friendly_assert (current == std_node, 393);
-         continue;
-       }
-      b = NAMESPACE_LEVEL (current);
-      while (TREE_CHAIN (last))
-       last = TREE_CHAIN (last);
-      TREE_CHAIN (last) = NAMESPACE_LEVEL (current) -> names;
+/* Pop back from the scope of the namespace NS, which was previously
+   entered with push_nested_namespace.  */
+     
+void
+pop_nested_namespace (ns)
+     tree ns;
+{
+  while (ns != global_namespace)
+    {
+      pop_namespace ();
+      ns = CP_DECL_CONTEXT (ns);
     }
+
+  pop_from_top_level ();
 }
+
 \f
 /* Subroutines for reverting temporarily to top-level for instantiation
    of templates and such.  We actually need to clear out the class- and
@@ -2129,6 +2472,7 @@ struct saved_scope {
   tree previous_class_type, previous_class_values;
   int processing_specialization;
   int processing_explicit_instantiation;
+  char *class_cache_firstobj;
 };
 static struct saved_scope *current_saved_scope;
 
@@ -2195,7 +2539,7 @@ maybe_push_to_top_level (pseudo)
   extern int current_lang_stacksize;
   struct saved_scope *s
     = (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
-  struct binding_level *b = inner_binding_level;
+  struct binding_level *b = current_binding_level;
   tree old_bindings = NULL_TREE;
 
   push_cp_function_context (NULL_TREE);
@@ -2246,6 +2590,7 @@ maybe_push_to_top_level (pseudo)
   s->processing_template_decl = processing_template_decl;
   s->previous_class_type = previous_class_type;
   s->previous_class_values = previous_class_values;
+  s->class_cache_firstobj = class_cache_firstobj;
   s->processing_specialization = processing_specialization;
   s->processing_explicit_instantiation = processing_explicit_instantiation;
 
@@ -2261,6 +2606,7 @@ maybe_push_to_top_level (pseudo)
   shadowed_labels = NULL_TREE;
   minimal_parse_mode = 0;
   previous_class_type = previous_class_values = NULL_TREE;
+  class_cache_firstobj = 0;
   processing_specialization = 0;
   processing_explicit_instantiation = 0;
   current_template_parms = NULL_TREE;
@@ -2289,10 +2635,7 @@ pop_from_top_level ()
 
   /* Clear out class-level bindings cache.  */
   if (previous_class_type)
-    {
-      popclass (-1);
-      previous_class_type = NULL_TREE;
-    }
+    invalidate_class_lookup_cache ();
 
   pop_obstacks ();
 
@@ -2335,6 +2678,7 @@ pop_from_top_level ()
   previous_class_values = s->previous_class_values;
   processing_specialization = s->processing_specialization;
   processing_explicit_instantiation = s->processing_explicit_instantiation;
+  class_cache_firstobj = s->class_cache_firstobj;
 
   free (s);
 
@@ -2378,14 +2722,14 @@ set_identifier_type_value_with_scope (id, type, b)
   SET_IDENTIFIER_TYPE_VALUE (id, type);
 }
 
-/* As set_identifier_type_value_with_scope, but using inner_binding_level.  */
+/* As set_identifier_type_value_with_scope, but using current_binding_level.  */
 
 void
 set_identifier_type_value (id, type)
      tree id;
      tree type;
 {
-  set_identifier_type_value_with_scope (id, type, inner_binding_level);
+  set_identifier_type_value_with_scope (id, type, current_binding_level);
 }
 
 /* Return the type associated with id. */
@@ -2418,10 +2762,10 @@ pop_everything ()
 #ifdef DEBUG_CP_BINDING_LEVELS
   fprintf (stderr, "XXX entering pop_everything ()\n");
 #endif
-  while (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+  while (!toplevel_bindings_p ())
     {
-      if (class_binding_level)
-       pop_nested_class (1);
+      if (current_binding_level->parm_flag == 2)
+       pop_nested_class ();
       else
        poplevel (0, 0, 0);
     }
@@ -2463,25 +2807,7 @@ maybe_process_template_type_declaration (type, globalize, b)
                          || TREE_CODE (type) == ENUMERAL_TYPE, 0);
                          
                          
-      if (/* If !GLOBALIZE then we are looking at a definition.
-            It may not be a primary template.  (For example, in:
-                 
-              template <class T>
-              struct S1 { class S2 {}; }
-                 
-            we have to push_template_decl for S2.)  */
-         (processing_template_decl && !globalize)
-         /* If we are declaring a friend template class, we will
-            have GLOBALIZE set, since something like:
-
-              template <class T>
-              struct S1 {
-                template <class U>
-                friend class S2; 
-              };
-
-            declares S2 to be at global scope.  */
-         || PROCESSING_REAL_TEMPLATE_DECL_P ())
+      if (processing_template_decl)
        {
          /* This may change after the call to
             push_template_decl_real, but we want the original value.  */
@@ -2499,15 +2825,12 @@ maybe_process_template_type_declaration (type, globalize, b)
              && !globalize && b->pseudo_global
              && b->level_chain->parm_flag == 2)
            {
-             pushdecl_with_scope (CLASSTYPE_TI_TEMPLATE (type),
-                                  b->level_chain);
              finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
              /* Put this tag on the list of tags for the class, since
                 that won't happen below because B is not the class
                 binding level, but is instead the pseudo-global level.  */
              b->level_chain->tags = 
                saveable_tree_cons (name, type, b->level_chain->tags);
-             TREE_NONLOCAL_FLAG (type) = 1;
              if (TYPE_SIZE (current_class_type) == NULL_TREE)
                CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
            }
@@ -2528,10 +2851,8 @@ pushtag (name, type, globalize)
      int globalize;
 {
   register struct binding_level *b;
-  tree context = 0;
-  tree c_decl = 0;
 
-  b = inner_binding_level;
+  b = current_binding_level;
   while (b->tag_transparent
         || (globalize && b->parm_flag == 2))
     b = b->level_chain;
@@ -2543,32 +2864,34 @@ pushtag (name, type, globalize)
 
   if (name)
     {
-      context = type ? TYPE_CONTEXT (type) : NULL_TREE;
-      if (! context)
-       {
-         tree cs = current_scope ();
-
-         if (! globalize)
-           context = cs;
-         else if (cs != NULL_TREE 
-                  && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
-           /* When declaring a friend class of a local class, we want
-              to inject the newly named class into the scope
-              containing the local class, not the namespace scope.  */
-           context = hack_decl_function_context (get_type_decl (cs));
-       }
-      if (context)
-       c_decl = TREE_CODE (context) == FUNCTION_DECL
-         ? context : TYPE_MAIN_DECL (context);
-
-      if (!context)
-       context = current_namespace;
-
       /* Do C++ gratuitous typedefing.  */
       if (IDENTIFIER_TYPE_VALUE (name) != type)
         {
           register tree d = NULL_TREE;
          int newdecl = 0, in_class = 0;
+         tree context;
+         tree c_decl = NULL_TREE;
+
+         context = type ? TYPE_CONTEXT (type) : NULL_TREE;
+         if (! context)
+           {
+             tree cs = current_scope ();
+
+             if (! globalize)
+               context = cs;
+             else if (cs != NULL_TREE 
+                      && TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
+               /* When declaring a friend class of a local class, we want
+                  to inject the newly named class into the scope
+                  containing the local class, not the namespace scope.  */
+               context = hack_decl_function_context (get_type_decl (cs));
+           }
+         if (context)
+           c_decl = TREE_CODE (context) == FUNCTION_DECL
+             ? context : TYPE_MAIN_DECL (context);
+
+         if (!context)
+           context = current_namespace;
 
          if ((b->pseudo_global && b->level_chain->parm_flag == 2)
              || b->parm_flag == 2)
@@ -2597,13 +2920,14 @@ pushtag (name, type, globalize)
 
          if (b->parm_flag == 2)
            {
-             pushdecl_class_level (d);
              if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
                /* Put this TYPE_DECL on the TYPE_FIELDS list for the
                   class.  But if it's a member template class, we
                   want the TEMPLATE_DECL, not the TYPE_DECL, so this
                   is done later.  */
                finish_member_declaration (d);
+             else
+               pushdecl_class_level (d);
            }
          else
            d = pushdecl_with_scope (d, b);
@@ -2622,7 +2946,6 @@ pushtag (name, type, globalize)
         }
       if (b->parm_flag == 2)
        {
-         TREE_NONLOCAL_FLAG (type) = 1;
          if (TYPE_SIZE (current_class_type) == NULL_TREE)
            CLASSTYPE_TAGS (current_class_type) = b->tags;
        }
@@ -2815,9 +3138,9 @@ warn_extern_redeclared_static (newdecl, olddecl)
 {
   tree name;
 
-  static char *explicit_extern_static_warning
+  static const char *explicit_extern_static_warning
     = "`%D' was declared `extern' and later `static'";
-  static char *implicit_extern_static_warning
+  static const char *implicit_extern_static_warning
     = "`%D' was declared implicitly `extern' and later `static'";
 
   if (TREE_CODE (newdecl) == TYPE_DECL)
@@ -3042,7 +3365,7 @@ duplicate_decls (newdecl, olddecl)
     return 1;
   else
     {
-      char *errmsg = redeclaration_error_message (newdecl, olddecl);
+      const char *errmsg = redeclaration_error_message (newdecl, olddecl);
       if (errmsg)
        {
          cp_error (errmsg, newdecl);
@@ -3242,7 +3565,7 @@ duplicate_decls (newdecl, olddecl)
       TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
       /* Lay the type out, unless already done.  */
-      if (newtype != canonical_type_variant (oldtype)
+      if (! same_type_p (newtype, oldtype)
          && TREE_TYPE (newdecl) != error_mark_node
          && !(processing_template_decl && uses_template_parms (newdecl)))
        layout_type (TREE_TYPE (newdecl));
@@ -3326,6 +3649,13 @@ duplicate_decls (newdecl, olddecl)
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
       DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       olddecl_friend = DECL_FRIEND_P (olddecl);
+
+      /* Only functions have DECL_BEFRIENDING_CLASSES.  */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL
+         || DECL_FUNCTION_TEMPLATE_P (newdecl))
+       DECL_BEFRIENDING_CLASSES (newdecl)
+         = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+                    DECL_BEFRIENDING_CLASSES (olddecl));
     }
 
   if (TREE_CODE (newdecl) == FUNCTION_DECL)
@@ -3888,7 +4218,7 @@ pushdecl (x)
                   /* No shadow warnings for vars made for inlining.  */
                   && ! DECL_FROM_INLINE (x))
            {
-             char *warnstring = NULL;
+             const char *warnstring = NULL;
 
              if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
                warnstring = "declaration of `%s' shadows a parameter";
@@ -3928,8 +4258,8 @@ pushdecl (x)
         We will reverse them later if necessary.  */
       TREE_CHAIN (x) = current_binding_level->names;
       current_binding_level->names = x;
-      if (! (current_binding_level != global_binding_level 
-            || TREE_PERMANENT (x)))
+      if (current_binding_level == global_binding_level
+         && !TREE_PERMANENT (x))
        my_friendly_abort (124);
     }
 
@@ -3973,7 +4303,7 @@ tree
 pushdecl_namespace_level (x)
      tree x;
 {
-  register struct binding_level *b = inner_binding_level;
+  register struct binding_level *b = current_binding_level;
   register tree t;
 
   t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
@@ -4034,39 +4364,27 @@ pushdecl_class_level (x)
 {
   /* Don't use DECL_ASSEMBLER_NAME here!  Everything that looks in class
      scope looks for the pre-mangled name.  */
-  register tree name = DECL_NAME (x);
+  register tree name;
+
+  if (TREE_CODE (x) == OVERLOAD)
+    x = OVL_CURRENT (x);
+  name = DECL_NAME (x);
 
   if (name)
     {
-      if (TYPE_BEING_DEFINED (current_class_type))
-       {
-         /* A name N used in a class S shall refer to the same declaration
-            in its context and when re-evaluated in the completed scope of S.
-            Types, enums, and static vars are checked here; other
-            members are checked in finish_struct.  */
-         tree icv = IDENTIFIER_CLASS_VALUE (name);
-
-         /* This should match check_member_decl_is_same_in_complete_scope.  */
-         if (icv && icv != x
-             && flag_optional_diags
-             /* Don't complain about inherited names.  */
-             && id_in_current_class (name)
-             /* Or shadowed tags.  */
-             && !(DECL_DECLARES_TYPE_P (icv)
-                  && DECL_CONTEXT (icv) == current_class_type))
-           {
-             cp_pedwarn ("declaration of identifier `%D' as `%#D'", name, x);
-             cp_pedwarn_at ("conflicts with previous use in class as `%#D'",
-                            icv);
-           }
-
-         check_template_shadow (x);
-       }
-
       push_class_level_binding (name, x);
       if (TREE_CODE (x) == TYPE_DECL)
        set_identifier_type_value (name, TREE_TYPE (x));
     }
+  else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+    {
+      tree f;
+
+      for (f = TYPE_FIELDS (TREE_TYPE (x));
+          f;
+          f = TREE_CHAIN (f))
+       pushdecl_class_level (f);
+    }
 }
 
 #if 0
@@ -4100,27 +4418,78 @@ push_class_level_binding (name, x)
      tree name;
      tree x;
 {
+  tree binding;
   /* The class_binding_level will be NULL if x is a template 
      parameter name in a member template.  */
   if (!class_binding_level)
     return;
 
+  /* Make sure that this new member does not have the same name
+     as a template parameter.  */
+  if (TYPE_BEING_DEFINED (current_class_type))
+    check_template_shadow (x);
+
   /* If this declaration shadows a declaration from an enclosing
      class, then we will need to restore IDENTIFIER_CLASS_VALUE when
      we leave this class.  Record the shadowed declaration here.  */
-  maybe_push_cache_obstack ();
-  class_binding_level->class_shadowed
-    = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
-                class_binding_level->class_shadowed);
-  TREE_TYPE (class_binding_level->class_shadowed)
-    = x;
-  pop_obstacks ();
-
-  /* Put the binding on the stack of bindings for the identifier, and
-     update IDENTIFIER_CLASS_VALUE.  */
-  push_class_binding (name, x);
+  binding = IDENTIFIER_BINDING (name);
+  if (binding 
+      && ((TREE_CODE (x) == OVERLOAD
+          && BINDING_VALUE (binding)
+          && is_overloaded_fn (BINDING_VALUE (binding)))
+         || INHERITED_VALUE_BINDING_P (binding)))
+    {
+      tree shadow;
+      tree old_decl;
+
+      /* If the old binding was from a base class, and was for a tag
+        name, slide it over to make room for the new binding.  The
+        old binding is still visible if explicitly qualified with a
+        class-key.  */
+      if (INHERITED_VALUE_BINDING_P (binding)
+         && BINDING_VALUE (binding)
+         && TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
+         && DECL_ARTIFICIAL (BINDING_VALUE (binding))
+         && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+       {
+         old_decl = BINDING_TYPE (binding);
+         BINDING_TYPE (binding) = BINDING_VALUE (binding);
+         BINDING_VALUE (binding) = NULL_TREE;
+         INHERITED_VALUE_BINDING_P (binding) = 0;
+       }
+      else
+       old_decl = BINDING_VALUE (binding);
+
+      /* There was already a binding for X containing fewer
+        functions than are named in X.  Find the previous
+        declaration of X on the class-shadowed list, and update it.  */
+      for (shadow = class_binding_level->class_shadowed;
+          shadow;
+          shadow = TREE_CHAIN (shadow))
+       if (TREE_PURPOSE (shadow) == name
+           && TREE_TYPE (shadow) == old_decl)
+         {
+           BINDING_VALUE (binding) = x;
+           INHERITED_VALUE_BINDING_P (binding) = 0;
+           TREE_TYPE (shadow) = x;
+           return;
+         }
+    }
 
-  obstack_ptr_grow (&decl_obstack, x);
+  /* If we didn't replace an existing binding, put the binding on the
+     stack of bindings for the identifier, and update
+     IDENTIFIER_CLASS_VALUE.  */
+  if (push_class_binding (name, x))
+    {
+      push_cache_obstack ();
+      class_binding_level->class_shadowed
+       = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
+                    class_binding_level->class_shadowed);
+      pop_obstacks ();
+      /* Record the value we are binding NAME to so that we can know
+        what to pop later.  */
+      TREE_TYPE (class_binding_level->class_shadowed) = x;
+    }
 }
 
 /* Insert another USING_DECL into the current binding level,
@@ -4365,7 +4734,7 @@ implicitly_declare (functionid)
    Otherwise return an error message format string with a %s
    where the identifier should go.  */
 
-static char *
+static const char *
 redeclaration_error_message (newdecl, olddecl)
      tree newdecl, olddecl;
 {
@@ -4607,20 +4976,38 @@ define_label (filename, line, name)
                        && !(DECL_INITIAL (new_decls) == NULL_TREE
                             && pod_type_p (TREE_TYPE (new_decls))))
                      {
-                       if (! identified) 
+                       /* 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)
                          {
-                           cp_error ("jump to label `%D'", decl);
-                           error_with_file_and_line (uses->filename_o_goto,
-                                                     uses->lineno_o_goto,
-                                                     "  from here");
+                           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 (DECL_INITIAL (new_decls)
-                           || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))
+
+                       if (problem)
                          cp_error_at ("  crosses initialization of `%#D'",
                                       new_decls);
                        else
-                         cp_error_at ("  enters scope of non-POD `%#D'",
+                         cp_pedwarn_at ("  enters scope of non-POD `%#D'",
                                         new_decls);
                      }
                    new_decls = TREE_CHAIN (new_decls);
@@ -4757,7 +5144,7 @@ storedecls (decls)
 
 /* Similarly, store the list of tags of the current level.  */
 
-static void
+void
 storetags (tags)
      tree tags;
 {
@@ -4870,59 +5257,6 @@ lookup_tag (form, name, binding_level, thislevel_only)
          else
            return NULL_TREE;
        }
-      if (current_class_type && level->level_chain->namespace_p)
-       {
-         /* Try looking in this class's tags before heading into
-            global binding level.  */
-         tree context = current_class_type;
-         while (context)
-           {
-             switch (TREE_CODE_CLASS (TREE_CODE (context)))
-               {
-               tree these_tags;
-               case 't':
-                   these_tags = CLASSTYPE_TAGS (context);
-                   if (ANON_AGGRNAME_P (name))
-                     while (these_tags)
-                       {
-                         if (TYPE_IDENTIFIER (TREE_VALUE (these_tags))
-                             == name)
-                           return TREE_VALUE (tail);
-                         these_tags = TREE_CHAIN (these_tags);
-                       }
-                   else
-                     while (these_tags)
-                       {
-                         if (TREE_PURPOSE (these_tags) == name)
-                           {
-                             if (TREE_CODE (TREE_VALUE (these_tags)) != form)
-                               {
-                                 cp_error ("`%#D' redeclared as %C in class scope",
-                                           TREE_VALUE (tail), form);
-                                 return NULL_TREE;
-                               }
-                             return TREE_VALUE (tail);
-                           }
-                         these_tags = TREE_CHAIN (these_tags);
-                       }
-                   /* If this type is not yet complete, then don't
-                      look at its context.  */
-                   if (TYPE_SIZE (context) == NULL_TREE)
-                     goto no_context;
-                   /* Go to next enclosing type, if any.  */
-                   context = DECL_CONTEXT (TYPE_MAIN_DECL (context));
-                   break;
-               case 'd':
-                   context = DECL_CONTEXT (context);
-                   break;
-               default:
-                   my_friendly_abort (10);
-               }
-             continue;
-             no_context:
-             break;
-           }
-       }
     }
   return NULL_TREE;
 }
@@ -5016,6 +5350,7 @@ lookup_namespace_name (namespace, name)
 {
   struct tree_binding _b;
   tree val;
+  tree template_id = NULL_TREE;
 
   my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
 
@@ -5032,6 +5367,16 @@ lookup_namespace_name (namespace, name)
 
   namespace = ORIGINAL_NAMESPACE (namespace);
 
+  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
+    {
+      template_id = name;
+      name = TREE_OPERAND (name, 0);
+      if (TREE_CODE (name) == OVERLOAD)
+       name = DECL_NAME (OVL_CURRENT (name));
+      else if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
+       name = DECL_NAME (name);
+    }
+
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
   
   val = binding_init (&_b);
@@ -5042,6 +5387,26 @@ lookup_namespace_name (namespace, name)
     {
       val = BINDING_VALUE (val);
 
+      if (template_id)
+       {
+         if (DECL_CLASS_TEMPLATE_P (val))
+           val = lookup_template_class (val, 
+                                        TREE_OPERAND (template_id, 1),
+                                        /*in_decl=*/NULL_TREE,
+                                        /*context=*/NULL_TREE,
+                                        /*entering_scope=*/0);
+         else if (DECL_FUNCTION_TEMPLATE_P (val)
+                  || TREE_CODE (val) == OVERLOAD)
+           val = lookup_template_function (val, 
+                                           TREE_OPERAND (template_id, 1));
+         else
+           {
+             cp_error ("`%D::%D' is not a template",
+                       namespace, name);
+             return error_mark_node;
+           }
+       }
+
       /* If we have a single function from a using decl, pull it out.  */
       if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
        val = OVL_FUNCTION (val);
@@ -5121,6 +5486,11 @@ build_typename_type (context, name, fullname, base_type)
                           &typename_compare))
     fatal ("virtual memory exhausted");
 
+  /* The FULLNAME needs to exist for the life of the hash table, i.e.,
+     for the entire compilation.  */
+  if (!TREE_PERMANENT (fullname))
+    fullname = copy_to_permanent (fullname);
+
   /* Build the TYPENAME_TYPE.  */
   t = make_lang_type (TYPENAME_TYPE);
   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
@@ -5156,11 +5526,20 @@ tree
 make_typename_type (context, name)
      tree context, name;
 {
-  tree t;
   tree fullname;
 
   if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
-    name = TYPE_IDENTIFIER (name);
+    {
+      if (!(TYPE_LANG_SPECIFIC (name) 
+           && (CLASSTYPE_IS_TEMPLATE (name) 
+               || CLASSTYPE_USE_TEMPLATE (name))))
+       name = TYPE_IDENTIFIER (name);
+      else
+       /* Create a TEMPLATE_ID_EXPR for the type.  */
+       name = build_nt (TEMPLATE_ID_EXPR,
+                        CLASSTYPE_TI_TEMPLATE (name),
+                        CLASSTYPE_TI_ARGS (name));
+    }
   else if (TREE_CODE (name) == TYPE_DECL)
     name = DECL_NAME (name);
 
@@ -5189,34 +5568,45 @@ make_typename_type (context, name)
     {
       if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
        {
+         tree tmpl = NULL_TREE;
          if (IS_AGGR_TYPE (context))
-           t = lookup_field (context, name, 0, 0);
-         else
+           tmpl = lookup_field (context, name, 0, 0);
+         if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
            {
              cp_error ("no class template named `%#T' in `%#T'",
                        name, context);
              return error_mark_node;
            }
 
-         if (t && DECL_CLASS_TEMPLATE_P (t))
-           return lookup_template_class (t, TREE_OPERAND (fullname, 1),
-                                         NULL_TREE, context, 
-                                         /*entering_scope=*/0);
+         return lookup_template_class (tmpl, 
+                                       TREE_OPERAND (fullname, 1),
+                                       NULL_TREE, context, 
+                                       /*entering_scope=*/0);
        }
       else
        {
-         if (IS_AGGR_TYPE (context))
-           t = lookup_field (context, name, 0, 1);
-         else
+          tree t;
+          
+         if (!IS_AGGR_TYPE (context))
            {
              cp_error ("no type named `%#T' in `%#T'", name, context);
              return error_mark_node;
            }
 
+         t = lookup_field (context, name, 0, 1);
          if (t)
            return TREE_TYPE (t);
        }
     }
+
+  /* If the CONTEXT is not a template type, then either the field is
+     there now or its never going to be.  */
+  if (!uses_template_parms (context))
+    {
+      cp_error ("no type named `%#T' in `%#T'", name, context);
+      return error_mark_node;
+    }
+    
   
   return build_typename_type (context, name, fullname,  NULL_TREE);
 }
@@ -5246,7 +5636,8 @@ select_decl (binding, flags)
     val = TYPE_STUB_DECL (BINDING_TYPE (binding));
   /* Don't return non-types if we really prefer types. */
   else if (val && LOOKUP_TYPES_ONLY (flags)  && TREE_CODE (val) != TYPE_DECL
-          && (!looking_for_template || TREE_CODE (val) != TEMPLATE_DECL))
+          && (TREE_CODE (val) != TEMPLATE_DECL
+              || !DECL_CLASS_TEMPLATE_P (val)))
     val = NULL_TREE;
 
   return val;
@@ -5283,7 +5674,7 @@ unqualified_namespace_lookup (name, flags)
        if (!lookup_using_namespace (name, b, level->using_directives,
                                      scope, flags))
          /* Give up because of error. */
-         return NULL_TREE;
+         return error_mark_node;
 
       /* Add all _DECLs seen through global using-directives. */
       /* XXX local and global using lists should work equally. */
@@ -5293,7 +5684,7 @@ unqualified_namespace_lookup (name, flags)
          if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter), 
                                       scope, flags))
            /* Give up because of error. */
-           return NULL_TREE;
+           return error_mark_node;
          if (siter == scope) break;
          siter = CP_DECL_CONTEXT (siter);
        }
@@ -5343,6 +5734,32 @@ qualify_lookup (val, flags)
   return val;
 }
 
+/* Any other BINDING overrides an implicit TYPENAME.  Warn about
+   that.  */
+
+static void
+warn_about_implicit_typename_lookup (typename, binding)
+     tree typename;
+     tree binding;
+{
+  tree subtype = TREE_TYPE (TREE_TYPE (typename));
+  tree name = DECL_NAME (typename);
+
+  if (! (TREE_CODE (binding) == TEMPLATE_DECL
+        && CLASSTYPE_TEMPLATE_INFO (subtype)
+        && CLASSTYPE_TI_TEMPLATE (subtype) == binding)
+      && ! (TREE_CODE (binding) == TYPE_DECL
+           && same_type_p (TREE_TYPE (binding), subtype)))
+    {
+      cp_warning ("lookup of `%D' finds `%#D'", 
+                 name, binding);
+      cp_warning ("  instead of `%D' from dependent base class",
+                 typename);
+      cp_warning ("  (use `typename %T::%D' if that's what you meant)",
+                 constructor_name (current_class_type), name);
+    }
+}
+
 /* Look up NAME in the current binding level and its superiors in the
    namespace of variables, functions and typedefs.  Return a ..._DECL
    node of some kind representing its definition if there is only one
@@ -5362,10 +5779,12 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
      tree name;
      int prefer_type, nonclass, namespaces_only;
 {
-  register tree val;
+  tree t;
+  tree val = NULL_TREE;
   int yylex = 0;
   tree from_obj = NULL_TREE;
   int flags;
+  int val_is_implicit_typename = 0;
 
   /* Hack: copy flag set by parser, if set. */
   if (only_namespace_names)
@@ -5380,8 +5799,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
       prefer_type = looking_for_typename;
 
       flags = lookup_flags (prefer_type, namespaces_only);
-      /* During parsing, we need to complain. */
-      flags |= LOOKUP_COMPLAIN;
       /* If the next thing is '<', class templates are types. */
       if (looking_for_template)
         flags |= LOOKUP_TEMPLATES_EXPECTED;
@@ -5421,26 +5838,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
                   || TREE_CODE (type) == TYPENAME_TYPE)
            /* Someone else will give an error about this if needed.  */
            val = NULL_TREE;
-         else if (TYPE_BEING_DEFINED (type))
-           {
-             val = IDENTIFIER_CLASS_VALUE (name);
-             if (val && DECL_CONTEXT (val) != type)
-               {
-                 struct binding_level *b = class_binding_level;
-                 for (val = NULL_TREE; b; b = b->level_chain)
-                   {
-                     tree t = purpose_member (name, b->class_shadowed);
-                     if (t && TREE_VALUE (t)
-                         && DECL_CONTEXT (TREE_VALUE (t)) == type)
-                       {
-                         val = TREE_VALUE (t);
-                         break;
-                       }
-                   }
-               }
-             if (val == NULL_TREE)
-               val = lookup_field (type, name, 0, 1);
-           }
          else if (type == current_class_type)
            val = IDENTIFIER_CLASS_VALUE (name);
          else
@@ -5455,95 +5852,56 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
        from_obj = val;
     }
   else
-    flags = lookup_flags (prefer_type, namespaces_only);
+    {
+      flags = lookup_flags (prefer_type, namespaces_only);
+      /* If we're not parsing, we need to complain. */
+      flags |= LOOKUP_COMPLAIN;
+    }
 
   /* First, look in non-namespace scopes.  */
-  for (val = IDENTIFIER_BINDING (name); val; val = TREE_CHAIN (val))
+  for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
     {
-      if (!LOCAL_BINDING_P (val) && nonclass)
+      tree binding;
+
+      if (!LOCAL_BINDING_P (t) && nonclass)
        /* We're not looking for class-scoped bindings, so keep going.  */
        continue;
-      
-      /* If this is the kind of thing we're looking for, we're done.  */
-      if (qualify_lookup (BINDING_VALUE (val), flags))
-       {
-         val = BINDING_VALUE (val);
-         break;
-       }
+      
+      /* If this is the kind of thing we're looking for, we're done.  */
+      if (qualify_lookup (BINDING_VALUE (t), flags))
+       binding = BINDING_VALUE (t);
       else if ((flags & LOOKUP_PREFER_TYPES) 
-              && qualify_lookup (BINDING_TYPE (val), flags))
-       {
-         val = BINDING_TYPE (val);
-         break;
+              && qualify_lookup (BINDING_TYPE (t), flags))
+       binding = BINDING_TYPE (t);
+      else
+       binding = NULL_TREE;
+
+      if (binding
+         && (!val || !(TREE_CODE (binding) == TYPE_DECL
+                       && IMPLICIT_TYPENAME_P (TREE_TYPE (binding)))))
+       {
+         if (val_is_implicit_typename && !yylex)
+           warn_about_implicit_typename_lookup (val, binding);
+         val = binding;
+         val_is_implicit_typename 
+           = (TREE_CODE (val) == TYPE_DECL
+              && IMPLICIT_TYPENAME_P (TREE_TYPE (val)));
+         if (!val_is_implicit_typename)
+           break;
        }
     }
 
-  /* If VAL is a type from a dependent base, we're not really supposed
-     to be able to see it; the fact that we can is the "implicit
-     typename" extension.  We call lookup_field here to turn VAL into
-     a TYPE_DECL for a TYPENAME_TYPE.  */
-  if (processing_template_decl && val
-      && val == IDENTIFIER_CLASS_VALUE (name)
-      && TREE_CODE (val) == TYPE_DECL
-      && !currently_open_class (DECL_CONTEXT (val))
-      && uses_template_parms (current_class_type))
-    val = lookup_field (current_class_type, name, 0, 1);
-
-  /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
-     list when we're defining a type.  It would probably be simpler to
-     do this, but we don't.  So, we must lookup names from base
-     classes explicitly.  */
-  if (!val && !nonclass 
-      && current_class_type && TYPE_BEING_DEFINED (current_class_type))
+  /* Now lookup in namespace scopes.  */
+  if (!val || val_is_implicit_typename)
     {
-      val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
-                           flags);
-      if (!val)
-       val = qualify_lookup (lookup_nested_field (name, !yylex),
-                             flags);
-    }
-  
-  /* If we found a type from a dependent base class (using the
-     implicit typename extension) make sure that there's not some
-     global name which should be chosen instead.  */
-  if (val && TREE_CODE (val) == TYPE_DECL
-      && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
-    {
-      tree global_val;
-
-      /* Any other name takes precedence over an implicit typename.  Warn the
-        user about this potentially confusing lookup.  */
-      global_val = unqualified_namespace_lookup (name, flags);
-
-      if (global_val)
-       {
-         tree subtype;
-
-         /* Only warn when not lexing; we don't want to warn if they
-            use this name as a declarator.  */
-         subtype = TREE_TYPE (TREE_TYPE (val));
-         if (! yylex
-             && ! (TREE_CODE (global_val) == TEMPLATE_DECL
-                   && CLASSTYPE_TEMPLATE_INFO (subtype)
-                   && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
-             && ! (TREE_CODE (global_val) == TYPE_DECL
-                   && same_type_p (TREE_TYPE (global_val), subtype)))
-           {
-             cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
-             cp_warning ("  instead of `%D' from dependent base class",
-                         val);
-             cp_warning ("  (use `typename %T::%D' if that's what you meant)",
-                         constructor_name (current_class_type), name);
-           }
-
-         /* Use the global value instead of the implicit typename.  */
-         val = global_val;
+      t = unqualified_namespace_lookup (name, flags);
+      if (t)
+       {
+         if (val_is_implicit_typename && !yylex)
+           warn_about_implicit_typename_lookup (val, t);
+         val = t;
        }
     }
-  else if (!val)
-    /* No local, or class-scoped binding.  Look for a namespace-scope
-       declaration.  */
-    val = unqualified_namespace_lookup (name, flags);
 
  done:
   if (val)
@@ -5609,15 +5967,21 @@ lookup_name (name, prefer_type)
   return lookup_name_real (name, prefer_type, 0, 0);
 }
 
-/* Similar to `lookup_name' but look only at current binding level.  */
+/* Similar to `lookup_name' but look only in the innermost non-class
+   binding level.  */
 
 tree
 lookup_name_current_level (name)
      tree name;
 {
-  register tree t = NULL_TREE;
+  struct binding_level *b;
+  tree t = NULL_TREE;
 
-  if (current_binding_level->namespace_p)
+  b = current_binding_level;
+  while (b->parm_flag == 2)
+    b = b->level_chain;
+
+  if (b->namespace_p)
     {
       t =  IDENTIFIER_NAMESPACE_VALUE (name);
 
@@ -5628,8 +5992,6 @@ lookup_name_current_level (name)
   else if (IDENTIFIER_BINDING (name) 
           && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
     {
-      struct binding_level *b = current_binding_level;
-
       while (1)
        {
          if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
@@ -5728,7 +6090,7 @@ static int builtin_type_tdescs_len, builtin_type_tdescs_max;
 static void
 record_builtin_type (rid_index, name, type)
      enum rid rid_index;
-     char *name;
+     const char *name;
      tree type;
 {
   tree rname = NULL_TREE, tname = NULL_TREE;
@@ -5771,7 +6133,7 @@ record_builtin_type (rid_index, name, type)
 
 static tree
 record_builtin_java_type (name, size)
-     char *name;
+     const char *name;
      int size;
 {
   tree type, decl;
@@ -5790,7 +6152,12 @@ record_builtin_java_type (name, size)
     }
   record_builtin_type (RID_MAX, name, type);
   decl = TYPE_NAME (type);
+
+  /* Suppress generate debug symbol entries for these types,
+     since for normal C++ they are just clutter.
+     However, push_lang_context undoes this if extern "Java" is seen. */
   DECL_IGNORED_P (decl) = 1;
+
   TYPE_FOR_JAVA (type) = 1;
   return type;
 }
@@ -5800,7 +6167,7 @@ record_builtin_java_type (name, size)
 static void
 record_unknown_type (type, name)
      tree type;
-     char *name;
+     const char *name;
 {
   tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
   /* Make sure the "unknown type" typedecl gets ignored for debug info.  */
@@ -5954,6 +6321,9 @@ init_decl_processing ()
        : make_unsigned_type (CHAR_TYPE_SIZE));
   record_builtin_type (RID_CHAR, "char", char_type_node);
 
+  /* `signed' is the same as `int' */
+  record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
+  
   long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
   record_builtin_type (RID_LONG, "long int", long_integer_type_node);
 
@@ -5994,6 +6364,15 @@ init_decl_processing ()
   unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
   record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
 
+  /* Create the widest literal types. */
+  widest_integer_literal_type_node = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+                       widest_integer_literal_type_node));
+
+  widest_unsigned_literal_type_node = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
+  pushdecl (build_decl (TYPE_DECL, NULL_TREE, 
+                       widest_unsigned_literal_type_node));
+
   /* These are types that type_for_size and type_for_mode use.  */
   intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
@@ -6589,6 +6968,7 @@ init_decl_processing ()
 
   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
      say -fwritable-strings?  */
@@ -6616,11 +6996,11 @@ lang_print_error_function (file)
 
 tree
 define_function (name, type, function_code, pfn, library_name)
-     char *name;
+     const char *name;
      tree type;
      enum built_in_function function_code;
      void (*pfn) PROTO((tree));
-     char *library_name;
+     const char *library_name;
 {
   tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
   DECL_EXTERNAL (decl) = 1;
@@ -6656,7 +7036,7 @@ define_function (name, type, function_code, pfn, library_name)
    union type.)  */
 
 void
-fixup_anonymous_union (t)
+fixup_anonymous_aggr (t)
      tree t;
 {
   tree *q;
@@ -6667,7 +7047,6 @@ fixup_anonymous_union (t)
   TYPE_HAS_INIT_REF (t) = 0;
   TYPE_HAS_CONST_INIT_REF (t) = 0;
   TYPE_HAS_ASSIGN_REF (t) = 0;
-  TYPE_HAS_ASSIGNMENT (t) = 0;
   TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
 
   /* Splice the implicitly generated functions out of the TYPE_METHODS
@@ -6740,8 +7119,21 @@ check_tag_decl (declspecs)
      Until we have a good way of detecting the latter, don't warn.  */
   if (t == NULL_TREE && ! current_class_type)
     pedwarn ("declaration does not declare anything");
-  else if (t && ANON_UNION_TYPE_P (t))
-    /* Anonymous unions are objects, so they can have specifiers.  */;
+
+  /* Check for an anonymous union.  We're careful
+     accessing TYPE_IDENTIFIER because some built-in types, like
+     pointer-to-member types, do not have TYPE_NAME.  */
+  else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
+          && TYPE_NAME (t)
+          && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+    {
+      /* Anonymous unions are objects, so they can have specifiers.  */;
+      SET_ANON_AGGR_TYPE_P (t);
+
+      if (TREE_CODE (t) != UNION_TYPE && pedantic && ! in_system_header)
+       pedwarn ("ISO C++ prohibits anonymous structs");
+    }
+
   else if (ob_modifier)
     {
       if (ob_modifier == ridpointers[(int) RID_INLINE]
@@ -6785,9 +7177,9 @@ shadow_tag (declspecs)
      union { ... } ;
      because there is no declarator after the union, the parser
      sends that declaration here.  */
-  if (t && ANON_UNION_TYPE_P (t))
+  if (t && ANON_AGGR_TYPE_P (t))
     {
-      fixup_anonymous_union (t);
+      fixup_anonymous_aggr (t);
 
       if (TYPE_FIELDS (t))
        {
@@ -6841,6 +7233,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   tree context;
   extern int have_extern_spec;
   extern int used_extern_spec;
+  tree attrlist;
 
 #if 0
   /* See code below that used this.  */
@@ -6855,13 +7248,22 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       used_extern_spec = 1;
     }
 
+  if (attributes || prefix_attributes)
+    attrlist = build_scratch_list (attributes, prefix_attributes);
+  else
+    attrlist = NULL_TREE;
+
   decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
-                        NULL_TREE);
+                        attrlist);
+                        
   if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
     return NULL_TREE;
 
   type = TREE_TYPE (decl);
 
+  if (type == error_mark_node)
+    return NULL_TREE;
+
   /* Don't lose if destructors must be executed at file-level.  */
   if (! processing_template_decl && TREE_STATIC (decl)
       && TYPE_NEEDS_DESTRUCTOR (complete_type (type))
@@ -6922,28 +7324,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
        break;
 
       default:
-       if (! processing_template_decl)
-         {
-           if (type != error_mark_node)
-             {
-               if (TYPE_SIZE (type) != NULL_TREE
-                   && ! TREE_CONSTANT (TYPE_SIZE (type)))
-                 {
-                   cp_error
-                     ("variable-sized object `%D' may not be initialized",
-                      decl);
-                   initialized = 0;
-                 }
-
-               if (TREE_CODE (type) == ARRAY_TYPE
-                   && TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
-                 {
-                   cp_error
-                     ("elements of array `%#D' have incomplete type", decl);
-                   initialized = 0;
-                 }
-             }
-         }
+       break;
       }
 
   if (initialized)
@@ -6964,7 +7345,7 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
 
   if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
     {
-      pushclass (context, 2);
+      push_nested_class (context, 2);
 
       if (TREE_CODE (decl) == VAR_DECL)
        {
@@ -7108,6 +7489,9 @@ start_decl_1 (decl)
   tree type = TREE_TYPE (decl);
   int initialized = (DECL_INITIAL (decl) != NULL_TREE);
 
+  if (type == error_mark_node)
+    return;
+
   /* If this type of object needs a cleanup, and control may
      jump past it, make a new binding level so that it is cleaned
      up only when it is initialized first.  */
@@ -7122,9 +7506,7 @@ start_decl_1 (decl)
     {
       /* Don't allow initializations for incomplete types except for
         arrays which might be completed by the initialization.  */
-      if (type == error_mark_node)
-       ;                       /* Don't complain again.  */
-      else if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
+      if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
        ;                       /* A complete type is ok.  */
       else if (TREE_CODE (type) != ARRAY_TYPE)
        {
@@ -7359,6 +7741,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   char *asmspec = NULL;
   int was_readonly = 0;
   int already_used = 0;
+  tree core_type;
 
   /* If this is 0, then we did not change obstacks.  */
   if (! decl)
@@ -7435,6 +7818,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
 
       goto finish_end0;
     }
+
   /* Take care of TYPE_DECLs up front.  */
   if (TREE_CODE (decl) == TYPE_DECL)
     {
@@ -7465,15 +7849,13 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                                DECL_CONTEXT (decl) == NULL_TREE, at_eof);
       goto finish_end;
     }
+
   if (TREE_CODE (decl) != FUNCTION_DECL)
-    {
-      ttype = target_type (type);
-    }
+    ttype = target_type (type);
 
   if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
       && TYPE_NEEDS_CONSTRUCTING (type))
     {
-
       /* Currently, GNU C++ puts constants in text space, making them
         impossible to initialize.  In the future, one would hope for
         an operating system which understood the difference between
@@ -7512,8 +7894,28 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       init = NULL_TREE;
     }
 
+  /* Check for certain invalid initializations.  */
+  if (init)
+    {
+      if (TYPE_SIZE (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
+       {
+         cp_error ("variable-sized object `%D' may not be initialized", decl);
+         init = NULL_TREE;
+       }
+      if (TREE_CODE (type) == ARRAY_TYPE
+         && !TYPE_SIZE (complete_type (TREE_TYPE (type))))
+       {
+         cp_error ("elements of array `%#D' have incomplete type", decl);
+         init = NULL_TREE;
+       }
+    }
+
   GNU_xref_decl (current_function_decl, decl);
 
+  core_type = type;
+  while (TREE_CODE (core_type) == ARRAY_TYPE)
+    core_type = TREE_TYPE (core_type);
+  
   if (TREE_CODE (decl) == FIELD_DECL)
     ;
   else if (TREE_CODE (decl) == CONST_DECL)
@@ -7562,14 +7964,11 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
   else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
           && (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
     {
-      tree ctype = type;
-      while (TREE_CODE (ctype) == ARRAY_TYPE)
-       ctype = TREE_TYPE (ctype);
-      if (! TYPE_NEEDS_CONSTRUCTING (ctype))
+      if (! TYPE_NEEDS_CONSTRUCTING (core_type))
        {
-         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (ctype))
+         if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
            cp_error ("structure `%D' with uninitialized const members", decl);
-         if (CLASSTYPE_REF_FIELDS_NEED_INIT (ctype))
+         if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
            cp_error ("structure `%D' with uninitialized reference members",
                      decl);
        }
@@ -7751,7 +8150,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
              else if (! DECL_ARTIFICIAL (decl))
                {
                  cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
-                 cp_warning_at ("  you can work around this by removing the initializer"), decl;
+                 cp_warning_at ("  you can work around this by removing the initializer", decl);
                }
            }
        }
@@ -7759,31 +8158,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       else if (TREE_CODE (decl) == VAR_DECL
               && DECL_LANG_SPECIFIC (decl)
               && DECL_COMDAT (decl))
-       {
-         /* Dynamically initialized vars go into common.  */
-         if (DECL_INITIAL (decl) == NULL_TREE
-             || DECL_INITIAL (decl) == error_mark_node)
-           DECL_COMMON (decl) = 1;
-         else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
-           {
-             DECL_COMMON (decl) = 1;
-             DECL_INITIAL (decl) = error_mark_node;
-           }
-         else
-           {
-             /* Statically initialized vars are weak or comdat, if
-                 supported.  */
-             if (flag_weak)
-               make_decl_one_only (decl);
-             else
-               {
-                 /* We can't do anything useful; leave vars for explicit
-                    instantiation.  */
-                 DECL_EXTERNAL (decl) = 1;
-                 DECL_NOT_REALLY_EXTERN (decl) = 0;
-               }
-           }
-       }
+       /* Set it up again; we might have set DECL_INITIAL since the
+          last time.  */
+       comdat_linkage (decl);
 
       if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
        make_decl_rtl (decl, NULL_PTR, toplev);
@@ -7860,17 +8237,17 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        resume_temporary_allocation ();
 
       if (type != error_mark_node
-         && TYPE_LANG_SPECIFIC (type)
-         && CLASSTYPE_ABSTRACT_VIRTUALS (type))
-       abstract_virtuals_error (decl, type);
+         && TYPE_LANG_SPECIFIC (core_type)
+         && CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
+       abstract_virtuals_error (decl, core_type);
       else if ((TREE_CODE (type) == FUNCTION_TYPE
                || TREE_CODE (type) == METHOD_TYPE)
               && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
               && CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
        abstract_virtuals_error (decl, TREE_TYPE (type));
 
-      if (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE (type))
-       signature_error (decl, type);
+      if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
+       signature_error (decl, core_type);
       else if ((TREE_CODE (type) == FUNCTION_TYPE
                || TREE_CODE (type) == METHOD_TYPE)
               && TYPE_LANG_SPECIFIC (TREE_TYPE (type))
@@ -8026,7 +8403,7 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
               the binding level..  */
            && TYPE_SIZE (context) != NULL_TREE
            && context == current_class_type)
-         popclass (1);
+         pop_nested_class ();
       }
     }
 
@@ -8084,7 +8461,7 @@ expand_static_init (decl, init)
       if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
        cp_error ("multiple initializations given for `%D'", decl);
     }
-  else if (! toplevel_bindings_p () && ! pseudo_global_level_p ())
+  else if (! toplevel_bindings_p ())
     {
       /* Emit code to perform this initialization but once.  */
       tree temp;
@@ -8121,7 +8498,7 @@ expand_static_init (decl, init)
 
       /* Begin the conditional initialization.  */
       expand_start_cond (build_binary_op (EQ_EXPR, temp,
-                                         integer_zero_node, 1), 0);
+                                         integer_zero_node), 0);
       expand_start_target_temps ();
 
       /* Do the initialization itself.  */
@@ -8149,6 +8526,8 @@ expand_static_init (decl, init)
        {
          tree cleanup, fcall;
          static tree Atexit = 0;
+         int saved_flag_access_control;
+
          if (Atexit == 0)
            {
              tree atexit_fndecl, PFV, pfvlist;
@@ -8160,11 +8539,16 @@ expand_static_init (decl, init)
              pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
 
              push_lang_context (lang_name_c);
+             /* Note that we do not call pushdecl for this function;
+                there's no reason that this declaration should be
+                accessible to anyone.  */
              atexit_fndecl
-               = builtin_function ("atexit",
-                                   build_function_type (void_type_node,
-                                                        pfvlist),
-                                   NOT_BUILT_IN, NULL_PTR);
+               = define_function ("atexit",
+                                  build_function_type (void_type_node,
+                                                       pfvlist),
+                                  NOT_BUILT_IN, 
+                                  /*pfn=*/0,
+                                  NULL_PTR);
              mark_used (atexit_fndecl);
              Atexit = default_conversion (atexit_fndecl);
              pop_lang_context ();
@@ -8175,33 +8559,45 @@ expand_static_init (decl, init)
             so that any access checks will be done relative to the
             current scope, rather than the scope of the anonymous
             function.  */
-         fcall = build_cleanup (decl);
+         build_cleanup (decl);
+
+         /* Now start the function.  */
          cleanup = start_anon_func ();
+
+         /* Now, recompute the cleanup.  It may contain SAVE_EXPRs
+            that refer to the original function, rather than the
+            anonymous one.  That will make the back-end think that
+            nested functions are in use, which causes confusion.  */
+         saved_flag_access_control = flag_access_control;
+         flag_access_control = 0;
+         fcall = build_cleanup (decl);
+         flag_access_control = saved_flag_access_control;
+
+         /* Finish off the function.  */
          expand_expr_stmt (fcall);
          end_anon_func ();
+
+         /* Call atexit with the cleanup function.  */
          mark_addressable (cleanup);
          cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
-         fcall = build_function_call (Atexit, expr_tree_cons (NULL_TREE, cleanup, NULL_TREE));
+         fcall = build_function_call (Atexit, 
+                                      expr_tree_cons (NULL_TREE, 
+                                                      cleanup, 
+                                                      NULL_TREE));
          expand_expr_stmt (fcall);
        }
 
       expand_end_cond ();
-      if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
-       {
-         static_aggregates = perm_tree_cons (temp, decl, static_aggregates);
-         TREE_STATIC (static_aggregates) = 1;
-       }
-
       /* Resume old (possibly temporary) allocation.  */
       pop_obstacks ();
     }
   else
     {
-      /* This code takes into account memory allocation
-        policy of `start_decl'.  Namely, if TYPE_NEEDS_CONSTRUCTING
-        does not hold for this object, then we must make permanent
-        the storage currently in the temporary obstack.  */
-      if (! TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+      /* This code takes into account memory allocation policy of
+        `start_decl'.  Namely, if TYPE_NEEDS_CONSTRUCTING does not
+        hold for this object, then we must make permanent the storage
+        currently in the temporary obstack.  */
+      if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
        preserve_initializer ();
       static_aggregates = perm_tree_cons (init, decl, static_aggregates);
     }
@@ -8209,7 +8605,7 @@ expand_static_init (decl, init)
 \f
 /* Make TYPE a complete type based on INITIAL_VALUE.
    Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
-   2 if there was no information (in which case assume 1 if DO_DEFAULT).  */
+   2 if there was no information (in which case assume 0 if DO_DEFAULT).  */
 
 int
 complete_array_type (type, initial_value, do_default)
@@ -8218,7 +8614,10 @@ complete_array_type (type, initial_value, do_default)
 {
   register tree maxindex = NULL_TREE;
   int value = 0;
-
+  
+  /* Allocate on the same obstack as TYPE.  */
+  push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
+  
   if (initial_value)
     {
       /* Note MAXINDEX  is really the maximum index,
@@ -8248,6 +8647,8 @@ complete_array_type (type, initial_value, do_default)
          /* Make an error message unless that happened already.  */
          if (initial_value != error_mark_node)
            value = 1;
+         else
+           initial_value = NULL_TREE;
 
          /* Prevent further error messages.  */
          maxindex = build_int_2 (0, 0);
@@ -8264,23 +8665,28 @@ complete_array_type (type, initial_value, do_default)
   if (maxindex)
     {
       tree itype;
+      tree domain;
+
+      domain = build_index_type (maxindex);
+      TYPE_DOMAIN (type) = domain;
 
-      TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (! TREE_TYPE (maxindex))
-       TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+       TREE_TYPE (maxindex) = domain;
       if (initial_value)
         itype = TREE_TYPE (initial_value);
       else
        itype = NULL;
       if (itype && !TYPE_DOMAIN (itype))
-       TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
+       TYPE_DOMAIN (itype) = domain;
       /* The type of the main variant should never be used for arrays
         of different sizes.  It should only ever be completed with the
         size of the array.  */
       if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
-       TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = TYPE_DOMAIN (type);
+       TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
     }
 
+  pop_obstacks();
+  
   /* Lay out the type now that we can get the real answer.  */
 
   layout_type (type);
@@ -8295,7 +8701,7 @@ complete_array_type (type, initial_value, do_default)
 static int
 member_function_or_else (ctype, cur_type, string)
      tree ctype, cur_type;
-     char *string;
+     const char *string;
 {
   if (ctype && ctype != cur_type)
     {
@@ -8313,7 +8719,7 @@ member_function_or_else (ctype, cur_type, string)
 static void
 bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
      tree object;
-     char *type;
+     const char *type;
      int virtualp, quals, friendp, raises, inlinep;
 {
   if (virtualp)
@@ -8346,19 +8752,20 @@ bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
 
 static tree
 grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
-           raises, attrlist, check, friendp, publicp, inlinep, funcdef_flag,
+           raises, check, friendp, publicp, inlinep, funcdef_flag,
            template_count, in_namespace)
      tree ctype, type;
      tree declarator;
      tree orig_declarator;
      int virtualp;
      enum overload_flags flags;
-     tree quals, raises, attrlist;
+     tree quals, raises;
      int check, friendp, publicp, inlinep, funcdef_flag, template_count;
      tree in_namespace;
 {
   tree cname, decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
+  int has_default_arg = 0;
   tree t;
 
   if (ctype)
@@ -8475,7 +8882,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
     if (TREE_PURPOSE (t)
        && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
       {
-       add_defarg_fn (decl);
+       has_default_arg = 1;
        break;
       }
 
@@ -8496,6 +8903,7 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
              return NULL_TREE;
            }
 
+
          /* A friend declaration of the form friend void f<>().  Record
             the information in the TEMPLATE_ID_EXPR.  */
          SET_DECL_IMPLICIT_INSTANTIATION (decl);
@@ -8503,9 +8911,26 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
            = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
                              TREE_OPERAND (orig_declarator, 1),
                              NULL_TREE);
+
+         if (has_default_arg)
+           {
+             cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
+                       decl);
+             return NULL_TREE;
+           }
+
+         if (inlinep)
+           {
+             cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'", 
+                       decl);
+             return NULL_TREE;
+           }
        }
     }
 
+  if (has_default_arg)
+    add_defarg_fn (decl);
+
   /* Plain overloading: will not be grok'd by grokclassfn.  */
   if (! ctype && ! processing_template_decl
       && DECL_LANGUAGE (decl) != lang_c
@@ -8609,11 +9034,6 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
       if (ctype == NULL_TREE || check)
        return decl;
 
-      if (attrlist)
-       cplus_decl_attributes (decl, TREE_PURPOSE (attrlist), 
-                              TREE_VALUE (attrlist));
-      make_decl_rtl (decl, NULL_PTR, 1);
-
       if (virtualp)
        {
          DECL_VIRTUAL_P (decl) = 1;
@@ -8779,6 +9199,41 @@ build_ptrmemfunc_type (type)
   return t;
 }
 
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+   Check to see that the definition is valid.  Issue appropriate error
+   messages.  Return 1 if the definition is particularly bad, or 0
+   otherwise.  */
+
+int
+check_static_variable_definition (decl, type)
+     tree decl;
+     tree type;
+{
+  /* Motion 10 at San Diego: If a static const integral data member is
+     initialized with an integral constant expression, the initializer
+     may appear either in the declaration (within the class), or in
+     the definition, but not both.  If it appears in the class, the
+     member is a member constant.  The file-scope definition is always
+     required.  */
+  if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      cp_error ("in-class initialization of static data member of non-integral type `%T'", 
+               type);
+      /* If we just return the declaration, crashes will sometimes
+        occur.  We therefore return void_type_node, as if this was a
+        friend declaration, to cause callers to completely ignore
+        this declaration.  */
+      return 1;
+    }
+  else if (!CP_TYPE_CONST_P (type))
+    cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+             decl);
+  else if (pedantic && !INTEGRAL_TYPE_P (type))
+    cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+  return 0;
+}
+
 /* Given declspecs and a declarator,
    determine the name and type of the object declared
    and construct a ..._DECL node for it.
@@ -8806,6 +9261,9 @@ build_ptrmemfunc_type (type)
      BITFIELD for a field with specified width.
    INITIALIZED is 1 if the decl has an initializer.
 
+   ATTRLIST is a TREE_LIST node with prefix attributes in TREE_VALUE and
+   normal attributes in TREE_PURPOSE, or NULL_TREE.
+
    In the TYPENAME case, DECLARATOR is really an absolute declarator.
    It may also be so in the PARM case, for a prototype where the
    argument type is specified but not the name.
@@ -8837,41 +9295,6 @@ build_ptrmemfunc_type (type)
 
 enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
 
-/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
-   Check to see that the definition is valid.  Issue appropriate error
-   messages.  Return 1 if the definition is particularly bad, or 0
-   otherwise.  */
-
-int
-check_static_variable_definition (decl, type)
-     tree decl;
-     tree type;
-{
-  /* Motion 10 at San Diego: If a static const integral data member is
-     initialized with an integral constant expression, the initializer
-     may appear either in the declaration (within the class), or in
-     the definition, but not both.  If it appears in the class, the
-     member is a member constant.  The file-scope definition is always
-     required.  */
-  if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
-    {
-      cp_error ("in-class initialization of static data member of non-integral type `%T'", 
-               type);
-      /* If we just return the declaration, crashes will sometimes
-        occur.  We therefore return void_type_node, as if this was a
-        friend declaration, to cause callers to completely ignore
-        this declaration.  */
-      return 1;
-    }
-  else if (!CP_TYPE_CONST_P (type))
-    cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
-             decl);
-  else if (pedantic && !INTEGRAL_TYPE_P (type))
-    cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
-
-  return 0;
-}
-
 tree
 grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
      tree declspecs;
@@ -9008,14 +9431,29 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          case CALL_EXPR:
            if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
              {
-               /* This is actually a variable declaration using constructor
-                  syntax.  We need to call start_decl and cp_finish_decl so we
-                  can get the variable initialized...  */
+               /* This is actually a variable declaration using
+                  constructor syntax.  We need to call start_decl and
+                  cp_finish_decl so we can get the variable
+                  initialized...  */
+
+               tree attributes, prefix_attributes;
 
                *next = TREE_OPERAND (decl, 0);
                init = TREE_OPERAND (decl, 1);
 
-               decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
+               if (attrlist)
+                 {
+                   attributes = TREE_PURPOSE (attrlist);
+                   prefix_attributes = TREE_VALUE (attrlist);
+                 }
+               else
+                 {
+                   attributes = NULL_TREE;
+                   prefix_attributes = NULL_TREE;
+                 }
+
+               decl = start_decl (declarator, declspecs, 1,
+                                  attributes, prefix_attributes);
                if (decl)
                  {
                    /* Look for __unused__ attribute */
@@ -9057,12 +9495,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                if (TREE_CODE (fns) == LOOKUP_EXPR)
                  fns = TREE_OPERAND (fns, 0);
 
-               if (TREE_CODE (fns) == IDENTIFIER_NODE)
-                 dname = fns;
-               else if (is_overloaded_fn (fns))
-                 dname = DECL_NAME (get_first_fn (fns));
-               else
-                 my_friendly_abort (0);
+               dname = fns;
+               if (TREE_CODE (dname) == COMPONENT_REF)
+                 dname = TREE_OPERAND (dname, 1);
+               if (TREE_CODE (dname) != IDENTIFIER_NODE)
+                 {
+                   my_friendly_assert (is_overloaded_fn (dname),
+                                       19990331);
+                   dname = DECL_NAME (get_first_fn (dname));
+                 }
              }
          /* Fall through. */
 
@@ -9519,14 +9960,24 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
   if (RIDBIT_SETP (RID_UNSIGNED, specbits)
-      || (bitfield && ! flag_signed_bitfields
-         && (explicit_int || defaulted_int || explicit_char
-             /* A typedef for plain `int' without `signed'
-                can be controlled just like plain `int'.  */
-             || ! (typedef_decl != NULL_TREE
-                   && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
-         && TREE_CODE (type) != ENUMERAL_TYPE
-         && RIDBIT_NOTSETP (RID_SIGNED, specbits)))
+      /* [class.bit]
+
+        It is implementation-defined whether a plain (neither
+        explicitly signed or unsigned) char, short, int, or long
+        bit-field is signed or unsigned.
+            
+        Naturally, we extend this to long long as well.  Note that
+        this does not include wchar_t.  */
+      || (bitfield && !flag_signed_bitfields
+         && RIDBIT_NOTSETP (RID_SIGNED, specbits)
+         /* A typedef for plain `int' without `signed' can be
+            controlled just like plain `int', but a typedef for
+            `signed int' cannot be so controlled.  */
+         && !(typedef_decl 
+              && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
+         && (TREE_CODE (type) == INTEGER_TYPE
+             || TREE_CODE (type) == CHAR_TYPE)
+         && !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
     {
       if (longlong)
        type = long_long_unsigned_type_node;
@@ -9667,7 +10118,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   /* Static anonymous unions are dealt with here.  */
   if (staticp && decl_context == TYPENAME
       && TREE_CODE (declspecs) == TREE_LIST
-      && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
+      && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
     decl_context = FIELD;
 
   /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
@@ -9932,6 +10383,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            if (type == error_mark_node)
              continue;
 
+           /* VC++ spells a zero-sized array with [].  */
+           if (size == NULL_TREE && decl_context == FIELD && ! staticp
+               && ! RIDBIT_SETP (RID_TYPEDEF, specbits))
+             size = integer_zero_node;
+
            if (size)
              {
                /* Must suspend_momentary here because the index
@@ -10015,7 +10471,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  = fold (build_binary_op (MINUS_EXPR,
                                           cp_convert (index_type, size),
                                           cp_convert (index_type,
-                                                      integer_one_node), 1));
+                                                      integer_one_node)));
                if (! TREE_CONSTANT (itype))
                  itype = variable_size (itype);
                else if (TREE_OVERFLOW (itype))
@@ -10405,7 +10861,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                    push_nested_class used to push into class scope for
                    parsing the argument list of a function decl, in
                    qualified_id.  */
-               pop_nested_class (1);
+               pop_nested_class ();
                TREE_COMPLEXITY (declarator) = current_class_depth;
              }
            else
@@ -10550,16 +11006,14 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        attrlist = build_decl_list (NULL_TREE, inner_attrs);
     }
 
+  /* Now TYPE has the actual type.  */
+
   if (explicitp == 1)
     {
       error ("only constructors can be declared `explicit'");
       explicitp = 0;
     }
 
-  /* Now TYPE has the actual type.  */
-
-  /* If this is declaring a typedef name, return a TYPE_DECL.  */
-
   if (RIDBIT_SETP (RID_MUTABLE, specbits))
     {
       if (type_quals & TYPE_QUAL_CONST)
@@ -10586,8 +11040,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       declarator = dname;
     }
   else
+    /* Unexpected declarator format.  */
     my_friendly_abort (990210);
 
+  /* If this is declaring a typedef name, return a TYPE_DECL.  */
+
   if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
     {
       tree decl;
@@ -10624,20 +11081,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
       if (type != error_mark_node
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
-         && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
+         && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type))
+         && CP_TYPE_QUALS (type) == TYPE_UNQUALIFIED)
        {
-         /* FIXME: This is bogus; we should not be doing this for
-                   cv-qualified types.  */
-
-         /* For anonymous structs that are cv-qualified, need to use
-             TYPE_MAIN_VARIANT so that name will mangle correctly. As
-             type not referenced after this block, don't bother
-             resetting type to original type, ie. TREE_TYPE (decl). */
-         type = TYPE_MAIN_VARIANT (type);
+         tree oldname = TYPE_NAME (type);
+         tree t;
 
          /* Replace the anonymous name with the real name everywhere.  */
          lookup_tag_reverse (type, declarator);
-         TYPE_NAME (type) = decl;
+         for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+           if (TYPE_NAME (t) == oldname)
+             TYPE_NAME (t) = decl;
 
          if (TYPE_LANG_SPECIFIC (type))
            TYPE_WAS_ANONYMOUS (type) = 1;
@@ -10928,7 +11382,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                               TREE_CODE (declarator) != TEMPLATE_ID_EXPR
                               ? declarator : dname,
                               declarator,
-                              virtualp, flags, quals, raises, attrlist,
+                              virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, publicp, inlinep,
                               funcdef_flag, template_count, in_namespace);
            if (decl == NULL_TREE)
@@ -10978,7 +11432,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            /* All method decls are public, so tell grokfndecl to set
               TREE_PUBLIC, also.  */
            decl = grokfndecl (ctype, type, declarator, declarator,
-                              virtualp, flags, quals, raises, attrlist,
+                              virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
                               template_count, in_namespace);
            if (decl == NULL_TREE)
@@ -11038,7 +11492,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                      }
 
                    t = do_friend (ctype, declarator, decl,
-                                  last_function_parms, flags, quals,
+                                  last_function_parms, attrlist, flags, quals,
                                   funcdef_flag);
                  }
                if (t && funcdef_flag)
@@ -11171,7 +11625,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                   || !RIDBIT_SETP (RID_STATIC, specbits));
 
        decl = grokfndecl (ctype, type, original_name, declarator,
-                          virtualp, flags, quals, raises, attrlist,
+                          virtualp, flags, quals, raises,
                           1, friendp,
                           publicp, inlinep, funcdef_flag, 
                           template_count, in_namespace);
@@ -11255,9 +11709,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
     if (RIDBIT_SETP (RID_STATIC, specbits))
       DECL_THIS_STATIC (decl) = 1;
 
-    /* Record constancy and volatility.  */
-    /* FIXME: Disallow `restrict' pointer-to-member declarations.  */
-    c_apply_type_quals_to_decl (type_quals, decl);
+    /* Record constancy and volatility.  There's no need to do this
+       when processing a template; we'll do this for the instantiated
+       declaration based on the type of DECL.  */
+    if (!processing_template_decl)
+      c_apply_type_quals_to_decl (type_quals, decl);
 
     return decl;
   }
@@ -11806,7 +12262,7 @@ grok_op_properties (decl, virtualp, friendp)
       if (name == ansi_opname[(int) MODIFY_EXPR]
          && !(DECL_TEMPLATE_INSTANTIATION (decl)
               && is_member_template (DECL_TI_TEMPLATE (decl))))
-       TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
+       ;
       else if (name == ansi_opname[(int) CALL_EXPR])
        TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
       else if (name == ansi_opname[(int) ARRAY_REF])
@@ -11915,7 +12371,7 @@ grok_op_properties (decl, virtualp, friendp)
          else if (! friendp)
            {
              int ref = (TREE_CODE (t) == REFERENCE_TYPE);
-             char *what = 0;
+             const char *what = 0;
              if (ref)
                t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
 
@@ -12070,7 +12526,7 @@ grok_op_properties (decl, virtualp, friendp)
     }
 }
 \f
-static char *
+static const char *
 tag_name (code)
      enum tag_types code;
 {
@@ -12111,9 +12567,10 @@ xref_tag (code_type_node, name, globalize)
   enum tree_code code;
   int temp = 0;
   register tree ref, t;
-  struct binding_level *b = inner_binding_level;
+  struct binding_level *b = current_binding_level;
   int got_type = 0;
   tree attributes = NULL_TREE;
+  tree context = NULL_TREE;
 
   /* If we are called from the parser, code_type_node will sometimes be a
      TREE_LIST.  This indicates that the user wrote
@@ -12166,64 +12623,87 @@ xref_tag (code_type_node, name, globalize)
     }
   else
     {
-      if (current_class_type 
-         && template_class_depth (current_class_type) 
-         && PROCESSING_REAL_TEMPLATE_DECL_P ())
-      /* Since GLOBALIZE is non-zero, we are not looking at a
-        definition of this tag.  Since, in addition, we are currently
-        processing a (member) template declaration of a template
-        class, we don't want to do any lookup at all; consider:
-
-          template <class X>
-          struct S1
-
-          template <class U>
-          struct S2
-          { template <class V>
-            friend struct S1; };
-          
-        Here, the S2::S1 declaration should not be confused with the
-        outer declaration.  In particular, the inner version should
-        have a template parameter of level 2, not level 1.  This
-        would be particularly important if the member declaration
-        were instead:
-
-          template <class V = U> friend struct S1;
-
-        say, when we should tsubst into `U' when instantiating S2.  */
-       ref = NULL_TREE;
-      else 
+      if (t)
        {
-         if (t)
-           {
-             if (t != TYPE_MAIN_VARIANT (t))
-               cp_pedwarn ("using typedef-name `%D' after `%s'",
-                           TYPE_NAME (t), tag_name (tag_code));
-             ref = t;
-           }
-         else
-           ref = lookup_tag (code, name, b, 0);
+         /* [dcl.type.elab] If the identifier resolves to a
+            typedef-name or a template type-parameter, the
+            elaborated-type-specifier is ill-formed.  */
+         if (t != TYPE_MAIN_VARIANT (t)
+             || (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
+           cp_pedwarn ("using typedef-name `%D' after `%s'",
+                       TYPE_NAME (t), tag_name (tag_code));
+         else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
+           cp_error ("using template type parameter `%T' after `%s'",
+                     t, tag_name (tag_code));
+
+         ref = t;
+       }
+      else
+       ref = lookup_tag (code, name, b, 0);
          
-         if (! ref)
-           {
-             /* Try finding it as a type declaration.  If that wins,
-                use it.  */ 
-             ref = lookup_name (name, 1);
-
-             if (ref != NULL_TREE
-                 && processing_template_decl
-                 && DECL_CLASS_TEMPLATE_P (ref)
-                 && template_class_depth (current_class_type) == 0)
-               /* Since GLOBALIZE is true, we're declaring a global
+      if (! ref)
+       {
+         /* Try finding it as a type declaration.  If that wins,
+            use it.  */ 
+         ref = lookup_name (name, 1);
+
+         if (ref != NULL_TREE
+             && processing_template_decl
+             && DECL_CLASS_TEMPLATE_P (ref)
+             && template_class_depth (current_class_type) == 0)
+           /* Since GLOBALIZE is true, we're declaring a global
               template, so we want this type.  */
-               ref = DECL_RESULT (ref);
+           ref = DECL_RESULT (ref);
 
-             if (ref && TREE_CODE (ref) == TYPE_DECL
-                 && TREE_CODE (TREE_TYPE (ref)) == code)
-               ref = TREE_TYPE (ref);
-             else
-               ref = NULL_TREE;
-           }
+         if (ref && TREE_CODE (ref) == TYPE_DECL
+             && TREE_CODE (TREE_TYPE (ref)) == code)
+           ref = TREE_TYPE (ref);
+         else
+           ref = NULL_TREE;
+       }
+
+      if (ref && current_class_type 
+         && template_class_depth (current_class_type) 
+         && PROCESSING_REAL_TEMPLATE_DECL_P ()) 
+       {
+         /* Since GLOBALIZE is non-zero, we are not looking at a
+            definition of this tag.  Since, in addition, we are currently
+            processing a (member) template declaration of a template
+            class, we must be very careful; consider:
+
+              template <class X>
+              struct S1
+
+              template <class U>
+              struct S2
+              { template <class V>
+              friend struct S1; };
+
+            Here, the S2::S1 declaration should not be confused with the
+            outer declaration.  In particular, the inner version should
+            have a template parameter of level 2, not level 1.  This
+            would be particularly important if the member declaration
+            were instead:
+
+              template <class V = U> friend struct S1;
+
+            say, when we should tsubst into `U' when instantiating
+            S2.  On the other hand, when presented with:
+
+                template <class T>
+                struct S1 {
+                  template <class U>
+                  struct S2 {};
+                  template <class U>
+                  friend struct S2;
+                };
+
+              we must find the inner binding eventually.  We
+             accomplish this by making sure that the new type we
+             create to represent this declaration has the right
+             TYPE_CONTEXT.  */
+         context = TYPE_CONTEXT (ref);
+         ref = NULL_TREE;
        }
     }
 
@@ -12270,6 +12750,7 @@ xref_tag (code_type_node, name, globalize)
          struct binding_level *old_b = class_binding_level;
 
          ref = make_lang_type (code);
+         TYPE_CONTEXT (ref) = context;
 
          if (tag_code == signature_type)
            {
@@ -12323,19 +12804,6 @@ xref_tag (code_type_node, name, globalize)
 
   TREE_TYPE (ref) = attributes;
 
-  if (ref && TYPE_P (ref))
-    {
-      /* [dcl.type.elab]
-            
-        If the identifier resolves to a typedef-name or a template
-        type-parameter, the elaborated-type-specifier is
-        ill-formed.  */
-      if (TYPE_LANG_SPECIFIC (ref) && TYPE_WAS_ANONYMOUS (ref))
-       cp_error ("`%T' is a typedef name", ref);
-      else if (TREE_CODE (ref) == TEMPLATE_TYPE_PARM)
-       cp_error ("`%T' is a template type paramter", ref);
-    }
-
   return ref;
 }
 
@@ -12373,6 +12841,8 @@ xref_basetypes (code_type_node, name, ref, binfo)
   /* In the declaration `A : X, Y, ... Z' we mark all the types
      (A, X, Y, ..., Z) so we can check for duplicates.  */
   tree binfos;
+  tree base;
+
   int i, len;
   enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
 
@@ -12385,6 +12855,13 @@ xref_basetypes (code_type_node, name, ref, binfo)
   len = list_length (binfo);
   push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
 
+  /* First, make sure that any templates in base-classes are
+     instantiated.  This ensures that if we call ourselves recursively
+     we do not get confused about which classes are marked and which
+     are not.  */
+  for (base = binfo; base; base = TREE_CHAIN (base))
+    complete_type (TREE_VALUE (base));
+
   SET_CLASSTYPE_MARKED (ref);
   BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
 
@@ -12423,16 +12900,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
 
       GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
 
-#if 1
       /* This code replaces similar code in layout_basetypes.
          We put the complete_type first for implicit `typename'.  */
-      if (TYPE_SIZE (complete_type (basetype)) == NULL_TREE
+      if (TYPE_SIZE (basetype) == NULL_TREE
          && ! (current_template_parms && uses_template_parms (basetype)))
        {
          cp_error ("base class `%T' has incomplete type", basetype);
          continue;
        }
-#endif
       else
        {
          if (CLASSTYPE_MARKED (basetype))
@@ -12516,6 +12991,10 @@ xref_basetypes (code_type_node, name, ref, binfo)
     CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
   CLEAR_CLASSTYPE_MARKED (ref);
 
+  /* Now that we know all the base-classes, set up the list of virtual
+     bases.  */
+  CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
+
   pop_obstacks ();
 }
   
@@ -12531,7 +13010,7 @@ start_enum (name)
      tree name;
 {
   register tree enumtype = NULL_TREE;
-  struct binding_level *b = inner_binding_level;
+  struct binding_level *b = current_binding_level;
 
   /* We are wasting space here and putting these on the permanent_obstack so
      that typeid(local enum) will work correctly. */
@@ -12769,13 +13248,10 @@ build_enumerator (name, value, type)
  TREE_READONLY (decl) = 1;
 
  if (context && context == current_class_type)
-   {
-     pushdecl_class_level (decl);
-     /* In something like `struct S { enum E { i = 7 }; };' we put `i'
-       on the TYPE_FIELDS list for `S'.  (That's so that you can say
-       things like `S::i' later.)  */
-     finish_member_declaration (decl);
-   }
+   /* In something like `struct S { enum E { i = 7 }; };' we put `i'
+      on the TYPE_FIELDS list for `S'.  (That's so that you can say
+      things like `S::i' later.)  */
+   finish_member_declaration (decl);
  else
    {
      pushdecl (decl);
@@ -13095,7 +13571,8 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
        {
          DECL_EXTERNAL (decl1)
            = (interface_only
-              || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines));
+              || (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines
+                  && !DECL_VINDEX (decl1)));
 
          /* For WIN32 we also want to put these in linkonce sections.  */
          maybe_make_one_only (decl1);
@@ -13105,6 +13582,20 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
       DECL_NOT_REALLY_EXTERN (decl1) = 0;
       DECL_INTERFACE_KNOWN (decl1) = 1;
     }
+  else if (interface_unknown && interface_only
+          && (! DECL_TEMPLATE_INSTANTIATION (decl1)
+              || flag_alt_external_templates))
+    {
+      /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
+        interface, we will have interface_only set but not
+        interface_known.  In that case, we don't want to use the normal
+        heuristics because someone will supply a #pragma implementation
+        elsewhere, and deducing it here would produce a conflict.  */
+      comdat_linkage (decl1);
+      DECL_EXTERNAL (decl1) = 0;
+      DECL_INTERFACE_KNOWN (decl1) = 1;
+      DECL_DEFER_OUTPUT (decl1) = 1;
+    }
   else
     {
       /* This is a definition, not a reference.
@@ -13511,7 +14002,7 @@ finish_function (lineno, flags, nested)
   if (fndecl == NULL_TREE)
     return;
 
-  if (! nested && function_depth > 1)
+  if (function_depth > 1)
     nested = 1;
 
   fntype = TREE_TYPE (fndecl);
@@ -13727,7 +14218,7 @@ finish_function (lineno, flags, nested)
          if (! ok_to_optimize_dtor)
            {
              cond = build_binary_op (NE_EXPR,
-                                     current_class_ptr, integer_zero_node, 1);
+                                     current_class_ptr, integer_zero_node);
              expand_start_cond (cond, 0);
            }
 
@@ -13782,12 +14273,10 @@ finish_function (lineno, flags, nested)
          tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
          CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
 
-         DECL_RETURNS_FIRST_ARG (fndecl) = 1;
-
          if (flag_this_is_variable > 0)
            {
              cond = build_binary_op (EQ_EXPR,
-                                     current_class_ptr, integer_zero_node, 1);
+                                     current_class_ptr, integer_zero_node);
              thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
                                              build_new (NULL_TREE, current_class_type, void_type_node, 0));
            }
@@ -13947,7 +14436,7 @@ finish_function (lineno, flags, nested)
   if (current_class_name)
     {
       ctype = current_class_type;
-      pop_nested_class (1);
+      pop_nested_class ();
     }
 
   /* Must mark the RESULT_DECL as being in this function.  */
@@ -14297,7 +14786,7 @@ maybe_build_cleanup_1 (decl, auto_delete)
      tree decl, auto_delete;
 {
   tree type = TREE_TYPE (decl);
-  if (TYPE_NEEDS_DESTRUCTOR (type))
+  if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
     {
       int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
       tree rval;
@@ -14466,13 +14955,6 @@ revert_static_member_fn (decl, fn, argtypes)
     *argtypes = args;
 }
 
-int
-id_in_current_class (id)
-     tree id;
-{
-  return !!purpose_member (id, class_binding_level->class_shadowed);
-}
-
 struct cp_function
 {
   int returns_value;