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 } }
+    ;
+}

Reply via email to