Commit ea4e080b by Mark Mitchell Committed by Mark Mitchell

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
parent f5e23e0d
1998-05-26 Mark Mitchell <mark@markmitchell.com> 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 * decl.c (store_parm_decls): Remove redundant call to
expand_main_function. expand_main_function.
......
...@@ -905,7 +905,9 @@ struct lang_type ...@@ -905,7 +905,9 @@ struct lang_type
/* Same, but cache a list whose value is the binfo of this 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) #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) #define CLASSTYPE_FRIEND_CLASSES(NODE) (TYPE_LANG_SPECIFIC(NODE)->friend_classes)
#ifdef MI_MATRIX #ifdef MI_MATRIX
......
...@@ -64,7 +64,7 @@ is_friend (type, supplicant) ...@@ -64,7 +64,7 @@ is_friend (type, supplicant)
tree friends = TREE_VALUE (list); tree friends = TREE_VALUE (list);
for (; friends ; friends = TREE_CHAIN (friends)) for (; friends ; friends = TREE_CHAIN (friends))
{ {
if (ctype == TREE_PURPOSE (friends)) if (comptypes (ctype, TREE_PURPOSE (friends), 1))
return 1; return 1;
if (TREE_VALUE (friends) == NULL_TREE) if (TREE_VALUE (friends) == NULL_TREE)
...@@ -102,10 +102,9 @@ is_friend (type, supplicant) ...@@ -102,10 +102,9 @@ is_friend (type, supplicant)
{ {
tree t = TREE_VALUE (list); tree t = TREE_VALUE (list);
if (supplicant == t if (TREE_CODE (t) == TEMPLATE_DECL ?
|| (CLASSTYPE_IS_TEMPLATE (t) is_specialization_of (TYPE_MAIN_DECL (supplicant), t) :
&& is_specialization_of (TYPE_MAIN_DECL (supplicant), comptypes (supplicant, t, 1))
CLASSTYPE_TI_TEMPLATE (t))))
return 1; return 1;
} }
} }
...@@ -241,6 +240,7 @@ make_friend_class (type, friend_type) ...@@ -241,6 +240,7 @@ make_friend_class (type, friend_type)
tree type, friend_type; tree type, friend_type;
{ {
tree classes; tree classes;
int is_template_friend;
if (IS_SIGNATURE (type)) if (IS_SIGNATURE (type))
{ {
...@@ -253,25 +253,36 @@ make_friend_class (type, friend_type) ...@@ -253,25 +253,36 @@ make_friend_class (type, friend_type)
IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type))); IDENTIFIER_POINTER (TYPE_IDENTIFIER (friend_type)));
return; return;
} }
/* If the TYPE is a template then it makes sense for it to be if (processing_template_decl > template_class_depth (type))
friends with itself; this means that each instantiation is /* If the TYPE is a template then it makes sense for it to be
friends with all other instantiations. */ friends with itself; this means that each instantiation is
if (type == friend_type && !CLASSTYPE_IS_TEMPLATE (type)) friends with all other instantiations. */
is_template_friend = 1;
else if (comptypes (type, friend_type, 1))
{ {
pedwarn ("class `%s' is implicitly friends with itself", pedwarn ("class `%s' is implicitly friends with itself",
TYPE_NAME_STRING (type)); TYPE_NAME_STRING (type));
return; return;
} }
else
is_template_friend = 0;
GNU_xref_hier (TYPE_NAME_STRING (type), GNU_xref_hier (TYPE_NAME_STRING (type),
TYPE_NAME_STRING (friend_type), 0, 0, 1); TYPE_NAME_STRING (friend_type), 0, 0, 1);
if (is_template_friend)
friend_type = CLASSTYPE_TI_TEMPLATE (friend_type);
classes = CLASSTYPE_FRIEND_CLASSES (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); classes = TREE_CHAIN (classes);
if (classes) if (classes)
warning ("class `%s' is already friends with class `%s'", cp_warning ("`%T' is already a friend of `%T'",
TYPE_NAME_STRING (TREE_VALUE (classes)), TYPE_NAME_STRING (type)); TREE_VALUE (classes), type);
else else
{ {
CLASSTYPE_FRIEND_CLASSES (type) CLASSTYPE_FRIEND_CLASSES (type)
......
// Build don't link:
template <class T = int> struct A;
template <class T> struct B
{
friend class A<T>;
};
template class B<int>;
// 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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment