aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMomchil Velikov <momchil.velikov@gmail.com>2015-01-15 21:02:15 +0000
committerJason Merrill <jason@gcc.gnu.org>2015-01-15 16:02:15 -0500
commit199b7a3586061f951fa737656217206164456910 (patch)
treeb986595b92e98bfac8ddd733fa895f37db151c48 /gcc
parent58b59d5ee7ac732d67736bc3654b6dc6c9af9e44 (diff)
downloadgcc-199b7a3586061f951fa737656217206164456910.zip
gcc-199b7a3586061f951fa737656217206164456910.tar.gz
gcc-199b7a3586061f951fa737656217206164456910.tar.bz2
re PR c++/59366 (A friend function template defined in a class is found without ADL)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c17
-rw-r--r--gcc/cp/name-lookup.c23
-rw-r--r--gcc/testsuite/g++.dg/template/friend57.C21
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/friend5.C2
5 files changed, 55 insertions, 16 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2e74c0a..9120e07 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 9d9a04e..35f4833 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index cf61240..ba16bef 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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
index 0000000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend57.C
@@ -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);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
int main()
{
- f(7);
+ f(C());
}