OSDN Git Service

Support for friend templates.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Feb 1998 03:17:44 +0000 (03:17 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 23 Feb 1998 03:17:44 +0000 (03:17 +0000)
* typeck.c (build_x_function_call): Handle static member function
templates like non-templates.  Handle friend templates like normal
function templates.
* pt.c (tsubst, *_PARM): Don't use orig_level.
(get_bindings): Don't call add_to_template_args.
(instantiate_template): Likewise.
(tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate.
* ptree.c (print_lang_type): Print index/level for template parms.
* Make-lang.in (cc1plus): Note that cc1plus depends on
cp/cp-tree.h and cp/cp-tree.def.
* cp-tree.def (TEMPLATE_CONST_PARM): Remove.
(TEMPLATE_PARM_INDEX): New tree code, used to indicate a
position in a template parameter list.
* cp-tree.h (template_parm_index): New structure, used as the tree
structure for a TEMPLATE_PARM_INDEX.
(TEMPLATE_PARM_IDX): New macro.
(TEMPLATE_PARM_LEVEL): Likewise.
(TEMPLATE_PARM_DESCENDANTS): Likewise.
(TEMPLATE_PARM_ORIG_LEVEL): Likewise.
(TEMPLATE_PARM_DECL): Likewise.
(TEMPLATE_TYPE_PARM_INDEX): Likewise.
(TEMPLATE_TYPE_ORIG_LEVEL): Likewise.
(TEMPLATE_TYPE_DECL): Likewise.
(TEMPLATE_CONST_IDX): Remove.
(TEMPLATE_CONST_LEVEL): Likewise.
(TEMPLATE_CONST_SET_INFO): Likewise.
(TEMPLATE_TYPE_SET_INFO): Likewise.
(TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX
node.
(TEMPLATE_TYPE_LEVEL): Likewise.
* decl.c (decls_match): Call comp_template_parms, rather than
expanding it inline.
(duplicate_decls): If two template declarations are being merged,
then their TEMPLATE_INFOs should be merged as well.
(grokfndecl): Save template-id information when declaring a friend
with explicit template arguments.  Pass arguments to
check_explicit_specialization via correct convention; at some
point check_explicit_specialization changed, but these call-sites
did not.
(grokdeclarator): Tidy up slightly.
* decl2.c (check_classfn): Tidy up slightly.  Don't assume that
two template functions with the same DECL_ASSEMBLER_NAME the same,
since the names are not yet mangled.
* error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of
TEMPLATE_CONST_PARM.
(dump_expr): Likewise.  Use the TEMPLATE_PARM_DECL to get at the
decl for a non-type parameter, rather than printing `<tparm ...>'.
* friend.c (is_friend): Handle TEMPLATE_DECL friends.
(do_friend): Deal with template friends.
* lex.c (do_pending_inlines): Call
maybe_begin_member_template_processing, rather than
conditionally calling begin_member_template_processing.
(process_next_inline): Likewise.  Call
maybe_end_member_template_processing, rather than
conditionally calling end_member_template_processing.
(do_pending_defargs): Likewise.
(do_identifier): Use TEMPLATE_PARM_INDEX instead of
TEMPLATE_CONST_PARM.
* method.c (build_mangled_template_parm_index): New function.
(build_overload_value): Use it.
(build_overload_name): Likewise.
* pt.c (finish_member_template_decl): Allow friend declarations.
(template_class_depth): New function.
(is_member_template): Rename, and modify, to become...
(is_member_or_friend_template): New function.
(end_member_template_processing): Rename, and modify, to become...
(maybe_end_member_template_processing).
(build_template_parm_index): New function.
(reduce_template_parm_level): New function.
(process_template_parm): Modify to use build_template_parm_index.
(current_template_args): Change name to current_template_parms.
(push_template_decl): Deal with friend templates.
(uses_template_parms): Use TEMPLATE_PARM_INDEX instead of
TEMPLATE_CONST_PARM.
(tsubst_friend_function): New function.
(instantiate_class_template): Generate the DECL_FRIENDLIST
for a new instantiation by using tsubst_friend_function rather
than just tsubst.
(tsubst): Don't tsubst into a type which is a TEMPLATE_DECL.
Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the
appropriate new macros.  Use reduce_template_parm_level to
generate lower-level template parameters.  Handle tsubst'ing into
TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS.  Don't forget
to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created
templates.  Similarly for the template parameters for a new
template.
(tsubst_copy): Tidy up slightly.  Use TEMPLATE_PARM_INDEX instead
of TEMPLATE_CONST_PARM.  Handle TYPE_DECLs by tsubsting into them.
(unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.
(get_bindings): Call add_to_template_args if necessary.
(instantiate_decl): Handle instantiations of friend templates.
* search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a
TEMPLATE_TYPE_PARM as a list of fields; it's not!
* spew.c (yylex): Do a little manual constant propogation to
clarify the code.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@18198 138bc75d-0d04-0410-961f-82ee72b054a4

17 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/friend.c
gcc/cp/gxxint.texi
gcc/cp/lex.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/ptree.c
gcc/cp/search.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c

index 5c90268..beb54a2 100644 (file)
@@ -1,3 +1,105 @@
+Mon Feb 23 03:04:14 1998  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * typeck.c (build_x_function_call): Handle static member function
+       templates like non-templates.  Handle friend templates like normal
+       function templates.
+       * pt.c (tsubst, *_PARM): Don't use orig_level.
+       (get_bindings): Don't call add_to_template_args.
+       (instantiate_template): Likewise.
+       (tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate.
+       * ptree.c (print_lang_type): Print index/level for template parms.
+
+Mon Feb 23 02:52:29 1998  Mark Mitchell  <mmitchell@usa.net>
+
+       * Make-lang.in (cc1plus): Note that cc1plus depends on
+       cp/cp-tree.h and cp/cp-tree.def.
+       
+       * cp-tree.def (TEMPLATE_CONST_PARM): Remove.
+       (TEMPLATE_PARM_INDEX): New tree code, used to indicate a
+       position in a template parameter list.
+       * cp-tree.h (template_parm_index): New structure, used as the tree
+       structure for a TEMPLATE_PARM_INDEX.
+       (TEMPLATE_PARM_IDX): New macro.
+       (TEMPLATE_PARM_LEVEL): Likewise.
+       (TEMPLATE_PARM_DESCENDANTS): Likewise.
+       (TEMPLATE_PARM_ORIG_LEVEL): Likewise.
+       (TEMPLATE_PARM_DECL): Likewise.
+       (TEMPLATE_TYPE_PARM_INDEX): Likewise.
+       (TEMPLATE_TYPE_ORIG_LEVEL): Likewise.
+       (TEMPLATE_TYPE_DECL): Likewise.
+       (TEMPLATE_CONST_IDX): Remove.
+       (TEMPLATE_CONST_LEVEL): Likewise.
+       (TEMPLATE_CONST_SET_INFO): Likewise.
+       (TEMPLATE_TYPE_SET_INFO): Likewise.
+       (TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX
+       node.
+       (TEMPLATE_TYPE_LEVEL): Likewise.
+       * decl.c (decls_match): Call comp_template_parms, rather than
+       expanding it inline.
+       (duplicate_decls): If two template declarations are being merged,
+       then their TEMPLATE_INFOs should be merged as well.
+       (grokfndecl): Save template-id information when declaring a friend
+       with explicit template arguments.  Pass arguments to
+       check_explicit_specialization via correct convention; at some
+       point check_explicit_specialization changed, but these call-sites
+       did not.
+       (grokdeclarator): Tidy up slightly.
+       * decl2.c (check_classfn): Tidy up slightly.  Don't assume that
+       two template functions with the same DECL_ASSEMBLER_NAME the same,
+       since the names are not yet mangled.
+       * error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of
+       TEMPLATE_CONST_PARM. 
+       (dump_expr): Likewise.  Use the TEMPLATE_PARM_DECL to get at the
+       decl for a non-type parameter, rather than printing `<tparm ...>'.
+       * friend.c (is_friend): Handle TEMPLATE_DECL friends.
+       (do_friend): Deal with template friends.
+       * lex.c (do_pending_inlines): Call
+       maybe_begin_member_template_processing, rather than
+       conditionally calling begin_member_template_processing.
+       (process_next_inline): Likewise.  Call
+       maybe_end_member_template_processing, rather than
+       conditionally calling end_member_template_processing.
+       (do_pending_defargs): Likewise.
+       (do_identifier): Use TEMPLATE_PARM_INDEX instead of
+       TEMPLATE_CONST_PARM.  
+       * method.c (build_mangled_template_parm_index): New function.
+       (build_overload_value): Use it.
+       (build_overload_name): Likewise.
+       * pt.c (finish_member_template_decl): Allow friend declarations.
+       (template_class_depth): New function.
+       (is_member_template): Rename, and modify, to become...
+       (is_member_or_friend_template): New function.
+       (end_member_template_processing): Rename, and modify, to become...
+       (maybe_end_member_template_processing).
+       (build_template_parm_index): New function.
+       (reduce_template_parm_level): New function.
+       (process_template_parm): Modify to use build_template_parm_index.
+       (current_template_args): Change name to current_template_parms.
+       (push_template_decl): Deal with friend templates.
+       (uses_template_parms): Use TEMPLATE_PARM_INDEX instead of
+       TEMPLATE_CONST_PARM.
+       (tsubst_friend_function): New function.
+       (instantiate_class_template): Generate the DECL_FRIENDLIST
+       for a new instantiation by using tsubst_friend_function rather
+       than just tsubst.
+       (tsubst): Don't tsubst into a type which is a TEMPLATE_DECL.
+       Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the
+       appropriate new macros.  Use reduce_template_parm_level to
+       generate lower-level template parameters.  Handle tsubst'ing into
+       TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS.  Don't forget
+       to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created
+       templates.  Similarly for the template parameters for a new
+       template.
+       (tsubst_copy): Tidy up slightly.  Use TEMPLATE_PARM_INDEX instead
+       of TEMPLATE_CONST_PARM.  Handle TYPE_DECLs by tsubsting into them.
+       (unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.  
+       (get_bindings): Call add_to_template_args if necessary.
+       (instantiate_decl): Handle instantiations of friend templates.
+       * search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a
+       TEMPLATE_TYPE_PARM as a list of fields; it's not!
+       * spew.c (yylex): Do a little manual constant propogation to
+       clarify the code.
+       
 Sun Feb 22 19:53:29 1998  Jeffrey A Law  (law@cygnus.com)
 
        * error.c: Include sys/types.h.
index a9e4e1c..6ed1678 100644 (file)
@@ -124,7 +124,8 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
  $(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
  $(srcdir)/cp/repo.c
 
-cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
+cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
+       $(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
        cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
 #\f
 # Build hooks:
index ab126fa..74d6441 100644 (file)
@@ -87,23 +87,60 @@ DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3)
  */
 DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0)
 
+/* Index into a template parameter list.  The TEMPLATE_PARM_IDX gives
+   the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL
+   gives the level (from 1) of the parameter.
+
+   Here's an example:
+   
+   template <class T> // Index 0, Level 1.
+   struct S
+   {
+      template <class U, // Index 0, Level 2.
+                class V> // Index 1, Level 2.
+      void f();
+   };  
+
+   The DESCENDANTS will be a chain of TEMPLATE_PARM_INDEXs descended
+   from this one.  The first descendant will have the same IDX, but
+   its LEVEL will be one less.  The TREE_CHAIN field is used to chain
+   together the descendants.  The TEMPLATE_PARM_DECL is the
+   declaration of this parameter, either a TYPE_DECL or CONST_DECL.
+   The TEMPLATE_PARM_ORIG_LEVEL is the LEVEL of the most distant
+   parent, i.e., the LEVEL that the parameter originally had when it
+   was declared.  For example, if we instantiate S<int>, we will have:
+
+   struct S<int>
+   {
+     template <class U, // Index 0, Level 1, Orig Level 2
+               class V> // Index 1, Level 1, Orig Level 2
+     void f();
+   };
+  
+   The LEVEL is the level of the parameter when we are worrying about
+   the types of things; the ORIG_LEVEL is the level when we are
+   worrying about instantiating things.  */
+DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", 'c', 
+            /* The addition of (sizeof(char*) - 1) in the next
+               expression is to ensure against the case where
+               sizeof(char*) does not evenly divide
+               sizeof(HOST_WIDE_INT).  */
+            2 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1)
+                 / sizeof (char*)))
+
 /* Index into a template parameter list.  This parameter must be a type.
-   Use TYPE_FIELDS to find parmlist and index.  */
+   The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX.  */
 DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
 
 /* Index into a template parameter list.  This parameter must be a type.
    If it is used in signature of a template, TEMPLATE_INFO is NULL_TREE.
    Otherwise it is used to declare a type like TT<int>.
-   Use TYPE_FIELDS to find parmlist and index.  */
+   The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX.  */
 DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
 
 /* A type designated by 'typename T::t'. */
 DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
 
-/* Index into a template parameter list.  This parameter must not be a
-   type.  */
-DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", 'c', 3)
-
 /* A thunk is a stub function.
 
    Thunks are used to implement multiple inheritance:
@@ -179,3 +216,9 @@ DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
 DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
 
 DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
+
+/*
+Local variables:
+mode:c
+End:
+*/
index a254db8..de63849 100644 (file)
@@ -47,6 +47,17 @@ typedef struct
   int new_type_flag;
 } flagged_type_tree;
 
