c++: P2360R0: Extend init-stmt to allow alias-decl [PR102617]
The following patch implements C++23 P2360R0. This proposal merely extends init-statement to contain alias-declaration. init-statement is used in if/for/switch. It also removes the unsightly duplication of code by calling cp_parser_init_statement twice. PR c++/102617 gcc/cp/ChangeLog: * parser.c (cp_parser_for): Maybe call cp_parser_init_statement twice. Warn about range-based for loops with initializer here. (cp_parser_init_statement): Don't duplicate code. Allow alias-declaration in init-statement. gcc/testsuite/ChangeLog: * g++.dg/cpp23/init-stmt1.C: New test. * g++.dg/cpp23/init-stmt2.C: New test.
This commit is contained in:
parent
2800628202
commit
5469d58d66
3 changed files with 95 additions and 31 deletions
|
@ -12040,6 +12040,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser *parser, tree *pattrs,
|
|||
init-statement:
|
||||
expression-statement
|
||||
simple-declaration
|
||||
alias-declaration
|
||||
|
||||
TM Extension:
|
||||
|
||||
|
@ -13327,6 +13328,23 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
|
|||
/* Begin the for-statement. */
|
||||
scope = begin_for_scope (&init);
|
||||
|
||||
/* Maybe parse the optional init-statement in a range-based for loop. */
|
||||
if (cp_parser_range_based_for_with_init_p (parser)
|
||||
/* Checked for diagnostic purposes only. */
|
||||
&& cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
|
||||
{
|
||||
tree dummy;
|
||||
cp_parser_init_statement (parser, &dummy);
|
||||
if (cxx_dialect < cxx20)
|
||||
{
|
||||
pedwarn (cp_lexer_peek_token (parser->lexer)->location,
|
||||
OPT_Wc__20_extensions,
|
||||
"range-based %<for%> loops with initializer only "
|
||||
"available with %<-std=c++20%> or %<-std=gnu++20%>");
|
||||
decl = error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the initialization. */
|
||||
is_range_for = cp_parser_init_statement (parser, &decl);
|
||||
|
||||
|
@ -13987,12 +14005,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
|
|||
return statement;
|
||||
}
|
||||
|
||||
/* Parse a init-statement or the declarator of a range-based-for.
|
||||
/* Parse an init-statement or the declarator of a range-based-for.
|
||||
Returns true if a range-based-for declaration is seen.
|
||||
|
||||
init-statement:
|
||||
expression-statement
|
||||
simple-declaration */
|
||||
simple-declaration
|
||||
alias-declaration */
|
||||
|
||||
static bool
|
||||
cp_parser_init_statement (cp_parser *parser, tree *decl)
|
||||
|
@ -14008,40 +14027,29 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
|
|||
bool is_range_for = false;
|
||||
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
|
||||
|
||||
/* Try to parse the init-statement. */
|
||||
if (cp_parser_range_based_for_with_init_p (parser))
|
||||
{
|
||||
tree dummy;
|
||||
cp_parser_parse_tentatively (parser);
|
||||
/* Parse the declaration. */
|
||||
cp_parser_simple_declaration (parser,
|
||||
/*function_definition_allowed_p=*/false,
|
||||
&dummy);
|
||||
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
|
||||
if (!cp_parser_parse_definitely (parser))
|
||||
/* That didn't work, try to parse it as an expression-statement. */
|
||||
cp_parser_expression_statement (parser, NULL_TREE);
|
||||
|
||||
if (cxx_dialect < cxx20)
|
||||
{
|
||||
pedwarn (cp_lexer_peek_token (parser->lexer)->location,
|
||||
OPT_Wc__20_extensions,
|
||||
"range-based %<for%> loops with initializer only "
|
||||
"available with %<-std=c++20%> or %<-std=gnu++20%>");
|
||||
*decl = error_mark_node;
|
||||
}
|
||||
}
|
||||
|
||||
/* A colon is used in range-based for. */
|
||||
parser->colon_corrects_to_scope_p = false;
|
||||
|
||||
/* We're going to speculatively look for a declaration, falling back
|
||||
to an expression, if necessary. */
|
||||
cp_parser_parse_tentatively (parser);
|
||||
/* Parse the declaration. */
|
||||
cp_parser_simple_declaration (parser,
|
||||
/*function_definition_allowed_p=*/false,
|
||||
decl);
|
||||
bool expect_semicolon_p = true;
|
||||
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
|
||||
{
|
||||
cp_parser_alias_declaration (parser);
|
||||
expect_semicolon_p = false;
|
||||
if (cxx_dialect < cxx23
|
||||
&& !cp_parser_uncommitted_to_tentative_parse_p (parser))
|
||||
pedwarn (cp_lexer_peek_token (parser->lexer)->location,
|
||||
OPT_Wc__23_extensions,
|
||||
"alias-declaration in init-statement only "
|
||||
"available with %<-std=c++23%> or %<-std=gnu++23%>");
|
||||
}
|
||||
else
|
||||
/* Parse the declaration. */
|
||||
cp_parser_simple_declaration (parser,
|
||||
/*function_definition_allowed_p=*/false,
|
||||
decl);
|
||||
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
|
||||
{
|
||||
|
@ -14054,7 +14062,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
|
|||
"range-based %<for%> loops only available with "
|
||||
"%<-std=c++11%> or %<-std=gnu++11%>");
|
||||
}
|
||||
else
|
||||
else if (expect_semicolon_p)
|
||||
/* The ';' is not consumed yet because we told
|
||||
cp_parser_simple_declaration not to. */
|
||||
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
|
||||
|
|
31
gcc/testsuite/g++.dg/cpp23/init-stmt1.C
Normal file
31
gcc/testsuite/g++.dg/cpp23/init-stmt1.C
Normal file
|
@ -0,0 +1,31 @@
|
|||
// PR c++/102617
|
||||
// P2360R0: Extend init-statement to allow alias-declaration
|
||||
// { dg-do compile { target c++20 } }
|
||||
// Test valid use.
|
||||
|
||||
int v[10];
|
||||
|
||||
void
|
||||
g ()
|
||||
{
|
||||
for (using T = int; (T) false;) // { dg-error "only available with" "" { target c++20_only } }
|
||||
;
|
||||
for (using T = int; T e : v) // { dg-error "only available with" "" { target c++20_only } }
|
||||
(void) e;
|
||||
if (using T = int; true) // { dg-error "only available with" "" { target c++20_only } }
|
||||
{
|
||||
T x = 0;
|
||||
(void) x;
|
||||
}
|
||||
if constexpr (using T = int; true) // { dg-error "only available with" "" { target c++20_only } }
|
||||
{
|
||||
T x = 0;
|
||||
(void) x;
|
||||
}
|
||||
switch (using T = int; 42) // { dg-error "only available with" "" { target c++20_only } }
|
||||
case 42:
|
||||
{
|
||||
T x = 0;
|
||||
(void) x;
|
||||
}
|
||||
}
|
25
gcc/testsuite/g++.dg/cpp23/init-stmt2.C
Normal file
25
gcc/testsuite/g++.dg/cpp23/init-stmt2.C
Normal file
|
@ -0,0 +1,25 @@
|
|||
// PR c++/102617
|
||||
// P2360R0: Extend init-statement to allow alias-declaration
|
||||
// { dg-do compile { target c++23 } }
|
||||
// Test invalid use.
|
||||
|
||||
int v[10];
|
||||
namespace N { using X = int; }
|
||||
|
||||
void
|
||||
g ()
|
||||
{
|
||||
for (using N::X; false;) // { dg-error "expected" }
|
||||
;
|
||||
for (using N::X; int e : v) // { dg-error "expected" }
|
||||
(void) e;
|
||||
for (using T = int; using U = int; int e : v) // { dg-error "" }
|
||||
;
|
||||
if (using N::X; false) // { dg-error "expected" }
|
||||
{}
|
||||
switch (using N::X; 0) // { dg-error "expected" }
|
||||
;
|
||||
if (using T = int;) // { dg-error "expected" }
|
||||
{
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue