OSDN Git Service

When a class template is explicitly instantiated, its member should be too.
[pf3gnuchains/gcc-fork.git] / gcc / cp / decl.c
index 64d8e52..92f6d14 100644 (file)
@@ -1,6 +1,6 @@
 /* Process declarations and variables for C++ compiler.
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003  Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004  Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com)
 
 This file is part of GCC.
@@ -51,30 +51,21 @@ Boston, MA 02111-1307, USA.  */
 #include "diagnostic.h"
 #include "debug.h"
 #include "timevar.h"
+#include "tree-flow.h"
 
-static tree grokparms (tree);
+static tree grokparms (tree, tree *);
 static const char *redeclaration_error_message (tree, tree);
 
-static void resume_binding_level (struct cp_binding_level *);
 static int decl_jump_unsafe (tree);
-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 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);
 static tree grok_reference_init (tree, tree, tree, tree *);
-static tree grokfndecl (tree, tree, tree, tree, int,
+static tree grokfndecl (tree, tree, tree, tree, tree, int,
                        enum overload_flags, tree,
                        tree, int, int, int, int, int, int, tree);
 static tree grokvardecl (tree, tree, RID_BIT_TYPE *, int, int, tree);
-static tree follow_tag_typedef (tree);
-static tree lookup_tag (enum tree_code, tree,
-                       struct cp_binding_level *, int);
-static void set_identifier_type_value_with_scope
-       (tree, tree, struct cp_binding_level *);
 static void record_unknown_type (tree, const char *);
 static tree builtin_function_1 (const char *, tree, tree, int,
                                 enum built_in_class, const char *,
@@ -83,24 +74,15 @@ static tree build_library_fn_1 (tree, enum tree_code, tree);
 static int member_function_or_else (tree, tree, enum overload_flags);
 static void bad_specifiers (tree, const char *, int, int, int, int,
                            int);
-static tree maybe_process_template_type_declaration 
-       (tree, int, struct cp_binding_level*);
 static void check_for_uninitialized_const_var (tree);
 static hashval_t typename_hash (const void *);
 static int typename_compare (const void *, const void *);
-static void push_binding (tree, tree, struct cp_binding_level*);
-static void pop_binding (tree, tree);
 static tree local_variable_p_walkfn (tree *, int *, void *);
-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);
 static const char *tag_name (enum tag_types code);
-static struct cp_binding_level *innermost_nonclass_level (void);
 static int walk_namespaces_r (tree, walk_namespaces_fn, void *);
 static int walk_globals_r (tree, void*);
 static int walk_vtables_r (tree, void*);
-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,
@@ -133,7 +115,6 @@ static tree check_special_function_return_type
 static tree push_cp_library_fn (enum tree_code, tree);
 static tree build_cp_library_fn (tree, enum tree_code, tree);
 static void store_parm_decls (tree);
-static int cp_missing_noreturn_ok_p (tree);
 static void initialize_local_var (tree, tree);
 static void expand_static_init (tree, tree);
 static tree next_initializable_field (tree);
@@ -159,7 +140,7 @@ tree error_mark_list;
        tree ptm_desc_type_node;
        tree base_desc_type_node;
 
-       tree class_type_node, record_type_node, union_type_node, enum_type_node;
+       tree class_type_node;
        tree unknown_type_node;
 
    Array type `vtable_entry_type[]'
@@ -193,10 +174,10 @@ tree cp_global_trees[CPTI_MAX];
 /* Indicates that there is a type value in some namespace, although
    that is not necessarily in scope at the moment.  */
 
-static GTY(()) tree global_type_node;
+tree global_type_node;
 
 /* The node that holds the "name" of the global scope.  */
-static GTY(()) tree global_scope_name;
+tree global_scope_name;
 
 /* Used only for jumps to as-yet undefined labels, since jumps to
    defined labels can have their validity checked immediately.  */
@@ -226,9 +207,6 @@ tree static_aggregates;
 
 tree integer_two_node, integer_three_node;
 
-/* Similar, for last_function_parm_tags.  */
-tree last_function_parms;
-
 /* A list of all LABEL_DECLs in the function that have names.  Here so
    we can clear out their names' definitions at the end of the
    function, and so we can check the validity of jumps to these labels.  */
@@ -247,10 +225,6 @@ struct named_label_list GTY(())
 
 #define named_labels cp_function_chain->x_named_labels
 \f
-/* The name of the anonymous namespace, throughout this translation
-   unit.  */
-tree anonymous_namespace_name;
-
 /* The number of function bodies which we are currently processing.
    (Zero if we are at namespace scope, one inside the body of a
    function, two inside the body of a function in a local class, etc.)  */
@@ -278,455 +252,12 @@ int adding_implicit_members = 0;
 bool have_extern_spec;
 
 \f
-/* For each binding contour we allocate a binding_level structure
-   which records the names defined in that contour.
-   Contours include:
-    0) the global one
-    1) one for each function definition,
-       where internal declarations of the parameters appear.
-    2) one for each compound statement,
-       to record its declarations.
-
-   The current meaning of a name can be found by searching the levels
-   from the current one out to the global one.
-
-   Off to the side, may be the class_binding_level.  This exists only
-   to catch class-local declarations.  It is otherwise nonexistent.
-
-   Also there may be binding levels that catch cleanups that must be
-   run when exceptions occur.  Thus, to see whether a name is bound in
-   the current scope, it is not enough to look in the
-   CURRENT_BINDING_LEVEL.  You should use lookup_name_current_level
-   instead.  */
-
-/* Note that the information in the `names' component of the global contour
-   is duplicated in the IDENTIFIER_GLOBAL_VALUEs of all identifiers.  */
-
-struct cp_binding_level GTY(())
-  {
-    /* A chain of _DECL nodes for all variables, constants, functions,
-       and typedef types.  These are in the reverse of the order
-       supplied.  There may be OVERLOADs on this list, too, but they
-       are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD.  */
-    tree names;
-
-    /* Count of elements in names chain.  */
-    size_t names_size;
-
-    /* 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 dictionary for looking up user-defined-types.  */
-    binding_table type_decls;
-
-    /* A list of USING_DECL nodes.  */
-    tree usings;
-
-    /* A list of used namespaces. PURPOSE is the namespace,
-       VALUE the common ancestor with this binding_level's namespace.  */
-    tree using_directives;
-
-    /* If this binding level is the binding level for a class, then
-       class_shadowed is a TREE_LIST.  The TREE_PURPOSE of each node
-       is the name of an entity bound in the class.  The TREE_TYPE is
-       the DECL bound by this name in the class.  */
-    tree class_shadowed;
-
-    /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
-       is used for all binding levels. In addition the TREE_VALUE is the
-       IDENTIFIER_TYPE_VALUE before we entered the class.  */
-    tree type_shadowed;
-
-    /* A TREE_LIST.  Each TREE_VALUE is the LABEL_DECL for a local
-       label in this scope.  The TREE_PURPOSE is the previous value of
-       the IDENTIFIER_LABEL VALUE.  */
-    tree shadowed_labels;
-
-    /* For each level (except not the global one),
-       a chain of BLOCK nodes for all the levels
-       that were entered and exited one level down.  */
-    tree blocks;
-
-    /* The entity (namespace, class, function) the scope of which this
-       binding contour corresponds to.  Otherwise NULL.  */
-    tree this_entity;
-
-    /* The binding level which this one is contained in (inherits from).  */
-    struct cp_binding_level *level_chain;
-
-    /* List of VAR_DECLS saved from a previous for statement.
-       These would be dead in ISO-conforming code, but might
-       be referenced in ARM-era code.  These are stored in a
-       TREE_LIST; the TREE_VALUE is the actual declaration.  */
-    tree dead_vars_from_for;
-
-    /* Binding depth at which this level began.  */
-    int binding_depth;
-
-    /* The kind of scope that this object represents.  However, a
-       SK_TEMPLATE_SPEC scope is represented with KIND set to
-       SK_TEMPALTE_PARMS and EXPLICIT_SPEC_P set to true.  */
-    enum scope_kind kind : 4;
-
-    /* True if this scope is an SK_TEMPLATE_SPEC scope.  This field is
-       only valid if KIND == SK_TEMPLATE_PARMS.  */
-    bool explicit_spec_p : 1;
-
-    /* true means make a BLOCK for this level regardless of all else.  */
-    unsigned keep : 1;
-
-    /* Nonzero if this level can safely have additional
-       cleanup-needing variables added to it.  */
-    unsigned more_cleanups_ok : 1;
-    unsigned have_cleanups : 1;
-
-    /* 22 bits left to fill a 32-bit word.  */
-  };
-
-#define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
-
-/* The binding level currently in effect.  */
-
-#define current_binding_level                  \
-  (*(cfun && cp_function_chain->bindings       \
-   ? &cp_function_chain->bindings              \
-   : &scope_chain->bindings))
-
-/* The binding level of the current class, if any.  */
-
-#define class_binding_level scope_chain->class_bindings
-
-/* A chain of binding_level structures awaiting reuse.  */
-
-static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
-
-/* true means unconditionally make a BLOCK for the next level pushed.  */
-
-static bool keep_next_level_flag;
-
 /* A TREE_LIST of VAR_DECLs.  The TREE_PURPOSE is a RECORD_TYPE or
    UNION_TYPE; the TREE_VALUE is a VAR_DECL with that type.  At the
    time the VAR_DECL was declared, the type was incomplete.  */
 
 static GTY(()) tree incomplete_vars;
-
-#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 (int depth)
-{
-  int i;
-
-  for (i = 0; i < depth * 2; i++)
-    putc (' ', stderr);
-}
-
-static tree pushdecl_with_scope        (tree, struct cp_binding_level *);
-
-/* Return a string describing the kind of SCOPE we have.  */
-static const char *
-cxx_scope_descriptor (cxx_scope *scope)
-{
-  /* The order of this table must match the "scope_kind"
-     enumerators.  */
-  static const char* scope_kind_names[] = {
-    "block-scope",
-    "cleanup-scope",
-    "try-scope",
-    "catch-scope",
-    "for-scope",
-    "function-parameter-scope",
-    "class-scope",
-    "namespace-scope",
-    "template-parameter-scope",
-    "template-explicit-spec-scope"
-  };
-  const scope_kind kind = scope->explicit_spec_p
-    ? sk_template_spec : scope->kind;
-
-  return scope_kind_names[kind];
-}
-
-/* Output a debugging information about SCOPE when performning
-   ACTION at LINE.  */
-static void
-cxx_scope_debug (cxx_scope *scope, int line, const char *action)
-{
-  const char *desc = cxx_scope_descriptor (scope);
-  if (scope->this_entity)
-    verbatim ("%s %s(%E) %p %d\n", action, desc,
-              scope->this_entity, (void *) scope, line);
-  else
-    verbatim ("%s %s %p %d\n", action, desc, (void *) scope, line);
-}
-
-/* Return the estimated initial size of the hashtable of a NAMESPACE
-   scope.  */
-
-static inline size_t
-namespace_scope_ht_size (tree ns)
-{
-  tree name = DECL_NAME (ns);
-
-  return name == std_identifier
-    ? NAMESPACE_STD_HT_SIZE
-    : (name == global_scope_name
-       ? GLOBAL_SCOPE_HT_SIZE
-       : NAMESPACE_ORDINARY_HT_SIZE);
-}
-
-/* Create a new KIND scope and make it the top of the active scopes stack.
-   ENTITY is the scope of the associated C++ entity (namespace, class,
-   function); it is NULL otherwise.  */
-
-cxx_scope *
-begin_scope (scope_kind kind, tree entity)
-{
-  cxx_scope *scope;
-  
-  /* Reuse or create a struct for this binding level.  */
-  if (!ENABLE_SCOPE_CHECKING && free_binding_level)
-    {
-      scope = free_binding_level;
-      free_binding_level = scope->level_chain;
-    }
-  else
-    scope = ggc_alloc (sizeof (cxx_scope));
-  memset (scope, 0, sizeof (cxx_scope));
-
-  scope->this_entity = entity;
-  scope->more_cleanups_ok = true;
-  switch (kind)
-    {
-    case sk_cleanup:
-      scope->keep = true;
-      break;
-      
-    case sk_template_spec:
-      scope->explicit_spec_p = true;
-      kind = sk_template_parms;
-      /* fall through */
-    case sk_template_parms:
-    case sk_block:
-    case sk_try:
-    case sk_catch:
-    case sk_for:
-    case sk_class:
-    case sk_function_parms:
-      scope->keep = keep_next_level_flag;
-      break;
-
-    case sk_namespace:
-      scope->type_decls = binding_table_new (namespace_scope_ht_size (entity));
-      NAMESPACE_LEVEL (entity) = scope;
-      VARRAY_TREE_INIT (scope->static_decls,
-                        DECL_NAME (entity) == std_identifier
-                        || DECL_NAME (entity) == global_scope_name
-                        ? 200 : 10,
-                        "Static declarations");
-      break;
-
-    default:
-      /* Should not happen.  */
-      my_friendly_assert (false, 20030922);
-      break;
-    }
-  scope->kind = kind;
-
-  /* Add it to the front of currently active scopes stack.  */
-  scope->level_chain = current_binding_level;
-  current_binding_level = scope;
-  keep_next_level_flag = false;
-
-  if (ENABLE_SCOPE_CHECKING)
-    {
-      scope->binding_depth = binding_depth;
-      indent (binding_depth);
-      cxx_scope_debug (scope, input_location.line, "push");
-      is_class_level = 0;
-      binding_depth++;
-    }
-
-  return scope;
-}
-
-/* We're about to leave current scope.  Pop the top of the stack of
-   currently active scopes.  Return the enclosing scope, now active.  */
-
-static cxx_scope *
-leave_scope (void)
-{
-  cxx_scope *scope = current_binding_level;
-
-  if (scope->kind == sk_namespace && class_binding_level)
-    current_binding_level = class_binding_level;
-
-  /* We cannot leave a scope, if there are none left.  */
-  if (NAMESPACE_LEVEL (global_namespace))
-    my_friendly_assert (!global_scope_p (scope), 20030527);
-  
-  if (ENABLE_SCOPE_CHECKING)
-    {
-      indent (--binding_depth);
-      cxx_scope_debug (scope, input_location.line, "leave");
-      if (is_class_level != (scope == class_binding_level))
-        {
-          indent (binding_depth);
-          verbatim ("XXX is_class_level != (current_scope == class_scope)\n");
-        }
-      is_class_level = 0;
-    }
-
-  /* Move one nesting level up.  */
-  current_binding_level = scope->level_chain;
-
-  /* Namespace-scopes are left most probably temporarily, not completely;
-     they can be reopen later, e.g. in namespace-extension or any name
-     binding acttivity that requires us to resume a namespace.  For other
-     scopes, we just make the structure available for reuse.  */
-  if (scope->kind != sk_namespace)
-    {
-      scope->level_chain = free_binding_level;
-      if (scope->kind == sk_class)
-        scope->type_decls = NULL;
-      else
-        binding_table_free (scope->type_decls);
-      my_friendly_assert (!ENABLE_SCOPE_CHECKING
-                          || scope->binding_depth == binding_depth,
-                          20030529);
-      free_binding_level = scope;
-    }
-
-  /* Find the innermost enclosing class scope, and reset
-     CLASS_BINDING_LEVEL appropriately.  */
-  for (scope = current_binding_level;
-       scope && scope->kind != sk_class;
-       scope = scope->level_chain)
-    ;
-  class_binding_level = scope && scope->kind == sk_class ? scope : NULL;
-
-  return current_binding_level;
-}
-
-static void
-resume_binding_level (struct cp_binding_level* b)
-{
-  /* Resuming binding levels is meant only for namespaces,
-     and those cannot nest into classes.  */
-  my_friendly_assert(!class_binding_level, 386);
-  /* 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 (ENABLE_SCOPE_CHECKING)
-    {
-      b->binding_depth = binding_depth;
-      indent (binding_depth);
-      cxx_scope_debug (b, input_location.line, "resume");
-      is_class_level = 0;
-      binding_depth++;
-    }
-}
 \f
-/* Nonzero if we are currently in the global binding level.  */
-
-int
-global_bindings_p (void)
-{
-  return global_scope_p (current_binding_level);
-}
-
-/* Return the innermost binding level that is not for a class scope.  */
-
-static struct cp_binding_level *
-innermost_nonclass_level (void)
-{
-  struct cp_binding_level *b;
-
-  b = current_binding_level;
-  while (b->kind == sk_class)
-    b = b->level_chain;
-
-  return b;
-}
-
-/* Nonzero if we are currently in a toplevel binding level.  This
-   means either the global binding level or a namespace in a toplevel
-   binding level.  Since there are no non-toplevel namespace levels,
-   this really means any namespace or template parameter level.  We
-   also include a class whose context is toplevel.  */
-
-int
-toplevel_bindings_p (void)
-{
-  struct cp_binding_level *b = innermost_nonclass_level ();
-
-  return b->kind == sk_namespace || b->kind == sk_template_parms;
-}
-
-/* Nonzero if this is a namespace scope, or if we are defining a class
-   which is itself at namespace scope, or whose enclosing class is
-   such a class, etc.  */
-
-int
-namespace_bindings_p (void)
-{
-  struct cp_binding_level *b = innermost_nonclass_level ();
-
-  return b->kind == sk_namespace;
-}
-
-/* If KEEP is true, make a BLOCK node for the next binding level,
-   unconditionally.  Otherwise, use the normal logic to decide whether
-   or not to create a BLOCK.  */
-
-void
-keep_next_level (bool keep)
-{
-  keep_next_level_flag = keep;
-}
-
-/* Nonzero if the current level needs to have a BLOCK made.  */
-
-int
-kept_level_p (void)
-{
-  return (current_binding_level->blocks != NULL_TREE
-         || current_binding_level->keep
-          || current_binding_level->kind == sk_cleanup
-         || current_binding_level->names != NULL_TREE
-         || current_binding_level->type_decls != NULL);
-}
-
-/* Returns the kind of the innermost scope.  */
-
-scope_kind
-innermost_scope_kind (void)
-{
-  return current_binding_level->kind;
-}
-
-/* Returns nonzero if this scope was created to store template
-   parameters.  */
-
-int
-template_parm_scope_p (void)
-{
-  return innermost_scope_kind () == sk_template_parms;
-}
-
 /* Returns the kind of template specialization we are currently
    processing, given that it's declaration contained N_CLASS_SCOPES
    explicit scope qualifications.  */
@@ -817,28 +348,6 @@ current_tmpl_spec_kind (int n_class_scopes)
     return innermost_specialization_p ? tsk_expl_spec : tsk_template;
 }
 
-void
-set_class_shadows (tree shadows)
-{
-  class_binding_level->class_shadowed = shadows;
-}
-
-/* We're defining an object of type TYPE.  If it needs a cleanup, but
-   we're not allowed to add any more objects with cleanups to the current
-   scope, create a new binding level.  */
-
-void
-maybe_push_cleanup_level (tree type)
-{
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
-      && current_binding_level->more_cleanups_ok == 0)
-    {
-      begin_scope (sk_cleanup, NULL);
-      clear_last_expr ();
-      add_scope_stmt (/*begin_p=*/1, /*partial_p=*/1);
-    }
-}
-
 /* Exit the current scope.  */
 
 void
@@ -847,192 +356,6 @@ finish_scope (void)
   poplevel (0, 0, 0);
 }
 
-/* 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, cxx_scope* level)
-{
-   cxx_binding *binding = cxx_binding_make (decl, NULL);
-
-  /* Now, fill in the binding information.  */
-  binding->previous = IDENTIFIER_BINDING (id);
-  binding->scope = level;
-  INHERITED_VALUE_BINDING_P (binding) = 0;
-  LOCAL_BINDING_P (binding) = (level != class_binding_level);
-
-  /* And put it on the front of the list of bindings for ID.  */
-  IDENTIFIER_BINDING (id) = binding;
-}
-
-/* Add DECL to the list of things declared in B.  */
-
-static void
-add_decl_to_level (tree decl, 
-                   struct cp_binding_level* b)
-{
-  if (TREE_CODE (decl) == NAMESPACE_DECL 
-      && !DECL_NAMESPACE_ALIAS (decl))
-    {
-      TREE_CHAIN (decl) = b->namespaces;
-      b->namespaces = decl;
-    }
-  else if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
-    {
-      TREE_CHAIN (decl) = b->vtables;
-      b->vtables = decl;
-    }
-  else       
-    {
-      /* We build up the list in reverse order, and reverse it later if
-         necessary.  */
-      TREE_CHAIN (decl) = b->names;
-      b->names = decl;
-      b->names_size++;
-
-      /* If appropriate, add decl to separate list of statics */
-      if (b->kind == sk_namespace)
-       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);
-    }
-}
-
-/* Bind DECL to ID in the current_binding_level, assumed to be a local
-   binding level.  If PUSH_USING is set in FLAGS, we know that DECL
-   doesn't really belong to this binding level, that it got here
-   through a using-declaration.  */
-
-void
-push_local_binding (tree id, tree decl, int flags)
-{
-  struct cp_binding_level *b;
-
-  /* Skip over any local classes.  This makes sense if we call
-     push_local_binding with a friend decl of a local class.  */
-  b = innermost_nonclass_level ();
-
-  if (lookup_name_current_level (id))
-    {
-      /* Supplement the existing binding.  */
-      if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
-       /* It didn't work.  Something else must be bound at this
-          level.  Do not add DECL to the list of things to pop
-          later.  */
-       return;
-    }
-  else
-    /* Create a new binding.  */
-    push_binding (id, decl, b);
-
-  if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
-    /* We must put the OVERLOAD into a TREE_LIST since the
-       TREE_CHAIN of an OVERLOAD is already used.  Similarly for
-       decls that got here through a using-declaration.  */
-    decl = build_tree_list (NULL_TREE, decl);
-
-  /* And put DECL on the list of things declared by the current
-     binding level.  */
-  add_decl_to_level (decl, b);
-}
-
-/* Bind DECL to ID in the class_binding_level.  Returns nonzero if the
-   binding was successful.  */
-
-int
-push_class_binding (tree id, tree decl)
-{
-  int result = 1;
-  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->scope == class_binding_level)
-    /* Supplement the existing binding.  */
-    result = supplement_binding (IDENTIFIER_BINDING (id), decl);
-  else
-    /* Create a new binding.  */
-    push_binding (id, decl, class_binding_level);
-
-  /* Update the IDENTIFIER_CLASS_VALUE for this ID to be the
-     class-level declaration.  Note that we do not use DECL here
-     because of the possibility of the `struct stat' hack; if DECL is
-     a class-name or enum-name we might prefer a field-name, or some
-     such.  */
-  IDENTIFIER_CLASS_VALUE (id) = IDENTIFIER_BINDING (id)->value;
-
-  /* If this is a binding from a base class, mark it as such.  */
-  binding = IDENTIFIER_BINDING (id);
-  if (binding->value == decl && TREE_CODE (decl) != TREE_LIST)
-    {
-      if (TREE_CODE (decl) == OVERLOAD)
-       context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
-      else
-       {
-         my_friendly_assert (DECL_P (decl), 0);
-         context = context_for_name_lookup (decl);
-       }
-
-      if (is_properly_derived_from (current_class_type, context))
-       INHERITED_VALUE_BINDING_P (binding) = 1;
-      else
-       INHERITED_VALUE_BINDING_P (binding) = 0;
-    }
-  else if (binding->value == decl)
-    /* We only encounter a TREE_LIST when push_class_decls detects an
-       ambiguity.  Such an ambiguity can be overridden by a definition
-       in this class.  */
-    INHERITED_VALUE_BINDING_P (binding) = 1;
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
-}
-
-/* Remove the binding for DECL which should be the innermost binding
-   for ID.  */
-
-static void
-pop_binding (tree id, tree decl)
-{
-  cxx_binding *binding;
-
-  if (id == NULL_TREE)
-    /* It's easiest to write the loops that call this function without
-       checking whether or not the entities involved have names.  We
-       get here for such an entity.  */
-    return;
-
-  /* Get the innermost binding for ID.  */
-  binding = IDENTIFIER_BINDING (id);
-
-  /* The name should be bound.  */
-  my_friendly_assert (binding != NULL, 0);
-
-  /* The DECL will be either the ordinary binding or the type
-     binding for this identifier.  Remove that binding.  */
-  if (binding->value == decl)
-    binding->value = NULL_TREE;
-  else if (binding->type == decl)
-    binding->type = NULL_TREE;
-  else
-    abort ();
-
-  if (!binding->value && !binding->type)
-    {
-      /* We're completely done with the innermost binding for this
-        identifier.  Unhook it from the list of bindings.  */
-      IDENTIFIER_BINDING (id) = binding->previous;
-
-      /* Add it to the free list.  */
-      cxx_binding_free (binding);
-    }
-}
-
 /* When a label goes out of scope, check to see if that label was used
    in a valid manner, and issue any appropriate warnings or errors.  */
 
@@ -1099,7 +422,7 @@ pop_labels (tree block)
 tree
 poplevel (int keep, int reverse, int functionbody)
 {
-  register tree link;
+  tree link;
   /* The chain of decls was accumulated in reverse order.
      Put it into forward order, just for cleanliness.  */
   tree decls;
@@ -1176,28 +499,6 @@ poplevel (int keep, int reverse, int functionbody)
   else
     decls = current_binding_level->names;
 
-  /* Output any nested inline functions within this block
-     if they weren't already output.  */
-  for (decl = decls; decl; decl = TREE_CHAIN (decl))
-    if (TREE_CODE (decl) == FUNCTION_DECL
-       && ! TREE_ASM_WRITTEN (decl)
-       && DECL_INITIAL (decl) != NULL_TREE
-       && TREE_ADDRESSABLE (decl)
-       && decl_function_context (decl) == current_function_decl)
-      {
-       /* If this decl was copied from a file-scope decl
-          on account of a block-scope extern decl,
-          propagate TREE_ADDRESSABLE to the file-scope decl.  */
-       if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
-         TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
-       else
-         {
-           push_function_context ();
-           output_inline_function (decl);
-           pop_function_context ();
-         }
-      }
-
   /* When not in function-at-a-time mode, expand_end_bindings will
      warn about unused variables.  But, in function-at-a-time mode
      expand_end_bindings is not passed the list of variables in the
@@ -1443,141 +744,30 @@ set_block (tree block ATTRIBUTE_UNUSED )
      but it is not applicable in function-at-a-time mode.  */
 }
 
-/* Do a pushlevel for class declarations.  */
+/* Returns nonzero if T is a virtual function table.  */
 
-void
-pushlevel_class (void)
+int
+vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
 {
-  if (ENABLE_SCOPE_CHECKING)
-    is_class_level = 1;
-
-  class_binding_level = begin_scope (sk_class, current_class_type);
+  return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
 }
 
-/* ...and a poplevel for class declarations.  */
+/* Returns nonzero if T is a TYPE_DECL for a type with virtual
+   functions.  */
 
