re PR c++/59366 (A friend function template defined in a class is found without ADL)
authorMomchil Velikov <momchil.velikov@gmail.com>
Thu, 15 Jan 2015 21:02:15 +0000 (21:02 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 15 Jan 2015 21:02:15 +0000 (16:02 -0500)
PR c++/59366
* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
and function templates, declared only in the class.
* decl.c (duplicate_decls): Reveal hidden friend functions or
function templates, if they are redeclared outside the class.

From-SVN: r219689

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/testsuite/g++.dg/template/friend57.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/friend5.C

index 2e74c0a4068eb5205e165c02220281e4aa56d564..9120e07eaf97688a12dfdb1f3e49bad376d79998 100644 (file)
@@ -1,3 +1,11 @@
+2015-01-15  Momchil Velikov  <momchil.velikov@gmail.com>
+
+       PR c++/59366
+       * name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
+       and function templates, declared only in the class.
+       * decl.c (duplicate_decls): Reveal hidden friend functions or
+       function templates, if they are redeclared outside the class.
+
 2015-01-15  Jason Merrill  <jason@redhat.com>
 
        PR c++/64356
index 9d9a04eeee6b56671887a193c015b6b06f4ccd6b..35f483363d8dce96c186e13f7ac8a5682b089302 100644 (file)
@@ -1871,6 +1871,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
   DECL_ATTRIBUTES (newdecl)
     = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
+  if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
+    {
+      olddecl_friend = DECL_FRIEND_P (olddecl);
+      hidden_friend = (DECL_ANTICIPATED (olddecl)
+                      && DECL_HIDDEN_FRIEND_P (olddecl)
+                      && newdecl_is_friend);
+      if (!hidden_friend)
+       {
+         DECL_ANTICIPATED (olddecl) = 0;
+         DECL_HIDDEN_FRIEND_P (olddecl) = 0;
+       }
+    }
+
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
       tree old_result;
@@ -2153,10 +2166,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       if (DECL_DECLARES_FUNCTION_P (newdecl))
        {
          DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-         olddecl_friend = DECL_FRIEND_P (olddecl);
-         hidden_friend = (DECL_ANTICIPATED (olddecl)
-                          && DECL_HIDDEN_FRIEND_P (olddecl)
-                          && newdecl_is_friend);
          DECL_BEFRIENDING_CLASSES (newdecl)
            = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
                       DECL_BEFRIENDING_CLASSES (olddecl));
index cf612407e9e58a5bde24891304fdf39a4f1d16ed..ba16befa74d9d5499a4ab724d91d757ed34bf948 100644 (file)
@@ -933,7 +933,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
        }
 
       if (DECL_DECLARES_FUNCTION_P (t))
-       check_default_args (t);
+       {
+         check_default_args (t);
+
+         if (is_friend && t == x && !flag_friend_injection)
+           {
+             /* This is a new friend declaration of a function or a
+                function template, so hide it from ordinary function
+                lookup.  */
+             DECL_ANTICIPATED (t) = 1;
+             DECL_HIDDEN_FRIEND_P (t) = 1;
+           }
+       }
 
       if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
        return t;
@@ -995,16 +1006,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
            }
        }
 
-      if (TREE_CODE (x) == FUNCTION_DECL
-         && is_friend
-         && !flag_friend_injection)
-       {
-         /* This is a new declaration of a friend function, so hide
-            it from ordinary function lookup.  */
-         DECL_ANTICIPATED (x) = 1;
-         DECL_HIDDEN_FRIEND_P (x) = 1;
-       }
-
       /* This name is new in its binding level.
         Install the new declaration and return it.  */
       if (namespace_bindings_p ())
diff --git a/gcc/testsuite/g++.dg/template/friend57.C b/gcc/testsuite/g++.dg/template/friend57.C
new file mode 100644 (file)
index 0000000..7077d5e
--- /dev/null
@@ -0,0 +1,21 @@
+// PR c++/59366
+// { dg-do compile }
+template<typename T> void f(T);
+
+struct S
+{
+  template<typename T> friend void f(T) {}
+  template<typename T> friend void g(T) {}
+  template<typename T> friend void h(T) {}
+};
+
+template<typename T> void h(T);
+
+int
+main ()
+{
+  f(1);
+  g(1); // { dg-error "'g' was not declared in this scope" }
+  g(S());
+  h(1);
+}
index 3feeb684e36cf26a3e2dc7e26deab8b1a2e5ce7a..edb9d62335914d21da815469583a87d60b2baaa2 100644 (file)
@@ -14,5 +14,5 @@ class C
 
 int main()
 {
-  f(7);
+  f(C());
 }