summaryrefslogtreecommitdiffstats
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog102
-rw-r--r--gcc/cp/Make-lang.in3
-rw-r--r--gcc/cp/cp-tree.def55
-rw-r--r--gcc/cp/cp-tree.h74
-rw-r--r--gcc/cp/decl.c79
-rw-r--r--gcc/cp/decl2.c27
-rw-r--r--gcc/cp/error.c27
-rw-r--r--gcc/cp/friend.c84
-rw-r--r--gcc/cp/gxxint.texi12
-rw-r--r--gcc/cp/lex.c17
-rw-r--r--gcc/cp/method.c68
-rw-r--r--gcc/cp/pt.c617
-rw-r--r--gcc/cp/ptree.c8
-rw-r--r--gcc/cp/search.c13
-rw-r--r--gcc/cp/spew.c2
-rw-r--r--gcc/cp/tree.c6
-rw-r--r--gcc/cp/typeck.c10
17 files changed, 874 insertions, 330 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5c9026827ce..beb54a2da11 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index a9e4e1ca87e..6ed167830c8 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 ab126fa7072..74d64412cb8 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 <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:
+*/
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a254db88a06..de6384944d1 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 ce35770dbc9..d05c4936328 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 c598c1adbf6..c847a2782b5 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 e236153013a..04517814a69 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 ("<tparm ");
- OB_PUTI (TEMPLATE_CONST_IDX (t));
- OB_PUTS (">");
- }
+ dump_decl (TEMPLATE_PARM_DECL (t), -1);
}
break;
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index 028706ad21b..f28e049cfa4 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 5f7346561c5..cf9aaa9a12d 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 550ca34d076..8d6d62229c5 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 a3ff1ac10ed..8be513b9828 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 6a657107028..a50368aa655 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 <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;
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index 5a859561512..4a6ce7bfaeb 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 8177157e81c..df391b52a21 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 95b505a3d74..b4799d42e68 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 1bd60f177b5..8fb0c9f586c 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 851020f99af..3375f11db0f 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)
{
OpenPOWER on IntegriCloud