parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid template-ids.
authorJason Merrill <jason@redhat.com>
Tue, 6 Jan 2015 20:44:59 +0000 (15:44 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 6 Jan 2015 20:44:59 +0000 (15:44 -0500)
* parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid
template-ids.

From-SVN: r219269

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp1y/var-templ20.C [new file with mode: 0644]

index e5e54eae6f068687dec5eb9dc23d0c19299eff39..f9322bfd839c3f47255dd082c528294b338499c7 100644 (file)
@@ -1,5 +1,8 @@
 2015-01-06  Jason Merrill  <jason@redhat.com>
 
+       * parser.c (cp_parser_nested_name_specifier_opt): Diagnose invalid
+       template-ids.
+
        PR c++/64455
        * pt.c (type_dependent_expression_p): Handle variable templates.
        * constexpr.c (potential_constant_expression_1): Use it.
index 22dff06eb6c7a87b6b6221c41fc5dab76fb96ae4..5c23a36337a42abd6d55cc759dbe47e831722903 100644 (file)
@@ -5435,6 +5435,46 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
              cp_lexer_consume_token (parser->lexer);
            }
 
+         if (cp_lexer_next_token_is (parser->lexer, CPP_TEMPLATE_ID)
+             && cp_lexer_nth_token_is (parser->lexer, 2, CPP_SCOPE))
+           {
+             /* If we have a non-type template-id followed by ::, it can't
+                possibly be valid.  */
+             token = cp_lexer_peek_token (parser->lexer);
+             tree tid = token->u.tree_check_value->value;
+             if (TREE_CODE (tid) == TEMPLATE_ID_EXPR
+                 && TREE_CODE (TREE_OPERAND (tid, 0)) != IDENTIFIER_NODE)
+               {
+                 tree tmpl = NULL_TREE;
+                 if (is_overloaded_fn (tid))
+                   {
+                     tree fns = get_fns (tid);
+                     if (!OVL_CHAIN (fns))
+                       tmpl = OVL_CURRENT (fns);
+                     error_at (token->location, "function template-id %qD "
+                               "in nested-name-specifier", tid);
+                   }
+                 else
+                   {
+                     /* Variable template.  */
+                     tmpl = TREE_OPERAND (tid, 0);
+                     gcc_assert (variable_template_p (tmpl));
+                     error_at (token->location, "variable template-id %qD "
+                               "in nested-name-specifier", tid);
+                   }
+                 if (tmpl)
+                   inform (DECL_SOURCE_LOCATION (tmpl),
+                           "%qD declared here", tmpl);
+
+                 parser->scope = error_mark_node;
+                 error_p = true;
+                 /* As below.  */
+                 success = true;
+                 cp_lexer_consume_token (parser->lexer);
+                 cp_lexer_consume_token (parser->lexer);
+               }
+           }
+
          if (cp_parser_uncommitted_to_tentative_parse_p (parser))
            break;
          /* If the next token is an identifier, and the one after
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ20.C b/gcc/testsuite/g++.dg/cpp1y/var-templ20.C
new file mode 100644 (file)
index 0000000..38bd370
--- /dev/null
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++14 } }
+
+template <bool> struct Sink {};
+template <class T> void fn();
+template <class T> T var = T();
+
+template <class T> void f()
+{
+  Sink<fn<T>::value>();                // { dg-error "function" }
+  Sink<var<T>::value>();       // { dg-error "variable" }
+}
+// { dg-prune-output "template argument" }