OSDN Git Service

* decl.c (ENABLE_SCOPE_CHECKING): Rename from DEBUG_BINDING_LEVELS.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 9078da6..ec302ae 100644 (file)
@@ -50,6 +50,7 @@ Boston, MA 02111-1307, USA.  */
 #include "c-pragma.h"
 #include "diagnostic.h"
 #include "debug.h"
+#include "timevar.h"
 
 static tree grokparms (tree);
 static const char *redeclaration_error_message (tree, tree);
@@ -66,7 +67,7 @@ static void storedecls (tree);
 static void require_complete_types_for_parms (tree);
 static int ambi_op_p (enum tree_code);
 static int unary_op_p (enum tree_code);
-static tree store_bindings (tree, tree);
+static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
 static tree lookup_tag_reverse (tree, tree);
 static void push_local_name (tree);
 static void warn_extern_redeclared_static (tree, tree);
@@ -97,8 +98,7 @@ static void push_binding (tree, tree, struct cp_binding_level*);
 static int add_binding (tree, tree);
 static void pop_binding (tree, tree);
 static tree local_variable_p_walkfn (tree *, int *, void *);
-static tree find_binding (tree, tree);
-static tree select_decl (tree, int);
+static tree select_decl (cxx_binding *, int);
 static int lookup_flags (int, int);
 static tree qualify_lookup (tree, int);
 static tree record_builtin_java_type (const char *, int);
@@ -112,7 +112,7 @@ static void add_decl_to_level (tree, struct cp_binding_level *);
 static tree make_label_decl (tree, int);
 static void use_label (tree);
 static void check_previous_goto_1 (tree, struct cp_binding_level *, tree,
-                                  const char *, int);
+                                  const location_t *);
 static void check_previous_goto (struct named_label_use_list *);
 static void check_switch_goto (struct cp_binding_level *);
 static void check_previous_gotos (tree);
@@ -148,10 +148,6 @@ static tree next_initializable_field (tree);
 static tree reshape_init (tree, tree *);
 static tree build_typename_type (tree, tree, tree);
 
-#if defined (DEBUG_BINDING_LEVELS)
-static void indent (void);
-#endif
-
 /* Erroneous argument lists can use this *IFF* they do not modify it.  */
 tree error_mark_list;
 
@@ -215,8 +211,7 @@ struct named_label_use_list GTY(())
   struct cp_binding_level *binding_level;
   tree names_in_scope;
   tree label_decl;
-  const char *filename_o_goto;
-  int lineno_o_goto;
+  location_t o_goto_locus;
   struct named_label_use_list *next;
 };
 
@@ -326,18 +321,14 @@ struct cp_binding_level GTY(())
     /* A chain of NAMESPACE_DECL nodes.  */
     tree namespaces;
 
+    /* An array of static functions and variables (for namespaces only) */
+    varray_type static_decls;
+
     /* A chain of VTABLE_DECL nodes.  */
     tree vtables; 
 
-    /* A list of structure, union and enum definitions, for looking up
-       tag names.
-       It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
-       or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
-       or ENUMERAL_TYPE node.
-
-       C++: the TREE_VALUE nodes can be simple types for
-       component_bindings.  */
-    tree tags;
+    /* A dictionary for looking up user-defined-types.  */
+    binding_table type_decls;
 
     /* A list of USING_DECL nodes.  */
     tree usings;
@@ -431,9 +422,9 @@ struct cp_binding_level GTY(())
 /* The binding level currently in effect.  */
 
 #define current_binding_level                  \
-  (cfun && cp_function_chain->bindings         \
-   ? cp_function_chain->bindings               \
-   : scope_chain->bindings)
+  (*(cfun && cp_function_chain->bindings       \
+   ? &cp_function_chain->bindings              \
+   : &scope_chain->bindings))
 
 /* The binding level of the current class, if any.  */
 
@@ -443,12 +434,6 @@ struct cp_binding_level GTY(())
 
 static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
 
-/* The outermost binding level, for names of file scope.
-   This is created when the compiler is started and exists
-   through the entire run.  */
-
-static GTY(()) struct cp_binding_level *global_binding_level;
-
 /* Nonzero means unconditionally make a BLOCK for the next level pushed.  */
 
 static int keep_next_level_flag;
@@ -459,19 +444,23 @@ static int keep_next_level_flag;
 
 static GTY(()) tree incomplete_vars;
 
-#if defined(DEBUG_BINDING_LEVELS)
+#ifndef ENABLE_SCOPE_CHECKING
+#  define ENABLE_SCOPE_CHECKING 0
+#else
+#  define ENABLE_SCOPE_CHECKING 1
+#endif
+
 static int binding_depth = 0;
 static int is_class_level = 0;
 
 static void
-indent (void)
+indent (int depth)
 {
-  register unsigned i;
+  int i;
 
-  for (i = 0; i < binding_depth*2; i++)
+  for (i = 0; i < depth * 2; i++)
     putc (' ', stderr);
 }
-#endif /* defined(DEBUG_BINDING_LEVELS) */
 
 static tree pushdecl_with_scope        (tree, struct cp_binding_level *);
 
@@ -489,14 +478,16 @@ push_binding_level (struct cp_binding_level *newlevel,
   newlevel->more_cleanups_ok = 1;
 
   newlevel->keep = keep;
-#if defined(DEBUG_BINDING_LEVELS)
-  newlevel->binding_depth = binding_depth;
-  indent ();
-  fprintf (stderr, "push %s level 0x%08x line %d\n",
-          (is_class_level) ? "class" : "block", newlevel, lineno);
-  is_class_level = 0;
-  binding_depth++;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+  if (ENABLE_SCOPE_CHECKING)
+    {
+      newlevel->binding_depth = binding_depth;
+      indent (binding_depth);
+      verbatim ("push %s level %p line %d\n",
+                (is_class_level) ? "class" : "block",
+                (void *) newlevel, input_line);
+      is_class_level = 0;
+      binding_depth++;
+    }
 }
 
 /* Find the innermost enclosing class scope, and reset
@@ -518,34 +509,35 @@ find_class_binding_level (void)
 static void
 pop_binding_level (void)
 {
-  if (global_binding_level)
+  if (NAMESPACE_LEVEL (global_namespace))
+    /* Cannot pop a level, if there are none left to pop.  */
+    my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+  /* Pop the current level, and free the structure for reuse.  */
+  if (ENABLE_SCOPE_CHECKING)
     {
-      /* Cannot pop a level, if there are none left to pop.  */
-      if (current_binding_level == global_binding_level)
-       abort ();
+      indent (--binding_depth);
+      verbatim ("pop  %s level %p line %d\n",
+                (is_class_level) ? "class" : "block",
+                (void*) current_binding_level, input_line);
+      if (is_class_level != (current_binding_level == class_binding_level))
+        {
+          indent (binding_depth);
+          verbatim ("XXX is_class_level != (current_binding_level "
+                    "== class_binding_level)\n");
+        }
+      is_class_level = 0;
     }
-  /* Pop the current level, and free the structure for reuse.  */
-#if defined(DEBUG_BINDING_LEVELS)
-  binding_depth--;
-  indent ();
-  fprintf (stderr, "pop  %s level 0x%08x line %d\n",
-         (is_class_level) ? "class" : "block",
-         current_binding_level, lineno);
-  if (is_class_level != (current_binding_level == class_binding_level))
-    {
-      indent ();
-      fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
-    }
-  is_class_level = 0;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
   {
     register struct cp_binding_level *level = current_binding_level;
     current_binding_level = current_binding_level->level_chain;
     level->level_chain = free_binding_level;
-#if 0 /* defined(DEBUG_BINDING_LEVELS) */
-    if (level->binding_depth != binding_depth)
-      abort ();
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+    if (level->parm_flag == 2)
+      level->type_decls = NULL;
+    else
+      binding_table_free (level->type_decls);
+    my_friendly_assert (!ENABLE_SCOPE_CHECKING
+                        || level->binding_depth == binding_depth,
+                        20030529);
     free_binding_level = level;
     find_class_binding_level ();
   }
@@ -557,26 +549,24 @@ suspend_binding_level (void)
   if (class_binding_level)
     current_binding_level = class_binding_level;
 
-  if (global_binding_level)
+  if (NAMESPACE_LEVEL (global_namespace))
+    /* Cannot suspend a level, if there are none left to suspend.  */
+    my_friendly_assert (!global_scope_p (current_binding_level), 20030527);
+  /* Suspend the current level.  */
+  if (ENABLE_SCOPE_CHECKING)
     {
-      /* Cannot suspend a level, if there are none left to suspend.  */
-      if (current_binding_level == global_binding_level)
-       abort ();
+      indent (--binding_depth);
+      verbatim ("suspend  %s level %p line %d\n",
+                (is_class_level) ? "class" : "block",
+                (void *) current_binding_level, input_line);
+      if (is_class_level != (current_binding_level == class_binding_level))
+        {
+          indent (binding_depth);
+          verbatim ("XXX is_class_level != (current_binding_level "
+                    "== class_binding_level)\n");
+        }
+      is_class_level = 0;
     }
-  /* Suspend the current level.  */
-#if defined(DEBUG_BINDING_LEVELS)
-  binding_depth--;
-  indent ();
-  fprintf (stderr, "suspend  %s level 0x%08x line %d\n",
-         (is_class_level) ? "class" : "block",
-         current_binding_level, lineno);
-  if (is_class_level != (current_binding_level == class_binding_level))
-    {
-      indent ();
-      fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
-    }
-  is_class_level = 0;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
   current_binding_level = current_binding_level->level_chain;
   find_class_binding_level ();
 }
@@ -590,14 +580,15 @@ resume_binding_level (struct cp_binding_level* b)
   /* Also, resuming a non-directly nested namespace is a no-no.  */
   my_friendly_assert(b->level_chain == current_binding_level, 386);
   current_binding_level = b;
-#if defined(DEBUG_BINDING_LEVELS)
-  b->binding_depth = binding_depth;
-  indent ();
-  fprintf (stderr, "resume %s level 0x%08x line %d\n",
-          (is_class_level) ? "class" : "block", b, lineno);
-  is_class_level = 0;
-  binding_depth++;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+  if (ENABLE_SCOPE_CHECKING)
+    {
+      b->binding_depth = binding_depth;
+      indent (binding_depth);
+      verbatim ("resume %s level %p line %d\n",
+                (is_class_level) ? "class" : "block", b, input_line);
+      is_class_level = 0;
+      binding_depth++;
+    }
 }
 \f
 /* Create a new `struct cp_binding_level'.  */
@@ -615,7 +606,7 @@ make_binding_level (void)
 int
 global_bindings_p (void)
 {
-  return current_binding_level == global_binding_level;
+  return global_scope_p (current_binding_level);
 }
 
 /* Return the innermost binding level that is not for a class scope.  */
@@ -676,7 +667,7 @@ kept_level_p (void)
   return (current_binding_level->blocks != NULL_TREE
          || current_binding_level->keep
          || current_binding_level->names != NULL_TREE
-         || (current_binding_level->tags != NULL_TREE
+         || (current_binding_level->type_decls != NULL
              && !current_binding_level->tag_transparent));
 }
 
@@ -802,11 +793,7 @@ pushlevel (int tag_transparent)
     return;
 
   /* Reuse or create a struct for this binding level.  */
-#if defined(DEBUG_BINDING_LEVELS)
-  if (0)
-#else /* !defined(DEBUG_BINDING_LEVELS) */
-  if (free_binding_level)
-#endif /* !defined(DEBUG_BINDING_LEVELS) */
+  if (!ENABLE_SCOPE_CHECKING && free_binding_level)
     {
       newlevel = free_binding_level;
       free_binding_level = free_binding_level->level_chain;
@@ -881,44 +868,21 @@ finish_scope (void)
   poplevel (0, 0, 0);
 }
 
-/* For a binding between a name and an entity at a block scope,
-   this is the `struct cp_binding_level' for the block.  */
-#define BINDING_LEVEL(NODE) \
-  (((struct tree_binding*)(NODE))->scope.level)
-
-/* A free list of CPLUS_BINDING nodes, connected by their
-   TREE_CHAINs.  */
-
-static GTY((deletable (""))) tree free_bindings;
-
 /* Make DECL the innermost binding for ID.  The LEVEL is the binding
    level at which this declaration is being bound.  */
 
 static void
-push_binding (tree id, 
-              tree decl,
-              struct cp_binding_level* level)
+push_binding (tree id, tree decl, cxx_scope* level)
 {
-  tree binding;
-
-  if (free_bindings)
-    {
-      binding = free_bindings;
-      free_bindings = TREE_CHAIN (binding);
-    }
-  else
-    binding = make_node (CPLUS_BINDING);
+   cxx_binding *binding = cxx_binding_make (decl, NULL);
 
   /* Now, fill in the binding information.  */
-  BINDING_VALUE (binding) = decl;
-  BINDING_TYPE (binding) = NULL_TREE;
-  BINDING_LEVEL (binding) = level;
+  binding->previous = IDENTIFIER_BINDING (id);
+  BINDING_SCOPE (binding) = level;
   INHERITED_VALUE_BINDING_P (binding) = 0;
   LOCAL_BINDING_P (binding) = (level != class_binding_level);
-  BINDING_HAS_LEVEL_P (binding) = 1;
 
   /* And put it on the front of the list of bindings for ID.  */
-  TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
   IDENTIFIER_BINDING (id) = binding;
 }
 
@@ -931,9 +895,10 @@ push_binding (tree id,
 static int
 add_binding (tree id, tree decl)
 {
-  tree binding = IDENTIFIER_BINDING (id);
+  cxx_binding *binding = IDENTIFIER_BINDING (id);
   int ok = 1;
 
+  timevar_push (TV_NAME_LOOKUP);
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
     /* The new name is the type name.  */
     BINDING_TYPE (binding) = decl;
@@ -990,7 +955,7 @@ add_binding (tree id, tree decl)
       ok = 0;
     }
 
-  return ok;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
 }
 
 /* Add DECL to the list of things declared in B.  */
@@ -1017,6 +982,13 @@ add_decl_to_level (tree decl,
       TREE_CHAIN (decl) = b->names;
       b->names = decl;
       b->names_size++;
+
+      /* If appropriate, add decl to separate list of statics */
+      if (b->namespace_p)
+       if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
+           || (TREE_CODE (decl) == FUNCTION_DECL
+               && (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
+         VARRAY_PUSH_TREE (b->static_decls, decl);
     }
 }
 
@@ -1067,15 +1039,16 @@ int
 push_class_binding (tree id, tree decl)
 {
   int result = 1;
-  tree binding = IDENTIFIER_BINDING (id);
+  cxx_binding *binding = IDENTIFIER_BINDING (id);
   tree context;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* Note that we declared this value so that we can issue an error if
      this is an invalid 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)
+  if (binding && BINDING_SCOPE (binding) == class_binding_level)
     /* Supplement the existing binding.  */
     result = add_binding (id, decl);
   else
@@ -1112,7 +1085,7 @@ push_class_binding (tree id, tree decl)
        in this class.  */
     INHERITED_VALUE_BINDING_P (binding) = 1;
 
-  return result;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
 }
 
 /* Remove the binding for DECL which should be the innermost binding
@@ -1121,7 +1094,7 @@ push_class_binding (tree id, tree decl)
 static void
 pop_binding (tree id, tree decl)
 {
-  tree binding;
+  cxx_binding *binding;
 
   if (id == NULL_TREE)
     /* It's easiest to write the loops that call this function without
@@ -1133,7 +1106,7 @@ pop_binding (tree id, tree decl)
   binding = IDENTIFIER_BINDING (id);
 
   /* The name should be bound.  */
-  my_friendly_assert (binding != NULL_TREE, 0);
+  my_friendly_assert (binding != NULL, 0);
 
   /* The DECL will be either the ordinary binding or the type
      binding for this identifier.  Remove that binding.  */
@@ -1148,15 +1121,14 @@ pop_binding (tree id, tree decl)
     {
       /* We're completely done with the innermost binding for this
         identifier.  Unhook it from the list of bindings.  */
-      IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+      IDENTIFIER_BINDING (id) = binding->previous;
 
       /* Add it to the free list.  */
-      TREE_CHAIN (binding) = free_bindings;
-      free_bindings = binding;
+      cxx_binding_free (binding);
 
-      /* Clear the BINDING_LEVEL so the garbage collector doesn't walk
+      /* Clear the BINDING_SCOPE so the garbage collector doesn't walk
         it.  */
-      BINDING_LEVEL (binding) = NULL;
+      BINDING_SCOPE (binding) = NULL;
     }
 }
 
@@ -1228,21 +1200,20 @@ poplevel (int keep, int reverse, int functionbody)
   tree decls;
   int tmp = functionbody;
   int real_functionbody;
-  tree tags;
   tree subblocks;
   tree block = NULL_TREE;
   tree decl;
   int leaving_for_scope;
 
+  timevar_push (TV_NAME_LOOKUP);
   if (cfun && !doing_semantic_analysis_p ())
-    return NULL_TREE;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 
   my_friendly_assert (current_binding_level->parm_flag != 2,
                      19990916);
 
   real_functionbody = (current_binding_level->keep == 2
                       ? ((functionbody = 0), tmp) : functionbody);
-  tags = functionbody >= 0 ? current_binding_level->tags : 0;
   subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
 
   my_friendly_assert (!current_binding_level->class_shadowed,
@@ -1362,8 +1333,8 @@ poplevel (int keep, int reverse, int functionbody)
       if (leaving_for_scope && TREE_CODE (link) == VAR_DECL
           && DECL_NAME (link))
        {
-         tree outer_binding
-           = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+         cxx_binding *outer_binding
+           = IDENTIFIER_BINDING (DECL_NAME (link))->previous;
          tree ns_binding;
 
          if (!outer_binding)
@@ -1372,7 +1343,7 @@ poplevel (int keep, int reverse, int functionbody)
            ns_binding = NULL_TREE;
 
          if (outer_binding
-             && (BINDING_LEVEL (outer_binding)
+             && (BINDING_SCOPE (outer_binding)
                  == current_binding_level->level_chain))
            /* We have something like:
 
@@ -1404,7 +1375,7 @@ poplevel (int keep, int reverse, int functionbody)
                 there only for backward compatibility.  */
              DECL_DEAD_FOR_LOCAL (link) = 1;
 
-             /* Keep track of what should of have happenned when we
+             /* Keep track of what should have happened when we
                 popped the binding.  */
              if (outer_binding && BINDING_VALUE (outer_binding))
                DECL_SHADOWED_FOR_VAR (link)
@@ -1418,10 +1389,9 @@ poplevel (int keep, int reverse, int functionbody)
                             current_binding_level->level_chain->
                             dead_vars_from_for);
 
-             /* Although we don't pop the CPLUS_BINDING, we do clear
-                its BINDING_LEVEL since the level is going away now.  */
-             BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
-               = 0;
+             /* Although we don't pop the cxx_binding, we do clear
+                its BINDING_SCOPE since the level is going away now.  */
+             BINDING_SCOPE (IDENTIFIER_BINDING (DECL_NAME (link))) = 0;
            }
        }
       else
@@ -1526,7 +1496,7 @@ poplevel (int keep, int reverse, int functionbody)
       block = poplevel (keep, reverse, functionbody);
     }
 
-  return block;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, block);
 }
 
 /* Delete the node BLOCK from the current binding level.
@@ -1583,11 +1553,7 @@ pushlevel_class (void)
   register struct cp_binding_level *newlevel;
 
   /* Reuse or create a struct for this binding level.  */
-#if defined(DEBUG_BINDING_LEVELS)
-  if (0)
-#else /* !defined(DEBUG_BINDING_LEVELS) */
-  if (free_binding_level)
-#endif /* !defined(DEBUG_BINDING_LEVELS) */
+  if (!ENABLE_SCOPE_CHECKING && free_binding_level)
     {
       newlevel = free_binding_level;
       free_binding_level = free_binding_level->level_chain;
@@ -1595,9 +1561,8 @@ pushlevel_class (void)
   else
     newlevel = make_binding_level ();
 
-#if defined(DEBUG_BINDING_LEVELS)
-  is_class_level = 1;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+  if (ENABLE_SCOPE_CHECKING)
+    is_class_level = 1;
 
   push_binding_level (newlevel, 0, 0);
 
@@ -1614,6 +1579,7 @@ poplevel_class (void)
   register struct cp_binding_level *level = class_binding_level;
   tree shadowed;
 
+  timevar_push (TV_NAME_LOOKUP);
   my_friendly_assert (level != 0, 354);
 
   /* If we're leaving a toplevel class, don't bother to do the setting
@@ -1642,15 +1608,15 @@ poplevel_class (void)
             shadowed;
             shadowed = TREE_CHAIN (shadowed))
          {
-           tree t;
-
-           t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
-           while (t && BINDING_LEVEL (t) != b)
-             t = TREE_CHAIN (t);
+           cxx_binding *binding;
+            
+           binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
+           while (binding && BINDING_SCOPE (binding) != b)
+             binding = binding->previous;
 
-           if (t)
+           if (binding)
              IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
-               = BINDING_VALUE (t);
+               = BINDING_VALUE (binding);
          }
     }
   else
@@ -1673,11 +1639,11 @@ poplevel_class (void)
 
   /* Now, pop out of the binding level which we created up in the
      `pushlevel_class' routine.  */
-#if defined(DEBUG_BINDING_LEVELS)
-  is_class_level = 1;
-#endif /* defined(DEBUG_BINDING_LEVELS) */
+  if (ENABLE_SCOPE_CHECKING)
+    is_class_level = 1;
 
   pop_binding_level ();
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* We are entering the scope of a class.  Clear IDENTIFIER_CLASS_VALUE
@@ -1843,23 +1809,12 @@ walk_globals (walk_globals_pred p, walk_globals_fn f, void *data)
 int
 wrapup_globals_for_namespace (tree namespace, void* data)
 {
-  tree globals = cp_namespace_decls (namespace);
-  int len = NAMESPACE_LEVEL (namespace)->names_size;
-  tree *vec = (tree *) alloca (sizeof (tree) * len);
-  int i;
-  int result;
-  tree decl;
+  struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
+  varray_type statics = level->static_decls;
+  tree *vec = &VARRAY_TREE (statics, 0);
+  int len = VARRAY_ACTIVE_SIZE (statics);
   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);
@@ -1867,9 +1822,7 @@ wrapup_globals_for_namespace (tree namespace, void* data)
     }
 
   /* Write out any globals that need to be output.  */
-  result = wrapup_global_declarations (vec, len);
-
-  return result;
+  return wrapup_global_declarations (vec, len);
 }
 
 \f
@@ -1877,13 +1830,52 @@ wrapup_globals_for_namespace (tree namespace, void* data)
 static int no_print_functions = 0;
 static int no_print_builtins = 0;
 
+/* Called from print_binding_level through binding_table_foreach to
+   print the content of binding ENTRY.  DATA is a pointer to line offset
+   marker.  */
+static void
+bt_print_entry (binding_entry entry, void *data)
+{
+  int *p = (int *) data;
+  int len;
+
+  if (entry->name == NULL)
+    len = 3;
+  else if (entry->name == TYPE_IDENTIFIER (entry->type))
+    len = 2;
+  else
+    len = 4;
+    len = 4;
+
+  *p += len;
+
+  if (*p > 5)
+    {
+      fprintf (stderr, "\n\t");
+      *p = len;
+    }
+  if (entry->name == NULL)
+    {
+      print_node_brief (stderr, "<unnamed-typedef", entry->type, 0);
+      fprintf (stderr, ">");
+    }
+  else if (entry->name == TYPE_IDENTIFIER (entry->type))
+    print_node_brief (stderr, "", entry->type, 0);
+  else
+    {
+      print_node_brief (stderr, "<typedef", entry->name, 0);
+      print_node_brief (stderr, "", entry->type, 0);
+      fprintf (stderr, ">");
+    }
+}
+
 void
 print_binding_level (struct cp_binding_level* lvl)
 {
   tree t;
   int i = 0, len;
   fprintf (stderr, " blocks=");
-  fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
+  fprintf (stderr, HOST_PTR_PRINTF, (void *) lvl->blocks);
   if (lvl->tag_transparent)
     fprintf (stderr, " tag-transparent");
   if (lvl->more_cleanups_ok)
@@ -1922,38 +1914,11 @@ print_binding_level (struct cp_binding_level* lvl)
       if (i)
         fprintf (stderr, "\n");
     }
-  if (lvl->tags)
+  if (lvl->type_decls)
     {
       fprintf (stderr, " tags:\t");
       i = 0;
-      for (t = lvl->tags; t; t = TREE_CHAIN (t))
-       {
-         if (TREE_PURPOSE (t) == NULL_TREE)
-           len = 3;
-         else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
-           len = 2;
-         else
-           len = 4;
-         i += len;
-         if (i > 5)
-           {
-             fprintf (stderr, "\n\t");
-             i = len;
-           }
-         if (TREE_PURPOSE (t) == NULL_TREE)
-           {
-             print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
-             fprintf (stderr, ">");
-           }
-         else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
-           print_node_brief (stderr, "", TREE_VALUE (t), 0);
-         else
-           {
-             print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
-             print_node_brief (stderr, "", TREE_VALUE (t), 0);
-             fprintf (stderr, ">");
-           }
-       }
+      binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
       if (i)
        fprintf (stderr, "\n");
     }
@@ -1981,10 +1946,10 @@ void
 print_other_binding_stack (struct cp_binding_level *stack)
 {
   struct cp_binding_level *level;
-  for (level = stack; level != global_binding_level; level = level->level_chain)
+  for (level = stack; !global_scope_p (level); level = level->level_chain)
     {
       fprintf (stderr, "binding level ");
-      fprintf (stderr, HOST_PTR_PRINTF, level);
+      fprintf (stderr, HOST_PTR_PRINTF, (void *) level);
       fprintf (stderr, "\n");
       print_binding_level (level);
     }
@@ -1995,11 +1960,12 @@ print_binding_stack (void)
 {
   struct cp_binding_level *b;
   fprintf (stderr, "current_binding_level=");
-  fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
+  fprintf (stderr, HOST_PTR_PRINTF, (void *) current_binding_level);
   fprintf (stderr, "\nclass_binding_level=");
-  fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
-  fprintf (stderr, "\nglobal_binding_level=");
-  fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
+  fprintf (stderr, HOST_PTR_PRINTF, (void *) class_binding_level);
+  fprintf (stderr, "\nNAMESPACE_LEVEL (global_namespace)=");
+  fprintf (stderr, HOST_PTR_PRINTF,
+           (void *) NAMESPACE_LEVEL (global_namespace));
   fprintf (stderr, "\n");
   if (class_binding_level)
     {
@@ -2015,119 +1981,12 @@ print_binding_stack (void)
     b = current_binding_level;
   print_other_binding_stack (b);
   fprintf (stderr, "global:\n");
-  print_binding_level (global_binding_level);
+  print_binding_level (NAMESPACE_LEVEL (global_namespace));
 }
 
 /* Namespace binding access routines: The namespace_bindings field of
    the identifier is polymorphic, with three possible values:
-   NULL_TREE, a list of CPLUS_BINDINGS, or any other tree_node
-   indicating the BINDING_VALUE of global_namespace.  */
-
-/* Check whether the a binding for the name to scope is known.
-   Assumes that the bindings of the name are already a list
-   of bindings. Returns the binding found, or NULL_TREE.  */
-
-static tree
-find_binding (tree name, tree scope)
-{
-  tree iter, prev = NULL_TREE;
-
-  scope = ORIGINAL_NAMESPACE (scope);
-
-  for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
-       iter = TREE_CHAIN (iter))
-    {
-      my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
-      if (BINDING_SCOPE (iter) == scope)
-       {
-         /* Move binding found to the front of the list, so
-             subsequent lookups will find it faster.  */
-         if (prev)
-           {
-             TREE_CHAIN (prev) = TREE_CHAIN (iter);
-             TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
-             IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
-           }
-         return iter;
-       }
-      prev = iter;
-    }
-  return NULL_TREE;
-}
-
-/* Always returns a binding for name in scope. If the
-   namespace_bindings is not a list, convert it to one first.
-   If no binding is found, make a new one.  */
-
-tree
-binding_for_name (tree name, tree scope)
-{
-  tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-  tree result;
-
-  scope = ORIGINAL_NAMESPACE (scope);
-
-  if (b && TREE_CODE (b) != CPLUS_BINDING)
-    {
-      /* Get rid of optimization for global scope.  */
-      IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
-      BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
-      b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-    }
-  if (b && (result = find_binding (name, scope)))
-    return result;
-  /* Not found, make a new one.  */
-  result = make_node (CPLUS_BINDING);
-  TREE_CHAIN (result) = b;
-  IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
-  BINDING_SCOPE (result) = scope;
-  BINDING_TYPE (result) = NULL_TREE;
-  BINDING_VALUE (result) = NULL_TREE;
-  return result;
-}
-
-/* Return the binding value for name in scope, considering that
-   namespace_binding may or may not be a list of CPLUS_BINDINGS.  */
-
-tree
-namespace_binding (tree name, tree scope)
-{
-  tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-  if (b == NULL_TREE)
-    return NULL_TREE;
-  if (scope == NULL_TREE)
-    scope = global_namespace;
-  if (TREE_CODE (b) != CPLUS_BINDING)
-    return (scope == global_namespace) ? b : NULL_TREE;
-  name = find_binding (name,scope);
-  if (name == NULL_TREE)
-    return name;
-  return BINDING_VALUE (name);
-}
-
-/* Set the binding value for name in scope. If modifying the binding
-   of global_namespace is attempted, try to optimize it.  */
-
-void
-set_namespace_binding (tree name, tree scope, tree val)
-{
-  tree b;
-
-  if (scope == NULL_TREE)
-    scope = global_namespace;
-
-  if (scope == global_namespace)
-    {
-      b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-      if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
-       {
-         IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
-         return;
-       }
-    }
-  b = binding_for_name (name, scope);
-  BINDING_VALUE (b) = val;
-}
+   NULL_TREE, a list of "cxx_binding"s.  */
 
 /* Push into the scope of the NAME namespace.  If NAME is NULL_TREE, then we
    select a name that is unique to this compilation unit.  */
@@ -2139,6 +1998,9 @@ push_namespace (tree name)
   int need_new = 1;
   int implicit_use = 0;
   int global = 0;
+
+  timevar_push (TV_NAME_LOOKUP);
+  
   if (!global_namespace)
     {
       /* This must be ::.  */
@@ -2187,6 +2049,13 @@ push_namespace (tree name)
          pushlevel (0);
          declare_namespace_level ();
          NAMESPACE_LEVEL (d) = current_binding_level;
+          current_binding_level->type_decls =
+            binding_table_new (name == std_identifier
+                               ? NAMESPACE_STD_HT_SIZE
+                               : NAMESPACE_ORDINARY_HT_SIZE);
+         VARRAY_TREE_INIT (current_binding_level->static_decls,
+                           name != std_identifier ? 10 : 200,
+                           "Static declarations");
        }
     }
   else
@@ -2196,6 +2065,8 @@ push_namespace (tree name)
     do_using_directive (d);
   /* Enter the name space.  */
   current_namespace = d;
+
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Pop from the scope of the current namespace.  */
@@ -2230,6 +2101,7 @@ push_nested_namespace (tree ns)
 void
 pop_nested_namespace (tree ns)
 {
+  timevar_push (TV_NAME_LOOKUP);
   while (ns != global_namespace)
     {
       pop_namespace ();
@@ -2237,9 +2109,26 @@ pop_nested_namespace (tree ns)
     }
 
   pop_from_top_level ();
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 \f
+/* Allocate storage for saving a C++ binding.  */
+#define cxx_saved_binding_make() \
+  (ggc_alloc (sizeof (cxx_saved_binding)))
+
+struct cxx_saved_binding GTY(())
+{
+  /* Link that chains saved C++ bindings for a given name into a stack.  */
+  cxx_saved_binding *previous;
+  /* The name of the current binding.  */
+  tree identifier;
+  /* The binding we're saving.  */
+  cxx_binding *binding;
+  tree class_value;
+  tree real_type_value;
+};
+
 /* Subroutines for reverting temporarily to top-level for instantiation
    of templates and such.  We actually need to clear out the class- and
    local-value slots of all identifiers, so that only the global values
@@ -2247,15 +2136,18 @@ pop_nested_namespace (tree ns)
    scope isn't enough, because more binding levels may be pushed.  */
 struct saved_scope *scope_chain;
 
-static tree
-store_bindings (tree names, tree old_bindings)
+static cxx_saved_binding *
+store_bindings (tree names, cxx_saved_binding *old_bindings)
 {
   tree t;
-  tree search_bindings = old_bindings;
+  cxx_saved_binding *search_bindings = old_bindings;
 
+  timevar_push (TV_NAME_LOOKUP);
   for (t = names; t; t = TREE_CHAIN (t))
     {
-      tree binding, t1, id;
+      tree id;
+      cxx_saved_binding *saved;
+      cxx_saved_binding *t1;
 
       if (TREE_CODE (t) == TREE_LIST)
        id = TREE_PURPOSE (t);
@@ -2269,24 +2161,24 @@ store_bindings (tree names, tree old_bindings)
          || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
        continue;
 
-      for (t1 = search_bindings; t1; t1 = TREE_CHAIN (t1))
-       if (TREE_VEC_ELT (t1, 0) == id)
+      for (t1 = search_bindings; t1; t1 = t1->previous)
+       if (t1->identifier == id)
          goto skip_it;
 
       my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
-      binding = make_tree_vec (4);
-      TREE_VEC_ELT (binding, 0) = id;
-      TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
-      TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
-      TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
-      IDENTIFIER_BINDING (id) = NULL_TREE;
+      saved = cxx_saved_binding_make ();
+      saved->previous = old_bindings;
+      saved->identifier = id;
+      saved->binding = IDENTIFIER_BINDING (id);
+      saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
+      saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
+      IDENTIFIER_BINDING (id) = NULL;
       IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
-      TREE_CHAIN (binding) = old_bindings;
-      old_bindings = binding;
+      old_bindings = saved;
     skip_it:
       ;
     }
-  return old_bindings;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
 }
 
 void
@@ -2294,9 +2186,10 @@ maybe_push_to_top_level (int pseudo)
 {
   struct saved_scope *s;
   struct cp_binding_level *b;
-  tree old_bindings;
+  cxx_saved_binding *old_bindings;
   int need_pop;
 
+  timevar_push (TV_NAME_LOOKUP);
   s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
 
   b = scope_chain ? current_binding_level : 0;
@@ -2310,11 +2203,11 @@ maybe_push_to_top_level (int pseudo)
   else
     need_pop = 0;
 
-  old_bindings = NULL_TREE;
+  old_bindings = NULL;
   if (scope_chain && previous_class_type)
     old_bindings = store_bindings (previous_class_values, old_bindings);
 
-  /* Have to include global_binding_level, because class-level decls
+  /* Have to include the global scope, because class-scope decls
      aren't listed anywhere useful.  */
   for (; b; b = b->level_chain)
     {
@@ -2324,7 +2217,7 @@ maybe_push_to_top_level (int pseudo)
         inserted into namespace level, finish_file wouldn't find them
         when doing pending instantiations. Therefore, don't stop at
         namespace level, but continue until :: .  */
-      if (b == global_binding_level || (pseudo && b->template_parms_p))
+      if (global_scope_p (b) || (pseudo && b->template_parms_p))
        break;
 
       old_bindings = store_bindings (b->names, old_bindings);
@@ -2343,13 +2236,13 @@ maybe_push_to_top_level (int pseudo)
   s->need_pop_function_context = need_pop;
   s->function_decl = current_function_decl;
   s->last_parms = last_function_parms;
-  s->check_access = flag_access_control;
 
   scope_chain = s;
   current_function_decl = NULL_TREE;
   VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
   current_lang_name = lang_name_cplusplus;
   current_namespace = global_namespace;
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 void
@@ -2362,8 +2255,9 @@ void
 pop_from_top_level (void)
 {
   struct saved_scope *s = scope_chain;
-  tree t;
+  cxx_saved_binding *saved;
 
+  timevar_push (TV_NAME_LOOKUP); 
   /* Clear out class-level bindings cache.  */
   if (previous_class_type)
     invalidate_class_lookup_cache ();
@@ -2371,13 +2265,13 @@ pop_from_top_level (void)
   current_lang_base = 0;
 
   scope_chain = s->prev;
-  for (t = s->old_bindings; t; t = TREE_CHAIN (t))
+  for (saved = s->old_bindings; saved; saved = saved->previous)
     {
-      tree id = TREE_VEC_ELT (t, 0);
+      tree id = saved->identifier;
 
-      SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
-      IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
-      IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
+      IDENTIFIER_BINDING (id) = saved->binding;
+      IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
+      SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
     }
 
   /* If we were in the middle of compiling a function, restore our
@@ -2386,6 +2280,7 @@ pop_from_top_level (void)
     pop_function_context_from (NULL_TREE);
   current_function_decl = s->function_decl;
   last_function_parms = s->last_parms;
+  timevar_pop (TV_NAME_LOOKUP);
 }
 \f
 /* Push a definition of struct, union or enum tag "name".
@@ -2416,7 +2311,8 @@ set_identifier_type_value_with_scope (tree id,
     }
   else
     {
-      tree binding = binding_for_name (id, current_namespace);
+      cxx_binding *binding =
+         binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
       BINDING_TYPE (binding) = type;
       /* Store marker instead of real type.  */
       type = global_type_node;
@@ -2437,18 +2333,19 @@ set_identifier_type_value (tree id, tree type)
 tree
 identifier_type_value (tree id)
 {
+  timevar_push (TV_NAME_LOOKUP);
   /* There is no type with that name, anywhere.  */
   if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
-    return NULL_TREE;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
   /* This is not the type marker, but the real thing.  */
   if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
-    return REAL_IDENTIFIER_TYPE_VALUE (id);
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
   /* Have to search for it. It must be on the global level, now.
      Ask lookup_name not to return non-types. */
   id = lookup_name_real (id, 2, 1, 0, LOOKUP_COMPLAIN);
   if (id)
-    return TREE_TYPE (id);
-  return NULL_TREE;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 }
 
 /* Pop off extraneous binding levels left over due to syntax errors.
@@ -2458,9 +2355,8 @@ identifier_type_value (tree id)
 void
 pop_everything (void)
 {
-#ifdef DEBUG_BINDING_LEVELS
-  fprintf (stderr, "XXX entering pop_everything ()\n");
-#endif
+  if (ENABLE_SCOPE_CHECKING)
+    verbatim ("XXX entering pop_everything ()\n");
   while (!toplevel_bindings_p ())
     {
       if (current_binding_level->parm_flag == 2)
@@ -2468,9 +2364,8 @@ pop_everything (void)
       else
        poplevel (0, 0, 0);
     }
-#ifdef DEBUG_BINDING_LEVELS
-  fprintf (stderr, "XXX leaving pop_everything ()\n");
-#endif
+  if (ENABLE_SCOPE_CHECKING)
+    verbatim ("XXX leaving pop_everything ()\n");
 }
 
 /* The type TYPE is being declared.  If it is a class template, or a
@@ -2524,16 +2419,19 @@ maybe_process_template_type_declaration (tree type,
              && b->level_chain->parm_flag == 2)
            {
              finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
-             /* Put this tag on the list of tags for the class, since
+             /* Put this UDT in the table of UDTs 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 =
-               tree_cons (name, type, b->level_chain->tags);
+              if (b->level_chain->type_decls == NULL)
+                b->level_chain->type_decls =
+                  binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+              binding_table_insert (b->level_chain->type_decls, name, type);
              if (!COMPLETE_TYPE_P (current_class_type))
                {
                  maybe_add_class_template_decl_list (current_class_type,
                                                      type, /*friend_p=*/0);
-                 CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
+                 CLASSTYPE_NESTED_UTDS (current_class_type) =
+                    b->level_chain->type_decls;
                }
            }
        }
@@ -2571,6 +2469,7 @@ push_local_name (tree decl)
   size_t i, nelts;
   tree t, name;
 
+  timevar_push (TV_NAME_LOOKUP);
   if (!local_names)
     VARRAY_TREE_INIT (local_names, 8, "local_names");
 
@@ -2591,11 +2490,13 @@ push_local_name (tree decl)
            DECL_DISCRIMINATOR (decl) = 1;
 
          VARRAY_TREE (local_names, i) = decl;
+         timevar_pop (TV_NAME_LOOKUP);
          return;
        }
     }
 
   VARRAY_PUSH_TREE (local_names, decl);
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Push a tag name NAME for struct/class/union/enum type TYPE.
@@ -2608,6 +2509,7 @@ pushtag (tree name, tree type, int globalize)
 {
   register struct cp_binding_level *b;
 
+  timevar_push (TV_NAME_LOOKUP);
   b = current_binding_level;
   while (b->tag_transparent
         || (b->parm_flag == 2
@@ -2619,7 +2521,9 @@ pushtag (tree name, tree type, int globalize)
                 || COMPLETE_TYPE_P (b->this_class))))
     b = b->level_chain;
 
-  b->tags = tree_cons (name, type, b->tags);
+  if (b->type_decls == NULL)
+    b->type_decls = binding_table_new (SCOPE_DEFAULT_HT_SIZE);
+  binding_table_insert (b->type_decls, name, type);
 
   if (name)
     {
@@ -2696,7 +2600,7 @@ pushtag (tree name, tree type, int globalize)
            {
              maybe_add_class_template_decl_list (current_class_type,
                                                  type, /*friend_p=*/0);
-             CLASSTYPE_TAGS (current_class_type) = b->tags;
+             CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
            }
        }
     }
@@ -2717,6 +2621,7 @@ pushtag (tree name, tree type, int globalize)
       tree d = build_decl (TYPE_DECL, NULL_TREE, type);
       TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
     }
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Counter used to create anonymous type names.  */
@@ -2735,14 +2640,13 @@ make_anon_name (void)
   return get_identifier (buf);
 }
 
-/* Clear the TREE_PURPOSE slot of tags which have anonymous typenames.
+/* Clear the TREE_PURPOSE slot of UTDs which have anonymous typenames.
    This keeps dbxout from getting confused.  */
 
 void
 clear_anon_tags (void)
 {
   register struct cp_binding_level *b;
-  register tree tags;
   static int last_cnt = 0;
 
   /* Fast out if no new anon names were declared.  */
@@ -2752,17 +2656,8 @@ clear_anon_tags (void)
   b = current_binding_level;
   while (b->tag_transparent)
     b = b->level_chain;
-  tags = b->tags;
-  while (tags)
-    {
-      /* A NULL purpose means we have already processed all tags
-        from here to the end of the list.  */
-      if (TREE_PURPOSE (tags) == NULL_TREE)
-       break;
-      if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
-       TREE_PURPOSE (tags) = NULL_TREE;
-      tags = TREE_CHAIN (tags);
-    }
+  if (b->type_decls != NULL)
+    binding_table_remove_anonymous_types (b->type_decls);
   last_cnt = anon_cnt;
 }
 \f
@@ -2959,19 +2854,19 @@ duplicate_decls (tree newdecl, tree olddecl)
               && DECL_UNINLINABLE (olddecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
        {
-         warning_with_decl (newdecl,
-                            "function `%s' redeclared as inline");
-         warning_with_decl (olddecl,
-                            "previous declaration of function `%s' with attribute noinline");
+         warning ("%Hfunction '%D' redeclared as inline",
+                   &DECL_SOURCE_LOCATION (newdecl), newdecl);
+         warning ("%Hprevious declaration of '%D' with attribute noinline",
+                   &DECL_SOURCE_LOCATION (olddecl), olddecl);
        }
       else if (DECL_DECLARED_INLINE_P (olddecl)
               && DECL_UNINLINABLE (newdecl)
               && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
        {
-         warning_with_decl (newdecl,
-                            "function `%s' redeclared with attribute noinline");
-         warning_with_decl (olddecl,
-                            "previous declaration of function `%s' was inline");
+         warning ("%Hfunction '%D' redeclared with attribute noinline",
+                   &DECL_SOURCE_LOCATION (newdecl), newdecl);
+         warning ("%Hprevious declaration of '%D' was inline",
+                   &DECL_SOURCE_LOCATION (olddecl), olddecl);
        }
     }
 
@@ -3040,6 +2935,10 @@ duplicate_decls (tree newdecl, tree olddecl)
          /* Replace the old RTL to avoid problems with inlining.  */
          SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
        }
+      /* Even if the types match, prefer the new declarations type
+        for anticipated built-ins, for exception lists, etc...  */
+      else if (DECL_ANTICIPATED (olddecl))
+       TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
 
       if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
        {
@@ -3329,7 +3228,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
        CLASSTYPE_FRIEND_CLASSES (newtype)
          = CLASSTYPE_FRIEND_CLASSES (oldtype);
-\
+
       DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
     }
 
@@ -3445,8 +3344,12 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
          DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
            |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
-         DECL_NO_LIMIT_STACK (newdecl)
-           |= DECL_NO_LIMIT_STACK (olddecl);
+         DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
+         TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+         TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
+         TREE_NOTHROW (newdecl) |= TREE_NOTHROW (olddecl);
+         DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
+         DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
          /* Keep the old RTL.  */
          COPY_DECL_RTL (olddecl, newdecl);
        }
@@ -3510,7 +3413,10 @@ duplicate_decls (tree newdecl, tree olddecl)
          DECL_BEFRIENDING_CLASSES (newdecl)
            = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
                       DECL_BEFRIENDING_CLASSES (olddecl));
-         DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
+         /* DECL_THUNKS is only valid for virtual functions,
+            otherwise it is a DECL_FRIEND_CONTEXT.  */
+         if (DECL_VIRTUAL_P (newdecl))
+           DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl);
        }
     }
 
@@ -3521,7 +3427,7 @@ duplicate_decls (tree newdecl, tree olddecl)
        {
          /* If newdecl is not a specialization, then it is not a
             template-related function at all.  And that means that we
-            shoud have exited above, returning 0.  */
+            should have exited above, returning 0.  */
          my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
                              0);
 
@@ -3668,6 +3574,15 @@ duplicate_decls (tree newdecl, tree olddecl)
      Update OLDDECL to be the same.  */
   DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
+  /* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
+    so that encode_section_info has a chance to look at the new decl
+    flags and attributes.  */
+  if (DECL_RTL_SET_P (olddecl) 
+      && (TREE_CODE (olddecl) == FUNCTION_DECL
+         || (TREE_CODE (olddecl) == VAR_DECL
+             && TREE_STATIC (olddecl))))
+    make_decl_rtl (olddecl, NULL);
+
   return 1;
 }
 
@@ -3686,6 +3601,7 @@ pushdecl (tree x)
   register tree name;
   int need_new_binding;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* We shouldn't be calling pushdecl when we're generating RTL for a
      function that we already did semantic analysis on previously.  */
   my_friendly_assert (!cfun || doing_semantic_analysis_p (),
@@ -3809,7 +3725,7 @@ pushdecl (tree x)
 
              /* Check for duplicate params.  */
              if (duplicate_decls (x, t))
-               return t;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
            }
          else if ((DECL_EXTERN_C_FUNCTION_P (x)
                    || DECL_FUNCTION_TEMPLATE_P (x))
@@ -3822,12 +3738,12 @@ pushdecl (tree x)
                            TREE_TYPE (x));
 
              /* Throw away the redeclaration.  */
-             return t;
+             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
            }
          else if (TREE_CODE (t) != TREE_CODE (x))
            {
              if (duplicate_decls (x, t))
-               return t;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
            }
          else if (duplicate_decls (x, t))
            {
@@ -3836,7 +3752,7 @@ pushdecl (tree x)
              else if (TREE_CODE (t) == FUNCTION_DECL)
                check_default_args (t);
 
-             return t;
+             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
            }
          else if (DECL_MAIN_P (x))
            {
@@ -3850,7 +3766,7 @@ pushdecl (tree x)
              error ("as `%D'", x);
              /* We don't try to push this declaration since that
                 causes a crash.  */
-             return x;
+             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
            }
        }
 
@@ -3868,7 +3784,7 @@ pushdecl (tree x)
        {
          t = push_overloaded_decl (x, PUSH_LOCAL);
          if (t != x)
-           return t;
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
          if (!namespace_bindings_p ())
            /* We do not need to create a binding for this name;
               push_overloaded_decl will have already done so if
@@ -3880,7 +3796,7 @@ pushdecl (tree x)
          t = push_overloaded_decl (x, PUSH_GLOBAL);
          if (t == x)
            add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
-         return t;
+         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
        }
 
       /* If declaring a type as a typedef, copy the type (unless we're
@@ -4056,7 +3972,9 @@ pushdecl (tree x)
          if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
              /* Inline decls shadow nothing.  */
              && !DECL_FROM_INLINE (x)
-             && TREE_CODE (oldlocal) == PARM_DECL)
+             && TREE_CODE (oldlocal) == PARM_DECL
+             /* Don't check the `this' parameter.  */
+             && !DECL_ARTIFICIAL (oldlocal))
            {
              bool err = false;
 
@@ -4081,7 +3999,8 @@ pushdecl (tree x)
                }
 
              if (warn_shadow && !err)
-               shadow_warning ("a parameter", name, oldlocal);
+               shadow_warning (SW_PARAM,
+                               IDENTIFIER_POINTER (name), oldlocal);
            }
 
          /* Maybe warn if shadowing something else.  */
@@ -4098,11 +4017,13 @@ pushdecl (tree x)
                            IDENTIFIER_POINTER (name));
              else if (oldlocal != NULL_TREE
                       && TREE_CODE (oldlocal) == VAR_DECL)
-               shadow_warning ("a previous local", name, oldlocal);
+               shadow_warning (SW_LOCAL,
+                               IDENTIFIER_POINTER (name), oldlocal);
              else if (oldglobal != NULL_TREE
                       && TREE_CODE (oldglobal) == VAR_DECL)
                /* XXX shadow warnings in outer-more namespaces */
-               shadow_warning ("a global declaration", name, oldglobal);
+               shadow_warning (SW_GLOBAL,
+                               IDENTIFIER_POINTER (name), oldglobal);
            }
        }
 
@@ -4119,7 +4040,7 @@ pushdecl (tree x)
                       ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
                       : current_binding_level);
 
-  return x;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
 }
 
 /* Same as pushdecl, but define X in binding-level LEVEL.  We rely on the
@@ -4131,6 +4052,7 @@ pushdecl_with_scope (tree x, struct cp_binding_level* level)
   register struct cp_binding_level *b;
   tree function_decl = current_function_decl;
 
+  timevar_push (TV_NAME_LOOKUP);
   current_function_decl = NULL_TREE;
   if (level->parm_flag == 2)
     {
@@ -4147,7 +4069,7 @@ pushdecl_with_scope (tree x, struct cp_binding_level* level)
       current_binding_level = b;
     }
   current_function_decl = function_decl;
-  return x;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
 }
 
 /* Like pushdecl, only it places X in the current namespace,
@@ -4159,6 +4081,7 @@ pushdecl_namespace_level (tree x)
   register struct cp_binding_level *b = current_binding_level;
   register tree t;
 
+  timevar_push (TV_NAME_LOOKUP);
   t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
 
   /* Now, the type_shadowed stack may screw us.  Munge it so it does
@@ -4168,7 +4091,7 @@ pushdecl_namespace_level (tree x)
       tree name = DECL_NAME (x);
       tree newval;
       tree *ptr = (tree *)0;
-      for (; b != global_binding_level; b = b->level_chain)
+      for (; !global_scope_p (b); b = b->level_chain)
         {
           tree shadowed = b->type_shadowed;
           for (; shadowed; shadowed = TREE_CHAIN (shadowed))
@@ -4192,19 +4115,19 @@ pushdecl_namespace_level (tree x)
          *ptr = newval;
         }
     }
-  return t;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
-/* Like pushdecl, only it places X in GLOBAL_BINDING_LEVEL,
-   if appropriate.  */
+/* Like pushdecl, only it places X in the global scope if appropriate.  */
 
 tree
 pushdecl_top_level (tree x)
 {
+  timevar_push (TV_NAME_LOOKUP);
   push_to_top_level ();
   x = pushdecl_namespace_level (x);
   pop_from_top_level ();
-  return x;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
 }
 
 /* Make the declaration of X appear in CLASS scope.  */
@@ -4214,6 +4137,7 @@ pushdecl_class_level (tree x)
 {
   tree name;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* Get the name of X.  */
   if (TREE_CODE (x) == OVERLOAD)
     name = DECL_NAME (get_first_fn (x));
@@ -4236,6 +4160,7 @@ pushdecl_class_level (tree x)
       for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
        pushdecl_class_level (f);
     }
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Enter DECL into the symbol table, if that's appropriate.  Returns
@@ -4273,11 +4198,15 @@ maybe_push_decl (tree decl)
 void
 push_class_level_binding (tree name, tree x)
 {
-  tree binding;
+  cxx_binding *binding;
+  timevar_push (TV_NAME_LOOKUP);
   /* The class_binding_level will be NULL if x is a template
      parameter name in a member template.  */
   if (!class_binding_level)
-    return;
+    {
+      timevar_pop (TV_NAME_LOOKUP);
+      return;
+    }
 
   /* Make sure that this new member does not have the same name
      as a template parameter.  */
@@ -4327,6 +4256,7 @@ push_class_level_binding (tree name, tree x)
            INHERITED_VALUE_BINDING_P (binding) = 0;
            TREE_TYPE (shadow) = x;
            IDENTIFIER_CLASS_VALUE (name) = x;
+           timevar_pop (TV_NAME_LOOKUP);
            return;
          }
     }
@@ -4342,6 +4272,7 @@ push_class_level_binding (tree name, tree x)
         what to pop later.  */
       TREE_TYPE (class_binding_level->class_shadowed) = x;
     }
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Insert another USING_DECL into the current binding level, returning
@@ -4354,18 +4285,20 @@ push_using_decl (tree scope, tree name)
 {
   tree decl;
 
+  timevar_push (TV_NAME_LOOKUP);
   my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
   for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
     if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
       break;
   if (decl)
-    return namespace_bindings_p () ? decl : NULL_TREE;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+                            namespace_bindings_p () ? decl : NULL_TREE);
   decl = build_lang_decl (USING_DECL, name, void_type_node);
   DECL_INITIAL (decl) = scope;
   TREE_CHAIN (decl) = current_binding_level->usings;
   current_binding_level->usings = decl;
-  return decl;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
 }
 
 /* Add namespace to using_directives. Return NULL_TREE if nothing was
@@ -4378,19 +4311,21 @@ push_using_directive (tree used)
   tree ud = current_binding_level->using_directives;
   tree iter, ancestor;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* Check if we already have this.  */
   if (purpose_member (used, ud) != NULL_TREE)
-    return NULL_TREE;
-
-  /* Recursively add all namespaces used.  */
-  for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
-    push_using_directive (TREE_PURPOSE (iter));
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 
   ancestor = namespace_ancestor (current_decl_namespace (), used);
   ud = current_binding_level->using_directives;
   ud = tree_cons (used, ancestor, ud);
   current_binding_level->using_directives = ud;
-  return ud;
+
+  /* Recursively add all namespaces used.  */
+  for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
+    push_using_directive (TREE_PURPOSE (iter));
+
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
 }
 
 /* DECL is a FUNCTION_DECL for a non-member function, which may have
@@ -4420,6 +4355,7 @@ push_overloaded_decl (tree decl, int flags)
   tree new_binding;
   int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
 
+  timevar_push (TV_NAME_LOOKUP);
   if (doing_global)
     old = namespace_binding (name, DECL_CONTEXT (decl));
   else
@@ -4452,7 +4388,7 @@ push_overloaded_decl (tree decl, int flags)
                          decl, fn);
 
              if (duplicate_decls (decl, fn))
-               return fn;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
            }
        }
       else if (old == error_mark_node)
@@ -4462,7 +4398,7 @@ push_overloaded_decl (tree decl, int flags)
        {
          cp_error_at ("previous non-function declaration `%#D'", old);
          error ("conflicts with function declaration `%#D'", decl);
-         return decl;
+         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
        }
     }
 
@@ -4493,7 +4429,7 @@ push_overloaded_decl (tree decl, int flags)
        {
          tree *d;
 
-         for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+         for (d = &BINDING_SCOPE (IDENTIFIER_BINDING (name))->names;
               *d;
               d = &TREE_CHAIN (*d))
            if (*d == old
@@ -4508,10 +4444,10 @@ push_overloaded_decl (tree decl, int flags)
                  *d = tree_cons (NULL_TREE, new_binding,
                                  TREE_CHAIN (*d));
 
-               /* And update the CPLUS_BINDING node.  */
+               /* And update the cxx_binding node.  */
                BINDING_VALUE (IDENTIFIER_BINDING (name))
                  = new_binding;
-               return decl;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
              }
 
          /* We should always find a previous binding in this case.  */
@@ -4522,7 +4458,7 @@ push_overloaded_decl (tree decl, int flags)
       push_local_binding (name, new_binding, flags);
     }
 
-  return decl;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
 }
 \f
 /* Generate an implicit declaration for identifier FUNCTIONID
@@ -4656,8 +4592,7 @@ make_label_decl (tree id, int local_p)
 
   /* Say where one reference is to the label, for the sake of the
      error if it is not defined.  */
-  DECL_SOURCE_LINE (decl) = lineno;
-  DECL_SOURCE_FILE (decl) = input_filename;
+  DECL_SOURCE_LOCATION (decl) = input_location;
 
   /* Record the fact that this identifier is bound to this label.  */
   SET_IDENTIFIER_LABEL_VALUE (id, decl);
@@ -4683,8 +4618,7 @@ use_label (tree decl)
       new_ent->label_decl = decl;
       new_ent->names_in_scope = current_binding_level->names;
       new_ent->binding_level = current_binding_level;
-      new_ent->lineno_o_goto = lineno;
-      new_ent->filename_o_goto = input_filename;
+      new_ent->o_goto_locus = input_location;
       new_ent->next = named_label_uses;
       named_label_uses = new_ent;
     }
