cp-tree.def (CPLUS_BINDING): Update documentation.
[gcc.git] / gcc / cp / decl.c
index 983b2d03b8f14d4f1fdd66b5c64b33d5f8ad0822..7c9a518e1617eb5fd04236fb865fbfcad1e510dd 100644 (file)
@@ -41,6 +41,7 @@ Boston, MA 02111-1307, USA.  */
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
+#include "../hash.h"
 
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free free
@@ -168,8 +169,6 @@ static tree lookup_tag PROTO((enum tree_code, tree,
                              struct binding_level *, int));
 static void set_identifier_type_value_with_scope
        PROTO((tree, tree, struct binding_level *));
-static void set_identifier_local_value_with_scope
-       PROTO((tree, tree, struct binding_level *));
 static void record_builtin_type PROTO((enum rid, char *, tree));
 static void record_unknown_type PROTO((tree, char *));
 static int member_function_or_else PROTO((tree, tree, char *));
@@ -178,6 +177,10 @@ static void bad_specifiers PROTO((tree, char *, int, int, int, int,
 static void lang_print_error_function PROTO((char *));
 static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
 static void check_for_uninitialized_const_var PROTO((tree));
+static unsigned long typename_hash PROTO((hash_table_key));
+static boolean typename_compare PROTO((hash_table_key, hash_table_key));
+static void push_binding PROTO((tree, tree, struct binding_level*));
+static void pop_binding PROTO((tree));
 
 #if defined (DEBUG_CP_BINDING_LEVELS)
 static void indent PROTO((void));
@@ -371,6 +374,10 @@ tree ctor_label;
 
 tree abort_fndecl;
 
+/* A FUNCTION_DECL for the default `::operator delete'.  */
+
+tree global_delete_fndecl;
+
 extern rtx cleanup_label, return_label;
 
 /* If original DECL_RESULT of current function was a register,
@@ -502,11 +509,6 @@ int current_function_returns_null;
 
 tree current_function_return_value;
 
-/* Set to nonzero by `grokdeclarator' for a function
-   whose return type is defaulted, if warnings for this are desired.  */
-
-static int warn_about_return_type;
-
 /* Nonzero means give `double' the same size as `float'.  */
 
 extern int flag_short_double;
@@ -609,7 +611,8 @@ struct binding_level
   {
     /* A chain of _DECL nodes for all variables, constants, functions,
        and typedef types.  These are in the reverse of the order
-       supplied.  */
+       supplied.  There may be OVERLOADs on this list, too, but they
+       are wrapped in TREE_LISTs; the TREE_VALUE is the OVERLOAD.  */
     tree names;
 
     /* A list of structure, union and enum definitions, for looking up
@@ -629,16 +632,16 @@ struct binding_level
        VALUE the common ancestor with this binding_level's namespace. */
     tree using_directives;
 
-    /* For each level, a list of shadowed outer-level local definitions
-       to be restored when this level is popped.
-       Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
-       whose TREE_VALUE is its old definition (a kind of ..._DECL node).  */
-    tree shadowed;
-
-    /* Same, for IDENTIFIER_CLASS_VALUE.  */
+    /* 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_VALUE is
+       the IDENTIFIER_CLASS_VALUE before we entered the class.  Thus,
+       when leaving class scope, we can restore the
+       IDENTIFIER_CLASS_VALUE by walking this list.  */
     tree class_shadowed;
 
-    /* Same, for IDENTIFIER_TYPE_VALUE.  */
+    /* Similar to class_shadowed, but for IDENTIFIER_TYPE_VALUE, and
+       is used for all binding levels.  */
     tree type_shadowed;
 
     /* For each level (except not the global one),
@@ -659,7 +662,8 @@ struct binding_level
 
     /* List of VAR_DECLS saved from a previous for statement.
        These would be dead in ANSI-conforming code, but might
-       be referenced in ARM-era code.  */
+       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;
 
     /* 1 for the level that holds the parameters of a function.
@@ -1028,6 +1032,112 @@ pushlevel_temporary (tag_transparent)
   expand_start_bindings (0);
 }
 
+/* For a binding between a name and an entity at a block scope,
+   this is the `struct binding_level' for the block.  */
+#define BINDING_LEVEL(NODE) \
+   ((struct binding_level*) ((struct tree_binding*)NODE)->scope)
+
+/* These are currently unused, but permanent, CPLUS_BINDING nodes.
+   They are kept here because they are allocated from the permanent
+   obstack and cannot be easily freed.  */
+static tree free_binding_nodes;
+
+/* Make DECL the innermost binding for ID.  The LEVEL is the binding
+   level at which this declaration is being bound.  */
+
+static void
+push_binding (id, decl, level)
+     tree id;
+     tree decl;
+     struct binding_level* level;
+{
+  tree binding;
+
+  if (!free_binding_nodes)
+    {
+      /* There are no free nodes, so we must build one here.  */
+      push_obstacks_nochange ();
+      end_temporary_allocation ();
+      binding = make_node (CPLUS_BINDING);
+      pop_obstacks ();
+    }
+  else
+    {
+      /* There are nodes on the free list.  Grab the first one.  */
+      binding = free_binding_nodes;
+      
+      /* And update the free list.  */
+      free_binding_nodes = TREE_CHAIN (free_binding_nodes);
+    }
+
+  /* Now, fill in the binding information.  */
+  BINDING_VALUE (binding) = decl;
+  BINDING_LEVEL (binding) = level;
+  LOCAL_BINDING_P (binding) = (level != class_binding_level);
+
+  /* And put it on the front of the ilst of bindings for ID.  */
+  TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
+  IDENTIFIER_BINDING (id) = binding;
+}
+
+/* Bind DECL to ID in the current_binding_level.  */
+
+void
+push_local_binding (id, decl)
+     tree id;
+     tree decl;
+{
+  tree d = decl;;
+
+  if (TREE_CODE (decl) == OVERLOAD)
+    /* We must put the OVERLOAD into a TREE_LIST since the
+       TREE_CHAIN of an OVERLOAD is already used.  */
+    decl = build_tree_list (NULL_TREE, decl);
+
+  /* Create a binding, hanging off of ID.  */
+  push_binding (id, d, current_binding_level);
+
+  /* And put DECL on the list of things declared by the current
+     binding level.  */
+  TREE_CHAIN (decl) = current_binding_level->names;
+  current_binding_level->names = decl;
+}
+
+/* Bind DECL to ID in the class_binding_level.  */
+
+void
+push_class_binding (id, decl)
+     tree id;
+     tree decl;
+{
+  push_binding (id, decl, class_binding_level);
+}
+
+/* Remove the innermost binding for ID; it has gone out of scope.  */
+
+static void 
+pop_binding (id) 
+     tree id;
+{
+  tree 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;
+
+  my_friendly_assert (IDENTIFIER_BINDING (id) != NULL_TREE, 0);
+
+  /* Unhook the innermost binding from the list of bindings.  */
+  binding = IDENTIFIER_BINDING (id);
+  IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
+
+  /* And place this list node on the free list.  */
+  TREE_CHAIN (binding) = free_binding_nodes;
+  free_binding_nodes = binding;
+}
+
 /* Exit a binding level.
    Pop the level off, and restore the state of the identifier-decl mappings
    that were in effect when this level was entered.
@@ -1036,12 +1146,6 @@ pushlevel_temporary (tag_transparent)
    and create a "block" (a BLOCK node) for the level
    to record its declarations and subblocks for symbol table output.
 
-   If KEEP == 2, this level's subblocks go to the front,
-   not the back of the current binding level.  This happens,
-   for instance, when code for constructors and destructors
-   need to generate code at the end of a function which must
-   be moved up to the front of the function.
-
    If FUNCTIONBODY is nonzero, this level is the body of a function,
    so create a block as if KEEP were set and also clear out all
    label names.
@@ -1067,6 +1171,18 @@ poplevel (keep, reverse, functionbody)
   tree block = NULL_TREE;
   tree decl;
   int block_previously_created;
+  int leaving_for_scope;
+
+  if (current_binding_level->parm_flag == 2
+      || current_binding_level->class_shadowed)
+    /* We should not be using poplevel to pop a class binding level.
+       Use poplevel_class instead.  */
+    my_friendly_abort (0);
+
+  /* We used to use KEEP == 2 to indicate that the new block should go
+     at the beginning of the list of blocks at this binding level,
+     rather than the end.  This hack is no longer used.  */
+  my_friendly_assert (keep == 0 || keep == 1, 0);
 
   GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
                      (HOST_WIDE_INT) current_binding_level->level_chain,
@@ -1126,9 +1242,8 @@ poplevel (keep, reverse, functionbody)
          if (decls || tags || subblocks)
            {
              if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
-               {
-                 warning ("internal compiler error: debugging info corrupted");
-               }
+               warning ("internal compiler error: debugging info corrupted");
+
              BLOCK_VARS (block) = decls;
              BLOCK_TYPE_TAGS (block) = tags;
 
@@ -1147,7 +1262,8 @@ poplevel (keep, reverse, functionbody)
          BLOCK_VARS (block) = decls;
          BLOCK_TYPE_TAGS (block) = tags;
          BLOCK_SUBBLOCKS (block) = subblocks;
-         /* Otherwise, for a new block, install a new BLOCK_END_NOTE value.  */
+         /* Otherwise, for a new block, install a new BLOCK_END_NOTE
+            value.  */ 
          remember_end_note (block);
        }
     }
@@ -1158,92 +1274,116 @@ poplevel (keep, reverse, functionbody)
     for (link = subblocks; link; link = TREE_CHAIN (link))
       BLOCK_SUPERCONTEXT (link) = block;
 
-  /* Clear out the meanings of the local variables of this level.  */
-
-  if (current_binding_level->is_for_scope && flag_new_for_scope == 1)
-    {
-      struct binding_level *outer = current_binding_level->level_chain;
-      for (link = decls; link; link = TREE_CHAIN (link))
-       {
-         if (TREE_CODE (link) == VAR_DECL)
-           DECL_DEAD_FOR_LOCAL (link) = 1;
+  /* We still support the old for-scope rules, whereby the variables
+     in a for-init statement were in scope after the for-statement
+     ended.  We only use the new rules in flag_new_for_scope is
+     nonzero.  */
+  leaving_for_scope 
+    = current_binding_level->is_for_scope && flag_new_for_scope == 1;
+
+  /* Remove declarations for all the DECLs in this level.  */
+  for (link = decls; link; link = TREE_CHAIN (link))
+    {
+      if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
+       {
+         tree outer_binding 
+           = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
+         tree ns_binding;
+
+         if (!outer_binding)
+           ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
+                                                  
+         if (outer_binding 
+             && (BINDING_LEVEL (outer_binding) 
+                 == current_binding_level->level_chain))
+           /* We have something like:
+              
+                int i;
+                for (int i; ;);
+                
+              and we are leaving the `for' scope.  There's no reason to
+              keep the binding of the inner `i' in this case.  */
+           pop_binding (DECL_NAME (link));
+         else if ((outer_binding 
+                   && (TREE_CODE (BINDING_VALUE (outer_binding)) 
+                       == TYPE_DECL))
+                  || (ns_binding 
+                      && TREE_CODE (ns_binding) == TYPE_DECL))
+           /* Here, we have something like:
+
+                typedef int I;
+
+                void f () {
+                  for (int I; ;);
+                }
+
+              We must pop the for-scope binding so we know what's a
+              type and what isn't.  */
+           pop_binding (DECL_NAME (link));
          else
-           IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
-       }
-
-      /* Save declarations made in a 'for' statement so we can support pre-ANSI
-        'for' scoping semantics.  */
-
-      for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
-       {
-         tree id = TREE_PURPOSE (link);
-         tree decl = IDENTIFIER_LOCAL_VALUE (id);
-
-         if (decl && DECL_DEAD_FOR_LOCAL (decl))
            {
-             /* In this case keep the dead for-decl visible,
-                but remember what (if anything) it shadowed.  */
-             DECL_SHADOWED_FOR_VAR (decl) = TREE_VALUE (link);
-             TREE_CHAIN (decl) = outer->dead_vars_from_for;
-             outer->dead_vars_from_for = decl;
+             /* Mark this VAR_DECL as dead so that we can tell we left it
+                there only for backward compatibility.  */
+             DECL_DEAD_FOR_LOCAL (link) = 1;
+             
+             /* Keep track of what should of have happenned when we
+                popped the binding.  */
+             if (outer_binding && BINDING_VALUE (outer_binding))
+               DECL_SHADOWED_FOR_VAR (link) 
+                 = BINDING_VALUE (outer_binding);
+
+             /* Add it to the list of dead variables in the next
+                outermost binding to that we can remove these when we
+                leave that binding.  */
+             current_binding_level->level_chain->dead_vars_from_for
+               = tree_cons (NULL_TREE, link,
+                            current_binding_level->level_chain->
+                            dead_vars_from_for);
+
+             /* Although we don't pop the CPLUS_BINDING, we do clear
+                its BINDING_LEVEL since the level is going away now.  */
+             BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
+               = 0;
            }
-         else
-           IDENTIFIER_LOCAL_VALUE (id) = TREE_VALUE (link);
        }
-    }
-  else /* Not special for scope.  */
-    {
-      for (link = decls; link; link = TREE_CHAIN (link))
+      else 
        {
-         if (DECL_NAME (link) != NULL_TREE)
-           {
-             /* If the ident. was used or addressed via a local extern decl,
-                don't forget that fact.  */
-             if (DECL_EXTERNAL (link))
-               {
-                 if (TREE_USED (link))
-                   TREE_USED (DECL_ASSEMBLER_NAME (link)) = 1;
-                 if (TREE_ADDRESSABLE (link))
-                   TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
-               }
-             IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = NULL_TREE;
-           }
+         /* Remove the binding.  */
+         if (TREE_CODE_CLASS (TREE_CODE (link)) == 'd')
+           pop_binding (DECL_NAME (link));
+         else if (TREE_CODE (link) == TREE_LIST)
+           pop_binding (DECL_NAME (OVL_FUNCTION (TREE_VALUE (link))));
+         else
+           my_friendly_abort (0);
        }
+    }
 
-      /* Restore all name-meanings of the outer levels
-        that were shadowed by this level.  */
-
-      for (link = current_binding_level->shadowed;
-          link; link = TREE_CHAIN (link))
-       IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-
-      /* We first restore the regular decls and *then* the dead_vars_from_for
-        to handle this case:
-
-        int i; // i#1
-        {
-          for (int i; ; ) { ...} // i#2
-           int i; // i#3
-        } // we are here
-
-        In this case, we want remove the binding for i#3, restoring
-        that of i#2.  Then we want to remove the binding for i#2,
-        and restore that of i#1.  */
+  /* Remove declarations for any `for' variables from inner scopes
+     that we kept around.  */
+  for (link = current_binding_level->dead_vars_from_for;
+       link; link = TREE_CHAIN (link))
+    pop_binding (DECL_NAME (TREE_VALUE (link)));
 
-      link = current_binding_level->dead_vars_from_for;
-      for (; link != NULL_TREE; link = TREE_CHAIN (link))
-       {
-         tree id = DECL_NAME (link);
-         if (IDENTIFIER_LOCAL_VALUE (id) == link)
-           IDENTIFIER_LOCAL_VALUE (id) = DECL_SHADOWED_FOR_VAR (link);
-       }
+  /* Restore the IDENTIFIER_TYPE_VALUEs.  */
+  for (link = current_binding_level->type_shadowed;
+       link; link = TREE_CHAIN (link))
+    SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+  
+  /* There may be OVERLOADs (wrapped in TREE_LISTs) on the BLOCK_VARs
+     list if a `using' declaration put them there.  The debugging
+     back-ends won't understand OVERLOAD, so we remove them here.
+     Because the BLOCK_VARS are (temporarily) shared with
+     CURRENT_BINDING_LEVEL->NAMES we must do this fixup after we have
+     popped all the bindings.  */
+  if (block)
+    {
+      tree* d;
 
-      for (link = current_binding_level->class_shadowed;
-          link; link = TREE_CHAIN (link))
-       IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-      for (link = current_binding_level->type_shadowed;
-          link; link = TREE_CHAIN (link))
-       SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
+      for (d = &BLOCK_VARS (block); 
+          *d; 
+          d = *d ? &TREE_CHAIN (*d) : d)
+       if (TREE_CODE (*d) == TREE_LIST)
+         *d = TREE_CHAIN (*d);
     }
 
   /* If the level being exited is the top level of a function,
@@ -1318,14 +1458,8 @@ poplevel (keep, reverse, functionbody)
      must be carried forward so they will later become subblocks
      of something else.  */
   else if (subblocks)
-    {
-      if (keep == 2)
-       current_binding_level->blocks
-         = chainon (subblocks, current_binding_level->blocks);
-      else
-       current_binding_level->blocks
-         = chainon (current_binding_level->blocks, subblocks);
-    }
+    current_binding_level->blocks
+      = chainon (current_binding_level->blocks, subblocks);
 
   /* Take care of compiler's internal binding structures.  */
   if (tmp == 2)
@@ -1412,9 +1546,7 @@ pushlevel_class ()
       free_binding_level = free_binding_level->level_chain;
     }
   else
-    {
-      newlevel = make_binding_level ();
-    }
+    newlevel = make_binding_level ();
 
 #if defined(DEBUG_CP_BINDING_LEVELS)
   is_class_level = 1;
@@ -1449,8 +1581,6 @@ poplevel_class (force)
   my_friendly_assert (level != 0, 354);
   
   decl_stack = pop_stack_level (decl_stack);
-  for (shadowed = level->shadowed; shadowed; shadowed = TREE_CHAIN (shadowed))
-    IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (shadowed)) = TREE_VALUE (shadowed);
   /* 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,
@@ -1473,6 +1603,12 @@ poplevel_class (force)
        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));
+
   GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
                      (HOST_WIDE_INT) class_binding_level->level_chain,
                      class_binding_level->parm_flag,
@@ -1579,15 +1715,6 @@ print_binding_level (lvl)
       if (i)
        fprintf (stderr, "\n");
     }
-  if (lvl->shadowed)
-    {
-      fprintf (stderr, " shadowed:");
-      for (t = lvl->shadowed; t; t = TREE_CHAIN (t))
-       {
-         fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
-       }
-      fprintf (stderr, "\n");
-    }
   if (lvl->class_shadowed)
     {
       fprintf (stderr, " class-shadowed:");
@@ -1937,9 +2064,11 @@ store_bindings (names, old_bindings)
       else
        id = DECL_NAME (t);
 
-      if (!id
-         || (!IDENTIFIER_LOCAL_VALUE (id)
-             && !IDENTIFIER_CLASS_VALUE (id)))
+      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 = old_bindings; t1; t1 = TREE_CHAIN (t1))
@@ -1959,9 +2088,9 @@ store_bindings (names, old_bindings)
          my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
          TREE_VEC_ELT (binding, 0) = id;
          TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
-         TREE_VEC_ELT (binding, 2) = IDENTIFIER_LOCAL_VALUE (id);
+         TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
          TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
-         IDENTIFIER_LOCAL_VALUE (id) = NULL_TREE;
+         IDENTIFIER_BINDING (id) = NULL_TREE;
          IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
        }
       TREE_CHAIN (binding) = old_bindings;
@@ -2090,7 +2219,7 @@ pop_from_top_level ()
       if (id)
        {
          SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
-         IDENTIFIER_LOCAL_VALUE (id) = TREE_VEC_ELT (t, 2);
+         IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
          IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
        }
       t = TREE_CHAIN (t);
@@ -2174,26 +2303,6 @@ set_identifier_type_value (id, type)
   set_identifier_type_value_with_scope (id, type, inner_binding_level);
 }
 
-static void
-set_identifier_local_value_with_scope (id, val, b)
-     tree id, val;
-     struct binding_level *b;
-{
-  tree oldlocal;
-  my_friendly_assert (! b->namespace_p, 980716);
-
-  oldlocal = IDENTIFIER_LOCAL_VALUE (id);
-  b->shadowed = tree_cons (id, oldlocal, b->shadowed);
-  IDENTIFIER_LOCAL_VALUE (id) = val;
-}
-
-void
-set_identifier_local_value (id, val)
-     tree id, val;
-{
-  set_identifier_local_value_with_scope (id, val, current_binding_level);
-}
-
 /* Return the type associated with id. */
 
 tree
@@ -2552,7 +2661,7 @@ decls_match (newdecl, olddecl)
          return 0;
        }
 
-      if (comptypes (TREE_TYPE (f1), TREE_TYPE (f2), 1))
+      if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
        {
          if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
              && p2 == NULL_TREE)
@@ -2595,7 +2704,8 @@ decls_match (newdecl, olddecl)
        types_match = 0;
       else
        types_match = comptypes (TREE_TYPE (newdecl),
-                                TREE_TYPE (olddecl), 1);
+                                TREE_TYPE (olddecl),
+                                COMPARE_REDECLARATION);
     }
 
   return types_match;
