Commit f84b4be9 by Jason Merrill

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
parent 9e89df50
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) Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com)
* error.c: Include sys/types.h. * error.c: Include sys/types.h.
......
...@@ -124,7 +124,8 @@ CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)/cp/decl2.c \ ...@@ -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/parse.y $(srcdir)/cp/sig.c $(srcdir)/cp/typeck2.c \
$(srcdir)/cp/repo.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 cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus
# #
# Build hooks: # Build hooks:
......
...@@ -87,23 +87,60 @@ DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3) ...@@ -87,23 +87,60 @@ DEFTREECODE (VEC_INIT_EXPR, "vec_init_expr", 'e', 3)
*/ */
DEFTREECODE (TEMPLATE_DECL, "template_decl", 'd', 0) 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. /* 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) DEFTREECODE (TEMPLATE_TYPE_PARM, "template_type_parm", 't', 0)
/* Index into a template parameter list. This parameter must be a type. /* 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. 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>. 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) DEFTREECODE (TEMPLATE_TEMPLATE_PARM, "template_template_parm", 't', 0)
/* A type designated by 'typename T::t'. */ /* A type designated by 'typename T::t'. */
DEFTREECODE (TYPENAME_TYPE, "typename_type", 't', 0) 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. /* A thunk is a stub function.
Thunks are used to implement multiple inheritance: Thunks are used to implement multiple inheritance:
...@@ -179,3 +216,9 @@ DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1) ...@@ -179,3 +216,9 @@ DEFTREECODE (AMBIG_CONV, "ambig_conv", 'e', 1)
DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1) DEFTREECODE (RVALUE_CONV, "rvalue_conv", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0) DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/*
Local variables:
mode:c
End:
*/
...@@ -47,6 +47,17 @@ typedef struct ...@@ -47,6 +47,17 @@ typedef struct
int new_type_flag; int new_type_flag;
} flagged_type_tree; } 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 /* To identify to the debug emitters if it should pay attention to the
flag `-Wtemplate-debugging'. */ flag `-Wtemplate-debugging'. */
#define HAVE_TEMPLATES 1 #define HAVE_TEMPLATES 1
...@@ -1340,6 +1351,18 @@ extern int flag_new_for_scope; ...@@ -1340,6 +1351,18 @@ extern int flag_new_for_scope;
#define TYPE_WAS_ANONYMOUS(NODE) (TYPE_LANG_SPECIFIC (NODE)->type_flags.was_anonymous) #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. */ /* 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)) #define DECL_FRIENDLIST(NODE) (DECL_INITIAL (NODE))
/* The DECL_ACCESS is used to record under which context /* The DECL_ACCESS is used to record under which context
...@@ -1352,6 +1375,17 @@ extern int flag_new_for_scope; ...@@ -1352,6 +1375,17 @@ extern int flag_new_for_scope;
#define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL) #define SET_DECL_REFERENCE_SLOT(NODE,VAL) ((NODE)->decl.arguments=VAL)
/* Accessor macros for C++ template decl nodes. */ /* 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_TEMPLATE_PARMS(NODE) DECL_ARGUMENTS(NODE)
#define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \ #define DECL_INNERMOST_TEMPLATE_PARMS(NODE) \
INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE)) INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (NODE))
...@@ -1374,6 +1408,12 @@ extern int flag_new_for_scope; ...@@ -1374,6 +1408,12 @@ extern int flag_new_for_scope;
(TREE_CODE (NODE) == TEMPLATE_DECL \ (TREE_CODE (NODE) == TEMPLATE_DECL \
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == FUNCTION_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) \ #define PRIMARY_TEMPLATE_P(NODE) \
(TREE_TYPE (DECL_INNERMOST_TEMPLATE_PARMS (NODE)) == (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 */ ...@@ -1934,24 +1974,27 @@ extern tree current_class_type; /* _TYPE: the type of the current class */
#define WANT_ARITH (WANT_INT | WANT_FLOAT) #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_NAME(LIST) (TREE_PURPOSE (LIST))
#define FRIEND_DECLS(LIST) (TREE_VALUE (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 /* These macros are for accessing the fields of TEMPLATE_TYPE_PARM
and TEMPLATE_TEMPLATE_PARM nodes. */ and TEMPLATE_TEMPLATE_PARM nodes. */
#define TEMPLATE_TYPE_IDX(NODE) TREE_INT_CST_LOW (TYPE_FIELDS (NODE)) #define TEMPLATE_TYPE_PARM_INDEX(NODE) (TYPE_FIELDS (NODE))
#define TEMPLATE_TYPE_LEVEL(NODE) TREE_INT_CST_HIGH (TYPE_FIELDS (NODE)) #define TEMPLATE_TYPE_IDX(NODE) \
#define TEMPLATE_TYPE_SET_INFO(NODE,I,L) \ (TEMPLATE_PARM_IDX (TEMPLATE_TYPE_PARM_INDEX (NODE)))
(TYPE_FIELDS (NODE) = build_int_2 (I, L)) #define TEMPLATE_TYPE_LEVEL(NODE) \
/* These macros are for accessing the fields of TEMPLATE_CONST_PARM nodes. */ (TEMPLATE_PARM_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_CONST_IDX(NODE) (TREE_INT_CST_LOW(NODE)) #define TEMPLATE_TYPE_ORIG_LEVEL(NODE) \
#define TEMPLATE_CONST_LEVEL(NODE) (TREE_INT_CST_HIGH(NODE)) (TEMPLATE_PARM_ORIG_LEVEL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_CONST_SET_INFO(NODE,I,L) \ #define TEMPLATE_TYPE_DECL(NODE) \
(TEMPLATE_CONST_IDX (NODE) = I, TEMPLATE_CONST_LEVEL (NODE) = L) (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
/* in lex.c */ /* in lex.c */
/* Indexed by TREE_CODE, these tables give C-looking names to /* Indexed by TREE_CODE, these tables give C-looking names to
...@@ -2336,8 +2379,8 @@ extern tree tsubst PROTO ((tree, tree, int, tree)); ...@@ -2336,8 +2379,8 @@ extern tree tsubst PROTO ((tree, tree, int, tree));
extern tree tsubst_expr 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_copy PROTO ((tree, tree, int, tree));
extern tree tsubst_chain PROTO((tree, tree)); extern tree tsubst_chain PROTO((tree, tree));
extern void begin_member_template_processing PROTO((tree)); extern void maybe_begin_member_template_processing PROTO((tree));
extern void end_member_template_processing PROTO((void)); extern void maybe_end_member_template_processing PROTO((tree));
extern tree finish_member_template_decl PROTO((tree, tree)); extern tree finish_member_template_decl PROTO((tree, tree));
extern void begin_template_parm_list PROTO((void)); extern void begin_template_parm_list PROTO((void));
extern void begin_specialization PROTO((void)); extern void begin_specialization PROTO((void));
...@@ -2382,6 +2425,7 @@ extern int more_specialized_class PROTO((tree, tree)); ...@@ -2382,6 +2425,7 @@ extern int more_specialized_class PROTO((tree, tree));
extern void do_pushlevel PROTO((void)); extern void do_pushlevel PROTO((void));
extern int is_member_template PROTO((tree)); extern int is_member_template PROTO((tree));
extern int comp_template_parms PROTO((tree, tree)); extern int comp_template_parms PROTO((tree, tree));
extern int template_class_depth PROTO((tree));
extern int processing_specialization; extern int processing_specialization;
extern int processing_explicit_instantiation; extern int processing_explicit_instantiation;
......
...@@ -2311,47 +2311,15 @@ decls_match (newdecl, olddecl) ...@@ -2311,47 +2311,15 @@ decls_match (newdecl, olddecl)
else if (TREE_CODE (newdecl) == TEMPLATE_DECL else if (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (olddecl) == TEMPLATE_DECL) && TREE_CODE (olddecl) == TEMPLATE_DECL)
{ {
tree newargs = DECL_TEMPLATE_PARMS (newdecl); if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
tree oldargs = DECL_TEMPLATE_PARMS (olddecl); DECL_TEMPLATE_PARMS (olddecl)))
int i; return 0;
/* Run through all the levels of template parameters, checking if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
that they match. */ types_match = 1;
while (newargs && oldargs) else
{ types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
int len = TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS (newargs)); DECL_TEMPLATE_RESULT (newdecl));
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));
} }
else else
{ {
...@@ -2760,6 +2728,7 @@ duplicate_decls (newdecl, olddecl) ...@@ -2760,6 +2728,7 @@ duplicate_decls (newdecl, olddecl)
cp_error ("invalid redeclaration of %D", newdecl); cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl)); TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl); DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
} }
return 1; return 1;
} }
...@@ -4504,7 +4473,10 @@ make_implicit_typename (context, t) ...@@ -4504,7 +4473,10 @@ make_implicit_typename (context, t)
If PREFER_TYPE is > 0, we prefer TYPE_DECLs. If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
If PREFER_TYPE is -2, we're being called from yylex(). (UGLY) 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 static tree
lookup_name_real (name, prefer_type, nonclass) lookup_name_real (name, prefer_type, nonclass)
...@@ -7461,8 +7433,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -7461,8 +7433,15 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
if (friendp && if (friendp &&
TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR) 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. */ /* Caller will do the rest of this. */
if (check < 0) if (check < 0)
...@@ -7485,8 +7464,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -7485,8 +7464,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = check_explicit_specialization (orig_declarator, decl, decl = check_explicit_specialization (orig_declarator, decl,
template_count, template_count,
funcdef_flag ? 2 : 2 * (funcdef_flag != 0) +
(friendp ? 3 : 0)); 4 * (friendp != 0));
if (check) if (check)
{ {
...@@ -7532,8 +7511,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals, ...@@ -7532,8 +7511,8 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
decl = check_explicit_specialization (orig_declarator, decl, decl = check_explicit_specialization (orig_declarator, decl,
template_count, template_count,
funcdef_flag ? 2 : 2 * (funcdef_flag != 0) +
(friendp ? 3 : 0)); 4 * (friendp != 0));
if (ctype != NULL_TREE && check) if (ctype != NULL_TREE && check)
{ {
...@@ -7952,10 +7931,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist) ...@@ -7952,10 +7931,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
if (TREE_CODE (fns) == IDENTIFIER_NODE) if (TREE_CODE (fns) == IDENTIFIER_NODE)
dname = fns; dname = fns;
else if (really_overloaded_fn (fns)) else if (is_overloaded_fn (fns))
dname = DECL_NAME (get_first_fn (fns)); dname = DECL_NAME (get_first_fn (fns));
else else
dname = DECL_NAME (fns); my_friendly_abort (0);
} }
/* fall through */ /* fall through */
......
...@@ -1431,19 +1431,22 @@ check_classfn (ctype, function) ...@@ -1431,19 +1431,22 @@ check_classfn (ctype, function)
if (fn_name == DECL_NAME (*methods)) if (fn_name == DECL_NAME (*methods))
{ {
got_it: got_it:
fndecl = *methods; for (fndecl = *methods; fndecl != NULL_TREE;
while (fndecl) 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; return fndecl;
#if 0
/* This doesn't work for static member functions that are /* We cannot simply call decls_match because this
pretending to be methods. */ doesn't work for static member functions that are
/* We have to do more extensive argument checking here, as pretending to be methods, and because the name
the name may have been changed by asm("new_name"). */ may have been changed by asm("new_name"). */
if (decls_match (function, fndecl))
return fndecl;
#else
if (DECL_NAME (function) == DECL_NAME (fndecl)) if (DECL_NAME (function) == DECL_NAME (fndecl))
{ {
tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function)); tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
...@@ -1471,8 +1474,6 @@ check_classfn (ctype, function) ...@@ -1471,8 +1474,6 @@ check_classfn (ctype, function)
templates = templates =
scratch_tree_cons (NULL_TREE, fndecl, templates); scratch_tree_cons (NULL_TREE, fndecl, templates);
} }
#endif
fndecl = DECL_CHAIN (fndecl);
} }
break; /* loser */ break; /* loser */
} }
......
...@@ -856,7 +856,7 @@ dump_decl (t, v) ...@@ -856,7 +856,7 @@ dump_decl (t, v)
case CONST_DECL: case CONST_DECL:
if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE) if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
|| (DECL_INITIAL (t) && || (DECL_INITIAL (t) &&
TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM)) TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
goto general; goto general;
else if (DECL_NAME (t)) else if (DECL_NAME (t))
dump_decl (DECL_NAME (t), v); dump_decl (DECL_NAME (t), v);
...@@ -1527,33 +1527,12 @@ dump_expr (t, nop) ...@@ -1527,33 +1527,12 @@ dump_expr (t, nop)
break; break;
} }
case TEMPLATE_CONST_PARM: case TEMPLATE_PARM_INDEX:
{ {
int l = current_template_parms ? int l = current_template_parms ?
list_length (current_template_parms) : 0; list_length (current_template_parms) : 0;
if (l >= TEMPLATE_CONST_LEVEL (t)) dump_decl (TEMPLATE_PARM_DECL (t), -1);
{
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 (">");
}
} }
break; break;
......
...@@ -33,22 +33,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -33,22 +33,7 @@ Boston, MA 02111-1307, USA. */
static void add_friend PROTO((tree, tree)); static void add_friend PROTO((tree, tree));
static void add_friends PROTO((tree, tree, tree)); static void add_friends PROTO((tree, tree, tree));
/* Friend data structures: /* Friend data structures are described in cp-tree.h. */
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. */
int int
is_friend (type, supplicant) is_friend (type, supplicant)
...@@ -83,6 +68,31 @@ is_friend (type, supplicant) ...@@ -83,6 +68,31 @@ is_friend (type, supplicant)
{ {
if (ctype == TREE_PURPOSE (friends)) if (ctype == TREE_PURPOSE (friends))
return 1; 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), if (comptypes (TREE_TYPE (supplicant),
TREE_TYPE (TREE_VALUE (friends)), 1)) TREE_TYPE (TREE_VALUE (friends)), 1))
return 1; return 1;
...@@ -302,9 +312,15 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -302,9 +312,15 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
tree quals; tree quals;
int funcdef_flag; int funcdef_flag;
{ {
int is_friend_template = 0;
/* Every decl that gets here is a friend of something. */ /* Every decl that gets here is a friend of something. */
DECL_FRIEND_P (decl) = 1; 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) if (ctype)
{ {
tree cname = TYPE_NAME (ctype); tree cname = TYPE_NAME (ctype);
...@@ -319,18 +335,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -319,18 +335,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
/* This will set up DECL_ARGUMENTS for us. */ /* This will set up DECL_ARGUMENTS for us. */
grokclassfn (ctype, cname, decl, flags, quals); 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); decl = check_classfn (ctype, decl);
if (TREE_TYPE (decl) != error_mark_node) 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); add_friend (current_class_type, decl);
else else
{ cp_error ("member `%D' declared as friend before type `%T' defined",
cp_error ("member `%D' declared as friend before type `%T' defined", decl, ctype);
decl, ctype);
}
} }
} }
else else
...@@ -386,10 +405,21 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -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 /* We can call pushdecl here, because the TREE_CHAIN of this
FUNCTION_DECL is not needed for other purposes. Don't do this FUNCTION_DECL is not needed for other purposes. Don't do this
for a template instantiation. */ for a template instantiation. */
decl = pushdecl (decl); 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)) && current_template_parms && uses_template_parms (decl))
{ {
static int explained; static int explained;
...@@ -405,8 +435,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag) ...@@ -405,8 +435,8 @@ do_friend (ctype, declarator, decl, parmdecls, flags, quals, funcdef_flag)
} }
make_decl_rtl (decl, NULL_PTR, 1); 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; DECL_FRIEND_P (decl) = 1;
} }
else else
......
...@@ -1684,14 +1684,14 @@ as a @samp{Z} followed by the encoding of the type. ...@@ -1684,14 +1684,14 @@ as a @samp{Z} followed by the encoding of the type.
A function template specialization (either an instantiation or an A function template specialization (either an instantiation or an
explicit specialization) is encoded by an @samp{H} followed by the explicit specialization) is encoded by an @samp{H} followed by the
encoding of the template parameters, as described above, followed by encoding of the template parameters, as described above, followed by an
an @samp{_}, the encoding of the argument types template function (not the @samp{_}, the encoding of the argument types to the template function
specialization), another @samp{_}, and the return type. (Like the (not the specialization), another @samp{_}, and the return type. (Like
argument types, the return type is the return type of the function the argument types, the return type is the return type of the function
template, not the specialization.) Template parameters in the argument template, not the specialization.) Template parameters in the argument
and return types are encoded by an @samp{X} for type parameters, or a 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 @samp{Y} for constant parameters, an index indicating their position
in the template parameter list declaration. in the template parameter list declaration, and their template depth.
@subsection Arrays @subsection Arrays
......
...@@ -1213,8 +1213,7 @@ do_pending_inlines () ...@@ -1213,8 +1213,7 @@ do_pending_inlines ()
context = hack_decl_function_context (t->fndecl); context = hack_decl_function_context (t->fndecl);
if (context) if (context)
push_cp_function_context (context); push_cp_function_context (context);
if (is_member_template (t->fndecl)) maybe_begin_member_template_processing (t->fndecl);
begin_member_template_processing (t->fndecl);
if (t->len > 0) if (t->len > 0)
{ {
feed_input (t->buf, t->len); feed_input (t->buf, t->len);
...@@ -1252,8 +1251,7 @@ process_next_inline (t) ...@@ -1252,8 +1251,7 @@ process_next_inline (t)
tree context; tree context;
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t); struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
context = hack_decl_function_context (i->fndecl); context = hack_decl_function_context (i->fndecl);
if (is_member_template (i->fndecl)) maybe_end_member_template_processing (i->fndecl);
end_member_template_processing ();
if (context) if (context)
pop_cp_function_context (context); pop_cp_function_context (context);
i = i->next; i = i->next;
...@@ -1276,8 +1274,7 @@ process_next_inline (t) ...@@ -1276,8 +1274,7 @@ process_next_inline (t)
context = hack_decl_function_context (i->fndecl); context = hack_decl_function_context (i->fndecl);
if (context) if (context)
push_cp_function_context (context); push_cp_function_context (context);
if (is_member_template (i->fndecl)) maybe_begin_member_template_processing (i->fndecl);
begin_member_template_processing (i->fndecl);
feed_input (i->buf, i->len); feed_input (i->buf, i->len);
lineno = i->lineno; lineno = i->lineno;
input_filename = i->filename; input_filename = i->filename;
...@@ -1891,8 +1888,7 @@ do_pending_defargs () ...@@ -1891,8 +1888,7 @@ do_pending_defargs ()
{ {
push_nested_class (TREE_PURPOSE (defarg_fns), 1); push_nested_class (TREE_PURPOSE (defarg_fns), 1);
pushlevel (0); pushlevel (0);
if (is_member_template (defarg_fn)) maybe_begin_member_template_processing (defarg_fn);
begin_member_template_processing (defarg_fn);
if (TREE_CODE (defarg_fn) == FUNCTION_DECL) if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
{ {
...@@ -1920,8 +1916,7 @@ do_pending_defargs () ...@@ -1920,8 +1916,7 @@ do_pending_defargs ()
return; return;
} }
if (is_member_template (defarg_fn)) maybe_end_member_template_processing (defarg_fn);
end_member_template_processing ();
poplevel (0, 0, 0); poplevel (0, 0, 0);
pop_nested_class (1); pop_nested_class (1);
} }
...@@ -2946,7 +2941,7 @@ do_identifier (token, parsing) ...@@ -2946,7 +2941,7 @@ do_identifier (token, parsing)
} }
if (! processing_template_decl if (! processing_template_decl
|| (DECL_INITIAL (id) || (DECL_INITIAL (id)
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM)) && TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
id = DECL_INITIAL (id); id = DECL_INITIAL (id);
} }
else else
......
...@@ -602,6 +602,24 @@ build_overload_int (value, in_template) ...@@ -602,6 +602,24 @@ build_overload_int (value, in_template)
icat (TREE_INT_CST_LOW (value)); 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 static void
build_overload_value (type, value, in_template) build_overload_value (type, value, in_template)
tree type, value; tree type, value;
...@@ -619,11 +637,9 @@ build_overload_value (type, value, in_template) ...@@ -619,11 +637,9 @@ build_overload_value (type, value, in_template)
numeric_output_need_bar = 0; numeric_output_need_bar = 0;
} }
if (TREE_CODE (value) == TEMPLATE_CONST_PARM) if (TREE_CODE (value) == TEMPLATE_PARM_INDEX)
{ {
OB_PUTC ('Y'); build_mangled_template_parm_index ("Y", value);
build_underscore_int (TEMPLATE_CONST_IDX (value));
build_underscore_int (TEMPLATE_CONST_LEVEL (value));
return; return;
} }
...@@ -761,13 +777,19 @@ build_overload_value (type, value, in_template) ...@@ -761,13 +777,19 @@ build_overload_value (type, value, in_template)
sorry ("template instantiation with pointer to method that is too complex"); sorry ("template instantiation with pointer to method that is too complex");
return; return;
} }
if (TREE_CODE (value) == INTEGER_CST if (TREE_CODE (value) == INTEGER_CST)
|| TREE_CODE (value) == TEMPLATE_CONST_PARM)
{ {
build_overload_int (value, in_template); build_overload_int (value, in_template);
numeric_output_need_bar = 1; numeric_output_need_bar = 1;
return; 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); value = TREE_OPERAND (value, 0);
if (TREE_CODE (value) == VAR_DECL) if (TREE_CODE (value) == VAR_DECL)
{ {
...@@ -1374,33 +1396,27 @@ process_overload_item (parmtype, extra_Gcode) ...@@ -1374,33 +1396,27 @@ process_overload_item (parmtype, extra_Gcode)
declaration. */ declaration. */
if (CLASSTYPE_TEMPLATE_INFO (parmtype)) if (CLASSTYPE_TEMPLATE_INFO (parmtype))
{ {
OB_PUTC ('t'); build_mangled_template_parm_index ("tzX",
OB_PUTC ('z'); TEMPLATE_TYPE_PARM_INDEX
OB_PUTC ('X'); (parmtype));
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype)); build_template_parm_names
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype)); (DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
CLASSTYPE_TI_ARGS (parmtype));
build_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (parmtype)),
CLASSTYPE_TI_ARGS (parmtype));
} }
else else
{ {
OB_PUTC ('Z'); build_mangled_template_parm_index ("ZzX",
OB_PUTC ('z'); TEMPLATE_TYPE_PARM_INDEX
OB_PUTC ('X'); (parmtype));
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype)); build_template_template_parm_names
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype)); (DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
build_template_template_parm_names (
DECL_INNERMOST_TEMPLATE_PARMS (TYPE_STUB_DECL (parmtype)));
} }
break; break;
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
OB_PUTC ('X'); build_mangled_template_parm_index ("X",
build_underscore_int (TEMPLATE_TYPE_IDX (parmtype)); TEMPLATE_TYPE_PARM_INDEX
build_underscore_int (TEMPLATE_TYPE_LEVEL (parmtype)); (parmtype));
break; break;
case TYPENAME_TYPE: case TYPENAME_TYPE:
......
...@@ -66,9 +66,13 @@ print_lang_type (file, node, indent) ...@@ -66,9 +66,13 @@ print_lang_type (file, node, indent)
register tree node; register tree node;
int indent; 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; return;
} }
......
...@@ -794,7 +794,17 @@ static tree ...@@ -794,7 +794,17 @@ static tree
lookup_field_1 (type, name) lookup_field_1 (type, name)
tree 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 #ifdef GATHER_STATISTICS
n_calls_lookup_field_1++; n_calls_lookup_field_1++;
...@@ -804,6 +814,7 @@ lookup_field_1 (type, name) ...@@ -804,6 +814,7 @@ lookup_field_1 (type, name)
#ifdef GATHER_STATISTICS #ifdef GATHER_STATISTICS
n_fields_searched++; n_fields_searched++;
#endif /* GATHER_STATISTICS */ #endif /* GATHER_STATISTICS */
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (field)) == 'd', 0);
if (DECL_NAME (field) == NULL_TREE if (DECL_NAME (field) == NULL_TREE
&& TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
{ {
......
...@@ -329,7 +329,7 @@ yylex () ...@@ -329,7 +329,7 @@ yylex ()
} }
} }
else else
lastiddecl = trrr; lastiddecl = NULL_TREE;
got_scope = NULL_TREE; got_scope = NULL_TREE;
/* and fall through to... */ /* and fall through to... */
case IDENTIFIER_DEFN: case IDENTIFIER_DEFN:
......
...@@ -2070,9 +2070,9 @@ cp_tree_equal (t1, t2) ...@@ -2070,9 +2070,9 @@ cp_tree_equal (t1, t2)
case FUNCTION_DECL: case FUNCTION_DECL:
return 0; return 0;
case TEMPLATE_CONST_PARM: case TEMPLATE_PARM_INDEX:
return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2) return TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
&& TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2); && TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2);
case SIZEOF_EXPR: case SIZEOF_EXPR:
case ALIGNOF_EXPR: case ALIGNOF_EXPR:
......
...@@ -2367,11 +2367,17 @@ build_x_function_call (function, params, decl) ...@@ -2367,11 +2367,17 @@ build_x_function_call (function, params, decl)
|| TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == METHOD_TYPE
|| TYPE_PTRMEMFUNC_P (type)); || TYPE_PTRMEMFUNC_P (type));
if (TREE_CODE (function) == FUNCTION_DECL if ((TREE_CODE (function) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (function)) && DECL_STATIC_FUNCTION_P (function))
|| (TREE_CODE (function) == TEMPLATE_DECL
&& DECL_STATIC_FUNCTION_P (DECL_RESULT (function))))
return build_member_call return build_member_call
(DECL_CONTEXT (function), DECL_NAME (function), params); (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. */ /* Handle methods, friends, and overloaded functions, respectively. */
if (is_method) if (is_method)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment