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 `<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.

From-SVN: r18198
This commit is contained in:
Jason Merrill 1998-02-22 22:17:44 -05:00
parent 9e89df5017
commit f84b4be9a7
17 changed files with 874 additions and 330 deletions

View File

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

View File

@ -124,7 +124,8 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \
$(srcdir)/cp/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
$(srcdir)/cp/repo.c
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o
cc1plus: $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
$(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
#
# Build hooks:

View File

@ -87,23 +87,60 @@ DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3)
*/
DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0)
/* Index into a template parameter list. The TEMPLATE_PARM_IDX gives
the index (from 0) of the parameter, while the TEMPLATE_PARM_LEVEL
gives the level (from 1) of the parameter.
Here's an example:
template <class T> // Index 0, Level 1.
struct S
{
template <class U, // Index 0, Level 2.
class V> // Index 1, Level 2.
void f();
};
The DESCENDANTS will be a chain of TEMPLATE_PARM_INDEXs descended
from this one. The first descendant will have the same IDX, but
its LEVEL will be one less. The TREE_CHAIN field is used to chain
together the descendants. The TEMPLATE_PARM_DECL is the
declaration of this parameter, either a TYPE_DECL or CONST_DECL.
The TEMPLATE_PARM_ORIG_LEVEL is the LEVEL of the most distant
parent, i.e., the LEVEL that the parameter originally had when it
was declared. For example, if we instantiate S<int>, we will have:
struct S<int>
{
template <class U, // Index 0, Level 1, Orig Level 2
class V> // Index 1, Level 1, Orig Level 2
void f();
};
The LEVEL is the level of the parameter when we are worrying about
the types of things; the ORIG_LEVEL is the level when we are
worrying about instantiating things. */
DEFTREECODE (TEMPLATE_PARM_INDEX, "template_parm_index", 'c',
/* The addition of (sizeof(char*) - 1) in the next
expression is to ensure against the case where
sizeof(char*) does not evenly divide
sizeof(HOST_WIDE_INT). */
2 + ((3 * sizeof (HOST_WIDE_INT) + sizeof(char*) - 1)
/ sizeof (char*)))
/* Index into a template parameter list. This parameter must be a type.
Use TYPE_FIELDS to find parmlist and index. */
The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */
DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
/* Index into a template parameter list. This parameter must be a type.
If it is used in signature of a template, TEMPLATE_INFO is NULL_TREE.
Otherwise it is used to declare a type like TT<int>.
Use TYPE_FIELDS to find parmlist and index. */
The TYPE_FIELDS value will be a TEMPLATE_PARM_INDEX. */
DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
/* A type designated by 'typename T::t'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0)
/* Index into a template parameter list. This parameter must not be a
type. */
DEFTREECODE (TEMPLATE_CONST_PARM, "template_const_parm", 'c', 3)
/* A thunk is a stub function.
Thunks are used to implement multiple inheritance:
@ -179,3 +216,9 @@ DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/*
Local variables:
mode:c
End:
*/

View File

@ -47,6 +47,17 @@ typedef struct
int new_type_flag;
} flagged_type_tree;
typedef struct
{
char common[sizeof (struct tree_common)];
struct rtx_def *rtl; /* Unused, but required to match up with what
the middle-end expects. */
HOST_WIDE_INT index;
HOST_WIDE_INT level;
HOST_WIDE_INT orig_level;
tree decl;
} template_parm_index;
/* To identify to the debug emitters if it should pay attention to the
flag `-Wtemplate-debugging'. */
#define HAVE_TEMPLATES 1
@ -1340,6 +1351,18 @@ extern int flag_new_for_scope;
#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous)
/* C++: all of these are overloaded! These apply only to TYPE_DECLs. */
/* The format of each node in the DECL_FRIENDLIST is as follows:
The TREE_PURPOSE will be the name of a function, i.e., an
IDENTIFIER_NODE. The TREE_VALUE will be itself a TREE_LIST, the
list of functions with that name which are friends. The
TREE_PURPOSE of each node in this sublist will be error_mark_node,
if the function was declared a friend individually, in which case
the TREE_VALUE will be the function_decl. If, however, all
functions with a given name in a class were declared to be friends,
the TREE_PUROSE will be the class type, and the TREE_VALUE will be
NULL_TREE. */
#define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
/* The DECL_ACCESS is used to record under which context
@ -1352,6 +1375,17 @@ extern int flag_new_for_scope;
#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
/* Accessor macros for C++ template decl nodes. */
/* The DECL_TEMPLATE_PARMS are a list. The TREE_PURPOSE of each node
indicates the level of the template parameters, with 1 being the
outermost set of template parameters. The TREE_VALUE is a vector,
whose elements are the template parameters at each level. Each
element in the vector is a TREE_LIST, whose TREE_VALUE is a
PARM_DECL (if the parameter is a non-type parameter), or a
TYPE_DECL (if the parameter is a type parameter). The TREE_PURPOSE
is the default value, if any. The TEMPLATE_PARM_INDEX for the
parameter is avilable as the DECL_INITIAL (for a PARM_DECL) or as
the TREE_TYPE (for a TYPE_DECL). */
#define DECL_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
@ -1374,6 +1408,12 @@ extern int flag_new_for_scope;
(TREE_CODE (NODE) == TEMPLATE_DECL \
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_DECL)
/* A `primary' template is one which depends on no tbemplate parameters
except those specified in its parameter list. So, a template
member of a non-template class is primary, and every global
function template is primary, but a member function of a template
class is not primary, neither is a member template of a template
class. */
#define PRIMARY_TEMPLATE_P(NODE) \
(TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (NODE))
@ -1934,24 +1974,27 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define WANT_ARITH (WANT_INT | WANT_FLOAT)
/* Anatomy of a DECL_FRIENDLIST (which is a TREE_LIST):
purpose = friend name (IDENTIFIER_NODE);
value = TREE_LIST of FUNCTION_DECLS;
chain, type = EMPTY; */
#define FRIEND_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (LIST))
/* These macros are used to access a TEMPLATE_PARM_INDEX. */
#define TEMPLATE_PARM_IDX(NODE) (((template_parm_index*) NODE)->index)
#define TEMPLATE_PARM_LEVEL(NODE) (((template_parm_index*) NODE)->level)
#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (((template_parm_index*) NODE)->orig_level)
#define TEMPLATE_PARM_DECL(NODE) (((template_parm_index*) NODE)->decl)
/* These macros are for accessing the fields of TEMPLATE_TYPE_PARM
and TEMPLATE_TEMPLATE_PARM nodes. */
#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \
(TYPE_FIELDS (NODE) = build_int_2 (I, L))
/* These macros are for accessing the fields of TEMPLATE_CONST_PARM nodes. */
#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE))
#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE))
#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \
(TEMPLATE_CONST_IDX (NODE) = I, TEMPLATE_CONST_LEVEL (NODE) = L)
#define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_IDX(NODE) \
(TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_LEVEL(NODE) \
(TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \
(TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_DECL(NODE) \
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
/* in lex.c */
/* Indexed by TREE_CODE, these tables give C-looking names to
@ -2336,8 +2379,8 @@ extern tree tsubst PROTO ((tree, tree, int, tree));
extern tree tsubst_expr PROTO ((tree, tree, int, tree));
extern tree tsubst_copy PROTO ((tree, tree, int, tree));
extern tree tsubst_chain PROTO((tree, tree));
extern void begin_member_template_processing PROTO((tree));
extern void end_member_template_processing PROTO((void));
extern void maybe_begin_member_template_processing PROTO((tree));
extern void maybe_end_member_template_processing PROTO((tree));
extern tree finish_member_template_decl PROTO((tree, tree));
extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void));
@ -2382,6 +2425,7 @@ extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree));
extern int comp_template_parms PROTO((tree, tree));
extern int template_class_depth PROTO((tree));
extern int processing_specialization;
extern int processing_explicit_instantiation;

View File

@ -2311,47 +2311,15 @@ decls_match (newdecl, olddecl)
else if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL)
{
tree newargs = DECL_TEMPLATE_PARMS (newdecl);
tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
int i;
/* Run through all the levels of template parameters, checking
that they match. */
while (newargs && oldargs)
{
int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs));
if (TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (oldargs)) != len)
return 0;
for (i = 0; i < len; i++)
{
tree newarg =
TREE_VALUE (TREE_VEC_ELT
(INNERMOST_TEMPLATE_PARMS (newargs), i));
tree oldarg =
TREE_VALUE (TREE_VEC_ELT
(INNERMOST_TEMPLATE_PARMS (oldargs), i));
if (TREE_CODE (newarg) != TREE_CODE (oldarg))
return 0;
else if (TREE_CODE (newarg) == TYPE_DECL)
/* continue */;
else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
return 0;
}
newargs = TREE_CHAIN (newargs);
oldargs = TREE_CHAIN (oldargs);
}
if ((newargs == NULL_TREE) != (oldargs == NULL_TREE))
/* One declaration has more levels that the other. */
return 0;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
DECL_TEMPLATE_RESULT (newdecl));
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
return 0;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
DECL_TEMPLATE_RESULT (newdecl));
}
else
{
@ -2760,6 +2728,7 @@ duplicate_decls (newdecl, olddecl)
cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
}
return 1;
}
@ -4504,7 +4473,10 @@ make_implicit_typename (context, t)
If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY)
Otherwise we prefer non-TYPE_DECLs. */
Otherwise we prefer non-TYPE_DECLs.
If NONCLASS is non-zero, we don't look for the NAME in class scope,
using IDENTIFIER_CLASS_VALUE. */
static tree
lookup_name_real (name, prefer_type, nonclass)
@ -7461,8 +7433,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (friendp &&
TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
/* A friend declaration of the form friend void f<>(). */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
{
/* A friend declaration of the form friend void f<>(). Record
the information in the TEMPLATE_ID_EXPR. */
SET_DECL_IMPLICIT_INSTANTIATION (decl);
DECL_TEMPLATE_INFO (decl)
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
}
/* Caller will do the rest of this. */
if (check < 0)
@ -7485,8 +7464,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (check)
{
@ -7532,8 +7511,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
funcdef_flag ? 2 :
(friendp ? 3 : 0));
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (ctype != NULL_TREE && check)
{
@ -7952,10 +7931,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (fns) == IDENTIFIER_NODE)
dname = fns;
else if (really_overloaded_fn (fns))
else if (is_overloaded_fn (fns))
dname = DECL_NAME (get_first_fn (fns));
else
dname = DECL_NAME (fns);
my_friendly_abort (0);
}
/* fall through */