@@ -2988,9 +3098,6 @@ duplicate_decls (newdecl, olddecl)
                             DECL_TEMPLATE_RESULT (olddecl)))
        cp_error ("invalid redeclaration of %D", newdecl);
       TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
-      DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
-      if (DECL_TEMPLATE_INFO (newdecl))
-       DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
       DECL_TEMPLATE_SPECIALIZATIONS (olddecl) 
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
                   DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@@ -3122,11 +3229,7 @@ duplicate_decls (newdecl, olddecl)
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
       DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-      if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
-       {
-         DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
-         DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
-       }
+      DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       olddecl_friend = DECL_FRIEND_P (olddecl);
     }
 
@@ -3333,14 +3436,14 @@ pushdecl (x)
 {
   register tree t;
   register tree name = DECL_ASSEMBLER_NAME (x);
-  register struct binding_level *b = current_binding_level;
+  int need_new_binding = 1;
 
   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))
       /* Don't change DECL_CONTEXT of virtual methods.  */
       && (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
-      && ! DECL_CONTEXT (x))
+      && !DECL_CONTEXT (x))
     DECL_CONTEXT (x) = current_function_decl;
   if (!DECL_CONTEXT (x))
     DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
@@ -3463,11 +3566,18 @@ pushdecl (x)
            }
        }
 
+      check_template_shadow (x);
+
       if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
        {
          t = push_overloaded_decl (x, 1);
          if (t != x || DECL_LANGUAGE (x) == lang_c)
            return 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))
        return push_overloaded_decl (x, 0);
@@ -3504,7 +3614,15 @@ pushdecl (x)
          if (type != error_mark_node
              && TYPE_NAME (type)
              && TYPE_IDENTIFIER (type))
-            set_identifier_type_value_with_scope (DECL_NAME (x), type, b);
+            set_identifier_type_value_with_scope (DECL_NAME (x), type, 
+                                                 current_binding_level);
+
+         if (TREE_CODE (x) == TYPE_DECL
+             && DECL_ARTIFICIAL (x)
+             && t != NULL_TREE)
+           /* We don't want an artificial TYPE_DECL is we already
+              have another DECL with the same name.  */
+           need_new_binding = 0;
        }
 
       /* Multiple external decls of the same identifier ought to match.
@@ -3527,7 +3645,7 @@ pushdecl (x)
          if (decl
              /* If different sort of thing, we already gave an error.  */
              && TREE_CODE (decl) == TREE_CODE (x)
-             && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl), 1))
+             && !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
            {
              cp_pedwarn ("type mismatch with previous external decl", x);
              cp_pedwarn_at ("previous external decl of `%#D'", decl);
@@ -3545,11 +3663,7 @@ pushdecl (x)
          if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
            TREE_PUBLIC (name) = 1;
 
-         /* Don't install an artificial TYPE_DECL if we already have
-            another _DECL with that name.  */
-         if (TREE_CODE (x) != TYPE_DECL
-             || t == NULL_TREE
-             || ! DECL_ARTIFICIAL (x))
+         if (need_new_binding)
            {
              if (TREE_CODE (x) == FUNCTION_DECL)
                my_friendly_assert 
@@ -3584,25 +3698,29 @@ pushdecl (x)
       else
        {
          /* Here to install a non-global value.  */
-         tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
+         tree oldlocal = IDENTIFIER_VALUE (name);
          tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
 
-         /* Don't install an artificial TYPE_DECL if we already have
-            another _DECL with that name.  */
-         if (TREE_CODE (x) != TYPE_DECL
-             || t == NULL_TREE
-             || ! DECL_ARTIFICIAL (x))
-           set_identifier_local_value_with_scope (name, x, b);
+         if (need_new_binding)
+           {
+             push_local_binding (name, x);
+             /* 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_with_scope (name, TREE_TYPE (x), b);
+           set_identifier_type_value_with_scope (name, TREE_TYPE (x), 
+                                                 current_binding_level);
 
          /* 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_with_scope (name, NULL_TREE, b);
+           set_identifier_type_value_with_scope (name, NULL_TREE, 
+                                                 current_binding_level);
 
          /* If this is an extern function declaration, see if we
             have a global definition or declaration for the function.  */
@@ -3628,9 +3746,7 @@ pushdecl (x)
              && oldglobal == NULL_TREE
              && DECL_EXTERNAL (x)
              && TREE_PUBLIC (x))
-           {
-             TREE_PUBLIC (name) = 1;
-           }
+           TREE_PUBLIC (name) = 1;
 
          if (DECL_FROM_INLINE (x))
            /* Inline decls shadow nothing.  */;
@@ -3651,7 +3767,8 @@ pushdecl (x)
              if (b->parm_flag == 1)
                cp_error ("declaration of `%#D' shadows a parameter", name);
            }
-         else if (warn_shadow && oldlocal != NULL_TREE && b->is_for_scope
+         else if (warn_shadow && oldlocal != NULL_TREE
+                  && current_binding_level->is_for_scope
                   && !DECL_DEAD_FOR_LOCAL (oldlocal))
            {
              warning ("variable `%s' shadows local",
@@ -3682,16 +3799,6 @@ pushdecl (x)
              if (warnstring)
                warning (warnstring, IDENTIFIER_POINTER (name));
            }
-         /* Check to see if decl redeclares a template parameter. */
-         if (oldlocal && (current_class_type || current_function_decl) 
-             && current_template_parms)
-           {
-             if (decl_template_parm_p (oldlocal))
-               {
-                 cp_error ("re-using name of template parameter `%T' in this scope", name);
-                 cp_error_at (" previously declared here `%#D'", oldlocal);
-               }
-           }
        }
 
       if (TREE_CODE (x) == FUNCTION_DECL)
@@ -3705,15 +3812,20 @@ pushdecl (x)
              /* RTTI TD entries are created while defining the type_info.  */
              || (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
                  && TYPE_BEING_DEFINED (TREE_TYPE (x)))))
-       b->incomplete = tree_cons (NULL_TREE, x, b->incomplete);
+       current_binding_level->incomplete 
+         = tree_cons (NULL_TREE, x, current_binding_level->incomplete);
     }
 
-  /* Put decls on list in reverse order.
-     We will reverse them later if necessary.  */
-  TREE_CHAIN (x) = b->names;
-  b->names = x;
-  if (! (b != global_binding_level || TREE_PERMANENT (x)))
-    my_friendly_abort (124);
+  if (need_new_binding)
+    {
+      /* Put decls on list in reverse order.
+        We will reverse them later if necessary.  */
+      TREE_CHAIN (x) = current_binding_level->names;
+      current_binding_level->names = x;
+      if (! (current_binding_level != global_binding_level 
+            || TREE_PERMANENT (x)))
+       my_friendly_abort (124);
+    }
 
   return x;
 }
@@ -3827,8 +3939,8 @@ pushdecl_class_level (x)
             Types, enums, and static vars are checked here; other
             members are checked in finish_struct.  */
          tree icv = IDENTIFIER_CLASS_VALUE (name);
-         tree ilv = IDENTIFIER_LOCAL_VALUE (name);
 
+         /* This should match check_member_decl_is_same_in_complete_scope.  */
          if (icv && icv != x
              && flag_optional_diags
              /* Don't complain about inherited names.  */
@@ -3842,24 +3954,12 @@ pushdecl_class_level (x)
                             icv);
            }
 
-         /* Check to see if decl redeclares a template parameter. */
-         if (ilv && ! decls_match (ilv, x)
-             && (current_class_type || current_function_decl) 
-             && current_template_parms)
-           {
-             if (decl_template_parm_p (ilv))
-               {
-                 cp_error ("re-using name of template parameter `%T' in this scope", name);
-                 cp_error_at (" previously declared here `%#D'", ilv);
-               }
-           }
+         check_template_shadow (x);
        }
 
       push_class_level_binding (name, x);
       if (TREE_CODE (x) == TYPE_DECL)
-       {
-         set_identifier_type_value (name, TREE_TYPE (x));
-       }
+       set_identifier_type_value (name, TREE_TYPE (x));
     }
 }
 
@@ -3903,12 +4003,20 @@ push_class_level_binding (name, x)
       && purpose_member (name, class_binding_level->class_shadowed))
     return;
 
+  /* If this declaration shadows a declaration from an enclosing
+     class, then we will need to restore IDENTIFIER_CLASS_VALUE when
+     we leave this class.  Record the shadowed declaration here.  */
   maybe_push_cache_obstack ();
   class_binding_level->class_shadowed
       = tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
                   class_binding_level->class_shadowed);
   pop_obstacks ();
+
+  /* Put the binding on the stack of bindings for the identifier, and
+     update IDENTIFIER_CLASS_VALUE.  */
+  push_class_binding (name, x);
   IDENTIFIER_CLASS_VALUE (name) = x;
+
   obstack_ptr_grow (&decl_obstack, x);
 }
 
@@ -3963,11 +4071,11 @@ push_using_directive (used)
   return ud;
 }
 
-/* DECL is a FUNCTION_DECL 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.
+/* 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.
 
    DECL may also be a TEMPLATE_DECL, with a FUNCTION_DECL in its DECL_RESULT
    slot.  It is dealt with the same way.
@@ -3981,13 +4089,14 @@ push_overloaded_decl (decl, forgettable)
      tree decl;
      int forgettable;
 {
-  tree orig_name = DECL_NAME (decl);
+  tree name = DECL_NAME (decl);
   tree old;
+  tree new_binding;
   int doing_global = (namespace_bindings_p () || ! forgettable);
 
   if (doing_global)
     {
-      old = namespace_binding (orig_name, DECL_CONTEXT (decl));
+      old = namespace_binding (name, DECL_CONTEXT (decl));
       if (old && TREE_CODE (old) == FUNCTION_DECL
          && DECL_ARTIFICIAL (old)
          && (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
@@ -3998,16 +4107,7 @@ push_overloaded_decl (decl, forgettable)
        }
     }
   else
-    {
-      old = IDENTIFIER_LOCAL_VALUE (orig_name);
-
-      if (! purpose_member (orig_name, current_binding_level->shadowed))
-       {
-         current_binding_level->shadowed
-           = tree_cons (orig_name, old, current_binding_level->shadowed);
-         old = NULL_TREE;
-       }
-    }
+    old = lookup_name_current_level (name);
 
   if (old)
     {
@@ -4040,17 +4140,44 @@ push_overloaded_decl (decl, forgettable)
   if (old || TREE_CODE (decl) == TEMPLATE_DECL)
     {
       if (old && TREE_CODE (old) != OVERLOAD)
-       old = ovl_cons (old, NULL_TREE);
-      old = ovl_cons (decl, old);
+       new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
+      else
+       new_binding = ovl_cons (decl, old);
     }
   else
-    /* orig_name is not ambiguous.  */
-    old = decl;
+    /* NAME is not ambiguous.  */
+    new_binding = decl;
 
   if (doing_global)
-    set_namespace_binding (orig_name, current_namespace, old);
+    set_namespace_binding (name, current_namespace, new_binding);
   else
-    IDENTIFIER_LOCAL_VALUE (orig_name) = old;
+    {
+      /* We only create an OVERLOAD if there was a previous binding at
+        this level.  In that case, we need to remove the old binding
+        and replace it with the new binding.  We must also run
+        through the NAMES on the current binding level to update the
+        chain.  */
+      if (TREE_CODE (new_binding) == OVERLOAD)
+       {
+         tree *d;
+         
+         for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
+              *d;
+              d = &TREE_CHAIN (*d))
+           if (*d == old
+               || (TREE_CODE (*d) == TREE_LIST
+                   && TREE_VALUE (*d) == old))
+             {
+               *d = TREE_CHAIN (*d);
+               break;
+             }
+
+         pop_binding (name);
+       }
+
+      /* Install the new binding.  */
+      push_local_binding (name, new_binding);
+    }
 
   return decl;
 }
@@ -4115,7 +4242,7 @@ redeclaration_error_message (newdecl, olddecl)
       /* Because C++ can put things into name space for free,
         constructs like "typedef struct foo { ... } foo"
         would look like an erroneous redeclaration.  */
-      if (comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl), 0))
+      if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
        return 0;
       else
        return "redefinition of `%#D'";
@@ -4345,9 +4472,8 @@ define_label (filename, line, name)
                           and they should be cleaned up
                           by the time we get to the label.  */
                        && ! DECL_ARTIFICIAL (new_decls)
-                       && ((DECL_INITIAL (new_decls) != NULL_TREE
-                            && DECL_INITIAL (new_decls) != error_mark_node)
-                           || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
+                       && !(DECL_INITIAL (new_decls) == NULL_TREE
+                            && pod_type_p (TREE_TYPE (new_decls))))
                      {
                        if (! identified) 
                          {
@@ -4357,8 +4483,13 @@ define_label (filename, line, name)
                                                      "  from here");
                            identified = 1;
                        }
-                       cp_error_at ("  crosses initialization of `%#D'",
-                                    new_decls);
+                       if (DECL_INITIAL (new_decls)
+                           || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls)))
+                         cp_error_at ("  crosses initialization of `%#D'",
+                                      new_decls);
+                       else
+                         cp_error_at ("  enters scope of non-POD `%#D'",
+                                        new_decls);
                      }
                    new_decls = TREE_CHAIN (new_decls);
                  }
@@ -4780,6 +4911,47 @@ lookup_namespace_name (namespace, name)
   return error_mark_node;
 }
 
+/* Hash a TYPENAME_TYPE.  K is really of type `tree'.  */
+
+static unsigned long
+typename_hash (k)
+     hash_table_key k;
+{
+  unsigned long hash;
+  tree t;
+
+  t = (tree) k;
+  hash = (((unsigned long) TYPE_CONTEXT (t))
+         ^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
+
+  return hash;
+}
+
+/* Compare two TYPENAME_TYPEs.  K1 and K2 are really of type `tree'.  */
+
+static boolean
+typename_compare (k1, k2)
+     hash_table_key k1;
+     hash_table_key k2;
+{
+  tree t1;
+  tree t2;
+  tree d1;
+  tree d2;
+
+  t1 = (tree) k1;
+  t2 = (tree) k2;
+  d1 = TYPE_NAME (t1);
+  d2 = TYPE_NAME (t2);
+  
+  return (DECL_NAME (d1) == DECL_NAME (d2)
+         && same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
+         && ((TREE_TYPE (t1) != NULL_TREE) 
+             == (TREE_TYPE (t2) != NULL_TREE))
+         && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
+         && TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
+}
+
 /* Build a TYPENAME_TYPE.  If the type is `typename T::t', CONTEXT is
    the type of `T', NAME is the IDENTIFIER_NODE for `t'.  If BASE_TYPE
    is non-NULL, this type is being created by the implicit typename
@@ -4797,25 +4969,44 @@ build_typename_type (context, name, fullname, base_type)
 {
   tree t;
   tree d;
+  struct hash_entry* e;
 
-  if (processing_template_decl)
-    push_obstacks (&permanent_obstack, &permanent_obstack);
+  static struct hash_table ht;
+
+  push_obstacks (&permanent_obstack, &permanent_obstack);
+
+  if (!ht.table
+      && !hash_table_init (&ht, &hash_newfunc, &typename_hash, 
+                          &typename_compare))
+    fatal ("virtual memory exhausted");
 
   /* Build the TYPENAME_TYPE.  */
   t = make_lang_type (TYPENAME_TYPE);
   TYPE_CONTEXT (t) = FROB_CONTEXT (context);
   TYPENAME_TYPE_FULLNAME (t) = fullname;
   TREE_TYPE (t) = base_type;
-  CLASSTYPE_GOT_SEMICOLON (t) = 1;
 
   /* Build the corresponding TYPE_DECL.  */
   d = build_decl (TYPE_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;
 
-  if (processing_template_decl)
-    pop_obstacks ();
+  /* See if we already have this type.  */
+  e = hash_lookup (&ht, t, /*create=*/false, /*copy=*/0);
+  if (e)
+    {
+      /* This will free not only TREE_TYPE, but the lang-specific data
+        and the TYPE_DECL as well.  */
+      obstack_free (&permanent_obstack, t);
+      t = (tree) e->key;
+    }
+  else
+    /* Insert the type into the table.  */
+    hash_lookup (&ht, t, /*create=*/true, /*copy=*/0);
+
+  pop_obstacks ();
 
   return t;
 }
@@ -5038,7 +5229,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   register tree val;
   int yylex = 0;
   tree from_obj = NULL_TREE;
-  tree locval, classval;
   int flags;
 
   /* Hack: copy flag set by parser, if set. */
@@ -5131,132 +5321,86 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
   else
     flags = lookup_flags (prefer_type, namespaces_only);
 
-  locval = classval = NULL_TREE;
-
-  if (! namespace_bindings_p ())
-    locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
-
-  /* In C++ class fields are between local and global scope,
-     just before the global scope.  */
-  if (current_class_type && ! nonclass)
-    {
-      classval = IDENTIFIER_CLASS_VALUE (name);
-      if (classval == NULL_TREE && TYPE_BEING_DEFINED (current_class_type))
-       /* Try to find values from base classes if we are presently
-          defining a type.  We are presently only interested in
-          TYPE_DECLs.  */
-       classval = lookup_field (current_class_type, name, 0, 1);
-
-      /* Add implicit 'typename' to types from template bases.  lookup_field
-         will do this for us.  If classval is actually from an enclosing
-         scope, lookup_nested_field will get it for us.  */
-      else if (processing_template_decl
-              && classval && TREE_CODE (classval) == TYPE_DECL
-              && ! currently_open_class (DECL_CONTEXT (classval))
-              && uses_template_parms (current_class_type))
-       classval = lookup_field (current_class_type, name, 0, 1);
-
-      /* yylex() calls this with -2, since we should never start digging for
-        the nested name at the point where we haven't even, for example,
-        created the COMPONENT_REF or anything like that.  */
-      if (classval == NULL_TREE)
-       classval = lookup_nested_field (name, ! yylex);
+  /* First, look in a non-global scope, carefully avoiding any
+     class-scope bindings if required.  */
+  val = IDENTIFIER_BINDING (name); 
+  while (val && nonclass && !LOCAL_BINDING_P (val))
+    val = TREE_CHAIN (val);
 
-      classval = qualify_lookup (classval, flags);
+  /* Get the DECL actually bound.  */
+  if (val)
+    val = BINDING_VALUE (val);
+
+  /* If VAL is a type from a dependent base, we're not really supposed
+     to be able to see it; the fact that we can is the "implicit
+     typename" extension.  We call lookup_field here to turn VAL into
+     a TYPE_DECL for a TYPENAME_TYPE.  */
+  if (processing_template_decl && val
+      && val == IDENTIFIER_CLASS_VALUE (name)
+      && TREE_CODE (val) == TYPE_DECL
+      && !currently_open_class (DECL_CONTEXT (val))
+      && uses_template_parms (current_class_type))
+    val = lookup_field (current_class_type, name, 0, 1);
+
+  /* Make sure that this binding is the sort of thing we're looking
+     for.  */
+  val = qualify_lookup (val, flags);
+
+  /* We don't put names from baseclasses onto the IDENTIFIER_BINDING
+     list when we're defining a type.  It would probably be simpler to
+     do this, but we don't.  So, we must lookup names from base
+     classes explicitly.  */
+  if (!val && !nonclass 
+      && current_class_type && TYPE_BEING_DEFINED (current_class_type))
+    {
+      val = qualify_lookup (lookup_field (current_class_type, name, 0, 0),
+                           flags);
+      if (!val)
+       val = qualify_lookup (lookup_nested_field (name, !yylex),
+                             flags);
     }
-
-  if (locval && classval)
+  
+  /* If we found a type from a dependent base class (using the
+     implicit typename extension), turn it into the TYPE_DECL for a
+     TYPENAME_TYPE here.  */
+  if (val && TREE_CODE (val) == TYPE_DECL
+      && IMPLICIT_TYPENAME_P (TREE_TYPE (val)))
     {
-      /* We have both a local binding and a class-level binding.  This
-        can happen in two ways:
-
-          o We are in a member function of a class.
-           o We are in a local class within a function.
-
-        We need to determine which one of these situations is
-        occuring, and give the innermost binding.  One tricky bit is
-        that with member templates we can be in the first case
-        without CURRENT_FUNCTION_DECL being set.  Consider
-         
-          struct A { template <class A> void f(A); };
-
-        Here, when we look at the `A' in the parameter declaration
-        for `f' we have a local binding (the template parameter) and
-        a class-level binding (the TYPE_DECL for the class).
-        Fortunately, if LOCVAL is a template parameter it is safe to
-        take it; nothing within the scope of the template parameter
-        is allowed to have the same name.  */
-
-      if (decl_template_parm_p (locval))
-       val = locval;
-      else if (current_scope () == current_function_decl
-         && ! hack_decl_function_context (current_function_decl))
-       /* Not in a nested function.  */
-       val = locval;
-      else
-       {
-         /* This is incredibly horrible.  The whole concept of
-            IDENTIFIER_LOCAL_VALUE / IDENTIFIER_CLASS_VALUE /
-            IDENTIFIER_GLOBAL_VALUE needs to be scrapped for local
-            classes.  */
-         tree lctx = hack_decl_function_context (locval);
-         tree cctx = hack_decl_function_context (classval);
-
-         if (lctx == current_scope ())
-           val = locval;
-         else if (lctx == cctx)
-           val = classval;
-         else
-           /* I don't know which is right; let's just guess for now.  */
-           val = locval;
-       }
-    }
-  else if (locval)
-    val = locval;
-  else if (classval)
-    val = classval;
-  else
-    val = unqualified_namespace_lookup (name, flags);
+      tree global_val;
 
-  /* Any other name takes precedence over an implicit typename.  Warn the
-     user about this potentially confusing lookup.  */
-  if (classval && TREE_CODE (val) == TYPE_DECL
-      && TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE
-      && TREE_TYPE (TREE_TYPE (val)))
-    {
-      if (locval == NULL_TREE)
-       locval = unqualified_namespace_lookup (name, flags);
+      /* Any other name takes precedence over an implicit typename.  Warn the
+        user about this potentially confusing lookup.  */
+      global_val = unqualified_namespace_lookup (name, flags);
 
-      if (locval && val != locval)
+      if (global_val)
        {
          tree subtype;
 
-         val = locval;
-
-         /* To avoid redundant warnings, only warn when lexing, and the
-            decls are significantly different.  */
-         subtype = TREE_TYPE (TREE_TYPE (classval));
-         if (yylex
-             && ! (TREE_CODE (locval) == TEMPLATE_DECL
+         /* Only warn when not lexing; we don't want to warn if they
+            use this name as a declarator.  */
+         subtype = TREE_TYPE (TREE_TYPE (val));
+         if (! yylex
+             && ! (TREE_CODE (global_val) == TEMPLATE_DECL
                    && CLASSTYPE_TEMPLATE_INFO (subtype)
-                   && CLASSTYPE_TI_TEMPLATE (subtype) == locval)
-             && ! (TREE_CODE (locval) == TYPE_DECL
-                   && comptypes (TREE_TYPE (locval), subtype, 1)))
+                   && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
+             && ! (TREE_CODE (global_val) == TYPE_DECL
+                   && same_type_p (TREE_TYPE (global_val), subtype)))
            {
-             static int explained;
-
-             cp_warning ("lookup of `%D' finds `%#D'", name, locval);
-             cp_warning
-               ("  instead of `%D' from dependent base class", classval);
-             if (! explained)
-               {
-                 explained = 1;
-                 cp_warning ("  (use `typename %D' if that's what you meant)",
-                             classval);
-               }
+             cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
+             cp_warning ("  instead of `%D' from dependent base class",
+                         val);
+             cp_warning ("  (use `typename %T::%D' if that's what you meant)",
+                         constructor_name (current_class_type), name);
            }
+
+         /* Use the global value instead of the implicit typename.  */
+         val = global_val;
        }
     }
+  else if (!val)
+    /* No local, or class-scoped binding.  Look for a namespace-scope
+       declaration.  */
+    val = unqualified_namespace_lookup (name, flags);
 
  done:
   if (val)
@@ -5281,17 +5425,6 @@ lookup_name_real (name, prefer_type, nonclass, namespaces_only)
            val = from_obj;
        }
 
-      if ((TREE_CODE (val) == TEMPLATE_DECL && looking_for_template)
-         || TREE_CODE (val) == TYPE_DECL || prefer_type <= 0)
-       ;
-      /* Caller wants a class-or-namespace-name. */
-      else if (prefer_type == 1 && TREE_CODE (val) == NAMESPACE_DECL)
-       ;
-      else if (IDENTIFIER_HAS_TYPE_VALUE (name))
-       val = TYPE_MAIN_DECL (IDENTIFIER_TYPE_VALUE (name));
-      else if (TREE_TYPE (val) == error_mark_node)
-       val = error_mark_node;
-
       /* If we have a single function from a using decl, pull it out.  */
       if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
        val = OVL_FUNCTION (val);
@@ -5349,13 +5482,16 @@ lookup_name_current_level (name)
       if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
        t = TREE_VALUE (t);
     }
-  else if (IDENTIFIER_LOCAL_VALUE (name) != NULL_TREE)
+  else if (IDENTIFIER_BINDING (name) 
+          && LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
     {
       struct binding_level *b = current_binding_level;
+
       while (1)
        {
-         if (purpose_member (name, b->shadowed))
-           return IDENTIFIER_LOCAL_VALUE (name);
+         if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
+           return IDENTIFIER_VALUE (name);
+         
          if (b->keep == 2)
            b = b->level_chain;
          else
@@ -5593,6 +5729,8 @@ init_decl_processing ()
 
   if (flag_strict_prototype == 2)
     flag_strict_prototype = pedantic;
+  if (! flag_permissive && ! pedantic)
+    flag_pedantic_errors = 1;
 
   strict_prototypes_lang_c = flag_strict_prototype;
 
@@ -5605,7 +5743,6 @@ init_decl_processing ()
   current_binding_level = NULL_BINDING_LEVEL;
   free_binding_level = NULL_BINDING_LEVEL;
 
-#ifndef __CYGWIN32__
   /* Because most segmentation signals can be traced back into user
      code, catch them and at least give the user a chance of working
      around compiler bugs.  */
@@ -5627,13 +5764,6 @@ init_decl_processing ()
 #ifdef SIGBUS
   signal (SIGBUS, signal_catch);
 #endif
-#else /* ndef __CYGWIN32__ */
-  /* Cygwin32 cannot handle catching signals other than
-     SIGABRT yet.  We hope this will cease to be the case soon. */
-#ifdef SIGABRT
-  signal (SIGABRT, signal_catch);
-#endif
-#endif /* ndef __CYGWIN32__ */
 
   gcc_obstack_init (&decl_obstack);
 
@@ -5732,7 +5862,7 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, intTI_type_node));
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
 #endif
   unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
@@ -5744,7 +5874,7 @@ init_decl_processing ()
   pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
   unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
-  pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intTI_type_node));
+  pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
 #endif
 
   float_type_node = make_node (REAL_TYPE);
@@ -6208,7 +6338,7 @@ init_decl_processing ()
   record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
 
   vtbl_type_node
-    = build_array_type (vtable_entry_type, NULL_TREE);
+    = build_cplus_array_type (vtable_entry_type, NULL_TREE);
   layout_type (vtbl_type_node);
   vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
   record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
@@ -6279,7 +6409,8 @@ init_decl_processing ()
       (void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
     auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
     auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
-    auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
+    global_delete_fndecl
+      = auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
     auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
   }
 
@@ -6413,41 +6544,39 @@ fixup_anonymous_union (t)
     error ("an anonymous union cannot have function members");
 }
 
-/* Called when a declaration is seen that contains no names to declare.
-   If its type is a reference to a structure, union or enum inherited
-   from a containing scope, shadow that tag name for the current scope
-   with a forward reference.
-   If its type defines a new named structure or union
-   or defines an enum, it is valid but we need not do anything here.
-   Otherwise, it is an error.
+/* Make sure that a declaration with no declarator is well-formed, i.e.
+   just defines a tagged type or anonymous union.
 
-   C++: may have to grok the declspecs to learn about static,
-   complain for anonymous unions.  */
+   Returns the type defined, if any.  */
 
-void
-shadow_tag (declspecs)
+tree
+check_tag_decl (declspecs)
      tree declspecs;
 {
-  int found_tag = 0;
+  int found_type = 0;
   tree ob_modifier = NULL_TREE;
   register tree link;
-  register enum tree_code code, ok_code = ERROR_MARK;
   register tree t = NULL_TREE;
 
   for (link = declspecs; link; link = TREE_CHAIN (link))
     {
       register tree value = TREE_VALUE (link);
 
-      code = TREE_CODE (value);
-      if (IS_AGGR_TYPE_CODE (code) || code == ENUMERAL_TYPE)
+      if (TYPE_P (value))
        {
-         my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+         ++found_type;
 
-         maybe_process_partial_specialization (value);
-
-         t = value;
-         ok_code = code;
-         found_tag++;
+         if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
+           {
+             my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
+             t = value;
+           }
+       }
+      else if (value == ridpointers[(int) RID_FRIEND])
+       {
+         if (current_class_type == NULL_TREE
+             || current_scope () != current_class_type)
+           ob_modifier = value;
        }
       else if (value == ridpointers[(int) RID_STATIC]
               || value == ridpointers[(int) RID_EXTERN]
@@ -6455,21 +6584,65 @@ shadow_tag (declspecs)
               || value == ridpointers[(int) RID_REGISTER]
               || value == ridpointers[(int) RID_INLINE]
               || value == ridpointers[(int) RID_VIRTUAL]
+              || value == ridpointers[(int) RID_CONST]
+              || value == ridpointers[(int) RID_VOLATILE]
               || value == ridpointers[(int) RID_EXPLICIT])
        ob_modifier = value;
     }
 
+  if (found_type > 1)
+    error ("multiple types in one declaration");
+
+  /* Inside a class, we might be in a friend or access declaration.
+     Until we have a good way of detecting the latter, don't warn.  */
+  if (t == NULL_TREE && ! current_class_type)
+    pedwarn ("declaration does not declare anything");
+  else if (t && ANON_UNION_TYPE_P (t))
+    /* Anonymous unions are objects, so they can have specifiers.  */;
+  else if (ob_modifier)
+    {
+      if (ob_modifier == ridpointers[(int) RID_INLINE]
+         || ob_modifier == ridpointers[(int) RID_VIRTUAL])
+       cp_error ("`%D' can only be specified for functions", ob_modifier);
+      else if (ob_modifier == ridpointers[(int) RID_FRIEND])
+       cp_error ("`%D' can only be specified inside a class", ob_modifier);
+      else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
+       cp_error ("`%D' can only be specified for constructors",
+                 ob_modifier);
+      else
+       cp_error ("`%D' can only be specified for objects and functions",
+                 ob_modifier);
+    }
+
+  return t;
+}
+
+/* Called when a declaration is seen that contains no names to declare.
+   If its type is a reference to a structure, union or enum inherited
+   from a containing scope, shadow that tag name for the current scope
+   with a forward reference.
+   If its type defines a new named structure or union
+   or defines an enum, it is valid but we need not do anything here.
+   Otherwise, it is an error.
+
+   C++: may have to grok the declspecs to learn about static,
+   complain for anonymous unions.  */
+
+void
+shadow_tag (declspecs)
+     tree declspecs;
+{
+  tree t = check_tag_decl (declspecs);
+
+  if (t)
+    maybe_process_partial_specialization (t);
+
   /* This is where the variables in an anonymous union are
      declared.  An anonymous union declaration looks like:
      union { ... } ;
      because there is no declarator after the union, the parser
      sends that declaration here.  */
-  if (ok_code == UNION_TYPE
-      && t != NULL_TREE
-      && ((TREE_CODE (TYPE_NAME (t)) == IDENTIFIER_NODE
-          && ANON_AGGRNAME_P (TYPE_NAME (t)))
-         || (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL
-             && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))))
+  if (t && ANON_UNION_TYPE_P (t))
     {
       fixup_anonymous_union (t);
 
@@ -6480,29 +6653,6 @@ shadow_tag (declspecs)
          finish_anon_union (decl);
        }
     }
-  else
-    {
-      /* Anonymous unions are objects, that's why we only check for
-        inappropriate specifiers in this branch.  */
-
-      if (ob_modifier)
-       {
-         if (ob_modifier == ridpointers[(int) RID_INLINE]
-             || ob_modifier == ridpointers[(int) RID_VIRTUAL])
-           cp_error ("`%D' can only be specified for functions", ob_modifier);
-         else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
-           cp_error ("`%D' can only be specified for constructors",
-                     ob_modifier);
-         else
-           cp_error ("`%D' can only be specified for objects and functions",
-                     ob_modifier);
-       }
-
-      if (found_tag == 0)
-       cp_error ("abstract declarator used as declaration");
-      else if (found_tag > 1)
-       pedwarn ("multiple types in one declaration");
-    }
 }
 \f
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
@@ -6671,6 +6821,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
 
   if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
     {
+      pushclass (context, 2);
+
       if (TREE_CODE (decl) == VAR_DECL)
        {
          tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
@@ -6707,13 +6859,21 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
       DECL_IN_AGGR_P (decl) = 0;
       if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl)) 
          || CLASSTYPE_USE_TEMPLATE (context))
-       SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+       {
+         SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+         /* [temp.expl.spec] An explicit specialization of a static data
+            member of a template is a definition if the declaration
+            includes an initializer; otherwise, it is a declaration.
+
+            We check for processing_specialization so this only applies
+            to the new specialization syntax.  */
+         if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
+           DECL_EXTERNAL (decl) = 1;
+       }
 
       if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
        cp_pedwarn ("declaration of `%#D' outside of class is not definition",
                    decl);
-
-      pushclass (context, 2);
     }
 
 #ifdef SET_DEFAULT_DECL_ATTRIBUTES
@@ -6921,10 +7081,6 @@ grok_reference_init (decl, type, init)
       return;
     }
 
-  if (TREE_TYPE (init) && TREE_CODE (TREE_TYPE (init)) == UNKNOWN_TYPE)
-    /* decay_conversion is probably wrong for references to functions.  */
-    init = decay_conversion (instantiate_type (TREE_TYPE (type), init, 1));
-
   if (TREE_CODE (init) == TREE_LIST)
     init = build_compound_expr (init);
 
@@ -7080,6 +7236,12 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
       init = NULL_TREE;
     }
 
+  if (current_class_type
+      && DECL_REAL_CONTEXT (decl) == current_class_type
+      && TYPE_BEING_DEFINED (current_class_type)
+      && (DECL_INITIAL (decl) || init))
+    DECL_DEFINED_IN_CLASS_P (decl) = 1;
+
   if (TREE_CODE (decl) == VAR_DECL 
       && DECL_CONTEXT (decl)
       && TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
@@ -7224,7 +7386,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
        {
          if (TREE_CODE (type) == ARRAY_TYPE)
            init = digest_init (type, init, (tree *) 0);
-         else if (TREE_CODE (init) == CONSTRUCTOR)
+         else if (TREE_CODE (init) == CONSTRUCTOR
+                  && TREE_HAS_CONSTRUCTOR (init))
            {
              if (TYPE_NON_AGGREGATE_CLASS (type))
                {
@@ -7622,7 +7785,8 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
 
          if (current_binding_level->is_for_scope)
            {
-             struct binding_level *outer = current_binding_level->level_chain;
+             struct 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,
@@ -7634,36 +7798,20 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
                 Otherwise, we need to preserve the temp slot for decl
                 to last into the outer binding level.  */
 
-             int handling_dead_for_vars = 0;
-             tree link = outer->names;
-             for (; ; link = TREE_CHAIN (link))
+             tree outer_binding 
+               = TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
+             
+             if (outer_binding && BINDING_LEVEL (outer_binding) == outer
+                 && (TREE_CODE (BINDING_VALUE (outer_binding)) 
+                     == VAR_DECL)
+                 && DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
                {
-                 if (link == NULL && handling_dead_for_vars == 0)
-                   {
-                     link = outer->dead_vars_from_for;
-                     handling_dead_for_vars = 1;
-                   }
-                 if (link == NULL)
-                   {
-                     if (DECL_IN_MEMORY_P (decl))
-                       preserve_temp_slots (DECL_RTL (decl));
-                     break;
-                   }
-                 if (DECL_NAME (link) == DECL_NAME (decl))
-                   {
-                     if (handling_dead_for_vars)
-                       {
-                         tree shadowing
-                           = purpose_member (DECL_NAME (decl),
-                                             current_binding_level->shadowed);
-                         if (shadowing && TREE_VALUE (shadowing) == link)
-                           TREE_VALUE (shadowing)
-                             = DECL_SHADOWED_FOR_VAR (link);
-                       }
-                     current_binding_level->is_for_scope = 0;
-                     break;
-                   }
+                 BINDING_VALUE (outer_binding)
+                   = DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
+                 current_binding_level->is_for_scope = 0;
                }
+             else if (DECL_IN_MEMORY_P (decl))
+               preserve_temp_slots (DECL_RTL (decl));
            }
 
          expand_start_target_temps ();
@@ -7798,14 +7946,39 @@ expand_static_init (decl, init)
       /* Remember this information until end of file.  */
       push_obstacks (&permanent_obstack, &permanent_obstack);
 
-      /* Emit code to perform this initialization but once.  */
+      /* Emit code to perform this initialization but once.  This code
+        looks like:
+
+           static int temp = 0;
+           if (!temp) {
+             // Do initialization.
+            temp = 1;
+            // Register variable for destruction at end of program.
+          }
+
+        Note that the `temp' variable is only set to 1 *after* the
+        initialization is complete.  This ensures that an exception,
+        thrown during the construction, will cause the variable to
+        reinitialized when we pass through this code again, as per:
+        
+          [stmt.dcl]
+
+          If the initialization exits by throwing an exception, the
+          initialization is not complete, so it will be tried again
+          the next time control enters the declaration.
+
+         In theory, this process should be thread-safe, too; multiple
+        threads should not be able to initialize the variable more
+        than once.  We don't yet attempt to ensure thread-safety.  */
       temp = get_temp_name (integer_type_node, 1);
       rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
+
+      /* Begin the conditional initialization.  */
       expand_start_cond (build_binary_op (EQ_EXPR, temp,
                                          integer_zero_node, 1), 0);
       expand_start_target_temps ();
 
-      expand_assignment (temp, integer_one_node, 0, 0);
+      /* Do the initialization itself.  */
       if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
          || (init && TREE_CODE (init) == TREE_LIST))
        {
@@ -7815,9 +7988,17 @@ expand_static_init (decl, init)
       else if (init)
        expand_assignment (decl, init, 0, 0);
 
-      /* Cleanup any temporaries needed for the initial value.  */
+      /* Set TEMP to 1.  */
+      expand_assignment (temp, integer_one_node, 0, 0);
+
+      /* Cleanup any temporaries needed for the initial value.  If
+        destroying one of the temporaries causes an exception to be
+        thrown, then the object itself has still been fully
+        constructed.  */
       expand_end_target_temps ();
 
+      /* Use atexit to register a function for destroying this static
+        variable.  */
       if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
        {
          tree cleanup, fcall;
@@ -8080,6 +8261,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
   if (ctype == NULL_TREE && DECL_MAIN_P (decl))
     {
+      if (processing_template_decl)
+       error ("cannot declare `main' to be a template");
       if (inlinep)
        error ("cannot declare `main' to be inline");
       else if (! publicp)
@@ -8088,8 +8271,10 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
       publicp = 1;
     }
 
-  /* Members of anonymous types have no linkage; make them internal.  */
-  if (ctype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype)))
+  /* Members of anonymous types and local classes have no linkage; make
+     them internal.  */
+  if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
+               || hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
     publicp = 0;
 
   if (publicp)
@@ -8181,6 +8366,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
       && (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
     set_mangled_name_for_decl (decl);
 
+  if (funcdef_flag)
+    /* Make the init_value nonzero so pushdecl knows this is not
+       tentative.  error_mark_node is replaced later with the BLOCK.  */
+    DECL_INITIAL (decl) = error_mark_node;
+
   /* Caller will do the rest of this.  */
   if (check < 0)
     return decl;
@@ -8405,7 +8595,7 @@ build_ptrmemfunc_type (type)
   push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
 
   u = make_lang_type (UNION_TYPE);
-  IS_AGGR_TYPE (u) = 0;
+  SET_IS_AGGR_TYPE (u, 0);
   fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
   fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
                                     delta_type_node);
@@ -8417,7 +8607,7 @@ build_ptrmemfunc_type (type)
   /* Let the front-end know this is a pointer to member function...  */
   TYPE_PTRMEMFUNC_FLAG (t) = 1;
   /* ... and not really an aggregate.  */
-  IS_AGGR_TYPE (t) = 0;
+  SET_IS_AGGR_TYPE (t, 0);
 
   fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
                                     delta_type_node);
@@ -8497,6 +8687,41 @@ build_ptrmemfunc_type (type)
 
 enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
 
+/* DECL is a VAR_DECL defined in-class, whose TYPE is also given.
+   Check to see that the definition is valid.  Issue appropriate error
+   messages.  Return 1 if the definition is particularly bad, or 0
+   otherwise.  */
+
+int
+check_static_variable_definition (decl, type)
+     tree decl;
+     tree type;
+{
+  /* Motion 10 at San Diego: If a static const integral data member is
+     initialized with an integral constant expression, the initializer
+     may appear either in the declaration (within the class), or in
+     the definition, but not both.  If it appears in the class, the
+     member is a member constant.  The file-scope definition is always
+     required.  */
+  if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
+    {
+      cp_error ("in-class initialization of static data member of non-integral type `%T'", 
+               type);
+      /* If we just return the declaration, crashes will sometimes
+        occur.  We therefore return void_type_node, as if this was a
+        friend declaration, to cause callers to completely ignore
+        this declaration.  */
+      return 1;
+    }
+  else if (!CP_TYPE_CONST_P (type))
+    cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
+             decl);
+  else if (pedantic && !INTEGRAL_TYPE_P (type))
+    cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
+
+  return 0;
+}
+
 tree
 grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
      tree declspecs;
@@ -8641,10 +8866,15 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                init = TREE_OPERAND (decl, 1);
 
                decl = start_decl (declarator, declspecs, 1, NULL_TREE, NULL_TREE);
-               /* Look for __unused__ attribute */
-               if (TREE_USED (TREE_TYPE (decl)))
-                 TREE_USED (decl) = 1;
-               finish_decl (decl, init, NULL_TREE);
+               if (decl)
+                 {
+                   /* Look for __unused__ attribute */
+                   if (TREE_USED (TREE_TYPE (decl)))
+                     TREE_USED (decl) = 1;
+                   finish_decl (decl, init, NULL_TREE);
+                 }
+               else
+                 cp_error ("invalid declarator");
                return 0;
              }
            innermost_code = TREE_CODE (decl);
@@ -9021,24 +9251,16 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        }
       else
        {
-         if (funcdef_flag)
-           {
-             if (warn_return_type
-                 && return_type == return_normal)
-               /* Save warning until we know what is really going on.  */
-               warn_about_return_type = 1;
-           }
-         else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
-           pedwarn ("ANSI C++ forbids typedef which does not specify a type");
-         else if (innermost_code != CALL_EXPR || pedantic
-                  || (warn_return_type && return_type == return_normal))
-           {
-             if (innermost_code == CALL_EXPR)
-               cp_pedwarn ("return-type of `%D' defaults to `int'", dname);
-             else
-               cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
-                           dname);
-           }
+         if (! pedantic && ! warn_return_type
+             && funcdef_flag
+             && MAIN_NAME_P (dname)
+             && ctype == NULL_TREE
+             && in_namespace == NULL_TREE
+             && current_namespace == global_namespace)
+           /* Let `main () { }' slide, since it's so common.  */;
+         else
+           cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
+                       dname);
          type = integer_type_node;
        }
     }
@@ -9054,7 +9276,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
     }
   else if (return_type == return_conversion)
     {
-      if (comptypes (type, ctor_return_type, 1) == 0)
+      if (!same_type_p (type, ctor_return_type))
        cp_error ("operator `%T' declared to return `%T'",
                  ctor_return_type, type);
       else
@@ -9386,7 +9608,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
        {
          /* It's common practice (and completely valid) to have a const
             be initialized and declared extern.  */
-         if (! constp)
+         if (!(type_quals & TYPE_QUAL_CONST))
            warning ("`%s' initialized and declared `extern'", name);
        }
       else
@@ -9536,6 +9758,18 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
            if (size == error_mark_node)
              type = error_mark_node;
+           else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
+             {
+               /* [dcl.array]
+
+                  the constant expressions that specify the bounds of
+                  the arrays can be omitted only for the first member
+                  of the sequence.  */
+               cp_error ("declaration of `%D' as multidimensional array",
+                         dname);
+               cp_error ("must have bounds for all dimensions except the first");
+               type = error_mark_node;
+             }
 
            if (type == error_mark_node)
              continue;
@@ -9558,6 +9792,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                   constant, but we don't know what the value is yet.  */
                if (processing_template_decl)
                  {
+                   /* 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, 0);
+                       if (t)
+                         size = t;
+                     }
+
                    itype = make_node (INTEGER_TYPE);
                    TYPE_MIN_VALUE (itype) = size_zero_node;
                    TYPE_MAX_VALUE (itype) = build_min
@@ -9566,7 +9811,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                  }
 
                if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
-                   && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+                   && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
+                   && TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
                  {
                    cp_error ("size of array `%D' has non-integer type",
                              dname);
@@ -10017,7 +10263,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
            ctype = TREE_OPERAND (declarator, 0);
 
            t = ctype;
-           while (t != NULL_TREE) 
+           while (t != NULL_TREE && CLASS_TYPE_P (t)
              {
                if (CLASSTYPE_TEMPLATE_INFO (t) &&
                    !CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
@@ -10179,7 +10425,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
       if (decl_context == FIELD)
        {
-         if (declarator == current_class_name)
+         if (declarator == constructor_name (current_class_type))
            cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
                        declarator);
          decl = build_lang_decl (TYPE_DECL, declarator, type);
@@ -10222,6 +10468,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
          if (TYPE_LANG_SPECIFIC (type))
            TYPE_WAS_ANONYMOUS (type) = 1;
 
+         /* If this is a typedef within a template class, the nested
+            type is a (non-primary) template.  The name for the
+            template needs updating as well.  */
+         if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
+           DECL_NAME (CLASSTYPE_TI_TEMPLATE (type)) 
+             = TYPE_IDENTIFIER (type);
+
          /* XXX Temporarily set the scope. 
             When returning, start_decl expects it as NULL_TREE,
             and will then then set it using pushdecl. */
@@ -10404,7 +10657,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
     if (decl_context == PARM)
       {
-       decl = build_decl (PARM_DECL, declarator, complete_type (type));
+       decl = build_decl (PARM_DECL, declarator, type);
 
        bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
                        inlinep, friendp, raises != NULL_TREE);
@@ -10434,7 +10687,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
               are error_mark_node, for example.  */
            decl = NULL_TREE;
          }
-       else if (in_namespace)
+       else if (in_namespace && !friendp)
          {
            /* Something like struct S { int N::j; };  */
            cp_error ("invalid use of `::'");
@@ -10641,47 +10894,36 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
                       the rest of the compiler does not correctly
                       handle the initialization unless the member is
                       static so we make it static below.  */
-                   cp_pedwarn ("ANSI C++ forbids initialization of %s `%D'",
-                               constp ? "const member" : "member", 
+                   cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
                                declarator);
                    cp_pedwarn ("making `%D' static", declarator);
                    staticp = 1;
                  }
 
-               /* Motion 10 at San Diego: If a static const integral data
-                  member is initialized with an integral constant
-                  expression, the initializer may appear either in the
-                  declaration (within the class), or in the definition,
-                  but not both.  If it appears in the class, the member is
-                  a member constant.  The file-scope definition is always
-                  required.  */
-               if (CLASS_TYPE_P (type)
-                   || TREE_CODE (type) == REFERENCE_TYPE)
-                 {
-                   cp_error ("in-class initialization of static data member of non-integral type `%T'", 
-                             type);
-                   /* If we just return the declaration, crashes will
-                      sometimes occur.  We therefore return
-                      void_type_node, as if this was a friend
-                      declaration, to cause callers to completely
-                      ignore this declaration.  */
-                   return void_type_node;
-                 }
-               else if (!constp)
-                 cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
-                           declarator);
-               else if (pedantic && ! INTEGRAL_TYPE_P (type) 
-                        && !uses_template_parms (type))
-                 cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", declarator, type);
+               if (uses_template_parms (type))
+                 /* We'll check at instantiation time.  */
+                 ;
+               else if (check_static_variable_definition (declarator,
+                                                          type))
+                 /* If we just return the declaration, crashes
+                    will sometimes occur.  We therefore return
+                    void_type_node, as if this was a friend
+                    declaration, to cause callers to completely
+                    ignore this declaration.  */
+                 return void_type_node;
              }
 
+           /* 9.2p13 [class.mem] */
+           if (declarator == constructor_name (current_class_type)
+               /* Divergence from the standard:  In extern "C", we
+                  allow non-static data members here, because C does
+                  and /usr/include/netinet/in.h uses that.  */
+               && (staticp || current_lang_name != lang_c))
+             cp_pedwarn ("ANSI C++ forbids data member `%D' with same name as enclosing class",
+                         declarator);
+
            if (staticp)
              {
-               /* ANSI C++ Apr '95 wp 9.2 */
-               if (declarator == current_class_name)
-                 cp_pedwarn ("ANSI C++ forbids static member `%D' with same name as enclosing class",
-                             declarator);
-
                /* C++ allows static class members.
                   All other work for this is done by grokfield.
                   This VAR_DCL is built by build_lang_field_decl.
@@ -10798,7 +11040,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
        /* An uninitialized decl with `extern' is a reference.  */
        decl = grokvardecl (type, declarator, &specbits, 
-                           initialized, constp, in_namespace);
+                           initialized, 
+                           (type_quals & TYPE_QUAL_CONST) != 0, 
+                           in_namespace);
        bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
                        inlinep, friendp, raises != NULL_TREE);
 
@@ -10877,18 +11121,14 @@ parmlist_is_exprlist (exprs)
   return 1;
 }
 
-/* Subroutine of `grokparms'.  In a fcn definition, arg types must
-   be complete.
-
-   C++: also subroutine of `start_function'.  */
+/* Subroutine of start_function.  Ensure that each of the parameter
+   types (as listed in PARMS) is complete, as is required for a
+   function definition.  */
 
 static void
 require_complete_types_for_parms (parms)
      tree parms;
 {
-  if (processing_template_decl)
-    return;
-
   while (parms)
     {
       tree type = TREE_TYPE (parms);
@@ -10901,31 +11141,9 @@ require_complete_types_for_parms (parms)
            error ("parameter has incomplete type");
          TREE_TYPE (parms) = error_mark_node;
        }
-#if 0
-      /* If the arg types are incomplete in a declaration,
-        they must include undefined tags.
-        These tags can never be defined in the scope of the declaration,
-        so the types can never be completed,
-        and no call can be compiled successfully.  */
-      /* This is not the right behavior for C++, but not having
-        it is also probably wrong.  */
       else
-       {
-         /* Now warn if is a pointer to an incomplete type.  */
-         while (TREE_CODE (type) == POINTER_TYPE
-                || TREE_CODE (type) == REFERENCE_TYPE)
-           type = TREE_TYPE (type);
-         type = TYPE_MAIN_VARIANT (type);
-         if (TYPE_SIZE (type) == NULL_TREE)
-           {
-             if (DECL_NAME (parm) != NULL_TREE)
-               warning ("parameter `%s' points to incomplete type",
-                        IDENTIFIER_POINTER (DECL_NAME (parm)));
-             else
-               warning ("parameter points to incomplete type");
-           }
-       }
-#endif
+       layout_decl (parms, 0);
+
       parms = TREE_CHAIN (parms);
     }
 }
@@ -11022,7 +11240,7 @@ grokparms (first_parm, funcdef_flag)
                                         TREE_PURPOSE (decl),
                                         PARM, init != NULL_TREE,
                                         NULL_TREE);
-                 if (! decl)
+                 if (! decl || TREE_TYPE (decl) == error_mark_node)
                    continue;
 
                  /* Top-level qualifiers on the parameters are
@@ -11119,24 +11337,32 @@ grokparms (first_parm, funcdef_flag)
                      /* Unparsed default arg from in-class decl.  */
                      else if (TREE_CODE (init) == DEFAULT_ARG)
                        ;
-                     else if (TREE_CODE (init) == VAR_DECL
-                              || TREE_CODE (init) == PARM_DECL)
+                     else if (TREE_CODE (init) == PARM_DECL
+                              || TREE_CODE (init) == VAR_DECL)
                        {
-                         if (IDENTIFIER_LOCAL_VALUE (DECL_NAME (init)))
+                         if (TREE_CODE (init) == VAR_DECL
+                             && (IDENTIFIER_VALUE (DECL_NAME (init))
+                                 == init)
+                             && LOCAL_BINDING_P
+                             (IDENTIFIER_BINDING (DECL_NAME
+                                                  (init))))
                            {
-                             /* ``Local variables may not be used in default
-                                argument expressions.'' dpANSI C++ 8.2.6 */
-                             /* If extern int i; within a function is not
-                                considered a local variable, then this code is
-                                wrong.  */
+                             /* ``Local variables may not be used in
+                                default argument expressions.''
+                                dpANSI C++ 8.2.6 */
+
                              cp_error ("local variable `%D' may not be used as a default argument", init);
                              any_error = 1;
                            }
                          else if (TREE_READONLY_DECL_P (init))
                            init = decl_constant_value (init);
                        }
-                     else
-                       init = require_instantiated_type (type, init, integer_zero_node);
+                     else if (TREE_TYPE (init) == NULL_TREE)
+                       {
+                         error ("argument list may not have an initializer list");
+                         init = error_mark_node;
+                       }
+
                      if (! processing_template_decl
                          && init != error_mark_node
                          && TREE_CODE (init) != DEFAULT_ARG
@@ -11188,10 +11414,6 @@ grokparms (first_parm, funcdef_flag)
 
   last_function_parms = decls;
 
-  /* In a fcn definition, arg types must be complete.  */
-  if (funcdef_flag > 0)
-    require_complete_types_for_parms (last_function_parms);
-
   return result;
 }
 
@@ -11256,19 +11478,45 @@ grok_ctor_properties (ctype, decl)
       parmtype = TREE_VALUE (parmtypes);
     }
 
+  /* [class.copy]
+
+     A non-template constructor for class X is a copy constructor if
+     its first parameter is of type X&, const X&, volatile X& or const
+     volatile X&, and either there are no other parameters or else all
+     other parameters have default arguments.  */
   if (TREE_CODE (parmtype) == REFERENCE_TYPE
       && TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
       && (TREE_CHAIN (parmtypes) == NULL_TREE
          || TREE_CHAIN (parmtypes) == void_list_node
-         || TREE_PURPOSE (TREE_CHAIN (parmtypes))))
+         || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+      && !(DECL_TEMPLATE_INSTANTIATION (decl)
+          && is_member_template (DECL_TI_TEMPLATE (decl))))
     {
       TYPE_HAS_INIT_REF (ctype) = 1;
       if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
        TYPE_HAS_CONST_INIT_REF (ctype) = 1;
     }
+  /* [class.copy]
+
+     A declaration of a constructor for a class X is ill-formed if its
+     first parameter is of type (optionally cv-qualified) X and either
+     there are no other parameters or else all other parameters have
+     default arguments.  
+
+     We *don't* complain about member template instantiations that
+     have this form, though; they can occur as we try to decide what
+     constructor to use during overload resolution.  Since overload
+     resolution will never prefer such a constructor to the
+     non-template copy constructor (which is either explicitly or
+     implicitly defined), there's no need to worry about their
+     existence.  Theoretically, they should never even be
+     instantiated, but that's hard to forestall.  */
   else if (TYPE_MAIN_VARIANT (parmtype) == ctype
-          && TREE_CHAIN (parmtypes) != NULL_TREE
-          && TREE_CHAIN (parmtypes) == void_list_node)
+          && (TREE_CHAIN (parmtypes) == NULL_TREE
+              || TREE_CHAIN (parmtypes) == void_list_node
+              || TREE_PURPOSE (TREE_CHAIN (parmtypes)))
+          && !(DECL_TEMPLATE_INSTANTIATION (decl)
+               && is_member_template (DECL_TI_TEMPLATE (decl))))
     {
       cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
                ctype, ctype);
@@ -11324,7 +11572,15 @@ grok_op_properties (decl, virtualp, friendp)
 
   if (! friendp)
     {
-      if (name == ansi_opname[(int) MODIFY_EXPR])
+      /* [class.copy]
+
+        A user-declared copy assignment operator X::operator= is a
+        non-static non-template member function of class X with
+        exactly one parameter of type X, X&, const X&, volatile X& or
+        const volatile X&.  */
+      if (name == ansi_opname[(int) MODIFY_EXPR]
+         && !(DECL_TEMPLATE_INSTANTIATION (decl)
+              && is_member_template (DECL_TI_TEMPLATE (decl))))
        TYPE_HAS_ASSIGNMENT (current_class_type) = 1;
       else if (name == ansi_opname[(int) CALL_EXPR])
        TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
@@ -11520,14 +11776,14 @@ grok_op_properties (decl, virtualp, friendp)
              if (list_length (argtypes) == 2)
                {
                  if (TREE_CODE (ret) != REFERENCE_TYPE
-                     || !comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
-                                    arg, 1))
+                     || !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
+                                      arg))
                    cp_warning ("prefix `%D' should return `%T'", decl,
                                build_reference_type (arg));
                }
              else
                {
-                 if (!comptypes (TYPE_MAIN_VARIANT (ret), arg, 1))
+                 if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
                    cp_warning ("postfix `%D' should return `%T'", decl, arg);
                }
            }
@@ -11589,6 +11845,27 @@ grok_op_properties (decl, virtualp, friendp)
     }
 }
 \f
+static char *
+tag_name (code)
+     enum tag_types code;
+{
+  switch (code)
+    {
+    case record_type:
+      return "struct";
+    case class_type:
+      return "class";
+    case union_type:
+      return "union ";
+    case enum_type:
+      return "enum";
+    case signature_type:
+      return "signature";
+    default:
+      my_friendly_abort (981122);
+    }
+}
+
 /* Get the struct, enum or union (CODE says which) with tag NAME.
    Define the tag as a forward-reference if it is not defined.
 
@@ -11658,19 +11935,9 @@ xref_tag (code_type_node, name, globalize)
 
   if (! globalize)
     {
-      if (t && (TREE_CODE (t) == TEMPLATE_TYPE_PARM 
-                           || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM))
-       {
-         cp_error ("redeclaration of template type-parameter `%T'", name);
-         cp_error_at ("  previously declared here `%#D'", 
-                      TEMPLATE_TYPE_DECL (t));
-       }
-      if (t && TYPE_CONTEXT (t) && got_type)
-       ref = t;
-      else
-       /* If we know we are defining this tag, only look it up in
-          this scope and don't try to find it as a type.  */
-       ref = lookup_tag (code, name, b, 1);
+      /* If we know we are defining this tag, only look it up in
+        this scope and don't try to find it as a type.  */
+      ref = lookup_tag (code, name, b, 1);
     }
   else
     {
@@ -11703,7 +11970,12 @@ xref_tag (code_type_node, name, globalize)
       else 
        {
          if (t)
-           ref = t;
+           {
+             if (t != TYPE_MAIN_VARIANT (t))
+               cp_pedwarn ("using typedef-name `%D' after `%s'",
+                           TYPE_NAME (t), tag_name (tag_code));
+             ref = t;
+           }
          else
            ref = lookup_tag (code, name, b, 0);
          
@@ -11953,9 +12225,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
             individual inheritance contains flags which say what
             the `accessibility' of that particular inheritance is.)  */
   
-         base_binfo = make_binfo (integer_zero_node, basetype,
-                                  TYPE_BINFO_VTABLE (basetype),
-                                  TYPE_BINFO_VIRTUALS (basetype));
+         base_binfo 
+           = make_binfo (integer_zero_node, basetype,
+                         CLASS_TYPE_P (basetype)
+                         ? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
+                         CLASS_TYPE_P (basetype)
+                         ? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
  
          TREE_VEC_ELT (binfos, i) = base_binfo;
          TREE_VIA_PUBLIC (base_binfo) = via_public;
@@ -11977,8 +12252,12 @@ xref_basetypes (code_type_node, name, ref, binfo)
              TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
            }
 
-         TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
-         TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+         if (CLASS_TYPE_P (basetype))
+           {
+             TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
+             TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
+           }
+
          i += 1;
        }
     }
@@ -11990,8 +12269,14 @@ xref_basetypes (code_type_node, name, ref, binfo)
   if (i > 1)
     TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
   else if (i == 1)
-    TYPE_USES_MULTIPLE_INHERITANCE (ref)
-      = TYPE_USES_MULTIPLE_INHERITANCE (BINFO_TYPE (TREE_VEC_ELT (binfos, 0)));
+    {
+      tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
+      
+      if (CLASS_TYPE_P (basetype))
+       TYPE_USES_MULTIPLE_INHERITANCE (ref)
+         = TYPE_USES_MULTIPLE_INHERITANCE (basetype);
+    }
+
   if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
     TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
 
@@ -12019,11 +12304,7 @@ start_enum (name)
 
   /* We are wasting space here and putting these on the permanent_obstack so
      that typeid(local enum) will work correctly. */
-#if 0
-  if (processing_template_decl && current_function_decl)
-#endif
-   
-  end_temporary_allocation ();
+  push_obstacks (&permanent_obstack, &permanent_obstack);
 
   /* If this is the real definition for a previous forward reference,
      fill in the contents in the same object that used to be the
@@ -12125,61 +12406,58 @@ finish_enum (enumtype)
     {
       tree scope = current_scope ();
       if (scope && TREE_CODE (scope) == FUNCTION_DECL)
-       {
-         add_tree (build_min (TAG_DEFN, enumtype));
-         resume_temporary_allocation ();
-       }
-      return enumtype;
+       add_tree (build_min (TAG_DEFN, enumtype));
     }
+  else
+    {
+      int unsignedp = tree_int_cst_sgn (minnode) >= 0;
+      int lowprec = min_precision (minnode, unsignedp);
+      int highprec = min_precision (maxnode, unsignedp);
+      int precision = MAX (lowprec, highprec);
+      tree tem;
 
-  {
-    int unsignedp = tree_int_cst_sgn (minnode) >= 0;
-    int lowprec = min_precision (minnode, unsignedp);
-    int highprec = min_precision (maxnode, unsignedp);
-    int precision = MAX (lowprec, highprec);
-
-    TYPE_SIZE (enumtype) = NULL_TREE;
-
-    /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
+      TYPE_SIZE (enumtype) = NULL_TREE;
 
-    TYPE_PRECISION (enumtype) = precision;
-    if (unsignedp)
-      fixup_unsigned_type (enumtype);
-    else
-      fixup_signed_type (enumtype);
+      /* Set TYPE_MIN_VALUE and TYPE_MAX_VALUE according to `precision'.  */
 
-    if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
-      /* Use the width of the narrowest normal C type which is wide enough.  */
-      TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
-                                                 (precision, 1));
-    else
-      TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
+      TYPE_PRECISION (enumtype) = precision;
+      if (unsignedp)
+       fixup_unsigned_type (enumtype);
+      else
+       fixup_signed_type (enumtype);
 
-    TYPE_SIZE (enumtype) = 0;
-    layout_type (enumtype);
-  }
+      if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
+       /* Use the width of the narrowest normal C type which is wide
+          enough.  */ 
+       TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
+                                                   (precision, 1));
+      else
+       TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
 
-  {
-    register tree tem;
+      TYPE_SIZE (enumtype) = 0;
+      layout_type (enumtype);
     
-    /* Fix up all variant types of this enum type.  */
-    for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
-        tem = TYPE_NEXT_VARIANT (tem))
-      {
-       TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
-       TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
-       TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
-       TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
-       TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
-       TYPE_MODE (tem) = TYPE_MODE (enumtype);
-       TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
-       TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
-       TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
-      }
-  }
+      /* Fix up all variant types of this enum type.  */
+      for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
+          tem = TYPE_NEXT_VARIANT (tem))
+       {
+         TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
+         TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
+         TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
+         TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
+         TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
+         TYPE_MODE (tem) = TYPE_MODE (enumtype);
+         TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
+         TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
+         TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
+       }
 
-  /* Finish debugging output for this type.  */
-  rest_of_type_compilation (enumtype, namespace_bindings_p ());
+      /* Finish debugging output for this type.  */
+      rest_of_type_compilation (enumtype, namespace_bindings_p ());
+    }
+
+  /* In start_enum we pushed obstacks.  Here, we must pop them.  */
+  pop_obstacks ();
 
   return enumtype;
 }
@@ -12293,6 +12571,15 @@ static int function_depth;
    they describe the function's name and the type it returns,
    but twisted together in a fashion that parallels the syntax of C.
 
+   If PRE_PARSED_P is non-zero then DECLARATOR is really the DECL for
+   the function we are about to process; DECLSPECS are ignored.  For
+   example, we set PRE_PARSED_P when processing the definition of
+   inline function that was defined in-class; the definition is
+   actually processed when the class is complete.  In this case,
+   PRE_PARSED_P is 2.  We also set PRE_PARSED_P when instanting the
+   body of a template function, and when constructing thunk functions
+   and such; in these cases PRE_PARSED_P is 1.
+   
    This function creates a binding context for the function body
    as well as setting up the FUNCTION_DECL in current_function_decl.
 
@@ -12329,7 +12616,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
   /* Assume, until we see it does.  */
   current_function_returns_value = 0;
   current_function_returns_null = 0;
-  warn_about_return_type = 0;
   named_labels = 0;
   shadowed_labels = 0;
   current_function_assigns_this = 0;
@@ -12394,17 +12680,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
            doing_friend = 1;
        }
 
-      /* In a fcn definition, arg types must be complete.  */
-      require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
-
-      /* In case some arg types were completed since the declaration was
-         parsed, fix up the decls.  */
-      {
-       tree t = DECL_ARGUMENTS (decl1);
-       for (; t; t = TREE_CHAIN (t))
-         layout_decl (t, 0);
-      }
-
       last_function_parms = DECL_ARGUMENTS (decl1);
       last_function_parm_tags = NULL_TREE;
     }
@@ -12418,8 +12693,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
       fntype = TREE_TYPE (decl1);
 
       restype = TREE_TYPE (fntype);