-void
-poplevel_class (void)
+int
+vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
 {
-  register struct cp_binding_level *level = class_binding_level;
-  tree shadowed;
+  return (TREE_CODE (t) == TYPE_DECL
+         && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
+         && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
+}
 
-  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
-     of IDENTIFIER_CLASS_VALUE to NULL_TREE, since first of all this slot
-     shouldn't even be used when current_class_type isn't set, and second,
-     if we don't touch it here, we're able to use the cache effect if the
-     next time we're entering a class scope, it is the same class.  */
-  if (current_class_depth != 1)
-    {
-      struct cp_binding_level* b;
-
-      /* Clear out our IDENTIFIER_CLASS_VALUEs.  */
-      for (shadowed = level->class_shadowed;
-          shadowed;
-          shadowed = TREE_CHAIN (shadowed))
-       IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
-
-      /* Find the next enclosing class, and recreate
-        IDENTIFIER_CLASS_VALUEs appropriate for that class.  */
-      b = level->level_chain;
-      while (b && b->kind != sk_class)
-       b = b->level_chain;
-
-      if (b)
-       for (shadowed = b->class_shadowed;
-            shadowed;
-            shadowed = TREE_CHAIN (shadowed))
-         {
-           cxx_binding *binding;
-            
-           binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
-           while (binding && binding->scope != b)
-             binding = binding->previous;
-
-           if (binding)
-             IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
-               = binding->value;
-         }
-    }
-  else
-    /* Remember to save what IDENTIFIER's were bound in this scope so we
-       can recover from cache misses.  */
-    {
-      previous_class_type = current_class_type;
-      previous_class_values = class_binding_level->class_shadowed;
-    }
-  for (shadowed = level->type_shadowed;
-       shadowed;
-       shadowed = TREE_CHAIN (shadowed))
-    SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
-
-  /* Remove the bindings for all of the class-level declarations.  */
-  for (shadowed = level->class_shadowed;
-       shadowed;
-       shadowed = TREE_CHAIN (shadowed))
-    pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
-
-  /* Now, pop out of the binding level which we created up in the
-     `pushlevel_class' routine.  */
-  if (ENABLE_SCOPE_CHECKING)
-    is_class_level = 1;
-
-  leave_scope ();
-  timevar_pop (TV_NAME_LOOKUP);
-}
-
-/* We are entering the scope of a class.  Clear IDENTIFIER_CLASS_VALUE
-   for any names in enclosing classes.  */
-
-void
-clear_identifier_class_values (void)
-{
-  tree t;
-
-  if (!class_binding_level)
-    return;
-
-  for (t = class_binding_level->class_shadowed;
-       t;
-       t = TREE_CHAIN (t))
-    IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
-}
-
-/* Returns nonzero if T is a virtual function table.  */
-
-int
-vtable_decl_p (tree t, void* data ATTRIBUTE_UNUSED )
-{
-  return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
-}
-
-/* Returns nonzero if T is a TYPE_DECL for a type with virtual
-   functions.  */
-
-int
-vtype_decl_p (tree t, void *data ATTRIBUTE_UNUSED )
-{
-  return (TREE_CODE (t) == TYPE_DECL
-         && TREE_CODE (TREE_TYPE (t)) == RECORD_TYPE
-         && TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
-}
-
-/* Return the declarations that are members of the namespace NS.  */
-
-tree
-cp_namespace_decls (tree ns)
-{
-  return NAMESPACE_LEVEL (ns)->names;
-}
-
-struct walk_globals_data {
-  walk_globals_pred p;
-  walk_globals_fn f;
-  void *data;
-};
+struct walk_globals_data {
+  walk_globals_pred p;
+  walk_globals_fn f;
+  void *data;
+};
 
 /* Walk the vtable declarations in NAMESPACE.  Whenever one is found
    for which P returns nonzero, call F with its address.  If any call
@@ -1709,2686 +899,1018 @@ wrapup_globals_for_namespace (tree namespace, void* data)
 }
 
 \f
-/* For debugging.  */
-static int no_print_functions = 0;
-static int no_print_builtins = 0;
+/* In C++, you don't have to write `struct S' to refer to `S'; you
+   can just use `S'.  We accomplish this by creating a TYPE_DECL as
+   if the user had written `typedef struct S S'.  Create and return
+   the TYPE_DECL for TYPE.  */
 
-/* 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)
+tree
+create_implicit_typedef (tree name, tree type)
 {
-  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;
+  tree decl;
 
-  *p += len;
+  decl = build_decl (TYPE_DECL, name, type);
+  DECL_ARTIFICIAL (decl) = 1;
+  /* There are other implicit type declarations, like the one *within*
+     a class that allows you to write `S::S'.  We must distinguish
+     amongst these.  */
+  SET_DECL_IMPLICIT_TYPEDEF_P (decl);
+  TYPE_NAME (type) = decl;
 
-  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, ">");
-    }
+  return decl;
 }
 
-void
-print_binding_level (struct cp_binding_level* lvl)
+/* Remember a local name for name-mangling purposes.  */
+
+static void
+push_local_name (tree decl)
 {
-  tree t;
-  int i = 0, len;
-  fprintf (stderr, " blocks=" HOST_PTR_PRINTF, (void *) lvl->blocks);
-  if (lvl->more_cleanups_ok)
-    fprintf (stderr, " more-cleanups-ok");
-  if (lvl->have_cleanups)
-    fprintf (stderr, " have-cleanups");
-  fprintf (stderr, "\n");
-  if (lvl->names)
-    {
-      fprintf (stderr, " names:\t");
-      /* We can probably fit 3 names to a line?  */
-      for (t = lvl->names; t; t = TREE_CHAIN (t))
-       {
-         if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL))
-           continue;
-         if (no_print_builtins
-             && (TREE_CODE (t) == TYPE_DECL)
-             && (!strcmp (DECL_SOURCE_FILE (t),"<built-in>")))
-           continue;
+  size_t i, nelts;
+  tree t, name;
 
-         /* Function decls tend to have longer names.  */
-         if (TREE_CODE (t) == FUNCTION_DECL)
-           len = 3;
-         else
-           len = 2;
-         i += len;
-         if (i > 6)
-           {
-             fprintf (stderr, "\n\t");
-             i = len;
-           }
-         print_node_brief (stderr, "", t, 0);
-         if (t == error_mark_node)
-           break;
-       }
-      if (i)
-        fprintf (stderr, "\n");
-    }
-  if (lvl->type_decls)
-    {
-      fprintf (stderr, " tags:\t");
-      i = 0;
-      binding_table_foreach (lvl->type_decls, bt_print_entry, &i);
-      if (i)
-       fprintf (stderr, "\n");
-    }
-  if (lvl->class_shadowed)
+  timevar_push (TV_NAME_LOOKUP);
+  if (!local_names)
+    VARRAY_TREE_INIT (local_names, 8, "local_names");
+
+  name = DECL_NAME (decl);
+
+  nelts = VARRAY_ACTIVE_SIZE (local_names);
+  for (i = 0; i < nelts; i++)
     {
-      fprintf (stderr, " class-shadowed:");
-      for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t))
+      t = VARRAY_TREE (local_names, i);
+      if (DECL_NAME (t) == name)
        {
-         fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
+         if (!DECL_LANG_SPECIFIC (decl))
+           retrofit_lang_decl (decl);
+         DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
+         if (DECL_LANG_SPECIFIC (t))
+           DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
+         else
+           DECL_DISCRIMINATOR (decl) = 1;
+
+         VARRAY_TREE (local_names, i) = decl;
+         timevar_pop (TV_NAME_LOOKUP);
+         return;
        }
-      fprintf (stderr, "\n");
-    }
-  if (lvl->type_shadowed)
-    {
-      fprintf (stderr, " type-shadowed:");
-      for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t))
-        {
-         fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-        }
-      fprintf (stderr, "\n");
     }
-}
 
-void
-print_other_binding_stack (struct cp_binding_level *stack)
-{
-  struct cp_binding_level *level;
-  for (level = stack; !global_scope_p (level); level = level->level_chain)
-    {
-      fprintf (stderr, "binding level " HOST_PTR_PRINTF "\n", (void *) level);
-      print_binding_level (level);
-    }
+  VARRAY_PUSH_TREE (local_names, decl);
+  timevar_pop (TV_NAME_LOOKUP);
 }
+\f
+/* Subroutine of duplicate_decls: return truthvalue of whether
+   or not types of these decls match.
 
-void
-print_binding_stack (void)
+   For C++, we must compare the parameter list so that `int' can match
+   `int&' in a parameter position, but `int&' is not confused with
+   `const int&'.  */
+
+int
+decls_match (tree newdecl, tree olddecl)
 {
-  struct cp_binding_level *b;
-  fprintf (stderr, "current_binding_level=" HOST_PTR_PRINTF
-          "\nclass_binding_level=" HOST_PTR_PRINTF
-          "\nNAMESPACE_LEVEL (global_namespace)=" HOST_PTR_PRINTF "\n",
-          (void *) current_binding_level, (void *) class_binding_level,
-           (void *) NAMESPACE_LEVEL (global_namespace));
-  if (class_binding_level)
-    {
-      for (b = class_binding_level; b; b = b->level_chain)
-       if (b == current_binding_level)
-         break;
-      if (b)
-       b = class_binding_level;
-      else
-       b = current_binding_level;
-    }
-  else
-    b = current_binding_level;
-  print_other_binding_stack (b);
-  fprintf (stderr, "global:\n");
-  print_binding_level (NAMESPACE_LEVEL (global_namespace));
-}
+  int types_match;
 
-/* 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.  */
+  if (newdecl == olddecl)
+    return 1;
 
-/* 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.  */
+  if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
+    /* If the two DECLs are not even the same kind of thing, we're not
+       interested in their types.  */
+    return 0;
 
-void
-push_namespace (tree name)
-{
-  tree d = NULL_TREE;
-  int need_new = 1;
-  int implicit_use = 0;
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      tree f1 = TREE_TYPE (newdecl);
+      tree f2 = TREE_TYPE (olddecl);
+      tree p1 = TYPE_ARG_TYPES (f1);
+      tree p2 = TYPE_ARG_TYPES (f2);
 
-  timevar_push (TV_NAME_LOOKUP);
-  
-  /* We should not get here if the global_namespace is not yet constructed
-     nor if NAME designates the global namespace:  The global scope is
-     constructed elsewhere.  */
-  my_friendly_assert (global_namespace != NULL && name != global_scope_name,
-                      20030531);
-
-  if (!name)
-    {
-      /* The name of anonymous namespace is unique for the translation
-         unit.  */
-      if (!anonymous_namespace_name)
-        anonymous_namespace_name = get_file_function_name ('N');
-      name = anonymous_namespace_name;
-      d = IDENTIFIER_NAMESPACE_VALUE (name);
-      if (d)
-        /* Reopening anonymous namespace.  */
-        need_new = 0;
-      implicit_use = 1;
+      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
+         && ! (DECL_EXTERN_C_P (newdecl)
+               && DECL_EXTERN_C_P (olddecl)))
+       return 0;
+
+      if (TREE_CODE (f1) != TREE_CODE (f2))
+        return 0;
+
+      if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+       {
+         if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
+             && (DECL_BUILT_IN (olddecl)
+#ifndef NO_IMPLICIT_EXTERN_C
+                 || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
+                 || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
+#endif
+             ))
+           {
+             types_match = self_promoting_args_p (p1);
+             if (p1 == void_list_node)
+               TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+           }
+#ifndef NO_IMPLICIT_EXTERN_C
+         else if (p1 == NULL_TREE
+                  && (DECL_EXTERN_C_P (olddecl)
+                      && DECL_IN_SYSTEM_HEADER (olddecl)
+                      && !DECL_CLASS_SCOPE_P (olddecl))
+                  && (DECL_EXTERN_C_P (newdecl)
+                      && DECL_IN_SYSTEM_HEADER (newdecl)
+                      && !DECL_CLASS_SCOPE_P (newdecl)))
+           {
+             types_match = self_promoting_args_p (p2);
+             TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
+           }
+#endif
+         else
+           types_match = compparms (p1, p2);
+       }
+      else
+       types_match = 0;
     }
-  else
+  else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      /* Check whether this is an extended namespace definition.  */
-      d = IDENTIFIER_NAMESPACE_VALUE (name);
-      if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
-        {
-          need_new = 0;
-          if (DECL_NAMESPACE_ALIAS (d))
-            {
-              error ("namespace alias `%D' not allowed here, assuming `%D'",
-                        d, DECL_NAMESPACE_ALIAS (d));
-              d = DECL_NAMESPACE_ALIAS (d);
-            }
-        }
-    }
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
+         != TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
+       return 0;
 
-  if (need_new)
-    {
-      /* Make a new namespace, binding the name to it.  */
-      d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
-      DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
-      d = pushdecl (d);
-      begin_scope (sk_namespace, d);
+      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+                               DECL_TEMPLATE_PARMS (olddecl)))
+       return 0;
+
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+       types_match = same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)),
+                                  TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)));
+      else
+       types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
+                                  DECL_TEMPLATE_RESULT (newdecl));
     }
   else
-    resume_binding_level (NAMESPACE_LEVEL (d));
-
-  if (implicit_use)
-    do_using_directive (d);
-  /* Enter the name space.  */
-  current_namespace = d;
+    {
+      if (TREE_TYPE (newdecl) == error_mark_node)
+       types_match = TREE_TYPE (olddecl) == error_mark_node;
+      else if (TREE_TYPE (olddecl) == NULL_TREE)
+       types_match = TREE_TYPE (newdecl) == NULL_TREE;
+      else if (TREE_TYPE (newdecl) == NULL_TREE)
+       types_match = 0;
+      else
+       types_match = comptypes (TREE_TYPE (newdecl),
+                                TREE_TYPE (olddecl),
+                                COMPARE_REDECLARATION);
+    }
 
-  timevar_pop (TV_NAME_LOOKUP);
+  return types_match;
 }
 
-/* Pop from the scope of the current namespace.  */
+/* If NEWDECL is `static' and an `extern' was seen previously,
+   warn about it.  OLDDECL is the previous declaration.
 
-void
-pop_namespace (void)
-{
-  my_friendly_assert (current_namespace != global_namespace, 20010801);
-  current_namespace = CP_DECL_CONTEXT (current_namespace);
-  /* The binding level is not popped, as it might be re-opened later.  */
-  leave_scope ();
-}
+   Note that this does not apply to the C++ case of declaring
+   a variable `extern const' and then later `const'.
 
-/* Push into the scope of the namespace NS, even if it is deeply
-   nested within another namespace.  */
+   Don't complain about built-in functions, since they are beyond
+   the user's control.  */
 
 void
-push_nested_namespace (tree ns)
+warn_extern_redeclared_static (tree newdecl, tree olddecl)
 {
-  if (ns == global_namespace)
-    push_to_top_level ();
-  else
-    {
-      push_nested_namespace (CP_DECL_CONTEXT (ns));
-      push_namespace (DECL_NAME (ns));
-    }
-}
-
-/* Pop back from the scope of the namespace NS, which was previously
-   entered with push_nested_namespace.  */
+  tree name;
 
-void
-pop_nested_namespace (tree ns)
-{
-  timevar_push (TV_NAME_LOOKUP);
-  while (ns != global_namespace)
-    {
-      pop_namespace ();
-      ns = CP_DECL_CONTEXT (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;
-};
+  if (TREE_CODE (newdecl) == TYPE_DECL
+      || TREE_CODE (newdecl) == TEMPLATE_DECL
+      || TREE_CODE (newdecl) == CONST_DECL
+      || TREE_CODE (newdecl) == NAMESPACE_DECL)
+    return;
 
-/* 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
-   are at all visible.  Simply setting current_binding_level to the global
-   scope isn't enough, because more binding levels may be pushed.  */
-struct saved_scope *scope_chain;
+  /* Don't get confused by static member functions; that's a different
+     use of `static'.  */
+  if (TREE_CODE (newdecl) == FUNCTION_DECL
+      && DECL_STATIC_FUNCTION_P (newdecl))
+    return;
 
-static cxx_saved_binding *
-store_bindings (tree names, cxx_saved_binding *old_bindings)
-{
-  tree t;
-  cxx_saved_binding *search_bindings = old_bindings;
+  /* If the old declaration was `static', or the new one isn't, then
+     then everything is OK.  */
+  if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
+    return;
 
-  timevar_push (TV_NAME_LOOKUP);
-  for (t = names; t; t = TREE_CHAIN (t))
-    {
-      tree id;
-      cxx_saved_binding *saved;
-      cxx_saved_binding *t1;
+  /* It's OK to declare a builtin function as `static'.  */
+  if (TREE_CODE (olddecl) == FUNCTION_DECL
+      && DECL_ARTIFICIAL (olddecl))
+    return;
 
-      if (TREE_CODE (t) == TREE_LIST)
-       id = TREE_PURPOSE (t);
-      else
-       id = DECL_NAME (t);
-
-      if (!id
-         /* Note that we may have an IDENTIFIER_CLASS_VALUE even when
-            we have no IDENTIFIER_BINDING if we have left the class
-            scope, but cached the class-level declarations.  */
-         || !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
-       continue;
-
-      for (t1 = search_bindings; t1; t1 = t1->previous)
-       if (t1->identifier == id)
-         goto skip_it;
-
-      my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
-      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;
-      old_bindings = saved;
-    skip_it:
-      ;
-    }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
+  name = DECL_ASSEMBLER_NAME (newdecl);
+  pedwarn ("`%D' was declared `extern' and later `static'", newdecl);
+  cp_pedwarn_at ("previous declaration of `%D'", olddecl);
 }
 
-void
-maybe_push_to_top_level (int pseudo)
-{
-  struct saved_scope *s;
-  struct cp_binding_level *b;
-  cxx_saved_binding *old_bindings;
-  int need_pop;
-
-  timevar_push (TV_NAME_LOOKUP);
-  s = ggc_alloc_cleared (sizeof (struct saved_scope));
-
-  b = scope_chain ? current_binding_level : 0;
-
-  /* If we're in the middle of some function, save our state.  */
-  if (cfun)
-    {
-      need_pop = 1;
-      push_function_context_to (NULL_TREE);
-    }
-  else
-    need_pop = 0;
-
-  old_bindings = NULL;
-  if (scope_chain && previous_class_type)
-    old_bindings = store_bindings (previous_class_values, old_bindings);
-
-  /* Have to include the global scope, because class-scope decls
-     aren't listed anywhere useful.  */
-  for (; b; b = b->level_chain)
-    {
-      tree t;
-
-      /* Template IDs are inserted into the global level. If they were
-        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 (global_scope_p (b) || (pseudo && b->kind == sk_template_parms))
-       break;
-
-      old_bindings = store_bindings (b->names, old_bindings);
-      /* We also need to check class_shadowed to save class-level type
-        bindings, since pushclass doesn't fill in b->names.  */
-      if (b->kind == sk_class)
-       old_bindings = store_bindings (b->class_shadowed, old_bindings);
+/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
+   If the redeclaration is invalid, a diagnostic is issued, and the
+   error_mark_node is returned.  Otherwise, OLDDECL is returned.
 
-      /* Unwind type-value slots back to top level.  */
-      for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
-       SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
-    }
-  s->prev = scope_chain;
-  s->old_bindings = old_bindings;
-  s->bindings = b;
-  s->need_pop_function_context = need_pop;
-  s->function_decl = current_function_decl;
-  s->last_parms = last_function_parms;
-
-  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);
-}
+   If NEWDECL is not a redeclaration of OLDDECL, NULL_TREE is
+   returned.  */
 
-void
-push_to_top_level (void)
+tree
+duplicate_decls (tree newdecl, tree olddecl)
 {
-  maybe_push_to_top_level (0);
-}
+  unsigned olddecl_uid = DECL_UID (olddecl);
+  int olddecl_friend = 0, types_match = 0;
+  int new_defines_function = 0;
 
-void
-pop_from_top_level (void)
-{
-  struct saved_scope *s = scope_chain;
-  cxx_saved_binding *saved;
+  if (newdecl == olddecl)
+    return olddecl;
 
-  timevar_push (TV_NAME_LOOKUP); 
-  /* Clear out class-level bindings cache.  */
-  if (previous_class_type)
-    invalidate_class_lookup_cache ();
+  types_match = decls_match (newdecl, olddecl);
 
-  current_lang_base = 0;
+  /* If either the type of the new decl or the type of the old decl is an
+     error_mark_node, then that implies that we have already issued an
+     error (earlier) for some bogus type specification, and in that case,
+     it is rather pointless to harass the user with yet more error message
+     about the same declaration, so just pretend the types match here.  */
+  if (TREE_TYPE (newdecl) == error_mark_node
+      || TREE_TYPE (olddecl) == error_mark_node)
+    types_match = 1;
 
-  scope_chain = s->prev;
-  for (saved = s->old_bindings; saved; saved = saved->previous)
+  if (DECL_P (olddecl)
+      && TREE_CODE (newdecl) == FUNCTION_DECL
+      && TREE_CODE (olddecl) == FUNCTION_DECL
+      && (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
     {
-      tree id = saved->identifier;
-
-      IDENTIFIER_BINDING (id) = saved->binding;
-      IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
-      SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
+      if (DECL_DECLARED_INLINE_P (newdecl)
+         && DECL_UNINLINABLE (newdecl)
+         && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+       /* Already warned elsewhere.  */;
+      else if (DECL_DECLARED_INLINE_P (olddecl)
+              && DECL_UNINLINABLE (olddecl)
+              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+       /* Already warned.  */;
+      else if (DECL_DECLARED_INLINE_P (newdecl)
+              && DECL_UNINLINABLE (olddecl)
+              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
+       {
+         warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
+         warning ("%Jprevious declaration of '%D' with attribute noinline",
+                   olddecl, olddecl);
+       }
+      else if (DECL_DECLARED_INLINE_P (olddecl)
+              && DECL_UNINLINABLE (newdecl)
+              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
+       {
+         warning ("%Jfunction '%D' redeclared with attribute noinline",
+                  newdecl, newdecl);
+         warning ("%Jprevious declaration of '%D' was inline",
+                  olddecl, olddecl);
+       }
     }
 
-  /* If we were in the middle of compiling a function, restore our
-     state.  */
-  if (s->need_pop_function_context)
-    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 named ID.  into
-   binding_level B.  DECL is a TYPE_DECL for the type.  We assume that
-   the tag ID is not already defined.  */
-
-static void
-set_identifier_type_value_with_scope (tree id, 
-                                      tree decl,
-                                      struct cp_binding_level* b)
-{
-  tree type;
-
-  if (b->kind != sk_namespace)
-    {
-      /* Shadow the marker, not the real thing, so that the marker
-        gets restored later.  */
-      tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
-      b->type_shadowed
-       = tree_cons (id, old_type_value, b->type_shadowed);
-      type = decl ? TREE_TYPE (decl) : NULL_TREE;
-    }
-  else
+  /* Check for redeclaration and other discrepancies.  */
+  if (TREE_CODE (olddecl) == FUNCTION_DECL
+      && DECL_ARTIFICIAL (olddecl))
     {
-      cxx_binding *binding =
-       binding_for_name (NAMESPACE_LEVEL (current_namespace), id);
-      if (decl)
+      if (TREE_CODE (newdecl) != FUNCTION_DECL)
        {
-         if (binding->value)
-           supplement_binding (binding, decl);
+          /* Avoid warnings redeclaring anticipated built-ins.  */
+          if (DECL_ANTICIPATED (olddecl))
+            return NULL_TREE;
+
+         /* If you declare a built-in or predefined function name as static,
+            the old definition is overridden, but optionally warn this was a
+            bad choice of name.  */
+         if (! TREE_PUBLIC (newdecl))
+           {
+             if (warn_shadow)
+               warning ("shadowing %s function `%#D'",
+                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+                           olddecl);
+             /* Discard the old built-in function.  */
+             return NULL_TREE;
+           }
+         /* If the built-in is not ansi, then programs can override
+            it even globally without an error.  */
+         else if (! DECL_BUILT_IN (olddecl))
+           warning ("library function `%#D' redeclared as non-function `%#D'",
+                       olddecl, newdecl);
          else
-           binding->value = decl;
+           {
+             error ("declaration of `%#D'", newdecl);
+             error ("conflicts with built-in declaration `%#D'",
+                       olddecl);
+           }
+         return NULL_TREE;
        }
-      else
-       abort ();
-      /* Store marker instead of real type.  */
-      type = global_type_node;
-    }
-  SET_IDENTIFIER_TYPE_VALUE (id, type);
-}
-
-/* As set_identifier_type_value_with_scope, but using current_binding_level.  */
+      else if (!types_match)
+       {
+          /* Avoid warnings redeclaring anticipated built-ins.  */
+          if (DECL_ANTICIPATED (olddecl))
+            ;  /* Do nothing yet.  */
+         else if ((DECL_EXTERN_C_P (newdecl)
+                   && DECL_EXTERN_C_P (olddecl))
+                  || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+                                TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
+           {
+             /* A near match; override the builtin.  */
 
-void
-set_identifier_type_value (tree id, tree decl)
-{
-  set_identifier_type_value_with_scope (id, decl, current_binding_level);
-}
+             if (TREE_PUBLIC (newdecl))
+               {
+                 warning ("new declaration `%#D'", newdecl);
+                 warning ("ambiguates built-in declaration `%#D'",
+                             olddecl);
+               }
+             else if (warn_shadow)
+               warning ("shadowing %s function `%#D'",
+                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
+                           olddecl);
+           }
+         else
+           /* Discard the old built-in function.  */
+           return NULL_TREE;
 
-/* Return the type associated with id.  */
+         /* 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 = TREE_TYPE (newdecl);
+         tree attribs = (*targetm.merge_type_attributes)
+           (TREE_TYPE (olddecl), 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)
-    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)
-    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)
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-}
+         type = cp_build_type_attribute_variant (type, attribs);
+         TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = type;
+       }
 
-/* Pop off extraneous binding levels left over due to syntax errors.
+      /* Whether or not the builtin can throw exceptions has no
+        bearing on this declarator.  */
+      TREE_NOTHROW (olddecl) = 0;
 
-   We don't pop past namespaces, as they might be valid.  */
+      if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
+       {
+         /* If a builtin function is redeclared as `static', merge
+            the declarations, but make the original one static.  */
+         DECL_THIS_STATIC (olddecl) = 1;
+         TREE_PUBLIC (olddecl) = 0;
 
-void
-pop_everything (void)
-{
-  if (ENABLE_SCOPE_CHECKING)
-    verbatim ("XXX entering pop_everything ()\n");
-  while (!toplevel_bindings_p ())
-    {
-      if (current_binding_level->kind == sk_class)
-       pop_nested_class ();
-      else
-       poplevel (0, 0, 0);
+         /* Make the old declaration consistent with the new one so
+            that all remnants of the builtin-ness of this function
+            will be banished.  */
+         SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
+         SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
+       }
     }
-  if (ENABLE_SCOPE_CHECKING)
-    verbatim ("XXX leaving pop_everything ()\n");
-}
-
-/* The type TYPE is being declared.  If it is a class template, or a
-   specialization of a class template, do any processing required and
-   perform error-checking.  If IS_FRIEND is nonzero, this TYPE is
-   being declared a friend.  B is the binding level at which this TYPE
-   should be bound.
-
-   Returns the TYPE_DECL for TYPE, which may have been altered by this
-   processing.  */
-
-static tree
-maybe_process_template_type_declaration (tree type, 
-                                         int globalize, 
-                                         struct cp_binding_level* b)
-{
-  tree decl = TYPE_NAME (type);
-
-  if (processing_template_parmlist)
-    /* You can't declare a new template type in a template parameter
-       list.  But, you can declare a non-template type:
-
-         template <class A*> struct S;
-
-       is a forward-declaration of `A'.  */
-    ;
-  else
+  else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
     {
-      maybe_check_template_type (type);
-
-      my_friendly_assert (IS_AGGR_TYPE (type)
-                         || TREE_CODE (type) == ENUMERAL_TYPE, 0);
-
-
-      if (processing_template_decl)
+      if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
+          && TREE_CODE (newdecl) != TYPE_DECL
+          && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
+                && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
+         || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
+             && TREE_CODE (olddecl) != TYPE_DECL
+             && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
+                   && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
+                       == TYPE_DECL))))
        {
-         /* This may change after the call to
-            push_template_decl_real, but we want the original value.  */
-         tree name = DECL_NAME (decl);
-
-         decl = push_template_decl_real (decl, globalize);
-         /* If the current binding level is the binding level for the
-            template parameters (see the comment in
-            begin_template_parm_list) and the enclosing level is a class
-            scope, and we're not looking at a friend, push the
-            declaration of the member class into the class scope.  In the
-            friend case, push_template_decl will already have put the
-            friend into global scope, if appropriate.  */
-         if (TREE_CODE (type) != ENUMERAL_TYPE
-             && !globalize && b->kind == sk_template_parms
-             && b->level_chain->kind == sk_class)
-           {
-             finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
-             /* 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.  */
-              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_NESTED_UTDS (current_class_type) =
-                    b->level_chain->type_decls;
-               }
-           }
+         /* We do nothing special here, because C++ does such nasty
+            things with TYPE_DECLs.  Instead, just let the TYPE_DECL
+            get shadowed, and know that if we need to find a TYPE_DECL
+            for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+            slot of the identifier.  */
+         return NULL_TREE;
        }
-    }
 
-  return decl;
-}
-
-/* In C++, you don't have to write `struct S' to refer to `S'; you
-   can just use `S'.  We accomplish this by creating a TYPE_DECL as
-   if the user had written `typedef struct S S'.  Create and return
-   the TYPE_DECL for TYPE.  */
-
-tree
-create_implicit_typedef (tree name, tree type)
-{
-  tree decl;
-
-  decl = build_decl (TYPE_DECL, name, type);
-  DECL_ARTIFICIAL (decl) = 1;
-  /* There are other implicit type declarations, like the one *within*
-     a class that allows you to write `S::S'.  We must distinguish
-     amongst these.  */
-  SET_DECL_IMPLICIT_TYPEDEF_P (decl);
-  TYPE_NAME (type) = decl;
-
-  return decl;
-}
-
-/* Remember a local name for name-mangling purposes.  */
-
-static void
-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");
-
-  name = DECL_NAME (decl);
-
-  nelts = VARRAY_ACTIVE_SIZE (local_names);
-  for (i = 0; i < nelts; i++)
-    {
-      t = VARRAY_TREE (local_names, i);
-      if (DECL_NAME (t) == name)
-       {
-         if (!DECL_LANG_SPECIFIC (decl))
-           retrofit_lang_decl (decl);
-         DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
-         if (DECL_LANG_SPECIFIC (t))
-           DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
-         else
-           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.
-   Normally put it into the inner-most non-sk_cleanup scope,
-   but if GLOBALIZE is true, put it in the inner-most non-class scope.
-   The latter is needed for implicit declarations.  */
-
-void
-pushtag (tree name, tree type, int globalize)
-{
-  register struct cp_binding_level *b;
-
-  timevar_push (TV_NAME_LOOKUP);
-  b = current_binding_level;
-  while (b->kind == sk_cleanup
-        || (b->kind == sk_class
-            && (globalize
-                /* We may be defining a new type in the initializer
-                   of a static member variable. We allow this when
-                   not pedantic, and it is particularly useful for
-                   type punning via an anonymous union.  */
-                || COMPLETE_TYPE_P (b->this_entity))))
-    b = b->level_chain;
-
-  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)
-    {
-      /* Do C++ gratuitous typedefing.  */
-      if (IDENTIFIER_TYPE_VALUE (name) != type)
-        {
-          register tree d = NULL_TREE;
-         int in_class = 0;
-         tree context = TYPE_CONTEXT (type);
-
-         if (! context)
-           {
-             tree cs = current_scope ();
-
-             if (! globalize)
-               context = cs;
-             else if (cs != NULL_TREE && TYPE_P (cs))
-               /* When declaring a friend class of a local class, we want
-                  to inject the newly named class into the scope
-                  containing the local class, not the namespace scope.  */
-               context = decl_function_context (get_type_decl (cs));
-           }
-         if (!context)
-           context = current_namespace;
-
-         if (b->kind == sk_class
-             || (b->kind == sk_template_parms 
-                 && b->level_chain->kind == sk_class))
-           in_class = 1;
-
-         if (current_lang_name == lang_name_java)
-           TYPE_FOR_JAVA (type) = 1;
-
-         d = create_implicit_typedef (name, type);
-         DECL_CONTEXT (d) = FROB_CONTEXT (context);
-         if (! in_class)
-           set_identifier_type_value_with_scope (name, d, b);
-
-         d = maybe_process_template_type_declaration (type,
-                                                      globalize, b);
-
-         if (b->kind == sk_class)
-           {
-             if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
-               /* Put this TYPE_DECL on the TYPE_FIELDS list for the
-                  class.  But if it's a member template class, we
-                  want the TEMPLATE_DECL, not the TYPE_DECL, so this
-                  is done later.  */
-               finish_member_declaration (d);
-             else
-               pushdecl_class_level (d);
-           }
-         else
-           d = pushdecl_with_scope (d, b);
-
-         /* FIXME what if it gets a name from typedef?  */
-         if (ANON_AGGRNAME_P (name))
-           DECL_IGNORED_P (d) = 1;
-
-         TYPE_CONTEXT (type) = DECL_CONTEXT (d);
-
-         /* If this is a local class, keep track of it.  We need this
-            information for name-mangling, and so that it is possible to find
-            all function definitions in a translation unit in a convenient
-            way.  (It's otherwise tricky to find a member function definition
-            it's only pointed to from within a local class.)  */
-         if (TYPE_CONTEXT (type)
-             && TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL
-             && !processing_template_decl)
-           VARRAY_PUSH_TREE (local_classes, type);
-        }
-      if (b->kind == sk_class
-         && !COMPLETE_TYPE_P (current_class_type))
-       {
-         maybe_add_class_template_decl_list (current_class_type,
-                                             type, /*friend_p=*/0);
-         CLASSTYPE_NESTED_UTDS (current_class_type) = b->type_decls;
-       }
-    }
-
-  if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
-    /* Use the canonical TYPE_DECL for this node.  */
-    TYPE_STUB_DECL (type) = TYPE_NAME (type);
-  else
-    {
-      /* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE
-        will be the tagged type we just added to the current
-        binding level.  This fake NULL-named TYPE_DECL node helps
-        dwarfout.c to know when it needs to output a
-        representation of a tagged type, and it also gives us a
-        convenient place to record the "scope start" address for
-        the tagged type.  */
-
-      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.  */
-
-static GTY(()) int anon_cnt;
-
-/* Return an IDENTIFIER which can be used as a name for
-   anonymous structs and unions.  */
-
-tree
-make_anon_name (void)
-{
-  char buf[32];
-
-  sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++);
-  return get_identifier (buf);
-}
-
-/* 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;
-  static int last_cnt = 0;
-
-  /* Fast out if no new anon names were declared.  */
-  if (last_cnt == anon_cnt)
-    return;
-
-  b = current_binding_level;
-  while (b->kind == sk_cleanup)
-    b = b->level_chain;
-  if (b->type_decls != NULL)
-    binding_table_remove_anonymous_types (b->type_decls);
-  last_cnt = anon_cnt;
-}
-\f
-/* Subroutine of duplicate_decls: return truthvalue of whether
-   or not types of these decls match.
-
-   For C++, we must compare the parameter list so that `int' can match
-   `int&' in a parameter position, but `int&' is not confused with
-   `const int&'.  */
-
-int
-decls_match (tree newdecl, tree olddecl)
-{
-  int types_match;
-
-  if (newdecl == olddecl)
-    return 1;
-
-  if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
-    /* If the two DECLs are not even the same kind of thing, we're not
-       interested in their types.  */
-    return 0;
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      tree f1 = TREE_TYPE (newdecl);
-      tree f2 = TREE_TYPE (olddecl);
-      tree p1 = TYPE_ARG_TYPES (f1);
-      tree p2 = TYPE_ARG_TYPES (f2);
-
-      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
-         && ! (DECL_EXTERN_C_P (newdecl)
-               && DECL_EXTERN_C_P (olddecl)))
-       return 0;
-
-      if (TREE_CODE (f1) != TREE_CODE (f2))
-        return 0;
-
-      if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
-       {
-         if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
-             && (DECL_BUILT_IN (olddecl)
-#ifndef NO_IMPLICIT_EXTERN_C
-                 || (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
-                 || (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
-#endif
-             ))
-           {
-             types_match = self_promoting_args_p (p1);
-             if (p1 == void_list_node)
-               TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
-           }
-#ifndef NO_IMPLICIT_EXTERN_C
-         else if (p1 == NULL_TREE
-                  && (DECL_EXTERN_C_P (olddecl)
-                      && DECL_IN_SYSTEM_HEADER (olddecl)
-                      && !DECL_CLASS_SCOPE_P (olddecl))
-                  && (DECL_EXTERN_C_P (newdecl)
-                      && DECL_IN_SYSTEM_HEADER (newdecl)
-                      && !DECL_CLASS_SCOPE_P (newdecl)))
-           {
-             types_match = self_promoting_args_p (p2);
-             TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
-           }
-#endif
-         else
-           types_match = compparms (p1, p2);
-       }
-      else
-       types_match = 0;
-    }
-  else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
-    {
-      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl))
-         != TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)))
-       return 0;
-
-      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-                               DECL_TEMPLATE_PARMS (olddecl)))
-       return 0;
-
-      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-       types_match = same_type_p (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)),
-                                  TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl)));
-      else
-       types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
-                                  DECL_TEMPLATE_RESULT (newdecl));
-    }
-  else
-    {
-      if (TREE_TYPE (newdecl) == error_mark_node)
-       types_match = TREE_TYPE (olddecl) == error_mark_node;
-      else if (TREE_TYPE (olddecl) == NULL_TREE)
-       types_match = TREE_TYPE (newdecl) == NULL_TREE;
-      else if (TREE_TYPE (newdecl) == NULL_TREE)
-       types_match = 0;
-      else
-       types_match = comptypes (TREE_TYPE (newdecl),
-                                TREE_TYPE (olddecl),
-                                COMPARE_REDECLARATION);
-    }
-
-  return types_match;
-}
-
-/* If NEWDECL is `static' and an `extern' was seen previously,
-   warn about it.  OLDDECL is the previous declaration.
-
-   Note that this does not apply to the C++ case of declaring
-   a variable `extern const' and then later `const'.
-
-   Don't complain about built-in functions, since they are beyond
-   the user's control.  */
-
-static void
-warn_extern_redeclared_static (tree newdecl, tree olddecl)
-{
-  static const char *const explicit_extern_static_warning
-    = "`%D' was declared `extern' and later `static'";
-  static const char *const implicit_extern_static_warning
-    = "`%D' was declared implicitly `extern' and later `static'";
-
-  tree name;
-
-  if (TREE_CODE (newdecl) == TYPE_DECL
-      || TREE_CODE (newdecl) == TEMPLATE_DECL
-      || TREE_CODE (newdecl) == CONST_DECL
-      || TREE_CODE (newdecl) == NAMESPACE_DECL)
-    return;
-
-  /* Don't get confused by static member functions; that's a different
-     use of `static'.  */
-  if (TREE_CODE (newdecl) == FUNCTION_DECL
-      && DECL_STATIC_FUNCTION_P (newdecl))
-    return;
-
-  /* If the old declaration was `static', or the new one isn't, then
-     then everything is OK.  */
-  if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
-    return;
-
-  /* It's OK to declare a builtin function as `static'.  */
-  if (TREE_CODE (olddecl) == FUNCTION_DECL
-      && DECL_ARTIFICIAL (olddecl))
-    return;
-
-  name = DECL_ASSEMBLER_NAME (newdecl);
-  pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
-             ? implicit_extern_static_warning
-             : explicit_extern_static_warning, newdecl);
-  cp_pedwarn_at ("previous declaration of `%D'", olddecl);
-}
-
-/* Handle when a new declaration NEWDECL has the same name as an old
-   one OLDDECL in the same binding contour.  Prints an error message
-   if appropriate.
-
-   If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
-   Otherwise, return 0.  */
-
-int
-duplicate_decls (tree newdecl, tree olddecl)
-{
-  unsigned olddecl_uid = DECL_UID (olddecl);
-  int olddecl_friend = 0, types_match = 0;
-  int new_defines_function = 0;
-
-  if (newdecl == olddecl)
-    return 1;
-
-  types_match = decls_match (newdecl, olddecl);
-
-  /* If either the type of the new decl or the type of the old decl is an
-     error_mark_node, then that implies that we have already issued an
-     error (earlier) for some bogus type specification, and in that case,
-     it is rather pointless to harass the user with yet more error message
-     about the same declaration, so just pretend the types match here.  */
-  if (TREE_TYPE (newdecl) == error_mark_node
-      || TREE_TYPE (olddecl) == error_mark_node)
-    types_match = 1;
-
-  if (DECL_P (olddecl)
-      && TREE_CODE (newdecl) == FUNCTION_DECL
-      && TREE_CODE (olddecl) == FUNCTION_DECL
-      && (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
-    {
-      if (DECL_DECLARED_INLINE_P (newdecl)
-         && DECL_UNINLINABLE (newdecl)
-         && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       /* Already warned elsewhere.  */;
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && DECL_UNINLINABLE (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       /* Already warned.  */;
-      else if (DECL_DECLARED_INLINE_P (newdecl)
-              && DECL_UNINLINABLE (olddecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
-       {
-         warning ("%Jfunction '%D' redeclared as inline", newdecl, newdecl);
-         warning ("%Jprevious declaration of '%D' with attribute noinline",
-                   olddecl, olddecl);
-       }
-      else if (DECL_DECLARED_INLINE_P (olddecl)
-              && DECL_UNINLINABLE (newdecl)
-              && lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
-       {
-         warning ("%Jfunction '%D' redeclared with attribute noinline",
-                  newdecl, newdecl);
-         warning ("%Jprevious declaration of '%D' was inline",
-                  olddecl, olddecl);
-       }
-    }
-
-  /* Check for redeclaration and other discrepancies.  */
-  if (TREE_CODE (olddecl) == FUNCTION_DECL
-      && DECL_ARTIFICIAL (olddecl))
-    {
-      if (TREE_CODE (newdecl) != FUNCTION_DECL)
-       {
-          /* Avoid warnings redeclaring anticipated built-ins.  */
-          if (DECL_ANTICIPATED (olddecl))
-            return 0;
-
-         /* If you declare a built-in or predefined function name as static,
-            the old definition is overridden, but optionally warn this was a
-            bad choice of name.  */
-         if (! TREE_PUBLIC (newdecl))
-           {
-             if (warn_shadow)
-               warning ("shadowing %s function `%#D'",
-                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
-                           olddecl);
-             /* Discard the old built-in function.  */
-             return 0;
-           }
-         /* If the built-in is not ansi, then programs can override
-            it even globally without an error.  */
-         else if (! DECL_BUILT_IN (olddecl))
-           warning ("library function `%#D' redeclared as non-function `%#D'",
-                       olddecl, newdecl);
-         else
-           {
-             error ("declaration of `%#D'", newdecl);
-             error ("conflicts with built-in declaration `%#D'",
-                       olddecl);
-           }
-         return 0;
-       }
-      else if (!types_match)
-       {
-          /* Avoid warnings redeclaring anticipated built-ins.  */
-          if (DECL_ANTICIPATED (olddecl))
-            ;  /* Do nothing yet.  */
-         else if ((DECL_EXTERN_C_P (newdecl)
-                   && DECL_EXTERN_C_P (olddecl))
-                  || compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
-                                TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
-           {
-             /* A near match; override the builtin.  */
-
-             if (TREE_PUBLIC (newdecl))
-               {
-                 warning ("new declaration `%#D'", newdecl);
-                 warning ("ambiguates built-in declaration `%#D'",
-                             olddecl);
-               }
-             else if (warn_shadow)
-               warning ("shadowing %s function `%#D'",
-                           DECL_BUILT_IN (olddecl) ? "built-in" : "library",
-                           olddecl);
-           }
-         else
-           /* Discard the old built-in function.  */
-           return 0;
-
-         /* 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);
-
-      /* Whether or not the builtin can throw exceptions has no
-        bearing on this declarator.  */
-      TREE_NOTHROW (olddecl) = 0;
-
-      if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
-       {
-         /* If a builtin function is redeclared as `static', merge
-            the declarations, but make the original one static.  */
-         DECL_THIS_STATIC (olddecl) = 1;
-         TREE_PUBLIC (olddecl) = 0;
-
-         /* Make the old declaration consistent with the new one so
-            that all remnants of the builtin-ness of this function
-            will be banished.  */
-         SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
-         SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
-       }
-    }
-  else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
-    {
-      if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
-          && TREE_CODE (newdecl) != TYPE_DECL
-          && ! (TREE_CODE (newdecl) == TEMPLATE_DECL
-                && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
-         || (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
-             && TREE_CODE (olddecl) != TYPE_DECL
-             && ! (TREE_CODE (olddecl) == TEMPLATE_DECL
-                   && (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
-                       == TYPE_DECL))))
-       {
-         /* We do nothing special here, because C++ does such nasty
-            things with TYPE_DECLs.  Instead, just let the TYPE_DECL
-            get shadowed, and know that if we need to find a TYPE_DECL
-            for a given name, we can look in the IDENTIFIER_TYPE_VALUE
-            slot of the identifier.  */
-         return 0;
-       }
-
-      if ((TREE_CODE (newdecl) == FUNCTION_DECL
-          && DECL_FUNCTION_TEMPLATE_P (olddecl))
-         || (TREE_CODE (olddecl) == FUNCTION_DECL
-             && DECL_FUNCTION_TEMPLATE_P (newdecl)))
-       return 0;
-
-      error ("`%#D' redeclared as different kind of symbol", newdecl);
-      if (TREE_CODE (olddecl) == TREE_LIST)
-       olddecl = TREE_VALUE (olddecl);
-      cp_error_at ("previous declaration of `%#D'", olddecl);
-
-      /* New decl is completely inconsistent with the old one =>
-        tell caller to replace the old one.  */
-
-      return 0;
-    }
-  else if (!types_match)
-    {
-      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
-       /* These are certainly not duplicate declarations; they're
-          from different scopes.  */
-       return 0;
-
-      if (TREE_CODE (newdecl) == TEMPLATE_DECL)
-       {
-         /* The name of a class template may not be declared to refer to
-            any other template, class, function, object, namespace, value,
-            or type in the same scope.  */
-         if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
-             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-           {
-             error ("declaration of template `%#D'", newdecl);
-             cp_error_at ("conflicts with previous declaration `%#D'",
-                          olddecl);
-           }
-         else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
-                  && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
-                  && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
-                                TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
-                  && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
-                                          DECL_TEMPLATE_PARMS (olddecl))
-                  /* Template functions can be disambiguated by
-                     return type.  */
-                  && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
-                                  TREE_TYPE (TREE_TYPE (olddecl))))
-           {
-             error ("new declaration `%#D'", newdecl);
-             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
-           }
-         return 0;
-       }
-      if (TREE_CODE (newdecl) == FUNCTION_DECL)
-       {
-         if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
-           {
-             error ("declaration of C function `%#D' conflicts with",
-                       newdecl);
-             cp_error_at ("previous declaration `%#D' here", olddecl);
-           }
-         else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
-                             TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
-           {
-             error ("new declaration `%#D'", newdecl);
-             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
-           }
-         else
-           return 0;
-       }
-
-      /* Already complained about this, so don't do so again.  */
-      else if (current_class_type == NULL_TREE
-         || IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
-       {
-         error ("conflicting declaration '%#D'", newdecl);
-         cp_error_at ("'%D' has a previous declaration as `%#D'",
-                       olddecl, olddecl);
-          return false;
-       }
-    }
-  else if (TREE_CODE (newdecl) == FUNCTION_DECL
-           && ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
-                && (!DECL_TEMPLATE_INFO (newdecl)
-                    || (DECL_TI_TEMPLATE (newdecl)
-                        != DECL_TI_TEMPLATE (olddecl))))
-               || (DECL_TEMPLATE_SPECIALIZATION (newdecl)
-                   && (!DECL_TEMPLATE_INFO (olddecl)
-                       || (DECL_TI_TEMPLATE (olddecl)
-                           != DECL_TI_TEMPLATE (newdecl))))))
-    /* It's OK to have a template specialization and a non-template
-       with the same type, or to have specializations of two
-       different templates with the same type.  Note that if one is a
-       specialization, and the other is an instantiation of the same
-       template, that we do not exit at this point.  That situation
-       can occur if we instantiate a template class, and then
-       specialize one of its methods.  This situation is valid, but
-       the declarations must be merged in the usual way.  */
-    return 0;
-  else if (TREE_CODE (newdecl) == FUNCTION_DECL
-          && ((DECL_TEMPLATE_INSTANTIATION (olddecl)
-               && !DECL_USE_TEMPLATE (newdecl))
-              || (DECL_TEMPLATE_INSTANTIATION (newdecl)
-                  && !DECL_USE_TEMPLATE (olddecl))))
-    /* One of the declarations is a template instantiation, and the
-       other is not a template at all.  That's OK.  */
-    return 0;
-  else if (TREE_CODE (newdecl) == NAMESPACE_DECL
-           && DECL_NAMESPACE_ALIAS (newdecl)
-           && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
-    /* Redeclaration of namespace alias, ignore it.  */
-    return 1;
-  else
-    {
-      const char *errmsg = redeclaration_error_message (newdecl, olddecl);
-      if (errmsg)
-       {
-         error (errmsg, newdecl);
-         if (DECL_NAME (olddecl) != NULL_TREE)
-           cp_error_at ((DECL_INITIAL (olddecl)
-                         && namespace_bindings_p ())
-                        ? "`%#D' previously defined here"
-                        : "`%#D' previously declared here", olddecl);
-         return 0;
-       }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
-              && DECL_INITIAL (olddecl) != NULL_TREE
-              && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
-              && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
-       {
-         /* Prototype decl follows defn w/o prototype.  */
-         cp_warning_at ("prototype for `%#D'", newdecl);
-         warning ("%Jfollows non-prototype definition here", olddecl);
-       }
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL
-              && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
-       {
-         /* extern "C" int foo ();
-            int foo () { bar (); }
-            is OK.  */
-         if (current_lang_depth () == 0)
-           SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
-         else
-           {
-             cp_error_at ("previous declaration of `%#D' with %L linkage",
-                          olddecl, DECL_LANGUAGE (olddecl));
-             error ("conflicts with new declaration with %L linkage",
-                       DECL_LANGUAGE (newdecl));
-           }
-       }
-
-      if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
-       ;
-      else if (TREE_CODE (olddecl) == FUNCTION_DECL)
-       {
-         tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
-         tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
-         int i = 1;
-
-         if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
-           t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
-
-         for (; t1 && t1 != void_list_node;
-              t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
-           if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
-             {
-               if (1 == simple_cst_equal (TREE_PURPOSE (t1),
-                                          TREE_PURPOSE (t2)))
-                 {
-                   pedwarn ("default argument given for parameter %d of `%#D'",
-                            i, newdecl);
-                   cp_pedwarn_at ("after previous specification in `%#D'",
-                                  olddecl);
-                 }
-               else
-                 {
-                   error ("default argument given for parameter %d of `%#D'",
-                             i, newdecl);
-                   cp_error_at ("after previous specification in `%#D'",
-                                olddecl);
-                 }
-             }
-
-         if (DECL_DECLARED_INLINE_P (newdecl) 
-             && ! DECL_DECLARED_INLINE_P (olddecl)
-             && TREE_ADDRESSABLE (olddecl) && warn_inline)
-           {
-             warning ("`%#D' was used before it was declared inline", newdecl);
-             warning ("%Jprevious non-inline declaration here", olddecl);
-           }
-       }
-    }
-
-  /* Do not merge an implicit typedef with an explicit one.  In:
-
-       class A;
-       ...
-       typedef class A A __attribute__ ((foo));
-
-     the attribute should apply only to the typedef.  */
-  if (TREE_CODE (olddecl) == TYPE_DECL
-      && (DECL_IMPLICIT_TYPEDEF_P (olddecl)
-         || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
-    return 0;
-
-  /* If new decl is `static' and an `extern' was seen previously,
-     warn about it.  */
-  warn_extern_redeclared_static (newdecl, olddecl);
-
-  /* We have committed to returning 1 at this point.  */
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      /* Now that functions must hold information normally held
-        by field decls, there is extra work to do so that
-        declaration information does not get destroyed during
-        definition.  */
-      if (DECL_VINDEX (olddecl))
-       DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
-      if (DECL_CONTEXT (olddecl))
-       DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
-      DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
-      DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
-      DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
-      DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
-      DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
-      DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
-      if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
-       SET_OVERLOADED_OPERATOR_CODE
-         (newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
-      new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
-
-      /* Optionally warn about more than one declaration for the same
-         name, but don't warn about a function declaration followed by a
-         definition.  */
-      if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
-         && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
-         /* Don't warn about extern decl followed by definition.  */
-         && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
-         /* Don't warn about friends, let add_friend take care of it.  */
-         && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
-       {
-         warning ("redundant redeclaration of `%D' in same scope", newdecl);
-         cp_warning_at ("previous declaration of `%D'", olddecl);
-       }
-    }
-
-  /* Deal with C++: must preserve virtual function table size.  */
-  if (TREE_CODE (olddecl) == TYPE_DECL)
-    {
-      register tree newtype = TREE_TYPE (newdecl);
-      register tree oldtype = TREE_TYPE (olddecl);
-
-      if (newtype != error_mark_node && oldtype != error_mark_node
-         && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
-       CLASSTYPE_FRIEND_CLASSES (newtype)
-         = CLASSTYPE_FRIEND_CLASSES (oldtype);
-
-      DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
-    }
-
-  /* Copy all the DECL_... slots specified in the new decl
-     except for any that we copy here from the old type.  */
-  DECL_ATTRIBUTES (newdecl)
-    = (*targetm.merge_decl_attributes) (olddecl, newdecl);
-
-  if (TREE_CODE (newdecl) == TEMPLATE_DECL)
-    {
-      TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
-      DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
-       = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
-                  DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
-
-      /* If the new declaration is a definition, update the file and
-        line information on the declaration.  */
-      if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
-         && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
-       {
-         DECL_SOURCE_LOCATION (olddecl) 
-           = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
-           = DECL_SOURCE_LOCATION (newdecl);
-       }
-
-      return 1;
-    }
-
-  if (types_match)
-    {
-      /* Automatically handles default parameters.  */
-      tree oldtype = TREE_TYPE (olddecl);
-      tree newtype;
-
-      /* Merge the data types specified in the two decls.  */
-      newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
-
-      /* If merge_types produces a non-typedef type, just use the old type.  */
-      if (TREE_CODE (newdecl) == TYPE_DECL
-         && newtype == DECL_ORIGINAL_TYPE (newdecl))
-       newtype = oldtype;
-
-      if (TREE_CODE (newdecl) == VAR_DECL)
-       {
-         DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
-         DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
-         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
-           |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
-       }
-
-      /* Do this after calling `merge_types' so that default
-        parameters don't confuse us.  */
-      else if (TREE_CODE (newdecl) == FUNCTION_DECL
-         && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
-             != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
-       {
-         TREE_TYPE (newdecl) = build_exception_variant (newtype,
-                                                        TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
-         TREE_TYPE (olddecl) = build_exception_variant (newtype,
-                                                        TYPE_RAISES_EXCEPTIONS (oldtype));
-
-         if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
-             && DECL_SOURCE_LINE (olddecl) != 0
-             && flag_exceptions
-             && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
-                                    TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
-           {
-             error ("declaration of `%F' throws different exceptions",
-                       newdecl);
-             cp_error_at ("than previous declaration `%F'", olddecl);
-           }
-       }
-      TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
-
-      /* Lay the type out, unless already done.  */
-      if (! same_type_p (newtype, oldtype)
-         && TREE_TYPE (newdecl) != error_mark_node
-         && !(processing_template_decl && uses_template_parms (newdecl)))
-       layout_type (TREE_TYPE (newdecl));
-
-      if ((TREE_CODE (newdecl) == VAR_DECL
-          || TREE_CODE (newdecl) == PARM_DECL
-          || TREE_CODE (newdecl) == RESULT_DECL
-          || TREE_CODE (newdecl) == FIELD_DECL
-          || TREE_CODE (newdecl) == TYPE_DECL)
-         && !(processing_template_decl && uses_template_parms (newdecl)))
-       layout_decl (newdecl, 0);
-
-      /* Merge the type qualifiers.  */
-      if (TREE_READONLY (newdecl))
-       TREE_READONLY (olddecl) = 1;
-      if (TREE_THIS_VOLATILE (newdecl))
-       TREE_THIS_VOLATILE (olddecl) = 1;
-
-      /* Merge the initialization information.  */
-      if (DECL_INITIAL (newdecl) == NULL_TREE
-         && DECL_INITIAL (olddecl) != NULL_TREE)
-       {
-         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
-         DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
-         if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
-             && DECL_LANG_SPECIFIC (newdecl)
-             && DECL_LANG_SPECIFIC (olddecl))
-           {
-             DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
-             DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
-           }
-       }
-
-      /* Merge the section attribute.
-         We want to issue an error if the sections conflict but that must be
-        done later in decl_attributes since we are called before attributes
-        are assigned.  */
-      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
-       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
-
-      if (TREE_CODE (newdecl) == FUNCTION_DECL)
-       {
-         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
-           |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (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);
-       }
-      else if (TREE_CODE (newdecl) == VAR_DECL 
-              && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
-       {
-         /* Keep the old RTL.  We cannot keep the old RTL if the old
-            declaration was for an incomplete object and the new
-            declaration is not since many attributes of the RTL will
-            change.  */
-         COPY_DECL_RTL (olddecl, newdecl);
-       }
-    }
-  /* If cannot merge, then use the new type and qualifiers,
-     and don't preserve the old rtl.  */
-  else
-    {
-      /* Clean out any memory we had of the old declaration.  */
-      tree oldstatic = value_member (olddecl, static_aggregates);
-      if (oldstatic)
-       TREE_VALUE (oldstatic) = error_mark_node;
-
-      TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
-      TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
-      TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
-      TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
-    }
-
-  /* Merge the storage class information.  */
-  merge_weak (newdecl, olddecl);
-
-  DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
-  DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
-  TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
-  TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
-  if (! DECL_EXTERNAL (olddecl))
-    DECL_EXTERNAL (newdecl) = 0;
-
-  if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
-    {
-      DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
-      DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
-      DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
-      DECL_TEMPLATE_INSTANTIATED (newdecl)
-       |= DECL_TEMPLATE_INSTANTIATED (olddecl);
-      /* Don't really know how much of the language-specific
-        values we should copy from old to new.  */
-      DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
-      DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 = 
-       DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
-      DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-      DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
-      DECL_INITIALIZED_IN_CLASS_P (newdecl)
-        |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
-      olddecl_friend = DECL_FRIEND_P (olddecl);
-
-      /* Only functions have DECL_BEFRIENDING_CLASSES.  */
-      if (TREE_CODE (newdecl) == FUNCTION_DECL
-         || DECL_FUNCTION_TEMPLATE_P (newdecl))
-       {
-         DECL_BEFRIENDING_CLASSES (newdecl)
-           = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
-                      DECL_BEFRIENDING_CLASSES (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);
-       }
-    }
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      if (DECL_TEMPLATE_INSTANTIATION (olddecl)
-         && !DECL_TEMPLATE_INSTANTIATION (newdecl))
-       {
-         /* If newdecl is not a specialization, then it is not a
-            template-related function at all.  And that means that we
-            should have exited above, returning 0.  */
-         my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
-                             0);
-
-         if (TREE_USED (olddecl))
-           /* From [temp.expl.spec]:
-
-              If a template, a member template or the member of a class
-              template is explicitly specialized then that
-              specialization shall be declared before the first use of
-              that specialization that would cause an implicit
-              instantiation to take place, in every translation unit in
-              which such a use occurs.  */
-           error ("explicit specialization of %D after first use",
-                     olddecl);
-
-         SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
-
-         /* [temp.expl.spec/14] We don't inline explicit specialization
-            just because the primary template says so.  */
-       }
-      else
-       {
-         if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
-           DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
-
-         DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
-
-         /* If either decl says `inline', this fn is inline, unless 
-            its definition was passed already.  */
-         if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
-           DECL_INLINE (olddecl) = 1;
-         DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
-
-         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
-           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
-       }
-
-      /* Preserve abstractness on cloned [cd]tors.  */
-      DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
-
-      if (! types_match)
-       {
-         SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
-         COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
-         SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
-       }
-      if (! types_match || new_defines_function)
-       {
-         /* These need to be copied so that the names are available.
-            Note that if the types do match, we'll preserve inline
-            info and other bits, but if not, we won't.  */
-         DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
-         DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
-       }
-      if (new_defines_function)
-       /* If defining a function declared with other language
-          linkage, use the previously declared language linkage.  */
-       SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
-      else if (types_match)
-       {
-         /* If redeclaring a builtin function, and not a definition,
-            it stays built in.  */
-         if (DECL_BUILT_IN (olddecl))
-           {
-             DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
-             DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
-             /* If we're keeping the built-in definition, keep the rtl,
-                regardless of declaration matches.  */
-             SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
-           }
-         else
-           DECL_ESTIMATED_INSNS (newdecl) = DECL_ESTIMATED_INSNS (olddecl);
-
-         DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
-         /* Don't clear out the arguments if we're redefining a function.  */
-         if (DECL_ARGUMENTS (olddecl))
-           DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
-       }
-    }
-  else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
-    NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
-
-  /* Now preserve various other info from the definition.  */
-  TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
-  TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
-  DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
-  COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
-
-  if (TREE_CODE (newdecl) == FUNCTION_DECL)
-    {
-      int function_size;
-
-      function_size = sizeof (struct tree_decl);
-
-      memcpy ((char *) olddecl + sizeof (struct tree_common),
-             (char *) newdecl + sizeof (struct tree_common),
-             function_size - sizeof (struct tree_common));
-
-      if (DECL_TEMPLATE_INSTANTIATION (newdecl))
-       /* If newdecl is a template instantiation, it is possible that
-          the following sequence of events has occurred:
-
-          o A friend function was declared in a class template.  The
-          class template was instantiated.
-
-          o The instantiation of the friend declaration was
-          recorded on the instantiation list, and is newdecl.
-
-          o Later, however, instantiate_class_template called pushdecl
-          on the newdecl to perform name injection.  But, pushdecl in
-          turn called duplicate_decls when it discovered that another
-          declaration of a global function with the same name already
-          existed.
+      if ((TREE_CODE (newdecl) == FUNCTION_DECL
+          && DECL_FUNCTION_TEMPLATE_P (olddecl))
+         || (TREE_CODE (olddecl) == FUNCTION_DECL
+             && DECL_FUNCTION_TEMPLATE_P (newdecl)))
+       return NULL_TREE;
 
-          o Here, in duplicate_decls, we decided to clobber newdecl.
+      error ("`%#D' redeclared as different kind of symbol", newdecl);
+      if (TREE_CODE (olddecl) == TREE_LIST)
+       olddecl = TREE_VALUE (olddecl);
+      cp_error_at ("previous declaration of `%#D'", olddecl);
 
-          If we're going to do that, we'd better make sure that
-          olddecl, and not newdecl, is on the list of
-          instantiations so that if we try to do the instantiation
-          again we won't get the clobbered declaration.  */
-       reregister_specialization (newdecl, 
-                                  DECL_TI_TEMPLATE (newdecl), 
-                                  olddecl);
-    }
-  else
-    {
-      memcpy ((char *) olddecl + sizeof (struct tree_common),
-             (char *) newdecl + sizeof (struct tree_common),
-             sizeof (struct tree_decl) - sizeof (struct tree_common)
-             + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
+      return error_mark_node;
     }
-
-  DECL_UID (olddecl) = olddecl_uid;
-  if (olddecl_friend)
-    DECL_FRIEND_P (olddecl) = 1;
-
-  /* NEWDECL contains the merged attribute lists.
-     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;
-}
-
-/* Record a decl-node X as belonging to the current lexical scope.
-   Check for errors (such as an incompatible declaration for the same
-   name already seen in the same scope).
-
-   Returns either X or an old decl for the same name.
-   If an old decl is returned, it may have been smashed
-   to agree with what X says.  */
-
-tree
-pushdecl (tree x)
-{
-  register tree t;
-  register tree name;
-  int need_new_binding;
-
-  timevar_push (TV_NAME_LOOKUP);
-
-  need_new_binding = 1;
-
-  if (DECL_TEMPLATE_PARM_P (x))
-    /* Template parameters have no context; they are not X::T even
-       when declared within a class or namespace.  */
-    ;
-  else
-    {
-      if (current_function_decl && x != current_function_decl
-         /* A local declaration for a function doesn't constitute
-             nesting.  */
-         && !(TREE_CODE (x) == FUNCTION_DECL && !DECL_INITIAL (x))
-         /* A local declaration for an `extern' variable is in the
-            scope of the current namespace, not the current
-            function.  */
-         && !(TREE_CODE (x) == VAR_DECL && DECL_EXTERNAL (x))
-         && !DECL_CONTEXT (x))
-       DECL_CONTEXT (x) = current_function_decl;
-
-      /* If this is the declaration for a namespace-scope function,
-        but the declaration itself is in a local scope, mark the
-        declaration.  */
-      if (TREE_CODE (x) == FUNCTION_DECL
-         && DECL_NAMESPACE_SCOPE_P (x)
-         && current_function_decl
-         && x != current_function_decl)
-       DECL_LOCAL_FUNCTION_P (x) = 1;
-    }
-
-  name = DECL_NAME (x);
-  if (name)
+  else if (!types_match)
     {
-      int different_binding_level = 0;
-
-      if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-       name = TREE_OPERAND (name, 0);
-
-      /* In case this decl was explicitly namespace-qualified, look it
-        up in its namespace context.  */
-      if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)
-         && namespace_bindings_p ())
-       t = namespace_binding (name, DECL_CONTEXT (x));
-      else
-       t = lookup_name_current_level (name);
-
-      /* [basic.link] If there is a visible declaration of an entity
-        with linkage having the same name and type, ignoring entities
-        declared outside the innermost enclosing namespace scope, the
-        block scope declaration declares that same entity and
-        receives the linkage of the previous declaration.  */
-      if (! t && current_function_decl && x != current_function_decl
-         && (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
-         && DECL_EXTERNAL (x))
-       {
-         /* Look in block scope.  */
-         t = IDENTIFIER_VALUE (name);
-         /* Or in the innermost namespace.  */
-         if (! t)
-           t = namespace_binding (name, DECL_CONTEXT (x));
-         /* Does it have linkage?  Note that if this isn't a DECL, it's an
-            OVERLOAD, which is OK.  */
-         if (t && DECL_P (t) && ! (TREE_STATIC (t) || DECL_EXTERNAL (t)))
-           t = NULL_TREE;
-         if (t)
-           different_binding_level = 1;
-       }
-
-      /* If we are declaring a function, and the result of name-lookup
-        was an OVERLOAD, look for an overloaded instance that is
-        actually the same as the function we are declaring.  (If
-        there is one, we have to merge our declaration with the
-        previous declaration.)  */
-      if (t && TREE_CODE (t) == OVERLOAD)
-       {
-         tree match;
-
-         if (TREE_CODE (x) == FUNCTION_DECL)
-           for (match = t; match; match = OVL_NEXT (match))
-             {
-               if (decls_match (OVL_CURRENT (match), x))
-                 break;
-             }
-         else
-           /* Just choose one.  */
-           match = t;
-
-         if (match)
-           t = OVL_CURRENT (match);
-         else
-           t = NULL_TREE;
-       }
+      if (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl))
+       /* These are certainly not duplicate declarations; they're
+          from different scopes.  */
+       return NULL_TREE;
 
-      if (t == error_mark_node)
-       {
-         /* error_mark_node is 0 for a while during initialization!  */
-         t = NULL_TREE;
-         cp_error_at ("`%#D' used prior to declaration", x);
-       }
-      else if (t != NULL_TREE)
+      if (TREE_CODE (newdecl) == TEMPLATE_DECL)
        {
-         if (different_binding_level)
-           {
-             if (decls_match (x, t))
-               /* The standard only says that the local extern
-                  inherits linkage from the previous decl; in
-                  particular, default args are not shared.  It would
-                  be nice to propagate inlining info, though.  FIXME.  */
-               TREE_PUBLIC (x) = TREE_PUBLIC (t);
-           }
-         else if (TREE_CODE (t) == PARM_DECL)
-           {
-             if (DECL_CONTEXT (t) == NULL_TREE)
-               /* This is probably caused by too many errors, but calling
-                  abort will say that if errors have occurred.  */
-               abort ();
-
-             /* Check for duplicate params.  */
-             if (duplicate_decls (x, t))
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
-           }
-         else if ((DECL_EXTERN_C_FUNCTION_P (x)
-                   || DECL_FUNCTION_TEMPLATE_P (x))
-                  && is_overloaded_fn (t))
-           /* Don't do anything just yet.  */;
-         else if (t == wchar_decl_node)
+         /* The name of a class template may not be declared to refer to
+            any other template, class, function, object, namespace, value,
+            or type in the same scope.  */
+         if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
+             || TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
            {
-             if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
-               pedwarn ("redeclaration of `wchar_t' as `%T'",
-                           TREE_TYPE (x));
-
-             /* Throw away the redeclaration.  */
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+             error ("declaration of template `%#D'", newdecl);
+             cp_error_at ("conflicts with previous declaration `%#D'",
+                          olddecl);
            }
-         else if (TREE_CODE (t) != TREE_CODE (x))
+         else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
+                  && TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
+                  && compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
+                                TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
+                  && comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+                                          DECL_TEMPLATE_PARMS (olddecl))
+                  /* Template functions can be disambiguated by
+                     return type.  */
+                  && same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
+                                  TREE_TYPE (TREE_TYPE (olddecl))))
            {
-             if (duplicate_decls (x, t))
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+             error ("new declaration `%#D'", newdecl);
+             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
            }
-         else if (duplicate_decls (x, t))
+         return NULL_TREE;
+       }
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
            {
-             if (TREE_CODE (t) == TYPE_DECL)
-               SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
-             else if (TREE_CODE (t) == FUNCTION_DECL)
-               check_default_args (t);
-
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+             error ("declaration of C function `%#D' conflicts with",
+                       newdecl);
+             cp_error_at ("previous declaration `%#D' here", olddecl);
            }
-         else if (DECL_MAIN_P (x))
+         else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
+                             TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
            {
-             /* A redeclaration of main, but not a duplicate of the
-                previous one.
-
-                [basic.start.main]
-
-                This function shall not be overloaded.  */
-             cp_error_at ("invalid redeclaration of `%D'", t);
-             error ("as `%D'", x);
-             /* We don't try to push this declaration since that
-                causes a crash.  */
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
+             error ("new declaration `%#D'", newdecl);
+             cp_error_at ("ambiguates old declaration `%#D'", olddecl);
            }
+         else
+           return NULL_TREE;
        }
-
-      check_template_shadow (x);
-
-      /* If this is a function conjured up by the backend, massage it
-        so it looks friendly.  */
-      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
+      else
        {
-         retrofit_lang_decl (x);
-         SET_DECL_LANGUAGE (x, lang_c);
+         error ("conflicting declaration '%#D'", newdecl);
+         cp_error_at ("'%D' has a previous declaration as `%#D'",
+                       olddecl, olddecl);
+          return NULL_TREE;
        }
+    }
+  else if (TREE_CODE (newdecl) == FUNCTION_DECL
+           && ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
+                && (!DECL_TEMPLATE_INFO (newdecl)
+                    || (DECL_TI_TEMPLATE (newdecl)
+                        != DECL_TI_TEMPLATE (olddecl))))
+               || (DECL_TEMPLATE_SPECIALIZATION (newdecl)
+                   && (!DECL_TEMPLATE_INFO (olddecl)
+                       || (DECL_TI_TEMPLATE (olddecl)
+                           != DECL_TI_TEMPLATE (newdecl))))))
+    /* It's OK to have a template specialization and a non-template
+       with the same type, or to have specializations of two
+       different templates with the same type.  Note that if one is a
+       specialization, and the other is an instantiation of the same
+       template, that we do not exit at this point.  That situation
+       can occur if we instantiate a template class, and then
+       specialize one of its methods.  This situation is valid, but
+       the declarations must be merged in the usual way.  */
+    return NULL_TREE;
+  else if (TREE_CODE (newdecl) == FUNCTION_DECL
+          && ((DECL_TEMPLATE_INSTANTIATION (olddecl)
+               && !DECL_USE_TEMPLATE (newdecl))
+              || (DECL_TEMPLATE_INSTANTIATION (newdecl)
+                  && !DECL_USE_TEMPLATE (olddecl))))
+    /* One of the declarations is a template instantiation, and the
+       other is not a template at all.  That's OK.  */
+    return NULL_TREE;
+  else if (TREE_CODE (newdecl) == NAMESPACE_DECL
+           && DECL_NAMESPACE_ALIAS (newdecl)
+           && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
+    /* In [namespace.alias] we have:
 
-      if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
-       {
-         t = push_overloaded_decl (x, PUSH_LOCAL);
-         if (t != x)
-           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
-              necessary.  */
-           need_new_binding = 0;
-       }
-      else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
+        In a declarative region, a namespace-alias-definition can be
+        used to redefine a namespace-alias declared in that declarative
+        region to refer only to the namespace to which it already
+        refers.  
+
+      Therefore, if we encounter a second alias directive for the same
+      alias, we can just ignore the second directive.  */
+    return olddecl;
+  else
+    {
+      const char *errmsg = redeclaration_error_message (newdecl, olddecl);
+      if (errmsg)
        {
-         t = push_overloaded_decl (x, PUSH_GLOBAL);
-         if (t == x)
-           add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+         error (errmsg, newdecl);
+         if (DECL_NAME (olddecl) != NULL_TREE)
+           cp_error_at ((DECL_INITIAL (olddecl)
+                         && namespace_bindings_p ())
+                        ? "`%#D' previously defined here"
+                        : "`%#D' previously declared here", olddecl);
+         return error_mark_node;
        }
-
-      /* If declaring a type as a typedef, copy the type (unless we're
-        at line 0), and install this TYPE_DECL as the new type's typedef
-        name.  See the extensive comment in ../c-decl.c (pushdecl).  */
-      if (TREE_CODE (x) == TYPE_DECL)
+      else if (TREE_CODE (olddecl) == FUNCTION_DECL
+              && DECL_INITIAL (olddecl) != NULL_TREE
+              && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
+              && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
        {
-         tree type = TREE_TYPE (x);
-         if (DECL_SOURCE_LINE (x) == 0)
-            {
-             if (TYPE_NAME (type) == 0)
-               TYPE_NAME (type) = x;
-            }
-          else if (type != error_mark_node && TYPE_NAME (type) != x
-                  /* We don't want to copy the type when all we're
-                     doing is making a TYPE_DECL for the purposes of
-                     inlining.  */
-                  && (!TYPE_NAME (type)
-                      || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
-            {
-             DECL_ORIGINAL_TYPE (x) = type;
-              type = build_type_copy (type);
-             TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
-              TYPE_NAME (type) = x;
-              TREE_TYPE (x) = type;
-            }
-
-         if (type != error_mark_node
-             && TYPE_NAME (type)
-             && TYPE_IDENTIFIER (type))
-            set_identifier_type_value (DECL_NAME (x), x);
+         /* Prototype decl follows defn w/o prototype.  */
+         cp_warning_at ("prototype for `%#D'", newdecl);
+         warning ("%Jfollows non-prototype definition here", olddecl);
        }
-
-      /* Multiple external decls of the same identifier ought to match.
-
-        We get warnings about inline functions where they are defined.
-        We get warnings about other functions from push_overloaded_decl.
-
-        Avoid duplicate warnings where they are used.  */
-      if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
+      else if (TREE_CODE (olddecl) == FUNCTION_DECL
+              && DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
        {
-         tree decl;
-
-         decl = IDENTIFIER_NAMESPACE_VALUE (name);
-         if (decl && TREE_CODE (decl) == OVERLOAD)
-           decl = OVL_FUNCTION (decl);
-
-         if (decl && decl != error_mark_node
-             && (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
-             /* If different sort of thing, we already gave an error.  */
-             && TREE_CODE (decl) == TREE_CODE (x)
-             && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
+         /* extern "C" int foo ();
+            int foo () { bar (); }
+            is OK.  */
+         if (current_lang_depth () == 0)
+           SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+         else
            {
-             pedwarn ("type mismatch with previous external decl of `%#D'", x);
-             cp_pedwarn_at ("previous external decl of `%#D'", decl);
+             cp_error_at ("previous declaration of `%#D' with %L linkage",
+                          olddecl, DECL_LANGUAGE (olddecl));
+             error ("conflicts with new declaration with %L linkage",
+                       DECL_LANGUAGE (newdecl));
            }
        }
 
-      /* This name is new in its binding level.
-        Install the new declaration and return it.  */
-      if (namespace_bindings_p ())
-       {
-         /* Install a global value.  */
-
-         /* If the first global decl has external linkage,
-            warn if we later see static one.  */
-         if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
-           TREE_PUBLIC (name) = 1;
-
-         /* Bind the name for the entity.  */
-         if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
-               && t != NULL_TREE)
-             && (TREE_CODE (x) == TYPE_DECL
-                 || TREE_CODE (x) == VAR_DECL
-                 || TREE_CODE (x) == ALIAS_DECL
-                 || TREE_CODE (x) == NAMESPACE_DECL
-                 || TREE_CODE (x) == CONST_DECL
-                 || TREE_CODE (x) == TEMPLATE_DECL))
-           SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
-
-         /* Don't forget if the function was used via an implicit decl.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name)
-             && TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
-           TREE_USED (x) = 1;
-
-         /* Don't forget if its address was taken in that way.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name)
-             && TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
-           TREE_ADDRESSABLE (x) = 1;
-
-         /* Warn about mismatches against previous implicit decl.  */
-         if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE
-             /* If this real decl matches the implicit, don't complain.  */
-             && ! (TREE_CODE (x) == FUNCTION_DECL
-                   && TREE_TYPE (TREE_TYPE (x)) == integer_type_node))
-           warning
-             ("`%D' was previously implicitly declared to return `int'", x);
-
-         /* If new decl is `static' and an `extern' was seen previously,
-            warn about it.  */
-         if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
-           warn_extern_redeclared_static (x, t);
-       }
-      else
+      if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
+       ;
+      else if (TREE_CODE (olddecl) == FUNCTION_DECL)
        {
-         /* Here to install a non-global value.  */
-         tree oldlocal = IDENTIFIER_VALUE (name);
-         tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
-
-         if (need_new_binding)
-           {
-             push_local_binding (name, x, 0);
-             /* Because push_local_binding will hook X on to the
-                current_binding_level's name list, we don't want to
-                do that again below.  */
-             need_new_binding = 0;
-           }
-
-         /* If this is a TYPE_DECL, push it into the type value slot.  */
-         if (TREE_CODE (x) == TYPE_DECL)
-           set_identifier_type_value (name, x);
-
-         /* Clear out any TYPE_DECL shadowed by a namespace so that
-            we won't think this is a type.  The C struct hack doesn't
-            go through namespaces.  */
-         if (TREE_CODE (x) == NAMESPACE_DECL)
-           set_identifier_type_value (name, NULL_TREE);
-
-         if (oldlocal)
-           {
-             tree d = oldlocal;
-
-             while (oldlocal
-                    && TREE_CODE (oldlocal) == VAR_DECL
-                    && DECL_DEAD_FOR_LOCAL (oldlocal))
-               oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
-
-             if (oldlocal == NULL_TREE)
-               oldlocal = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (d));
-           }
-
-         /* If this is an extern function declaration, see if we
-            have a global definition or declaration for the function.  */
-         if (oldlocal == NULL_TREE
-             && DECL_EXTERNAL (x)
-             && oldglobal != NULL_TREE
-             && TREE_CODE (x) == FUNCTION_DECL
-             && TREE_CODE (oldglobal) == FUNCTION_DECL)
-           {
-             /* We have one.  Their types must agree.  */
-             if (decls_match (x, oldglobal))
-               /* OK */;
-             else
-               {
-                 warning ("extern declaration of `%#D' doesn't match", x);
-                 cp_warning_at ("global declaration `%#D'", oldglobal);
-               }
-           }
-         /* If we have a local external declaration,
-            and no file-scope declaration has yet been seen,
-            then if we later have a file-scope decl it must not be static.  */
-         if (oldlocal == NULL_TREE
-             && oldglobal == NULL_TREE
-             && DECL_EXTERNAL (x)
-             && TREE_PUBLIC (x))
-           TREE_PUBLIC (name) = 1;
-
-         /* Warn if shadowing an argument at the top level of the body.  */
-         if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
-             /* Inline decls shadow nothing.  */
-             && !DECL_FROM_INLINE (x)
-             && TREE_CODE (oldlocal) == PARM_DECL
-             /* Don't check the `this' parameter.  */
-             && !DECL_ARTIFICIAL (oldlocal))
-           {
-             bool err = false;
-
-             /* Don't complain if it's from an enclosing function.  */
-             if (DECL_CONTEXT (oldlocal) == current_function_decl
-                 && TREE_CODE (x) != PARM_DECL)
-               {
-                 /* Go to where the parms should be and see if we find
-                    them there.  */
-                 struct cp_binding_level *b = current_binding_level->level_chain;
-
-                 /* Skip the ctor/dtor cleanup level.  */
-                 b = b->level_chain;
+         tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
+         tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
+         int i = 1;
 
-                 /* ARM $8.3 */
-                 if (b->kind == sk_function_parms)
-                   {
-                     error ("declaration of `%#D' shadows a parameter",
-                            name);
-                     err = true;
-                   }
-               }
+         if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
+           t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
 
-             if (warn_shadow && !err)
-               shadow_warning (SW_PARAM,
-                               IDENTIFIER_POINTER (name), oldlocal);
-           }
+         for (; t1 && t1 != void_list_node;
+              t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
+           if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
+             {
+               if (1 == simple_cst_equal (TREE_PURPOSE (t1),
+                                          TREE_PURPOSE (t2)))
+                 {
+                   pedwarn ("default argument given for parameter %d of `%#D'",
+                            i, newdecl);
+                   cp_pedwarn_at ("after previous specification in `%#D'",
+                                  olddecl);
+                 }
+               else
+                 {
+                   error ("default argument given for parameter %d of `%#D'",
+                             i, newdecl);
+                   cp_error_at ("after previous specification in `%#D'",
+                                olddecl);
+                 }
+             }
 
-         /* Maybe warn if shadowing something else.  */
-         else if (warn_shadow && !DECL_EXTERNAL (x)
-             /* No shadow warnings for internally generated vars.  */
-             && ! DECL_ARTIFICIAL (x)
-             /* No shadow warnings for vars made for inlining.  */
-             && ! DECL_FROM_INLINE (x))
+         if (DECL_DECLARED_INLINE_P (newdecl) 
+             && ! DECL_DECLARED_INLINE_P (olddecl)
+             && TREE_ADDRESSABLE (olddecl) && warn_inline)
            {
-             if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
-                      && current_class_ptr
-                      && !TREE_STATIC (name))
-               warning ("declaration of `%s' shadows a member of `this'",
-                           IDENTIFIER_POINTER (name));
-             else if (oldlocal != NULL_TREE
-                      && TREE_CODE (oldlocal) == VAR_DECL)
-               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,
-                               IDENTIFIER_POINTER (name), oldglobal);
+             warning ("`%#D' was used before it was declared inline", newdecl);
+             warning ("%Jprevious non-inline declaration here", olddecl);
            }
        }
-
-      if (TREE_CODE (x) == FUNCTION_DECL)
-       check_default_args (x);
-
-      if (TREE_CODE (x) == VAR_DECL)
-       maybe_register_incomplete_var (x);
     }
 
-  if (need_new_binding)
-    add_decl_to_level (x,
-                      DECL_NAMESPACE_SCOPE_P (x)
-                      ? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
-                      : current_binding_level);
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
-}
-
-/* Same as pushdecl, but define X in binding-level LEVEL.  We rely on the
-   caller to set DECL_CONTEXT properly.  */
-
-static tree
-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->kind == sk_class)
-    {
-      b = class_binding_level;
-      class_binding_level = level;
-      pushdecl_class_level (x);
-      class_binding_level = b;
-    }
-  else
-    {
-      b = current_binding_level;
-      current_binding_level = level;
-      x = pushdecl (x);
-      current_binding_level = b;
-    }
-  current_function_decl = function_decl;
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
-}
+  /* Do not merge an implicit typedef with an explicit one.  In:
 
-/* Like pushdecl, only it places X in the current namespace,
-   if appropriate.  */
+       class A;
+       ...
+       typedef class A A __attribute__ ((foo));
 
-tree
-pushdecl_namespace_level (tree x)
-{
-  register struct cp_binding_level *b = current_binding_level;
-  register tree t;
+     the attribute should apply only to the typedef.  */
+  if (TREE_CODE (olddecl) == TYPE_DECL
+      && (DECL_IMPLICIT_TYPEDEF_P (olddecl)
+         || DECL_IMPLICIT_TYPEDEF_P (newdecl)))
+    return NULL_TREE;
 
-  timevar_push (TV_NAME_LOOKUP);
-  t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
+  /* If new decl is `static' and an `extern' was seen previously,
+     warn about it.  */
+  warn_extern_redeclared_static (newdecl, olddecl);
 
-  /* Now, the type_shadowed stack may screw us.  Munge it so it does
-     what we want.  */
-  if (TREE_CODE (x) == TYPE_DECL)
+  /* We have committed to returning 1 at this point.  */
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
-      tree name = DECL_NAME (x);
-      tree newval;
-      tree *ptr = (tree *)0;
-      for (; !global_scope_p (b); b = b->level_chain)
-        {
-          tree shadowed = b->type_shadowed;
-          for (; shadowed; shadowed = TREE_CHAIN (shadowed))
-            if (TREE_PURPOSE (shadowed) == name)
-              {
-               ptr = &TREE_VALUE (shadowed);
-               /* Can't break out of the loop here because sometimes
-                  a binding level will have duplicate bindings for
-                  PT names.  It's gross, but I haven't time to fix it.  */
-              }
-        }
-      newval = TREE_TYPE (x);
-      if (ptr == (tree *)0)
-        {
-          /* @@ This shouldn't be needed.  My test case "zstring.cc" trips
-             up here if this is changed to an assertion.  --KR  */
-         SET_IDENTIFIER_TYPE_VALUE (name, x);
-       }
-      else
-        {
-         *ptr = newval;
-        }
-    }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
-}
-
-/* Like pushdecl, only it places X in the global scope if appropriate.
-   Calls cp_finish_decl to register the variable, initializing it with
-   *INIT, if INIT is non-NULL.  */
-
-static tree
-pushdecl_top_level_1 (tree x, tree *init)
-{
-  timevar_push (TV_NAME_LOOKUP);
-  push_to_top_level ();
-  x = pushdecl_namespace_level (x);
-  if (init)
-    cp_finish_decl (x, *init, NULL_TREE, 0);
-  pop_from_top_level ();
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
-}
-
-/* Like pushdecl, only it places X in the global scope if appropriate.  */
-
-tree
-pushdecl_top_level (tree x)
-{
-  return pushdecl_top_level_1 (x, NULL);
-}
+      /* Now that functions must hold information normally held
+        by field decls, there is extra work to do so that
+        declaration information does not get destroyed during
+        definition.  */
+      if (DECL_VINDEX (olddecl))
+       DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
+      if (DECL_CONTEXT (olddecl))
+       DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
+      DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
+      DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
+      DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
+      DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
+      DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
+      DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
+      if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
+       SET_OVERLOADED_OPERATOR_CODE
+         (newdecl, DECL_OVERLOADED_OPERATOR_P (olddecl));
+      new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
 
-/* Like pushdecl, only it places X in the global scope if
-   appropriate.  Calls cp_finish_decl to register the variable,
-   initializing it with INIT.  */
+      /* Optionally warn about more than one declaration for the same
+         name, but don't warn about a function declaration followed by a
+         definition.  */
+      if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
+         && !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
+         /* Don't warn about extern decl followed by definition.  */
+         && !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
+         /* Don't warn about friends, let add_friend take care of it.  */
+         && ! (DECL_FRIEND_P (newdecl) || DECL_FRIEND_P (olddecl)))
+       {
+         warning ("redundant redeclaration of `%D' in same scope", newdecl);
+         cp_warning_at ("previous declaration of `%D'", olddecl);
+       }
+    }
 
-tree
-pushdecl_top_level_and_finish (tree x, tree init)
-{
-  return pushdecl_top_level_1 (x, &init);
-}
+  /* Deal with C++: must preserve virtual function table size.  */
+  if (TREE_CODE (olddecl) == TYPE_DECL)
+    {
+      tree newtype = TREE_TYPE (newdecl);
+      tree oldtype = TREE_TYPE (olddecl);
 
-/* Make the declaration of X appear in CLASS scope.  */
+      if (newtype != error_mark_node && oldtype != error_mark_node
+         && TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
+       CLASSTYPE_FRIEND_CLASSES (newtype)
+         = CLASSTYPE_FRIEND_CLASSES (oldtype);
 
-bool
-pushdecl_class_level (tree x)
-{
-  tree name;
-  bool is_valid = true;
+      DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
+    }
 
-  timevar_push (TV_NAME_LOOKUP);
-  /* Get the name of X.  */
-  if (TREE_CODE (x) == OVERLOAD)
-    name = DECL_NAME (get_first_fn (x));
-  else
-    name = DECL_NAME (x);
+  /* Copy all the DECL_... slots specified in the new decl
+     except for any that we copy here from the old type.  */
+  DECL_ATTRIBUTES (newdecl)
+    = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
-  if (name)
-    {
-      is_valid = push_class_level_binding (name, x);
-      if (TREE_CODE (x) == TYPE_DECL)
-       set_identifier_type_value (name, x);
-    }
-  else if (ANON_AGGR_TYPE_P (TREE_TYPE (x)))
+  if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      /* If X is an anonymous aggregate, all of its members are
-        treated as if they were members of the class containing the
-        aggregate, for naming purposes.  */
-      tree f;
+      TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+      DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
+       = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
+                  DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
 
-      for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
+      /* If the new declaration is a definition, update the file and
+        line information on the declaration.  */
+      if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
+         && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
        {
-         location_t save_location = input_location;
-         input_location = DECL_SOURCE_LOCATION (f);
-         if (!pushdecl_class_level (f))
-           is_valid = false;
-         input_location = save_location;
+         DECL_SOURCE_LOCATION (olddecl) 
+           = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+           = DECL_SOURCE_LOCATION (newdecl);
+         if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+           DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
+             = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
        }
-    }
-  timevar_pop (TV_NAME_LOOKUP);
 
-  return is_valid;
-}
+      if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+       {
+         DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl)) 
+           |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
+         DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
+           |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
+       }
 
-/* Enter DECL into the symbol table, if that's appropriate.  Returns
-   DECL, or a modified version thereof.  */
+      return olddecl;
+    }
 
-tree
-maybe_push_decl (tree decl)
-{
-  tree type = TREE_TYPE (decl);
+  if (types_match)
+    {
+      /* Automatically handles default parameters.  */
+      tree oldtype = TREE_TYPE (olddecl);
+      tree newtype;
 
-  /* Add this decl to the current binding level, but not if it comes
-     from another scope, e.g. a static member variable.  TEM may equal
-     DECL or it may be a previous decl of the same name.  */
-  if (decl == error_mark_node
-      || (TREE_CODE (decl) != PARM_DECL
-         && DECL_CONTEXT (decl) != NULL_TREE
-         /* Definitions of namespace members outside their namespace are
-            possible.  */
-         && TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
-      || (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
-      || TREE_CODE (type) == UNKNOWN_TYPE
-      /* The declaration of a template specialization does not affect
-        the functions available for overload resolution, so we do not
-        call pushdecl.  */
-      || (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_TEMPLATE_SPECIALIZATION (decl)))
-    return decl;
-  else
-    return pushdecl (decl);
-}
+      /* Merge the data types specified in the two decls.  */
+      newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
 
-/* Make the declaration(s) of X appear in CLASS scope under the name
-   NAME.  Returns true if the binding is valid.  */
+      /* If merge_types produces a non-typedef type, just use the old type.  */
+      if (TREE_CODE (newdecl) == TYPE_DECL
+         && newtype == DECL_ORIGINAL_TYPE (newdecl))
+       newtype = oldtype;
 
-bool
-push_class_level_binding (tree name, tree x)
-{
-  cxx_binding *binding;
+      if (TREE_CODE (newdecl) == VAR_DECL)
+       {
+         DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
+         DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
+         DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
+           |= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
+       }
 
-  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)
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-
-  /* Make sure that this new member does not have the same name
-     as a template parameter.  */
-  if (TYPE_BEING_DEFINED (current_class_type))
-    check_template_shadow (x);
-
-  /* If this declaration shadows a declaration from an enclosing
-     class, then we will need to restore IDENTIFIER_CLASS_VALUE when
-     we leave this class.  Record the shadowed declaration here.  */
-  binding = IDENTIFIER_BINDING (name);
-  if (binding && binding->value)
-    {
-      tree bval = binding->value;
-      tree old_decl = NULL_TREE;
-
-      if (INHERITED_VALUE_BINDING_P (binding))
-       {
-         /* If the old binding was from a base class, and was for a
-            tag name, slide it over to make room for the new binding.
-            The old binding is still visible if explicitly qualified
-            with a class-key.  */
-         if (TREE_CODE (bval) == TYPE_DECL && DECL_ARTIFICIAL (bval)
-             && !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
+      /* Do this after calling `merge_types' so that default
+        parameters don't confuse us.  */
+      else if (TREE_CODE (newdecl) == FUNCTION_DECL
+         && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
+             != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
+       {
+         TREE_TYPE (newdecl) = build_exception_variant (newtype,
+                                                        TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
+         TREE_TYPE (olddecl) = build_exception_variant (newtype,
+                                                        TYPE_RAISES_EXCEPTIONS (oldtype));
+
+         if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
+             && DECL_SOURCE_LINE (olddecl) != 0
+             && flag_exceptions
+             && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
+                                    TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
            {
-             old_decl = binding->type;
-             binding->type = bval;
-             binding->value = NULL_TREE;
-             INHERITED_VALUE_BINDING_P (binding) = 0;
+             error ("declaration of `%F' throws different exceptions",
+                       newdecl);
+             cp_error_at ("than previous declaration `%F'", olddecl);
            }
-         else
-           old_decl = bval;
-       }
-      else if (TREE_CODE (x) == OVERLOAD && is_overloaded_fn (bval))
-       old_decl = bval;
-      else if (TREE_CODE (x) == USING_DECL && TREE_CODE (bval) == USING_DECL)
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-      else if (TREE_CODE (x) == USING_DECL && is_overloaded_fn (bval))
-       old_decl = bval;
-      else if (TREE_CODE (bval) == USING_DECL && is_overloaded_fn (x))
-       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-      
-      if (old_decl)
-       {
-         tree shadow;
-         
-         /* Find the previous binding of name on the class-shadowed
-             list, and update it.  */
-         for (shadow = class_binding_level->class_shadowed;
-              shadow;
-              shadow = TREE_CHAIN (shadow))
-           if (TREE_PURPOSE (shadow) == name
-               && TREE_TYPE (shadow) == old_decl)
-             {
-               binding->value = x;
-               INHERITED_VALUE_BINDING_P (binding) = 0;
-               TREE_TYPE (shadow) = x;
-               IDENTIFIER_CLASS_VALUE (name) = x;
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-             }
        }
-    }
+      TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
 
-  /* If we didn't replace an existing binding, put the binding on the
-     stack of bindings for the identifier, and update the shadowed list.  */
-  if (push_class_binding (name, x))
-    {
-      class_binding_level->class_shadowed
-       = tree_cons (name, NULL,
-                    class_binding_level->class_shadowed);
-      /* Record the value we are binding NAME to so that we can know
-        what to pop later.  */
-      TREE_TYPE (class_binding_level->class_shadowed) = x;
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, true);
-    }
+      /* Lay the type out, unless already done.  */
+      if (! same_type_p (newtype, oldtype)
+         && TREE_TYPE (newdecl) != error_mark_node
+         && !(processing_template_decl && uses_template_parms (newdecl)))
+       layout_type (TREE_TYPE (newdecl));
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, false);
-}
+      if ((TREE_CODE (newdecl) == VAR_DECL
+          || TREE_CODE (newdecl) == PARM_DECL
+          || TREE_CODE (newdecl) == RESULT_DECL
+          || TREE_CODE (newdecl) == FIELD_DECL
+          || TREE_CODE (newdecl) == TYPE_DECL)
+         && !(processing_template_decl && uses_template_parms (newdecl)))
+       layout_decl (newdecl, 0);
 
-/* Insert another USING_DECL into the current binding level, returning
-   this declaration. If this is a redeclaration, do nothing, and
-   return NULL_TREE if this not in namespace scope (in namespace
-   scope, a using decl might extend any previous bindings).  */
+      /* Merge the type qualifiers.  */
+      if (TREE_READONLY (newdecl))
+       TREE_READONLY (olddecl) = 1;
+      if (TREE_THIS_VOLATILE (newdecl))
+       TREE_THIS_VOLATILE (olddecl) = 1;
 
-tree
-push_using_decl (tree scope, tree name)
-{
-  tree decl;
+      /* Merge the initialization information.  */
+      if (DECL_INITIAL (newdecl) == NULL_TREE
+         && DECL_INITIAL (olddecl) != NULL_TREE)
+       {
+         DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
+         DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
+         if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
+             && DECL_LANG_SPECIFIC (newdecl)
+             && DECL_LANG_SPECIFIC (olddecl))
+           {
+             DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
+             DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
+           }
+       }
 
-  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)
-    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;
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
-}
+      /* Merge the section attribute.
+         We want to issue an error if the sections conflict but that must be
+        done later in decl_attributes since we are called before attributes
+        are assigned.  */
+      if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
+       DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
 
-/* Add namespace to using_directives. Return NULL_TREE if nothing was
-   changed (i.e. there was already a directive), or the fresh
-   TREE_LIST otherwise.  */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       {
+         DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
+           |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (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);
+       }
+      else if (TREE_CODE (newdecl) == VAR_DECL 
+              && (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
+       {
+         /* Keep the old RTL.  We cannot keep the old RTL if the old
+            declaration was for an incomplete object and the new
+            declaration is not since many attributes of the RTL will
+            change.  */
+         COPY_DECL_RTL (olddecl, newdecl);
+       }
+    }
+  /* If cannot merge, then use the new type and qualifiers,
+     and don't preserve the old rtl.  */
+  else
+    {
+      /* Clean out any memory we had of the old declaration.  */
+      tree oldstatic = value_member (olddecl, static_aggregates);
+      if (oldstatic)
+       TREE_VALUE (oldstatic) = error_mark_node;
 
-tree
-push_using_directive (tree used)
-{
-  tree ud = current_binding_level->using_directives;
-  tree iter, ancestor;
+      TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
+      TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
+      TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
+      TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
+    }
 
-  timevar_push (TV_NAME_LOOKUP);
-  /* Check if we already have this.  */
-  if (purpose_member (used, ud) != NULL_TREE)
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+  /* Merge the storage class information.  */
+  merge_weak (newdecl, olddecl);
 
-  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;
+  DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
+  DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
+  TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
+  TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
+  if (! DECL_EXTERNAL (olddecl))
+    DECL_EXTERNAL (newdecl) = 0;
 
-  /* Recursively add all namespaces used.  */
-  for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
-    push_using_directive (TREE_PURPOSE (iter));
+  if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
+    {
+      DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
+      DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
+      DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
+      DECL_TEMPLATE_INSTANTIATED (newdecl)
+       |= DECL_TEMPLATE_INSTANTIATED (olddecl);
+      /* Don't really know how much of the language-specific
+        values we should copy from old to new.  */
+      DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
+      DECL_LANG_SPECIFIC (newdecl)->decl_flags.u2 = 
+       DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
+      DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
+      DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+      DECL_INITIALIZED_IN_CLASS_P (newdecl)
+        |= DECL_INITIALIZED_IN_CLASS_P (olddecl);
+      olddecl_friend = DECL_FRIEND_P (olddecl);
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ud);
-}
+      /* Only functions have DECL_BEFRIENDING_CLASSES.  */
+      if (TREE_CODE (newdecl) == FUNCTION_DECL
+         || DECL_FUNCTION_TEMPLATE_P (newdecl))
+       {
+         DECL_BEFRIENDING_CLASSES (newdecl)
+           = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
+                      DECL_BEFRIENDING_CLASSES (olddecl));
+         /* 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);
+       }
+    }
 
-/* DECL is a FUNCTION_DECL for a non-member function, which may have
-   other definitions already in place.  We get around this by making
-   the value of the identifier point to a list of all the things that
-   want to be referenced by that name.  It is then up to the users of
-   that name to decide what to do with that list.
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      if (DECL_TEMPLATE_INSTANTIATION (olddecl)
+         && !DECL_TEMPLATE_INSTANTIATION (newdecl))
+       {
+         /* If newdecl is not a specialization, then it is not a
+            template-related function at all.  And that means that we
+            should have exited above, returning 0.  */
+         my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
+                             0);
 
-   DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its
-   DECL_TEMPLATE_RESULT.  It is dealt with the same way.
+         if (TREE_USED (olddecl))
+           /* From [temp.expl.spec]:
 
-   FLAGS is a bitwise-or of the following values:
-     PUSH_LOCAL: Bind DECL in the current scope, rather than at
-                 namespace scope.
-     PUSH_USING: DECL is being pushed as the result of a using
-                 declaration.
+              If a template, a member template or the member of a class
+              template is explicitly specialized then that
+              specialization shall be declared before the first use of
+              that specialization that would cause an implicit
+              instantiation to take place, in every translation unit in
+              which such a use occurs.  */
+           error ("explicit specialization of %D after first use",
+                     olddecl);
 
-   The value returned may be a previous declaration if we guessed wrong
-   about what language DECL should belong to (C or C++).  Otherwise,
-   it's always DECL (and never something that's not a _DECL).  */
+         SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
 
-tree
-push_overloaded_decl (tree decl, int flags)
-{
-  tree name = DECL_NAME (decl);
-  tree old;
-  tree new_binding;
-  int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
+         /* [temp.expl.spec/14] We don't inline explicit specialization
+            just because the primary template says so.  */
+       }
+      else
+       {
+         if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
+           DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
 
-  timevar_push (TV_NAME_LOOKUP);
-  if (doing_global)
-    old = namespace_binding (name, DECL_CONTEXT (decl));
-  else
-    old = lookup_name_current_level (name);
+         DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
 
-  if (old)
-    {
-      if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
-       {
-         tree t = TREE_TYPE (old);
-         if (IS_AGGR_TYPE (t) && warn_shadow
-             && (! DECL_IN_SYSTEM_HEADER (decl)
-                 || ! DECL_IN_SYSTEM_HEADER (old)))
-           warning ("`%#D' hides constructor for `%#T'", decl, t);
-         old = NULL_TREE;
-       }
-      else if (is_overloaded_fn (old))
-        {
-          tree tmp;
+         /* If either decl says `inline', this fn is inline, unless 
+            its definition was passed already.  */
+         if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
+           DECL_INLINE (olddecl) = 1;
+         DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
 
-         for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
-           {
-             tree fn = OVL_CURRENT (tmp);
+         DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
+           = (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
+       }
 
-             if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
-                 && !(flags & PUSH_USING)
-                 && compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
-                               TYPE_ARG_TYPES (TREE_TYPE (decl))))
-               error ("`%#D' conflicts with previous using declaration `%#D'",
-                         decl, fn);
+      /* Preserve abstractness on cloned [cd]tors.  */
+      DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
 
-             if (duplicate_decls (decl, fn))
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
-           }
+      if (! types_match)
+       {
+         SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
+         COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
+         SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
        }
-      else if (old == error_mark_node)
-       /* Ignore the undefined symbol marker.  */
-       old = NULL_TREE;
-      else
+      if (! types_match || new_defines_function)
        {
-         cp_error_at ("previous non-function declaration `%#D'", old);
-         error ("conflicts with function declaration `%#D'", decl);
-         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
+         /* These need to be copied so that the names are available.
+            Note that if the types do match, we'll preserve inline
+            info and other bits, but if not, we won't.  */
+         DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
+         DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
        }
-    }
+      if (new_defines_function)
+       /* If defining a function declared with other language
+          linkage, use the previously declared language linkage.  */
+       SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
+      else if (types_match)
+       {
+         /* If redeclaring a builtin function, and not a definition,
+            it stays built in.  */
+         if (DECL_BUILT_IN (olddecl))
+           {
+             DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
+             DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
+             /* If we're keeping the built-in definition, keep the rtl,
+                regardless of declaration matches.  */
+             SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
+           }
 
-  if (old || TREE_CODE (decl) == TEMPLATE_DECL)
-    {
-      if (old && TREE_CODE (old) != OVERLOAD)
-       new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
-      else
-       new_binding = ovl_cons (decl, old);
-      if (flags & PUSH_USING)
-       OVL_USED (new_binding) = 1;
+         DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
+         /* Don't clear out the arguments if we're redefining a function.  */
+         if (DECL_ARGUMENTS (olddecl))
+           DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
+       }
     }
-  else
-    /* NAME is not ambiguous.  */
-    new_binding = decl;
+  else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
+    NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
 
-  if (doing_global)
-    set_namespace_binding (name, current_namespace, new_binding);
-  else
-    {
-      /* We only create an OVERLOAD if there was a previous binding at
-        this level, or if decl is a template. In the former case, we
-        need to remove the old binding and replace it with the new
-        binding.  We must also run through the NAMES on the binding
-        level where the name was bound to update the chain.  */
+  /* Now preserve various other info from the definition.  */
+  TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
+  TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
+  DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
+  COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
 
-      if (TREE_CODE (new_binding) == OVERLOAD && old)
+  /* If either declaration has a nondefault visibility, use it.  */
+  if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
+    {
+      if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
+         && DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
        {
-         tree *d;
-
-         for (d = &IDENTIFIER_BINDING (name)->scope->names;
-              *d;
-              d = &TREE_CHAIN (*d))
-           if (*d == old
-               || (TREE_CODE (*d) == TREE_LIST
-                   && TREE_VALUE (*d) == old))
-             {
-               if (TREE_CODE (*d) == TREE_LIST)
-                 /* Just replace the old binding with the new.  */
-                 TREE_VALUE (*d) = new_binding;
-               else
-                 /* Build a TREE_LIST to wrap the OVERLOAD.  */
-                 *d = tree_cons (NULL_TREE, new_binding,
-                                 TREE_CHAIN (*d));
+         warning ("%J'%D': visibility attribute ignored because it",
+                  newdecl, newdecl);
+         warning ("%Jconflicts with previous declaration here", olddecl);
+       }
+      DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+    }
 
-               /* And update the cxx_binding node.  */
-               IDENTIFIER_BINDING (name)->value = new_binding;
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
-             }
+  if (TREE_CODE (newdecl) == FUNCTION_DECL)
+    {
+      int function_size;
 
-         /* We should always find a previous binding in this case.  */
-         abort ();
-       }
+      function_size = sizeof (struct tree_decl);
 
-      /* Install the new binding.  */
-      push_local_binding (name, new_binding, flags);
-    }
+      memcpy ((char *) olddecl + sizeof (struct tree_common),
+             (char *) newdecl + sizeof (struct tree_common),
+             function_size - sizeof (struct tree_common));
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
-}
-\f
-/* Generate an implicit declaration for identifier FUNCTIONID
-   as a function of type int ().  Print a warning if appropriate.  */
+      if (DECL_TEMPLATE_INSTANTIATION (newdecl))
+       /* If newdecl is a template instantiation, it is possible that
+          the following sequence of events has occurred:
 
-tree
-implicitly_declare (tree functionid)
-{
-  register tree decl;
+          o A friend function was declared in a class template.  The
+          class template was instantiated.
 
-  /* We used to reuse an old implicit decl here,
-     but this loses with inline functions because it can clobber
-     the saved decl chains.  */
-  decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
+          o The instantiation of the friend declaration was
+          recorded on the instantiation list, and is newdecl.
 
-  DECL_EXTERNAL (decl) = 1;
-  TREE_PUBLIC (decl) = 1;
+          o Later, however, instantiate_class_template called pushdecl
+          on the newdecl to perform name injection.  But, pushdecl in
+          turn called duplicate_decls when it discovered that another
+          declaration of a global function with the same name already
+          existed.
 
-  /* ISO standard says implicit declarations are in the innermost block.
-     So we record the decl in the standard fashion.  */
-  pushdecl (decl);
-  rest_of_decl_compilation (decl, NULL, 0, 0);
+          o Here, in duplicate_decls, we decided to clobber newdecl.
 
-  if (warn_implicit
-      /* Only one warning per identifier.  */
-      && IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
+          If we're going to do that, we'd better make sure that
+          olddecl, and not newdecl, is on the list of
+          instantiations so that if we try to do the instantiation
+          again we won't get the clobbered declaration.  */
+       reregister_specialization (newdecl, 
+                                  DECL_TI_TEMPLATE (newdecl), 
+                                  olddecl);
+    }
+  else
     {
-      pedwarn ("implicit declaration of function `%#D'", decl);
+      memcpy ((char *) olddecl + sizeof (struct tree_common),
+             (char *) newdecl + sizeof (struct tree_common),
+             sizeof (struct tree_decl) - sizeof (struct tree_common)
+             + TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
     }
 
-  SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
+  DECL_UID (olddecl) = olddecl_uid;
+  if (olddecl_friend)
+    DECL_FRIEND_P (olddecl) = 1;
+
+  /* NEWDECL contains the merged attribute lists.
+     Update OLDDECL to be the same.  */
+  DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
-  return decl;
-}
+  /* 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 olddecl;
+}
+\f
 /* Return zero if the declaration NEWDECL is valid
    when the declaration OLDDECL (assumed to be for the same name)
    has already been seen.
@@ -4438,16 +1960,31 @@ redeclaration_error_message (tree newdecl, tree olddecl)
     }
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
-          && (DECL_TEMPLATE_RESULT (newdecl)
-              != DECL_TEMPLATE_RESULT (olddecl))
-          && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
-          && DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
-         || (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
-             && COMPLETE_TYPE_P (TREE_TYPE (newdecl))
-             && COMPLETE_TYPE_P (TREE_TYPE (olddecl))))
+      tree nt, ot;
+
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+       {
+         if (COMPLETE_TYPE_P (TREE_TYPE (newdecl))
+             && COMPLETE_TYPE_P (TREE_TYPE (olddecl)))
+           return "redefinition of `%#D'";
+         return NULL;
+       }
+
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) != FUNCTION_DECL
+         || (DECL_TEMPLATE_RESULT (newdecl) 
+             == DECL_TEMPLATE_RESULT (olddecl)))
+       return NULL;
+
+      nt = DECL_TEMPLATE_RESULT (newdecl);
+      if (DECL_TEMPLATE_INFO (nt))
+       nt = DECL_TEMPLATE_RESULT (template_for_substitution (nt));
+      ot = DECL_TEMPLATE_RESULT (olddecl);
+      if (DECL_TEMPLATE_INFO (ot))
+       ot = DECL_TEMPLATE_RESULT (template_for_substitution (ot));
+      if (DECL_INITIAL (nt) && DECL_INITIAL (ot))
        return "redefinition of `%#D'";
-      return 0;
+
+      return NULL;
     }
   else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
     {
@@ -4529,8 +2066,7 @@ lookup_label (tree id)
   /* 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));
+      error ("label `%E' referenced outside of any function", id);
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
     }
 
@@ -4771,7 +2307,7 @@ define_label (location_t location, tree name)
 {
   tree decl = lookup_label (name);
   struct named_label_list *ent;
-  register struct cp_binding_level *p;
+  struct cp_binding_level *p;
 
   timevar_push (TV_NAME_LOOKUP);
   for (ent = named_labels; ent; ent = ent->next)
@@ -4847,9 +2383,11 @@ push_switch (tree switch_stmt)
 void
 pop_switch (void)
 {
-  struct cp_switch *cs;
+  struct cp_switch *cs = switch_stack;
+
+  /* Emit warnings as needed.  */
+  c_do_switch_warnings (cs->cases, cs->switch_stmt);
 
-  cs = switch_stack;
   splay_tree_delete (cs->cases);
   switch_stack = switch_stack->next;
   free (cs);
@@ -4862,341 +2400,37 @@ tree
 finish_case_label (tree low_value, tree high_value)
 {
   tree cond, r;
-  register struct cp_binding_level *p;
-
-  if (! switch_stack)
-    {
-      if (high_value)
-       error ("case label not within a switch statement");
-      else if (low_value)
-       error ("case label `%E' not within a switch statement",
-                 low_value);
-      else
-       error ("`default' label not within a switch statement");
-      return NULL_TREE;
-    }
-
-  if (processing_template_decl)
-    {
-      tree label;
-
-      /* For templates, just add the case label; we'll do semantic
-        analysis at instantiation-time.  */
-      label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
-      return add_stmt (build_case_label (low_value, high_value, label));
-    }
-
-  /* Find the condition on which this switch statement depends.  */
-  cond = SWITCH_COND (switch_stack->switch_stmt);
-  if (cond && TREE_CODE (cond) == TREE_LIST)
-    cond = TREE_VALUE (cond);
-
-  r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
-
-  check_switch_goto (switch_stack->level);
-
-  /* After labels, make any new cleanups in the function go into their
-     own new (temporary) binding contour.  */
-  for (p = current_binding_level; 
-       p->kind != sk_function_parms; 
-       p = p->level_chain)
-    p->more_cleanups_ok = 0;
-
-  return r;
-}
-\f
-/* Return the list of declarations of the current level.
-   Note that this list is in reverse order unless/until
-   you nreverse it; and when you do nreverse it, you must
-   store the result back using `storedecls' or you will lose.  */
-
-tree
-getdecls (void)
-{
-  return current_binding_level->names;
-}
-
-/* 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.  */
-
-static void
-storedecls (tree decls)
-{
-  current_binding_level->names = decls;
-}
-
-/* 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
-cxx_remember_type_decls (binding_table table)
-{
-  current_binding_level->type_decls = table;
-}
-\f
-/* Return the type that should be used when TYPE's name is preceded
-   by a tag such as 'struct' or 'union', or null if the name cannot
-   be used in this way.
-
-   For example, when processing the third line of:
-
-       struct A;
-       typedef struct A A;
-       struct A;
-
-   lookup of A will find the typedef.  Given A's typedef, this function
-   will return the type associated with "struct A".  For the tag to be
-   anything other than TYPE, TYPE must be a typedef whose original type
-   has the same name and context as TYPE itself.
-
-   It is not valid for a typedef of an anonymous type to be used with
-   an explicit tag:
-
-       typedef struct { ... } B;
-       struct B;
-
-   Return null for this case.  */
-
-static tree
-follow_tag_typedef (tree type)
-{
-  tree original;
-
-  original = original_type (type);
-  if (! TYPE_NAME (original))
-    return NULL_TREE;
-  if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type)
-      && (CP_DECL_CONTEXT (TYPE_NAME (original))
-         == CP_DECL_CONTEXT (TYPE_NAME (type)))
-      && !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original)))
-    return original;
-  else
-    return NULL_TREE;
-}
-
-/* Given NAME, an IDENTIFIER_NODE,
-   return the structure (or union or enum) definition for that name.
-   Searches binding levels from its SCOPE up to the global level.
-   If THISLEVEL_ONLY is nonzero, searches only the specified context
-   (but skips any sk_cleanup contexts to find one that is
-   meaningful for tags).
-   FORM says which kind of type the caller wants;
-   it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
-   If the wrong kind of type is found, and it's not a template, an error is
-   reported.  */
-
-static tree
-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 (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->kind == sk_namespace)
-       /* Do namespace lookup.  */
-       for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (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
-               && binding && binding->value
-               && DECL_CLASS_TEMPLATE_P (binding->value))
-             old = binding->value;
-           else if (binding)
-             old = select_decl (binding, LOOKUP_PREFER_TYPES);
-            else
-              old = NULL_TREE;
-
-           if (old)
-             {
-               /* We've found something at this binding level.  If it is
-                  a typedef, extract the tag it refers to.  Lookup fails
-                  if the typedef doesn't refer to a taggable type.  */
-               old = TREE_TYPE (old);
-               old = follow_tag_typedef (old);
-               if (!old)
-                 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);
-                   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-                 }
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
-             }
-           if (thislevel_only || tail == global_namespace)
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-         }
-      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", 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->kind != sk_cleanup)
-       {
-         if (level->kind == sk_template_parms && allow_template_parms_p)
-           {
-             /* We must deal with cases like this:
-
-                  template <class T> struct S;
-                  template <class T> struct S {};
-
-                When looking up `S', for the second declaration, we
-                would like to find the first declaration.  But, we
-                are in the pseudo-global level created for the
-                template parameters, rather than the (surrounding)
-                namespace level.  Thus, we keep going one more level,
-                even though THISLEVEL_ONLY is nonzero.  */
-             allow_template_parms_p = 0;
-             continue;
-           }
-         else
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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.
-   Otherwise return 0.  However, the value can never be 0
-   in the cases in which this is used.
-
-   C++: If NAME is nonzero, this is the new name to install.  This is
-   done when replacing anonymous tags with real tag names.  */
-
-static tree
-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)
-    {
-      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);
-}
-\f
-/* Look up NAME in the NAMESPACE.  */
-
-tree
-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);
+  struct cp_binding_level *p;
 
-  if (TREE_CODE (name) == NAMESPACE_DECL)
-    /* This happens for A::B<int> when B is a namespace.  */
-    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
-  else if (TREE_CODE (name) == TEMPLATE_DECL)
+  if (processing_template_decl)
     {
-      /* This happens for A::B where B is a template, and there are no
-        template arguments.  */
-      error ("invalid use of `%D'", name);
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-    }
-
-  namespace = ORIGINAL_NAMESPACE (namespace);
+      tree label;
 
-  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
-    {
-      template_id = name;
-      name = TREE_OPERAND (name, 0);
-      if (TREE_CODE (name) == OVERLOAD)
-       name = DECL_NAME (OVL_CURRENT (name));
-      else if (DECL_P (name))
-       name = DECL_NAME (name);
+      /* For templates, just add the case label; we'll do semantic
+        analysis at instantiation-time.  */
+      label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
+      return add_stmt (build_case_label (low_value, high_value, label));
     }
 
-  my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
-
-  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 = binding.value;
+  /* Find the condition on which this switch statement depends.  */
+  cond = SWITCH_COND (switch_stack->switch_stmt);
+  if (cond && TREE_CODE (cond) == TREE_LIST)
+    cond = TREE_VALUE (cond);
 
-      if (template_id)
-       {
-         if (DECL_CLASS_TEMPLATE_P (val))
-           val = lookup_template_class (val,
-                                        TREE_OPERAND (template_id, 1),
-                                        /*in_decl=*/NULL_TREE,
-                                        /*context=*/NULL_TREE,
-                                        /*entering_scope=*/0,
-                                        tf_error | tf_warning);
-         else if (DECL_FUNCTION_TEMPLATE_P (val)
-                  || TREE_CODE (val) == OVERLOAD)
-           val = lookup_template_function (val,
-                                           TREE_OPERAND (template_id, 1));
-         else
-           {
-             error ("`%D::%D' is not a template",
-                       namespace, name);
-             POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-           }
-       }
+  r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
 
-      /* If we have a single function from a using decl, pull it out.  */
-      if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
-       val = OVL_FUNCTION (val);
+  check_switch_goto (switch_stack->level);
 
-      /* Ignore built-in functions that haven't been prototyped yet.  */
-      if (!val || !DECL_P(val)
-          || !DECL_LANG_SPECIFIC(val)
-          || !DECL_ANTICIPATED (val))
-        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
-    }
+  /* After labels, make any new cleanups in the function go into their
+     own new (temporary) binding contour.  */
+  for (p = current_binding_level; 
+       p->kind != sk_function_parms; 
+       p = p->level_chain)
+    p->more_cleanups_ok = 0;
 
-  error ("`%D' undeclared in namespace `%D'", name, namespace);
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
+  return r;
 }
-
+\f
 /* Hash a TYPENAME_TYPE.  K is really of type `tree'.  */
 
 static hashval_t
@@ -5336,7 +2570,7 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
       return error_mark_node;
     }
 
-  if (! uses_template_parms (context)
+  if (!dependent_type_p (context)
       || currently_open_class (context))
     {
       if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
@@ -5374,516 +2608,94 @@ make_typename_type (tree context, tree name, tsubst_flags_t complain)
 
          t = lookup_field (context, name, 0, true);
          if (t)
-           {
-             if (TREE_CODE (t) != TYPE_DECL)
-               {
-                 if (complain & tf_error)
-                   error ("no type named `%#T' in `%#T'", name, context);
-                 return error_mark_node;
-               }
-
-             if (complain & tf_error)
-               perform_or_defer_access_check (TYPE_BINFO (context), t);
-
-             if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
-               t = TREE_TYPE (t);
-             
-             return t;
-           }
-       }
-    }
-
-  /* If the CONTEXT is not a template type, then either the field is
-     there now or its never going to be.  */
-  if (!uses_template_parms (context))
-    {
-      if (complain & tf_error)
-       error ("no type named `%#T' in `%#T'", name, context);
-      return error_mark_node;
-    }
-
-  return build_typename_type (context, name, fullname);
-}
-
-/* Resolve `CONTEXT::template NAME'.  Returns an appropriate type,
-   unless an error occurs, in which case error_mark_node is returned.
-   If we locate a TYPE_DECL, we return that, rather than the _TYPE it
-   corresponds to.  If COMPLAIN zero, don't complain about any errors
-   that occur.  */
-
-tree
-make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
-{
-  tree t;
-  tree d;
-
-  if (TYPE_P (name))
-    name = TYPE_IDENTIFIER (name);
-  else if (DECL_P (name))
-    name = DECL_NAME (name);
-  if (TREE_CODE (name) != IDENTIFIER_NODE)
-    abort ();
-
-  if (!uses_template_parms (context)
-      || currently_open_class (context))
-    {
-      tree tmpl = NULL_TREE;
-
-      if (IS_AGGR_TYPE (context))
-       tmpl = lookup_field (context, name, 0, false);
-
-      if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
-       {
-         if (complain & tf_error)
-           error ("no class template named `%#T' in `%#T'", name, context);
-         return error_mark_node;
-       }
-      
-      if (complain & tf_error)
-       perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
-
-      return tmpl;
-    }
-
-  /* Build the UNBOUND_CLASS_TEMPLATE.  */
-  t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
-  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
-  TREE_TYPE (t) = NULL_TREE;
-
-  /* Build the corresponding TEMPLATE_DECL.  */
-  d = build_decl (TEMPLATE_DECL, name, t);
-  TYPE_NAME (TREE_TYPE (d)) = d;
-  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
-  DECL_CONTEXT (d) = FROB_CONTEXT (context);
-  DECL_ARTIFICIAL (d) = 1;
-
-  return t;
-}
-
-/* Select the right _DECL from multiple choices.  */
-
-static tree
-select_decl (cxx_binding *binding, int flags)
-{
-  tree val;
-  val = binding->value;
-
-  timevar_push (TV_NAME_LOOKUP);
-  if (LOOKUP_NAMESPACES_ONLY (flags))
-    {
-      /* We are not interested in types.  */
-      if (val && TREE_CODE (val) == NAMESPACE_DECL)
-        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-    }
-
-  /* If looking for a type, or if there is no non-type binding, select
-     the value binding.  */
-  if (binding->type && (!val || (flags & LOOKUP_PREFER_TYPES)))
-    val = binding->type;
-  /* Don't return non-types if we really prefer types.  */
-  else if (val && LOOKUP_TYPES_ONLY (flags)  && TREE_CODE (val) != TYPE_DECL
-          && (TREE_CODE (val) != TEMPLATE_DECL
-              || !DECL_CLASS_TEMPLATE_P (val)))
-    val = NULL_TREE;
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
-}
-
-/* Unscoped lookup of a global: iterate over current namespaces,
-   considering using-directives.  If SPACESP is non-NULL, store a list
-   of the namespaces we've considered in it.  */
-
-tree
-unqualified_namespace_lookup (tree name, int flags, tree* spacesp)
-{
-  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);
-
-      /* Ignore anticipated built-in functions.  */
-      if (b && b->value && DECL_P (b->value)
-          && DECL_LANG_SPECIFIC (b->value) && DECL_ANTICIPATED (b->value))
-        /* Keep binding cleared.  */;
-      else if (b)
-        {
-          /* Initialize binding for this context.  */
-          binding.value = b->value;
-          binding.type = b->type;
-        }
-
-      /* Add all _DECLs seen through local using-directives.  */
-      for (level = current_binding_level;
-          level->kind != sk_namespace;
-          level = level->level_chain)
-       if (!lookup_using_namespace (name, &binding, level->using_directives,
-                                     scope, flags, spacesp))
-         /* Give up because of error.  */
-         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, &binding,
-                                       DECL_NAMESPACE_USING (siter),
-                                      scope, flags, spacesp))
-           /* Give up because of error.  */
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
-         if (siter == scope) break;
-         siter = CP_DECL_CONTEXT (siter);
-       }
-
-      val = select_decl (&binding, flags);
-      if (scope == global_namespace)
-       break;
-    }
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
-}
-
-/* Combine prefer_type and namespaces_only into flags.  */
-
-static int
-lookup_flags (int prefer_type, int namespaces_only)
-{
-  if (namespaces_only)
-    return LOOKUP_PREFER_NAMESPACES;
-  if (prefer_type > 1)
-    return LOOKUP_PREFER_TYPES;
-  if (prefer_type > 0)
-    return LOOKUP_PREFER_BOTH;
-  return 0;
-}
-
-/* Given a lookup that returned VAL, use FLAGS to decide if we want to
-   ignore it or not.  Subroutine of lookup_name_real.  */
-
-static tree
-qualify_lookup (tree val, int flags)
-{
-  if (val == NULL_TREE)
-    return val;
-  if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
-    return val;
-  if ((flags & LOOKUP_PREFER_TYPES)
-      && (TREE_CODE (val) == TYPE_DECL || TREE_CODE (val) == TEMPLATE_DECL))
-    return val;
-  if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
-    return NULL_TREE;
-  return val;
-}
-
-/* Look up NAME (an IDENTIFIER_NODE) in SCOPE (either a NAMESPACE_DECL
-   or a class TYPE).  If IS_TYPE_P is TRUE, then ignore non-type
-   bindings.  
-
-   Returns a DECL (or OVERLOAD, or BASELINK) representing the
-   declaration found.  If no suitable declaration can be found,
-   ERROR_MARK_NODE is returned.  Iif COMPLAIN is true and SCOPE is
-   neither a class-type nor a namespace a diagnostic is issued.  */
-
-tree
-lookup_qualified_name (tree scope, tree name, bool is_type_p, bool complain)
-{
-  int flags = 0;
-
-  if (TREE_CODE (scope) == NAMESPACE_DECL)
-    {
-      cxx_binding binding;
-
-      cxx_binding_clear (&binding);
-      flags |= LOOKUP_COMPLAIN;
-      if (is_type_p)
-       flags |= LOOKUP_PREFER_TYPES;
-      if (qualified_lookup_using_namespace (name, scope, &binding, 
-                                           flags))
-       return select_decl (&binding, flags);
-    }
-  else if (is_aggr_type (scope, complain))
-    {
-      tree t;
-      t = lookup_member (scope, name, 0, is_type_p);
-      if (t)
-       return t;
-    }
-
-  return error_mark_node;
-}
-
-/* Check to see whether or not DECL is a variable that would have been
-   in scope under the ARM, but is not in scope under the ANSI/ISO
-   standard.  If so, issue an error message.  If name lookup would
-   work in both cases, but return a different result, this function
-   returns the result of ANSI/ISO lookup.  Otherwise, it returns
-   DECL.  */
-
-tree
-check_for_out_of_scope_variable (tree decl)
-{
-  tree shadowed;
-
-  /* We only care about out of scope variables.  */
-  if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
-    return decl;
-
-  shadowed = DECL_SHADOWED_FOR_VAR (decl);
-  while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
-        && DECL_DEAD_FOR_LOCAL (shadowed))
-    shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
-  if (!shadowed)
-    shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (decl));
-  if (shadowed)
-    {
-      if (!DECL_ERROR_REPORTED (decl))
-       {
-         warning ("name lookup of `%D' changed",
-                     DECL_NAME (decl));
-         cp_warning_at ("  matches this `%D' under ISO standard rules",
-                        shadowed);
-         cp_warning_at ("  matches this `%D' under old rules", decl);
-         DECL_ERROR_REPORTED (decl) = 1;
-       }
-      return shadowed;
-    }
-
-  /* If we have already complained about this declaration, there's no
-     need to do it again.  */
-  if (DECL_ERROR_REPORTED (decl))
-    return decl;
-
-  DECL_ERROR_REPORTED (decl) = 1;
-  if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
-    {
-      error ("name lookup of `%D' changed for new ISO `for' scoping",
-            DECL_NAME (decl));
-      cp_error_at ("  cannot use obsolete binding at `%D' because it has a destructor", decl);
-      return error_mark_node;
-    }
-  else
-    {
-      pedwarn ("name lookup of `%D' changed for new ISO `for' scoping",
-              DECL_NAME (decl));
-      cp_pedwarn_at ("  using obsolete binding at `%D'", decl);
-    }
-
-  return decl;
-}
-
-/* Look up NAME in the current binding level and its superiors in the
-   namespace of variables, functions and typedefs.  Return a ..._DECL
-   node of some kind representing its definition if there is only one
-   such declaration, or return a TREE_LIST with all the overloaded
-   definitions if there are many, or return 0 if it is undefined.
-
-   If PREFER_TYPE is > 0, we prefer TYPE_DECLs or namespaces.
-   If PREFER_TYPE is > 1, we reject non-type decls (e.g. namespaces).
-   Otherwise we prefer non-TYPE_DECLs.
-
-   If NONCLASS is nonzero, we don't look for the NAME in class scope,
-   using IDENTIFIER_CLASS_VALUE.  */
-
-tree
-lookup_name_real (tree name, int prefer_type, int nonclass, 
-                 int namespaces_only, int flags)
-{
-  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.  */
-  if (IDENTIFIER_TYPENAME_P (name)) 
-    {
-      struct cp_binding_level *level;
-
-      for (level = current_binding_level; 
-          level && level->kind != sk_namespace;
-          level = level->level_chain)
-       {
-         tree class_type;
-         tree operators;
-         
-         /* A conversion operator can only be declared in a class 
-            scope.  */
-         if (level->kind != sk_class)
-           continue;
-         
-         /* Lookup the conversion operator in the class.  */
-         class_type = level->this_entity;
-         operators = lookup_fnfields (class_type, name, /*protect=*/0);
-         if (operators)
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, operators);
-       }
-
-      POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
-    }
-
-  flags |= lookup_flags (prefer_type, namespaces_only);
-
-  /* First, look in non-namespace scopes.  */
-
-  if (current_class_type == NULL_TREE)
-    nonclass = 1;
-
-  for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
-    {
-      tree binding;
-
-      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 (iter->value, flags))
-       binding = iter->value;
-      else if ((flags & LOOKUP_PREFER_TYPES)
-              && qualify_lookup (iter->type, flags))
-       binding = iter->type;
-      else
-       binding = NULL_TREE;
-
-      if (binding)
-       {
-         val = binding;
-         break;
-       }
-    }
-
-  /* Now lookup in namespace scopes.  */
-  if (!val)
-    {
-      tree t = unqualified_namespace_lookup (name, flags, 0);
-      if (t)
-       val = t;
-    }
-
-  if (val)
-    {
-      /* If we have a single function from a using decl, pull it out.  */
-      if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
-       val = OVL_FUNCTION (val);
-    }
-
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
-}
-
-tree
-lookup_name_nonclass (tree name)
-{
-  return lookup_name_real (name, 0, 1, 0, LOOKUP_COMPLAIN);
-}
-
-tree
-lookup_function_nonclass (tree name, tree args)
-{
-  return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
-}
-
-tree
-lookup_name (tree name, int prefer_type)
-{
-  return lookup_name_real (name, prefer_type, 0, 0, LOOKUP_COMPLAIN);
-}
-
-/* Similar to `lookup_name' but look only in the innermost non-class
-   binding level.  */
-
-tree
-lookup_name_current_level (tree name)
-{
-  struct cp_binding_level *b;
-  tree t = NULL_TREE;
-
-  timevar_push (TV_NAME_LOOKUP);
-  b = innermost_nonclass_level ();
+           {
+             if (TREE_CODE (t) != TYPE_DECL)
+               {
+                 if (complain & tf_error)
+                   error ("no type named `%#T' in `%#T'", name, context);
+                 return error_mark_node;
+               }
 
-  if (b->kind == sk_namespace)
-    {
-      t = IDENTIFIER_NAMESPACE_VALUE (name);
+             if (complain & tf_error)
+               perform_or_defer_access_check (TYPE_BINFO (context), t);
 
-      /* extern "C" function() */
-      if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
-       t = TREE_VALUE (t);
+             if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+               t = TREE_TYPE (t);
+             
+             return t;
+           }
+       }
     }
-  else if (IDENTIFIER_BINDING (name)
-          && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
-    {
-      while (1)
-       {
-         if (IDENTIFIER_BINDING (name)->scope == b)
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
 
-         if (b->kind == sk_cleanup)
-           b = b->level_chain;
-         else
-           break;
-       }
+  /* If the CONTEXT is not a template type, then either the field is
+     there now or its never going to be.  */
+  if (!dependent_type_p (context))
+    {
+      if (complain & tf_error)
+       error ("no type named `%#T' in `%#T'", name, context);
+      return error_mark_node;
     }
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
+  return build_typename_type (context, name, fullname);
 }
 
-/* Like lookup_name_current_level, but for types.  */
+/* Resolve `CONTEXT::template NAME'.  Returns an appropriate type,
+   unless an error occurs, in which case error_mark_node is returned.
+   If we locate a TYPE_DECL, we return that, rather than the _TYPE it
+   corresponds to.  If COMPLAIN zero, don't complain about any errors
+   that occur.  */
 
 tree
-lookup_type_current_level (tree name)
+make_unbound_class_template (tree context, tree name, tsubst_flags_t complain)
 {
-  register tree t = NULL_TREE;
+  tree t;
+  tree d;
 
-  timevar_push (TV_NAME_LOOKUP);
-  my_friendly_assert (current_binding_level->kind != sk_namespace, 
-                     980716);
+  if (TYPE_P (name))
+    name = TYPE_IDENTIFIER (name);
+  else if (DECL_P (name))
+    name = DECL_NAME (name);
+  if (TREE_CODE (name) != IDENTIFIER_NODE)
+    abort ();
 
-  if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
-      && REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
+  if (!dependent_type_p (context)
+      || currently_open_class (context))
     {
-      struct cp_binding_level *b = current_binding_level;
-      while (1)
-       {
-         if (purpose_member (name, b->type_shadowed))
-           POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
-                                    REAL_IDENTIFIER_TYPE_VALUE (name));
-         if (b->kind == sk_cleanup)
-           b = b->level_chain;
-         else
-           break;
-       }
-    }
+      tree tmpl = NULL_TREE;
 
-  POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
-}
+      if (IS_AGGR_TYPE (context))
+       tmpl = lookup_field (context, name, 0, false);
 
-\f
+      if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
+       {
+         if (complain & tf_error)
+           error ("no class template named `%#T' in `%#T'", name, context);
+         return error_mark_node;
+       }
+      
+      if (complain & tf_error)
+       perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
 
-/* A chain of TYPE_DECLs for the builtin types.  */
+      return tmpl;
+    }
 
-static GTY(()) tree builtin_type_decls;
+  /* Build the UNBOUND_CLASS_TEMPLATE.  */
+  t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
+  TYPE_CONTEXT (t) = FROB_CONTEXT (context);
+  TREE_TYPE (t) = NULL_TREE;
 
-/* Return a chain of TYPE_DECLs for the builtin types.  */
+  /* Build the corresponding TEMPLATE_DECL.  */
+  d = build_decl (TEMPLATE_DECL, name, t);
+  TYPE_NAME (TREE_TYPE (d)) = d;
+  TYPE_STUB_DECL (TREE_TYPE (d)) = d;
+  DECL_CONTEXT (d) = FROB_CONTEXT (context);
+  DECL_ARTIFICIAL (d) = 1;
 
-tree
-cxx_builtin_type_decls (void)
-{
-  return builtin_type_decls;
+  return t;
 }
 
+\f
+
 /* Push the declarations of builtin types into the namespace.
    RID_INDEX is the index of the builtin type in the array
    RID_POINTERS.  NAME is the name used when looking up the builtin
@@ -5927,10 +2739,7 @@ record_builtin_type (enum rid rid_index,
     TYPE_NAME (type) = tdecl;
 
   if (tdecl)
-    {
-      TREE_CHAIN (tdecl) = builtin_type_decls;
-      builtin_type_decls = tdecl;
-    }
+    debug_hooks->type_decl (tdecl, 0);
 }
 
 /* Record one of the standard Java types.
@@ -6048,15 +2857,11 @@ cxx_init_decl_processing (void)
   /* Create all the identifiers we need.  */
   initialize_predefined_identifiers ();
 
-  /* Fill in back-end hooks.  */
-  lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
-
   /* Create the global variables.  */
   push_to_top_level ();
 
   current_function_decl = NULL_TREE;
-  current_binding_level = NULL_BINDING_LEVEL;
-  free_binding_level = NULL_BINDING_LEVEL;
+  current_binding_level = NULL;
   /* Enter the global namespace.  */
   my_friendly_assert (global_namespace == NULL_TREE, 375);
   global_namespace = build_lang_decl (NAMESPACE_DECL, global_scope_name,
@@ -6231,20 +3036,16 @@ cxx_init_decl_processing (void)
   start_fname_decls ();
 
   /* Show we use EH for cleanups.  */
-  using_eh_for_cleanups ();
-
-  /* Maintain consistency.  Perhaps we should just complain if they
-     say -fwritable-strings?  */
-  if (flag_writable_strings)
-    flag_const_strings = 0;
+  if (flag_exceptions)
+    using_eh_for_cleanups ();
 }
 
 /* Generate an initializer for a function naming variable from
-   NAME. NAME may be NULL, in which case we generate a special
-   ERROR_MARK node which should be replaced later.  */
+   NAME. NAME may be NULL, to indicate a dependent name.  TYPE_P is
+   filled in with the type of the init.  */
 
 tree
-cp_fname_init (const char* name)
+cp_fname_init (const char* name, tree *type_p)
 {
   tree domain = NULL_TREE;
   tree type;
@@ -6261,12 +3062,12 @@ cp_fname_init (const char* name)
   type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
   type = build_cplus_array_type (type, domain);
 
+  *type_p = type;
+  
   if (init)
     TREE_TYPE (init) = type;
   else
-    /* We don't know the value until instantiation time. Make
-       something which will be digested now, but replaced later.  */
-    init = build (ERROR_MARK, type);
+    init = error_mark_node;
   
   return init;
 }
@@ -6275,15 +3076,19 @@ cp_fname_init (const char* name)
    decl, NAME is the initialization string and TYPE_DEP indicates whether
    NAME depended on the type of the function. We make use of that to detect
    __PRETTY_FUNCTION__ inside a template fn. This is being done
-   lazily at the point of first use, so we musn't push the decl now.  */
+   lazily at the point of first use, so we mustn't push the decl now.  */
 
 static tree
 cp_make_fname_decl (tree id, int type_dep)
 {
   const char *const name = (type_dep && processing_template_decl
-                     ? NULL : fname_as_string (type_dep));
-  tree init = cp_fname_init (name);
-  tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
+                           ? NULL : fname_as_string (type_dep));
+  tree type;
+  tree init = cp_fname_init (name, &type);
+  tree decl = build_decl (VAR_DECL, id, type);
+
+  if (name)
+    free ((char *) name);
 
   /* As we're using pushdecl_with_scope, we must set the context.  */
   DECL_CONTEXT (decl) = current_function_decl;
@@ -6302,9 +3107,10 @@ cp_make_fname_decl (tree id, int type_dep)
       while (b->level_chain->kind != sk_function_parms)
        b = b->level_chain;
       pushdecl_with_scope (decl, b);
-    }  
-
-  cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+      cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
+    }
+  else
+    pushdecl_top_level_and_finish (decl, init);
       
   return decl;
 }
@@ -6513,7 +3319,7 @@ fixup_anonymous_aggr (tree t)
 {
   tree *q;
 
-  /* Wipe out memory of synthesized methods */
+  /* Wipe out memory of synthesized methods */
   TYPE_HAS_CONSTRUCTOR (t) = 0;
   TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
   TYPE_HAS_INIT_REF (t) = 0;
@@ -6577,7 +3383,7 @@ check_tag_decl (tree declspecs)
   int saw_friend = 0;
   int saw_typedef = 0;
   tree ob_modifier = NULL_TREE;
-  register tree link;
+  tree link;
   /* If a class, struct, or enum type is declared by the DECLSPECS
      (i.e, if a class-specifier, enum-specifier, or non-typename
      elaborated-type-specifier appears in the DECLSPECS),
@@ -6774,7 +3580,7 @@ start_decl (tree declarator,
             tree prefix_attributes)
 {
   tree decl;
-  register tree type, tem;
+  tree type, tem;
   tree context;
 
   /* This should only be done once on the top most decl.  */
@@ -6900,7 +3706,11 @@ start_decl (tree declarator,
        }
       else
        {
-         tree field = check_classfn (context, decl);
+         tree field = check_classfn (context, decl,
+                                     (processing_template_decl
+                                      > template_class_depth (context))
+                                     ? current_template_parms
+                                     : NULL_TREE);
          if (field && duplicate_decls (decl, field))
            decl = field;
        }
@@ -6931,6 +3741,8 @@ start_decl (tree declarator,
 
   if (processing_template_decl)
     tem = push_template_decl (tem);
+  if (tem == error_mark_node)
+    return error_mark_node;
 
 #if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
   /* Tell the back-end to use or not use .common as appropriate.  If we say
@@ -6958,8 +3770,6 @@ start_decl_1 (tree decl)
   if (type == error_mark_node)
     return;
 
-  maybe_push_cleanup_level (type);
-
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?
        If not, set INITIALIZED to zero, which will indirectly
@@ -7015,12 +3825,20 @@ start_decl_1 (tree decl)
 
   if (! initialized)
     DECL_INITIAL (decl) = NULL_TREE;
+
+  /* Create a new scope to hold this declaration if necessary.
+     Whether or not a new scope is necessary cannot be determined
+     until after the type has been completed; if the type is a
+     specialization of a class template it is not until after
+     instantiation has occurred that TYPE_HAS_NONTRIVIAL_DESTRUCTOR
+     will be set correctly.  */
+  maybe_push_cleanup_level (type);
 }
 
 /* Handle initialization of references.  DECL, TYPE, and INIT have the
    same meaning as in cp_finish_decl.  *CLEANUP must be NULL on entry,
    but will be set to a new CLEANUP_STMT if a temporary is created
-   that must be destroeyd subsequently.
+   that must be destroyed subsequently.
 
    Returns an initializer expression to use to initialize DECL, or
    NULL if the initialization can be performed statically.
@@ -7315,8 +4133,7 @@ reshape_init (tree type, tree *initp)
      enclosed elements.  Advance past the brace-enclosed initializer
      now.  */
   if (TREE_CODE (old_init_value) == CONSTRUCTOR
-      && TREE_TYPE (old_init_value) == NULL_TREE
-      && TREE_HAS_CONSTRUCTOR (old_init_value))
+      && BRACE_ENCLOSED_INITIALIZER_P (old_init_value))
     {
       *initp = TREE_CHAIN (old_init);
       TREE_CHAIN (old_init) = NULL_TREE;
@@ -7386,8 +4203,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);
-      TREE_HAS_CONSTRUCTOR (new_init) = 1;
+      new_init = build_constructor (NULL_TREE, NULL_TREE);
 
       if (CLASS_TYPE_P (type))
        {
@@ -7403,8 +4219,11 @@ reshape_init (tree type, tree *initp)
                 empty class shall have the form of an empty
                 initializer-list {}.  */
              if (!brace_enclosed_p)
-               error ("initializer for `%T' must be brace-enclosed",
-                      type);
+               {
+                 error ("initializer for `%T' must be brace-enclosed",
+                        type);
+                 return error_mark_node;
+               }
            }
          else
            {
@@ -7429,6 +4248,8 @@ reshape_init (tree type, tree *initp)
                    break;
 
                  field_init = reshape_init (TREE_TYPE (field), initp);
+                 if (field_init == error_mark_node)
+                   return error_mark_node;
                  TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
                  CONSTRUCTOR_ELTS (new_init) = field_init;
                  /* [dcl.init.aggr] 
@@ -7442,15 +4263,30 @@ reshape_init (tree type, tree *initp)
                }
            }
        }
-      else if (TREE_CODE (type) == ARRAY_TYPE)
+      else if (TREE_CODE (type) == ARRAY_TYPE
+              || TREE_CODE (type) == VECTOR_TYPE)
        {
          tree index;
          tree max_index;
 
          /* If the bound of the array is known, take no more initializers
             than are allowed.  */
-         max_index = (TYPE_DOMAIN (type) 
-                      ? array_type_nelts (type) : NULL_TREE);
+         max_index = NULL_TREE;
+         if (TREE_CODE (type) == ARRAY_TYPE)
+           {
+             if (TYPE_DOMAIN (type))
+               max_index = array_type_nelts (type);
+           }
+         else
+           {
+             /* For a vector, the representation type is a struct
+                containing a single member which is an array of the
+                appropriate size.  */
+             tree rtype = TYPE_DEBUG_REPRESENTATION_TYPE (type);
+             if (rtype && TYPE_DOMAIN (TREE_TYPE (TYPE_FIELDS (rtype))))
+               max_index = array_type_nelts (TREE_TYPE (TYPE_FIELDS (rtype)));
+           }
+
          /* Loop through the array elements, gathering initializers.  */
          for (index = size_zero_node;
               *initp && (!max_index || !tree_int_cst_lt (max_index, index));
@@ -7459,10 +4295,22 @@ reshape_init (tree type, tree *initp)
              tree element_init;
 
              element_init = reshape_init (TREE_TYPE (type), initp);
+             if (element_init == error_mark_node)
+               return error_mark_node;
              TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
              CONSTRUCTOR_ELTS (new_init) = element_init;
              if (TREE_PURPOSE (element_init))
-               index = TREE_PURPOSE (element_init);
+               {
+                 tree next_index = TREE_PURPOSE (element_init);
+                 if (TREE_CODE (next_index) == IDENTIFIER_NODE)
+                   {
+                     error ("name `%D' used in a GNU-style designated "
+                            "initializer for an array", next_index);
+                     TREE_PURPOSE (element_init) = NULL_TREE;
+                   }
+                 else
+                   index = next_index;
+               }
            }
        }
       else
@@ -7495,6 +4343,7 @@ static tree
 check_initializer (tree decl, tree init, int flags, tree *cleanup)
 {
   tree type = TREE_TYPE (decl);
+  tree init_code = NULL;
 
   /* If `start_decl' didn't like having an initialization, ignore it now.  */
   if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
@@ -7545,7 +4394,8 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
     init = grok_reference_init (decl, type, init, cleanup);
   else if (init)
     {
-      if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
+      if (TREE_CODE (init) == CONSTRUCTOR 
+         && BRACE_ENCLOSED_INITIALIZER_P (init))
        {
          /* [dcl.init] paragraph 13,
             If T is a scalar type, then a declaration of the form
@@ -7570,15 +4420,13 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
         array size from the initializer.  */
       maybe_deduce_size_from_array_init (decl, init);
       type = TREE_TYPE (decl);
-      if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
-       TREE_TYPE (init) = type;
 
       if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
        {
          if (TREE_CODE (type) == ARRAY_TYPE)
            goto initialize_aggr;
          else if (TREE_CODE (init) == CONSTRUCTOR
-                  && TREE_HAS_CONSTRUCTOR (init))
+                  && BRACE_ENCLOSED_INITIALIZER_P (init))
            {
              if (TYPE_NON_AGGREGATE_CLASS (type))
                {
@@ -7611,7 +4459,10 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
        {
        dont_use_constructor:
          if (TREE_CODE (init) != TREE_VEC)
-           init = store_init_value (decl, init);
+           {
+             init_code = store_init_value (decl, init);
+             init = NULL;
+           }
        }
     }
   else if (DECL_EXTERNAL (decl))
@@ -7634,9 +4485,9 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
     check_for_uninitialized_const_var (decl);
 
   if (init && init != error_mark_node)
-    init = build (INIT_EXPR, type, decl, init);
+    init_code = build (INIT_EXPR, type, decl, init);
 
-  return init;
+  return init_code;
 }
 
 /* If DECL is not a local variable, give it RTL.  */
@@ -7668,12 +4519,12 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
   /* Set the DECL_ASSEMBLER_NAME for the variable.  */
   if (asmspec)
     {
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
+      change_decl_assembler_name (decl, get_identifier (asmspec));
       /* The `register' keyword, when used together with an
         asm-specification, indicates that the variable should be
         placed in a particular register.  */
       if (DECL_REGISTER (decl))
-       DECL_C_HARD_REGISTER (decl) = 1;
+       DECL_HARD_REGISTER (decl) = 1;
     }
 
   /* We don't create any RTL for local variables.  */
@@ -7720,59 +4571,6 @@ make_rtl_for_nonlocal_decl (tree decl, tree init, const char* asmspec)
     rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
 }
 
-/* The old ARM scoping rules injected variables declared in the
-   initialization statement of a for-statement into the surrounding
-   scope.  We support this usage, in order to be backward-compatible.
-   DECL is a just-declared VAR_DECL; if necessary inject its
-   declaration into the surrounding scope.  */
-
-void
-maybe_inject_for_scope_var (tree decl)
-{
-  timevar_push (TV_NAME_LOOKUP);
-  if (!DECL_NAME (decl))
-    {
-      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))
-    {
-      timevar_pop (TV_NAME_LOOKUP);
-      return;
-    }
-
-  if (current_binding_level->kind == sk_for)
-    {
-      struct cp_binding_level *outer
-       = current_binding_level->level_chain;
-
-      /* Check to see if the same name is already bound at the outer
-        level, either because it was directly declared, or because a
-        dead for-decl got preserved.  In either case, the code would
-        not have been valid under the ARM scope rules, so clear
-        is_for_scope for the current_binding_level.
-
-        Otherwise, we need to preserve the temp slot for decl to last
-        into the outer binding level.  */
-
-      cxx_binding *outer_binding
-       = IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
-
-      if (outer_binding && outer_binding->scope == outer
-         && (TREE_CODE (outer_binding->value) == VAR_DECL)
-         && DECL_DEAD_FOR_LOCAL (outer_binding->value))
-       {
-         outer_binding->value = DECL_SHADOWED_FOR_VAR (outer_binding->value);
-         current_binding_level->kind = sk_block;
-       }
-    }
-  timevar_pop (TV_NAME_LOOKUP);
-}
-
 /* Generate code to initialize DECL (a local variable).  */
 
 static void
@@ -7854,7 +4652,9 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   const char *asmspec = NULL;
   int was_readonly = 0;
 
-  if (! decl)
+  if (decl == error_mark_node)
+    return;
+  else if (! decl)
     {
       if (init)
        error ("assignment (not initialization) in declaration");
@@ -7869,7 +4669,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   /* If a name was specified, get the string.  */
   if (global_scope_p (current_binding_level))
     asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
-  if (asmspec_tree)
+  if (asmspec_tree) 
     asmspec = TREE_STRING_POINTER (asmspec_tree);
 
   if (init && TREE_CODE (init) == NAMESPACE_DECL)
@@ -7911,6 +4711,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
 
       if (init && DECL_INITIAL (decl))
        DECL_INITIAL (decl) = init;
+      if (TREE_CODE (decl) == VAR_DECL
+         && !DECL_PRETTY_FUNCTION_P (decl)
+         && !dependent_type_p (TREE_TYPE (decl)))
+       maybe_deduce_size_from_array_init (decl, init);
       goto finish_end0;
     }
 
@@ -7943,27 +4747,20 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
   if (TREE_CODE (decl) != FUNCTION_DECL)
     ttype = target_type (type);
 
-  if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
-      && (TYPE_NEEDS_CONSTRUCTING (type) 
-         || TREE_CODE (type) == REFERENCE_TYPE))
+  
+  /* Currently, GNU C++ puts constants in text space, making them
+     impossible to initialize.  In the future, one would hope for
+     an operating system which understood the difference between
+     initialization and the running of a program.  */
+  if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl))
     {
-      /* Currently, GNU C++ puts constants in text space, making them
-        impossible to initialize.  In the future, one would hope for
-        an operating system which understood the difference between
-        initialization and the running of a program.  */
       was_readonly = 1;
-      TREE_READONLY (decl) = 0;
+      if (TYPE_NEEDS_CONSTRUCTING (type) 
+         || TREE_CODE (type) == REFERENCE_TYPE)
+       TREE_READONLY (decl) = 0;
     }
 
-  if (TREE_CODE (decl) == FIELD_DECL && asmspec)
-    {
-      /* This must override the asm specifier which was placed by
-        grokclassfn.  Lay this out fresh.  */
-      SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
-      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
-      make_decl_rtl (decl, asmspec);
-    }
-  else if (TREE_CODE (decl) == VAR_DECL)
+  if (TREE_CODE (decl) == VAR_DECL)
     {
       /* Only PODs can have thread-local storage.  Other types may require
         various kinds of non-trivial initialization.  */
@@ -8038,8 +4835,19 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          || TREE_CODE (type) == METHOD_TYPE)
        abstract_virtuals_error (decl,
                                 strip_array_types (TREE_TYPE (type)));
+      else if (POINTER_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE)
+      {
+       /* If it's either a pointer or an array type, strip through all
+          of them but the last one. If the last is an array type, issue 
+          an error if the element type is abstract.  */
+       while (POINTER_TYPE_P (TREE_TYPE (type)) 
+              || TREE_CODE (TREE_TYPE (type)) == ARRAY_TYPE)
+         type = TREE_TYPE (type);
+       if (TREE_CODE (type) == ARRAY_TYPE)
+         abstract_virtuals_error (decl, TREE_TYPE (type));
+      }
       else
-       abstract_virtuals_error (decl, strip_array_types (type));
+       abstract_virtuals_error (decl, type);
 
       if (TREE_CODE (decl) == FUNCTION_DECL 
          || TREE_TYPE (decl) == error_mark_node)
@@ -8106,10 +4914,10 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
 
   /* If this was marked 'used', be sure it will be output.  */
   if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
-    mark_referenced (DECL_ASSEMBLER_NAME (decl));
+    mark_decl_referenced (decl);
 }
 
-/* This is here for a midend callback from c-common.c */
+/* This is here for a midend callback from c-common.c */
 
 void
 finish_decl (tree decl, tree init, tree asmspec_tree)
@@ -8267,6 +5075,8 @@ start_cleanup_fn (void)
      it is only called via a function pointer, but we avoid unnecessary
      emissions this way.  */
   DECL_INLINE (fndecl) = 1;
+  DECL_DECLARED_INLINE_P (fndecl) = 1;
+  DECL_INTERFACE_KNOWN (fndecl) = 1;
   /* Build the parameter.  */
   if (flag_use_cxa_atexit)
     {
@@ -8468,7 +5278,7 @@ start_handler_parms (tree declspecs, tree declarator)
 int
 complete_array_type (tree type, tree initial_value, int do_default)
 {
-  register tree maxindex = NULL_TREE;
+  tree maxindex = NULL_TREE;
   int value = 0;
 
   if (initial_value)
@@ -8530,6 +5340,7 @@ complete_array_type (tree type, tree initial_value, int do_default)
     {
       tree itype;
       tree domain;
+      tree elt_type;
 
       domain = build_index_type (maxindex);
       TYPE_DOMAIN (type) = domain;
@@ -8547,6 +5358,12 @@ complete_array_type (tree type, tree initial_value, int do_default)
         size of the array.  */
       if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
        TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
+
+      elt_type = TREE_TYPE (type);
+      TYPE_NEEDS_CONSTRUCTING (type)
+       = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (elt_type));
+      TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
+       = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TYPE_MAIN_VARIANT (elt_type));      
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -8611,6 +5428,7 @@ bad_specifiers (tree object,
    TYPE is type this FUNCTION_DECL should have, either FUNCTION_TYPE
    or METHOD_TYPE.
    DECLARATOR is the function's name.
+   PARMS is a chain of PARM_DECLs for the function.
    VIRTUALP is truthvalue of whether the function is virtual or not.
    FLAGS are to be passed through to `grokclassfn'.
    QUALS are qualifiers indicating whether the function is `const'
@@ -8626,6 +5444,7 @@ static tree
 grokfndecl (tree ctype, 
             tree type,
             tree declarator,
+           tree parms,
             tree orig_declarator,
             int virtualp,
             enum overload_flags flags,
@@ -8648,6 +5467,7 @@ grokfndecl (tree ctype,
     type = build_exception_variant (type, raises);
 
   decl = build_lang_decl (FUNCTION_DECL, declarator, type);
+  DECL_ARGUMENTS (decl) = parms;
   /* Propagate volatile out from type to decl.  */
   if (TYPE_VOLATILE (type))
     TREE_THIS_VOLATILE (decl) = 1;
@@ -8696,8 +5516,7 @@ grokfndecl (tree ctype,
     }
 
   /* Members of anonymous types and local classes have no linkage; make
-     them internal.  */
-  /* FIXME what if it gets a name from typedef?  */
+     them internal.  If a typedef is made later, this will be changed.  */
   if (ctype && (TYPE_ANONYMOUS_P (ctype)
                || decl_function_context (TYPE_MAIN_DECL (ctype))))
     publicp = 0;
@@ -8860,7 +5679,11 @@ grokfndecl (tree ctype,
     {
       tree old_decl;
 
-      old_decl = check_classfn (ctype, decl);
+      old_decl = check_classfn (ctype, decl,
+                               (processing_template_decl
+                                > template_class_depth (ctype))
+                               ? current_template_parms
+                               : NULL_TREE);
 
       if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
        /* Because grokfndecl is always supposed to return a
@@ -8871,18 +5694,16 @@ grokfndecl (tree ctype,
 
       if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
          && TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
-       {
-         /* Remove the `this' parm added by grokclassfn.
-            XXX Isn't this done in start_function, too?  */
-         revert_static_member_fn (decl);
-         last_function_parms = TREE_CHAIN (last_function_parms);
-       }
+       /* Remove the `this' parm added by grokclassfn.
+          XXX Isn't this done in start_function, too?  */
+       revert_static_member_fn (decl);
       if (old_decl && DECL_ARTIFICIAL (old_decl))
        error ("definition of implicitly-declared `%D'", old_decl);
 
       if (old_decl)
        {
-         bool ok;
+         tree ok;
+         bool pop_p;
 
          /* Since we've smashed OLD_DECL to its
             DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
@@ -8891,9 +5712,10 @@ grokfndecl (tree ctype,
 
          /* Attempt to merge the declarations.  This can fail, in
             the case of some invalid specialization declarations.  */
-         push_scope (ctype);
+         pop_p = push_scope (ctype);
          ok = duplicate_decls (decl, old_decl);
-         pop_scope (ctype);
+         if (pop_p)
+           pop_scope (ctype);
          if (!ok)
            {
              error ("no `%#D' member function declared in class `%T'",
@@ -9028,7 +5850,19 @@ grokvardecl (tree type,
       if (t)
        {
          if (TYPE_ANONYMOUS_P (t))
-           /* Ignore for now; `enum { foo } e' is pretty common.  */;
+           {
+             if (DECL_EXTERN_C_P (decl))
+               /* Allow this; it's pretty common in C.  */;
+             else
+               {
+                 pedwarn ("non-local variable `%#D' uses anonymous type",
+                          decl);
+                 if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
+                   cp_pedwarn_at ("\
+`%#D' does not refer to the unqualified type, so it is not used for linkage",
+                                  TYPE_NAME (t));
+               }
+           }
          else
            pedwarn ("non-local variable `%#D' uses local type `%T'",
                        decl, t);
@@ -9148,7 +5982,7 @@ check_static_variable_definition (tree decl, tree type)
       error ("invalid in-class initialization of static data member of non-integral type `%T'",
             type);
       /* If we just return the declaration, crashes will sometimes
-        occur.  We therefore return void_type_node, as if this was a
+        occur.  We therefore return void_type_node, as if this were a
         friend declaration, to cause callers to completely ignore
         this declaration.  */
       return 1;
@@ -9169,48 +6003,35 @@ check_static_variable_definition (tree decl, tree type)
 tree
 compute_array_index_type (tree name, tree size)
 {
+  tree type = TREE_TYPE (size);
   tree itype;
 
-  /* If this involves a template parameter, it will be a constant at
-     instantiation time, but we don't know what the value is yet.
-     Even if no template parameters are involved, we may an expression
-     that is not a constant; we don't even simplify `1 + 2' when
-     processing a template.  */
-  if (processing_template_decl)
+  /* The array bound must be an integer type.  */
+  if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
     {
-      /* Resolve a qualified reference to an enumerator or static
-        const data member of ours.  */
-      if (TREE_CODE (size) == SCOPE_REF
-         && TREE_OPERAND (size, 0) == current_class_type)
-       {
-         tree t = lookup_field (current_class_type,
-                                TREE_OPERAND (size, 1), 0, false);
-         if (t)
-           size = t;
-       }
-
-      return build_index_type (build_min (MINUS_EXPR, sizetype,
-                                         size, integer_one_node));
+      if (name)
+       error ("size of array `%D' has non-integral type `%T'", name, type);
+      else
+       error ("size of array has non-integral type `%T'", type);
+      size = integer_one_node;
+      type = TREE_TYPE (size);
     }
 
+  if (abi_version_at_least (2)
+      /* We should only handle value dependent expressions specially.  */
+      ? value_dependent_expression_p (size)
+      /* But for abi-1, we handled all instances in templates. This
+        effects the manglings produced.  */
+      : processing_template_decl)
+    return build_index_type (build_min (MINUS_EXPR, sizetype,
+                                       size, integer_one_node));
+
   /* The size might be the result of a cast.  */
   STRIP_TYPE_NOPS (size);
 
   /* It might be a const variable or enumeration constant.  */
   size = decl_constant_value (size);
 
-  /* The array bound must be an integer type.  */
-  if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
-      && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
-      && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
-    {
-      if (name)
-       error ("size of array `%D' has non-integer type", name);
-      else
-       error ("size of array has non-integer type");
-      size = integer_one_node;
-    }
-
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
     {
@@ -9232,9 +6053,8 @@ compute_array_index_type (tree name, tree size)
            error ("size of array is negative");
          size = integer_one_node;
        }
-      /* Except that an extension we allow zero-sized arrays.  We
-        always allow them in system headers because glibc uses
-        them.  */
+      /* As an extension we allow zero-sized arrays.  We always allow
+        them in system headers because glibc uses them.  */
       else if (integer_zerop (size) && pedantic && !in_system_header)
        {
          if (name)
@@ -9252,38 +6072,36 @@ compute_array_index_type (tree name, tree size)
       else
        error ("size of array is not an integral constant-expression");
     }
+  else if (pedantic)
+    {
+      if (name)
+       pedwarn ("ISO C++ forbids variable-size array `%D'", name);
+      else
+       pedwarn ("ISO C++ forbids variable-size array");
+    }
 
-  /* Compute the index of the largest element in the array.  It is
-     one less than the number of elements in the array.  */
-  itype
-    = fold (cp_build_binary_op (MINUS_EXPR,
-                               cp_convert (ssizetype, size),
-                               cp_convert (ssizetype,
-                                           integer_one_node)));
-
-  /* Check for variable-sized arrays.  We allow such things as an
-     extension, even though they are not allowed in ANSI/ISO C++.  */
-  if (!TREE_CONSTANT (itype))
+  if (processing_template_decl && !TREE_CONSTANT (size))
+    /* A variable sized array.  */
+    itype = build_min (MINUS_EXPR, sizetype, size, integer_one_node);
+  else
     {
-      if (pedantic)
+      /* Compute the index of the largest element in the array.  It is
+        one less than the number of elements in the array.  */
+      itype
+       = fold (cp_build_binary_op (MINUS_EXPR,
+                                   cp_convert (ssizetype, size),
+                                   cp_convert (ssizetype, integer_one_node)));
+      if (!TREE_CONSTANT (itype))
+       /* A variable sized array.  */
+       itype = variable_size (itype);
+      /* Make sure that there was no overflow when creating to a signed
+        index type.  (For example, on a 32-bit machine, an array with
+        size 2^32 - 1 is too big.)  */
+      else if (TREE_OVERFLOW (itype))
        {
-         if (name)
-           pedwarn ("ISO C++ forbids variable-size array `%D'",
-                       name);
-         else
-           pedwarn ("ISO C++ forbids variable-size array");
+         error ("overflow in array dimension");
+         TREE_OVERFLOW (itype) = 0;
        }
-
-      /* Create a variable-sized array index type.  */
-      itype = variable_size (itype);
-    }
-  /* Make sure that there was no overflow when creating to a signed
-     index type.  (For example, on a 32-bit machine, an array with
-     size 2^32 - 1 is too big.)  */
-  else if (TREE_OVERFLOW (itype))
-    {
-      error ("overflow in array dimension");
-      TREE_OVERFLOW (itype) = 0;
     }
 
   /* Create and return the appropriate index type.  */
@@ -9532,6 +6350,7 @@ grokdeclarator (tree declarator,
   tree in_namespace = NULL_TREE;
   tree returned_attrs = NULL_TREE;
   tree scope = NULL_TREE;
+  tree parms = NULL_TREE;
 
   RIDBIT_RESET_ALL (specbits);
   if (decl_context == FUNCDEF)
@@ -9545,7 +6364,7 @@ grokdeclarator (tree declarator,
      and get it as a string, for an error message.  */
   {
     tree *next = &declarator;
-    register tree decl;
+    tree decl;
     name = NULL;
 
     while (next && *next)
@@ -9869,8 +6688,8 @@ grokdeclarator (tree declarator,
 
   for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
     {
-      register int i;
-      register tree id;
+      int i;
+      tree id;
 
       /* Certain parse errors slip through.  For example,
         `int class;' is not caught by the parser. Try
@@ -9936,7 +6755,7 @@ grokdeclarator (tree declarator,
                        longlong = 1;
                    }
                  else if (RIDBIT_SETP (i, specbits))
-                   pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
+                   pedwarn ("duplicate `%E'", id);
 
                  /* Diagnose "__thread extern" or "__thread static".  */
                  if (RIDBIT_SETP (RID_THREAD, specbits))
@@ -9974,10 +6793,9 @@ grokdeclarator (tree declarator,
        error ("two or more data types in declaration of `%s'", name);
       else if (TREE_CODE (id) == IDENTIFIER_NODE)
        {
-         register tree t = lookup_name (id, 1);
+         tree t = lookup_name (id, 1);
          if (!t || TREE_CODE (t) != TYPE_DECL)
-           error ("`%s' fails to be a typedef or built in type",
-                  IDENTIFIER_POINTER (id));
+           error ("`%E' fails to be a typedef or built in type", id);
          else
            {
              type = TREE_TYPE (t);
@@ -10283,7 +7101,7 @@ grokdeclarator (tree declarator,
       else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
        ;
       else if (decl_context == FIELD
-              /* C++ allows static class elements  */
+              /* C++ allows static class elements.  */
               && RIDBIT_SETP (RID_STATIC, specbits))
        /* C++ also allows inlines and signed and unsigned elements,
           but in those cases we don't come in here.  */
@@ -10293,7 +7111,7 @@ grokdeclarator (tree declarator,
          if (decl_context == FIELD)
            {
              tree tmp = NULL_TREE;
-             register int op = 0;
+             int op = 0;
 
              if (declarator)
                {
@@ -10451,6 +7269,13 @@ grokdeclarator (tree declarator,
 
            type = create_array_type_for_decl (dname, type, size);
 
+           if (declarator
+               && (TREE_CODE (declarator) == INDIRECT_REF
+                   || TREE_CODE (declarator) == ADDR_EXPR))
+             /* We can never complete an array type which is the target of a
+                pointer, so go ahead and lay it out.  */
+             layout_type (type);
+
            ctype = NULL_TREE;
          }
          break;
@@ -10526,8 +7351,8 @@ grokdeclarator (tree declarator,
                      error ("destructor cannot be static member function");
                    if (quals)
                      {
-                       error ("destructors may not be `%s'",
-                                 IDENTIFIER_POINTER (TREE_VALUE (quals)));
+                       error ("destructors may not be `%E'",
+                                 TREE_VALUE (quals));
                        quals = NULL_TREE;
                      }
                    if (decl_context == FIELD)
@@ -10555,8 +7380,8 @@ grokdeclarator (tree declarator,
                      }
                    if (quals)
                      {
-                       error ("constructors may not be `%s'",
-                                 IDENTIFIER_POINTER (TREE_VALUE (quals)));
+                       error ("constructors may not be `%E'",
+                               TREE_VALUE (quals));
                        quals = NULL_TREE;
                      }
                    {
@@ -10604,7 +7429,7 @@ grokdeclarator (tree declarator,
 
            declarator = TREE_OPERAND (declarator, 0);
 
-           arg_types = grokparms (inner_parms);
+           arg_types = grokparms (inner_parms, &parms);
 
            if (declarator && flags == DTOR_FLAG)
              {
@@ -10618,7 +7443,7 @@ grokdeclarator (tree declarator,
                  {
                    error ("destructors may not have parameters");
                    arg_types = void_list_node;
-                   last_function_parms = NULL_TREE;
+                   parms = NULL_TREE;
                  }
              }
 
@@ -10669,7 +7494,7 @@ grokdeclarator (tree declarator,
 
          if (TREE_TYPE (declarator))
            {
-             register tree typemodlist;
+             tree typemodlist;
              int erred = 0;
              int constp = 0;
              int volatilep = 0;
@@ -10785,7 +7610,11 @@ grokdeclarator (tree declarator,
                  }
                else if (TREE_CODE (type) == FUNCTION_TYPE)
                  {
-                   if (current_class_type == NULL_TREE || friendp)
+                   if (NEW_DELETE_OPNAME_P (sname))
+                     /* Overloaded operator new and operator delete
+                        are always static functions.  */
+                     ;
+                   else if (current_class_type == NULL_TREE || friendp)
                      type 
                        = build_method_type_directly (ctype, 
                                                      TREE_TYPE (type),
@@ -10932,6 +7761,7 @@ grokdeclarator (tree declarator,
     }
 
   if (declarator == NULL_TREE
+      || TREE_CODE (declarator) == ERROR_MARK
       || TREE_CODE (declarator) == IDENTIFIER_NODE
       || (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
          && (TREE_CODE (type) == FUNCTION_TYPE
@@ -11044,8 +7874,7 @@ grokdeclarator (tree declarator,
     type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
 
   /* Detect where we're using a typedef of function type to declare a
-     function. last_function_parms will not be set, so we must create
-     it now.  */
+     function. PARMS will not be set, so we must create it now.  */
   
   if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
     {
@@ -11060,7 +7889,7 @@ grokdeclarator (tree declarator,
          decls = decl;
        }
       
-      last_function_parms = nreverse (decls);
+      parms = nreverse (decls);
     }
 
   /* If this is a type name (such as, in a cast or sizeof),
@@ -11188,7 +8017,7 @@ grokdeclarator (tree declarator,
     }
 
   {
-    register tree decl;
+    tree decl;
 
     if (decl_context == PARM)
       {
@@ -11254,10 +8083,7 @@ grokdeclarator (tree declarator,
                    return void_type_node;
                  }
 
-               if (declarator == ansi_opname (NEW_EXPR)
-                   || declarator == ansi_opname (VEC_NEW_EXPR)
-                   || declarator == ansi_opname (DELETE_EXPR)
-                   || declarator == ansi_opname (VEC_DELETE_EXPR))
+               if (NEW_DELETE_OPNAME_P (declarator))
                  {
                    if (virtualp)
                      {
@@ -11280,6 +8106,7 @@ grokdeclarator (tree declarator,
            decl = grokfndecl (ctype, type,
                               TREE_CODE (declarator) != TEMPLATE_ID_EXPR
                               ? declarator : dname,
+                              parms,
                               declarator,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, publicp, inlinep,
@@ -11326,6 +8153,7 @@ grokdeclarator (tree declarator,
            decl = grokfndecl (ctype, type,
                               TREE_CODE (declarator) != TEMPLATE_ID_EXPR
                               ? declarator : dname,
+                              parms,
                               declarator,
                               virtualp, flags, quals, raises,
                               friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
@@ -11333,7 +8161,7 @@ grokdeclarator (tree declarator,
            if (decl == NULL_TREE)
              return NULL_TREE;
          }
-       else if (!staticp && ! processing_template_decl
+       else if (!staticp && !dependent_type_p (type)
                 && !COMPLETE_TYPE_P (complete_type (type))
                 && (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
          {
@@ -11359,8 +8187,8 @@ grokdeclarator (tree declarator,
          {
            if (friendp)
              {
-               error ("`%s' is neither function nor member function; cannot be declared friend",
-                      IDENTIFIER_POINTER (declarator));
+               error ("`%E' is neither function nor member function; "
+                       "cannot be declared friend", declarator);
                friendp = 0;
              }
            decl = NULL_TREE;
@@ -11383,15 +8211,14 @@ grokdeclarator (tree declarator,
                  }
                
                decl = do_friend (ctype, declarator, decl,
-                                 last_function_parms, *attrlist,
-                                 flags, quals, funcdef_flag);
+                                 *attrlist, flags, quals, funcdef_flag);
                return decl;
              }
            else
              return void_type_node;
          }
 
-       /* Structure field.  It may not be a function, except for C++ */
+       /* Structure field.  It may not be a function, except for C++ */
 
        if (decl == NULL_TREE)
          {
@@ -11432,13 +8259,6 @@ grokdeclarator (tree 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);
@@ -11504,7 +8324,8 @@ grokdeclarator (tree declarator,
                virtualp = 0;
              }
          }
-       else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
+       else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2
+                && !NEW_DELETE_OPNAME_P (original_name))
          type = build_method_type_directly (ctype, 
                                             TREE_TYPE (type),
                                             TYPE_ARG_TYPES (type));
@@ -11514,7 +8335,7 @@ grokdeclarator (tree declarator,
                   || RIDBIT_SETP (RID_EXTERN, specbits)
                   || !RIDBIT_SETP (RID_STATIC, specbits));
 
-       decl = grokfndecl (ctype, type, original_name, declarator,
+       decl = grokfndecl (ctype, type, original_name, parms, declarator,
                           virtualp, flags, quals, raises,
                           1, friendp,
                           publicp, inlinep, funcdef_flag,
@@ -11616,15 +8437,13 @@ require_complete_types_for_parms (tree parms)
   for (; parms; parms = TREE_CHAIN (parms))
     {
       if (VOID_TYPE_P (TREE_TYPE (parms)))
-        /* grokparms will have already issued an error */
+        /* grokparms will have already issued an error */
         TREE_TYPE (parms) = error_mark_node;
       else if (complete_type_or_else (TREE_TYPE (parms), parms))
        {
          layout_decl (parms, 0);
          DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
        }
-      else
-        TREE_TYPE (parms) = error_mark_node;
     }
 }
 
@@ -11754,10 +8573,10 @@ check_default_argument (tree decl, tree arg)
    flag. If unset, we append void_list_node. A parmlist declared
    as `(void)' is accepted as the empty parmlist.
 
-   Also set last_function_parms to the chain of PARM_DECLs.  */
+   *PARMS is set to the chain of PARM_DECLs created.  */
 
 static tree
-grokparms (tree first_parm)
+grokparms (tree first_parm, tree *parms)
 {
   tree result = NULL_TREE;
   tree decls = NULL_TREE;
@@ -11863,7 +8682,7 @@ grokparms (tree first_parm)
   result = nreverse (result);
   if (!ellipsis)
     result = chainon (result, void_list_node);
-  last_function_parms = decls;
+  *parms = decls;
 
   return result;
 }
@@ -12006,7 +8825,6 @@ grok_ctor_properties (tree ctype, tree decl)
         instantiated, but that's hard to forestall.  */
       error ("invalid constructor; you probably meant `%T (const %T&)'",
                ctype, ctype);
-      SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
       return 0;
     }
   
@@ -12117,21 +8935,9 @@ grok_op_properties (tree decl, int friendp, bool complain)
     }
 
   if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
-    {
-      /* When the compiler encounters the definition of A::operator new, it
-        doesn't look at the class declaration to find out if it's static.  */
-      if (methodp)
-       revert_static_member_fn (decl);
-
-      TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
-    }
+    TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
   else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
-    {
-      if (methodp)
-       revert_static_member_fn (decl);
-
-      TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
-    }
+    TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
   else
     {
       /* An operator function must either be a non-static member function
@@ -12465,8 +9271,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
    Define the tag as a forward-reference if it is not defined.
 
    If a declaration is given, process it here, and report an error if
-   multiple declarations are not identical.  ATTRIBUTE is the attribute
-   appeared in this declaration.
+   multiple declarations are not identical.
 
    GLOBALIZE is false when this is also a definition.  Only look in
    the current frame for the name (since C++ allows new names in any
@@ -12476,11 +9281,11 @@ check_elaborated_type_specifier (enum tag_types tag_code,
    a set of template parameters.  */
 
 tree
-xref_tag (enum tag_types tag_code, tree name, tree attributes, 
+xref_tag (enum tag_types tag_code, tree name,
          bool globalize, bool template_header_p)
 {
   enum tree_code code;
-  register tree t;
+  tree t;
   struct cp_binding_level *b = current_binding_level;
   tree context = NULL_TREE;
 
@@ -12512,7 +9317,7 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
     }
   else
     {
-      tree decl = lookup_name (name, 1);
+      tree decl = lookup_name (name, 2);
 
       if (decl && DECL_CLASS_TEMPLATE_P (decl))
        decl = DECL_TEMPLATE_RESULT (decl);
@@ -12599,25 +9404,7 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
       if (code == ENUMERAL_TYPE)
        {
          error ("use of enum `%#D' without previous declaration", name);
-
-         t = make_node (ENUMERAL_TYPE);
-
-         /* Give the type a default layout like unsigned int
-            to avoid crashing if it does not get defined.  */
-         TYPE_MODE (t) = TYPE_MODE (unsigned_type_node);
-         TYPE_ALIGN (t) = TYPE_ALIGN (unsigned_type_node);
-         TYPE_USER_ALIGN (t) = 0;
-         TREE_UNSIGNED (t) = 1;
-         TYPE_PRECISION (t) = TYPE_PRECISION (unsigned_type_node);
-         TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (unsigned_type_node);
-         TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (unsigned_type_node);
-
-         /* Enable us to recognize when a type is created in class context.
-            To do nested classes correctly, this should probably be cleared
-            out when we leave this classes scope.  Currently this in only
-            done in `start_enum'.  */
-
-         pushtag (name, t, globalize);
+         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
        }
       else
        {
@@ -12630,10 +9417,15 @@ xref_tag (enum tag_types tag_code, tree name, tree attributes,
     {
       if (!globalize && processing_template_decl && IS_AGGR_TYPE (t))
        redeclare_class_template (t, current_template_parms);
+      else if (!processing_template_decl 
+              && CLASS_TYPE_P (t)
+              && CLASSTYPE_IS_TEMPLATE (t))
+       {
+         error ("redeclaration of `%T' as a non-template", t);
+         t = error_mark_node;
+       }
     }
 
-  TYPE_ATTRIBUTES (t) = attributes;
-
   POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
 }
 
@@ -12650,7 +9442,7 @@ xref_tag_from_type (tree old, tree id, int globalize)
   if (id == NULL_TREE)
     id = TYPE_IDENTIFIER (old);
 
-  return xref_tag (tag_kind, id, /*attributes=*/NULL_TREE, globalize, false);
+  return xref_tag (tag_kind, id, globalize, false);
 }
 
 /* REF is a type (named NAME), for which we have just seen some
@@ -12812,7 +9604,15 @@ xref_basetypes (tree ref, tree base_list)
      inheritance order chain.  */
   copy_base_binfos (TYPE_BINFO (ref), ref, NULL_TREE);
   CLASSTYPE_VBASECLASSES (ref) = nreverse (CLASSTYPE_VBASECLASSES (ref));
-  
+
+  if (TYPE_FOR_JAVA (ref))
+    {
+      if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
+       error ("Java class '%T' cannot have multiple bases", ref);
+      if (CLASSTYPE_VBASECLASSES (ref))
+       error ("Java class '%T' cannot have virtual bases", ref);
+    }
+
   /* Unmark all the types.  */
   while (i--)
     {
@@ -12838,7 +9638,7 @@ xref_basetypes (tree ref, tree base_list)
 tree
 start_enum (tree name)
 {
-  register tree enumtype = NULL_TREE;
+  tree enumtype = NULL_TREE;
   struct cp_binding_level *b = current_binding_level;
 
   /* If this is the real definition for a previous forward reference,
@@ -12977,7 +9777,7 @@ finish_enum (tree enumtype)
     {
       underlying_type = integer_types[itk];
       if (TYPE_PRECISION (underlying_type) >= precision
-         && TREE_UNSIGNED (underlying_type) == unsignedp)
+         && TYPE_UNSIGNED (underlying_type) == unsignedp)
        break;
     }
   if (itk == itk_none)
@@ -13014,7 +9814,7 @@ finish_enum (tree enumtype)
   TYPE_MODE (enumtype) = TYPE_MODE (underlying_type);
   TYPE_ALIGN (enumtype) = TYPE_ALIGN (underlying_type);
   TYPE_USER_ALIGN (enumtype) = TYPE_USER_ALIGN (underlying_type);
-  TREE_UNSIGNED (enumtype) = TREE_UNSIGNED (underlying_type);
+  TYPE_UNSIGNED (enumtype) = TYPE_UNSIGNED (underlying_type);
 
   /* Convert each of the enumerators to the type of the underlying
      type of the enumeration.  */
@@ -13040,7 +9840,7 @@ finish_enum (tree enumtype)
       TYPE_PRECISION (t) = TYPE_PRECISION (enumtype);
       TYPE_ALIGN (t) = TYPE_ALIGN (enumtype);
       TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype);
-      TREE_UNSIGNED (t) = TREE_UNSIGNED (enumtype);
+      TYPE_UNSIGNED (t) = TYPE_UNSIGNED (enumtype);
     }
 
   /* Finish debugging output for this type.  */
@@ -13136,7 +9936,9 @@ 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;
+  TREE_CONSTANT (decl) = 1;
+  TREE_INVARIANT (decl) = 1;
+  TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
 
   if (context && context == current_class_type)
@@ -13255,12 +10057,10 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
          else
            doing_friend = 1;
        }
-
-      last_function_parms = DECL_ARGUMENTS (decl1);
     }
   else
     {
-      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
+      decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, &attrs);
       /* If the declarator is not suitable for a function definition,
         cause a syntax error.  */
       if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
@@ -13307,16 +10107,9 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
       && TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
     {
       revert_static_member_fn (decl1);
-      last_function_parms = TREE_CHAIN (last_function_parms);
       ctype = NULL_TREE;
     }
 
-  /* Warn if function was previously implicitly declared
-     (but not if we warned then).  */
-  if (! warn_implicit
-      && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
-    cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
-
   /* Set up current_class_type, and enter the scope of the class, if
      appropriate.  */
   if (ctype)
@@ -13360,7 +10153,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
 
   /* Save the parm names or decls from this function's declarator
      where store_parm_decls will find them.  */
-  current_function_parms = last_function_parms;
+  current_function_parms = DECL_ARGUMENTS (decl1);
 
   /* Make sure the parameter and return types are reasonable.  When
      you declare a function, these types can be incomplete, but they
@@ -13400,9 +10193,6 @@ 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_ESTIMATED_INSNS (decl1) = 0;
-
   /* Let the user know we're compiling this function.  */
   announce_function (decl1);
 
@@ -13412,9 +10202,22 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
   if (!processing_template_decl && !(flags & SF_PRE_PARSED))
     {
       /* A specialization is not used to guide overload resolution.  */
-      if (!DECL_TEMPLATE_SPECIALIZATION (decl1)
-         && ! DECL_FUNCTION_MEMBER_P (decl1))
-       decl1 = pushdecl (decl1);
+      if (!DECL_FUNCTION_MEMBER_P (decl1)
+         && !(DECL_USE_TEMPLATE (decl1) && 
+              PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl1))))
+       {
+         tree olddecl = pushdecl (decl1);
+
+         if (olddecl == error_mark_node)
+           /* If something went wrong when registering the declaration,
+              use DECL1; we have to have a FUNCTION_DECL to use when
+              parsing the body of the function.  */
+           ;
+         else
+           /* Otherwise, OLDDECL is either a previous declaration of
+              the same function or DECL1 itself.  */
+           decl1 = olddecl;
+       }
       else
        {
          /* We need to set the DECL_CONTEXT.  */
@@ -13485,8 +10288,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
      If it belongs to someone else's interface, it is also external.
      This only affects inlines and template instantiations.  */
   else if (interface_unknown == 0
-          && (! DECL_TEMPLATE_INSTANTIATION (decl1)
-              || flag_alt_external_templates))
+          && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
       if (DECL_DECLARED_INLINE_P (decl1) 
          || DECL_TEMPLATE_INSTANTIATION (decl1)
@@ -13507,8 +10309,7 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
       DECL_INTERFACE_KNOWN (decl1) = 1;
     }
   else if (interface_unknown && interface_only
-          && (! DECL_TEMPLATE_INSTANTIATION (decl1)
-              || flag_alt_external_templates))
+          && ! DECL_TEMPLATE_INSTANTIATION (decl1))
     {
       /* If MULTIPLE_SYMBOL_SPACES is defined and we saw a #pragma
         interface, we will have interface_only set but not
@@ -13562,8 +10363,8 @@ start_function (tree declspecs, tree declarator, tree attrs, int flags)
 static void
 store_parm_decls (tree current_function_parms)
 {
-  register tree fndecl = current_function_decl;
-  register tree parm;
+  tree fndecl = current_function_decl;
+  tree parm;
 
   /* This is a chain of any other decls that came in among the parm
      declarations.  If a parm is declared with  enum {foo, bar} x;
@@ -13582,7 +10383,7 @@ store_parm_decls (tree current_function_parms)
 
       /* Must clear this because it might contain TYPE_DECLs declared
             at class level.  */
-      storedecls (NULL_TREE);
+      current_binding_level->names = NULL;
 
       /* If we're doing semantic analysis, then we'll call pushdecl
             for each of these.  We must do them in reverse order so that
@@ -13621,7 +10422,7 @@ store_parm_decls (tree current_function_parms)
      as the decl-chain of the current lexical scope.
      Put the enumerators in as well, at the front so that
      DECL_ARGUMENTS is not modified.  */
-  storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+  current_binding_level->names = chainon (nonparms, DECL_ARGUMENTS (fndecl));
 
   /* Do the starting of the exception specifications, if we have any.  */
   if (flag_exceptions && !processing_template_decl
@@ -13757,8 +10558,8 @@ finish_destructor_body (void)
       be looked up in the scope of the destructor's class and if
       found shall be accessible and unambiguous.  */
       exprstmt = build_op_delete_call
-       (DELETE_EXPR, current_class_ptr, virtual_size,
-        LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
+       (DELETE_EXPR, current_class_ptr, virtual_size, 
+        /*global_p=*/false, NULL_TREE);
 
       if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
@@ -13839,7 +10640,7 @@ finish_function_body (tree compstmt)
 tree
 finish_function (int flags)
 {
-  register tree fndecl = current_function_decl;
+  tree fndecl = current_function_decl;
   tree fntype, ctype = NULL_TREE;
   int inclass_inline = (flags & 2) != 0;
   int nested;
@@ -13866,8 +10667,6 @@ finish_function (int flags)
       which then got a warning when stored in a ptr-to-function variable.  */
 
   my_friendly_assert (building_stmt_tree (), 20000911);
-
-  finish_fname_decls ();
   
   /* For a cloned function, we've already got all the code we need;
      there's no need to add any extra bits.  */
@@ -13892,6 +10691,8 @@ finish_function (int flags)
                              current_eh_spec_block);
     }
 
+  finish_fname_decls ();
+
   /* If we're saving up tree structure, tie off the function now.  */
   finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
@@ -13932,10 +10733,8 @@ finish_function (int flags)
      of curly braces for a function.  */
   my_friendly_assert (stmts_are_full_exprs_p (), 19990831);
 
-  /* Set up the named return value optimization, if we can.  Here, we
-     eliminate the copy from the nrv into the RESULT_DECL and any cleanup
-     for the nrv.  genrtl_start_function and declare_return_variable
-     handle making the nrv and RESULT_DECL share space.  */
+  /* Set up the named return value optimization, if we can.  Candidate
+     variables are selected in check_return_value.  */
   if (current_function_return_value)
     {
       tree r = current_function_return_value;
@@ -13952,16 +10751,9 @@ finish_function (int flags)
          /* 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);
-       }
-      else
-       /* Clear it so genrtl_start_function and declare_return_variable
-          know we're not optimizing.  */
-       current_function_return_value = NULL_TREE;
+       finalize_nrv (&DECL_SAVED_TREE (fndecl), r, DECL_RESULT (fndecl));
+
+      current_function_return_value = NULL_TREE;
     }
 
   /* Remember that we were in class scope.  */
@@ -13979,21 +10771,10 @@ finish_function (int flags)
   if (!processing_template_decl)
     save_function_data (fndecl);
 
-  /* If this function calls `setjmp' it cannot be inlined.  When
-     `longjmp' is called it is not guaranteed to restore the value of
-     local variables that have been modified since the call to
-     `setjmp'.  So, if were to inline this function into some caller
-     `c', then when we `longjmp', we might not restore all variables
-     in `c'.  (It might seem, at first blush, that there's no way for
-     this function to modify local variables in `c', but their
-     addresses may have been stored somewhere accessible to this
-     function.)  */
-  if (!processing_template_decl && calls_setjmp_p (fndecl))
-    DECL_UNINLINABLE (fndecl) = 1;
-
   /* Complain if there's just no return statement.  */
   if (warn_return_type
       && TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
+      && !dependent_type_p (TREE_TYPE (fntype))
       && !current_function_returns_value && !current_function_returns_null
       /* Don't complain if we abort or throw.  */
       && !current_function_returns_abnormally
@@ -14003,8 +10784,21 @@ finish_function (int flags)
       && (DECL_INLINE (fndecl) || processing_template_decl))
     warning ("no return statement in function returning non-void");
 
+  /* Store the end of the function, so that we get good line number
+     info for the epilogue.  */
+  cfun->function_end_locus = input_location;
+
+  /* Genericize before inlining.  */
+  if (!processing_template_decl)
+    {
+      c_genericize (fndecl);
+
+      /* Handle attribute((warn_unused_result)).  Relies on gimple input.  */
+      c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
+    }
+
   /* We're leaving the context of this function, so zap cfun.  It's still in
-     DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation.  */
+     DECL_STRUCT_FUNCTION, and we'll restore it in tree_rest_of_compilation.  */
   cfun = NULL;
   current_function_decl = NULL;
 
@@ -14076,13 +10870,10 @@ start_method (tree declspecs, tree declarator, tree attrlist)
 
   if (DECL_IN_AGGR_P (fndecl))
     {
-      if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
-       {
-         if (DECL_CONTEXT (fndecl)
-             && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
-           error ("`%D' is already defined in class `%T'", fndecl,
-                     DECL_CONTEXT (fndecl));
-       }
+      if (DECL_CONTEXT (fndecl)
+         && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
+       error ("`%D' is already defined in class `%T'", fndecl,
+              DECL_CONTEXT (fndecl));
       return void_type_node;
     }
 
@@ -14112,7 +10903,7 @@ start_method (tree declspecs, tree declarator, tree attrlist)
 
   cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0);
 
-  /* Make a place for the parms */
+  /* Make a place for the parms */
   begin_scope (sk_function_parms, fndecl);
 
   DECL_IN_AGGR_P (fndecl) = 1;
@@ -14134,10 +10925,10 @@ start_method (tree declspecs, tree declarator, tree attrlist)
 tree
 finish_method (tree decl)
 {
-  register tree fndecl = decl;
+  tree fndecl = decl;
   tree old_initial;
 
-  register tree link;
+  tree link;
 
   if (decl == void_type_node)
     return decl;
@@ -14325,8 +11116,6 @@ cxx_push_function_context (struct function * f)
     {
       tree fn = f->decl;
 
-      current_function_is_thunk = DECL_THUNK_P (fn);
-
       if (DECL_SAVED_FUNCTION_DATA (fn))
        {
          /* If we already parsed this function, and we're just expanding it
@@ -14370,20 +11159,10 @@ cp_tree_node_structure (union lang_tree_node * t)
     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;
     default:                   return TS_CP_GENERIC;
     }
 }
 
-/* Return the IDENTIFIER_GLOBAL_VALUE of T, for use in common code, since
-   the definition of IDENTIFIER_GLOBAL_VALUE is different for C and C++.  */
-
-tree
-identifier_global_value        (tree t)
-{
-  return IDENTIFIER_GLOBAL_VALUE (t);
-}
-
 /* Build the void_list_node (void_type_node having been created).  */
 tree
 build_void_list_node (void)
@@ -14393,7 +11172,7 @@ build_void_list_node (void)
   return t;
 }
 
-static int
+bool
 cp_missing_noreturn_ok_p (tree decl)
 {
   /* A missing noreturn is ok for the `main' function.  */