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>
* 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.
......
......@@ -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
......
......@@ -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)
......
// 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