-      if (IS_AGGR_TYPE (restype) && ! TYPE_PTRMEMFUNC_P (restype)
-         && ! CLASSTYPE_GOT_SEMICOLON (restype))
+      if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
        {
          cp_error ("semicolon missing after declaration of `%#T'", restype);
          shadow_tag (build_expr_list (NULL_TREE, restype));
@@ -12445,7 +12719,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
                pedwarn ("return type for `main' changed to `int'");
              TREE_TYPE (decl1) = fntype = default_function_type;
            }
-         warn_about_return_type = 0;
        }
     }
 
@@ -12455,16 +12728,37 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
       && IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
     cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
 
+  announce_function (decl1);
+
+  /* Set up current_class_type, and enter the scope of the class, if
+     appropriate.  */
+  if (ctype)
+    push_nested_class (ctype, 1);
+  else if (DECL_STATIC_FUNCTION_P (decl1))
+    push_nested_class (DECL_CONTEXT (decl1), 2);
+
+  /* Now that we have entered the scope of the class, we must restore
+     the bindings for any template parameters surrounding DECL1, if it
+     is an inline member template.  (Order is important; consider the
+     case where a template parameter has the same name as a field of
+     the class.)  It is not until after this point that
+     PROCESSING_TEMPLATE_DECL is guaranteed to be set up correctly.  */
+  if (pre_parsed_p == 2)
+    maybe_begin_member_template_processing (decl1);
+
+  /* We are now in the scope of the function being defined.  */
   current_function_decl = decl1;
+
   /* 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_parm_tags = last_function_parm_tags;
 
-  announce_function (decl1);
-
   if (! processing_template_decl)
     {
+      /* In a fcn definition, arg types must be complete.  */
+      require_complete_types_for_parms (DECL_ARGUMENTS (decl1));
+
       if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
        {
          cp_error ("return-type `%#T' is an incomplete type",
@@ -12496,9 +12790,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
        abstract_virtuals_error (decl1, TREE_TYPE (fntype));
     }
 
-  if (warn_about_return_type)
-    pedwarn ("return-type defaults to `int'");
-
   /* Effective C++ rule 15.  See also c_expand_return.  */
   if (warn_ecpp
       && DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
@@ -12517,13 +12808,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
 
-  /* Set up current_class_type, and enter the scope of the class, if
-     appropriate.  */
-  if (ctype)
-    push_nested_class (ctype, 1);
-  else if (DECL_STATIC_FUNCTION_P (decl1))
-    push_nested_class (DECL_CONTEXT (decl1), 2);
-
   /* We must call push_template_decl after current_class_type is set
      up.  (If we are processing inline definitions after exiting a
      class scope, current_class_type will be NULL_TREE until set above
@@ -12630,13 +12914,24 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
 
          if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
            {
-             int i = suspend_momentary ();
+             int i;
+
+             if (! hack_decl_function_context (decl1))
+               temporary_allocation ();
+             i = suspend_momentary ();
 
-             /* Fool build_indirect_ref.  */
+             /* Normally, build_indirect_ref returns
+                current_class_ref whenever current_class_ptr is
+                dereferenced.  This time, however, we want it to
+                *create* current_class_ref, so we temporarily clear
+                current_class_ptr to fool it.  */
              current_class_ptr = NULL_TREE;
              current_class_ref = build_indirect_ref (t, NULL_PTR);
              current_class_ptr = t;
+
              resume_momentary (i);
+             if (! hack_decl_function_context (decl1))
+               end_temporary_allocation ();
            }
          else
            /* We're having a signature pointer here.  */
@@ -12645,9 +12940,7 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
        }
     }
   else
-    {
-      current_class_ptr = current_class_ref = NULL_TREE;
-    }
+    current_class_ptr = current_class_ref = NULL_TREE;
 
   pushlevel (0);
   current_binding_level->parm_flag = 1;
@@ -12750,9 +13043,6 @@ store_parm_decls ()
   /* Initialize RTL machinery.  */
   init_function_start (fndecl, input_filename, lineno);
 
-  /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function.  */
-  declare_function_name ();
-
   /* Create a binding level for the parms.  */
   expand_start_bindings (0);
 
@@ -12838,6 +13128,9 @@ store_parm_decls ()
 
   storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
 
+  /* Declare __FUNCTION__ and __PRETTY_FUNCTION__ for this function.  */
+  declare_function_name ();
+
   /* Initialize the RTL code for the function.  */
   DECL_SAVED_INSNS (fndecl) = NULL_RTX;
   if (! processing_template_decl)
@@ -12948,18 +13241,23 @@ store_return_init (return_id, init)
    This is called after parsing the body of the function definition.
    LINENO is the current line number.
 
-   C++: CALL_POPLEVEL is non-zero if an extra call to poplevel
-   (and expand_end_bindings) must be made to take care of the binding
-   contour for the base initializers.  This is only relevant for
-   constructors.
+   FLAGS is a bitwise or of the following values: 
+     1 - CALL_POPLEVEL 
+       An extra call to poplevel (and expand_end_bindings) must be
+       made to take care of the binding contour for the base
+       initializers.  This is only relevant for constructors.
+     2 - INCLASS_INLINE
+       We just finished processing the body of an in-class inline
+       function definition.  (This processing will have taken place
+       after the class definition is complete.)
 
    NESTED is nonzero if we were in the middle of compiling another function
    when we started on this one.  */
 
 void
-finish_function (lineno, call_poplevel, nested)
+finish_function (lineno, flags, nested)
      int lineno;
-     int call_poplevel;
+     int flags;
      int nested;
 {
   register tree fndecl = current_function_decl;
@@ -12968,6 +13266,9 @@ finish_function (lineno, call_poplevel, nested)
   /* Label to use if this function is supposed to return a value.  */
   tree no_return_label = NULL_TREE;
   tree decls = NULL_TREE;
+  int call_poplevel = (flags & 1) != 0;
+  int inclass_inline = (flags & 2) != 0;
+  int in_template;
 
   /* When we get some parse errors, we can end up without a
      current_function_decl, so cope.  */
@@ -13067,7 +13368,8 @@ finish_function (lineno, call_poplevel, nested)
             pointer to represent the type of our base class.  */
 
          /* This side-effect makes call to `build_delete' generate the
-            code we have to have at the end of this destructor.  */
+            code we have to have at the end of this destructor.
+            `build_delete' will set the flag again.  */
          TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
 
          /* These are two cases where we cannot delegate deletion.  */
@@ -13126,8 +13428,6 @@ finish_function (lineno, call_poplevel, nested)
                expand_end_cond ();
            }
 
-         TYPE_HAS_DESTRUCTOR (current_class_type) = 1;
-
          virtual_size = c_sizeof (current_class_type);
 
          /* At the end, call delete if that's what's requested.  */
@@ -13161,7 +13461,7 @@ finish_function (lineno, call_poplevel, nested)
 
          /* End of destructor.  */
          expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
-         poplevel (2, 0, 0);   /* XXX change to 1 */
+         poplevel (getdecls () != NULL_TREE, 0, 0);
 
          /* Back to the top of destructor.  */
          /* Don't execute destructor code if `this' is NULL.  */
@@ -13374,6 +13674,27 @@ finish_function (lineno, call_poplevel, nested)
       /* Generate rtl for function exit.  */
       expand_function_end (input_filename, lineno, 1);
     }
+  
+  /* Must mark the RESULT_DECL as being in this function.  */
+  DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
+
+  /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
+     to the FUNCTION_DECL node itself.  */
+  BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
+
+  /* If we're processing a template, squirrel away the definition
+     until we do an instantiation.  */
+  if (processing_template_decl)
+    {
+      --minimal_parse_mode;
+      DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
+      /* We have to save this value here in case
+        maybe_end_member_template_processing decides to pop all the
+        template parameters.  */
+      in_template = 1;
+    }
+  else
+    in_template = 0;
 
   /* This must come after expand_function_end because cleanups might
      have declarations (from inline functions) that need to go into
@@ -13382,6 +13703,13 @@ finish_function (lineno, call_poplevel, nested)
     my_friendly_abort (122);
   poplevel (1, 0, 1);
 
+  /* If this is a in-class inline definition, we may have to pop the
+     bindings for the template parameters that we added in
+     maybe_begin_member_template_processing when start_function was
+     called.  */
+  if (inclass_inline)
+    maybe_end_member_template_processing ();
+
   /* Reset scope for C++: if we were in the scope of a class,
      then when we finish this function, we are not longer so.
      This cannot be done until we know for sure that no more
@@ -13393,14 +13721,7 @@ finish_function (lineno, call_poplevel, nested)
       pop_nested_class (1);
     }
 
-  /* Must mark the RESULT_DECL as being in this function.  */
-  DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
-
-  /* Set the BLOCK_SUPERCONTEXT of the outermost function scope to point
-     to the FUNCTION_DECL node itself.  */
-  BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
-
-  if (! processing_template_decl)
+  if (!in_template)
     {
       int saved_flag_keep_inline_functions =
        flag_keep_inline_functions;
@@ -13484,12 +13805,6 @@ finish_function (lineno, call_poplevel, nested)
   /* Free all the tree nodes making up this function.  */
   /* Switch back to allocating nodes permanently
      until we start another function.  */
-  if (processing_template_decl)
-    {
-      --minimal_parse_mode;
-      DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
-    }
-
   if (! nested)
     permanent_allocation (1);
 
@@ -13524,8 +13839,6 @@ finish_function (lineno, call_poplevel, nested)
 }
 \f
 /* Create the FUNCTION_DECL for a function definition.
-   LINE1 is the line number that the definition absolutely begins on.
-   LINE2 is the line number that the name of the function appears on.
    DECLSPECS and DECLARATOR are the parts of the declaration;
    they describe the return type and the name of the function,
    but twisted together in a fashion that parallels the syntax of C.
@@ -13580,6 +13893,8 @@ start_method (declspecs, declarator, attrlist)
       return void_type_node;
     }
 
+  check_template_shadow (fndecl);
+
   DECL_THIS_INLINE (fndecl) = 1;
 
   if (flag_default_inline)
@@ -13661,23 +13976,11 @@ finish_method (decl)
   for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
     {
       if (DECL_NAME (link) != NULL_TREE)
-       IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
+       pop_binding (DECL_NAME (link));
       my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
       DECL_CONTEXT (link) = NULL_TREE;
     }
 
-  /* Restore all name-meanings of the outer levels
-     that were shadowed by this level.  */
-
-  for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
-      IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-  for (link = current_binding_level->class_shadowed;
-       link; link = TREE_CHAIN (link))
-    IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-  for (link = current_binding_level->type_shadowed;
-       link; link = TREE_CHAIN (link))
-    SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
-
   GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
                      (HOST_WIDE_INT) current_binding_level->level_chain,
                      current_binding_level->parm_flag,
@@ -13837,10 +14140,10 @@ cplus_expand_expr_stmt (exp)
 
   if (TREE_TYPE (exp) == unknown_type_node)
     {
-      if (TREE_CODE (exp) == ADDR_EXPR || TREE_CODE (exp) == TREE_LIST)
+      if (TREE_CODE (exp) == COMPONENT_REF)
+       error ("invalid reference to a member function name, did you forget the ()?");
+      else
        error ("address of overloaded function with no contextual type information");
-      else if (TREE_CODE (exp) == COMPONENT_REF)
-       warning ("useless reference to a member function name, did you forget the ()?");
     }
   else
     {
@@ -13946,12 +14249,12 @@ struct cp_function
 {
   int returns_value;
   int returns_null;
-  int warn_about_return_type;
   int assigns_this;
   int just_assigned_this;
   int parms_stored;
   int temp_name_counter;
   tree named_labels;
+  struct named_label_list *named_label_uses;
   tree shadowed_labels;
   tree ctor_label;
   tree dtor_label;
@@ -13988,10 +14291,10 @@ push_cp_function_context (context)
   cp_function_chain = p;
 
   p->named_labels = named_labels;
+  p->named_label_uses = named_label_uses;
   p->shadowed_labels = shadowed_labels;
   p->returns_value = current_function_returns_value;
   p->returns_null = current_function_returns_null;
-  p->warn_about_return_type = warn_about_return_type;
   p->binding_level = current_binding_level;
   p->ctor_label = ctor_label;
   p->dtor_label = dtor_label;
@@ -14030,10 +14333,10 @@ pop_cp_function_context (context)
   cp_function_chain = p->next;
 
   named_labels = p->named_labels;
+  named_label_uses = p->named_label_uses;
   shadowed_labels = p->shadowed_labels;
   current_function_returns_value = p->returns_value;
   current_function_returns_null = p->returns_null;
-  warn_about_return_type = p->warn_about_return_type;
   current_binding_level = p->binding_level;
   ctor_label = p->ctor_label;
   dtor_label = p->dtor_label;