View File

@ -1431,19 +1431,22 @@ check_classfn (ctype, function)
if (fn_name == DECL_NAME (*methods))
{
got_it:
fndecl = *methods;
while (fndecl)
for (fndecl = *methods; fndecl != NULL_TREE;
fndecl = DECL_CHAIN (fndecl))
{
if (DECL_ASSEMBLER_NAME (function) == DECL_ASSEMBLER_NAME (fndecl))
/* The DECL_ASSEMBLER_NAME for a TEMPLATE_DECL is
not mangled, so the check below does not work
correctly in that case. */
if (TREE_CODE (function) != TEMPLATE_DECL
&& TREE_CODE (fndecl) != TEMPLATE_DECL
&& (DECL_ASSEMBLER_NAME (function)
== DECL_ASSEMBLER_NAME (fndecl)))
return fndecl;
#if 0
/* This doesn't work for static member functions that are
pretending to be methods. */
/* We have to do more extensive argument checking here, as
the name may have been changed by asm("new_name"). */
if (decls_match (function, fndecl))
return fndecl;
#else
/* We cannot simply call decls_match because this
doesn't work for static member functions that are
pretending to be methods, and because the name
may have been changed by asm("new_name"). */
if (DECL_NAME (function) == DECL_NAME (fndecl))
{
tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
@ -1471,8 +1474,6 @@ check_classfn (ctype, function)
templates =
scratch_tree_cons (NULL_TREE, fndecl, templates);
}
#endif
fndecl = DECL_CHAIN (fndecl);
}
break; /* loser */
}

