On 5/8/22 20:26, Marek Polacek wrote:
This patch implements C++23 <https://wg21.link/p2324r2>, which allows
labels at the end of a compound statement.   Its C FE counterpart was
already implemented in r11-4813.

In cp_parser_statement I rely on in_compound to determine whether we're
in a compound-statement, so that the patch doesn't accidentally allow

   void fn(int c) {
     if (c)
   label:
   }

Strangely, in_compound was reset after seeing a label (this is tested in
c-c++-common/gomp/pr63326.c), so I've made a modifiable copy specific
for OpenMP #pragma purposes.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

OK.

        PR c++/103539

gcc/cp/ChangeLog:

        * parser.cc (cp_parser_statement): Constify the in_compound parameter.
        Create a modifiable copy.  Allow labels at the end of compound
        statements.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp23/label1.C: New test.
        * g++.dg/cpp23/label2.C: New test.
---
  gcc/cp/parser.cc                    | 43 +++++++++++---
  gcc/testsuite/g++.dg/cpp23/label1.C | 89 +++++++++++++++++++++++++++++
  gcc/testsuite/g++.dg/cpp23/label2.C | 52 +++++++++++++++++
  3 files changed, 175 insertions(+), 9 deletions(-)
  create mode 100644 gcc/testsuite/g++.dg/cpp23/label1.C
  create mode 100644 gcc/testsuite/g++.dg/cpp23/label2.C

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 3ebaa414a3d..a4c3d8aa234 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -12174,7 +12174,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser 
*parser, tree *pattrs,
       atomic-statement
IN_COMPOUND is true when the statement is nested inside a
-  cp_parser_compound_statement; this matters for certain pragmas.
+  cp_parser_compound_statement.
If IF_P is not NULL, *IF_P is set to indicate whether the statement
    is a (possibly labeled) if statement which is not enclosed in braces