+typedef struct 
+{
+  char common[sizeof (struct tree_common)];
+  struct rtx_def *rtl; /* Unused, but required to match up with what
+                          the middle-end expects.  */
+  HOST_WIDE_INT index;
+  HOST_WIDE_INT level;
+  HOST_WIDE_INT orig_level;
+  tree decl;
+} template_parm_index;
+
 /* To identify to the debug emitters if it should pay attention to the
    flag `-Wtemplate-debugging'.  */
 #define HAVE_TEMPLATES 1
@@ -1340,6 +1351,18 @@ extern int flag_new_for_scope;
 #define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous)
 
 /* C++: all of these are overloaded!  These apply only to TYPE_DECLs.  */
+
+/* The format of each node in the DECL_FRIENDLIST is as follows:
+
+   The TREE_PURPOSE will be the name of a function, i.e., an
+   IDENTIFIER_NODE.  The TREE_VALUE will be itself a TREE_LIST, the
+   list of functions with that name which are friends.  The
+   TREE_PURPOSE of each node in this sublist will be error_mark_node,
+   if the function was declared a friend individually, in which case
+   the TREE_VALUE will be the function_decl.  If, however, all
+   functions with a given name in a class were declared to be friends,
+   the TREE_PUROSE will be the class type, and the TREE_VALUE will be
+   NULL_TREE.  */
 #define DECL_FRIENDLIST(NODE)          (DECL_INITIAL (NODE))
 
 /* The DECL_ACCESS is used to record under which context
@@ -1352,6 +1375,17 @@ extern int flag_new_for_scope;
 #define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
 
 /* Accessor macros for C++ template decl nodes.  */
+
+/* The DECL_TEMPLATE_PARMS are a list.  The TREE_PURPOSE of each node
+   indicates the level of the template parameters, with 1 being the
+   outermost set of template parameters.  The TREE_VALUE is a vector,
+   whose elements are the template parameters at each level.  Each
+   element in the vector is a TREE_LIST, whose TREE_VALUE is a
+   PARM_DECL (if the parameter is a non-type parameter), or a
+   TYPE_DECL (if the parameter is a type parameter).  The TREE_PURPOSE
+   is the default value, if any.  The TEMPLATE_PARM_INDEX for the
+   parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as
+   the TREE_TYPE (for a TYPE_DECL).  */
 #define DECL_TEMPLATE_PARMS(NODE)       DECL_ARGUMENTS(NODE)
 #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
    INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
@@ -1374,6 +1408,12 @@ extern int flag_new_for_scope;
   (TREE_CODE (NODE) == TEMPLATE_DECL \
    && TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
 
+/* A `primary' template is one which depends on no tbemplate parameters
+   except those specified in its parameter list.  So, a template
+   member of a non-template class is primary, and every global
+   function template is primary, but a member function of a template
+   class is not primary, neither is a member template of a template
+   class.  */
 #define PRIMARY_TEMPLATE_P(NODE) \
   (TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))
 
@@ -1934,24 +1974,27 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
 
 #define WANT_ARITH     (WANT_INT | WANT_FLOAT)
 
-/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
-   purpose = friend name (IDENTIFIER_NODE);
-   value = TREE_LIST of FUNCTION_DECLS;
-   chain, type = EMPTY;  */
 #define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
 #define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
 
+/* These macros are used to access a TEMPLATE_PARM_INDEX.  */
+#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
+#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level)
+#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
+#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (((template_parm_index*) NODE)->orig_level)
+#define TEMPLATE_PARM_DECL(NODE) (((template_parm_index*) NODE)->decl)
+
 /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM 
    and TEMPLATE_TEMPLATE_PARM nodes.  */
-#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE))
-#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE))
-#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \
-  (TYPE_FIELDS (NODE) = build_int_2 (I, L))
-/* These macros are for accessing the fields of TEMPLATE_CONST_PARM nodes.  */
-#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE))
-#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE))
-#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \
-  (TEMPLATE_CONST_IDX (NODE) = I, TEMPLATE_CONST_LEVEL (NODE) = L)
+#define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE))
+#define TEMPLATE_TYPE_IDX(NODE) \
+  (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_LEVEL(NODE) \
+  (TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \
+  (TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
+#define TEMPLATE_TYPE_DECL(NODE) \
+  (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
 
 /* in lex.c  */
 /* Indexed by TREE_CODE, these tables give C-looking names to
@@ -2336,8 +2379,8 @@ extern tree tsubst                                PROTO ((tree, tree, int, tree));
 extern tree tsubst_expr                                PROTO ((tree, tree, int, tree));
 extern tree tsubst_copy                                PROTO ((tree, tree, int, tree));
 extern tree tsubst_chain                       PROTO((tree, tree));
-extern void begin_member_template_processing    PROTO((tree));
-extern void end_member_template_processing      PROTO((void));
+extern void maybe_begin_member_template_processing PROTO((tree));
+extern void maybe_end_member_template_processing PROTO((tree));
 extern tree finish_member_template_decl         PROTO((tree, tree));
 extern void begin_template_parm_list           PROTO((void));
 extern void begin_specialization                PROTO((void));
@@ -2382,6 +2425,7 @@ extern int more_specialized_class         PROTO((tree, tree));
 extern void do_pushlevel                       PROTO((void));
 extern int is_member_template                   PROTO((tree));
 extern int comp_template_parms                  PROTO((tree, tree));
+extern int template_class_depth                 PROTO((tree));
 extern int processing_specialization;
 extern int processing_explicit_instantiation;
 
index ce35770..d05c493 100644 (file)
@@ -2311,47 +2311,15 @@ decls_match (newdecl, olddecl)
   else if (TREE_CODE (newdecl) == TEMPLATE_DECL
           && TREE_CODE (olddecl) == TEMPLATE_DECL)
     {
-       tree newargs = DECL_TEMPLATE_PARMS (newdecl);
-       tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
-       int i;
-
-       /* Run through all the levels of template parameters, checking
-          that they match.  */
-       while (newargs && oldargs) 
-         {
-           int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
-
-           if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
-             return 0;
-           
-           for (i = 0; i < len; i++)
-             {
-               tree newarg = 
-                 TREE_VALUE (TREE_VEC_ELT 
-                             (INNERMOST_TEMPLATE_PARMS (newargs), i));
-               tree oldarg = 
-                 TREE_VALUE (TREE_VEC_ELT 
-                             (INNERMOST_TEMPLATE_PARMS (oldargs), i));
-               if (TREE_CODE (newarg) != TREE_CODE (oldarg))
-                 return 0;
-               else if (TREE_CODE (newarg) == TYPE_DECL)
-                 /* continue */;
-               else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
-                 return 0;
-             }
-           newargs = TREE_CHAIN (newargs);
-           oldargs = TREE_CHAIN (oldargs);
-         }
-
-       if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
-         /* One declaration has more levels that the other. */
-         return 0;
-
-       if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
-         types_match = 1;
-       else
-         types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
-                                    DECL_TEMPLATE_RESULT (newdecl));
+      if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
+                               DECL_TEMPLATE_PARMS (olddecl)))
+       return 0;
+      
+      if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
+       types_match = 1;
+      else
+       types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
+                                  DECL_TEMPLATE_RESULT (newdecl));
     }
   else
     {
@@ -2760,6 +2728,7 @@ duplicate_decls (newdecl, olddecl)
            cp_error ("invalid redeclaration of %D", newdecl);
          TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
          DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
+         DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
        }
       return 1;
     }
