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