https://gcc.gnu.org/g:088d18f1833e84cd5153cdae7687331edb56e948
commit r17-5099-g088d18f1833e84cd5153cdae7687331edb56e948 Author: Marek Polacek <[email protected]> Date: Fri Oct 9 16:21:46 2026 -0400 c++: using in init-stmt followed by colon accepted [PR127780] We accept the stray ':' in if (using T = int; : x) because we're fooled into thinking it's a range-for. Fix it the obvious way: cp_parser_alias_declaration already consumes the ';', so a following ':' can't belong to a range-for declaration. Also, it's better to point at the location of the 'using' than at whatever follows it. PR c++/127780 gcc/cp/ChangeLog: * parser.cc (cp_parser_init_statement): Use the location of 'using' in the C++23 pedwarn. Only consume the ':' if expect_semicolon_p. gcc/testsuite/ChangeLog: * g++.dg/cpp23/init-stmt3.C: New test. * g++.dg/cpp23/init-stmt4.C: New test. Reviewed-by: Jason Merrill <[email protected]> Diff: --- gcc/cp/parser.cc | 7 ++++--- gcc/testsuite/g++.dg/cpp23/init-stmt3.C | 12 ++++++++++++ gcc/testsuite/g++.dg/cpp23/init-stmt4.C | 9 +++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc index 48e3117a71e7..3b3adc0f09a7 100644 --- a/gcc/cp/parser.cc +++ b/gcc/cp/parser.cc @@ -16704,12 +16704,12 @@ cp_parser_init_statement (cp_parser *parser, tree *decl) bool expect_semicolon_p = true; if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING)) { + const location_t loc = cp_lexer_peek_token (parser->lexer)->location; 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, + pedwarn (loc, OPT_Wc__23_extensions, "alias-declaration in init-statement only " "available with %<-std=c++23%> or %<-std=gnu++23%>"); } @@ -16719,7 +16719,8 @@ cp_parser_init_statement (cp_parser *parser, tree *decl) /*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)) + if (expect_semicolon_p + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) { /* It is a range-for, consume the ':'. */ cp_lexer_consume_token (parser->lexer); diff --git a/gcc/testsuite/g++.dg/cpp23/init-stmt3.C b/gcc/testsuite/g++.dg/cpp23/init-stmt3.C new file mode 100644 index 000000000000..53b693abe2b9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/init-stmt3.C @@ -0,0 +1,12 @@ +// PR c++/127780 +// { dg-do compile { target c++23 } } + +void +f (int x) +{ + if (using T = int; : x) {} // { dg-error "expected primary-expression before .:.|expected .\\)." } + switch (using T = int; : x) {} // { dg-error "expected primary-expression before .:.|expected .\\)." } + for (using T = int; : x) {} // { dg-error "expected primary-expression before .:.|expected .\\)." } +} + +// { dg-prune-output {before .\}. token} } diff --git a/gcc/testsuite/g++.dg/cpp23/init-stmt4.C b/gcc/testsuite/g++.dg/cpp23/init-stmt4.C new file mode 100644 index 000000000000..8a365b01fa06 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp23/init-stmt4.C @@ -0,0 +1,9 @@ +// PR c++/127780 +// { dg-do compile { target c++20 } } + +void +g () +{ + if (using T = int; T t = 1) // { dg-error "7:only available with" "" { target c++20_only } } + ; +}