@@ -12184,7 +12184,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser 
*parser, tree *pattrs,
static void
  cp_parser_statement (cp_parser* parser, tree in_statement_expr,
-                    bool in_compound, bool *if_p, vec<tree> *chain,
+                    const bool in_compound, bool *if_p, vec<tree> *chain,
                     location_t *loc_after_labels)
  {
    tree statement, std_attrs = NULL_TREE;
@@ -12192,6 +12192,9 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
    location_t statement_location, attrs_loc;
    bool in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
    bool has_std_attrs;
+  /* A copy of IN_COMPOUND which is set to false after seeing a label.
+     This matters for certain pragmas.  */
+  bool in_compound_for_pragma = in_compound;
restart:
    if (if_p != NULL)
@@ -12286,7 +12289,7 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
             Parse the label, and then use tail recursion to parse
             the statement.  */
          cp_parser_label_for_labeled_statement (parser, std_attrs);
-         in_compound = false;
+         in_compound_for_pragma = false;
          in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
          goto restart;
@@ -12370,7 +12373,21 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
             the statement.  */
cp_parser_label_for_labeled_statement (parser, std_attrs);
-         in_compound = false;
+
+         /* If there's no statement, it's not a labeled-statement, just
+            a label.  That's allowed in C++23, but only if we're at the
+            end of a compound-statement.  */
+         if (in_compound
+             && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+           {
+             location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+             if (cxx_dialect < cxx23)
+               pedwarn (loc, OPT_Wc__23_extensions,
+                        "label at end of compound statement only available "
+                        "with %<-std=c++2b%> or %<-std=gnu++2b%>");
+             return;
+           }
+         in_compound_for_pragma = false;
          in_omp_attribute_pragma = parser->lexer->in_omp_attribute_pragma;
          goto restart;
        }
@@ -12393,7 +12410,7 @@ cp_parser_statement (cp_parser* parser, tree 
in_statement_expr,
         the context of a compound, accept the pragma as a "statement" and
         return so that we can check for a close brace.  Otherwise we
         require a real statement and must go back and read one.  */
-      if (in_compound)
+      if (in_compound_for_pragma)
        cp_parser_pragma (parser, pragma_compound, if_p);
        else if (!cp_parser_pragma (parser, pragma_stmt, if_p))
        do_restart = true;
@@ -12544,9 +12561,13 @@ attr_chainon (tree attrs, tree attr)
/* Parse the label for a labeled-statement, i.e. - identifier :
-   case constant-expression :
-   default :
+   label:
+     attribute-specifier-seq[opt] identifier :
+     attribute-specifier-seq[opt] case constant-expression :
+     attribute-specifier-seq[opt] default :
+
+   labeled-statement:
+     label statement
GNU Extension:
     case constant-expression ... constant-expression : statement
@@ -12766,7 +12787,11 @@ cp_parser_expression_statement (cp_parser* parser, 
tree in_statement_expr)
  /* Parse a compound-statement.
compound-statement:
-     { statement-seq [opt] }
+     { statement-seq [opt] label-seq [opt] }
+
+   label-seq:
+     label
+     label-seq label
GNU extension: diff --git a/gcc/testsuite/g++.dg/cpp23/label1.C b/gcc/testsuite/g++.dg/cpp23/label1.C
new file mode 100644
index 00000000000..14657652f4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/label1.C
@@ -0,0 +1,89 @@
+// P2324R2 - Labels at the end of compound statements
+// PR c++/103539
+// { dg-do compile }
+// Test good cases.
+
+void
+p2324 ()
+{
+first:
+  int x;
+second:
+  x = 1;
+last:
+} // { dg-error "label at end of compound statement only available with" "" { 
target c++20_down } }
+
+void
+fn1 ()
+{
+  l1:
+} // { dg-error "label at end of compound statement only available with" "" { 
target c++20_down } }
+
+void
+fn2 ()
+{
+  if (1)
+    {
+l1:
+    } // { dg-error "label at end of compound statement only available with" 
"" { target c++20_down } }
+}
+
+void
+fn3 ()
+{
+  {
+    {
+label:
+    } // { dg-error "label at end of compound statement only available with" 
"" { target c++20_down } }
+  }
+}
+
+void
+fn4 ()
+{
+  switch (1)
+    {
+lab:
+    } // { dg-error "label at end of compound statement only available with" 
"" { target c++20_down } }
+}
+
+void
+fn5 ()
+{
+l1:
+l2:
+l3:
+} // { dg-error "label at end of compound statement only available with" "" { 
target c++20_down } }
+
+void
+fn6 ()
+{
+  ;
+l1:
+l2:
+l3:
+} // { dg-error "label at end of compound statement only available with" "" { 
target c++20_down } }
+
+
+#if __cplusplus >= 201103L
+void
+fn7 ()
+{
+  auto l = [](){
+    lab:
+  }; // { dg-error "label at end of compound statement only available with" "" { 
target { c++20_down && c++11 } } }
+}
+#endif
+
+void
+fn8 ()
+{
+  try
+    {
+lab1:
+    } // { dg-error "label at end of compound statement only available with" 
"" { target c++20_down } }
+  catch (int)
+    {
+lab2:
+    } // { dg-error "label at end of compound statement only available with" 
"" { target c++20_down } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/label2.C 
b/gcc/testsuite/g++.dg/cpp23/label2.C
new file mode 100644
index 00000000000..3457e71ace2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/label2.C
@@ -0,0 +1,52 @@
+// P2324R2 - Labels at the end of compound statements
+// PR c++/103539
+// { dg-do compile { target c++23 } }
+// Test bad cases.
+
+void
+fn1 ()
+{
+  /* A selection-statement wants a statement, but a mere label isn't a 
statement.  */
+  if (1)
+lab:
+} // { dg-error "expected" }
+
+void
+fn2 ()
+{
+  if (0)
+    {
+    }
+  else
+lab:
+} // { dg-error "expected" }
+
+void
+fn3 ()
+{
+  do
+lab:
+  while (0); // { dg-error "expected" }
+} // { dg-error "expected" }
+
+void
+fn4 ()
+{
+  for (;;)
+lab:
+} // { dg-error "expected" }
+
+void
+fn5 ()
+{
+  switch (1)
+  lab:
+} // { dg-error "expected" }
+
+void
+fn6 ()
+{
+  if (1)
+lab1:
+lab2:
+} // { dg-error "expected" }

base-commit: a1947c92f7cda5f6cf7b8d8a9a44f6dd45352c03

Reply via email to