cp-tree.def (CPLUS_BINDING): Update documentation.
authorMark Mitchell <mark@markmitchell.com>
Sun, 13 Dec 1998 14:46:07 +0000 (14:46 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sun, 13 Dec 1998 14:46:07 +0000 (14:46 +0000)
* cp-tree.def (CPLUS_BINDING): Update documentation.
* cp-tree.h (LOCAL_BINDING_P): New macro.
(lang_identifier): Rename local_value to bindings.
(tree_binding): Make `scope' of type `void*', not `tree'.
(BINDING_SCOPE): Update documentation.
(IDENTIFIER_LOCAL_VALUE): Remove.
(IDENTIFIER_CLASS_VALUE): Document.
(IDENTIFIER_BINDING): New macro.
(IDENTIFIER_VALUE): Likewise.
(TIME_IDENTIFIER_TIME): Likewise.
(TIME_IDENTIFIER_FILEINFO): Likewise.
(IMPLICIT_TYPENAME_P): Likewise.
(set_identifier_local_value): Remove.
(push_local_binding): New function.
(push_class_binding): Likewise.
* class.c (pushclass): Update comments; use push_class_binding.
* decl.c (set_identifier_local_value_with_scope): Remove.
(set_identifier_local_value): Likewise.
(push_binding): New function.
(pop_binding): Likewise.
(binding_level): Update documentation.  Remove shadowed.
(BINDING_LEVEL): New macro.
(free_binding_nodes): New variable.
(poplevel): Adjust for new name-lookup scheme.  Don't mess up
BLOCK_VARs when doing for-scope extension.  Remove effectively
dead code.
(pushlevel_class): Tweak formatting.
(poplevel_class): Adjust for new name-lookup scheme.
(print_binding_level): Likewise.
(store_bindings): Likewise.
(pushdecl): Likewise.
(pushdecl_class_level): Likewise.
(push_class_level_binding): Likewise.
(push_overloaded_decl): Update comments.  Adjust for new
name-lookup scheme.
(lookup_name_real): Likewise.
(lookup_name_current_level): Likewise.
(cp_finish_decl): Likewise.
(require_complete_types_for_parms): Likewise.  Remove misleading
#if 0'd code.
(grok_parms): Likewise.  Don't call
require_complete_types_for_parms here.
(grok_ctor_properties): Don't treat templates as copy
constructors.
(grop_op_properties): Or as assignment operators.
(start_function): Document.  Adjust for new name-lookup scheme.
(finish_function): Likewise.
* decl2.c (do_local_using_decl): Use push_local_binding.
* lex.c (begin_definition_of_inclass_inline): New function, split
out from ...
(do_pending_inlines): Here, and ...
(process_next_inline): Here.
(get_time_identifier): Use TIME_IDENTIFIER_* macros.
(init_filename_times): Likewise.
(extract_interface_info): Likewise.
(ste_typedecl_interface_info): Likewise.
(check_newline): Likewise.
(dump_time_statistics): Likewise.
(handle_cp_pragma): Likewise.
(do_identifier): Adjust for new name-lookup scheme.
* parse.y (function_try_block): Return ctor_initializer_opt value.
(fndef): Use it.
(fn.defpen): Pass appropriate values to start_function.
(pending_inline): Use functor_try_block value, and pass
appropriate values to finish_function.
* pt.c (is_member_template): Update documentation; remove handling
of FUNCTION_DECLs.  As per name, this function should deal only in
TEMPLATE_DECLs.
(decl_template_parm_p): Change name of olddecl parameter to decl.
(check_template_shadow): Adjust for new name-lookup scheme.
(lookup_template_class): Likewise.
(tsubst_decl): Tweak so as not to confuse member templates with
copy constructors and assignment operators.
(unify): Handle UNION_TYPEs.
* ptree.c (print_lang_identifier): Adjust for new name-lookup scheme.
(lang_print_xnode): Adjust for new name-lookup scheme.
* typeck.c (mark_addressable): Likewise.
(c_expand_return): Likewise.

From-SVN: r24296

19 files changed:
gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/lex.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/ptree.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.bugs/900511_02.C
gcc/testsuite/g++.old-deja/g++.bugs/900511_03.C
gcc/testsuite/g++.old-deja/g++.other/for1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/lookup6.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.other/overload9.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/copy1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/friend34.C
gcc/testsuite/g++.old-deja/g++.pt/union1.C [new file with mode: 0644]

index 1c3bd37b8412da5c1dc21b16226952f551cec236..84cc28fa1b7d0ddb21b22fc1db13ddf8700d048f 100644 (file)
@@ -1,3 +1,84 @@
+1998-12-13  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.def (CPLUS_BINDING): Update documentation.
+       * cp-tree.h (LOCAL_BINDING_P): New macro.
+       (lang_identifier): Rename local_value to bindings.
+       (tree_binding): Make `scope' of type `void*', not `tree'.
+       (BINDING_SCOPE): Update documentation.
+       (IDENTIFIER_LOCAL_VALUE): Remove.
+       (IDENTIFIER_CLASS_VALUE): Document.
+       (IDENTIFIER_BINDING): New macro.
+       (IDENTIFIER_VALUE): Likewise.
+       (TIME_IDENTIFIER_TIME): Likewise.
+       (TIME_IDENTIFIER_FILEINFO): Likewise.
+       (IMPLICIT_TYPENAME_P): Likewise.
+       (set_identifier_local_value): Remove.
+       (push_local_binding): New function.
+       (push_class_binding): Likewise.
+       * class.c (pushclass): Update comments; use push_class_binding.
+       * decl.c (set_identifier_local_value_with_scope): Remove.
+       (set_identifier_local_value): Likewise.
+       (push_binding): New function.
+       (pop_binding): Likewise.
+       (binding_level): Update documentation.  Remove shadowed.
+       (BINDING_LEVEL): New macro.
+       (free_binding_nodes): New variable.
+       (poplevel): Adjust for new name-lookup scheme.  Don't mess up
+       BLOCK_VARs when doing for-scope extension.  Remove effectively
+       dead code.
+       (pushlevel_class): Tweak formatting.
+       (poplevel_class): Adjust for new name-lookup scheme.
+       (print_binding_level): Likewise.
+       (store_bindings): Likewise.
+       (pushdecl): Likewise.
+       (pushdecl_class_level): Likewise.
+       (push_class_level_binding): Likewise.
+       (push_overloaded_decl): Update comments.  Adjust for new
+       name-lookup scheme.
+       (lookup_name_real): Likewise.
+       (lookup_name_current_level): Likewise.
+       (cp_finish_decl): Likewise.
+       (require_complete_types_for_parms): Likewise.  Remove misleading
+       #if 0'd code. 
+       (grok_parms): Likewise.  Don't call
+       require_complete_types_for_parms here.
+       (grok_ctor_properties): Don't treat templates as copy
+       constructors. 
+       (grop_op_properties): Or as assignment operators.
+       (start_function): Document.  Adjust for new name-lookup scheme.
+       (finish_function): Likewise.
+       * decl2.c (do_local_using_decl): Use push_local_binding.
+       * lex.c (begin_definition_of_inclass_inline): New function, split
+       out from ...
+       (do_pending_inlines): Here, and ...
+       (process_next_inline): Here.
+       (get_time_identifier): Use TIME_IDENTIFIER_* macros.
+       (init_filename_times): Likewise.
+       (extract_interface_info): Likewise.
+       (ste_typedecl_interface_info): Likewise.
+       (check_newline): Likewise.
+       (dump_time_statistics): Likewise.
+       (handle_cp_pragma): Likewise.
+       (do_identifier): Adjust for new name-lookup scheme.
+       * parse.y (function_try_block): Return ctor_initializer_opt value.
+       (fndef): Use it.
+       (fn.defpen): Pass appropriate values to start_function.
+       (pending_inline): Use functor_try_block value, and pass
+       appropriate values to finish_function.
+       * pt.c (is_member_template): Update documentation; remove handling
+       of FUNCTION_DECLs.  As per name, this function should deal only in
+       TEMPLATE_DECLs. 
+       (decl_template_parm_p): Change name of olddecl parameter to decl.
+       (check_template_shadow): Adjust for new name-lookup scheme.
+       (lookup_template_class): Likewise.
+       (tsubst_decl): Tweak so as not to confuse member templates with
+       copy constructors and assignment operators.
+       (unify): Handle UNION_TYPEs.
+       * ptree.c (print_lang_identifier): Adjust for new name-lookup scheme.
+       (lang_print_xnode): Adjust for new name-lookup scheme.
+       * typeck.c (mark_addressable): Likewise.
+       (c_expand_return): Likewise.
+       
 1998-12-08  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl.c (grokdeclarator): Allow field with same name as class
index a73605a96e5df9b7a834119343580eeb2a09a069..5031b55691758579ef6f341b69c6ded098f14286 100644 (file)
@@ -4780,15 +4780,18 @@ pushclass (type, modify)
        {
          tree item;
 
-         /* Hooray, we successfully cached; let's just install the
-            cached class_shadowed list, and walk through it to get the
-            IDENTIFIER_TYPE_VALUEs correct.  */
+         /* We are re-entering the same class we just left, so we
+            don't have to search the whole inheritance matrix to find
+            all the decls to bind again.  Instead, we install the
+            cached class_shadowed list, and walk through it binding
+            names and setting up IDENTIFIER_TYPE_VALUEs.  */
          set_class_shadows (previous_class_values);
          for (item = previous_class_values; item; item = TREE_CHAIN (item))
            {
              tree id = TREE_PURPOSE (item);
              tree decl = IDENTIFIER_CLASS_VALUE (id);
 
+             push_class_binding (id, decl);
              if (TREE_CODE (decl) == TYPE_DECL)
                set_identifier_type_value (id, TREE_TYPE (decl));
            }
index 3c50e8fe2994b9ccd0d0df31ea14be9cc123b56e..37c444687fa1b39a2b848625b77e4fc40034e502 100644 (file)
@@ -178,9 +178,9 @@ DEFTREECODE (DEFAULT_ARG, "default_arg", 'c', 2)
    the template may be an IDENTIFIER_NODE.  */
 DEFTREECODE (TEMPLATE_ID_EXPR, "template_id_expr", 'e', 2)
 
-/* An association between namespace and entity. Parameters are the
-   scope and the (non-type) value.
-   TREE_TYPE indicates the type bound to the name. */
+/* An association between name and entity. Parameters are the scope
+   and the (non-type) value.  TREE_TYPE indicates the type bound to
+   the name. */
 DEFTREECODE (CPLUS_BINDING, "binding", 'x', 2)
 
 /* A list-like node for chaining overloading candidates. TREE_TYPE is 
index 119efdd9888a9df09fb494c2eefdbd4fbfe0686c..395b24a2b40b1aa0b0277119f52957619eb5ef60 100644 (file)
@@ -31,6 +31,7 @@ Boston, MA 02111-1307, USA.  */
       LOOKUP_EXPR_GLOBAL (in LOOKUP_EXPR).
       TREE_NEGATED_INT (in INTEGER_CST).
       IDENTIFIER_MARKED (used by search routines).
+      LOCAL_BINDING_P (in CPLUS_BINDING)
    1:  IDENTIFIER_VIRTUAL_P.
       TI_PENDING_TEMPLATE_FLAG.
       TEMPLATE_PARMS_FOR_INLINE.
@@ -92,7 +93,8 @@ Boston, MA 02111-1307, USA.  */
 struct lang_identifier
 {
   struct tree_identifier ignore;
-  tree namespace_bindings, local_value;
+  tree namespace_bindings;
+  tree bindings;
   tree class_value;
   tree class_template_info;
   struct lang_id2 *x;
@@ -127,15 +129,24 @@ typedef struct ptrmem_cst
   tree member;
 }* ptrmem_cst_t;
 
-/* For a binding between a name and an entity, defines the scope
-   where the binding is declared. Currently always points to a
-   namespace declaration.  */
-#define BINDING_SCOPE(NODE)    (((struct tree_binding*)NODE)->scope)
+/* Nonzero if this binding is for a local scope, as opposed to a class
+   or namespace scope.  */
+#define LOCAL_BINDING_P(NODE) TREE_LANG_FLAG_0(NODE)
+
+/* For a binding between a name and an entity at a non-local scope,
+   defines the scope where the binding is declared.  (Either a class
+   _TYPE node, or a NAMESPACE_DECL.)  This macro should be used only
+   for namespace-level bindings; on the IDENTIFIER_BINDING list
+   BINDING_LEVEL is used instead.  */
+#define BINDING_SCOPE(NODE) ((tree) ((struct tree_binding*)NODE)->scope)
+
 /* This is the declaration bound to the name. Possible values:
    variable, overloaded function, namespace, template, enumerator.  */
 #define BINDING_VALUE(NODE)    (((struct tree_binding*)NODE)->value)
+
 /* If name is bound to a type, this is the type (struct, union, enum).  */
 #define BINDING_TYPE(NODE)     TREE_TYPE(NODE)
+
 #define IDENTIFIER_GLOBAL_VALUE(NODE) \
   namespace_binding (NODE, global_namespace)
 #define SET_IDENTIFIER_GLOBAL_VALUE(NODE, VAL) \
@@ -148,7 +159,7 @@ typedef struct ptrmem_cst
 struct tree_binding
 {
   char common[sizeof (struct tree_common)];
-  tree scope;
+  void* scope;
   tree value;
 };
 
@@ -200,13 +211,43 @@ struct tree_srcloc
 
 #define IDENTIFIER_NAMESPACE_BINDINGS(NODE)    \
   (((struct lang_identifier *)(NODE))->namespace_bindings)
-#define IDENTIFIER_CLASS_VALUE(NODE)   \
-  (((struct lang_identifier *)(NODE))->class_value)
-#define IDENTIFIER_LOCAL_VALUE(NODE)   \
-  (((struct lang_identifier *)(NODE))->local_value)
 #define IDENTIFIER_TEMPLATE(NODE)      \
   (((struct lang_identifier *)(NODE))->class_template_info)
 
+/* The IDENTIFIER_BINDING is the innermost CPLUS_BINDING for the
+    identifier.  It's TREE_CHAIN is the next outermost binding.  Each
+    BINDING_VALUE is a DECL for the associated declaration.  Thus,
+    name lookup consists simply of pulling off the node at the front
+    of the list (modulo oddities for looking up the names of types,
+    and such.)  You can use BINDING_SCOPE or BINDING_LEVEL to
+    determine the scope that bound the name.  */
+#define IDENTIFIER_BINDING(NODE) \
+  (((struct lang_identifier*) (NODE))->bindings)
+
+/* The IDENTIFIER_VALUE is the value of the IDENTIFIER_BINDING, or
+   NULL_TREE if there is no binding.  */
+#define IDENTIFIER_VALUE(NODE)                 \
+  (IDENTIFIER_BINDING (NODE)                   \
+   ? BINDING_VALUE (IDENTIFIER_BINDING (NODE)) \
+   : NULL_TREE)
+
+/* If we are currently in class scope, then IDENTIFIER_CLASS_VALUE
+   indicates the class-scoped binding of NODE.  This is just a pointer
+   to the BINDING_VALUE of one of the bindings in the
+   IDENTIFIER_BINDINGs list, so any time that this is set so is
+   IDENTIFIER_BINDING.  */
+#define IDENTIFIER_CLASS_VALUE(NODE) \
+  (((struct lang_identifier *) (NODE))->class_value)
+
+/* The amount of time used by the file whose special "time identifier"
+   is NODE, represented as an INTEGER_CST.  See get_time_identifier.  */
+#define TIME_IDENTIFIER_TIME(NODE) IDENTIFIER_BINDING(NODE)
+
+/* For a "time identifier" this is a INTEGER_CST.  The
+   TREE_INT_CST_LOW is 1 if the corresponding file is "interface only".
+   The TRE_INT_CST_HIGH is 1 if it is "interface unknown".  */
+#define TIME_IDENTIFIER_FILEINFO(NODE) IDENTIFIER_CLASS_VALUE (NODE)
+
 /* TREE_TYPE only indicates on local and class scope the current
    type. For namespace scope, the presence of a type in any namespace
    is indicated with global_type_node, and the real type behind must
@@ -1444,6 +1485,10 @@ struct lang_decl
    TEMPLATE_ID_EXPR if we had something like `typename X::Y<T>'.  */
 #define TYPENAME_TYPE_FULLNAME(NODE) TYPE_BINFO (NODE)
 
+/* Nonzero if NODE is an implicit typename.  */
+#define IMPLICIT_TYPENAME_P(NODE) \
+  (TREE_CODE (NODE) == TYPENAME_TYPE && TREE_TYPE (NODE))
+
 /* Nonzero in INTEGER_CST means that this int is negative by dint of
    using a twos-complement negated operand.  */
 #define TREE_NEGATED_INT(NODE) (TREE_LANG_FLAG_0 (NODE))
@@ -2665,7 +2710,6 @@ extern void push_to_top_level                     PROTO((void));
 extern void pop_from_top_level                 PROTO((void));
 extern tree identifier_type_value              PROTO((tree));
 extern void set_identifier_type_value          PROTO((tree, tree));
-extern void set_identifier_local_value         PROTO((tree, tree));
 extern void pop_everything                     PROTO((void));
 extern void pushtag                            PROTO((tree, tree, int));
 extern tree make_anon_name                     PROTO((void));
@@ -2761,6 +2805,8 @@ extern void revert_static_member_fn             PROTO((tree*, tree*, tree*));
 extern void cat_namespace_levels                PROTO((void));
 extern void fixup_anonymous_union               PROTO((tree));
 extern int check_static_variable_definition     PROTO((tree, tree));
+extern void push_local_binding                  PROTO((tree, tree));
+extern void push_class_binding                  PROTO((tree, tree));
 
 /* in decl2.c */
 extern int check_java_method                   PROTO((tree));
index c2afcb7d0fcfdf913507de9198421b2982e9e899..7c9a518e1617eb5fd04236fb865fbfcad1e510dd 100644 (file)
@@ -169,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 *));
@@ -181,6 +179,8 @@ static tree maybe_process_template_type_declaration PROTO((tree, int, struct bin
 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));
@@ -611,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
@@ -631,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),
@@ -661,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.
@@ -1030,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.
@@ -1063,6 +1171,13 @@ 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,
@@ -1127,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;
 
@@ -1148,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);
        }
     }
@@ -1159,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,
@@ -1407,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;
@@ -1444,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,
@@ -1468,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,
@@ -1574,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:");
@@ -1932,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))
@@ -1954,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;
@@ -2085,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);
@@ -2169,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
@@ -3322,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);
@@ -3459,6 +3573,11 @@ pushdecl (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);
@@ -3495,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.
@@ -3536,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 
@@ -3575,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.  */
@@ -3619,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.  */;
@@ -3642,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",
@@ -3686,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;
 }
@@ -3828,9 +3959,7 @@ pushdecl_class_level (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));
     }
 }
 
@@ -3874,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);
 }
 
@@ -3934,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.
@@ -3952,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)))
@@ -3969,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)
     {
@@ -4011,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;
 }
@@ -5073,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. */
@@ -5166,140 +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 () && IDENTIFIER_LOCAL_VALUE (name))
-    {
-      locval = qualify_lookup (IDENTIFIER_LOCAL_VALUE (name), flags);
+  /* 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);
 
-      /* Kludge kludge kludge */
-      if (locval == NULL_TREE && prefer_type)
-       {
-         locval = REAL_IDENTIFIER_TYPE_VALUE (name);
-         if (locval && locval != global_type_node
-             && TYPE_NAME (locval)
-             && DECL_FUNCTION_SCOPE_P (TYPE_NAME (locval)))
-           locval = TYPE_NAME (locval);
-         else
-           locval = NULL_TREE;
-       }
-    }
-
-  /* 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 primarily interested in
-          TYPE_DECLs or constants.  */
-       classval = lookup_field (current_class_type, name, 0, prefer_type);
-
-      /* 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);
-
-      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:
+      tree global_val;
 
-          o We are in a member function of a class.
-           o We are in a local class within a function.
+      /* Any other name takes precedence over an implicit typename.  Warn the
+        user about this potentially confusing lookup.  */
+      global_val = unqualified_namespace_lookup (name, flags);
 
-        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);
-
-  /* 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);
-
-      if (locval && val != locval)
+      if (global_val)
        {
          tree subtype;
 
-         val = locval;
-
          /* Only warn when not lexing; we don't want to warn if they
             use this name as a declarator.  */
-         subtype = TREE_TYPE (TREE_TYPE (classval));
+         subtype = TREE_TYPE (TREE_TYPE (val));
          if (! yylex
-             && ! (TREE_CODE (locval) == TEMPLATE_DECL
+             && ! (TREE_CODE (global_val) == TEMPLATE_DECL
                    && CLASSTYPE_TEMPLATE_INFO (subtype)
-                   && CLASSTYPE_TI_TEMPLATE (subtype) == locval)
-             && ! (TREE_CODE (locval) == TYPE_DECL
-                   && same_type_p (TREE_TYPE (locval), subtype)))
+                   && CLASSTYPE_TI_TEMPLATE (subtype) == global_val)
+             && ! (TREE_CODE (global_val) == TYPE_DECL
+                   && same_type_p (TREE_TYPE (global_val), subtype)))
            {
-             cp_warning ("lookup of `%D' finds `%#D'", name, locval);
+             cp_warning ("lookup of `%D' finds `%#D'", name, global_val);
              cp_warning ("  instead of `%D' from dependent base class",
-                         classval);
+                         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)
@@ -5381,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
@@ -7681,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,
@@ -7693,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 ();
@@ -11032,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);
@@ -11058,31 +11143,7 @@ require_complete_types_for_parms (parms)
        }
       else
        layout_decl (parms, 0);
-#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
+
       parms = TREE_CHAIN (parms);
     }
 }
@@ -11276,16 +11337,20 @@ 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;
                            }
@@ -11349,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;
 }
 
@@ -11417,20 +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_PURPOSE (TREE_CHAIN (parmtypes))))
+              || 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);
@@ -11486,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;
@@ -12477,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.
 
@@ -12577,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;
     }
@@ -12636,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",
@@ -12695,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
@@ -12937,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);
 
@@ -13025,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)
@@ -13135,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;
@@ -13155,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.  */
@@ -13560,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
@@ -13568,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
@@ -13579,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;
@@ -13670,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);
 
@@ -13710,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.
@@ -13849,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,
index 570d2929ef280ee3590c18dcf219b81fecb86112..630e262183f058cb55b65a24e51761bfadfff787 100644 (file)
@@ -4829,7 +4829,7 @@ do_local_using_decl (decl)
   do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
 
   if (newval)
-    set_identifier_local_value (name, newval);
+    push_local_binding (name, newval);
   if (newtype)
     set_identifier_type_value (name, newtype);
 }
index 45d3d41c3c9e42850ec9edf67cb7694ed0ffbf07..e6dd29fe31a3d27bf5e5bce7b0fdcdff2b1ab2e7 100644 (file)
@@ -84,6 +84,7 @@ static int reduce_cmp PROTO((int *, int *));
 static int token_cmp PROTO((int *, int *));
 #endif
 #endif
+static void begin_definition_of_inclass_inline PROTO((struct pending_inline*));
 
 /* Given a file name X, return the nondirectory portion.
    Keep in mind that X can be computed more than once.  */
@@ -322,12 +323,13 @@ get_time_identifier (name)
   bcopy (name, buf+5, len);
   buf[len+5] = '\0';
   time_identifier = get_identifier (buf);
-  if (IDENTIFIER_LOCAL_VALUE (time_identifier) == NULL_TREE)
+  if (TIME_IDENTIFIER_TIME (time_identifier) == NULL_TREE)
     {
       push_obstacks_nochange ();
       end_temporary_allocation ();
-      IDENTIFIER_LOCAL_VALUE (time_identifier) = build_int_2 (0, 0);
-      IDENTIFIER_CLASS_VALUE (time_identifier) = build_int_2 (0, 1);
+      TIME_IDENTIFIER_TIME (time_identifier) = build_int_2 (0, 0);
+      TIME_IDENTIFIER_FILEINFO (time_identifier) 
+       = build_int_2 (0, 1);
       SET_IDENTIFIER_GLOBAL_VALUE (time_identifier, filename_times);
       filename_times = time_identifier;
       pop_obstacks ();
@@ -435,7 +437,8 @@ init_filename_times ()
     {
       header_time = 0;
       body_time = my_get_run_time ();
-      TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time)) = body_time;
+      TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time)) 
+       = body_time;
     }
 }
 
@@ -1145,7 +1148,7 @@ extract_interface_info ()
     }
   if (!fileinfo)
     fileinfo = get_time_identifier (input_filename);
-  fileinfo = IDENTIFIER_CLASS_VALUE (fileinfo);
+  fileinfo = TIME_IDENTIFIER_FILEINFO (fileinfo);
   interface_only = TREE_INT_CST_LOW (fileinfo);
   interface_unknown = TREE_INT_CST_HIGH (fileinfo);
 }
@@ -1196,7 +1199,7 @@ set_typedecl_interface_info (prev, vars)
      tree prev ATTRIBUTE_UNUSED, vars;
 {
   tree id = get_time_identifier (DECL_SOURCE_FILE (vars));
-  tree fileinfo = IDENTIFIER_CLASS_VALUE (id);
+  tree fileinfo = TIME_IDENTIFIER_FILEINFO (id);
   tree type = TREE_TYPE (vars);
 
   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
@@ -1222,6 +1225,37 @@ set_vardecl_interface_info (prev, vars)
   return 0;
 }
 \f
+/* Set up the state required to correctly handle the definition of the
+   inline function whose preparsed state has been saved in PI.  */
+
+static void
+begin_definition_of_inclass_inline (pi)
+     struct pending_inline* pi;
+{
+  tree context;
+
+  if (!pi->fndecl)
+    return;
+
+  /* If this is an inline function in a local class, we must make sure
+     that we save all pertinent information about the function
+     surrounding the local class.  */
+  context = hack_decl_function_context (pi->fndecl);
+  if (context)
+    push_cp_function_context (context);
+
+  feed_input (pi->buf, pi->len);
+  lineno = pi->lineno;
+  input_filename = pi->filename;
+  yychar = PRE_PARSED_FUNCTION_DECL;
+  yylval.ttype = build_tree_list ((tree) pi, pi->fndecl);
+  /* Pass back a handle to the rest of the inline functions, so that they
+     can be processed later.  */
+  DECL_PENDING_INLINE_INFO (pi->fndecl) = 0;
+  interface_unknown = pi->interface == 1;
+  interface_only  = pi->interface == 0;
+}
+
 /* Called from the top level: if there are any pending inlines to
    do, set up to process them now.  This function sets up the first function
    to be parsed; after it has been, the rule for fndef in parse.y will
@@ -1231,7 +1265,6 @@ void
 do_pending_inlines ()
 {
   struct pending_inline *t;
-  tree context;
 
   /* Oops, we're still dealing with the last batch.  */
   if (yychar == PRE_PARSED_FUNCTION_DECL)
@@ -1258,32 +1291,7 @@ do_pending_inlines ()
     return;
            
   /* Now start processing the first inline function.  */
-  context = hack_decl_function_context (t->fndecl);
-  if (context)
-    push_cp_function_context (context);
-  maybe_begin_member_template_processing (t->fndecl);
-  if (t->len > 0)
-    {
-      feed_input (t->buf, t->len);
-      lineno = t->lineno;
-#if 0
-      if (input_filename != t->filename)
-       {
-         input_filename = t->filename;
-         /* Get interface/implementation back in sync.  */
-         extract_interface_info ();
-       }
-#else
-      input_filename = t->filename;
-      interface_unknown = t->interface == 1;
-      interface_only = t->interface == 0;
-#endif
-      yychar = PRE_PARSED_FUNCTION_DECL;
-    }
-  /* Pass back a handle on the rest of the inline functions, so that they
-     can be processed later.  */
-  yylval.ttype = build_tree_list ((tree) t, t->fndecl);
-  DECL_PENDING_INLINE_INFO (t->fndecl) = 0;
+  begin_definition_of_inclass_inline (t);
 }
 
 static int nextchar = -1;
@@ -1299,7 +1307,6 @@ process_next_inline (t)
   tree context;
   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
   context = hack_decl_function_context (i->fndecl);  
-  maybe_end_member_template_processing ();
   if (context)
     pop_cp_function_context (context);
   i = i->next;
@@ -1317,24 +1324,8 @@ process_next_inline (t)
     }
   yychar = YYEMPTY;
   end_input ();
-  if (i && i->fndecl != NULL_TREE)
-    {
-      context = hack_decl_function_context (i->fndecl);
-      if (context)
-       push_cp_function_context (context);
-      maybe_begin_member_template_processing (i->fndecl);
-      feed_input (i->buf, i->len);
-      lineno = i->lineno;
-      input_filename = i->filename;
-      yychar = PRE_PARSED_FUNCTION_DECL;
-      yylval.ttype = build_tree_list ((tree) i, i->fndecl);
-      DECL_PENDING_INLINE_INFO (i->fndecl) = 0;
-    }
   if (i)
-    {
-      interface_unknown = i->interface == 1;
-      interface_only = i->interface == 0;
-    }
+    begin_definition_of_inclass_inline (i);
   else
     extract_interface_info ();
 }
@@ -2507,7 +2498,7 @@ linenum:
          int this_time = my_get_run_time ();
          tree time_identifier = get_time_identifier (TREE_STRING_POINTER (yylval.ttype));
          header_time += this_time - body_time;
-         TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+         TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
            += this_time - body_time;
          this_filename_time = time_identifier;
          body_time = this_time;
@@ -2943,11 +2934,9 @@ do_identifier (token, parsing, args)
   /* Do Koenig lookup if appropriate (inside templates we build lookup
      expressions instead).  */
   if (args && !current_template_parms && (!id || is_global (id)))
-    {
-      /* If we have arguments and we only found global names,
-         do Koenig lookup. */
-      id = lookup_arg_dependent (token, id, args);
-    }
+    /* If we have arguments and we only found global names, do Koenig
+         lookup. */
+    id = lookup_arg_dependent (token, id, args);
 
   /* Remember that this name has been used in the class definition, as per
      [class.scope0] */
@@ -3183,16 +3172,20 @@ identifier_typedecl_value (node)
   type = IDENTIFIER_TYPE_VALUE (node);
   if (type == NULL_TREE)
     return NULL_TREE;
-#define do(X) \
-  { \
-    t = (X); \
-    if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type) \
-      return t; \
-  }
-  do (IDENTIFIER_LOCAL_VALUE (node));
-  do (IDENTIFIER_CLASS_VALUE (node));
-  do (IDENTIFIER_NAMESPACE_VALUE (node));
-#undef do
+
+  if (IDENTIFIER_BINDING (node))
+    {
+      t = IDENTIFIER_VALUE (node);
+      if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+       return t;
+    }
+  if (IDENTIFIER_NAMESPACE_VALUE (node))
+    {
+      t = IDENTIFIER_NAMESPACE_VALUE (node);
+      if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == type)
+       return t;
+    }
+
   /* Will this one ever happen?  */
   if (TYPE_MAIN_DECL (type))
     return TYPE_MAIN_DECL (type);
@@ -4737,7 +4730,7 @@ dump_time_statistics ()
 {
   register tree prev = 0, decl, next;
   int this_time = my_get_run_time ();
-  TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (this_filename_time))
+  TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (this_filename_time))
     += this_time - body_time;
 
   fprintf (stderr, "\n******\n");
@@ -4756,7 +4749,7 @@ dump_time_statistics ()
 
   for (decl = prev; decl; decl = IDENTIFIER_GLOBAL_VALUE (decl))
     print_time (IDENTIFIER_POINTER (decl),
-               TREE_INT_CST_LOW (IDENTIFIER_LOCAL_VALUE (decl)));
+               TREE_INT_CST_LOW (TIME_IDENTIFIER_TIME (decl)));
 }
 
 void
