aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexandre Oliva <aoliva@redhat.com>2020-02-25 21:29:03 -0500
committerJason Merrill <jason@redhat.com>2020-02-25 23:21:14 -0500
commit3d99aab56d7237bb8260653ed07ca8b182fbf975 (patch)
treef3ebf8fc190d7a6d9877f0238982b0b27677d0d0 /gcc
parent6470e8caa2bd331fb6e21524d6c14662531cfa9b (diff)
downloadgcc-3d99aab56d7237bb8260653ed07ca8b182fbf975.zip
gcc-3d99aab56d7237bb8260653ed07ca8b182fbf975.tar.gz
gcc-3d99aab56d7237bb8260653ed07ca8b182fbf975.tar.bz2
c++: tsubst friend tpl ctxt before looking it up for dupes [PR86747]
When a member template is redeclared as a friend, we enter the context of the member before looking it up, and then we check that the decls are compatible. However, when the member template references template types of the enclosing context, say an enclosing template class, the compare fails because the friend decl is already tsubsted, whereas the looked up name isn't. The problem is that the enclosing context is taken from the friend declaration before tsubsting it, so we look up in the context of the generic template instead of that of the tsubsted one we're specializing. The solution is to tsubst the enclosing context when it's a non-namespace scope. gcc/cp/ChangeLog 2020-02-25 Alexandre Oliva <aoliva@redhat.com> PR c++/86747 * pt.c (tsubst_friend_class): Enter tsubsted class context. gcc/testsuite/ChangeLog 2020-02-25 Alexandre Oliva <aoliva@redhat.com> PR c++/86747 * g++.dg/pr86747.C: New.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/pr86747.C8
4 files changed, 22 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index eecfc71..f070889 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2020-02-25 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/86747
+ * pt.c (tsubst_friend_class): Enter tsubsted class context.
+
2020-02-25 Jason Merrill <jason@redhat.com>
PR c++/86429 - constexpr variable in lambda.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0d186e6..409e861 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10580,7 +10580,10 @@ tsubst_friend_class (tree friend_tmpl, tree args)
if (TREE_CODE (context) == NAMESPACE_DECL)
push_nested_namespace (context);
else
- push_nested_class (context);
+ {
+ context = tsubst (context, args, tf_error, NULL_TREE);
+ push_nested_class (context);
+ }
tmpl = lookup_name_real (DECL_NAME (friend_tmpl), /*prefer_type=*/false,
/*non_class=*/false, /*block_p=*/false,
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ace9be5..4c94167 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2020-02-25 Alexandre Oliva <aoliva@redhat.com>
+
+ PR c++/86747
+ * g++.dg/pr86747.C: New.
+
2019-02-05 Alexandre Oliva <aoliva@redhat.com>
PR c++/87770
diff --git a/gcc/testsuite/g++.dg/pr86747.C b/gcc/testsuite/g++.dg/pr86747.C
new file mode 100644
index 0000000..5b0a0bb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr86747.C
@@ -0,0 +1,8 @@
+// { dg-do compile }
+
+template <typename T> class A {
+ template <void (A::*p)()> class C; // #1
+ template <void (A::*q)()> friend class C; // #2
+};
+
+A<double> a;