From ea4e080b25061c49143467d14d6438996b671987 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 26 May 1998 23:17:56 +0000 Subject: friend.c (is_friend): Use comptypes, rather than == to compare types. * friend.c (is_friend): Use comptypes, rather than == to compare types. Modify for new representation of template friends. (make_friend_class): Likewise. * pt.c (tsubst_friend_class): Undo 1998-05-21 change. Tweak. (instantiate_class_template): Deal with template friends. From-SVN: r20080 --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/cp-tree.h | 4 ++- gcc/cp/friend.c | 37 ++++++++++++++++++---------- gcc/testsuite/g++.old-deja/g++.pt/friend20.C | 10 ++++++++ gcc/testsuite/g++.old-deja/g++.pt/friend21.C | 30 ++++++++++++++++++++++ 5 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend20.C create mode 100644 gcc/testsuite/g++.old-deja/g++.pt/friend21.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 64fc782..f1249c8 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 1998-05-26 Mark Mitchell + * friend.c (is_friend): Use comptypes, rather than == to compare + types. Modify for new representation of template friends. + (make_friend_class): Likewise. + * pt.c (tsubst_friend_class): Undo 1998-05-21 change. Tweak. + (instantiate_class_template): Deal with template friends. + * decl.c (store_parm_decls): Remove redundant call to expand_main_function. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index f65fbd4..129047a 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -905,7 +905,9 @@ struct lang_type /* Same, but cache a list whose value is the binfo of this type. */ #define CLASSTYPE_BINFO_AS_LIST(NODE) (TYPE_LANG_SPECIFIC(NODE)->binfo_as_list) -/* A list of class types with which this type is a friend. */ +/* A list of class types with which this type is a friend. The + TREE_VALUE is normally a TYPE, but will be a TEMPLATE_DECL in the + case of a template friend. */ #define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes) #ifdef MI_MATRIX diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c index 6f40f0a..8adeb60 100644 --- a/gcc/cp/friend.c +++ b/gcc/cp/friend.c @@ -64,7 +64,7 @@ is_friend (type, supplicant) tree friends = TREE_VALUE (list); for (; friends ; friends = TREE_CHAIN (friends)) { - if (ctype == TREE_PURPOSE (friends)) + if (comptypes (ctype, TREE_PURPOSE (friends), 1)) return 1; if (TREE_VALUE (friends) == NULL_TREE) @@ -102,10 +102,9 @@ is_friend (type, supplicant) { tree t = TREE_VALUE (list); - if (supplicant == t - || (CLASSTYPE_IS_TEMPLATE (t) - && is_specialization_of (TYPE_MAIN_DECL (supplicant), - CLASSTYPE_TI_TEMPLATE (t)))) + if (TREE_CODE (t) == TEMPLATE_DECL ? + is_specialization_of (TYPE_MAIN_DECL (supplicant), t) : + comptypes (supplicant, t, 1)) return 1; } } @@ -241,6 +240,7 @@ make_friend_class (type, friend_type) tree type, friend_type; { tree classes; + int is_template_friend; if (IS_SIGNATURE (type)) { @@ -253,25 +253,36 @@ make_friend_class (type, friend_type) IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); return; } - /* If the TYPE is a template then it makes sense for it to be - friends with itself; this means that each instantiation is - friends with all other instantiations. */ - if (type == friend_type && !CLASSTYPE_IS_TEMPLATE (type)) + if (processing_template_decl > template_class_depth (type)) + /* If the TYPE is a template then it makes sense for it to be + friends with itself; this means that each instantiation is + friends with all other instantiations. */ + is_template_friend = 1; + else if (comptypes (type, friend_type, 1)) { pedwarn ("class `%s' is implicitly friends with itself", TYPE_NAME_STRING (type)); return; } + else + is_template_friend = 0; GNU_xref_hier (TYPE_NAME_STRING (type), TYPE_NAME_STRING (friend_type), 0, 0, 1); + if (is_template_friend) + friend_type = CLASSTYPE_TI_TEMPLATE (friend_type); + classes = CLASSTYPE_FRIEND_CLASSES (type); - while (classes && TREE_VALUE (classes) != friend_type) + while (classes + /* Stop if we find the same type on the list. */ + && !(TREE_CODE (TREE_VALUE (classes)) == TEMPLATE_DECL ? + friend_type == TREE_VALUE (classes) : + comptypes (TREE_VALUE (classes), friend_type, 1))) classes = TREE_CHAIN (classes); - if (classes) - warning ("class `%s' is already friends with class `%s'", - TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); + if (classes) + cp_warning ("`%T' is already a friend of `%T'", + TREE_VALUE (classes), type); else { CLASSTYPE_FRIEND_CLASSES (type) diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend20.C b/gcc/testsuite/g++.old-deja/g++.pt/friend20.C new file mode 100644 index 0000000..40d5370 --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend20.C @@ -0,0 +1,10 @@ +// Build don't link: + +template struct A; + +template struct B +{ + friend class A; +}; + +template class B; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend21.C b/gcc/testsuite/g++.old-deja/g++.pt/friend21.C new file mode 100644 index 0000000..c724f8c --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/friend21.C @@ -0,0 +1,30 @@ +// Build don't link: + +template struct A { + static void f(); +}; + +template class B +{ + friend class A; + static int i; +}; + +template class C +{ + template + friend class A; + + static int i; +}; + +template +void A::f() +{ + B::i = 3; + C::i = 3; + C::i = 3; + B::i = 3; // ERROR - member `i' is private +} + +template void A::f(); // ERROR - instantiated from here -- cgit v1.1