@@ -4847,7 +4840,8 @@ handle_cp_pragma (pname)
     }
   else if (! strcmp (pname, "interface"))
     {
-      tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+      tree fileinfo 
+       = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
       char *main_filename = input_filename;
 
       main_filename = file_name_nondirectory (main_filename);
@@ -4882,7 +4876,7 @@ handle_cp_pragma (pname)
 #ifdef AUTO_IMPLEMENT
          filename = file_name_nondirectory (main_input_filename);
          fi = get_time_identifier (filename);
-         fi = IDENTIFIER_CLASS_VALUE (fi);
+         fi = TIME_IDENTIFIER_FILEINFO (fi);
          TREE_INT_CST_LOW (fi) = 0;
          TREE_INT_CST_HIGH (fi) = 1;
          /* Get default.  */
@@ -4902,7 +4896,8 @@ handle_cp_pragma (pname)
     }
   else if (! strcmp (pname, "implementation"))
     {
-      tree fileinfo = IDENTIFIER_CLASS_VALUE (get_time_identifier (input_filename));
+      tree fileinfo 
+       = TIME_IDENTIFIER_FILEINFO (get_time_identifier (input_filename));
       char *main_filename = main_input_filename ? main_input_filename : input_filename;
 
       main_filename = file_name_nondirectory (main_filename);
index 87ac736ea1ebcc711b37ba9478874ce0d599c94f..4d4827c95e0959b82cf99e764a8c6ff4229b146b 100644 (file)
@@ -236,7 +236,7 @@ empty_parms ()
 %token <ttype> PRE_PARSED_CLASS_DECL DEFARG DEFARG_MARKER
 %type <ttype> component_constructor_declarator
 %type <ttype> fn.def2 return_id fn.defpen constructor_declarator
-%type <itype> ctor_initializer_opt
+%type <itype> ctor_initializer_opt function_try_block
 %type <ttype> named_class_head named_class_head_sans_basetype
 %type <ttype> named_complex_class_head_sans_basetype
 %type <ttype> unnamed_class_head
@@ -639,7 +639,11 @@ fndef:
          fn.def1 maybe_return_init ctor_initializer_opt compstmt_or_error
                { finish_function (lineno, (int)$3, 0); }
        | fn.def1 maybe_return_init function_try_block
-               { }
+               { 
+                 int nested = (hack_decl_function_context
+                               (current_function_decl) != NULL_TREE);
+                 finish_function (lineno, (int)$3, nested); 
+               }
        | fn.def1 maybe_return_init error
                { }
        ;
@@ -2037,7 +2041,7 @@ initlist:
 fn.defpen:
        PRE_PARSED_FUNCTION_DECL
                { start_function (NULL_TREE, TREE_VALUE ($1),
-                                 NULL_TREE, 1);
+                                 NULL_TREE, 2);
                  reinit_parse_for_function (); }
 
 pending_inline:
@@ -2045,11 +2049,16 @@ pending_inline:
                {
                  int nested = (hack_decl_function_context
                                (current_function_decl) != NULL_TREE);
-                 finish_function (lineno, (int)$3, nested);
+                 finish_function (lineno, (int)$3 | 2, nested);
                  process_next_inline ($1);
                }
        | fn.defpen maybe_return_init function_try_block
-               { process_next_inline ($1); }
+               { 
+                 int nested = (hack_decl_function_context
+                               (current_function_decl) != NULL_TREE);
+                 finish_function (lineno, (int)$3 | 2, nested); 
+                  process_next_inline ($1);
+               }
        | fn.defpen maybe_return_init error
                { process_next_inline ($1); }
        ;
@@ -3339,10 +3348,8 @@ function_try_block:
                 }
          handler_seq
                {
-                 int nested = (hack_decl_function_context
-                               (current_function_decl) != NULL_TREE);
                  expand_end_all_catch ();
-                 finish_function (lineno, (int)$3, nested);
+                 $$ = $3;
                }
        ;
 
index 50e44b5879ba8681a5a2c20a97f242468a5052fa..bdf85dd760f174447793eb2c66630ace2a1412c3 100644 (file)
@@ -426,14 +426,14 @@ maybe_end_member_template_processing ()
      template <class T> class C { template <class U> void f(U); }
 
    then neither C<int>::f<char> nor C<T>::f<double> is considered
-   to be a member template.  */
+   to be a member template.  But, `template <class U> void
+   C<int>::f(U)' is considered a member template.  */
 
 int
 is_member_template (t)
      tree t;
 {
-  if (TREE_CODE (t) != FUNCTION_DECL
-      && !DECL_FUNCTION_TEMPLATE_P (t))
+  if (!DECL_FUNCTION_TEMPLATE_P (t))
     /* Anything that isn't a function or a template function is
        certainly not a member template.  */
     return 0;
@@ -442,31 +442,12 @@ is_member_template (t)
   if (hack_decl_function_context (t))
     return 0;
 
-  if ((DECL_FUNCTION_MEMBER_P (t) 
-       && !DECL_TEMPLATE_SPECIALIZATION (t))
-      || (TREE_CODE (t) == TEMPLATE_DECL 
-         && DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
-    {
-      tree tmpl;
-
-      if (DECL_FUNCTION_TEMPLATE_P (t))
-       tmpl = t;
-      else if (DECL_TEMPLATE_INFO (t) 
-              && DECL_FUNCTION_TEMPLATE_P (DECL_TI_TEMPLATE (t)))
-       tmpl = DECL_TI_TEMPLATE (t);
-      else
-       tmpl = NULL_TREE;
-
-      if (tmpl
+  return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
          /* If there are more levels of template parameters than
             there are template classes surrounding the declaration,
             then we have a member template.  */
-         && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) > 
-             template_class_depth (DECL_CLASS_CONTEXT (t))))
-       return 1;
-    }
-
-  return 0;
+         && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > 
+             template_class_depth (DECL_CLASS_CONTEXT (t))));
 }
 
 #if 0 /* UNUSED */
@@ -1487,28 +1468,27 @@ int comp_template_parms (parms1, parms2)
 }
 
 
-/* Returns 1 iff old_id is a template parameter. OLD_DECL is the decl
-   from IDENTIFIER_LOCAL_VALUE (new identifier). */
+/* Returns 1 iff DECL is a template parameter.  */
 
-int decl_template_parm_p (old_decl)
-     tree old_decl;
+int decl_template_parm_p (decl)
+     tree decl;
 {
   /* For template template parms. */
-  if (TREE_CODE (old_decl) == TEMPLATE_DECL
-      && TREE_TYPE (old_decl)
-      && TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TEMPLATE_PARM)
+  if (TREE_CODE (decl) == TEMPLATE_DECL
+      && TREE_TYPE (decl)
+      && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
     return 1;
 
   /* For template type parms. */
-  if (TREE_CODE (old_decl) == TYPE_DECL
-      && TREE_TYPE (old_decl)
-      && TREE_CODE (TREE_TYPE (old_decl)) == TEMPLATE_TYPE_PARM)
+  if (TREE_CODE (decl) == TYPE_DECL
+      && TREE_TYPE (decl)
+      && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM)
     return 1;
 
   /* For template non-type parms. */
-  if (TREE_CODE (old_decl) == CONST_DECL
-      && DECL_INITIAL (old_decl) 
-      && TREE_CODE (DECL_INITIAL (old_decl)) == TEMPLATE_PARM_INDEX)
+  if (TREE_CODE (decl) == CONST_DECL
+      && DECL_INITIAL (decl) 
+      && TREE_CODE (DECL_INITIAL (decl)) == TEMPLATE_PARM_INDEX)
     return 1;
 
   return 0;
@@ -1523,11 +1503,10 @@ void
 check_template_shadow (decl)
      tree decl;
 {
-  if (current_template_parms 
-      && IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)))
-    {
-      tree olddecl = IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl));
+  tree olddecl = IDENTIFIER_VALUE (DECL_NAME (decl));
 
+  if (current_template_parms && olddecl)
+    {
       /* We check for decl != olddecl to avoid bogus errors for using a
         name inside a class.  We check TPFI to avoid duplicate errors for
         inline member templates.  */
@@ -3423,9 +3402,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
 
   if (TREE_CODE (d1) == IDENTIFIER_NODE)
     {
-      if (IDENTIFIER_LOCAL_VALUE (d1) 
-         && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_LOCAL_VALUE (d1)))
-       template = IDENTIFIER_LOCAL_VALUE (d1);
+      if (IDENTIFIER_VALUE (d1) 
+         && DECL_TEMPLATE_TEMPLATE_PARM_P (IDENTIFIER_VALUE (d1)))
+       template = IDENTIFIER_VALUE (d1);
       else
        {
          if (context)
@@ -3468,9 +3447,10 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope)
     my_friendly_abort (272);
 
   /* With something like `template <class T> class X class X { ... };'