@@ -4700,18 +4634,19 @@ lookup_label (tree id)
   tree decl;
   struct named_label_list *ent;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* You can't use labels at global scope.  */
   if (current_function_decl == NULL_TREE)
     {
       error ("label `%s' referenced outside of any function",
             IDENTIFIER_POINTER (id));
-      return NULL_TREE;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
   /* See if we've already got this label.  */
   decl = IDENTIFIER_LABEL_VALUE (id);
   if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
-    return decl;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
 
   /* Record this label on the list of labels used in this function.
      We do this before calling make_label_decl so that we get the
@@ -4728,7 +4663,7 @@ lookup_label (tree id)
   /* Now fill in the information we didn't have before.  */
   ent->label_decl = decl;
 
-  return decl;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
 }
 
 /* Declare a local label named ID.  */
@@ -4782,9 +4717,7 @@ decl_jump_unsafe (tree decl)
 static void
 check_previous_goto_1 (tree decl,
                        struct cp_binding_level* level,
-                       tree names,
-                       const char* file,
-                       int line)
+                       tree names, const location_t *locus)
 {
   int identified = 0;
   int saw_eh = 0;
@@ -4807,8 +4740,8 @@ check_previous_goto_1 (tree decl,
              else
                pedwarn ("jump to case label");
 
-             if (file)
-               pedwarn_with_file_and_line (file, line, "  from here");
+             if (locus)
+               pedwarn ("%H  from here", locus);
              identified = 1;
            }
 
@@ -4831,8 +4764,8 @@ check_previous_goto_1 (tree decl,
              else
                pedwarn ("jump to case label");
 
-             if (file)
-               pedwarn_with_file_and_line (file, line, "  from here");
+             if (locus)
+               pedwarn ("%H  from here", locus);
              identified = 1;
            }
          if (b->is_try_scope)
@@ -4848,14 +4781,13 @@ static void
 check_previous_goto (struct named_label_use_list* use)
 {
   check_previous_goto_1 (use->label_decl, use->binding_level,
-                        use->names_in_scope, use->filename_o_goto,
-                        use->lineno_o_goto);
+                        use->names_in_scope, &use->o_goto_locus);
 }
 
 static void
 check_switch_goto (struct cp_binding_level* level)
 {
-  check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
+  check_previous_goto_1 (NULL_TREE, level, level->names, NULL);
 }
 
 /* Check that any previously seen jumps to a newly defined label DECL
@@ -4952,6 +4884,7 @@ define_label (const char* filename, int line, tree name)
   struct named_label_list *ent;
   register struct cp_binding_level *p;
 
+  timevar_push (TV_NAME_LOOKUP);
   for (ent = named_labels; ent; ent = ent->next)
     if (ent->label_decl == decl)
       break;
@@ -4967,7 +4900,7 @@ define_label (const char* filename, int line, tree name)
   if (DECL_INITIAL (decl) != NULL_TREE)
     {
       error ("duplicate label `%D'", decl);
-      return 0;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
   else
     {
@@ -4982,8 +4915,9 @@ define_label (const char* filename, int line, tree name)
          ent->binding_level = current_binding_level;
        }
       check_previous_gotos (decl);
-      return decl;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
     }
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 struct cp_switch
@@ -5093,14 +5027,6 @@ getdecls (void)
   return current_binding_level->names;
 }
 
-/* Return the list of type-tags (for structs, etc) of the current level.  */
-
-tree
-gettags (void)
-{
-  return current_binding_level->tags;
-}
-
 /* Store the list of declarations of the current level.
    This is done for the parameter declarations of a function being defined,
    after they are modified in the light of any missing parameters.  */
@@ -5111,12 +5037,13 @@ storedecls (tree decls)
   current_binding_level->names = decls;
 }
 
-/* Similarly, store the list of tags of the current level.  */
-
+/* Set the current binding TABLE for type declarations..  This is a
+   temporary workaround of the fact that the data structure classtypes
+   does not currently carry its allocated cxx_scope structure.  */
 void
-storetags (tree tags)
+cxx_remember_type_decls (binding_table table)
 {
-  current_binding_level->tags = tags;
+  current_binding_level->type_decls = table;
 }
 \f
 /* Return the type that should be used when TYPE's name is preceded
@@ -5161,7 +5088,7 @@ follow_tag_typedef (tree type)
 
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
-   Searches binding levels from BINDING_LEVEL up to the global level.
+   Searches binding levels from BINDING_SCOPE up to the global level.
    If THISLEVEL_ONLY is nonzero, searches only the specified context
    (but skips any tag-transparent contexts to find one that is
    meaningful for tags).
@@ -5171,43 +5098,47 @@ follow_tag_typedef (tree type)
    reported.  */
 
 static tree
