Commit 19db77ce by Kriang Lerdsuwanakij Committed by Kriang Lerdsuwanakij

PR c++/641, c++/11876

	PR c++/641, c++/11876
	* friend.c (add_friend): Add complain parameter.
	(make_friend_class): Likewise.
	(do_friend): Adjust add_friend call.
	* decl.c (grokdeclarator): Adjust make_friend_class call.
	* parser.c (cp_parser_member_declaration): Likewise.
	(cp_parser_template_declaration_after_exp): Likewise.
	* pt.c (instantiate_class_template): Adjust make_friend_class
	and add_friend call.
	* cp-tree.h (make_friend_class): Adjust declaration.
	(add_friend): Likewise.

	* g++.dg/template/friend22.C: New test.
	* g++.dg/template/friend23.C: Likewise.

From-SVN: r70732
parent fe232263
2003-08-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/641, c++/11876
* friend.c (add_friend): Add complain parameter.
(make_friend_class): Likewise.
(do_friend): Adjust add_friend call.
* decl.c (grokdeclarator): Adjust make_friend_class call.
* parser.c (cp_parser_member_declaration): Likewise.
(cp_parser_template_declaration_after_exp): Likewise.
* pt.c (instantiate_class_template): Adjust make_friend_class
and add_friend call.
* cp-tree.h (make_friend_class): Adjust declaration.
(add_friend): Likewise.
2003-08-21 Jason Merrill <jason@redhat.com> 2003-08-21 Jason Merrill <jason@redhat.com>
PR c++/11283 PR c++/11283
......
...@@ -3840,8 +3840,8 @@ extern tree cplus_expand_constant (tree); ...@@ -3840,8 +3840,8 @@ extern tree cplus_expand_constant (tree);
/* friend.c */ /* friend.c */
extern int is_friend (tree, tree); extern int is_friend (tree, tree);
extern void make_friend_class (tree, tree); extern void make_friend_class (tree, tree, bool);
extern void add_friend (tree, tree); extern void add_friend (tree, tree, bool);
extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int); extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int);
/* in init.c */ /* in init.c */
......
...@@ -11252,7 +11252,8 @@ grokdeclarator (tree declarator, ...@@ -11252,7 +11252,8 @@ grokdeclarator (tree declarator,
{ {
/* A friendly class? */ /* A friendly class? */
if (current_class_type) if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type)); make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type),
/*complain=*/true);
else else
error ("trying to make class `%T' a friend of global scope", error ("trying to make class `%T' a friend of global scope",
type); type);
......
...@@ -127,10 +127,14 @@ is_friend (tree type, tree supplicant) ...@@ -127,10 +127,14 @@ is_friend (tree type, tree supplicant)
} }
/* Add a new friend to the friends of the aggregate type TYPE. /* Add a new friend to the friends of the aggregate type TYPE.
DECL is the FUNCTION_DECL of the friend being added. */ DECL is the FUNCTION_DECL of the friend being added.
If COMPLAIN is true, warning about duplicate friend is issued.
We want to have this diagnostics during parsing but not
when a template is being instantiated. */
void void
add_friend (tree type, tree decl) add_friend (tree type, tree decl, bool complain)
{ {
tree typedecl; tree typedecl;
tree list; tree list;
...@@ -153,10 +157,13 @@ add_friend (tree type, tree decl) ...@@ -153,10 +157,13 @@ add_friend (tree type, tree decl)
{ {
if (decl == TREE_VALUE (friends)) if (decl == TREE_VALUE (friends))
{ {
warning ("`%D' is already a friend of class `%T'", if (complain)
decl, type); {
cp_warning_at ("previous friend declaration of `%D'", warning ("`%D' is already a friend of class `%T'",
TREE_VALUE (friends)); decl, type);
cp_warning_at ("previous friend declaration of `%D'",
TREE_VALUE (friends));
}
return; return;
} }
} }
...@@ -192,10 +199,14 @@ add_friend (tree type, tree decl) ...@@ -192,10 +199,14 @@ add_friend (tree type, tree decl)
classes that are not defined. If a type has not yet been defined, classes that are not defined. If a type has not yet been defined,
then the DECL_WAITING_FRIENDS contains a list of types then the DECL_WAITING_FRIENDS contains a list of types
waiting to make it their friend. Note that these two can both waiting to make it their friend. Note that these two can both
be in use at the same time! */ be in use at the same time!
If COMPLAIN is true, warning about duplicate friend is issued.
We want to have this diagnostics during parsing but not
when a template is being instantiated. */
void void
make_friend_class (tree type, tree friend_type) make_friend_class (tree type, tree friend_type, bool complain)
{ {
tree classes; tree classes;
int is_template_friend; int is_template_friend;
...@@ -227,8 +238,9 @@ make_friend_class (tree type, tree friend_type) ...@@ -227,8 +238,9 @@ make_friend_class (tree type, tree friend_type)
} }
else if (same_type_p (type, friend_type)) else if (same_type_p (type, friend_type))
{ {
pedwarn ("class `%T' is implicitly friends with itself", if (complain)
type); pedwarn ("class `%T' is implicitly friends with itself",
type);
return; return;
} }
else else
...@@ -275,8 +287,9 @@ make_friend_class (tree type, tree friend_type) ...@@ -275,8 +287,9 @@ make_friend_class (tree type, tree friend_type)
{ {
if (friend_type == probe) if (friend_type == probe)
{ {
warning ("`%D' is already a friend of `%T'", if (complain)
probe, type); warning ("`%D' is already a friend of `%T'",
probe, type);
break; break;
} }
} }
...@@ -284,8 +297,9 @@ make_friend_class (tree type, tree friend_type) ...@@ -284,8 +297,9 @@ make_friend_class (tree type, tree friend_type)
{ {
if (same_type_p (probe, friend_type)) if (same_type_p (probe, friend_type))
{ {
warning ("`%T' is already a friend of `%T'", if (complain)
probe, type); warning ("`%T' is already a friend of `%T'",
probe, type);
break; break;
} }
} }
...@@ -369,7 +383,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, ...@@ -369,7 +383,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
parameters. Instead, we rely on tsubst_friend_function parameters. Instead, we rely on tsubst_friend_function
to check the validity of the declaration later. */ to check the validity of the declaration later. */
if (processing_template_decl) if (processing_template_decl)
add_friend (current_class_type, decl); add_friend (current_class_type, decl, /*complain=*/true);
/* A nested class may declare a member of an enclosing class /* A nested class may declare a member of an enclosing class
to be a friend, so we do lookup here even if CTYPE is in to be a friend, so we do lookup here even if CTYPE is in
the process of being defined. */ the process of being defined. */
...@@ -378,7 +392,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, ...@@ -378,7 +392,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
decl = check_classfn (ctype, decl); decl = check_classfn (ctype, decl);
if (decl) if (decl)
add_friend (current_class_type, decl); add_friend (current_class_type, decl, /*complain=*/true);
} }
else else
error ("member `%D' declared as friend before type `%T' defined", error ("member `%D' declared as friend before type `%T' defined",
...@@ -446,7 +460,8 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls, ...@@ -446,7 +460,8 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
} }
add_friend (current_class_type, add_friend (current_class_type,
is_friend_template ? DECL_TI_TEMPLATE (decl) : decl); is_friend_template ? DECL_TI_TEMPLATE (decl) : decl,
/*complain=*/true);
DECL_FRIEND_P (decl) = 1; DECL_FRIEND_P (decl) = 1;
} }
......
...@@ -11840,7 +11840,8 @@ cp_parser_member_declaration (cp_parser* parser) ...@@ -11840,7 +11840,8 @@ cp_parser_member_declaration (cp_parser* parser)
error ("friend declaration does not name a class or " error ("friend declaration does not name a class or "
"function"); "function");
else else
make_friend_class (current_class_type, type); make_friend_class (current_class_type, type,
/*complain=*/true);
} }
/* If there is no TYPE, an error message will already have /* If there is no TYPE, an error message will already have
been issued. */ been issued. */
...@@ -13636,7 +13637,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p) ...@@ -13636,7 +13637,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
if (member_p && !friend_p && decl) if (member_p && !friend_p && decl)
decl = finish_member_template_decl (decl); decl = finish_member_template_decl (decl);
else if (friend_p && decl && TREE_CODE (decl) == TYPE_DECL) else if (friend_p && decl && TREE_CODE (decl) == TYPE_DECL)
make_friend_class (current_class_type, TREE_TYPE (decl)); make_friend_class (current_class_type, TREE_TYPE (decl),
/*complain=*/true);
} }
/* We are done with the current parameter list. */ /* We are done with the current parameter list. */
--parser->num_template_parameter_lists; --parser->num_template_parameter_lists;
......
...@@ -5381,14 +5381,16 @@ instantiate_class_template (tree type) ...@@ -5381,14 +5381,16 @@ instantiate_class_template (tree type)
++processing_template_decl; ++processing_template_decl;
if (new_friend_type != error_mark_node) if (new_friend_type != error_mark_node)
make_friend_class (type, new_friend_type); make_friend_class (type, new_friend_type,
/*complain=*/false);
if (TREE_CODE (friend_type) == TEMPLATE_DECL) if (TREE_CODE (friend_type) == TEMPLATE_DECL)
--processing_template_decl; --processing_template_decl;
} }
else else
/* Build new DECL_FRIENDLIST. */ /* Build new DECL_FRIENDLIST. */
add_friend (type, tsubst_friend_function (t, args)); add_friend (type, tsubst_friend_function (t, args),
/*complain=*/false);
} }
} }
......
2003-08-23 Kriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
PR c++/641, c++/11876
* g++.dg/template/friend22.C: New test.
* g++.dg/template/friend23.C: Likewise.
2003-08-22 Mark Mitchell <mark@codesourcery.com> 2003-08-22 Mark Mitchell <mark@codesourcery.com>
* gcc.misc-tests/linkage.exp: Treat all HP-UX platforms * gcc.misc-tests/linkage.exp: Treat all HP-UX platforms
......
// { dg-do compile }
// Origin: Benoit Hudson <bh@techhouse.brown.edu>
// PR c++/641: Duplicate friend diagnostics
template <class T> class iterator { };
template <class T> class item {
friend class iterator<T>;
friend class iterator<const T>;
};
class A { };
item<const A> i;
// { dg-do compile }
// Origin: Alexandre Tolmos <ktulu@free.fr>
// PR c++/11876: Friend of its own class diagnostics
template <typename T>
class A
{
friend class A<int>;
friend class A<float>;
protected:
T _data;
inline A() : _data(0) {}
template <typename U>
inline A(const A<U>& r) : _data(r._data) {}
};
class B : public A<int>
{
public:
inline B() {}
inline B(const B& r) : A<int>(r) {}
};
class C : public A<float>
{
public:
inline C() {}
inline C(const B& r) : A<float>(r) {}
};
int main(int, char*[])
{
B b1, b2(b1);
C c(b1);
return 0;
}
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