PR c++/641, c++/11876
authorKriang Lerdsuwanakij <lerdsuwa@users.sourceforge.net>
Sat, 23 Aug 2003 12:53:48 +0000 (12:53 +0000)
committerKriang Lerdsuwanakij <lerdsuwa@gcc.gnu.org>
Sat, 23 Aug 2003 12:53:48 +0000 (12:53 +0000)
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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/friend.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/friend22.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/friend23.C [new file with mode: 0644]

index 7eaf150b76ac7b0d4c0f4f70d9027a4d019d536b..ad2cdbc23875f2a879aabf9f7a3d1ad9b395685e 100644 (file)
@@ -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
index 9cda7696e77230a1ddf0df8e19f5cdfdc669019b..025277e6fae3b3db48f17864b06070d19d32fa59 100644 (file)
@@ -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 */
index e35fa07ab6912de9da05282b76b5bfd36174ce7e..dc3495f42ef1cce328f3ae647119fd30d5be4001 100644 (file)
@@ -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);
index b71c5f203db08c844c999b4bd11173c9f402b5cb..1b3d4b462333199a8120a3b72af2e8a28c5888ef 100644 (file)
@@ -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;
     }
 
index c177a6c778d7dbe4d6bf688abba0e5620335b63c..1fb1a5104108fad9e904abb5a49d6a976f717397 100644 (file)
@@ -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;
index c66b5bc504b0eb15ae7893b8f73bcb374452ff4f..d6ea8cc82033fea6d91216f785d369f3adc34ea7 100644 (file)
@@ -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);
        }
     }
 
index 3ec6c04a3f468b57b713372b20d4c02504c19442..c25f750b5b66b6911c2269d115c16a766942e71d 100644 (file)
@@ -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 (file)
index 0000000..41a73bb
--- /dev/null
@@ -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 (file)
index 0000000..96f8125
--- /dev/null
@@ -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;
+}