View File

@ -856,7 +856,7 @@ dump_decl (t, v)
case CONST_DECL:
if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
|| (DECL_INITIAL (t) &&
TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM))
TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
goto general;
else if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v);
@ -1527,33 +1527,12 @@ dump_expr (t, nop)
break;
}
case TEMPLATE_CONST_PARM:
case TEMPLATE_PARM_INDEX:
{
int l = current_template_parms ?
list_length (current_template_parms) : 0;
if (l >= TEMPLATE_CONST_LEVEL (t))
{
int i;
tree parms = current_template_parms;
tree r;
for (i = 0; i < l - TEMPLATE_CONST_LEVEL (t); ++i)
{
parms = TREE_CHAIN (parms);
my_friendly_assert (parms != NULL_TREE, 0);
}
r = TREE_VEC_ELT (TREE_VALUE (parms),
TEMPLATE_CONST_IDX (t));
dump_decl (TREE_VALUE (r), -1);
}
else
{
OB_PUTS ("<tparm ");
OB_PUTI (TEMPLATE_CONST_IDX (t));
OB_PUTS (">");
}
dump_decl (TEMPLATE_PARM_DECL (t), -1);
}
break;

View File

@ -33,22 +33,7 @@ Boston, MA 02111-1307, USA. */
static void add_friend PROTO((tree, tree));
static void add_friends PROTO((tree, tree, tree));
/* Friend data structures:
Lists of friend functions come from TYPE_DECL nodes. Since all
aggregate types are automatically typedef'd, these nodes are guaranteed
to exist.
The TREE_PURPOSE of a friend list is the name of the friend,
and its TREE_VALUE is another list.
For each element of that list, either the TREE_VALUE or the TREE_PURPOSE
will be filled in, but not both. The TREE_VALUE of that list is an
individual function which is a friend. The TREE_PURPOSE of that list
indicates a type in which all functions by that name are friends.
Lists of friend classes come from _TYPE nodes. Love that consistency
thang. */
/* Friend data structures are described in cp-tree.h. */
int
is_friend (type, supplicant)
@ -83,6 +68,31 @@ is_friend (type, supplicant)
{
if (ctype == TREE_PURPOSE (friends))
return 1;
if (TREE_VALUE (friends) == NULL_TREE)
continue;
if (TREE_CODE (TREE_VALUE (friends)) == TEMPLATE_DECL)
{
tree t;
/* Perhaps this function is a specialization of
a friend template. */
for (t = supplicant;
t != NULL_TREE;
t = DECL_TEMPLATE_INFO (t) ?
DECL_TI_TEMPLATE (t) : NULL_TREE)
/* FIXME: The use of comptypes here, and below, is
bogus, since two specializations of a
template parameter with non-type parameters
may have the same type, but be different. */
if (comptypes (TREE_TYPE (t),
TREE_TYPE (TREE_VALUE (friends)), 1))
return 1;
continue;
}
if (comptypes (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends)), 1))
return 1;
@ -302,9 +312,15 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
tree quals;
int funcdef_flag;
{
int is_friend_template = 0;
/* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1;
if (TREE_CODE (decl) == FUNCTION_DECL)
is_friend_template = processing_template_decl >
template_class_depth (current_class_type);
if (ctype)
{
tree cname = TYPE_NAME (ctype);
@ -319,18 +335,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
/* This will set up DECL_ARGUMENTS for us. */
grokclassfn (ctype, cname, decl, flags, quals);
if (TYPE_SIZE (ctype) != 0)
if (is_friend_template)
decl = DECL_TI_TEMPLATE (push_template_decl (decl));
if (TYPE_SIZE (ctype) != 0
&& template_class_depth (ctype) == 0)
decl = check_classfn (ctype, decl);
if (TREE_TYPE (decl) != error_mark_node)
{
if (TYPE_SIZE (ctype))
if (TYPE_SIZE (ctype) || template_class_depth (ctype) > 0)
add_friend (current_class_type, decl);
else
{
cp_error ("member `%D' declared as friend before type `%T' defined",
decl, ctype);
}
cp_error ("member `%D' declared as friend before type `%T' defined",
decl, ctype);
}
}
else
@ -386,10 +405,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
{
/* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. Don't do this
for a template instantiation. */
decl = pushdecl (decl);
for a template instantiation. */
if (!is_friend_template)
{
/* However, we don't call pushdecl() for a friend
function of a template class, since in general,
such a declaration depends on template
parameters. Instead, we call pushdecl when the
class is instantiated. */
if (template_class_depth (current_class_type) == 0)
decl = pushdecl (decl);
}
else
decl = push_template_decl (decl);
if (! funcdef_flag && ! flag_guiding_decls
if (! funcdef_flag && ! flag_guiding_decls && ! is_friend_template
&& current_template_parms && uses_template_parms (decl))
{
static int explained;
@ -405,8 +435,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
}
make_decl_rtl (decl, NULL_PTR, 1);
add_friend (current_class_type, decl);
add_friend (current_class_type,
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl);
DECL_FRIEND_P (decl) = 1;
}
else

View File

@ -1684,14 +1684,14 @@ as a @samp{Z} followed by the encoding of the type.
A function template specialization (either an instantiation or an
explicit specialization) is encoded by an @samp{H} followed by the
encoding of the template parameters, as described above, followed by
an @samp{_}, the encoding of the argument types template function (not the
specialization), another @samp{_}, and the return type. (Like the
argument types, the return type is the return type of the function
encoding of the template parameters, as described above, followed by an
@samp{_}, the encoding of the argument types to the template function
(not the specialization), another @samp{_}, and the return type. (Like
the argument types, the return type is the return type of the function
template, not the specialization.) Template parameters in the argument
and return types are encoded by an @samp{X} for type parameters, or a
@samp{Y} for constant parameters, and an index indicating their position
in the template parameter list declaration.
@samp{Y} for constant parameters, an index indicating their position
in the template parameter list declaration, and their template depth.
@subsection Arrays

View File

@ -1213,8 +1213,7 @@ do_pending_inlines ()
context = hack_decl_function_context (t->fndecl);
if (context)
push_cp_function_context (context);
if (is_member_template (t->fndecl))
begin_member_template_processing (t->fndecl);
maybe_begin_member_template_processing (t->fndecl);
if (t->len > 0)
{
feed_input (t->buf, t->len);
@ -1252,8 +1251,7 @@ process_next_inline (t)
tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl);
if (is_member_template (i->fndecl))
end_member_template_processing ();
maybe_end_member_template_processing (i->fndecl);
if (context)
pop_cp_function_context (context);
i = i->next;
@ -1276,8 +1274,7 @@ process_next_inline (t)
context = hack_decl_function_context (i->fndecl);
if (context)
push_cp_function_context (context);
if (is_member_template (i->fndecl))
begin_member_template_processing (i->fndecl);
maybe_begin_member_template_processing (i->fndecl);
feed_input (i->buf, i->len);
lineno = i->lineno;
input_filename = i->filename;
@ -1891,8 +1888,7 @@ do_pending_defargs ()
{
push_nested_class (TREE_PURPOSE (defarg_fns), 1);
pushlevel (0);
if (is_member_template (defarg_fn))
begin_member_template_processing (defarg_fn);
maybe_begin_member_template_processing (defarg_fn);
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{
@ -1920,8 +1916,7 @@ do_pending_defargs ()
return;
}
if (is_member_template (defarg_fn))
end_member_template_processing ();
maybe_end_member_template_processing (defarg_fn);
poplevel (0, 0, 0);
pop_nested_class (1);
}
@ -2946,7 +2941,7 @@ do_identifier (token, parsing)
}
if (! processing_template_decl
|| (DECL_INITIAL (id)
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
id = DECL_INITIAL (id);
}
else

View File

@ -602,6 +602,24 @@ build_overload_int (value, in_template)
icat (TREE_INT_CST_LOW (value));
}
/* Output S followed by a representation of the TEMPLATE_PARM_INDEX
supplied in INDEX. */
static void
build_mangled_template_parm_index (s, index)
char* s;
tree index;
{
OB_PUTCP (s);
build_underscore_int (TEMPLATE_PARM_IDX (index));
/* We use the LEVEL, not the ORIG_LEVEL, because the mangling is a
representation of the function from the point of view of its
type. */
build_underscore_int (TEMPLATE_PARM_LEVEL (index));
}
static void
build_overload_value (type, value, in_template)
tree type, value;
@ -619,11 +637,9 @@ build_overload_value (type, value, in_template)
numeric_output_need_bar = 0;
}
if (TREE_CODE (value) == TEMPLATE_CONST_PARM)
if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
{
OB_PUTC ('Y');
build_underscore_int (TEMPLATE_CONST_IDX (value));
build_underscore_int (TEMPLATE_CONST_LEVEL (value));
build_mangled_template_parm_index ("Y", value);
return;
}
@ -761,13 +777,19 @@ build_overload_value (type, value, in_template)
sorry ("template instantiation with pointer to method that is too complex");
return;
}
if (TREE_CODE (value) == INTEGER_CST
|| TREE_CODE (value) == TEMPLATE_CONST_PARM)
if (TREE_CODE (value) == INTEGER_CST)
{
build_overload_int (value, in_template);
numeric_output_need_bar = 1;
return;
}
else if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
{
build_mangled_template_parm_index ("", value);
numeric_output_need_bar = 1;
return;
}
value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL)
{
@ -1374,33 +1396,27 @@ process_overload_item (parmtype, extra_Gcode)
declaration. */
if (CLASSTYPE_TEMPLATE_INFO (parmtype))
{
OB_PUTC ('t');
OB_PUTC ('z');
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
build_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
CLASSTYPE_TI_ARGS (parmtype));
build_mangled_template_parm_index ("tzX",
TEMPLATE_TYPE_PARM_INDEX
(parmtype));
build_template_parm_names
(DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
CLASSTYPE_TI_ARGS (parmtype));
}
else
{
OB_PUTC ('Z');
OB_PUTC ('z');
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
build_template_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
build_mangled_template_parm_index ("ZzX",
TEMPLATE_TYPE_PARM_INDEX
(parmtype));
build_template_template_parm_names
(DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
}
break;
case TEMPLATE_TYPE_PARM:
OB_PUTC ('X');
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype));
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype));
build_mangled_template_parm_index ("X",
TEMPLATE_TYPE_PARM_INDEX
(parmtype));
break;
case TYPENAME_TYPE:

View File

@ -86,6 +86,7 @@ static int type_unification_real PROTO((tree, tree *, tree, tree, int*,
static void note_template_header PROTO((int));
static tree maybe_fold_nontype_arg PROTO((tree));
static tree convert_nontype_argument PROTO((tree, tree));
static int is_member_or_friend_template PROTO((tree, int));
/* Do any processing required when DECL (a member template declaration
using TEMPLATE_PARAMETERS as its innermost parameter list) is
@ -109,22 +110,51 @@ finish_member_template_decl (template_parameters, decl)
return DECL_TI_TEMPLATE (decl);
}
if (decl)
return decl;
cp_error ("invalid member template declaration");
return NULL_TREE;
return decl;
}
/* Restore the template parameter context. */
/* 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 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)
{
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;
}
}
if (parm_levels > template_class_levels)
r = 1;
}
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;
}
return r;
return 0;
}
/* Returns non-zero iff T is a member template. */
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;
tree ctx;
int primary;
int is_friend = (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_FRIEND_P (decl));
/* 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)) */)
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;

View File

@ -66,9 +66,13 @@ print_lang_type (file, node, indent)
register tree node;
int indent;
{
if (TREE_CODE (node) == TEMPLATE_TYPE_PARM)
if (TREE_CODE (node) == TEMPLATE_TYPE_PARM
|| TREE_CODE (node) == TEMPLATE_TEMPLATE_PARM)
{
print_node (file, "tinfo", TYPE_VALUES (node), indent + 4);
indent_to (file, indent + 3);
fprintf (file, "index %d level %d orig_level %d",
TEMPLATE_TYPE_IDX (node), TEMPLATE_TYPE_LEVEL (node),
TEMPLATE_TYPE_ORIG_LEVEL (node));
return;
}

View File

@ -794,7 +794,17 @@ static tree
lookup_field_1 (type, name)
tree type, name;
{
register tree field = TYPE_FIELDS (type);
register tree field;
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
/* The TYPE_FIELDS of a TEMPLATE_TYPE_PARM are not fields at all;
instead TYPE_FIELDS is the TEMPLATE_PARM_INDEX. (Miraculously,
the code often worked even when we treated the index as a list
of fields!) */
return NULL_TREE;
field = TYPE_FIELDS (type);
#ifdef GATHER_STATISTICS
n_calls_lookup_field_1++;
@ -804,6 +814,7 @@ lookup_field_1 (type, name)
#ifdef GATHER_STATISTICS
n_fields_searched++;
#endif /* GATHER_STATISTICS */
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (field)) == 'd', 0);
if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{

View File

@ -329,7 +329,7 @@ yylex ()
}
}
else
lastiddecl = trrr;
lastiddecl = NULL_TREE;
got_scope = NULL_TREE;
/* and fall through to... */
case IDENTIFIER_DEFN:

View File

@ -2070,9 +2070,9 @@ cp_tree_equal (t1, t2)
case FUNCTION_DECL:
return 0;
case TEMPLATE_CONST_PARM:
return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
&& TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
case TEMPLATE_PARM_INDEX:
return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
case SIZEOF_EXPR:
case ALIGNOF_EXPR:

View File

@ -2367,11 +2367,17 @@ build_x_function_call (function, params, decl)
|| TREE_CODE (type) == METHOD_TYPE
|| TYPE_PTRMEMFUNC_P (type));
if (TREE_CODE (function) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (function))
if ((TREE_CODE (function) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (function))
|| (TREE_CODE (function) == TEMPLATE_DECL
&& DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
return build_member_call
(DECL_CONTEXT (function), DECL_NAME (function), params);
/* A friend template. Make it look like a toplevel declaration. */
if (! is_method && TREE_CODE (function) == TEMPLATE_DECL)
function = build_scratch_list (NULL_TREE, function);
/* Handle methods, friends, and overloaded functions, respectively. */
if (is_method)
{