-     we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE.
-     We don't want to do that, but we have to deal with the situation, so
-     let's give them some syntax errors to chew on instead of a crash.  */
+     we could end up with D1 having nothing but an IDENTIFIER_VALUE.
+     We don't want to do that, but we have to deal with the situation,
+     so let's give them some syntax errors to chew on instead of a
+     crash.  */
   if (! template)
     {
       cp_error ("`%T' is not a template", d1);
@@ -5434,11 +5414,9 @@ tsubst_decl (t, args, type, in_decl)
        if (member && !strncmp (OPERATOR_TYPENAME_FORMAT,
                                IDENTIFIER_POINTER (DECL_NAME (r)),
                                sizeof (OPERATOR_TYPENAME_FORMAT) - 1))
-         {
-           /* Type-conversion operator.  Reconstruct the name, in
-              case it's the name of one of the template's parameters.  */
-           DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
-         }
+         /* Type-conversion operator.  Reconstruct the name, in
+            case it's the name of one of the template's parameters.  */
+         DECL_NAME (r) = build_typename_overload (TREE_TYPE (type));
 
        DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
        DECL_MAIN_VARIANT (r) = r;
@@ -5453,14 +5431,6 @@ tsubst_decl (t, args, type, in_decl)
        DECL_PENDING_INLINE_INFO (r) = 0;
        TREE_USED (r) = 0;
 
-       if (DECL_CONSTRUCTOR_P (r))
-         {
-           maybe_retrofit_in_chrg (r);
-           grok_ctor_properties (ctx, r);
-         }
-       if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
-         grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
-
        /* Set up the DECL_TEMPLATE_INFO for R and compute its mangled
           name.  There's no need to do this in the special friend
           case mentioned above where GEN_TMPL is NULL.  */
@@ -5507,6 +5477,14 @@ tsubst_decl (t, args, type, in_decl)
                    == NULL_TREE))
              SET_IDENTIFIER_GLOBAL_VALUE (DECL_ASSEMBLER_NAME (r), r);
          }
+
+       if (DECL_CONSTRUCTOR_P (r))
+         {
+           maybe_retrofit_in_chrg (r);
+           grok_ctor_properties (ctx, r);
+         }
+       if (IDENTIFIER_OPNAME_P (DECL_NAME (r)))
+         grok_op_properties (r, DECL_VIRTUAL_P (r), DECL_FRIEND_P (r));
       }
       break;
 
@@ -7688,11 +7666,12 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
       }
 
     case RECORD_TYPE:
+    case UNION_TYPE:
       if (TYPE_PTRMEMFUNC_FLAG (parm))
        return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
                      arg, strict, explicit_mask);
 
-      if (TREE_CODE (arg) != RECORD_TYPE)
+      if (TREE_CODE (arg) != TREE_CODE (parm))
        return 1;
   
       if (CLASSTYPE_TEMPLATE_INFO (parm) && uses_template_parms (parm))
index eddc2e47303e60d3f8dfaa2fbe46b31412be202d..4fb0413b9c0efa829ef9cab57e9897ee94a602f4 100644 (file)
@@ -152,7 +152,7 @@ print_lang_identifier (file, node, indent)
 {
   print_node (file, "bindings", IDENTIFIER_NAMESPACE_BINDINGS (node), indent + 4);
   print_node (file, "class", IDENTIFIER_CLASS_VALUE (node), indent + 4);
-  print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
+  print_node (file, "local bindings", IDENTIFIER_BINDING (node), indent + 4);
   print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
   print_node (file, "template", IDENTIFIER_TEMPLATE (node), indent + 4);
   print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
@@ -168,7 +168,8 @@ lang_print_xnode (file, node, indent)
   switch (TREE_CODE (node))
     {
     case CPLUS_BINDING:
-      print_node (file, "scope", BINDING_SCOPE (node), indent+4);
+      fprintf (file, " scope ");
+      fprintf (file, HOST_PTR_PRINTF, BINDING_SCOPE (node));
       print_node (file, "value", BINDING_VALUE (node), indent+4);
       print_node (file, "chain", TREE_CHAIN (node), indent+4);
       break;
index 58f42d2ffa5838581440a4bfc0df5e19f6ca2d78..fddc9998070d34341276570b60c0359a12dbfde0 100644 (file)
@@ -4849,7 +4849,8 @@ mark_addressable (exp)
 
            TREE_ASM_WRITTEN (x) = 0;
            DECL_RTL (x) = 0;
-           rest_of_decl_compilation (x, 0, IDENTIFIER_LOCAL_VALUE (x) == 0,
+           rest_of_decl_compilation (x, 0, 
+                                     !DECL_FUNCTION_SCOPE_P (x),
                                      0);
            TREE_ADDRESSABLE (x) = 1;
 
@@ -7235,9 +7236,9 @@ c_expand_return (retval)
              if (TEMP_NAME_P (DECL_NAME (whats_returned)))
                warning ("reference to non-lvalue returned");
              else if (TREE_CODE (TREE_TYPE (whats_returned)) != REFERENCE_TYPE
-                      && ! TREE_STATIC (whats_returned)
-                      && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
-                      && !TREE_PUBLIC (whats_returned))
+                      && DECL_FUNCTION_SCOPE_P (whats_returned)
+                      && !(TREE_STATIC (whats_returned)
+                           || TREE_PUBLIC (whats_returned)))
                cp_warning_at ("reference to local variable `%D' returned", whats_returned);
            }
        }
