public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-217] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539]
@ 2022-05-09 19:57 Marek Polacek
  0 siblings, 0 replies; only message in thread
From: Marek Polacek @ 2022-05-09 19:57 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:4b2a6628644b2ce15d877c1e85d14e314965a296

commit r13-217-g4b2a6628644b2ce15d877c1e85d14e314965a296
Author: Marek Polacek <polacek@redhat.com>
Date:   Sun May 8 17:36:34 2022 -0400

    c++: Implement P2324R2, labels at the end of compound-stmts [PR103539]
    
    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.
    
            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.

Diff:
---
 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(-)

diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index a28e0e20c75..84b45cf47ec 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" }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-05-09 19:57 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 19:57 [gcc r13-217] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539] Marek Polacek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).