aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-06-28 15:41:43 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-06-28 15:41:43 -0400
commit36f48ebd016d4ace605a864c7f7303dbc281748d (patch)
tree23314e421c96fcafc0a55196f4681e1873a3f9e2 /gcc
parent1e5f79b61994f8ffccad62a58031f5937aa16ae3 (diff)
downloadgcc-36f48ebd016d4ace605a864c7f7303dbc281748d.zip
gcc-36f48ebd016d4ace605a864c7f7303dbc281748d.tar.gz
gcc-36f48ebd016d4ace605a864c7f7303dbc281748d.tar.bz2
PR c++/45976 - error with ::template in declarator.
* pt.c (resolve_typename_type): Fix TEMPLATE_ID_EXPR handling. From-SVN: r249753
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/testsuite/g++.dg/template/template-keyword1.C15
3 files changed, 37 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3b3bb6d..7b7070a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 957d229..b060a19 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 0000000..0f928a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/template-keyword1.C
@@ -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" }