@@ -7247,9 +7248,9 @@ c_expand_return (retval)
 
          if (TREE_CODE (whats_returned) == VAR_DECL
              && DECL_NAME (whats_returned)
-             && IDENTIFIER_LOCAL_VALUE (DECL_NAME (whats_returned))
-             && !TREE_STATIC (whats_returned)
-             && !TREE_PUBLIC (whats_returned))
+             && DECL_FUNCTION_SCOPE_P (whats_returned)
+             && !(TREE_STATIC (whats_returned)
+                  || TREE_PUBLIC (whats_returned)))
            cp_warning_at ("address of local variable `%D' returned", whats_returned);
        }
     }
index 0154bfe41404b21e8a772c83c6e2f6ea7314b612..dcd35681bde59014f3d5d036f243aa495ef96a4d 100644 (file)
@@ -8,11 +8,11 @@
 
 // cfront 2.0 passes this test.
 
-enum enum0 { enum0_value_0 };  // ERROR - 
+enum enum0 { enum0_value_0 };
 
 struct struct0 {
-  int enum0;                   // ERROR - 
-  void member_function (enum0 e);
+  int enum0;                   
+  void member_function (enum0 e); // ERROR - 
 };
 
 void class0::member_function (enum0 e) {       // ERROR - 
index d8a549aa82c01ee253ca2225e8ec1b4d8b083237..d3cf47c575e714825527d35f987e4c5451b5d85b 100644 (file)
@@ -6,11 +6,11 @@
 
 // keywords: typedef names, shadowing, scope, formal parameter list
 
-class class0;                          // ERROR - 
+class class0;
 
 struct struct1 {
-  int class0;                  // ERROR - 
-  void member_function (class0 *);
+  int class0;                  
+  void member_function (class0 *); // ERROR - 
 };
 
 void class1::member_function (class0 *p) {     // ERROR - 
diff --git a/gcc/testsuite/g++.old-deja/g++.other/for1.C b/gcc/testsuite/g++.old-deja/g++.other/for1.C
new file mode 100644 (file)
index 0000000..31cd741
--- /dev/null
@@ -0,0 +1,41 @@
+// Build don't link:
+
+int i;
+int j;
+
+struct S {
+  int operator()(int)
+    {
+      i = 1;
+    }
+
+  typedef int I;
+
+  void f() {
+    for (S I; false; )
+      ;
+    int k = I(3);
+  }
+};
+
+typedef int J;
+
+struct T {
+  int operator()(int)
+    {
+      j = 1;
+    }
+
+  void f() {
+    for (T J; false; )
+      ;
+    int k = J(3);
+  }
+};
+
+int main()
+{
+  S s;
+  s.f();
+  return 2 * i + j;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/lookup6.C b/gcc/testsuite/g++.old-deja/g++.other/lookup6.C
new file mode 100644 (file)
index 0000000..08f5ac5
--- /dev/null
@@ -0,0 +1,25 @@
+int f(int i)
+{
+  struct C {
+    int i;
+    C () : i(1) {}
+    int f() {    
+      struct D {
+        int i;
+       D () : i(2) {}
+        int g() { return i; }
+      } d;
+
+      return d.g();
+    }
+  } c;
+
+  return c.f();
+}
+
+
+int main()
+{
+  if (f(0) != 2)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/overload9.C b/gcc/testsuite/g++.old-deja/g++.other/overload9.C
new file mode 100644 (file)
index 0000000..521f4bd
--- /dev/null
@@ -0,0 +1,31 @@
+struct T { ~T() {}; };
+
+int g ()
+{
+ foo:
+  T t;
+  int f(int);
+ bar:
+  T t2;
+  int f(double);
+  return f(3);
+}
+
+
+int f(int)
+{
+  return 0;
+}
+
+
+int f(double)
+{
+  return 1;
+}
+
+
+int main()
+{
+  return g();
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/copy1.C b/gcc/testsuite/g++.old-deja/g++.pt/copy1.C
new file mode 100644 (file)
index 0000000..7981530
--- /dev/null
@@ -0,0 +1,29 @@
+int i = 0;
+
+template <class T>
+class F 
+{
+public:
+  F() {}
+  
+  template <class T2> F(F<T2>) 
+    {
+      i = 1;
+    }      
+};
+
+
+F<int>
+foo()
+{
+  F<int> f1;
+  F<int> f2(f1);
+  return f1;
+}
+
+int
+main()
+{
+  return i;
+}
+
index 8ba2c739d30e606806cf30312b805403a3222d93..56eb80a5056da2a29a947e3d840f3bcc458d8138 100644 (file)
@@ -1,5 +1,5 @@
 // Build don't link:
-// excess errors test - XFAIL *-*-*
+// excess errors test 
 
 // This testcase won't fail if class ::foo is forward-declared in the
 // global namespace, nor if class bar is not a template class.
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/union1.C b/gcc/testsuite/g++.old-deja/g++.pt/union1.C
new file mode 100644 (file)
index 0000000..a1da446
--- /dev/null
@@ -0,0 +1,18 @@
+// Build don't link:
+
+union Un {int i;};
+
+template<class T1, class T2> struct St1 {};
+template<class T> struct St1<Un,T> {};
+
+template<class T> struct St2 {};
+template<> struct St2<Un> {};
+
+template<class T1, class T2> struct St3 {};
+template<> struct St3<Un,int> {};
+
+void f() {
+  St1<int,int> s1;
+  St2<int>     s2;
+  St3<int,int> s3;
+}