GCC HEAD on Wandbox rejects the code I pasted below, while Clang accepts it without errors. Link: http://melpon.org/wandbox/permlink/DShqHOBBMDx3X0H2 I also have a local TDM-GCC 5.1.0 (DW2) installation which gives the same error message for my original code, but for some reason the bug doesn’t trigger on Wandbox’s 5.1.0 with the minimal testcase I’ve extracted. /*-- Code --*/ template<typename> struct SpecPerType; class Specializer { public: template<bool> void MbrFnTempl() //Must be a template { } template<unsigned> struct InnerClassTempl { //Had to be a template whenever I tested for it static void InnerMemberFn(); }; void Trigger() { InnerClassTempl<0u>::InnerMemberFn(); } }; template<> struct SpecPerType<Specializer> { using FnType = void (Specializer::*)(); template<bool P> static constexpr FnType SpecMbrFnPtr = &Specializer::template MbrFnTempl<P>; }; template<bool> constexpr SpecPerType<Specializer>::FnType SpecPerType<Specializer>::SpecMbrFnPtr; //Just a formalism template<unsigned X> void Specializer::InnerClassTempl<X>::InnerMemberFn() { using Spec = SpecPerType<Specializer>; typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr<true>; //ErrorSite would get called next in the original code //(this should result in a call to MbrFnTempl) } int main() { }
The error message I got, copied from Wandbox: prog.cc: In instantiation of 'static void Specializer::InnerClassTempl<<anonymous> >::InnerMemberFn() [with unsigned int <anonymous> = 0u]': prog.cc:16:24: required from here prog.cc:33:36: error: 'template<bool P> constexpr void (Specializer::* const SpecPerType<Specializer>::SpecMbrFnPtr)()<<anonymous> >' is not a function template typename Spec::FnType ErrorSite = Spec::template SpecMbrFnPtr<true>; ^~~~ prog.cc:33:36: error: 'SpecMbrFnPtr<true>' is not a member of 'Spec {aka SpecPerType<Specializer>}'
Confirmed. The following simplified test case also reproduces the error with today's top of trunk. 5.1.0 compiles the test case successfully so this is a regression. $ cat u.cpp && /home/msebor/build/gcc-trunk-svn/gcc/xg++ -B/home/msebor/build/gcc-trunk-svn/gcc -S -Wall -Wextra -o/dev/null -std=c++14 u.cpp struct A { template <int> static void (*pf)(); }; template <int> void foo () { (void)A::pf<true>; } void bar () { foo<0>(); } u.cpp: In instantiation of ‘void foo() [with int <anonymous> = 0]’: u.cpp:13:10: required from here u.cpp:9:9: error: ‘template<int <anonymous> > void (* A::pf)()<<anonymous> >’ is not a function template (void)A::pf<true>; ^ u.cpp:9:9: error: ‘pf<true>’ is not a member of ‘A’
Your testcase is really quite a bit smaller still – impressive skills! :) Thanks for confirming and since 5.1.0 works for you, on Wandbox and additionally your testcase doesn’t fail locally, I guess I might just have looked at the wrong one of my two installations when I queried the version, perhaps I forgot to prepend '.\' or something like that.
(In reply to Martin Sebor from comment #2) > Confirmed. The following simplified test case also reproduces the error > with today's top of trunk. 5.1.0 compiles the test case successfully so > this is a regression. > > $ cat u.cpp && /home/msebor/build/gcc-trunk-svn/gcc/xg++ > -B/home/msebor/build/gcc-trunk-svn/gcc -S -Wall -Wextra -o/dev/null > -std=c++14 u.cpp > struct A > { > template <int> > static void (*pf)(); > }; > > template <int> > void foo () { > (void)A::pf<true>; > } > > void bar () { > foo<0>(); > } > u.cpp: In instantiation of ‘void foo() [with int <anonymous> = 0]’: > u.cpp:13:10: required from here > u.cpp:9:9: error: ‘template<int <anonymous> > void (* A::pf)()<<anonymous> > >’ is not a function template > (void)A::pf<true>; > ^ > > u.cpp:9:9: error: ‘pf<true>’ is not a member of ‘A’ This test seems to regress between 5.2 and 5.3.
I looks like it was introduced in r186681. The last good commit before that is r186667, and none of those in between touch the C++ front end. Though the changes in r186681 look very mechanical and not related to templates at all so I'm not sure.
This fixes it: diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index ef79b59..264c8aa 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13735,7 +13735,19 @@ tsubst_qualified_id (tree qualified_id, tree args, } if (is_template) - expr = lookup_template_function (expr, template_args); + { + if (variable_template_p (expr)) + { + expr = lookup_template_variable (expr, template_args); + if (!any_dependent_template_arguments_p (template_args)) + { + expr = finish_template_variable (expr, complain); + mark_used (expr); + } + } + else + expr = lookup_template_function (expr, template_args); + } if (expr == error_mark_node && complain & tf_error) qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
(In reply to Patrick Palka from comment #6) > This fixes it: Are you going to post it to gcc-patches (with ChangeLog and testcase)?
The #c5 mentioned revisions look really weird, my bisection shows this regressed on the trunk with r226642, which has been indeed backported to 5 branch too. Downgrading to P2, as we've already released one compiler (5.3) with this bug.
(In reply to Jakub Jelinek from comment #7) > (In reply to Patrick Palka from comment #6) > > This fixes it: > > Are you going to post it to gcc-patches (with ChangeLog and testcase)? It doesn't yet make sense to me why r226642 introduces this regression. Once I figure it out I'll post the patch.
(In reply to Patrick Palka from comment #9) > (In reply to Jakub Jelinek from comment #7) > > (In reply to Patrick Palka from comment #6) > > > This fixes it: > > > > Are you going to post it to gcc-patches (with ChangeLog and testcase)? > > It doesn't yet make sense to me why r226642 introduces this regression. Once > I figure it out I'll post the patch. This change --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8187,14 +8187,14 @@ lookup_template_class (tree d1, tree arglist, tree in_decl, tree context, tree lookup_template_variable (tree templ, tree arglist) { - tree type = unknown_type_node; + tree type = NULL_TREE; return build2 (TEMPLATE_ID_EXPR, type, templ, arglist); } made finish_id_expression later wrap the variable-template expression in a SCOPE_REF since the expression is now considered dependent (dependent_type_p returns true for a NULL_TREE). But later during instantiation, tsubst is not yet prepared to handle a SCOPE_REF whose RHS is a variable template and the patch I posted seems to address that.
There is another bug lurking here, though. The following test case fails to compile, even with my proposed patch: struct A { template <int> static void *pf; }; template <typename B> bool foo () { return B::template pf<false>; } bool bar () { return foo<A>(); } 69098.C: In instantiation of ‘bool foo() [with B = A]’: 69098.C:16:17: required from here 69098.C:12:10: error: ‘A::pf<0>’ is not a template [-fpermissive] return B::template pf<false>; ^
Author: ppalka Date: Fri Feb 12 01:11:52 2016 New Revision: 233365 URL: https://gcc.gnu.org/viewcvs?rev=233365&root=gcc&view=rev Log: Fix PR c++/69098 (bogus errors with static data member template) gcc/cp/ChangeLog: PR c++/69098 * pt.c (lookup_and_finish_template_variable): New function, extracted from ... (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: ... here. (tsubst_qualified_id): Consider that EXPR might be a variable template. * typeck.c (check_template_keyword): Don't emit an error if DECL is a variable template. gcc/testsuite/ChangeLog: PR c++/69098 * g++.dg/cpp1y/69098.C: New test. * g++.dg/cpp1y/69098-2.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp1y/69098-2.C trunk/gcc/testsuite/g++.dg/cpp1y/69098.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/pt.c trunk/gcc/cp/typeck.c trunk/gcc/testsuite/ChangeLog
Is this fixed now?
Oops yeah, fixed for GCC 6.