@@ -4504,7 +4473,10 @@ make_implicit_typename (context, t)
 
    If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
    If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
-   Otherwise we prefer non-TYPE_DECLs.  */
+   Otherwise we prefer non-TYPE_DECLs.  
+
+   If NONCLASS is non-zero, we don't look for the NAME in class scope,
+   using IDENTIFIER_CLASS_VALUE.  */
 
 static tree
 lookup_name_real (name, prefer_type, nonclass)
@@ -7461,8 +7433,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
   if (friendp && 
       TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
-    /* A friend declaration of the form friend void f<>().  */
-    SET_DECL_IMPLICIT_INSTANTIATION (decl);
+    {
+      /* A friend declaration of the form friend void f<>().  Record
+        the information in the TEMPLATE_ID_EXPR.  */
+      SET_DECL_IMPLICIT_INSTANTIATION (decl);
+      DECL_TEMPLATE_INFO (decl) 
+       = perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
+                         TREE_OPERAND (orig_declarator, 1),
+                         NULL_TREE);
+    }
 
   /* Caller will do the rest of this.  */
   if (check < 0)
@@ -7485,8 +7464,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
       decl = check_explicit_specialization (orig_declarator, decl,
                                            template_count, 
-                                           funcdef_flag ? 2 : 
-                                           (friendp ? 3 : 0));
+                                           2 * (funcdef_flag != 0) + 
+                                           4 * (friendp != 0));
 
       if (check)
        {
@@ -7532,8 +7511,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
 
       decl = check_explicit_specialization (orig_declarator, decl,
                                            template_count, 
-                                           funcdef_flag ? 2 : 
-                                           (friendp ? 3 : 0));
+                                           2 * (funcdef_flag != 0) + 
+                                           4 * (friendp != 0));
 
       if (ctype != NULL_TREE && check)
        {
@@ -7952,10 +7931,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
 
                if (TREE_CODE (fns) == IDENTIFIER_NODE)
                  dname = fns;
-               else if (really_overloaded_fn (fns))
+               else if (is_overloaded_fn (fns))
                  dname = DECL_NAME (get_first_fn (fns));
                else
-                 dname = DECL_NAME (fns);
+                 my_friendly_abort (0);
              }
          /* fall through */
 
index c598c1a..c847a27 100644 (file)
@@ -1431,19 +1431,22 @@ check_classfn (ctype, function)
          if (fn_name == DECL_NAME (*methods))
            {
            got_it:
-             fndecl = *methods;
-             while (fndecl)
+             for (fndecl = *methods; fndecl != NULL_TREE;
+                  fndecl = DECL_CHAIN (fndecl))
                {
-                 if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
+                 /* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
+                    not mangled, so the check below does not work
+                    correctly in that case.  */
+                 if (TREE_CODE (function) != TEMPLATE_DECL
+                     && TREE_CODE (fndecl) != TEMPLATE_DECL
+                     && (DECL_ASSEMBLER_NAME (function) 
+                         == DECL_ASSEMBLER_NAME (fndecl)))
                    return fndecl;
-#if 0
-                 /* This doesn't work for static member functions that are
-                     pretending to be methods.  */
-                 /* We have to do more extensive argument checking here, as
-                    the name may have been changed by asm("new_name").  */
-                 if (decls_match (function, fndecl))
-                   return fndecl;
-#else
+
+                 /* We cannot simply call decls_match because this
+                    doesn't work for static member functions that are 
+                     pretending to be methods, and because the name
+                    may have been changed by asm("new_name").  */ 
                  if (DECL_NAME (function) == DECL_NAME (fndecl))
                    {
                      tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
@@ -1471,8 +1474,6 @@ check_classfn (ctype, function)
                        templates = 
                          scratch_tree_cons (NULL_TREE, fndecl, templates);
                    }
-#endif
-                 fndecl = DECL_CHAIN (fndecl);
                }
              break;            /* loser */
            }
index e236153..0451781 100644 (file)
@@ -856,7 +856,7 @@ dump_decl (t, v)
     case CONST_DECL:
       if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
          || (DECL_INITIAL (t) &&
-             TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM))
+             TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
        goto general;
       else if (DECL_NAME (t))
        dump_decl (DECL_NAME (t), v);
@@ -1527,33 +1527,12 @@ dump_expr (t, nop)
        break;
       }
 
-    case TEMPLATE_CONST_PARM:
+    case TEMPLATE_PARM_INDEX:
       {
        int l = current_template_parms ? 
          list_length (current_template_parms) : 0;
 
-       if (l >= TEMPLATE_CONST_LEVEL (t))
-         {
-           int i;
-           tree parms = current_template_parms;
-           tree r;
-           
-           for (i = 0; i < l - TEMPLATE_CONST_LEVEL (t); ++i)
-             {
-               parms = TREE_CHAIN (parms);
-               my_friendly_assert (parms != NULL_TREE, 0);
-             }
-           
-           r = TREE_VEC_ELT (TREE_VALUE (parms),
-                             TEMPLATE_CONST_IDX (t));
-           dump_decl (TREE_VALUE (r), -1);
-         }
-       else
-         {
-           OB_PUTS ("<tparm ");
-           OB_PUTI (TEMPLATE_CONST_IDX (t));
-           OB_PUTS (">");
-         }
+       dump_decl (TEMPLATE_PARM_DECL (t), -1);
       }
       break;
 
index 028706a..f28e049 100644 (file)
@@ -33,22 +33,7 @@ Boston, MA 02111-1307, USA.  */
 static void add_friend PROTO((tree, tree));
 static void add_friends PROTO((tree, tree, tree));
 
-/* Friend data structures:
-
-   Lists of friend functions come from TYPE_DECL nodes.  Since all
-   aggregate types are automatically typedef'd, these nodes are guaranteed
-   to exist.
-
-   The TREE_PURPOSE of a friend list is the name of the friend,
-   and its TREE_VALUE is another list.
-
-   For each element of that list, either the TREE_VALUE or the TREE_PURPOSE
-   will be filled in, but not both.  The TREE_VALUE of that list is an
-   individual function which is a friend.  The TREE_PURPOSE of that list
-   indicates a type in which all functions by that name are friends.
-
-   Lists of friend classes come from _TYPE nodes.  Love that consistency
-   thang.  */
+/* Friend data structures are described in cp-tree.h.  */
 
 int
 is_friend (type, supplicant)
@@ -83,6 +68,31 @@ is_friend (type, supplicant)
                {
                  if (ctype == TREE_PURPOSE (friends))
                    return 1;
+
+                 if (TREE_VALUE (friends) == NULL_TREE)
+                   continue;
+
+                 if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
+                   {
+                     tree t;
+
+                     /* Perhaps this function is a specialization of
+                        a friend template.  */
+                     for (t = supplicant;
+                          t != NULL_TREE;
+                          t = DECL_TEMPLATE_INFO (t) ? 
+                            DECL_TI_TEMPLATE (t) : NULL_TREE)
+                       /* FIXME: The use of comptypes here, and below, is
+                          bogus, since two specializations of a
+                          template parameter with non-type parameters
+                          may have the same type, but be different.  */
+                       if (comptypes (TREE_TYPE (t),
+                                      TREE_TYPE (TREE_VALUE (friends)), 1))
+                         return 1;
+
+                     continue;
+                   }
+
                  if (comptypes (TREE_TYPE (supplicant),
                                 TREE_TYPE (TREE_VALUE (friends)), 1))
                    return 1;
@@ -302,9 +312,15 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
      tree quals;
      int funcdef_flag;
 {
+  int is_friend_template = 0;
+
   /* Every decl that gets here is a friend of something.  */
   DECL_FRIEND_P (decl) = 1;
 
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    is_friend_template = processing_template_decl >
+      template_class_depth (current_class_type);
+
   if (ctype)
     {
       tree cname = TYPE_NAME (ctype);
@@ -319,18 +335,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
 
          /* This will set up DECL_ARGUMENTS for us.  */
          grokclassfn (ctype, cname, decl, flags, quals);
-         if (TYPE_SIZE (ctype) != 0)
+
+         if (is_friend_template)
+           decl = DECL_TI_TEMPLATE (push_template_decl (decl));
+
+         if (TYPE_SIZE (ctype) != 0 
+             && template_class_depth (ctype) == 0)
            decl = check_classfn (ctype, decl);
 
          if (TREE_TYPE (decl) != error_mark_node)
            {
-             if (TYPE_SIZE (ctype))
+             if (TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
                add_friend (current_class_type, decl);
              else
-               {
-                 cp_error ("member `%D' declared as friend before type `%T' defined",
-                           decl, ctype);
-               }
+               cp_error ("member `%D' declared as friend before type `%T' defined",
+                         decl, ctype);
            }
        }
       else
@@ -386,10 +405,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
        {
          /* We can call pushdecl here, because the TREE_CHAIN of this
             FUNCTION_DECL is not needed for other purposes.  Don't do this
-            for a template instantiation. */
-         decl = pushdecl (decl);
+            for a template instantiation.  */
+         if (!is_friend_template)
+           {  
+             /* However, we don't call pushdecl() for a friend
+                function of a template class, since in general,
+                such a declaration depends on template
+                parameters.  Instead, we call pushdecl when the
+                class is instantiated.  */
+             if (template_class_depth (current_class_type) == 0)
+               decl = pushdecl (decl);
+           }
+         else 
+           decl = push_template_decl (decl); 
 
-         if (! funcdef_flag && ! flag_guiding_decls
+         if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
              && current_template_parms && uses_template_parms (decl))
            {
              static int explained;
@@ -405,8 +435,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
        }
 
       make_decl_rtl (decl, NULL_PTR, 1);
-      add_friend (current_class_type, decl);
-
+      add_friend (current_class_type, 
+                 is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
       DECL_FRIEND_P (decl) = 1;
     }
   else
index 5f73465..cf9aaa9 100644 (file)
@@ -1684,14 +1684,14 @@ as a @samp{Z} followed by the encoding of the type.
 
 A function template specialization (either an instantiation or an
 explicit specialization) is encoded by an @samp{H} followed by the
-encoding of the template parameters, as described above, followed by 
-an @samp{_}, the encoding of the argument types template function (not the
-specialization), another @samp{_}, and the return type.  (Like the
-argument types, the return type is the return type of the function
+encoding of the template parameters, as described above, followed by an
+@samp{_}, the encoding of the argument types to the template function
+(not the specialization), another @samp{_}, and the return type.  (Like
+the argument types, the return type is the return type of the function
 template, not the specialization.)  Template parameters in the argument
 and return types are encoded by an @samp{X} for type parameters, or a
-@samp{Y} for constant parameters, and an index indicating their position
-in the template parameter list declaration.
+@samp{Y} for constant parameters, an index indicating their position
+in the template parameter list declaration, and their template depth.
 
 @subsection Arrays
 
index 550ca34..8d6d622 100644 (file)
@@ -1213,8 +1213,7 @@ do_pending_inlines ()
   context = hack_decl_function_context (t->fndecl);
   if (context)
     push_cp_function_context (context);
-  if (is_member_template (t->fndecl))
-    begin_member_template_processing (t->fndecl);
+  maybe_begin_member_template_processing (t->fndecl);
   if (t->len > 0)
     {
       feed_input (t->buf, t->len);
@@ -1252,8 +1251,7 @@ process_next_inline (t)
   tree context;
   struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
   context = hack_decl_function_context (i->fndecl);  
-  if (is_member_template (i->fndecl))
-    end_member_template_processing ();
+  maybe_end_member_template_processing (i->fndecl);
   if (context)
     pop_cp_function_context (context);
   i = i->next;
@@ -1276,8 +1274,7 @@ process_next_inline (t)
       context = hack_decl_function_context (i->fndecl);
       if (context)
        push_cp_function_context (context);
-      if (is_member_template (i->fndecl))
-       begin_member_template_processing (i->fndecl);
+      maybe_begin_member_template_processing (i->fndecl);
       feed_input (i->buf, i->len);
       lineno = i->lineno;
       input_filename = i->filename;
@@ -1891,8 +1888,7 @@ do_pending_defargs ()
        {
          push_nested_class (TREE_PURPOSE (defarg_fns), 1);
          pushlevel (0);
-         if (is_member_template (defarg_fn))
-           begin_member_template_processing (defarg_fn);
+         maybe_begin_member_template_processing (defarg_fn);
 
          if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
            {
@@ -1920,8 +1916,7 @@ do_pending_defargs ()
            return;
          }
 
-      if (is_member_template (defarg_fn))
-       end_member_template_processing ();
+      maybe_end_member_template_processing (defarg_fn);
       poplevel (0, 0, 0);
       pop_nested_class (1);
     }
@@ -2946,7 +2941,7 @@ do_identifier (token, parsing)
        }
       if (! processing_template_decl
          || (DECL_INITIAL (id)
-             && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
+             && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
        id = DECL_INITIAL (id);
     }
   else
index a3ff1ac..8be513b 100644 (file)
@@ -602,6 +602,24 @@ build_overload_int (value, in_template)
   icat (TREE_INT_CST_LOW (value));
 }
 
+
+/* Output S followed by a representation of the TEMPLATE_PARM_INDEX
+   supplied in INDEX.  */
+
+static void 
+build_mangled_template_parm_index (s, index)
+     char* s;
+     tree index;
+{
+  OB_PUTCP (s);
+  build_underscore_int (TEMPLATE_PARM_IDX (index));
+  /* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a
+     representation of the function from the point of view of its
+     type.  */
+  build_underscore_int (TEMPLATE_PARM_LEVEL (index));
+}
+
+
 static void
 build_overload_value (type, value, in_template)
      tree type, value;
@@ -619,11 +637,9 @@ build_overload_value (type, value, in_template)
       numeric_output_need_bar = 0;
     }
 
-  if (TREE_CODE (value) == TEMPLATE_CONST_PARM)
+  if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
     {
-      OB_PUTC ('Y');
-      build_underscore_int (TEMPLATE_CONST_IDX (value));
-      build_underscore_int (TEMPLATE_CONST_LEVEL (value));
+      build_mangled_template_parm_index ("Y", value);
       return;
     }
 
@@ -761,13 +777,19 @@ build_overload_value (type, value, in_template)
          sorry ("template instantiation with pointer to method that is too complex");
          return;
        }
-      if (TREE_CODE (value) == INTEGER_CST
-         || TREE_CODE (value) == TEMPLATE_CONST_PARM)
+      if (TREE_CODE (value) == INTEGER_CST)
        {
          build_overload_int (value, in_template);
          numeric_output_need_bar = 1;
          return;
        }
+      else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
+       {
+         build_mangled_template_parm_index ("", value);
+         numeric_output_need_bar = 1;
+         return;
+       }
+
       value = TREE_OPERAND (value, 0);
       if (TREE_CODE (value) == VAR_DECL)
        {
@@ -1374,33 +1396,27 @@ process_overload_item (parmtype, extra_Gcode)
          declaration. */
       if (CLASSTYPE_TEMPLATE_INFO (parmtype))
         {
-          OB_PUTC ('t');
-          OB_PUTC ('z');
-          OB_PUTC ('X');
-          build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
-          build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
-
-          build_template_parm_names (
-            DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
-            CLASSTYPE_TI_ARGS (parmtype));
+         build_mangled_template_parm_index ("tzX",
+                                            TEMPLATE_TYPE_PARM_INDEX 
+                                            (parmtype));
+          build_template_parm_names
+            (DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
+            CLASSTYPE_TI_ARGS (parmtype));
         }
       else
         {
-          OB_PUTC ('Z');
-          OB_PUTC ('z');
-          OB_PUTC ('X');
-          build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
-          build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
-
-          build_template_template_parm_names (
-            DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
+         build_mangled_template_parm_index ("ZzX",
+                                            TEMPLATE_TYPE_PARM_INDEX 
+                                            (parmtype));
+          build_template_template_parm_names
+            (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
         }
       break;
 
     case TEMPLATE_TYPE_PARM:
-      OB_PUTC ('X');
-      build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
-      build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
+      build_mangled_template_parm_index ("X", 
+                                        TEMPLATE_TYPE_PARM_INDEX
+                                        (parmtype));
       break;
         
     case TYPENAME_TYPE:
index 6a65710..a50368a 100644 (file)
@@ -86,6 +86,7 @@ static int  type_unification_real PROTO((tree, tree *, tree, tree, int*,
 static void note_template_header PROTO((int));
 static tree maybe_fold_nontype_arg PROTO((tree));
 static tree convert_nontype_argument PROTO((tree, tree));
+static int is_member_or_friend_template PROTO((tree, int));
 
 /* Do any processing required when DECL (a member template declaration
    using TEMPLATE_PARAMETERS as its innermost parameter list) is
@@ -109,22 +110,51 @@ finish_member_template_decl (template_parameters, decl)
       return DECL_TI_TEMPLATE (decl);
     }
 
-  if (decl)
-    return decl;
+  return decl;
+}
 
-  cp_error ("invalid member template declaration");
-  return NULL_TREE;
+/* Returns the template nesting level of the indicated class TYPE.
+   
+   For example, in:
+     template <class T>
+     struct A
+     {
+       template <class U>
+       struct B {};
+     };
+
+   A<T>::B<U> has depth two, while A<T> has depth one.  Also,
+   both A<T>::B<int> and A<int>::B<U> have depth one.  */
+
+int 
+template_class_depth (type)
+     tree type;
+{
+  int depth = 0;
+
+  /* Note: this implementation will be broken when we have nested
+     template classes.  Presumably we will have to wrap this if
+     statement a loop.  */
+  if (CLASSTYPE_TEMPLATE_INFO (type)
+      && uses_template_parms (CLASSTYPE_TI_ARGS (type)))
+    ++depth;
+
+  return depth;
 }
 
-/* Restore the template parameter context. */
+/* Restore the template parameter context for a member template or
+   a friend template defined in a class definition.  */
 
 void 
-begin_member_template_processing (decl)
+maybe_begin_member_template_processing (decl)
      tree decl;
 {
   tree parms;
   int i;
 
+  if (!is_member_or_friend_template (decl, 1))
+    return;
+
   parms = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
 
   ++processing_template_decl;
@@ -163,8 +193,12 @@ begin_member_template_processing (decl)
 /* Undo the effects of begin_member_template_processing. */
 
 void 
-end_member_template_processing ()
+maybe_end_member_template_processing (decl)
+     tree decl;
 {
+  if (!is_member_or_friend_template (decl, 1))
+    return;
+
   if (! processing_template_decl)
     return;
 
@@ -173,8 +207,9 @@ end_member_template_processing ()
   poplevel (0, 0, 0);
 }
 
-/* Returns non-zero iff T is a member template function.  We must be
-   careful as in 
+/* Returns non-zero iff T is a member template function, or, if
+   ALLOW_FRIEND is non-zero, a friend template function.  We must be
+   careful as in
 
      template <class T> class C { void f(); }
 
@@ -187,67 +222,56 @@ end_member_template_processing ()
    then neither C<int>::f<char> nor C<T>::f<double> is considered
    to be a member template.  */
 
-int
-is_member_template (t)
+static int
+is_member_or_friend_template (t, allow_friend)
      tree t;
+     int allow_friend;
 {
-  int r = 0;
-
   if (TREE_CODE (t) != FUNCTION_DECL
       && !DECL_FUNCTION_TEMPLATE_P (t))
     /* Anything that isn't a function or a template function is
        certainly not a member template.  */
     return 0;
 
-  if ((DECL_FUNCTION_MEMBER_P (t) 
+  if (((DECL_FUNCTION_MEMBER_P (t) 
+       || (allow_friend && DECL_FRIEND_P (t)))
        && !DECL_TEMPLATE_SPECIALIZATION (t))
-      || (TREE_CODE (t) == TEMPLATE_DECL && 
-         DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))))
+      || (TREE_CODE (t) == TEMPLATE_DECL 
+         && (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t))
+             || (allow_friend
+                 && DECL_FUNCTION_TEMPLATE_P (t) 
+                 && DECL_FRIEND_P (DECL_TEMPLATE_RESULT (t))
+                 && DECL_CLASS_CONTEXT (t)))))
     {
-      tree tmpl = NULL_TREE;
+      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 && 
+         /* If there are more levels of template parameters than
+            there are template classes surrounding the declaration,
+            then we have a member template.  */
+         list_length (DECL_TEMPLATE_PARMS (tmpl)) > 
+         template_class_depth (DECL_CLASS_CONTEXT (t)))
+       return 1;
+    }
 
-      if (tmpl) 
-       {
-         tree parms = DECL_TEMPLATE_PARMS (tmpl);
-         int parm_levels = list_length (parms);
-         int template_class_levels = 0;
-         tree ctx = DECL_CLASS_CONTEXT (t);
-
-         /* NB - The code below does not yet handle template class
-            members, e.g. 
-            
-              template <class T> class C { template <class U> class D; }}
-
-            correctly.  In that case, the D should have level 2.  */
-
-         if (CLASSTYPE_TEMPLATE_INFO (ctx))
-           {
-             tree args = CLASSTYPE_TI_ARGS (ctx);
-             int i;
-             
-             if (args == NULL_TREE)
-               template_class_levels = 1;
-             else 
-               for (i = 0; i < TREE_VEC_LENGTH (args); ++i)
-                 if (uses_template_parms (TREE_VEC_ELT (args, i)))
-                   {
-                     template_class_levels++;
-                     break;
-                   }
-           }
+  return 0;
+}
 
-         if (parm_levels > template_class_levels)
-           r = 1;
-       }
-    }
+/* Returns non-zero iff T is a member template.  */
 
-  return r;
+int
+is_member_template (t)
+     tree t;
+{
+  return is_member_or_friend_template (t, 0);
 }
 
 /* Return a new template argument vector which contains all of ARGS,
@@ -595,10 +619,6 @@ determine_specialization (template_id, decl, targs_out,
    Returns DECL, or an equivalent declaration that should be used
    instead. 
    
-     0: The function is not an explicit specialization or instantiation.
-     1: The function is an explicit specialization.
-     2: The function is an explicit instantiation.
-
    FLAGS is a bitmask consisting of the following flags: 
 
    1: We are being called by finish_struct.  (We are unable to
@@ -1004,6 +1024,57 @@ int comp_template_parms (parms1, parms2)
 }
 
 
+/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
+   ORIG_LEVEL, DECL, and TYPE.  */
+
+static tree
+build_template_parm_index (index, level, orig_level, decl, type)
+     int index;
+     int level;
+     int orig_level;
+     tree decl;
+     tree type;
+{
+  tree t = make_node (TEMPLATE_PARM_INDEX);
+  TEMPLATE_PARM_IDX (t) = index;
+  TEMPLATE_PARM_LEVEL (t) = level;
+  TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
+  TEMPLATE_PARM_DECL (t) = decl;
+  TREE_TYPE (t) = type;
+
+  return t;
+}
+
+
+/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose
+   TEMPLATE_PARM_LEVEL has been decreased by one.  If such a
+   TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a
+   new one is created.  */
+
+static tree 
+reduce_template_parm_level (index, type)
+     tree index;
+     tree type;
+{
+  if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE
+      || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
+         != TEMPLATE_PARM_LEVEL (index) - 1))
+    {
+      tree decl 
+       = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)),
+                     DECL_NAME (TEMPLATE_PARM_DECL (index)),
+                     type);
+      tree t
+       = build_template_parm_index (TEMPLATE_PARM_IDX (index),
+                                    TEMPLATE_PARM_LEVEL (index) - 1,
+                                    TEMPLATE_PARM_ORIG_LEVEL (index),
+                                    decl, type);
+      TEMPLATE_PARM_DESCENDANTS (index) = t;
+    }
+
+  return TEMPLATE_PARM_DESCENDANTS (index);
+}
+
 /* Process information from new template parameter NEXT and append it to the
    LIST being built.  */
 
