Implement N4051 - Allow typename in a template template parameter
cp/ 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. testsuite/ 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. From-SVN: r213065
This commit is contained in:
parent
a634323ae0
commit
37545fa722
@ -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 <paolo.carlini@oracle.com>
|
||||
|
||||
PR c++/50961
|
||||
|
@ -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 %<class%> or %<typename%>");
|
||||
|
||||
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
|
||||
|
@ -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 <burnus@net-b.de>
|
||||
|
||||
* gfortran.dg/storage_size_5.f90: New.
|
||||
|
11
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C
Normal file
11
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-neg.C
Normal file
@ -0,0 +1,11 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "" }
|
||||
|
||||
template<template<typename> struct X> // { dg-error "expected .class. or .typename. before" }
|
||||
struct D {};
|
||||
|
||||
template<template<typename> X> // { dg-error "expected .class. or .typename. before" }
|
||||
struct E {};
|
||||
|
||||
// { dg-error "expected identifier" "expected" { target *-*-* } 4 }
|
||||
// { dg-error "expected .>." "expected" { target *-*-* } 4 }
|
28
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C
Normal file
28
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm-ped-neg.C
Normal file
@ -0,0 +1,28 @@
|
||||
// { dg-do compile { target c++1y_down } }
|
||||
// { dg-options "-pedantic" }
|
||||
|
||||
template<typename T>
|
||||
struct A {};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename T>
|
||||
using B = int;
|
||||
#endif
|
||||
|
||||
template<template<typename> class X>
|
||||
struct C {};
|
||||
|
||||
C<A> ca;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
C<B> cb;
|
||||
#endif
|
||||
|
||||
template<template<typename> typename X> // { dg-warning "ISO C.. forbids typename key in template template parameter" }
|
||||
struct D {};
|
||||
|
||||
D<A> da;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
D<B> db;
|
||||
#endif
|
28
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C
Normal file
28
gcc/testsuite/g++.dg/cpp1z/typename-tmpl-tmpl-parm.C
Normal file
@ -0,0 +1,28 @@
|
||||
// { dg-do compile }
|
||||
// { dg-options "" }
|
||||
|
||||
template<typename T>
|
||||
struct A {};
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
template<typename T>
|
||||
using B = int;
|
||||
#endif
|
||||
|
||||
template<template<typename> class X>
|
||||
struct C {};
|
||||
|
||||
C<A> ca;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
C<B> cb;
|
||||
#endif
|
||||
|
||||
template<template<typename> typename X>
|
||||
struct D {};
|
||||
|
||||
D<A> da;
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
D<B> db;
|
||||
#endif
|
@ -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 { } {
|
||||
|
Loading…
Reference in New Issue
Block a user