public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539]
@ 2022-05-09  0:26 Marek Polacek
  2022-05-09 19:23 ` Jason Merrill
  0 siblings, 1 reply; 2+ messages in thread
From: Marek Polacek @ 2022-05-09  0:26 UTC (permalink / raw)
  To: GCC Patches, Jason Merrill

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?

	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
-- 
2.35.3


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539]
  2022-05-09  0:26 [PATCH] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539] Marek Polacek
@ 2022-05-09 19:23 ` Jason Merrill
  0 siblings, 0 replies; 2+ messages in thread
From: Jason Merrill @ 2022-05-09 19:23 UTC (permalink / raw)
  To: Marek Polacek, GCC Patches

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


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-05-09 19:23 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09  0:26 [PATCH] c++: Implement P2324R2, labels at the end of compound-stmts [PR103539] Marek Polacek
2022-05-09 19:23 ` Jason Merrill

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).