@@ -1015,6 +1086,7 @@ process_template_parm (list, next)
   tree decl = 0;
   tree defval;
   int is_type, idx;
+
   parm = next;
   my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259);
   defval = TREE_PURPOSE (parm);
@@ -1030,7 +1102,7 @@ process_template_parm (list, next)
       else if (TREE_CODE (p) == TEMPLATE_DECL)
        idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p)));
       else
-       idx = TEMPLATE_CONST_IDX (DECL_INITIAL (p));
+       idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p));
       ++idx;
     }
   else
@@ -1038,7 +1110,6 @@ process_template_parm (list, next)
 
   if (!is_type)
     {
-      tree tinfo = 0;
       my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260);
       /* is a const-param */
       parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
@@ -1059,18 +1130,16 @@ process_template_parm (list, next)
                   || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE))
        cp_pedwarn ("`%T' is not a valid type for a template constant parameter",
                    TREE_TYPE (parm));
-      tinfo = make_node (TEMPLATE_CONST_PARM);
-      my_friendly_assert (TREE_PERMANENT (tinfo), 260.5);
       if (TREE_PERMANENT (parm) == 0)
         {
          parm = copy_node (parm);
          TREE_PERMANENT (parm) = 1;
         }
-      TREE_TYPE (tinfo) = TREE_TYPE (parm);
       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
-      DECL_INITIAL (decl) = tinfo;
-      DECL_INITIAL (parm) = tinfo;
-      TEMPLATE_CONST_SET_INFO (tinfo, idx, processing_template_decl);
+      DECL_INITIAL (parm) = DECL_INITIAL (decl) 
+       = build_template_parm_index (idx, processing_template_decl,
+                                    processing_template_decl,
+                                    decl, TREE_TYPE (parm));
     }
   else
     {
@@ -1097,7 +1166,10 @@ process_template_parm (list, next)
       TYPE_NAME (t) = decl;
       TYPE_STUB_DECL (t) = decl;
       parm = decl;
-      TEMPLATE_TYPE_SET_INFO (t, idx, processing_template_decl);
+      TEMPLATE_TYPE_PARM_INDEX (t)
+       = build_template_parm_index (idx, processing_template_decl, 
+                                    processing_template_decl,
+                                    decl, TREE_TYPE (parm));
     }
   SET_DECL_ARTIFICIAL (decl);
   pushdecl (decl);
