From f3110581a4c1b02117152713d4f46cae9ee2662d Mon Sep 17 00:00:00 2001 From: jason Date: Mon, 23 Feb 1998 03:17:44 +0000 Subject: [PATCH] Support for friend templates. * 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 `'. * 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 --- gcc/cp/ChangeLog | 102 +++++++++ gcc/cp/Make-lang.in | 3 +- gcc/cp/cp-tree.def | 55 ++++- gcc/cp/cp-tree.h | 74 +++++-- gcc/cp/decl.c | 79 +++---- gcc/cp/decl2.c | 27 +-- gcc/cp/error.c | 27 +-- gcc/cp/friend.c | 84 ++++--- gcc/cp/gxxint.texi | 12 +- gcc/cp/lex.c | 17 +- gcc/cp/method.c | 68 +++--- gcc/cp/pt.c | 617 ++++++++++++++++++++++++++++++++++++++++------------ gcc/cp/ptree.c | 8 +- gcc/cp/search.c | 13 +- gcc/cp/spew.c | 2 +- gcc/cp/tree.c | 6 +- gcc/cp/typeck.c | 10 +- 17 files changed, 874 insertions(+), 330 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5c90268..beb54a2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,105 @@ +Mon Feb 23 03:04:14 1998 Jason Merrill + + * 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 + + * 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 `'. + * 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. diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in index a9e4e1c..6ed1678 100644 --- a/gcc/cp/Make-lang.in +++ b/gcc/cp/Make-lang.in @@ -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 # # Build hooks: diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index ab126fa..74d6441 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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 // Index 0, Level 1. + struct S + { + template // 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, we will have: + + struct S + { + template // 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. - 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: +*/ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a254db8..de63849 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index ce35770..d05c493 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 */ diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c598c1a..c847a27 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 */ } diff --git a/gcc/cp/error.c b/gcc/cp/error.c index e236153..0451781 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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 (""); - } + dump_decl (TEMPLATE_PARM_DECL (t), -1); } break; diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 028706a..f28e049 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -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 diff --git a/gcc/cp/gxxint.texi b/gcc/cp/gxxint.texi index 5f73465..cf9aaa9 100644 --- a/gcc/cp/gxxint.texi +++ b/gcc/cp/gxxint.texi @@ -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 diff --git a/gcc/cp/lex.c b/gcc/cp/lex.c index 550ca34..8d6d622 100644 --- a/gcc/cp/lex.c +++ b/gcc/cp/lex.c @@ -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 diff --git a/gcc/cp/method.c b/gcc/cp/method.c index a3ff1ac..8be513b 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6a65710..a50368a 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 + struct A + { + template + struct B {}; + }; + + A::B has depth two, while A has depth one. Also, + both A::B and A::B 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 C { void f(); } @@ -187,67 +222,56 @@ end_member_template_processing () then neither C::f nor C::f 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 C { template 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 struct S { + template friend void f(T, U); + }; + + Then, in S, template 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; diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 5a85956..4a6ce7b 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -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; } diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 8177157..df391b5 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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) { diff --git a/gcc/cp/spew.c b/gcc/cp/spew.c index 95b505a..b4799d4 100644 --- a/gcc/cp/spew.c +++ b/gcc/cp/spew.c @@ -329,7 +329,7 @@ yylex () } } else - lastiddecl = trrr; + lastiddecl = NULL_TREE; got_scope = NULL_TREE; /* and fall through to... */ case IDENTIFIER_DEFN: diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 1bd60f1..8fb0c9f 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 851020f..3375f11 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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) { -- 2.7.4