On 07/22/2014 01:56 AM, Ville Voutilainen wrote:
+/* Parse a type-parameter-key.
+
+ type-parameter-key:
+ class
+ typedef
+
+ Returns the kind of type-parameter-key specified, or none_type to indicate
+ error. */
+
Typo above, should be typename, not typedef.
Thanks!
New patch..
OK?
cp/
2014-07-22 Edward Smith-Rowland <3dw...@verizon.net>
Implement N4051 - Allow typename in a template template parameter
* parser.c (enum required_token): Add RT_TYPE_PARAMETER_KEY;
(cp_parser_type_parameter_key): New funtion;
(cp_parser_token_is_type_parameter_key): Ditto;
(cp_parser_type_parameter): Look for type-parameter-key for cxx1z or
or greater; (cp_parser_required_error): Error for RT_TYPE_PARAMETER_KEY.
testsuite/
2014-07-22 Edward Smith-Rowland <3dw...@verizon.net>
Implement N4051 - Allow typename in a template template parameter
* g++.dg/cpp1z/typename-tmpl-tmpl-parm.C: New.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 178114d..dd5ddac 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -177,6 +177,7 @@ typedef enum required_token {
RT_INTERATION, /* iteration-statement */
RT_JUMP, /* jump-statement */
RT_CLASS_KEY, /* class-key */
+ RT_TYPE_PARAMETER_KEY, /* type-parameter-key */
RT_CLASS_TYPENAME_TEMPLATE, /* class, typename, or template */
RT_TRANSACTION_ATOMIC, /* __transaction_atomic */
RT_TRANSACTION_RELAXED, /* __transaction_relaxed */
@@ -2151,6 +2152,8 @@ static tree cp_parser_class_head
(cp_parser *, bool *);
static enum tag_types cp_parser_class_key
(cp_parser *);
+static enum tag_types cp_parser_type_parameter_key
+ (cp_parser* parser);
static void cp_parser_member_specification_opt
(cp_parser *);
static void cp_parser_member_declaration
@@ -2409,6 +2412,8 @@ static bool
cp_parser_nth_token_starts_template_argument_list_p
(cp_parser *, size_t);
static enum tag_types cp_parser_token_is_class_key
(cp_token *);
+static enum tag_types cp_parser_token_is_type_parameter_key
+ (cp_token *);
static void cp_parser_check_class_key
(enum tag_types, tree type);
static void cp_parser_check_access_in_redeclaration
@@ -13375,8 +13380,18 @@ cp_parser_type_parameter (cp_parser* parser, bool
*is_parameter_pack)
cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
- /* Look for the `class' keyword. */
- cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS);
+ if (cxx_dialect < cxx1z)
+ {
+ /* Look for the `class' keyword. */
+ cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS);
+ }
+ else
+ {
+ /* Look for the `class' or 'typename' keywords. */
+ enum tag_types tag_type = cp_parser_type_parameter_key (parser);
+ if (tag_type == none_type)
+ return error_mark_node;
+ }
/* If the next token is an ellipsis, we have a template
argument pack. */
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -20258,6 +20273,33 @@ cp_parser_class_key (cp_parser* parser)
return tag_type;
}
+/* Parse a type-parameter-key.
+
+ type-parameter-key:
+ class
+ typename
+
+ Returns the kind of type-parameter-key specified, or none_type to indicate
+ error. */
+
+static enum tag_types
+cp_parser_type_parameter_key (cp_parser* parser)
+{
+ cp_token *token;
+ enum tag_types tag_type;
+
+ /* Look for the type-parameter-key. */
+ token = cp_parser_require (parser, CPP_KEYWORD, RT_TYPE_PARAMETER_KEY);
+ if (!token)
+ return none_type;
+
+ /* Check to see if the TOKEN is a type-parameter-key. */
+ tag_type = cp_parser_token_is_type_parameter_key (token);
+ if (!tag_type)
+ cp_parser_error (parser, "expected type-parameter-key");
+ return tag_type;
+}
+
/* Parse an (optional) member-specification.
member-specification:
@@ -24543,6 +24585,9 @@ cp_parser_required_error (cp_parser *parser,
case RT_CLASS_KEY:
cp_parser_error (parser, "expected class-key");
return;
+ case RT_TYPE_PARAMETER_KEY:
+ cp_parser_error (parser, "expected %<class%> or %<typename%>");
+ return;
case RT_CLASS_TYPENAME_TEMPLATE:
cp_parser_error (parser,
"expected %<class%>, %<typename%>, or %<template%>");
@@ -24776,6 +24821,24 @@ cp_parser_token_is_class_key (cp_token* token)
}
}
+/* Returns the kind of tag indicated by TOKEN, if it is a type-parameter-key,
+ or none_type otherwise. */
+
+static enum tag_types
+cp_parser_token_is_type_parameter_key (cp_token* token)
+{
+ switch (token->keyword)
+ {
+ case RID_CLASS:
+ return class_type;
+ case RID_TYPENAME:
+ return typename_type;
+
+ default:
+ return none_type;
+ }
+}
+
/* Issue an error message if the CLASS_KEY does not match the TYPE. */
static void
diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C
b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C
new file mode 100644
index 0000000..0a4e26f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C
@@ -0,0 +1,21 @@
+// { dg-options "-std=c++1z" }
+
+template<typename T>
+ struct A {};
+
+template<typename T>
+ using B = int;
+
+template<template<typename> class X>
+ struct C {};
+
+C<A> ca;
+
+C<B> cb;
+
+template<template<typename> typename X>
+ struct D {};
+
+D<A> da;
+
+D<B> db;