aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-06-28 15:41:49 -0400
committerJason Merrill <jason@gcc.gnu.org>2017-06-28 15:41:49 -0400
commit4516a545864a489d573c4c3aca498edd849899ad (patch)
tree19caa4248473de1e47f0aa8b7c6577994f588504
parent36f48ebd016d4ace605a864c7f7303dbc281748d (diff)
downloadgcc-4516a545864a489d573c4c3aca498edd849899ad.zip
gcc-4516a545864a489d573c4c3aca498edd849899ad.tar.gz
gcc-4516a545864a489d573c4c3aca498edd849899ad.tar.bz2
PR c++/55639 - partial specialization with ::template
* parser.c (cp_parser_class_head): Handle ::template. From-SVN: r249754
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/parser.c11
-rw-r--r--gcc/testsuite/g++.dg/template/partial-specialization8.C19
3 files changed, 33 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7b7070a..f4b93ca 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2017-06-28 Jason Merrill <jason@redhat.com>
+ PR c++/55639 - partial specialization with ::template
+ * parser.c (cp_parser_class_head): Handle ::template.
+
PR c++/45976 - error with ::template in declarator.
* pt.c (resolve_typename_type): Fix TEMPLATE_ID_EXPR handling.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index c9fc284..bd99c05 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -22602,6 +22602,9 @@ cp_parser_class_head (cp_parser* parser,
/*is_declaration=*/false);
/* If there was a nested-name-specifier, then there *must* be an
identifier. */
+
+ cp_token *bad_template_keyword = NULL;
+
if (nested_name_specifier)
{
type_start_token = cp_lexer_peek_token (parser->lexer);
@@ -22623,6 +22626,8 @@ cp_parser_class_head (cp_parser* parser,
class-name is a template-id; if we looked for the
template-name first we would stop after the template-name. */
cp_parser_parse_tentatively (parser);
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
+ bad_template_keyword = cp_lexer_consume_token (parser->lexer);
type = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
@@ -22742,6 +22747,12 @@ cp_parser_class_head (cp_parser* parser,
{
tree scope;
+ if (bad_template_keyword)
+ /* [temp.names]: in a qualified-id formed by a class-head-name, the
+ keyword template shall not appear at the top level. */
+ pedwarn (bad_template_keyword->location, OPT_Wpedantic,
+ "keyword %<template%> not allowed in class-head-name");
+
/* Reject typedef-names in class heads. */
if (!DECL_IMPLICIT_TYPEDEF_P (type))
{
diff --git a/gcc/testsuite/g++.dg/template/partial-specialization8.C b/gcc/testsuite/g++.dg/template/partial-specialization8.C
new file mode 100644
index 0000000..e3ffe3b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial-specialization8.C
@@ -0,0 +1,19 @@
+// PR c++/55639
+
+template <int number>
+struct SomeClass
+{
+ SomeClass() { }
+
+ template <typename E, int number2>
+ struct Fun {
+ static void
+ fun() { }
+ };
+};
+
+template <int number>
+template <typename E>
+struct SomeClass<number>::template Fun<E, 0> { // { dg-error "template" }
+ static void fun() { }
+};