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:
parent
9e89df5017
commit
f84b4be9a7
102
gcc/cp/ChangeLog
102
gcc/cp/ChangeLog
@ -1,3 +1,105 @@
|
||||
Mon Feb 23 03:04:14 1998 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* typeck.c (build_x_function_call): Handle static member function
|
||||
templates like non-templates. Handle friend templates like normal
|
||||
function templates.
|
||||
* pt.c (tsubst, *_PARM): Don't use orig_level.
|
||||
(get_bindings): Don't call add_to_template_args.
|
||||
(instantiate_template): Likewise.
|
||||
(tsubst, FUNCTION_DECL): Call add_to_template_args as appropriate.
|
||||
* ptree.c (print_lang_type): Print index/level for template parms.
|
||||
|
||||
Mon Feb 23 02:52:29 1998 Mark Mitchell <mmitchell@usa.net>
|
||||
|
||||
* Make-lang.in (cc1plus): Note that cc1plus depends on
|
||||
cp/cp-tree.h and cp/cp-tree.def.
|
||||
|
||||
* cp-tree.def (TEMPLATE_CONST_PARM): Remove.
|
||||
(TEMPLATE_PARM_INDEX): New tree code, used to indicate a
|
||||
position in a template parameter list.
|
||||
* cp-tree.h (template_parm_index): New structure, used as the tree
|
||||
structure for a TEMPLATE_PARM_INDEX.
|
||||
(TEMPLATE_PARM_IDX): New macro.
|
||||
(TEMPLATE_PARM_LEVEL): Likewise.
|
||||
(TEMPLATE_PARM_DESCENDANTS): Likewise.
|
||||
(TEMPLATE_PARM_ORIG_LEVEL): Likewise.
|
||||
(TEMPLATE_PARM_DECL): Likewise.
|
||||
(TEMPLATE_TYPE_PARM_INDEX): Likewise.
|
||||
(TEMPLATE_TYPE_ORIG_LEVEL): Likewise.
|
||||
(TEMPLATE_TYPE_DECL): Likewise.
|
||||
(TEMPLATE_CONST_IDX): Remove.
|
||||
(TEMPLATE_CONST_LEVEL): Likewise.
|
||||
(TEMPLATE_CONST_SET_INFO): Likewise.
|
||||
(TEMPLATE_TYPE_SET_INFO): Likewise.
|
||||
(TEMPLATE_TYPE_IDX): Redefine in terms of TEMPLATE_PARM_INDEX
|
||||
node.
|
||||
(TEMPLATE_TYPE_LEVEL): Likewise.
|
||||
* decl.c (decls_match): Call comp_template_parms, rather than
|
||||
expanding it inline.
|
||||
(duplicate_decls): If two template declarations are being merged,
|
||||
then their TEMPLATE_INFOs should be merged as well.
|
||||
(grokfndecl): Save template-id information when declaring a friend
|
||||
with explicit template arguments. Pass arguments to
|
||||
check_explicit_specialization via correct convention; at some
|
||||
point check_explicit_specialization changed, but these call-sites
|
||||
did not.
|
||||
(grokdeclarator): Tidy up slightly.
|
||||
* decl2.c (check_classfn): Tidy up slightly. Don't assume that
|
||||
two template functions with the same DECL_ASSEMBLER_NAME the same,
|
||||
since the names are not yet mangled.
|
||||
* error.c (dump_decl): Use TEMPLATE_PARM_INDEX instead of
|
||||
TEMPLATE_CONST_PARM.
|
||||
(dump_expr): Likewise. Use the TEMPLATE_PARM_DECL to get at the
|
||||
decl for a non-type parameter, rather than printing `<tparm ...>'.
|
||||
* friend.c (is_friend): Handle TEMPLATE_DECL friends.
|
||||
(do_friend): Deal with template friends.
|
||||
* lex.c (do_pending_inlines): Call
|
||||
maybe_begin_member_template_processing, rather than
|
||||
conditionally calling begin_member_template_processing.
|
||||
(process_next_inline): Likewise. Call
|
||||
maybe_end_member_template_processing, rather than
|
||||
conditionally calling end_member_template_processing.
|
||||
(do_pending_defargs): Likewise.
|
||||
(do_identifier): Use TEMPLATE_PARM_INDEX instead of
|
||||
TEMPLATE_CONST_PARM.
|
||||
* method.c (build_mangled_template_parm_index): New function.
|
||||
(build_overload_value): Use it.
|
||||
(build_overload_name): Likewise.
|
||||
* pt.c (finish_member_template_decl): Allow friend declarations.
|
||||
(template_class_depth): New function.
|
||||
(is_member_template): Rename, and modify, to become...
|
||||
(is_member_or_friend_template): New function.
|
||||
(end_member_template_processing): Rename, and modify, to become...
|
||||
(maybe_end_member_template_processing).
|
||||
(build_template_parm_index): New function.
|
||||
(reduce_template_parm_level): New function.
|
||||
(process_template_parm): Modify to use build_template_parm_index.
|
||||
(current_template_args): Change name to current_template_parms.
|
||||
(push_template_decl): Deal with friend templates.
|
||||
(uses_template_parms): Use TEMPLATE_PARM_INDEX instead of
|
||||
TEMPLATE_CONST_PARM.
|
||||
(tsubst_friend_function): New function.
|
||||
(instantiate_class_template): Generate the DECL_FRIENDLIST
|
||||
for a new instantiation by using tsubst_friend_function rather
|
||||
than just tsubst.
|
||||
(tsubst): Don't tsubst into a type which is a TEMPLATE_DECL.
|
||||
Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM, and the
|
||||
appropriate new macros. Use reduce_template_parm_level to
|
||||
generate lower-level template parameters. Handle tsubst'ing into
|
||||
TEMPLATE_DECLS that declare TEMPLATE_TEMPLATE_PARMS. Don't forget
|
||||
to tsubst the DECL_CONTEXT and DECL_CLASS_CONTEXT of newly created
|
||||
templates. Similarly for the template parameters for a new
|
||||
template.
|
||||
(tsubst_copy): Tidy up slightly. Use TEMPLATE_PARM_INDEX instead
|
||||
of TEMPLATE_CONST_PARM. Handle TYPE_DECLs by tsubsting into them.
|
||||
(unify): Use TEMPLATE_PARM_INDEX instead of TEMPLATE_CONST_PARM.
|
||||
(get_bindings): Call add_to_template_args if necessary.
|
||||
(instantiate_decl): Handle instantiations of friend templates.
|
||||
* search.c (lookup_field_1): Don't treat the TYPE_FIELDS of a
|
||||
TEMPLATE_TYPE_PARM as a list of fields; it's not!
|
||||
* spew.c (yylex): Do a little manual constant propogation to
|
||||
clarify the code.
|
||||
|
||||
Sun Feb 22 19:53:29 1998 Jeffrey A Law (law@cygnus.com)
|
||||
|
||||
* error.c: Include sys/types.h.
|
||||
|
@ -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:
|
||||
|
@ -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:
|
||||
*/
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
17
gcc/cp/lex.c
17
gcc/cp/lex.c
@ -1213,8 +1213,7 @@ do_pending_inlines ()
|
||||
context = hack_decl_function_context (t->fndecl);
|
||||
if (context)
|
||||
push_cp_function_context (context);
|
||||
if (is_member_template (t->fndecl))
|
||||
begin_member_template_processing (t->fndecl);
|
||||
maybe_begin_member_template_processing (t->fndecl);
|
||||
if (t->len > 0)
|
||||
{
|
||||
feed_input (t->buf, t->len);
|
||||
@ -1252,8 +1251,7 @@ process_next_inline (t)
|
||||
tree context;
|
||||
struct pending_inline *i = (struct pending_inline *) TREE_PURPOSE (t);
|
||||
context = hack_decl_function_context (i->fndecl);
|
||||
if (is_member_template (i->fndecl))
|
||||
end_member_template_processing ();
|
||||
maybe_end_member_template_processing (i->fndecl);
|
||||
if (context)
|
||||
pop_cp_function_context (context);
|
||||
i = i->next;
|
||||
@ -1276,8 +1274,7 @@ process_next_inline (t)
|
||||
context = hack_decl_function_context (i->fndecl);
|
||||
if (context)
|
||||
push_cp_function_context (context);
|
||||
if (is_member_template (i->fndecl))
|
||||
begin_member_template_processing (i->fndecl);
|
||||
maybe_begin_member_template_processing (i->fndecl);
|
||||
feed_input (i->buf, i->len);
|
||||
lineno = i->lineno;
|
||||
input_filename = i->filename;
|
||||
@ -1891,8 +1888,7 @@ do_pending_defargs ()
|
||||
{
|
||||
push_nested_class (TREE_PURPOSE (defarg_fns), 1);
|
||||
pushlevel (0);
|
||||
if (is_member_template (defarg_fn))
|
||||
begin_member_template_processing (defarg_fn);
|
||||
maybe_begin_member_template_processing (defarg_fn);
|
||||
|
||||
if (TREE_CODE (defarg_fn) == FUNCTION_DECL)
|
||||
{
|
||||
@ -1920,8 +1916,7 @@ do_pending_defargs ()
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_member_template (defarg_fn))
|
||||
end_member_template_processing ();
|
||||
maybe_end_member_template_processing (defarg_fn);
|
||||
poplevel (0, 0, 0);
|
||||
pop_nested_class (1);
|
||||
}
|
||||
@ -2946,7 +2941,7 @@ do_identifier (token, parsing)
|
||||
}
|
||||
if (! processing_template_decl
|
||||
|| (DECL_INITIAL (id)
|
||||
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_CONST_PARM))
|
||||
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
|
||||
id = DECL_INITIAL (id);
|
||||
}
|
||||
else
|
||||
|
@ -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:
|
||||
|
617
gcc/cp/pt.c
617
gcc/cp/pt.c
@ -86,6 +86,7 @@ static int type_unification_real PROTO((tree, tree *, tree, tree, int*,
|
||||
static void note_template_header PROTO((int));
|
||||
static tree maybe_fold_nontype_arg PROTO((tree));
|
||||
static tree convert_nontype_argument PROTO((tree, tree));
|
||||
static int is_member_or_friend_template PROTO((tree, int));
|
||||
|
||||
/* Do any processing required when DECL (a member template declaration
|
||||
using TEMPLATE_PARAMETERS as its innermost parameter list) is
|
||||
@ -109,22 +110,51 @@ finish_member_template_decl (template_parameters, decl)
|
||||
return DECL_TI_TEMPLATE (decl);
|
||||
}
|
||||
|
||||
if (decl)
|
||||
return decl;
|
||||
|
||||
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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -329,7 +329,7 @@ yylex ()
|
||||
}
|
||||
}
|
||||
else
|
||||
lastiddecl = trrr;
|
||||
lastiddecl = NULL_TREE;
|
||||
got_scope = NULL_TREE;
|
||||
/* and fall through to... */
|
||||
case IDENTIFIER_DEFN:
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user