diff options
author | Mark Mitchell <mark@markmitchell.com> | 1998-05-26 23:17:56 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1998-05-26 23:17:56 +0000 |
commit | ea4e080b25061c49143467d14d6438996b671987 (patch) | |
tree | 9a97484e1c054bb01be5879ff02fcca55cf3f0f3 /gcc | |
parent | f5e23e0df78594ef4148ed4e8ea6068804f5eb15 (diff) | |
download | gcc-ea4e080b25061c49143467d14d6438996b671987.zip gcc-ea4e080b25061c49143467d14d6438996b671987.tar.gz gcc-ea4e080b25061c49143467d14d6438996b671987.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 4 | ||||
-rw-r--r-- | gcc/cp/friend.c | 37 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend20.C | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/friend21.C | 30 |
5 files changed, 73 insertions, 14 deletions
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 <mark@markmitchell.com> + * 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 <class T = int> struct A; + +template <class T> struct B +{ + friend class A<T>; +}; + +template class B<int>; 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 <class T> struct A { + static void f(); +}; + +template <class T> class B +{ + friend class A<T>; + static int i; +}; + +template <class T> class C +{ + template <class U> + friend class A<U>; + + static int i; +}; + +template <class T> +void A<T>::f() +{ + B<T>::i = 3; + C<T>::i = 3; + C<double>::i = 3; + B<double>::i = 3; // ERROR - member `i' is private +} + +template void A<int>::f(); // ERROR - instantiated from here |