Message ID | 20210305180446.3640500-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: Fix tsubsting member variable template-id [PR96330] | expand |
On 3/5/21 1:04 PM, Patrick Palka wrote: > This makes tsubst_copy appropriately handle a variable template-id, which > in turn fixes tsubsting a COMPONENT_REF whose member operand is known at > parse time to be a variable template-id, as in the initialization of 'x' > in the first testcase. Previously, we rejected this testcase with the > error "foo_t::bar<T> is not a function template", issued from > lookup_template_fuction. > > We were already properly handling the analagous case where the object > operand of the COMPONENT_REF is dependent (and so the member operand is > a dependent template name), but there doesn't seems to be existing test > coverage for this, hence the second testcase below. > > Bootstrapped and regtested on x86_64-pc-linux-gnu. Does this look OK > for trunk or perhaps GCC 12? OK for trunk. > gcc/cp/ChangeLog: > > PR c++/96330 > * pt.c (tsubst_copy) <case TEMPLATE_ID_EXPR>: Rename local > variable 'fn' to 'tmpl'. Handle a variable template-id by > calling lookup_template_variable. > > gcc/testsuite/ChangeLog: > > PR c++/96330 > * g++.dg/cpp1y/var-templ68.C: New test. > * g++.dg/cpp1y/var-templ68a.C: New test. > > Co-authored-by: Jakub Jelinek <jakub@redhat.com> > --- > gcc/cp/pt.c | 9 ++++++--- > gcc/testsuite/g++.dg/cpp1y/var-templ68.C | 15 +++++++++++++++ > gcc/testsuite/g++.dg/cpp1y/var-templ68a.C | 16 ++++++++++++++++ > 3 files changed, 37 insertions(+), 3 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ68.C > create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ68a.C > > diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c > index ec869451cd2..c956815ce85 100644 > --- a/gcc/cp/pt.c > +++ b/gcc/cp/pt.c > @@ -17108,14 +17108,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) > case TEMPLATE_ID_EXPR: > { > /* Substituted template arguments */ > - tree fn = TREE_OPERAND (t, 0); > + tree tmpl = TREE_OPERAND (t, 0); > tree targs = TREE_OPERAND (t, 1); > > - fn = tsubst_copy (fn, args, complain, in_decl); > + tmpl = tsubst_copy (tmpl, args, complain, in_decl); > if (targs) > targs = tsubst_template_args (targs, args, complain, in_decl); > > - return lookup_template_function (fn, targs); > + if (variable_template_p (tmpl)) > + return lookup_template_variable (tmpl, targs); > + else > + return lookup_template_function (tmpl, targs); > } > > case TREE_LIST: > diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ68.C b/gcc/testsuite/g++.dg/cpp1y/var-templ68.C > new file mode 100644 > index 00000000000..4c560d4bd35 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ68.C > @@ -0,0 +1,15 @@ > +// PR c++/96330 > +// { dg-do compile { target c++14 } } > + > +struct foo_t { > + template <class T> static constexpr bool bar = true; > +}; > +constexpr foo_t foo{}; > + > +template <class T> > +void f() { > + int x = foo.bar<T>; > + int y = foo_t::bar<T>; > +} > + > +template void f<int>(); > diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C b/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C > new file mode 100644 > index 00000000000..6091a03a004 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C > @@ -0,0 +1,16 @@ > +// PR c++/96330 > +// { dg-do compile { target c++14 } } > + > +template <class> > +struct foo_t { > + template <class T> static constexpr bool bar = true; > +}; > +template <class T> constexpr foo_t<T> foo{}; > + > +template <class T> > +void f() { > + int x = foo<T>.template bar<T>; > + int y = foo_t<T>::template bar<T>; > +} > + > +template void f<int>(); >
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ec869451cd2..c956815ce85 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -17108,14 +17108,17 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) case TEMPLATE_ID_EXPR: { /* Substituted template arguments */ - tree fn = TREE_OPERAND (t, 0); + tree tmpl = TREE_OPERAND (t, 0); tree targs = TREE_OPERAND (t, 1); - fn = tsubst_copy (fn, args, complain, in_decl); + tmpl = tsubst_copy (tmpl, args, complain, in_decl); if (targs) targs = tsubst_template_args (targs, args, complain, in_decl); - return lookup_template_function (fn, targs); + if (variable_template_p (tmpl)) + return lookup_template_variable (tmpl, targs); + else + return lookup_template_function (tmpl, targs); } case TREE_LIST: diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ68.C b/gcc/testsuite/g++.dg/cpp1y/var-templ68.C new file mode 100644 index 00000000000..4c560d4bd35 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ68.C @@ -0,0 +1,15 @@ +// PR c++/96330 +// { dg-do compile { target c++14 } } + +struct foo_t { + template <class T> static constexpr bool bar = true; +}; +constexpr foo_t foo{}; + +template <class T> +void f() { + int x = foo.bar<T>; + int y = foo_t::bar<T>; +} + +template void f<int>(); diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C b/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C new file mode 100644 index 00000000000..6091a03a004 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/var-templ68a.C @@ -0,0 +1,16 @@ +// PR c++/96330 +// { dg-do compile { target c++14 } } + +template <class> +struct foo_t { + template <class T> static constexpr bool bar = true; +}; +template <class T> constexpr foo_t<T> foo{}; + +template <class T> +void f() { + int x = foo<T>.template bar<T>; + int y = foo_t<T>::template bar<T>; +} + +template void f<int>();