-lookup_tag (enum tree_code form,
-            tree name,
-            struct cp_binding_level* binding_level,
-            int thislevel_only)
+lookup_tag (enum tree_code form, tree name,
+            struct cp_binding_level* binding_level, int thislevel_only)
 {
   register struct cp_binding_level *level;
   /* Nonzero if, we should look past a template parameter level, even
      if THISLEVEL_ONLY.  */
   int allow_template_parms_p = 1;
+  bool type_is_anonymous = ANON_AGGRNAME_P (name);
 
+  timevar_push (TV_NAME_LOOKUP);
   for (level = binding_level; level; level = level->level_chain)
     {
       register tree tail;
-      if (ANON_AGGRNAME_P (name))
-       for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
-         {
-           /* There's no need for error checking here, because
-              anon names are unique throughout the compilation.  */
-           if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
-             return TREE_VALUE (tail);
-         }
+      if (type_is_anonymous && level->type_decls != NULL)
+        {
+          tree type = binding_table_find_anon_type (level->type_decls, name);
+          /* There is no need for error checking here, because
+           anon names are unique throughout the compilation.  */
+          if (type != NULL)
+            POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, type);
+        }
       else if (level->namespace_p)
        /* Do namespace lookup.  */
        for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
          {
-           tree old = binding_for_name (name, tail);
+            cxx_binding *binding =
+              cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
+           tree old;
 
            /* If we just skipped past a template parameter level,
               even though THISLEVEL_ONLY, and we find a template
               class declaration, then we use the _TYPE node for the
               template.  See the example below.  */
            if (thislevel_only && !allow_template_parms_p
-               && old && BINDING_VALUE (old)
-               && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
-             old = TREE_TYPE (BINDING_VALUE (old));
-           else
-             old = BINDING_TYPE (old);
+               && binding && BINDING_VALUE (binding)
+               && DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
+             old = TREE_TYPE (BINDING_VALUE (binding));
+           else if (binding)
+             old = BINDING_TYPE (binding);
+            else
+              old = NULL_TREE;
 
            if (old)
              {
@@ -5216,35 +5147,35 @@ lookup_tag (enum tree_code form,
                   if the typedef doesn't refer to a taggable type.  */
                old = follow_tag_typedef (old);
                if (!old)
-                 return NULL_TREE;
+                 POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
                if (TREE_CODE (old) != form
                    && (form == ENUMERAL_TYPE
                        || TREE_CODE (old) == ENUMERAL_TYPE))
                  {
                    error ("`%#D' redeclared as %C", old, form);
-                   return NULL_TREE;
+                   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
                  }
-               return old;
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
              }
            if (thislevel_only || tail == global_namespace)
-             return NULL_TREE;
+             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
          }
-      else
-       for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
-         {
-           if (TREE_PURPOSE (tail) == name)
-             {
-               enum tree_code code = TREE_CODE (TREE_VALUE (tail));
+      else if (level->type_decls != NULL)
+        {
+          binding_entry entry = binding_table_find (level->type_decls, name);
+          if (entry != NULL)
+            {
+              enum tree_code code = TREE_CODE (entry->type);
                
-               if (code != form
-                   && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
-                 {
-                   /* Definition isn't the kind we were looking for.  */
-                   error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
-                   return NULL_TREE;
-                 }
-               return TREE_VALUE (tail);
-             }
+              if (code != form
+                  && (form == ENUMERAL_TYPE || code == ENUMERAL_TYPE))
+                {
+                  /* Definition isn't the kind we were looking for.  */
+                  error ("`%#D' redeclared as %C", entry->type, form);
+                  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+                }
+              POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->type);
+            }
          }
       if (thislevel_only && ! level->tag_transparent)
        {
@@ -5265,10 +5196,10 @@ lookup_tag (enum tree_code form,
              continue;
            }
          else
-           return NULL_TREE;
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
        }
     }
-  return NULL_TREE;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 }
 
 /* Given a type, find the tag that was defined for it and return the tag name.
@@ -5283,20 +5214,16 @@ lookup_tag_reverse (tree type, tree name)
 {
   register struct cp_binding_level *level;
 
+  timevar_push (TV_NAME_LOOKUP);
   for (level = current_binding_level; level; level = level->level_chain)
     {
-      register tree tail;
-      for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
-       {
-         if (TREE_VALUE (tail) == type)
-           {
-             if (name)
-               TREE_PURPOSE (tail) = name;
-             return TREE_PURPOSE (tail);
-           }
-       }
+      binding_entry entry = level->type_decls == NULL
+        ? NULL
+        : binding_table_reverse_maybe_remap (level->type_decls, type, name);
+      if (entry)
+        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, entry->name);
     }
-  return NULL_TREE;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 }
 \f
 /* Look up NAME in the NAMESPACE.  */
@@ -5306,18 +5233,20 @@ lookup_namespace_name (tree namespace, tree name)
 {
   tree val;
   tree template_id = NULL_TREE;
+  cxx_binding binding;
 
+  timevar_push (TV_NAME_LOOKUP);
   my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
 
   if (TREE_CODE (name) == NAMESPACE_DECL)
     /* This happens for A::B<int> when B is a namespace.  */
-    return name;
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
   else if (TREE_CODE (name) == TEMPLATE_DECL)
     {
       /* This happens for A::B where B is a template, and there are no
         template arguments.  */
       error ("invalid use of `%D'", name);
-      return error_mark_node;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
     }
 
   namespace = ORIGINAL_NAMESPACE (namespace);
@@ -5334,13 +5263,13 @@ lookup_namespace_name (tree namespace, tree name)
 
   my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
 
-  val = make_node (CPLUS_BINDING);
-  if (!qualified_lookup_using_namespace (name, namespace, val, 0))
-    return error_mark_node;
+  cxx_binding_clear (&binding);
+  if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
+    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
-  if (BINDING_VALUE (val))
+  if (binding.value)
     {
-      val = BINDING_VALUE (val);
+      val = binding.value;
 
       if (template_id)
        {
@@ -5359,7 +5288,7 @@ lookup_namespace_name (tree namespace, tree name)
            {
              error ("`%D::%D' is not a template",
                        namespace, name);
-             return error_mark_node;
+             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
            }
        }
 
@@ -5371,11 +5300,11 @@ lookup_namespace_name (tree namespace, tree name)
       if (!val || !DECL_P(val)
           || !DECL_LANG_SPECIFIC(val)
           || !DECL_ANTICIPATED (val))
-        return val;
+        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
     }
 
   error ("`%D' undeclared in namespace `%D'", name, namespace);
-  return error_mark_node;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 }
 
 /* Hash a TYPENAME_TYPE.  K is really of type `tree'.  */
@@ -5472,6 +5401,11 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
 {
   tree fullname;
 
+  if (name == error_mark_node
+      || context == NULL_TREE
+      || context == error_mark_node)
+    return error_mark_node;
+
   if (TYPE_P (name))
     {
       if (!(TYPE_LANG_SPECIFIC (name)
@@ -5520,7 +5454,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
        {
          tree tmpl = NULL_TREE;
          if (IS_AGGR_TYPE (context))
-           tmpl = lookup_field (context, name, 0, 0);
+           tmpl = lookup_field (context, name, 0, false);
          if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
            {
              if (complain & tf_error)
@@ -5530,12 +5464,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
            }
 
          if (complain & tf_error)
-           {
-             if (complain & tf_parsing)
-               perform_or_defer_access_check (context, tmpl);
-             else
-               enforce_access (context, tmpl);
-           }
+           perform_or_defer_access_check (context, tmpl);
 
          return lookup_template_class (tmpl,
                                        TREE_OPERAND (fullname, 1),
@@ -5554,7 +5483,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
              return error_mark_node;
            }
 
-         t = lookup_field (context, name, 0, 1);
+         t = lookup_field (context, name, 0, true);
          if (t)
            {
              if (TREE_CODE (t) != TYPE_DECL)
@@ -5565,12 +5494,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
                }
 
              if (complain & tf_error)
-               {
-                 if (complain & tf_parsing)
-                   perform_or_defer_access_check (context, t);
-                 else
-                   enforce_access (context, t);
-               }
+               perform_or_defer_access_check (context, t);
 
              if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
                t = TREE_TYPE (t);
@@ -5617,7 +5541,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
       tree tmpl = NULL_TREE;
 
       if (IS_AGGR_TYPE (context))
-       tmpl = lookup_field (context, name, 0, 0);
+       tmpl = lookup_field (context, name, 0, false);
 
       if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
        {
@@ -5627,12 +5551,7 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
        }
       
       if (complain & tf_error)
-       {
-         if (complain & tf_parsing)
-           perform_or_defer_access_check (context, tmpl);
-         else
-           enforce_access (context, tmpl);
-       }
+       perform_or_defer_access_check (context, tmpl);
 
       return tmpl;
     }
@@ -5655,17 +5574,18 @@ make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
 /* Select the right _DECL from multiple choices.  */
 
 static tree
-select_decl (tree binding, int flags)
+select_decl (cxx_binding *binding, int flags)
 {
   tree val;
   val = BINDING_VALUE (binding);
 
+  timevar_push (TV_NAME_LOOKUP);
   if (LOOKUP_NAMESPACES_ONLY (flags))
     {
       /* We are not interested in types.  */
       if (val && TREE_CODE (val) == NAMESPACE_DECL)
-        return val;
-      return NULL_TREE;
+        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
   /* If we could have a type and
@@ -5680,7 +5600,7 @@ select_decl (tree binding, int flags)
               || !DECL_CLASS_TEMPLATE_P (val)))
     val = NULL_TREE;
 
-  return val;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
 }
 
 /* Unscoped lookup of a global: iterate over current namespaces,
@@ -5690,65 +5610,66 @@ select_decl (tree binding, int flags)
 tree
 unqualified_namespace_lookup (tree name, int flags, tree* spacesp)
 {
-  tree b = make_node (CPLUS_BINDING);
   tree initial = current_decl_namespace ();
   tree scope = initial;
   tree siter;
   struct cp_binding_level *level;
   tree val = NULL_TREE;
+  cxx_binding binding;
 
+  timevar_push (TV_NAME_LOOKUP);
+  cxx_binding_clear (&binding);
   if (spacesp)
     *spacesp = NULL_TREE;
 
   for (; !val; scope = CP_DECL_CONTEXT (scope))
     {
+      cxx_binding *b =
+         cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
       if (spacesp)
        *spacesp = tree_cons (scope, NULL_TREE, *spacesp);
-      val = binding_for_name (name, scope);
 
       /* Ignore anticipated built-in functions.  */
-      if (val && BINDING_VALUE (val)
-          && DECL_P (BINDING_VALUE (val))
-          && DECL_LANG_SPECIFIC (BINDING_VALUE (val))
-          && DECL_ANTICIPATED (BINDING_VALUE (val)))
-        {
-          BINDING_VALUE (b) = NULL_TREE;
-          BINDING_TYPE (b) = NULL_TREE;
-        }
-      else
+      if (b && BINDING_VALUE (b)
+          && DECL_P (BINDING_VALUE (b))
+          && DECL_LANG_SPECIFIC (BINDING_VALUE (b))
+          && DECL_ANTICIPATED (BINDING_VALUE (b)))
+        /* Keep binding cleared.  */;
+      else if (b)
         {
           /* Initialize binding for this context.  */
-          BINDING_VALUE (b) = BINDING_VALUE (val);
-          BINDING_TYPE (b) = BINDING_TYPE (val);
+          binding.value = BINDING_VALUE (b);
+          binding.type = BINDING_TYPE (b);
         }
 
       /* Add all _DECLs seen through local using-directives.  */
       for (level = current_binding_level;
           !level->namespace_p;
           level = level->level_chain)
-       if (!lookup_using_namespace (name, b, level->using_directives,
+       if (!lookup_using_namespace (name, &binding, level->using_directives,
                                      scope, flags, spacesp))
          /* Give up because of error.  */
-         return error_mark_node;
+         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
       /* Add all _DECLs seen through global using-directives.  */
       /* XXX local and global using lists should work equally.  */
       siter = initial;
       while (1)
        {
-         if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
+         if (!lookup_using_namespace (name, &binding,
+                                       DECL_NAMESPACE_USING (siter),
                                       scope, flags, spacesp))
            /* Give up because of error.  */
-           return error_mark_node;
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
          if (siter == scope) break;
          siter = CP_DECL_CONTEXT (siter);
        }
 
-      val = select_decl (b, flags);
+      val = select_decl (&binding, flags);
       if (scope == global_namespace)
        break;
     }
-  return val;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
 }
 
 /* Combine prefer_type and namespaces_only into flags.  */
@@ -5794,15 +5715,15 @@ lookup_qualified_name (tree scope, tree name, bool is_type_p, int flags)
 {
   if (TREE_CODE (scope) == NAMESPACE_DECL)
     {
-      tree val;
+      cxx_binding binding;
 
-      val = make_node (CPLUS_BINDING);
+      cxx_binding_clear (&binding);
       flags |= LOOKUP_COMPLAIN;
       if (is_type_p)
        flags |= LOOKUP_PREFER_TYPES;
-      if (!qualified_lookup_using_namespace (name, scope, val, flags))
+      if (!qualified_lookup_using_namespace (name, scope, &binding, flags))
        return NULL_TREE;
-      return select_decl (val, flags);
+      return select_decl (&binding, flags);
     }
   else
     return lookup_member (scope, name, 0, is_type_p);
@@ -5881,15 +5802,13 @@ check_for_out_of_scope_variable (tree decl)
    using IDENTIFIER_CLASS_VALUE.  */
 
 tree
-lookup_name_real (tree name, 
-                 int prefer_type, 
-                 int nonclass, 
-                 int namespaces_only,
-                 int flags)
+lookup_name_real (tree name, int prefer_type, int nonclass, 
+                 int namespaces_only, int flags)
 {
-  tree t;
+  cxx_binding *iter;
   tree val = NULL_TREE;
 
+  timevar_push (TV_NAME_LOOKUP);
   /* Conversion operators are handled specially because ordinary
      unqualified name lookup will not find template conversion
      operators.  */
@@ -5913,10 +5832,10 @@ lookup_name_real (tree name,
          class_type = level->this_class;
          operators = lookup_fnfields (class_type, name, /*protect=*/0);
          if (operators)
-           return operators;
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
        }
 
-      return NULL_TREE;
+      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
   flags |= lookup_flags (prefer_type, namespaces_only);
@@ -5926,20 +5845,20 @@ lookup_name_real (tree name,
   if (current_class_type == NULL_TREE)
     nonclass = 1;
 
-  for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
+  for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
     {
       tree binding;
 
-      if (!LOCAL_BINDING_P (t) && nonclass)
+      if (!LOCAL_BINDING_P (iter) && 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 (t), flags))
-       binding = BINDING_VALUE (t);
+      if (qualify_lookup (BINDING_VALUE (iter), flags))
+       binding = BINDING_VALUE (iter);
       else if ((flags & LOOKUP_PREFER_TYPES)
-              && qualify_lookup (BINDING_TYPE (t), flags))
-       binding = BINDING_TYPE (t);
+              && qualify_lookup (BINDING_TYPE (iter), flags))
+       binding = BINDING_TYPE (iter);
       else
        binding = NULL_TREE;
 
@@ -5953,7 +5872,7 @@ lookup_name_real (tree name,
   /* Now lookup in namespace scopes.  */
   if (!val)
     {
-      t = unqualified_namespace_lookup (name, flags, 0);
+      tree t = unqualified_namespace_lookup (name, flags, 0);
       if (t)
        val = t;
     }
@@ -5965,7 +5884,7 @@ lookup_name_real (tree name,
        val = OVL_FUNCTION (val);
     }
 
-  return val;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
 }
 
 tree
@@ -5995,6 +5914,7 @@ lookup_name_current_level (tree name)
   struct cp_binding_level *b;
   tree t = NULL_TREE;
 
+  timevar_push (TV_NAME_LOOKUP);
   b = current_binding_level;
   while (b->parm_flag == 2)
     b = b->level_chain;
@@ -6012,8 +5932,8 @@ lookup_name_current_level (tree name)
     {
       while (1)
        {
-         if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
-           return IDENTIFIER_VALUE (name);
+         if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
 
          if (b->keep == 2)
            b = b->level_chain;
@@ -6022,7 +5942,7 @@ lookup_name_current_level (tree name)
        }
     }
 
-  return t;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
 /* Like lookup_name_current_level, but for types.  */
@@ -6032,6 +5952,7 @@ lookup_type_current_level (tree name)
 {
   register tree t = NULL_TREE;
 
+  timevar_push (TV_NAME_LOOKUP);
   my_friendly_assert (! current_binding_level->namespace_p, 980716);
 
   if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
@@ -6041,7 +5962,8 @@ lookup_type_current_level (tree name)
       while (1)
        {
          if (purpose_member (name, b->type_shadowed))
-           return REAL_IDENTIFIER_TYPE_VALUE (name);
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
+                                    REAL_IDENTIFIER_TYPE_VALUE (name));
          if (b->keep == 2)
            b = b->level_chain;
          else
@@ -6049,7 +5971,7 @@ lookup_type_current_level (tree name)
        }
     }
 
-  return t;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
 \f
@@ -6071,8 +5993,6 @@ record_builtin_type (enum rid rid_index,
   if (name)
     tname = get_identifier (name);
 
-  TYPE_BUILT_IN (type) = 1;
-
   if (tname)
     {
       tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
@@ -6256,11 +6176,15 @@ cxx_init_decl_processing (void)
 
   /* Make the binding_level structure for global names.  */
   pushlevel (0);
-  global_binding_level = current_binding_level;
+  current_binding_level->type_decls = binding_table_new (GLOBAL_SCOPE_HT_SIZE);
   /* The global level is the namespace level of ::.  */
-  NAMESPACE_LEVEL (global_namespace) = global_binding_level;
+  NAMESPACE_LEVEL (global_namespace) = current_binding_level;
   declare_namespace_level ();
 
+  VARRAY_TREE_INIT (current_binding_level->static_decls,
+                   200,
+                   "Static declarations");
+
   /* Create the `std' namespace.  */
   push_namespace (std_identifier);
   std_node = current_namespace;
@@ -7039,15 +6963,15 @@ start_decl (tree declarator,
   cplus_decl_attributes (&decl, attributes, 0);
 
   /* If #pragma weak was used, mark the decl weak now.  */
-  if (current_binding_level == global_binding_level)
+  if (global_scope_p (current_binding_level))
     maybe_apply_pragma_weak (decl);
 
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_DECLARED_INLINE_P (decl)
       && DECL_UNINLINABLE (decl)
       && lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
-    warning_with_decl (decl,
-                      "inline function `%s' given attribute noinline");
+    warning ("%Hinline function '%D' given attribute noinline",
+             &DECL_SOURCE_LOCATION (decl), decl);
 
   if (context && COMPLETE_TYPE_P (complete_type (context)))
     {
@@ -7055,7 +6979,7 @@ start_decl (tree declarator,
 
       if (TREE_CODE (decl) == VAR_DECL)
        {
-         tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
+         tree field = lookup_field (context, DECL_NAME (decl), 0, false);
          if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
            error ("`%#D' is not a static member of `%#T'", decl, context);
          else
@@ -7244,10 +7168,7 @@ grok_reference_init (tree decl, tree type, tree init)
      DECL_INITIAL for local references (instead assigning to them
      explicitly); we need to allow the temporary to be initialized
      first.  */
-  tmp = convert_to_reference
-    (type, init, CONV_IMPLICIT,
-     LOOKUP_ONLYCONVERTING|LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND,
-     decl);
+  tmp = initialize_reference (type, init, decl);
 
   if (tmp == error_mark_node)
     return NULL_TREE;
@@ -7383,40 +7304,43 @@ maybe_commonize_var (tree decl)
   if (TREE_STATIC (decl)
       /* Don't mess with __FUNCTION__.  */
       && ! DECL_ARTIFICIAL (decl)
-      && current_function_decl
-      && DECL_CONTEXT (decl) == current_function_decl
-      && (DECL_DECLARED_INLINE_P (current_function_decl)
-         || DECL_TEMPLATE_INSTANTIATION (current_function_decl))
-      && TREE_PUBLIC (current_function_decl))
-    {
-      /* If flag_weak, we don't need to mess with this, as we can just
-        make the function weak, and let it refer to its unique local
-        copy.  This works because we don't allow the function to be
-        inlined.  */
-      if (! flag_weak)
-       {
-         if (DECL_INTERFACE_KNOWN (current_function_decl))
-           {
-             TREE_PUBLIC (decl) = 1;
-             DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
-           }
-         else if (DECL_INITIAL (decl) == NULL_TREE
-                  || DECL_INITIAL (decl) == error_mark_node)
+      && DECL_FUNCTION_SCOPE_P (decl)
+      /* Unfortunately, import_export_decl has not always been called
+        before the function is processed, so we cannot simply check
+        DECL_COMDAT.  */ 
+      && (DECL_COMDAT (DECL_CONTEXT (decl))
+         || ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
+              || DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
+             && TREE_PUBLIC (DECL_CONTEXT (decl)))))
+    {
+      if (flag_weak)
+       {
+         /* With weak symbols, we simply make the variable COMDAT;
+            that will cause copies in multiple translations units to
+            be merged.  */
+         comdat_linkage (decl);
+       }
+      else
+       {
+         if (DECL_INITIAL (decl) == NULL_TREE
+             || DECL_INITIAL (decl) == error_mark_node)
            {
+             /* Without weak symbols, we can use COMMON to merge
+                uninitialized variables.  */
              TREE_PUBLIC (decl) = 1;
              DECL_COMMON (decl) = 1;
            }
-         /* else we lose. We can only do this if we can use common,
-            which we can't if it has been initialized.  */
-
-         if (!TREE_PUBLIC (decl))
+         else
            {
+             /* While for initialized variables, we must use internal
+                linkage -- which means that multiple copies will not
+                be merged.  */
+             TREE_PUBLIC (decl) = 0;
+             DECL_COMMON (decl) = 0;
              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);
            }
        }
-      else
-       comdat_linkage (decl);
     }
   else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
     /* Set it up again; we might have set DECL_INITIAL since the last
@@ -7570,7 +7494,7 @@ reshape_init (tree type, tree *initp)
   else
     {
       /* Build a CONSTRUCTOR to hold the contents of the aggregate.  */  
-      new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
+      new_init = build_constructor (type, NULL_TREE);
       TREE_HAS_CONSTRUCTOR (new_init) = 1;
 
       if (CLASS_TYPE_P (type))
@@ -7594,10 +7518,24 @@ reshape_init (tree type, tree *initp)
            {
              /* Loop through the initializable fields, gathering
                 initializers.  */
-             while (*initp && field)
+             while (*initp)
                {
                  tree field_init;
 
+                 /* Handle designated initializers, as an extension.  */
+                 if (TREE_PURPOSE (*initp))
+                   {
+                     if (pedantic)
+                       pedwarn ("ISO C++ does not allow designated initializers");
+                     field = lookup_field_1 (type, TREE_PURPOSE (*initp),
+                                             /*want_type=*/false);
+                     if (!field || TREE_CODE (field) != FIELD_DECL)
+                       error ("`%T' has no non-static data member named `%D'",
+                              type, TREE_PURPOSE (*initp));
+                   }
+                 if (!field)
+                   break;
+
                  field_init = reshape_init (TREE_TYPE (field), initp);
                  TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
                  CONSTRUCTOR_ELTS (new_init) = field_init;
@@ -7608,8 +7546,6 @@ reshape_init (tree type, tree *initp)
                     initializer for the first member of the union.  */
                  if (TREE_CODE (type) == UNION_TYPE)
                    break;
-                 if (TREE_PURPOSE (field_init))
-                   field = TREE_PURPOSE (field_init);
                  field = next_initializable_field (TREE_CHAIN (field));
                }
            }
@@ -7729,6 +7665,12 @@ check_initializer (tree decl, tree init, int flags)
             scalar, so just don't call it.  */
          if (CP_AGGREGATE_TYPE_P (type))
            init = reshape_init (type, &init);
+
+         if ((*targetm.vector_opaque_p) (type))
+           {
+             error ("opaque vector types cannot be initialized");
+             init = error_mark_node;
+           }
        }
 
       /* If DECL has an array type without a specific bound, deduce the
@@ -7894,14 +7836,21 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
 void
 maybe_inject_for_scope_var (tree decl)
 {
+  timevar_push (TV_NAME_LOOKUP);
   if (!DECL_NAME (decl))
-    return;
+    {
+      timevar_pop (TV_NAME_LOOKUP);
+      return;
+    }
   
   /* Declarations of __FUNCTION__ and its ilk appear magically when
      the variable is first used.  If that happens to be inside a
      for-loop, we don't want to do anything special.  */
   if (DECL_PRETTY_FUNCTION_P (decl))
-    return;
+    {
+      timevar_pop (TV_NAME_LOOKUP);
+      return;
+    }
 
   if (current_binding_level->is_for_scope)
     {
@@ -7917,12 +7866,11 @@ maybe_inject_for_scope_var (tree decl)
         Otherwise, we need to preserve the temp slot for decl to last
         into the outer binding level.  */
 
-      tree outer_binding
-       = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+      cxx_binding *outer_binding
+       = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
 
-      if (outer_binding && BINDING_LEVEL (outer_binding) == outer
-         && (TREE_CODE (BINDING_VALUE (outer_binding))
-             == VAR_DECL)
+      if (outer_binding && BINDING_SCOPE (outer_binding) == outer
+         && (TREE_CODE (BINDING_VALUE (outer_binding)) == VAR_DECL)
          && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
        {
          BINDING_VALUE (outer_binding)
@@ -7930,6 +7878,7 @@ maybe_inject_for_scope_var (tree decl)
          current_binding_level->is_for_scope = 0;
        }
     }
+  timevar_pop (TV_NAME_LOOKUP);
 }
 
 /* Generate code to initialize DECL (a local variable).  */
@@ -8027,7 +7976,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
     }
 
   /* If a name was specified, get the string.  */
-  if (current_binding_level == global_binding_level)
+  if (global_scope_p (current_binding_level))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
   if (asmspec_tree)
     asmspec = TREE_STRING_POINTER (asmspec_tree);
@@ -8164,6 +8113,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
             necessary zero-initialization has already been performed.  */
          if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
            DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
+                                                  /*nelts=*/NULL_TREE,
                                                   /*static_storage_p=*/true);
          /* Remember that the initialization for this variable has
             taken place.  */
@@ -8465,7 +8415,6 @@ register_dtor_fn (tree decl)
   tree compound_stmt;
   tree args;
   tree fcall;
-  int saved_flag_access_control;
 
   if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
     return;
@@ -8482,10 +8431,10 @@ register_dtor_fn (tree decl)
      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;
-  scope_chain->check_access = flag_access_control = 0;
+  
+  push_deferring_access_checks (dk_no_check);
   fcall = build_cleanup (decl);
-  scope_chain->check_access = flag_access_control = saved_flag_access_control;
+  pop_deferring_access_checks ();
 
   /* Create the body of the anonymous function.  */
   compound_stmt = begin_compound_stmt (/*has_no_scope=*/0);
@@ -8878,7 +8827,7 @@ grokfndecl (tree ctype,
         or enumeration declared in a local scope) shall not be used to
         declare an entity with linkage.
 
-        Only check this for public decls for now.  */
+        Only check this for public decls for now.  See core 319, 389.  */
       t = no_linkage_check (TREE_TYPE (decl));
       if (t)
        {
@@ -8909,13 +8858,19 @@ grokfndecl (tree ctype,
       DECL_NOT_REALLY_EXTERN (decl) = 1;
     }
 
+  DID_INLINE_FUNC (decl) = 0;
   /* If the declaration was declared inline, mark it as such.  */
   if (inlinep)
     DECL_DECLARED_INLINE_P (decl) = 1;
   /* We inline functions that are explicitly declared inline, or, when
      the user explicitly asks us to, all functions.  */
-  if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+  if (DECL_DECLARED_INLINE_P (decl))
     DECL_INLINE (decl) = 1;
+  if (flag_inline_trees == 2 && !DECL_INLINE (decl))
+    {
+      DID_INLINE_FUNC (decl) = 1;
+      DECL_INLINE (decl) = 1;
+    }
 
   DECL_EXTERNAL (decl) = 1;
   if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@@ -9052,6 +9007,8 @@ grokfndecl (tree ctype,
 
       if (old_decl)
        {
+         bool ok;
+
          /* Since we've smashed OLD_DECL to its
             DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
          if (TREE_CODE (decl) == TEMPLATE_DECL)
@@ -9060,10 +9017,14 @@ grokfndecl (tree ctype,
          /* Attempt to merge the declarations.  This can fail, in
             the case of some invalid specialization declarations.  */
          push_scope (ctype);
-         if (!duplicate_decls (decl, old_decl))
-           error ("no `%#D' member function declared in class `%T'",
-                     decl, ctype);
+         ok = duplicate_decls (decl, old_decl);
          pop_scope (ctype);
+         if (!ok)
+           {
+             error ("no `%#D' member function declared in class `%T'",
+                    decl, ctype);
+             return NULL_TREE;
+           }
          return old_decl;
        }
     }
@@ -9332,7 +9293,7 @@ compute_array_index_type (tree name, tree size)
          && TREE_OPERAND (size, 0) == current_class_type)
        {
          tree t = lookup_field (current_class_type,
-                                TREE_OPERAND (size, 1), 0, 0);
+                                TREE_OPERAND (size, 1), 0, false);
          if (t)
            size = t;
        }
@@ -11044,11 +11005,14 @@ grokdeclarator (tree declarator,
       type = error_mark_node;
     }
 
-  if (decl_context == FIELD 
+  if ((decl_context == FIELD || decl_context == PARM)
       && !processing_template_decl 
       && variably_modified_type_p (type))
     {
-      error ("data member may not have variably modified type `%T'", type);
+      if (decl_context == FIELD)
+       error ("data member may not have variably modified type `%T'", type);
+      else
+       error ("parameter may not have variably modified type `%T'", type);
       type = error_mark_node;
     }
 
@@ -11062,7 +11026,7 @@ grokdeclarator (tree declarator,
 
   if (RIDBIT_SETP (RID_MUTABLE, specbits))
     {
-      if (current_class_name == NULL_TREE || decl_context == PARM || friendp)
+      if (decl_context != FIELD || friendp)
         {
          error ("non-member `%s' cannot be declared `mutable'", name);
           RIDBIT_RESET (RID_MUTABLE, specbits);
@@ -11584,18 +11548,15 @@ grokdeclarator (tree declarator,
                  return void_type_node;
              }
 
-           /* 9.2p13 [class.mem] */
-           if (constructor_name_p (declarator, current_class_type)
-               /* The standard does not allow non-static data members
-                  here either, but we agreed at the 10/99 meeting
-                  to change that in TC 1 so that they are allowed in
-                  classes with no user-defined constructors.  */
-               && staticp)
-             pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
-                         declarator);
-
            if (staticp)
              {
+               /* [class.mem] forbids static data members with the
+                  same name as the enclosing class.  Non-static data
+                  members are checked in check_field_decls.  */
+               if (constructor_name_p (declarator, current_class_type))
+                 pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
+                          declarator);
+                 
                /* C++ allows static class members.  All other work
                   for this is done by grokfield.  */
                decl = build_lang_decl (VAR_DECL, declarator, type);
@@ -12546,6 +12507,38 @@ tag_name (enum tag_types code)
     }
 }
 
+/* Name lookup in an elaborated-type-specifier (after the keyword
+   indicated by TAG_CODE) has found TYPE.  If the
+   elaborated-type-specifier is invalid, issue a diagnostic and return
+   error_mark_node; otherwise, return TYPE itself.  */
+
+static tree
+check_elaborated_type_specifier (enum tag_types tag_code,
+                                tree type)
+{
+  tree t;
+
+  t = follow_tag_typedef (type);
+
+  /* [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)
+    {
+      error ("using typedef-name `%D' after `%s'",
+            TYPE_NAME (type), tag_name (tag_code));
+      t = error_mark_node;
+    }
+  else if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
+    {
+      error ("using template type parameter `%T' after `%s'",
+            type, tag_name (tag_code));
+      t = error_mark_node;
+    }
+
+  return t;
+}
+
 /* Get the struct, enum or union (CODE says which) with tag NAME.
    Define the tag as a forward-reference if it is not defined.
 
@@ -12565,6 +12558,7 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
   struct cp_binding_level *b = current_binding_level;
   tree context = NULL_TREE;
 
+  timevar_push (TV_NAME_LOOKUP);
   switch (tag_code)
     {
     case record_type:
@@ -12631,20 +12625,9 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
     {
       if (t)
        {
-         ref = follow_tag_typedef (t);
-
-         /* [dcl.type.elab] If the identifier resolves to a
-            typedef-name or a template type-parameter, the
-            elaborated-type-specifier is ill-formed.  */
-         if (!ref)
-           {
-             pedwarn ("using typedef-name `%D' after `%s'",
-                      TYPE_NAME (t), tag_name (tag_code));
-             ref = t;
-           }
-         else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
-           error ("using template type parameter `%T' after `%s'",
-                  t, tag_name (tag_code));
+         ref = check_elaborated_type_specifier (tag_code, t);
+         if (ref == error_mark_node)
+           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
        }
       else
        ref = lookup_tag (code, name, b, 0);
@@ -12663,9 +12646,15 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
               template, so we want this type.  */
            ref = DECL_TEMPLATE_RESULT (ref);
 
-         if (ref && TREE_CODE (ref) == TYPE_DECL
-             && TREE_CODE (TREE_TYPE (ref)) == code)
-           ref = TREE_TYPE (ref);
+         if (ref && TREE_CODE (ref) == TYPE_DECL)
+           {
+             ref = check_elaborated_type_specifier (tag_code, 
+                                                    TREE_TYPE (ref));
+             if (ref == error_mark_node)
+               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+             if (ref && TREE_CODE (ref) != code)
+               ref = NULL_TREE;
+           }
          else
            ref = NULL_TREE;
        }
@@ -12767,7 +12756,7 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
 
   TYPE_ATTRIBUTES (ref) = attributes;
 
-  return ref;
+  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
 }
 
 tree
@@ -12787,17 +12776,17 @@ xref_tag_from_type (tree old, tree id, int globalize)
 }
 
 /* REF is a type (named NAME), for which we have just seen some
-   baseclasses.  BINFO is a list of those baseclasses; the
+   baseclasses.  BASE_LIST is a list of those baseclasses; the
    TREE_PURPOSE is an access_* node, and the TREE_VALUE is the type of
-   the base-class.  CODE_TYPE_NODE indicates whether REF is a class,
+   the base-class.  TREE_VIA_VIRTUAL indicates virtual
+   inheritance. CODE_TYPE_NODE indicates whether REF is a class,
    struct, or union.  */
 
 void
-xref_basetypes (tree ref, tree binfo)
+xref_basetypes (tree ref, tree base_list)
 {
   /* 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 *basep;
 
   int i;
@@ -12815,145 +12804,147 @@ xref_basetypes (tree ref, tree binfo)
      instantiated.  This ensures that if we call ourselves recursively
      we do not get confused about which classes are marked and which
      are not.  */
-  basep = &binfo
+  basep = &base_list
   while (*basep) 
     {
       tree basetype = TREE_VALUE (*basep);
       if (!(processing_template_decl && uses_template_parms (basetype))
          && !complete_type_or_else (basetype, NULL))
-       /* An incomplete type.  Remove it form the list.  */
+       /* An incomplete type.  Remove it from the list.  */
        *basep = TREE_CHAIN (*basep);
       else
        basep = &TREE_CHAIN (*basep);
     }
 
   SET_CLASSTYPE_MARKED (ref);
-  BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos 
-    = make_tree_vec (list_length (binfo));
-
-  for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
-    {
-      /* The base of a derived struct is public by default.  */
-      int via_public
-       = (TREE_PURPOSE (binfo) == access_public_node
-          || TREE_PURPOSE (binfo) == access_public_virtual_node
-          || (tag_code != class_type
-              && (TREE_PURPOSE (binfo) == access_default_node
-                  || TREE_PURPOSE (binfo) == access_default_virtual_node)));
-      int via_protected
-       = (TREE_PURPOSE (binfo) == access_protected_node
-          || TREE_PURPOSE (binfo) == access_protected_virtual_node);
-      int via_virtual
-       = (TREE_PURPOSE (binfo) == access_private_virtual_node
-          || TREE_PURPOSE (binfo) == access_protected_virtual_node
-          || TREE_PURPOSE (binfo) == access_public_virtual_node
-          || TREE_PURPOSE (binfo) == access_default_virtual_node);
-      tree basetype = TREE_VALUE (binfo);
-      tree base_binfo;
-
-      if (basetype && TREE_CODE (basetype) == TYPE_DECL)
-       basetype = TREE_TYPE (basetype);
-      if (!basetype
-         || (TREE_CODE (basetype) != RECORD_TYPE
-             && TREE_CODE (basetype) != TYPENAME_TYPE
-             && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
-             && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
-       {
-         error ("base type `%T' fails to be a struct or class type",
-                   TREE_VALUE (binfo));
-         continue;
-       }
-
-      if (CLASSTYPE_MARKED (basetype))
+  i = list_length (base_list);
+  if (i)
+    {
+      tree binfo = TYPE_BINFO (ref);
+      tree binfos = make_tree_vec (i);
+      tree accesses = make_tree_vec (i);
+      
+      BINFO_BASETYPES (binfo) = binfos;
+      BINFO_BASEACCESSES (binfo) = accesses;
+  
+      for (i = 0; base_list; base_list = TREE_CHAIN (base_list))
        {
-         if (basetype == ref)
-           error ("recursive type `%T' undefined", basetype);
+         tree access = TREE_PURPOSE (base_list);
+         int via_virtual = TREE_VIA_VIRTUAL (base_list);
+         tree basetype = TREE_VALUE (base_list);
+         tree base_binfo;
+         
+         if (access == access_default_node)
+           /* The base of a derived struct is public by default.  */
+           access = (tag_code == class_type
+                     ? access_private_node : access_public_node);
+         
+         if (basetype && TREE_CODE (basetype) == TYPE_DECL)
+           basetype = TREE_TYPE (basetype);
+         if (!basetype
+             || (TREE_CODE (basetype) != RECORD_TYPE
+                 && TREE_CODE (basetype) != TYPENAME_TYPE
+                 && TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
+                 && TREE_CODE (basetype) != BOUND_TEMPLATE_TEMPLATE_PARM))
+           {
+             error ("base type `%T' fails to be a struct or class type",
+                    basetype);
+             continue;
+           }
+         
+         if (CLASSTYPE_MARKED (basetype))
+           {
+             if (basetype == ref)
+               error ("recursive type `%T' undefined", basetype);
+             else
+               error ("duplicate base type `%T' invalid", basetype);
+             continue;
+           }
+         
+         if (TYPE_FOR_JAVA (basetype)
+             && (current_lang_depth () == 0))
+           TYPE_FOR_JAVA (ref) = 1;
+         
+         if (CLASS_TYPE_P (basetype))
+           {
+             base_binfo = TYPE_BINFO (basetype);
+             /* This flag will be in the binfo of the base type, we must
+                clear it after copying the base binfos.  */
+             BINFO_DEPENDENT_BASE_P (base_binfo)
+               = dependent_type_p (basetype);
+           }
          else
-           error ("duplicate base type `%T' invalid", basetype);
-         continue;
+           base_binfo = make_binfo (size_zero_node, basetype,
+                                    NULL_TREE, NULL_TREE);
+         
+         TREE_VEC_ELT (binfos, i) = base_binfo;
+         TREE_VEC_ELT (accesses, i) = access;
+         /* This flag will be in the binfo of the base type, we must
+            clear it after copying the base binfos.  */
+         TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
+         
+         SET_CLASSTYPE_MARKED (basetype);
+         
+         /* We are free to modify these bits because they are meaningless
+            at top level, and BASETYPE is a top-level type.  */
+         if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+           {
+             TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
+             /* Converting to a virtual base class requires looking
+                up the offset of the virtual base.  */
+             TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
+           }
+         
+         if (CLASS_TYPE_P (basetype))
+           {
+             TYPE_HAS_NEW_OPERATOR (ref)
+               |= TYPE_HAS_NEW_OPERATOR (basetype);
+             TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
+               |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
+             TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+             /* If the base-class uses multiple inheritance, so do we.  */
+             TYPE_USES_MULTIPLE_INHERITANCE (ref)
+               |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+             /* Likewise, if converting to a base of the base may require
+                code, then we may need to generate code to convert to a
+                base as well.  */
+             TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
+               |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+           }
+         i++;
        }
-
-      if (TYPE_FOR_JAVA (basetype)
-         && (current_lang_depth () == 0))
-       TYPE_FOR_JAVA (ref) = 1;
-
-      /* Note that the BINFO records which describe individual
-        inheritances are *not* shared in the lattice!  They
-        cannot be shared because a given baseclass may be
-        inherited with different `accessibility' by different
-        derived classes.  (Each BINFO record describing an
-        individual inheritance contains flags which say what
-        the `accessibility' of that particular inheritance is.)  */
-
-      base_binfo
-       = make_binfo (size_zero_node, basetype,
-                     CLASS_TYPE_P (basetype)
-                     ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
-                     CLASS_TYPE_P (basetype)
-                     ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
-
-      TREE_VEC_ELT (binfos, i) = base_binfo;
-      TREE_VIA_PUBLIC (base_binfo) = via_public;
-      TREE_VIA_PROTECTED (base_binfo) = via_protected;
-      TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
-      BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
-
-      /* We need to unshare the binfos now so that lookups during class
-        definition work.  */
-      unshare_base_binfos (base_binfo);
-
-      SET_CLASSTYPE_MARKED (basetype);
-
-      /* We are free to modify these bits because they are meaningless
-        at top level, and BASETYPE is a top-level type.  */
-      if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
-       {
-         TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
-         /* Converting to a virtual base class requires looking
-            up the offset of the virtual base.  */
+      if (i)
+       TREE_VEC_LENGTH (accesses) = TREE_VEC_LENGTH (binfos) = i;
+      else
+       BINFO_BASEACCESSES (binfo) = BINFO_BASETYPES (binfo) = NULL_TREE;
+      
+      if (i > 1)
+       {
+         TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
+         /* If there is more than one non-empty they cannot be at the same
+            address.  */
          TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
        }
-
+    }
+  
+  /* Copy the base binfos, collect the virtual bases and set the
+     inheritance order chain.  */
+  copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
+  CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
+  
+  /* Unmark all the types.  */
+  while (i--)
+    {
+      tree basetype = BINFO_TYPE (BINFO_BASETYPE (TYPE_BINFO (ref), i));
+      
+      CLEAR_CLASSTYPE_MARKED (basetype);
       if (CLASS_TYPE_P (basetype))
        {
-         TYPE_HAS_NEW_OPERATOR (ref)
-           |= TYPE_HAS_NEW_OPERATOR (basetype);
-         TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
-           |= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
-         TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
-         /* If the base-class uses multiple inheritance, so do we.  */
-         TYPE_USES_MULTIPLE_INHERITANCE (ref)
-           |= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
-         /* Likewise, if converting to a base of the base may require
-            code, then we may need to generate code to convert to a
-            base as well.  */
-         TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
-           |= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype);
+         TREE_VIA_VIRTUAL (TYPE_BINFO (basetype)) = 0;
+         BINFO_DEPENDENT_BASE_P (TYPE_BINFO (basetype)) = 0;
        }
-
-      i += 1;
     }
-  if (i)
-    TREE_VEC_LENGTH (binfos) = i;
-  else
-    BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
-
-  if (i > 1)
-    {
-      TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
-      /* If there is more than one non-empty they cannot be at the same
-        address.  */
-      TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
-    }
-
-  /* Unmark all the types.  */
-  while (--i >= 0)
-    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.  */
-  get_vbase_types (ref);
 }
 
 \f
@@ -13011,44 +13002,56 @@ finish_enum (tree enumtype)
   /* We built up the VALUES in reverse order.  */
   TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
 
-  /* [dcl.enum]
-
-     Following the closing brace of an enum-specifier, each
-     enumerator has the type of its enumeration.  Prior to the
-     closing brace, the type of each enumerator is the type of
-     its initializing value.  */
-  for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
-    TREE_TYPE (TREE_VALUE (pair)) = enumtype;
-  
-  /* For an enum defined in a template, all further processing is
-     postponed until the template is instantiated.  */
+  /* For an enum defined in a template, just set the type of the values;
+     all further processing is postponed until the template is
+     instantiated.  We need to set the type so that tsubst of a CONST_DECL
+     works.  */
   if (processing_template_decl)
     {
+      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
+       TREE_TYPE (TREE_VALUE (pair)) = enumtype;
       if (at_function_scope_p ())
        add_stmt (build_min (TAG_DEFN, enumtype));
       return;
     }
 
-  /* Figure out what the minimum and maximum values of the enumerators
-     are.  */
   if (TYPE_VALUES (enumtype))
     {
       minnode = maxnode = NULL_TREE;
 
-      for (pair = TYPE_VALUES (enumtype);
-          pair;
-          pair = TREE_CHAIN (pair))
+      for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
        {
-         tree value;
+         tree decl = TREE_VALUE (pair);
+         tree value = DECL_INITIAL (decl);
 
-         value = DECL_INITIAL (TREE_VALUE (pair));
+         /* [dcl.enum]: Following the closing brace of an enum-specifier,
+            each enumerator has the type of its enumeration.  Prior to the
+            closing brace, the type of each enumerator is the type of its
+            initializing value.  */
+         TREE_TYPE (decl) = enumtype;
 
+         /* Figure out what the minimum and maximum values of the
+            enumerators are.  */
          if (!minnode)
            minnode = maxnode = value;
          else if (tree_int_cst_lt (maxnode, value))
            maxnode = value;
          else if (tree_int_cst_lt (value, minnode))
            minnode = value;
+
+         /* Set the TREE_TYPE for the values as well.  That's so that when
+            we call decl_constant_value we get an entity of the right type
+            (but with the constant value).  But first make a copy so we
+            don't clobber shared INTEGER_CSTs.  */
+         if (TREE_TYPE (value) != enumtype)
+           {
+             value = DECL_INITIAL (decl) = copy_node (value);
+             TREE_TYPE (value) = enumtype;
+           }
+
+         /* In addition, transform the TYPE_VALUES list to contain the
+            values, rather than the CONST_DECLs for them.  */
+         TREE_VALUE (pair) = value;
        }
     }
   else
@@ -13063,18 +13066,6 @@ finish_enum (tree enumtype)
   highprec = min_precision (maxnode, unsignedp);
   precision = MAX (lowprec, highprec);
 
-  /* Set the TREE_TYPE for the values as well.  That's so that when we
-     call decl_constant_value we get an entity of the right type (but
-     with the constant value).  In addition, transform the TYPE_VALUES
-     list to contain the values, rather than the CONST_DECLs for them.  */
-  for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
-    {
-      tree value = DECL_INITIAL (TREE_VALUE (pair));
-
-      TREE_TYPE (value) = enumtype;
-      TREE_VALUE (pair) = value;
-    }
-
   /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
   TYPE_SIZE (enumtype) = NULL_TREE;
   TYPE_PRECISION (enumtype) = precision;
@@ -13123,7 +13114,6 @@ build_enumerator (tree name, tree value, tree enumtype)
   tree decl;
   tree context;
   tree type;
-  tree values;
 
   /* Remove no-op casts from the value.  */
   if (value)
@@ -13149,7 +13139,7 @@ build_enumerator (tree name, tree value, tree enumtype)
        }
 
       /* Default based on previous value.  */
-      if (value == NULL_TREE && ! processing_template_decl)
+      if (value == NULL_TREE)
        {
          tree prev_value;
 
@@ -13170,26 +13160,9 @@ build_enumerator (tree name, tree value, tree enumtype)
        }
 
       /* Remove no-op casts from the value.  */
-      if (value)
-       STRIP_TYPE_NOPS (value);
-#if 0
-      /* To fix MAX_VAL enum consts. (bkoz)  */
-      TREE_TYPE (value) = integer_type_node;
-#endif
+      STRIP_TYPE_NOPS (value);
     }
 
-  /* We always have to copy here; not all INTEGER_CSTs are unshared.
-     Even in other cases, we will later (in finish_enum) be setting
-     the type of VALUE.  But, we don't need to make a copy if this
-     VALUE is one of the enumeration constants for this same
-     enumeration type.  */
-  for (values = TYPE_VALUES (enumtype); values; values = TREE_CHAIN (values))
-    if (TREE_VALUE (values) == value)
-      break;
-  /* If we didn't break out of the loop, then we do need a copy.  */
-  if (!values && value)
-    value = copy_node (value);
-
   /* C++ associates enums with global, function, or class declarations.  */
   context = current_scope ();
 
@@ -13218,8 +13191,8 @@ build_enumerator (tree name, tree value, tree enumtype)
     decl = build_decl (CONST_DECL, name, type);
 
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+  TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
-  TREE_READONLY (decl) = 1;
 
   if (context && context == current_class_type)
     /* In something like `struct S { enum E { i = 7 }; };' we put `i'
@@ -13351,7 +13324,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
       cplus_decl_attributes (&decl1, attrs, 0);
 
       /* If #pragma weak was used, mark the decl weak now.  */
-      if (current_binding_level == global_binding_level)
+      if (global_scope_p (current_binding_level))
        maybe_apply_pragma_weak (decl1);
 
       fntype = TREE_TYPE (decl1);
@@ -13376,8 +13349,9 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
        ctype = TYPE_METHOD_BASETYPE (fntype);
       else if (DECL_MAIN_P (decl1))
        {
-         /* If this doesn't return integer_type, complain.  */
-         if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
+         /* If this doesn't return integer_type, or a typedef to
+            integer_type, complain.  */
+         if (!same_type_p (TREE_TYPE (TREE_TYPE (decl1)), integer_type_node))
            {
              if (pedantic || warn_return_type)
                pedwarn ("return type for `main' changed to `int'");
@@ -13388,8 +13362,8 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
 
   if (DECL_DECLARED_INLINE_P (decl1)
       && lookup_attribute ("noinline", attrs))
-    warning_with_decl (decl1,
-                      "inline function `%s' given attribute noinline");
+    warning ("%Hinline function '%D' given attribute noinline",
+             &DECL_SOURCE_LOCATION (decl1), decl1);
 
   if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
     /* This is a constructor, we must ensure that any default args
@@ -13483,7 +13457,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
      CFUN set up, and our per-function variables initialized.
      FIXME factor out the non-RTL stuff.  */
   bl = current_binding_level;
-  init_function_start (decl1, input_filename, lineno);
+  init_function_start (decl1, input_filename, input_line);
   current_binding_level = bl;
 
   /* Even though we're inside a function body, we still don't want to
@@ -13496,6 +13470,9 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
   /* Start the statement-tree, start the tree now.  */
   begin_stmt_tree (&DECL_SAVED_TREE (decl1));
 
+  /* Don't double-count statements in templates.  */
+  DECL_NUM_STMTS (decl1) = 0;
+
   /* Let the user know we're compiling this function.  */
   announce_function (decl1);
 
@@ -13707,7 +13684,6 @@ store_parm_decls (tree current_function_parms)
         function.  This is all and only the PARM_DECLs that were
         pushed into scope by the loop above.  */
       DECL_ARGUMENTS (fndecl) = getdecls ();
-      storetags (gettags ());
     }
   else
     DECL_ARGUMENTS (fndecl) = NULL_TREE;
@@ -13994,6 +13970,12 @@ finish_function (int flags)
   /* If we're saving up tree structure, tie off the function now.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
+  /* If this function can't throw any exceptions, remember that.  */
+  if (!processing_template_decl
+      && !cp_function_chain->can_throw
+      && !flag_non_call_exceptions)
+    TREE_NOTHROW (fndecl) = 1;
+
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
      this function's blocks.  */
@@ -14028,11 +14010,21 @@ finish_function (int flags)
   if (current_function_return_value)
     {
       tree r = current_function_return_value;
-      /* This is only worth doing for fns that return in memory--and
-        simpler, since we don't have to worry about promoted modes.  */
+      tree outer;
+
       if (r != error_mark_node
-         && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
+         /* This is only worth doing for fns that return in memory--and
+            simpler, since we don't have to worry about promoted modes.  */
+         && aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl)))
+         /* Only allow this for variables declared in the outer scope of
+            the function so we know that their lifetime always ends with a
+            return; see g++.dg/opt/nrv6.C.  We could be more flexible if
+            we were to do this optimization in tree-ssa.  */
+         /* Skip the artificial function body block.  */
+         && (outer = BLOCK_SUBBLOCKS (BLOCK_SUBBLOCKS (DECL_INITIAL (fndecl))),
+             chain_member (r, BLOCK_VARS (outer))))
        {
+         
          DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
          walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
                                        nullify_returns_r, r);
@@ -14171,6 +14163,7 @@ start_method (tree declspecs, tree declarator, tree attrlist)
 
   DECL_DECLARED_INLINE_P (fndecl) = 1;
 
+  DID_INLINE_FUNC (fndecl) = 0;
   if (flag_default_inline)
     DECL_INLINE (fndecl) = 1;
 
@@ -14426,13 +14419,11 @@ cp_tree_node_structure (union lang_tree_node * t)
     {
     case DEFAULT_ARG:          return TS_CP_DEFAULT_ARG;
     case IDENTIFIER_NODE:      return TS_CP_IDENTIFIER;
-    case CPLUS_BINDING:                return TS_CP_BINDING;
     case OVERLOAD:             return TS_CP_OVERLOAD;
     case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
     case PTRMEM_CST:           return TS_CP_PTRMEM;
     case BASELINK:              return TS_CP_BASELINK;
     case WRAPPER:              return TS_CP_WRAPPER;
-    case SRCLOC:               return TS_CP_SRCLOC;
     default:                   return TS_CP_GENERIC;
     }
 }