PR c++/71227 - specializing hidden friend
authorJason Merrill <jason@redhat.com>
Tue, 31 May 2016 19:16:26 +0000 (15:16 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 31 May 2016 19:16:26 +0000 (15:16 -0400)
* pt.c (check_explicit_specialization): Give better diagnostic about
specializing a hidden friend.

From-SVN: r236941

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/friend62.C [new file with mode: 0644]

index 0401255dad7c81a40d946f57b863fa92729e8fa3..35042bc262d4afc035405215a78fc044cf87b006 100644 (file)
@@ -1,3 +1,9 @@
+2016-05-31  Jason Merrill  <jason@redhat.com>
+
+       PR c++/71227
+       * pt.c (check_explicit_specialization): Give better diagnostic about
+       specializing a hidden friend.
+
 2016-05-31  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/71248
index 4a24c9840fc2ea6fd8451328b217add61efe0455..af37586177252162b27e0c9037616112f46101de 100644 (file)
@@ -2808,6 +2808,13 @@ check_explicit_specialization (tree declarator,
                 context.  */
              fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
                                           false, true);
+             if (fns == error_mark_node)
+               /* If lookup fails, look for a friend declaration so we can
+                  give a better diagnostic.  */
+               fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname,
+                                            /*type*/false, /*complain*/true,
+                                            /*hidden*/true);
+
              if (fns == error_mark_node || !is_overloaded_fn (fns))
                {
                  error ("%qD is not a template function", dname);
@@ -2953,6 +2960,15 @@ check_explicit_specialization (tree declarator,
                                           CP_DECL_CONTEXT (tmpl)))
            error ("%qD is not declared in %qD",
                   tmpl, current_namespace);
+         else if (TREE_CODE (decl) == FUNCTION_DECL
+                  && DECL_HIDDEN_FRIEND_P (tmpl))
+           {
+             if (pedwarn (DECL_SOURCE_LOCATION (decl), 0,
+                          "friend declaration %qD is not visible to "
+                          "explicit specialization", tmpl))
+               inform (DECL_SOURCE_LOCATION (tmpl),
+                       "friend declaration here");
+           }
 
          tree gen_tmpl = most_general_template (tmpl);
 
diff --git a/gcc/testsuite/g++.dg/template/friend62.C b/gcc/testsuite/g++.dg/template/friend62.C
new file mode 100644 (file)
index 0000000..c9796c4
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/71227
+// { dg-options "" }
+
+class A {
+  public:
+    template<typename T>
+      friend int f(int x, T v) { // { dg-message "declaration" }
+        return x + v;
+      }
+};
+
+
+template<>
+int f(int x, int v) {          // { dg-warning "friend" }
+  return x + v;
+}