PR c++/45976 - error with ::template in declarator.
authorJason Merrill <jason@redhat.com>
Wed, 28 Jun 2017 19:41:43 +0000 (15:41 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 28 Jun 2017 19:41:43 +0000 (15:41 -0400)
* pt.c (resolve_typename_type): Fix TEMPLATE_ID_EXPR handling.

From-SVN: r249753

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/template-keyword1.C [new file with mode: 0644]

index 3b3bb6d51fef61343afae508444883ce9f2d6403..7b7070adf9c5ad9892d2d953448ba9d5d9619ee4 100644 (file)
@@ -1,5 +1,8 @@
 2017-06-28  Jason Merrill  <jason@redhat.com>
 
+       PR c++/45976 - error with ::template in declarator.
+       * pt.c (resolve_typename_type): Fix TEMPLATE_ID_EXPR handling.
+
        PR c++/54769 - wrong lookup of dependent template-name.
        * parser.c (cp_parser_template_name): Handle dependent object type.
        (cp_parser_nested_name_specifier_opt): Make template_keyword_p a
index 957d22922d553d08f15f3ee560f4d8677dfc196b..b060a19094677fb374ab244d28c32bd368691dd2 100644 (file)
@@ -24624,26 +24624,38 @@ resolve_typename_type (tree type, bool only_current_p)
   
   /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
      find a TEMPLATE_DECL.  Otherwise, we want to find a TYPE_DECL.  */
+  tree fullname = TYPENAME_TYPE_FULLNAME (type);
   if (!decl)
     /*nop*/;
-  else if (identifier_p (TYPENAME_TYPE_FULLNAME (type))
+  else if (identifier_p (fullname)
           && TREE_CODE (decl) == TYPE_DECL)
     {
       result = TREE_TYPE (decl);
       if (result == error_mark_node)
        result = NULL_TREE;
     }
-  else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
+  else if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR
           && DECL_CLASS_TEMPLATE_P (decl))
     {
-      tree tmpl;
-      tree args;
       /* Obtain the template and the arguments.  */
-      tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
-      args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
+      tree tmpl = TREE_OPERAND (fullname, 0);
+      if (TREE_CODE (tmpl) == IDENTIFIER_NODE)
+       {
+         /* We get here with a plain identifier because a previous tentative
+            parse of the nested-name-specifier as part of a ptr-operator saw
+            ::template X<A>.  The use of ::template is necessary in a
+            ptr-operator, but wrong in a declarator-id.
+
+            [temp.names]: In a qualified-id of a declarator-id, the keyword
+            template shall not appear at the top level.  */
+         pedwarn (EXPR_LOC_OR_LOC (fullname, input_location), OPT_Wpedantic,
+                  "keyword %<template%> not allowed in declarator-id");
+         tmpl = decl;
+       }
+      tree args = TREE_OPERAND (fullname, 1);
       /* Instantiate the template.  */
       result = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
-                                     /*entering_scope=*/0,
+                                     /*entering_scope=*/true,
                                      tf_error | tf_user);
       if (result == error_mark_node)
        result = NULL_TREE;
diff --git a/gcc/testsuite/g++.dg/template/template-keyword1.C b/gcc/testsuite/g++.dg/template/template-keyword1.C
new file mode 100644 (file)
index 0000000..0f928a8
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/45976
+
+template<int a>
+struct A {
+    static const int value;
+   
+    template<int b>
+    struct B {
+        static const int value;
+    };
+};
+
+template<int a>
+template<int b>
+const int A<a>::template B<b>::value = 0; // { dg-error "keyword .template" }