@@ -1212,30 +1284,48 @@ build_template_decl (decl, parms)
 
   
 /* Creates a TEMPLATE_DECL for the indicated DECL using the template
-   parameters given by current_template_args, or reuses a previously
-   existing one, if appropriate.  Returns the DECL, or an equivalent
-   one, if it is replaced via a call to duplicate_decls.  */
+   parameters given by current_template_args, or reuses a
+   previously existing one, if appropriate.  Returns the DECL, or an
+   equivalent one, if it is replaced via a call to duplicate_decls.  */
 
 tree
 push_template_decl (decl)
      tree decl;
 {
   tree tmpl;
-  tree args = NULL_TREE;
+  tree args;
   tree info;
-  tree ctx = DECL_CONTEXT (decl) ? DECL_CONTEXT (decl) : current_class_type;
-  int primary = 0;
-
-  /* Kludge! */
-  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl)
-      && DECL_CLASS_CONTEXT (decl))
-    ;
-  /* Note that this template is a "primary template" */
-  else if (! ctx 
-          || (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't' 
-              && ! CLASSTYPE_TEMPLATE_INFO (ctx))
-      /* || (processing_template_decl > CLASSTYPE_TEMPLATE_LEVEL (ctx)) */)
+  tree ctx;
+  int primary;
+  int is_friend = (TREE_CODE (decl) == FUNCTION_DECL
+                  && DECL_FRIEND_P (decl));
+
+  if (is_friend)
+    /* For a friend, we want the context of the friend function, not
+       the type of which it is a friend.  */
+    ctx = DECL_CONTEXT (decl);
+  else if (DECL_REAL_CONTEXT (decl))
+    /* In the case of a virtual function, we want the class in which
+       it is defined.  */
+    ctx = DECL_REAL_CONTEXT (decl);
+  else
+    /* Otherwise, if we're currently definining some class, the DECL
+       is assumed to be a member of the class.  */
+    ctx = current_class_type;
+
+  if ((! ctx
+       || (TREE_CODE_CLASS (TREE_CODE (ctx)) == 't'
+          && template_class_depth (ctx) == 0))
+      /* At this point, we know that the DECL is not a member of some
+        template class.  However, a friend function declared in a
+        template class is still not primary, since, in general it can
+        depend on the template parameters of the enclosing class.  */
+      && !(is_friend
+          && DECL_CLASS_CONTEXT (decl)
+          && template_class_depth (DECL_CLASS_CONTEXT (decl)) > 0))
     primary = 1;
+  else
+    primary = 0;
 
   /* Partial specialization.  */
   if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl)
@@ -1263,19 +1353,28 @@ push_template_decl (decl)
 
   args = current_template_args ();
 
-  if (! ctx || TREE_CODE (ctx) == FUNCTION_DECL 
-      || TYPE_BEING_DEFINED (ctx))
+  if (!ctx 
+      || TREE_CODE (ctx) == FUNCTION_DECL
+      || TYPE_BEING_DEFINED (ctx)
+      || (is_friend && !DECL_TEMPLATE_INFO (decl)))
     {
-      tmpl = build_template_decl (decl, current_template_parms);
-      
       if (DECL_LANG_SPECIFIC (decl)
-         && DECL_TEMPLATE_SPECIALIZATION (decl))
+         && DECL_TEMPLATE_INFO (decl)
+         && DECL_TI_TEMPLATE (decl))
+       tmpl = DECL_TI_TEMPLATE (decl);
+      else
        {
-         /* A specialization of a member template of a template
-            class. */
-         SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
-         DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
-         DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+         tmpl = build_template_decl (decl, current_template_parms);
+         
+         if (DECL_LANG_SPECIFIC (decl)
+             && DECL_TEMPLATE_SPECIALIZATION (decl))
+           {
+             /* A specialization of a member template of a template
+                class. */
+             SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
+             DECL_TEMPLATE_INFO (tmpl) = DECL_TEMPLATE_INFO (decl);
+             DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+           }
        }
     }
   else
@@ -1325,8 +1424,7 @@ push_template_decl (decl)
          
          a = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
          t = DECL_INNERMOST_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl));
-         if (TREE_VEC_LENGTH (t) 
-             != TREE_VEC_LENGTH (a))
+         if (TREE_VEC_LENGTH (t) != TREE_VEC_LENGTH (a))
            {
              cp_error ("got %d template parameters for `%#D'",
                        TREE_VEC_LENGTH (a), decl);
@@ -1372,7 +1470,10 @@ push_template_decl (decl)
   DECL_TEMPLATE_RESULT (tmpl) = decl;
   TREE_TYPE (tmpl) = TREE_TYPE (decl);
 
-  if (! ctx)
+  if (! ctx && primary)
+    /* The check of PRIMARY ensures that we do not try to push a
+       global template friend declared in a template class; such a
+       thing may well depend on the template parameters of the class.  */
     tmpl = pushdecl_top_level (tmpl);
 
   if (primary)
@@ -2014,6 +2115,9 @@ coerce_template_parms (parms, arglist, in_decl,
   return vec;
 }
 
+/* Renturns 1 iff the OLDARGS and NEWARGS are in fact identical sets
+   of template arguments.  Returns 0 otherwise.  */
+
 static int
 comp_template_args (oldargs, newargs)
      tree oldargs, newargs;
@@ -2540,7 +2644,7 @@ uses_template_parms (t)
       /* template parm nodes */
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_CONST_PARM:
+    case TEMPLATE_PARM_INDEX:
       return 1;
 
       /* simple type nodes */
@@ -2713,11 +2817,106 @@ tinst_for_decl ()
   return p;
 }
 
+
+/* DECL is a friend FUNCTION_DECL or TEMPLATE_DECL.  ARGS is the
+   vector of template arguments, as for tsubst.
+
+   Returns an appropriate tsbust'd friend declaration.  */
+
+static tree
+tsubst_friend_function (decl, args)
+     tree decl;
+     tree args;
+{
+  tree new_friend;
+  
+  if (TREE_CODE (decl) == FUNCTION_DECL 
+      && DECL_TEMPLATE_INSTANTIATION (decl)
+      && TREE_CODE (DECL_TI_TEMPLATE (decl)) != TEMPLATE_DECL)
+    /* This was a friend declared with an explicit template
+       argument list, e.g.:
+       
+       friend void f<>(T);
+       
+       to indicate that f was a template instantiation, not a new
+       function declaration.  Now, we have to figure out what
+       instantiation of what template.  */
+    {
+      tree template_id;
+      tree new_args;
+      tree tmpl;
+      tree tinfo;
+
+      template_id
+       = lookup_template_function (tsubst_expr (DECL_TI_TEMPLATE (decl),
+                                                args, 
+                                                TREE_VEC_LENGTH (args),
+                                                NULL_TREE),
+                                   tsubst (DECL_TI_ARGS (decl),
+                                           args,
+                                           TREE_VEC_LENGTH (decl),
+                                           NULL_TREE));
+      
+      /* Temporarily remove the DECL_TEMPLATE_INFO so as not to
+        confuse tsubst.  */
+      tinfo = DECL_TEMPLATE_INFO (decl);
+      DECL_TEMPLATE_INFO (decl) = NULL_TREE;
+      new_friend = tsubst (decl, args, TREE_VEC_LENGTH (args), NULL_TREE);
+      DECL_TEMPLATE_INFO (decl) = tinfo;
+
+      tmpl = determine_specialization (template_id,
+                                      new_friend,
+                                      &new_args,
+                                      0, 1);
+      return instantiate_template (tmpl, new_args);
+    }
+    else
+      new_friend = tsubst (decl, args, TREE_VEC_LENGTH (args), NULL_TREE);
+       
+  /* The new_friend will look like an instantiation, to the
+     compiler, but is not an instantiation from the point of view of
+     the language.  For example, we might have had:
+     
+     template <class T> struct S {
+       template <class U> friend void f(T, U);
+     };
+     
+     Then, in S<int>, template <class U> void f(int, U) is not an
+     instantiation of anything.  */
+  DECL_USE_TEMPLATE (new_friend) = 0;
+  if (TREE_CODE (decl) == TEMPLATE_DECL)
+    DECL_USE_TEMPLATE (DECL_TEMPLATE_RESULT (new_friend)) = 0;
+  
+  if (DECL_CONTEXT (new_friend) == NULL_TREE)
+    {
+      if (TREE_CODE (new_friend) == TEMPLATE_DECL)
+       /* This declaration is a `primary' template.  */
+       TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (new_friend))
+           = new_friend;
+
+       new_friend = pushdecl_top_level (new_friend);
+    }
+  else if (TYPE_SIZE (DECL_CONTEXT (new_friend)))
+    {
+      /* Check to see that the declaration is really present, and,
+        possibly obtain an improved declaration.  */
+      tree fn = check_classfn (DECL_CONTEXT (new_friend),
+                              new_friend);
+      
+      if (fn)
+       new_friend = fn;
+    }
+
+  return new_friend;
+}
+
+
 tree
 instantiate_class_template (type)
      tree type;
 {
   tree template, template_info, args, pattern, t, *field_chain;
+  tree typedecl;
 
   if (type == error_mark_node)
     return error_mark_node;
@@ -2910,9 +3109,42 @@ instantiate_class_template (type)
        grok_op_properties (t, DECL_VIRTUAL_P (t), 0);
     }
 
