Message ID | or5zwwk60e.fsf@lxoliva.fsfla.org |
---|---|
State | New |
Headers | show |
Series | [PR86747] tsubst friend tpl ctxt before looking it up for dupes | expand |
On 11/16/18 5:32 PM, Alexandre Oliva wrote: > 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. > > Regstrapped on i686- and x86_64-linux-gnu. Ok to install? OK. > > > for gcc/cp/ChangeLog > > PR c++/86747 > * pt.c (tsubst_friend_class): Enter tsubsted class context. > > for gcc/testsuite/ChangeLog > > PR c++/86747 > * g++.dg/pr86747.C: New. > --- > gcc/cp/pt.c | 5 ++++- > gcc/testsuite/g++.dg/pr86747.C | 8 ++++++++ > 2 files changed, 12 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/pr86747.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index 83d0a74b209f..82c8019431b8 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -10568,7 +10568,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/g++.dg/pr86747.C b/gcc/testsuite/g++.dg/pr86747.C > new file mode 100644 > index 000000000000..5b0a0bb95146 > --- /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; >
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 83d0a74b209f..82c8019431b8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -10568,7 +10568,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/g++.dg/pr86747.C b/gcc/testsuite/g++.dg/pr86747.C new file mode 100644 index 000000000000..5b0a0bb95146 --- /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;