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);
+}

Reply via email to