-  DECL_FRIENDLIST (TYPE_MAIN_DECL (type))
-    = tsubst (DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern)),
-             args, TREE_VEC_LENGTH (args), NULL_TREE);
+  /* Construct the DECL_FRIENDLIST for the new class type.  */
+  typedecl = TYPE_MAIN_DECL (type);
+  for (t = DECL_FRIENDLIST (TYPE_MAIN_DECL (pattern));
+       t != NULL_TREE;
+       t = TREE_CHAIN (t))
+    {
+      tree friends;
+
+      DECL_FRIENDLIST (typedecl)
+       = tree_cons (TREE_PURPOSE (t), NULL_TREE, 
+                    DECL_FRIENDLIST (typedecl));
+
+      for (friends = TREE_VALUE (t);
+          friends != NULL_TREE;
+          friends = TREE_CHAIN (friends))
+       {
+         if (TREE_PURPOSE (friends) == error_mark_node)
+           {
+             TREE_VALUE (DECL_FRIENDLIST (typedecl))
+               = tree_cons (error_mark_node, 
+                            tsubst_friend_function (TREE_VALUE (friends),
+                                                    args),
+                            TREE_VALUE (DECL_FRIENDLIST (typedecl)));
+           }
+         else
+           {
+             TREE_VALUE (DECL_FRIENDLIST (typedecl))
+               = tree_cons (tsubst (TREE_PURPOSE (friends),
+                                    args, TREE_VEC_LENGTH (args),
+                                    NULL_TREE),
+                            NULL_TREE,
+                            TREE_VALUE (DECL_FRIENDLIST (typedecl)));
+
+           }
+       }
+    }
 
   {
     tree d = CLASSTYPE_FRIEND_CLASSES (type)
@@ -3034,6 +3266,7 @@ maybe_fold_nontype_arg (arg)
   return arg;
 }
 
+
 /* Take the tree structure T and replace template parameters used therein
    with the argument vector ARGS.  NARGS is the number of args; should
    be removed.  IN_DECL is an associated decl for diagnostics.
@@ -3059,7 +3292,8 @@ tsubst (t, args, nargs, in_decl)
   if (type == unknown_type_node)
     my_friendly_abort (42);
   if (type && TREE_CODE (t) != FUNCTION_DECL
-      && TREE_CODE (t) != TYPENAME_TYPE)
+      && TREE_CODE (t) != TYPENAME_TYPE
+      && TREE_CODE (t) != TEMPLATE_DECL)
     type = tsubst (type, args, nargs, in_decl);
 
   switch (TREE_CODE (t))
@@ -3141,10 +3375,11 @@ tsubst (t, args, nargs, in_decl)
 
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_CONST_PARM:
+    case TEMPLATE_PARM_INDEX:
       {
        int idx;
        int level;
+       tree r = NULL_TREE;
 
        if (TREE_CODE (t) == TEMPLATE_TYPE_PARM
            || TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM)
@@ -3154,11 +3389,11 @@ tsubst (t, args, nargs, in_decl)
          }
        else
          {
-           idx = TEMPLATE_CONST_IDX (t);
-           level = TEMPLATE_CONST_LEVEL (t);
+           idx = TEMPLATE_PARM_IDX (t);
+           level = TEMPLATE_PARM_LEVEL (t);
          }
 
-       if (TREE_VEC_LENGTH (args) > 0) 
+       if (TREE_VEC_LENGTH (args) > 0)
          {
            tree arg = NULL_TREE;
 
@@ -3212,14 +3447,32 @@ tsubst (t, args, nargs, in_decl)
 
        /* If we get here, we must have been looking at a parm for a
           more deeply nested template.  */
-       my_friendly_assert((TREE_CODE (t) == TEMPLATE_CONST_PARM 
-                           && TEMPLATE_CONST_LEVEL (t) > 1) 
-                          || (TREE_CODE (t) == TEMPLATE_TYPE_PARM
-                              && TEMPLATE_TYPE_LEVEL (t) > 1)
-                          || (TREE_CODE (t) == TEMPLATE_TEMPLATE_PARM
-                              && TEMPLATE_TYPE_LEVEL (t) > 1),
-                          0);
-       return t;
+       my_friendly_assert(level > 1, 0);
+       
+       /* Make a new version of this template parameter, but with a
+          lower level.  */
+       switch (TREE_CODE (t))
+         {
+         case TEMPLATE_TYPE_PARM:
+         case TEMPLATE_TEMPLATE_PARM:
+           r = copy_node (t);
+           TEMPLATE_TYPE_PARM_INDEX (r)
+             = reduce_template_parm_level (TEMPLATE_TYPE_PARM_INDEX (t),
+                                           r);
+           TYPE_STUB_DECL (r) = TYPE_NAME (r) = TEMPLATE_TYPE_DECL (r);
+           TYPE_MAIN_VARIANT (r) = r;
+           TYPE_POINTER_TO (r) = NULL_TREE;
+           break;
+
+         case TEMPLATE_PARM_INDEX:
+           r = reduce_template_parm_level (t, TREE_TYPE (t));
+           break;
+          
+         default:
+           my_friendly_abort (0);
+         }
+
+       return r;
       }
 
     case TEMPLATE_DECL:
@@ -3230,8 +3483,22 @@ tsubst (t, args, nargs, in_decl)
        tree decl = DECL_TEMPLATE_RESULT (t);
        tree new_decl;
        tree parms;
+       tree* new_parms;
        tree spec;
 
+       if (TREE_CODE (decl) == TYPE_DECL)
+         {
+           if (TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TEMPLATE_PARM)
+             /* There is no tsubst'ing to be done in a template template
+                parameter.  */
+             return t;
+
+           /* This must be a member template class.  We don't handle
+              this case yet.  */
+           sorry ("member template classes");
+           return t;
+         }
+
        /* We might already have an instance of this template. */
        spec = retrieve_specialization (t, args);
        if (spec != NULL_TREE)
@@ -3247,6 +3514,10 @@ tsubst (t, args, nargs, in_decl)
        my_friendly_assert (DECL_LANG_SPECIFIC (tmpl) != 0, 0);
        DECL_CHAIN (tmpl) = NULL_TREE;
        TREE_CHAIN (tmpl) = NULL_TREE;
+       DECL_CONTEXT (tmpl) = tsubst (DECL_CONTEXT (t),
+                                     args, nargs, in_decl);
+       DECL_CLASS_CONTEXT (tmpl) = tsubst (DECL_CLASS_CONTEXT (t),
+                                           args, nargs, in_decl);
        DECL_TEMPLATE_INFO (tmpl) = build_tree_list (t, args);
        new_decl = tsubst (decl, args, nargs, in_decl);
        DECL_RESULT (tmpl) = new_decl;
@@ -3258,12 +3529,38 @@ tsubst (t, args, nargs, in_decl)
        /* The template parameters for this new template are all the
           template parameters for the old template, except the
           outermost level of parameters. */
-       DECL_TEMPLATE_PARMS (tmpl)
-         = copy_node (DECL_TEMPLATE_PARMS (tmpl));
-       for (parms = DECL_TEMPLATE_PARMS (tmpl);
+       for (new_parms = &DECL_TEMPLATE_PARMS (tmpl),
+              parms = DECL_TEMPLATE_PARMS (t);
             TREE_CHAIN (parms) != NULL_TREE;
-            parms = TREE_CHAIN (parms))
-         TREE_CHAIN (parms) = copy_node (TREE_CHAIN (parms));
+            new_parms = &(TREE_CHAIN (*new_parms)),
+              parms = TREE_CHAIN (parms))
+         {
+           tree new_vec = 
+             make_tree_vec (TREE_VEC_LENGTH (TREE_VALUE (parms)));
+           int i;
+
+           for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
+             {
+               tree default_value =
+                 TREE_PURPOSE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+               tree parm_decl = 
+                 TREE_VALUE (TREE_VEC_ELT (TREE_VALUE (parms), i));
+                 
+               TREE_VEC_ELT (new_vec, i)
+                 = build_tree_list (tsubst (default_value, args,
+                                            nargs, in_decl),
+                                    tsubst (parm_decl, args, nargs,
+                                            in_decl));
+                 
+             }
+
+           *new_parms = 
+             tree_cons (build_int_2 (0, 
+                                     TREE_INT_CST_HIGH 
+                                     (TREE_PURPOSE (parms)) - 1),
+                        new_vec,
+                        NULL_TREE);
+         }
 
        /* What should we do with the specializations of this member
           template?  Are they specializations of this new template,
@@ -3330,7 +3627,8 @@ tsubst (t, args, nargs, in_decl)
       {
        tree r = NULL_TREE;
        tree ctx;
-
+       tree fullargs = args;
+       tree tmpl = NULL_TREE;
        int member;
 
        if (DECL_CONTEXT (t) != NULL_TREE
@@ -3350,12 +3648,18 @@ tsubst (t, args, nargs, in_decl)
            type = tsubst (type, args, nargs, in_decl);
          }
 
-       /* Do we already have this instantiation?  */
+       /* If we are instantiating a specialization, get the other args.  */
        if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
          {
-           tree tmpl = DECL_TI_TEMPLATE (t);
-           tree spec = retrieve_specialization (tmpl, args);
+           tree spec;
+
+           tmpl = DECL_TI_TEMPLATE (t);
+           /* FIXME is this right for specializations?  */
+           if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
+             fullargs = add_to_template_args (DECL_TI_ARGS (tmpl), args);
 
+           /* Do we already have this instantiation?  */
+           spec = retrieve_specialization (tmpl, fullargs);
            if (spec)
              return spec;
          }
@@ -3432,21 +3736,19 @@ tsubst (t, args, nargs, in_decl)
                   build_template_decl_overload since the innermost
                   template parameters are still just template
                   parameters; there are no corresponding subsitution
-                  arguments.  */
-               /* FIXME The messed up thing here is that we get here with
-                  full args and only one level of parms.  This is necessary
-                  because when we partially instantiate a member template,
-                  even though there's really only one level of parms left
-                  we re-use the parms from the original template, which
-                  have level 2.  When this is fixed we can remove the
-                  add_to_template_args from instantiate_template.  */
-               tree tparms;
+                  arguments.  We get here with full args and only one
+                  level of parms.  This is necessary because when we
+                  partially instantiate a member template, even
+                  though there's really only one level of parms, left
+                  the parms from the original template, which have
+                  level 2, may appear in the definition of the a
+                  function body.  */
+               tree tparms; 
                tree targs;
 
                if (!DECL_TEMPLATE_SPECIALIZATION (tmpl)) 
                  {
                    tparms = DECL_TEMPLATE_PARMS (tmpl);
-
                    while (tparms && TREE_CHAIN (tparms) != NULL_TREE)
                      tparms = TREE_CHAIN (tparms);
                    
@@ -3546,8 +3848,13 @@ tsubst (t, args, nargs, in_decl)
 
        if (DECL_TEMPLATE_INFO (t) != NULL_TREE)
          {
-           tree tmpl = DECL_TI_TEMPLATE (t);
-           tree argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
+           tree argvec;
+
+           /* FIXME this is ugly.  */
+           if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+             argvec = args;
+           else
+             argvec = tsubst (DECL_TI_ARGS (t), args, nargs, in_decl);
 
            if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
              {
@@ -4112,9 +4419,10 @@ tsubst_copy (t, args, nargs, in_decl)
     case CALL_EXPR:
       {
        tree fn = TREE_OPERAND (t, 0);
-       if (really_overloaded_fn (fn))
+       if (is_overloaded_fn (fn))
          fn = tsubst_copy (get_first_fn (fn), args, nargs, in_decl);
        else
+         /* Sometimes FN is a LOOKUP_EXPR.  */
          fn = tsubst_copy (fn, args, nargs, in_decl);
        return build_nt
          (code, fn, tsubst_copy (TREE_OPERAND (t, 1), args, nargs, in_decl),
@@ -4235,7 +4543,7 @@ tsubst_copy (t, args, nargs, in_decl)
     case INTEGER_TYPE:
     case TEMPLATE_TYPE_PARM:
     case TEMPLATE_TEMPLATE_PARM:
-    case TEMPLATE_CONST_PARM:
+    case TEMPLATE_PARM_INDEX:
     case POINTER_TYPE:
     case REFERENCE_TYPE:
     case OFFSET_TYPE:
@@ -4243,6 +4551,7 @@ tsubst_copy (t, args, nargs, in_decl)
     case METHOD_TYPE:
     case ARRAY_TYPE:
     case TYPENAME_TYPE:
+    case TYPE_DECL:
       return tsubst (t, args, nargs, in_decl);
 
     case IDENTIFIER_NODE:
@@ -4577,6 +4886,8 @@ instantiate_template (tmpl, targ_ptr)
 
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283);
 
+  /* FIXME this won't work with member templates; we only have one level
+     of args here.  */
   if (DECL_FUNCTION_TEMPLATE_P (tmpl))
     {
       /* Check to see if we already have this specialization.  */
@@ -4611,9 +4922,6 @@ instantiate_template (tmpl, targ_ptr)
     }
   targ_ptr = copy_to_permanent (targ_ptr);
 
-  if (DECL_TEMPLATE_INFO (tmpl) && DECL_TI_ARGS (tmpl))
-    targ_ptr = add_to_template_args (DECL_TI_ARGS (tmpl), targ_ptr);
-
   /* substitute template parameters */
   fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, len, tmpl);
 
@@ -5024,7 +5332,7 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
                tree t = TREE_VEC_ELT (parmvec, i);
                if (TREE_CODE (t) != TEMPLATE_TYPE_PARM
                    && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
-                   && TREE_CODE (t) != TEMPLATE_CONST_PARM)
+                   && TREE_CODE (t) != TEMPLATE_PARM_INDEX)
                  continue;
 
                /* This argument can be deduced.  */
@@ -5048,9 +5356,9 @@ unify (tparms, targs, ntparms, parm, arg, nsubsts, strict)
       targs[idx] = arg;
       return 0;
 
-    case TEMPLATE_CONST_PARM:
+    case TEMPLATE_PARM_INDEX:
       (*nsubsts)++;
-      idx = TEMPLATE_CONST_IDX (parm);
+      idx = TEMPLATE_PARM_IDX (parm);
       if (targs[idx])
        {
          int i = cp_tree_equal (targs[idx], arg);
@@ -5357,7 +5665,7 @@ get_bindings (fn, decl, explicit_args)
                       DECL_NTPARMS (fn),
                       NULL_TREE);
 
-      if (!comptypes(t, TREE_TYPE (TREE_TYPE (decl)), 1))
+      if (!comptypes (t, TREE_TYPE (TREE_TYPE (decl)), 1))
        return NULL_TREE;
 
       return targs;
@@ -5669,6 +5977,20 @@ do_type_instantiation (t, storage)
   }
 }
 
+/* Return the TREE_VEC with the arguments for the innermost template header,
+   where ARGS is either that or the VEC of VECs for all the arguments.  */
+
+tree
+innermost_args (args)
+     tree args;
+{
+  if (TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+    return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
+  return args;
+}
+
+/* Produce the definition of D, a _DECL generated from a template.  */
+
 tree
 instantiate_decl (d)
      tree d;
@@ -5685,7 +6007,15 @@ instantiate_decl (d)
   int line = lineno;
   char *file = input_filename;
 
-  for (td = tmpl; DECL_TEMPLATE_INSTANTIATION (td); )
+  for (td = tmpl; 
+       DECL_TEMPLATE_INSTANTIATION (td) 
+        /* This next clause handles friend templates defined inside
+           class templates.  The friend templates are not really
+           instantiations from the point of view of the language, but
+           they are instantiations from the point of view of the
+           compiler.  */
+        || (DECL_TEMPLATE_INFO (td) && !DECL_TEMPLATE_SPECIALIZATION (td)); 
+       )
     td = DECL_TI_TEMPLATE (td);
 
   /* In the case of a member template, decl_pattern is the partially
@@ -5781,7 +6111,10 @@ instantiate_decl (d)
   /* Trick tsubst into giving us a new decl in case the template changed.  */
   save_ti = DECL_TEMPLATE_INFO (decl_pattern);
   DECL_TEMPLATE_INFO (decl_pattern) = NULL_TREE;
-  td = tsubst (decl_pattern, args, TREE_VEC_LENGTH (args), tmpl);
+  /* FIXME this is ugly.  */
+  td = tsubst (decl_pattern,
+              DECL_TEMPLATE_SPECIALIZATION (decl_pattern)
+              ? args : innermost_args (args), 0, tmpl);
   SET_DECL_IMPLICIT_INSTANTIATION (td);
   DECL_TEMPLATE_INFO (decl_pattern) = save_ti;
 
index 5a85956..4a6ce7b 100644 (file)
@@ -66,9 +66,13 @@ print_lang_type (file, node, indent)
      register tree node;
      int indent;
 {
-  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
+  if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
+      || TREE_CODE (node) == TEMPLATE_TEMPLATE_PARM)
     {
-      print_node (file, "tinfo", TYPE_VALUES (node), indent + 4);
+      indent_to (file, indent + 3);
+      fprintf (file, "index %d level %d orig_level %d",
+              TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
+              TEMPLATE_TYPE_ORIG_LEVEL (node));
       return;
     }
 
index 8177157..df391b5 100644 (file)
@@ -794,7 +794,17 @@ static tree
 lookup_field_1 (type, name)
      tree type, name;
 {
-  register tree field = TYPE_FIELDS (type);
+  register tree field;
+
+  if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
+      || TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
+    /* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM are not fields at all;
+       instead TYPE_FIELDS is the TEMPLATE_PARM_INDEX.  (Miraculously,
+       the code often worked even when we treated the index as a list
+       of fields!)  */
+    return NULL_TREE;
+
+  field = TYPE_FIELDS (type);
 
 #ifdef GATHER_STATISTICS
   n_calls_lookup_field_1++;
@@ -804,6 +814,7 @@ lookup_field_1 (type, name)
 #ifdef GATHER_STATISTICS
       n_fields_searched++;
 #endif /* GATHER_STATISTICS */
+      my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (field)) == 'd', 0);
       if (DECL_NAME (field) == NULL_TREE
          && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
        {
index 95b505a..b4799d4 100644 (file)
@@ -329,7 +329,7 @@ yylex ()
            }
        }
       else
-       lastiddecl = trrr;
+       lastiddecl = NULL_TREE;
       got_scope = NULL_TREE;
       /* and fall through to...  */
     case IDENTIFIER_DEFN:
index 1bd60f1..8fb0c9f 100644 (file)
@@ -2070,9 +2070,9 @@ cp_tree_equal (t1, t2)
     case FUNCTION_DECL:
       return 0;
 
-    case TEMPLATE_CONST_PARM:
-      return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
-       && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
+    case TEMPLATE_PARM_INDEX:
+      return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
+       && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
 
     case SIZEOF_EXPR:
     case ALIGNOF_EXPR:
index 851020f..3375f11 100644 (file)
@@ -2367,11 +2367,17 @@ build_x_function_call (function, params, decl)
               || TREE_CODE (type) == METHOD_TYPE
               || TYPE_PTRMEMFUNC_P (type));
 
-  if (TREE_CODE (function) == FUNCTION_DECL
-      && DECL_STATIC_FUNCTION_P (function))
+  if ((TREE_CODE (function) == FUNCTION_DECL
+       && DECL_STATIC_FUNCTION_P (function))
+      || (TREE_CODE (function) == TEMPLATE_DECL
+         && DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
     return build_member_call
       (DECL_CONTEXT (function), DECL_NAME (function), params);
 
+  /* A friend template.  Make it look like a toplevel declaration.  */
+  if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
+    function = build_scratch_list (NULL_TREE, function);
+
   /* Handle methods, friends, and overloaded functions, respectively.  */
   if (is_method)
     {