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