aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@markmitchell.com>1998-05-26 23:17:56 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1998-05-26 23:17:56 +0000
commitea4e080b25061c49143467d14d6438996b671987 (patch)
tree9a97484e1c054bb01be5879ff02fcca55cf3f0f3
parentf5e23e0df78594ef4148ed4e8ea6068804f5eb15 (diff)
downloadgcc-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
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/friend.c37
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend20.C10
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend21.C30
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