diff options
author | Marek Polacek <polacek@redhat.com> | 2021-10-21 11:10:02 -0400 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-10-26 11:34:53 -0400 |
commit | 5469d58d6620195c6275d11b474d686f5921c3ba (patch) | |
tree | c74e8137c6408bff107f4a2bfbfd89d5a9474855 /gcc/cp/parser.c | |
parent | 28006282028b548238cee4601117f21c498dc2b7 (diff) | |
download | gcc-5469d58d6620195c6275d11b474d686f5921c3ba.zip gcc-5469d58d6620195c6275d11b474d686f5921c3ba.tar.gz gcc-5469d58d6620195c6275d11b474d686f5921c3ba.tar.bz2 |
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.
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r-- | gcc/cp/parser.c | 70 |
1 files changed, 39 insertions, 31 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 49d951c..93335c8 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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); |