OSDN Git Service

* decl.c (ENABLE_SCOPE_CHECKING): Rename from DEBUG_BINDING_LEVELS.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 99898d0..ec302ae 100644 (file)
@@ -98,7 +98,6 @@ 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 cxx_binding *find_binding (tree, tree, cxx_binding *);
 static tree select_decl (cxx_binding *, int);
 static int lookup_flags (int, int);
 static tree qualify_lookup (tree, int);
@@ -113,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);
@@ -149,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;
 
@@ -216,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;
 };
 
@@ -333,15 +327,8 @@ struct cp_binding_level GTY(())
     /* 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;
@@ -435,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.  */
 
@@ -447,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;
@@ -463,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 *);
 
@@ -493,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
@@ -522,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 ();
   }
@@ -561,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 ();
 }
@@ -594,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'.  */
@@ -619,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.  */
@@ -680,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));
 }
 
@@ -806,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;
@@ -885,39 +868,19 @@ 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) ((NODE)->scope.level)
-
-/* A free list of cxx_binding nodes, connected by their
-   TREE_CHAINs.  */
-
-static GTY((deletable (""))) cxx_binding *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)
 {
-  cxx_binding *binding;
-
-  if (free_bindings)
-    {
-      binding = free_bindings;
-      free_bindings = binding->previous;
-    }
-  else
-    binding = cxx_binding_make ();
+   cxx_binding *binding = cxx_binding_make (decl, NULL);
 
   /* Now, fill in the binding information.  */
   binding->previous = IDENTIFIER_BINDING (id);
-  BINDING_VALUE (binding) = decl;
-  BINDING_TYPE (binding) = NULL_TREE;
-  BINDING_LEVEL (binding) = level;
+  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.  */
   IDENTIFIER_BINDING (id) = binding;
@@ -1085,7 +1048,7 @@ push_class_binding (tree id, tree decl)
      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
@@ -1161,12 +1124,11 @@ pop_binding (tree id, tree decl)
       IDENTIFIER_BINDING (id) = binding->previous;
 
       /* Add it to the free list.  */
-      binding->previous = 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;
     }
 }
 
@@ -1238,7 +1200,6 @@ 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;
@@ -1253,7 +1214,6 @@ poplevel (int keep, int reverse, int functionbody)
 
   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,
@@ -1383,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:
 
@@ -1415,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)
@@ -1430,9 +1390,8 @@ poplevel (int keep, int reverse, int functionbody)
                             dead_vars_from_for);
 
              /* Although we don't pop the cxx_binding, we do clear
-                its BINDING_LEVEL since the level is going away now.  */
-             BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
-               = 0;
+                its BINDING_SCOPE since the level is going away now.  */
+             BINDING_SCOPE (IDENTIFIER_BINDING (DECL_NAME (link))) = 0;
            }
        }
       else
@@ -1594,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;
@@ -1606,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);
 
@@ -1657,7 +1611,7 @@ poplevel_class (void)
            cxx_binding *binding;
             
            binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
-           while (binding && BINDING_LEVEL (binding) != b)
+           while (binding && BINDING_SCOPE (binding) != b)
              binding = binding->previous;
 
            if (binding)
@@ -1685,9 +1639,8 @@ 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);
@@ -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,114 +1981,13 @@ 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 "cxx_binding"s.  */
 
-/* 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 inline cxx_binding *
-find_binding (tree name, tree scope, cxx_binding *front)
-{
-  cxx_binding *iter;
-  cxx_binding *prev = NULL;
-
-  timevar_push (TV_NAME_LOOKUP);
-  scope = ORIGINAL_NAMESPACE (scope);
-
-  for (iter = front; iter != NULL; iter = iter->previous)
-    {
-      if (BINDING_SCOPE (iter) == scope)
-       {
-         /* Move binding found to the front of the list, so
-             subsequent lookups will find it faster.  */
-         if (prev)
-           {
-             prev->previous = iter->previous;
-             iter->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
-             IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
-           }
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
-       }
-      prev = iter;
-    }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
-}
-
-/* Return the binding for NAME in SCOPE, if any.  Otherwise, return NULL.  */
-cxx_binding *
-cxx_scope_find_binding_for_name (tree scope, tree name)
-{
-  cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
-  if (b)
-    {
-      scope = ORIGINAL_NAMESPACE (scope);
-      /* Fold-in case where NAME is used only once.  */
-      if (scope == BINDING_SCOPE (b) && b->previous == NULL)
-        return b;
-      return find_binding (name, scope, b);
-    }
-  return b;
-}
-
-/* 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.  */
-
-cxx_binding *
-binding_for_name (tree name, tree scope)
-{
-  cxx_binding *result;
-
-  scope = ORIGINAL_NAMESPACE (scope);
-  result = cxx_scope_find_binding_for_name (scope, name);
-  if (result)
-    return result;
-  /* Not found, make a new one.  */
-  result = cxx_binding_make ();
-  result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
-  BINDING_TYPE (result) = NULL_TREE;
-  BINDING_VALUE (result) = NULL_TREE;
-  BINDING_SCOPE (result) = scope;
-  result->is_local = false;
-  result->value_is_inherited = false;
-  result->has_level = false;
-  IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
-  return result;
-}
-
-/* Return the binding value for name in scope.  */
-
-tree
-namespace_binding (tree name, tree scope)
-{
-  cxx_binding *b =
-    cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
-
-  return b ? b->value : NULL_TREE;
-}
-
-/* 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)
-{
-  cxx_binding *b;
-
-  timevar_push (TV_NAME_LOOKUP);
-  if (scope == NULL_TREE)
-    scope = global_namespace;
-  b = binding_for_name (name, scope);
-  BINDING_VALUE (b) = val;
-  timevar_pop (TV_NAME_LOOKUP);
-}
-
 /* 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.  */
 
@@ -2184,6 +2049,10 @@ 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");
@@ -2338,7 +2207,7 @@ maybe_push_to_top_level (int pseudo)
   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)
     {
@@ -2348,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);
@@ -2367,7 +2236,6 @@ 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;
@@ -2443,7 +2311,8 @@ set_identifier_type_value_with_scope (tree id,
     }
   else
     {
-      cxx_binding *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;
@@ -2486,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)
@@ -2496,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
@@ -2552,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;
                }
            }
        }
@@ -2620,7 +2490,8 @@ push_local_name (tree decl)
            DECL_DISCRIMINATOR (decl) = 1;
 
          VARRAY_TREE (local_names, i) = decl;
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+         timevar_pop (TV_NAME_LOOKUP);
+         return;
        }
     }
 
@@ -2650,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)
     {
@@ -2727,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;
            }
        }
     }
@@ -2767,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.  */
@@ -2784,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
@@ -3073,7 +2936,7 @@ duplicate_decls (tree newdecl, tree olddecl)
          SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
        }
       /* Even if the types match, prefer the new declarations type
-        for anitipated built-ins, for exception lists, etc...  */
+        for anticipated built-ins, for exception lists, etc...  */
       else if (DECL_ANTICIPATED (olddecl))
        TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
 
@@ -3365,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);
     }
 
@@ -3481,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);
        }
@@ -3707,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;
 }
 
@@ -4123,7 +3999,7 @@ pushdecl (tree x)
                }
 
              if (warn_shadow && !err)
-               shadow_warning (SW_PARAM, false,
+               shadow_warning (SW_PARAM,
                                IDENTIFIER_POINTER (name), oldlocal);
            }
 
@@ -4141,12 +4017,12 @@ pushdecl (tree x)
                            IDENTIFIER_POINTER (name));
              else if (oldlocal != NULL_TREE
                       && TREE_CODE (oldlocal) == VAR_DECL)
-               shadow_warning (SW_LOCAL, false,
+               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 (SW_GLOBAL, false,
+               shadow_warning (SW_GLOBAL,
                                IDENTIFIER_POINTER (name), oldglobal);
            }
        }
@@ -4215,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))
@@ -4242,8 +4118,7 @@ pushdecl_namespace_level (tree x)
   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)
@@ -4328,7 +4203,10 @@ push_class_level_binding (tree name, tree x)
   /* The class_binding_level will be NULL if x is a template
      parameter name in a member template.  */
   if (!class_binding_level)
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+    {
+      timevar_pop (TV_NAME_LOOKUP);
+      return;
+    }
 
   /* Make sure that this new member does not have the same name
      as a template parameter.  */
@@ -4378,7 +4256,8 @@ push_class_level_binding (tree name, tree x)
            INHERITED_VALUE_BINDING_P (binding) = 0;
            TREE_TYPE (shadow) = x;
            IDENTIFIER_CLASS_VALUE (name) = x;
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+           timevar_pop (TV_NAME_LOOKUP);
+           return;
          }
     }
 
@@ -4550,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
@@ -4713,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);
@@ -4740,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;
     }
@@ -4840,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;
@@ -4865,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;
            }
 
@@ -4889,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)
@@ -4906,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
@@ -5153,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.  */
@@ -5171,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
@@ -5221,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).
@@ -5238,25 +5105,26 @@ lookup_tag (enum tree_code form, tree name,
   /* 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)
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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))
          {
             cxx_binding *binding =
-              cxx_scope_find_binding_for_name (tail, name);
+              cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (tail), name);
            tree old;
 
            /* If we just skipped past a template parameter level,
@@ -5292,22 +5160,22 @@ lookup_tag (enum tree_code form, tree name,
            if (thislevel_only || tail == global_namespace)
              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);
-                   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-                 }
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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)
        {
@@ -5349,16 +5217,11 @@ lookup_tag_reverse (tree type, tree name)
   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;
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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);
     }
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
 }
@@ -5538,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)
@@ -5596,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),
@@ -5631,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);
@@ -5693,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;
     }
@@ -5771,7 +5624,8 @@ unqualified_namespace_lookup (tree name, int flags, tree* spacesp)
 
   for (; !val; scope = CP_DECL_CONTEXT (scope))
     {
-      cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
+      cxx_binding *b =
+         cxx_scope_find_binding_for_name (NAMESPACE_LEVEL (scope), name);
       if (spacesp)
        *spacesp = tree_cons (scope, NULL_TREE, *spacesp);
 
@@ -6078,7 +5932,7 @@ lookup_name_current_level (tree name)
     {
       while (1)
        {
-         if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+         if (BINDING_SCOPE (IDENTIFIER_BINDING (name)) == b)
            POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
 
          if (b->keep == 2)
@@ -6322,12 +6176,12 @@ 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 (global_binding_level->static_decls,
+  VARRAY_TREE_INIT (current_binding_level->static_decls,
                    200,
                    "Static declarations");
 
@@ -7109,7 +6963,7 @@ 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
@@ -7450,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
@@ -7637,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))
@@ -7661,11 +7518,24 @@ reshape_init (tree type, tree *initp)
            {
              /* Loop through the initializable fields, gathering
                 initializers.  */
-              /* FIXME support non-trivial labeled 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;
@@ -7968,13 +7838,19 @@ maybe_inject_for_scope_var (tree decl)
 {
   timevar_push (TV_NAME_LOOKUP);
   if (!DECL_NAME (decl))
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+    {
+      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))
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
+    {
+      timevar_pop (TV_NAME_LOOKUP);
+      return;
+    }
 
   if (current_binding_level->is_for_scope)
     {
@@ -7993,7 +7869,7 @@ maybe_inject_for_scope_var (tree decl)
       cxx_binding *outer_binding
        = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
 
-      if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+      if (outer_binding && BINDING_SCOPE (outer_binding) == outer
          && (TREE_CODE (BINDING_VALUE (outer_binding)) == VAR_DECL)
          && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
        {
@@ -8100,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);
@@ -8539,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;
@@ -8556,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);
@@ -8952,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)
        {
@@ -9132,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)
@@ -9140,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;
        }
     }
@@ -11145,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);
@@ -11667,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);
@@ -12629,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.
 
@@ -12715,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);
@@ -12747,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;
        }
@@ -13286,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'
@@ -13419,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);
@@ -13444,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'");
@@ -13551,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
@@ -13778,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;
@@ -14065,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.  */
@@ -14513,7 +14424,6 @@ cp_tree_node_structure (union lang_tree_node * t)
     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;
     }
 }