aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>2003-08-23 12:53:48 +0000
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>2003-08-23 12:53:48 +0000
commit19db77cefec38a1a0a3eb69007f01e8a1c108d5d (patch)
treeecb689f7b3c2f693d19580d30f4517483bf94220
parentfe232263197821a4e018211df9adbe9e026da247 (diff)
downloadgcc-19db77cefec38a1a0a3eb69007f01e8a1c108d5d.zip
gcc-19db77cefec38a1a0a3eb69007f01e8a1c108d5d.tar.gz
gcc-19db77cefec38a1a0a3eb69007f01e8a1c108d5d.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/cp-tree.h4
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/friend.c49
-rw-r--r--gcc/cp/parser.c6
-rw-r--r--gcc/cp/pt.c6
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/template/friend22.C15
-rw-r--r--gcc/testsuite/g++.dg/template/friend23.C38
9 files changed, 117 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7eaf150..ad2cdbc 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,17 @@
+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>
PR c++/11283
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 9cda769..025277e 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3840,8 +3840,8 @@ extern tree cplus_expand_constant (tree);
/* friend.c */
extern int is_friend (tree, tree);
-extern void make_friend_class (tree, tree);
-extern void add_friend (tree, tree);
+extern void make_friend_class (tree, tree, bool);
+extern void add_friend (tree, tree, bool);
extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int);
/* in init.c */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e35fa07..dc3495f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11252,7 +11252,8 @@ grokdeclarator (tree declarator,
{
/* A friendly class? */
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
error ("trying to make class `%T' a friend of global scope",
type);
diff --git a/gcc/cp/friend.c b/gcc/cp/friend.c
index b71c5f2..1b3d4b4 100644
--- a/gcc/cp/friend.c
+++ b/gcc/cp/friend.c
@@ -127,10 +127,14 @@ is_friend (tree type, tree supplicant)
}
/* 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
-add_friend (tree type, tree decl)
+add_friend (tree type, tree decl, bool complain)
{
tree typedecl;
tree list;
@@ -153,10 +157,13 @@ add_friend (tree type, tree decl)
{
if (decl == TREE_VALUE (friends))
{
- warning ("`%D' is already a friend of class `%T'",
- decl, type);
- cp_warning_at ("previous friend declaration of `%D'",
- TREE_VALUE (friends));
+ if (complain)
+ {
+ warning ("`%D' is already a friend of class `%T'",
+ decl, type);
+ cp_warning_at ("previous friend declaration of `%D'",
+ TREE_VALUE (friends));
+ }
return;
}
}
@@ -192,10 +199,14 @@ add_friend (tree type, tree decl)
classes that are not defined. If a type has not yet been defined,
then the DECL_WAITING_FRIENDS contains a list of types
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
-make_friend_class (tree type, tree friend_type)
+make_friend_class (tree type, tree friend_type, bool complain)
{
tree classes;
int is_template_friend;
@@ -227,8 +238,9 @@ make_friend_class (tree type, tree friend_type)
}
else if (same_type_p (type, friend_type))
{
- pedwarn ("class `%T' is implicitly friends with itself",
- type);
+ if (complain)
+ pedwarn ("class `%T' is implicitly friends with itself",
+ type);
return;
}
else
@@ -275,8 +287,9 @@ make_friend_class (tree type, tree friend_type)
{
if (friend_type == probe)
{
- warning ("`%D' is already a friend of `%T'",
- probe, type);
+ if (complain)
+ warning ("`%D' is already a friend of `%T'",
+ probe, type);
break;
}
}
@@ -284,8 +297,9 @@ make_friend_class (tree type, tree friend_type)
{
if (same_type_p (probe, friend_type))
{
- warning ("`%T' is already a friend of `%T'",
- probe, type);
+ if (complain)
+ warning ("`%T' is already a friend of `%T'",
+ probe, type);
break;
}
}
@@ -369,7 +383,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
parameters. Instead, we rely on tsubst_friend_function
to check the validity of the declaration later. */
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
to be a friend, so we do lookup here even if CTYPE is in
the process of being defined. */
@@ -378,7 +392,7 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
decl = check_classfn (ctype, decl);
if (decl)
- add_friend (current_class_type, decl);
+ add_friend (current_class_type, decl, /*complain=*/true);
}
else
error ("member `%D' declared as friend before type `%T' defined",
@@ -446,7 +460,8 @@ do_friend (tree ctype, tree declarator, tree decl, tree parmdecls,
}
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;
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c177a6c..1fb1a51 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -11840,7 +11840,8 @@ cp_parser_member_declaration (cp_parser* parser)
error ("friend declaration does not name a class or "
"function");
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
been issued. */
@@ -13636,7 +13637,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
if (member_p && !friend_p && decl)
decl = finish_member_template_decl (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. */
--parser->num_template_parameter_lists;
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c66b5bc..d6ea8cc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -5381,14 +5381,16 @@ instantiate_class_template (tree type)
++processing_template_decl;
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)
--processing_template_decl;
}
else
/* Build new DECL_FRIENDLIST. */
- add_friend (type, tsubst_friend_function (t, args));
+ add_friend (type, tsubst_friend_function (t, args),
+ /*complain=*/false);
}
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3ec6c04..c25f750 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+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>
* gcc.misc-tests/linkage.exp: Treat all HP-UX platforms
diff --git a/gcc/testsuite/g++.dg/template/friend22.C b/gcc/testsuite/g++.dg/template/friend22.C
new file mode 100644
index 0000000..41a73bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend22.C
@@ -0,0 +1,15 @@
+// { 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;
diff --git a/gcc/testsuite/g++.dg/template/friend23.C b/gcc/testsuite/g++.dg/template/friend23.C
new file mode 100644
index 0000000..96f8125
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend23.C
@@ -0,0 +1,38 @@
+// { 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;
+}