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? 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 <ja...@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>(); -- 2.31.0.rc0.75.gec125d1bc1