My patch to limit template lookup after -> and . to class templates sets parser->context->object_type even for a dependent object expression, so that we know that there was one. This is normally cleared in cp_parser_lookup_name, but cp_parser_template_name was optimizing away the call to that function for set_default, so we lost this important side-effect, and so when we went to look up random_positive we thought we were still looking up the name in object scope. Fixed by preserving the side-effect even when we don't make the call.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit a3f8ced9964242a69bacec5a94c14ce380380fec Author: Jason Merrill <ja...@redhat.com> Date: Fri Feb 17 16:20:10 2017 -0500 PR c++/79508 - lookup error with member template * parser.c (cp_parser_template_name): Clear parser->context->object_type if we aren't doing lookup. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 060962d..92d8cce 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -15719,6 +15719,7 @@ cp_parser_template_name (cp_parser* parser, cp_lexer_purge_tokens_after (parser->lexer, start); if (is_identifier) *is_identifier = true; + parser->context->object_type = NULL_TREE; return identifier; } @@ -15730,7 +15731,12 @@ cp_parser_template_name (cp_parser* parser, && (!parser->scope || (TYPE_P (parser->scope) && dependent_type_p (parser->scope)))) - return identifier; + { + /* We're optimizing away the call to cp_parser_lookup_name, but we + still need to do this. */ + parser->context->object_type = NULL_TREE; + return identifier; + } } /* Look up the name. */ diff --git a/gcc/testsuite/g++.dg/template/memtmpl5.C b/gcc/testsuite/g++.dg/template/memtmpl5.C new file mode 100644 index 0000000..c5c3634 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/memtmpl5.C @@ -0,0 +1,22 @@ +// PR c++/79508 + +struct C +{ + template< void(*F)()> void set_default() { } +}; + + +template <class T> void random_positive() +{ +} + +template<class T> void initialize(T& x) +{ + x.template set_default<random_positive<T> >(); +} + +int main () +{ + C x; + initialize<C>(x); +}