diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 779e087e444..cfe0a480824 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2014-07-25 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement N4051 - Allow typename in a template template parameter + * parser.c (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 all versions + but pedwarn for less than cxx1z. + 2014-07-17 Paolo Carlini PR c++/50961 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 178114d2c84..32c7a3fe146 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2151,6 +2151,8 @@ static tree cp_parser_class_head (cp_parser *, bool *); static enum tag_types cp_parser_class_key (cp_parser *); +static void 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 +2411,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 +13379,8 @@ 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); + /* Look for the `class' or 'typename' keywords. */ + cp_parser_type_parameter_key (parser); /* 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 +20262,35 @@ cp_parser_class_key (cp_parser* parser) return tag_type; } +/* Parse a type-parameter-key. + + type-parameter-key: + class + typename + */ + +static void +cp_parser_type_parameter_key (cp_parser* parser) +{ + /* Look for the type-parameter-key. */ + enum tag_types tag_type = none_type; + cp_token *token = cp_lexer_peek_token (parser->lexer); + if ((tag_type = cp_parser_token_is_type_parameter_key (token)) != none_type) + { + cp_lexer_consume_token (parser->lexer); + if (pedantic && tag_type == typename_type && cxx_dialect < cxx1z) + /* typename is not allowed in a template template parameter + by the standard until C++1Z. */ + pedwarn (token->location, OPT_Wpedantic, + "ISO C++ forbids typename key in template template parameter;" + " use -std=c++1z or -std=gnu++1z"); + } + else + cp_parser_error (parser, "expected % or %"); + + return; +} + /* Parse an (optional) member-specification. member-specification: @@ -24776,6 +24809,27 @@ 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 or if the token is null. */ + +static enum tag_types +cp_parser_token_is_type_parameter_key (cp_token* token) +{ + if (!token) + return none_type; + + 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/ChangeLog b/gcc/testsuite/ChangeLog index ebf7badad82..92d1f9693d7 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,15 @@ +2014-07-25 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement N4051 - Allow typename in a template template parameter + * lib/target-supports.exp (check_effective_target_c++1y): Now + means C++1y and up. + (check_effective_target_c++1y_down): New. + (check_effective_target_c++1z_only): New. + (check_effective_target_c++1z): New. + * g++.dg/cpp1z/typename-tmpl-tmpl-parm.C: New. + * g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C: New. + * g++.dg/cpp1z/typename-tmpl-tmpl-parm-.C: New. + 2014-07-25 Tobias Burnus * gfortran.dg/storage_size_5.f90: New. diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C new file mode 100644 index 00000000000..29c699d0fd2 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C @@ -0,0 +1,11 @@ +// { dg-do compile } +// { dg-options "" } + +template struct X> // { dg-error "expected .class. or .typename. before" } + struct D {}; + +template X> // { dg-error "expected .class. or .typename. before" } + struct E {}; + +// { dg-error "expected identifier" "expected" { target *-*-* } 4 } +// { dg-error "expected .>." "expected" { target *-*-* } 4 } diff --git a/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C new file mode 100644 index 00000000000..48cb8ab0892 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C @@ -0,0 +1,28 @@ +// { dg-do compile { target c++1y_down } } +// { dg-options "-pedantic" } + +template + struct A {}; + +#if __cplusplus >= 201103L +template + using B = int; +#endif + +template class X> + struct C {}; + +C ca; + +#if __cplusplus >= 201103L +C cb; +#endif + +template typename X> // { dg-warning "ISO C.. forbids typename key in template template parameter" } + struct D {}; + +D da; + +#if __cplusplus >= 201103L +D db; +#endif 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 00000000000..4c3eae11203 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C @@ -0,0 +1,28 @@ +// { dg-do compile } +// { dg-options "" } + +template + struct A {}; + +#if __cplusplus >= 201103L +template + using B = int; +#endif + +template class X> + struct C {}; + +C ca; + +#if __cplusplus >= 201103L +C cb; +#endif + +template typename X> + struct D {}; + +D da; + +#if __cplusplus >= 201103L +D db; +#endif diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index ade3cad1b90..fa5137ea472 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -5707,7 +5707,16 @@ proc check_effective_target_c++1y_only { } { return [check-flags { { } { } { -std=c++1y -std=gnu++1y -std=c++14 -std=gnu++14 } }] } proc check_effective_target_c++1y { } { - return [check_effective_target_c++1y_only] + if [check_effective_target_c++1y_only] { + return 1 + } + return [check_effective_target_c++1z] +} +proc check_effective_target_c++1y_down { } { + if ![check_effective_target_c++] { + return 0 + } + return ![check_effective_target_c++1z] } proc check_effective_target_c++98_only { } { @@ -5717,6 +5726,16 @@ proc check_effective_target_c++98_only { } { return ![check_effective_target_c++11] } +proc check_effective_target_c++1z_only { } { + if ![check_effective_target_c++] { + return 0 + } + return [check-flags { { } { } { -std=c++1z -std=gnu++1z } }] +} +proc check_effective_target_c++1z { } { + return [check_effective_target_c++1z_only] +} + # Return 1 if expensive testcases should be run. proc check_effective_target_run_expensive_tests { } {