+ Joseph On Mon, Nov 04, 2024 at 06:26:47PM -0500, Marek Polacek wrote: > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk? > > -- >8 -- > This patch implements C2y N3356, if declarations as described at > <https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3356.htm>. > > This feature is cognate with C++17 Selection statements with initializer > <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r1.html>, > but they are not the same yet. For example, C++17 allows > > if (lock (); int i = getval ()) > > whereas C2y does not. > > The proposal adds new grammar productions. selection-header is handled > in c_parser_selection_header which is the gist of the patch. > simple-declaration is handled by c_parser_declaration_or_fndef, which > gets a new parameter. > > PR c/117019 > > gcc/c/ChangeLog: > > * c-parser.cc (c_parser_declaration_or_fndef): Adjust declaration. > (c_parser_external_declaration): Adjust a call to > c_parser_declaration_or_fndef. > (c_parser_declaration_or_fndef): New bool parameter. Return a tree > instead of void. Add an error. Adjust for N3356. Adjust a call to > c_parser_declaration_or_fndef. > (c_parser_compound_statement_nostart): Adjust calls to > c_parser_declaration_or_fndef. > (c_parser_selection_header): New. > (c_parser_paren_selection_header): New. > (c_parser_if_statement): Call c_parser_paren_selection_header > instead of c_parser_paren_condition. > (c_parser_switch_statement): Call c_parser_selection_header instead of > c_parser_expression. > (c_parser_for_statement): Adjust calls to c_parser_declaration_or_fndef. > (c_parser_objc_methodprotolist): Likewise. > (c_parser_oacc_routine): Likewise. > (c_parser_omp_loop_nest): Likewise. > (c_parser_omp_declare_simd): Likewise. > > gcc/testsuite/ChangeLog: > > * gcc.dg/c23-if-decls-1.c: New test. > * gcc.dg/c23-if-decls-2.c: New test. > * gcc.dg/c2y-if-decls-1.c: New test. > * gcc.dg/c2y-if-decls-2.c: New test. > * gcc.dg/c2y-if-decls-3.c: New test. > * gcc.dg/c2y-if-decls-4.c: New test. > * gcc.dg/c2y-if-decls-5.c: New test. > * gcc.dg/c2y-if-decls-6.c: New test. > * gcc.dg/c2y-if-decls-7.c: New test. > * gcc.dg/gnu2y-if-decls-1.c: New test. > * gcc.dg/gnu99-if-decls-1.c: New test. > * gcc.dg/gnu99-if-decls-2.c: New test. > --- > gcc/c/c-parser.cc | 250 ++++++++++++++++++------ > gcc/testsuite/gcc.dg/c23-if-decls-1.c | 15 ++ > gcc/testsuite/gcc.dg/c23-if-decls-2.c | 6 + > gcc/testsuite/gcc.dg/c2y-if-decls-1.c | 154 +++++++++++++++ > gcc/testsuite/gcc.dg/c2y-if-decls-2.c | 38 ++++ > gcc/testsuite/gcc.dg/c2y-if-decls-3.c | 40 ++++ > gcc/testsuite/gcc.dg/c2y-if-decls-4.c | 191 ++++++++++++++++++ > gcc/testsuite/gcc.dg/c2y-if-decls-5.c | 35 ++++ > gcc/testsuite/gcc.dg/c2y-if-decls-6.c | 27 +++ > gcc/testsuite/gcc.dg/c2y-if-decls-7.c | 21 ++ > gcc/testsuite/gcc.dg/gnu2y-if-decls-1.c | 15 ++ > gcc/testsuite/gcc.dg/gnu99-if-decls-1.c | 15 ++ > gcc/testsuite/gcc.dg/gnu99-if-decls-2.c | 15 ++ > 13 files changed, 766 insertions(+), 56 deletions(-) > create mode 100644 gcc/testsuite/gcc.dg/c23-if-decls-1.c > create mode 100644 gcc/testsuite/gcc.dg/c23-if-decls-2.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-1.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-2.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-3.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-4.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-5.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-6.c > create mode 100644 gcc/testsuite/gcc.dg/c2y-if-decls-7.c > create mode 100644 gcc/testsuite/gcc.dg/gnu2y-if-decls-1.c > create mode 100644 gcc/testsuite/gcc.dg/gnu99-if-decls-1.c > create mode 100644 gcc/testsuite/gcc.dg/gnu99-if-decls-2.c > > diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc > index 179c772fb76..7ed5b40cf1d 100644 > --- a/gcc/c/c-parser.cc > +++ b/gcc/c/c-parser.cc > @@ -1634,8 +1634,8 @@ static bool c_parser_nth_token_starts_std_attributes > (c_parser *, > static tree c_parser_std_attribute_specifier_sequence (c_parser *); > static void c_parser_external_declaration (c_parser *); > static void c_parser_asm_definition (c_parser *); > -static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, > - bool, bool, tree * = NULL, > +static tree c_parser_declaration_or_fndef (c_parser *, bool, bool, bool, > + bool, bool, bool, tree * = NULL, > vec<c_token> * = NULL, > bool have_attrs = false, > tree attrs = NULL, > @@ -2060,7 +2060,8 @@ c_parser_external_declaration (c_parser *parser) > an @interface or @protocol with prefix attributes). We can > only tell which after parsing the declaration specifiers, if > any, and the first declarator. */ > - c_parser_declaration_or_fndef (parser, true, true, true, false, true); > + c_parser_declaration_or_fndef (parser, true, true, true, false, true, > + false); > break; > } > } > @@ -2145,7 +2146,13 @@ handle_assume_attribute (location_t here, tree attrs, > bool nested) > parsed in the caller (in contexts where such attributes had to be > parsed to determine whether what follows is a declaration or a > statement); HAVE_ATTRS says whether there were any such attributes > - (even empty). > + (even empty). If SIMPLE_OK, the construct can be a simple-declaration; > + in that case, the ';' is not consumed (left to the caller so that it > + can figure out if there was a simple-declaration or not), there must > + be an initializer, and only one object may be declared. When SIMPLE_OK > + is true we are called from c_parser_selection_header. > + > + Returns the resulting declaration, if there was any with an initializer. > > declaration: > declaration-specifiers init-declarator-list[opt] ; > @@ -2167,6 +2174,10 @@ handle_assume_attribute (location_t here, tree attrs, > bool nested) > declarator simple-asm-expr[opt] gnu-attributes[opt] > declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer > > + simple-declaration: > + attribute-specifier-sequence[opt] declaration-specifiers declarator > + = initializer > + > GNU extensions: > > nested-function-definition: > @@ -2213,10 +2224,11 @@ handle_assume_attribute (location_t here, tree attrs, > bool nested) > declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator > declaration-list[opt] compound-statement */ > > -static void > +static tree > c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, > bool static_assert_ok, bool empty_ok, > bool nested, bool start_attr_ok, > + bool simple_ok, > tree *objc_foreach_object_declaration > /* = NULL */, > vec<c_token> *omp_declare_simd_clauses > @@ -2232,6 +2244,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > tree all_prefix_attrs; > bool diagnosed_no_specs = false; > location_t here = c_parser_peek_token (parser)->location; > + tree result = NULL_TREE; > > add_debug_begin_stmt (c_parser_peek_token (parser)->location); > > @@ -2239,7 +2252,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT)) > { > c_parser_static_assert_declaration (parser); > - return; > + return result; > } > specs = build_null_declspecs (); > > @@ -2325,13 +2338,13 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > if (parser->error) > { > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > if (nested && !specs->declspecs_seen_p) > { > c_parser_error (parser, "expected declaration specifiers"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > > finish_declspecs (specs); > @@ -2366,6 +2379,10 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > break; > } > } > + > + if (simple_ok && specs->storage_class != csc_none) > + error_at (here, "invalid storage class in condition"); > + > if (c_parser_next_token_is (parser, CPP_SEMICOLON)) > { > bool handled_assume = false; > @@ -2383,7 +2400,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > c_parser_pragma (parser, pragma_external, NULL, NULL_TREE); > } > c_parser_consume_token (parser); > - return; > + return result; > } > if (specs->typespec_kind == ctsk_none > && lookup_attribute ("gnu", "assume", specs->attrs)) > @@ -2425,7 +2442,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > c_parser_consume_token (parser); > if (oacc_routine_data) > c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false); > - return; > + return result; > } > > /* Provide better error recovery. Note that a type name here is usually > @@ -2438,7 +2455,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > c_parser_error (parser, "expected %<;%>, identifier or %<(%>"); > parser->error = false; > shadow_tag_warned (specs, 1); > - return; > + return result; > } > else if (c_dialect_objc () && !any_auto_type_p) > { > @@ -2448,7 +2465,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > case CPP_PLUS: > case CPP_MINUS: > if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) > - return; > + return result; > if (specs->attrs) > { > warning_at (c_parser_peek_token (parser)->location, > @@ -2460,7 +2477,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > c_parser_objc_method_definition (parser); > else > c_parser_objc_methodproto (parser); > - return; > + return result; > break; > default: > break; > @@ -2475,15 +2492,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > case RID_AT_INTERFACE: > { > if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) > - return; > + return result; > c_parser_objc_class_definition (parser, specs->attrs); > - return; > + return result; > } > break; > case RID_AT_IMPLEMENTATION: > { > if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) > - return; > + return result; > if (specs->attrs) > { > warning_at (c_parser_peek_token (parser)->location, > @@ -2492,15 +2509,15 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > specs->attrs = NULL_TREE; > } > c_parser_objc_class_definition (parser, NULL_TREE); > - return; > + return result; > } > break; > case RID_AT_PROTOCOL: > { > if (c_parser_objc_diagnose_bad_element_prefix (parser, specs)) > - return; > + return result; > c_parser_objc_protocol_definition (parser, specs->attrs); > - return; > + return result; > } > break; > case RID_AT_ALIAS: > @@ -2532,6 +2549,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > prefix_attrs = specs->attrs; > all_prefix_attrs = prefix_attrs; > specs->attrs = NULL_TREE; > + bool more_than_one_decl = false; > while (true) > { > struct c_declarator *declarator; > @@ -2554,8 +2572,10 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > omp_declare_simd_clauses); > if (oacc_routine_data) > c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false); > - c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + /* This check is here purely to improve the diagnostic. */ > + if (!simple_ok) > + c_parser_skip_to_end_of_block_or_statement (parser); > + return result; > } > if (flag_openmp || flag_openmp_simd) > { > @@ -2572,7 +2592,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > "%<__auto_type%> requires a plain identifier" > " as declarator"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > if (std_auto_type_p) > { > @@ -2585,7 +2605,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > "%<auto%> requires a plain identifier, possibly with" > " attributes, as declarator"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > underspec_name = d->u.id.id; > } > @@ -2626,7 +2646,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > error_at (here, "attributes should be specified before the " > "declarator in a function definition"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > } > if (c_parser_next_token_is (parser, CPP_EQ)) > @@ -2766,6 +2786,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > maybe_warn_string_init (init_loc, TREE_TYPE (d), init); > finish_decl (d, init_loc, init.value, > init.original_type, asm_name); > + result = d; > } > } > else > @@ -2776,7 +2797,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > "%qs requires an initialized data declaration", > any_auto_type_p ? auto_type_keyword : "constexpr"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > > location_t lastloc = UNKNOWN_LOCATION; > @@ -2869,13 +2890,14 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > } > if (c_parser_next_token_is (parser, CPP_COMMA)) > { > + more_than_one_decl = true; > if (any_auto_type_p || specs->constexpr_p) > { > error_at (here, > "%qs may only be used with a single declarator", > any_auto_type_p ? auto_type_keyword : "constexpr"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > c_parser_consume_token (parser); > if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)) > @@ -2887,8 +2909,9 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > } > else if (c_parser_next_token_is (parser, CPP_SEMICOLON)) > { > - c_parser_consume_token (parser); > - return; > + if (!simple_ok) > + c_parser_consume_token (parser); > + return result; > } > else if (c_parser_next_token_is_keyword (parser, RID_IN)) > { > @@ -2897,13 +2920,20 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > Objective-C foreach statement. Do not consume the > token, so that the caller can use it to determine > that this indeed is a foreach context. */ > - return; > + return result; > } > else > { > - c_parser_error (parser, "expected %<,%> or %<;%>"); > - c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + if (!simple_ok) > + { > + c_parser_error (parser, "expected %<,%> or %<;%>"); > + c_parser_skip_to_end_of_block_or_statement (parser); > + } > + /* It's not valid to use if (int i = 2, j = 3). */ > + else if (more_than_one_decl) > + error_at (here, "declaration in condition can only declare " > + "a single object"); > + return result; > } > } > else if (any_auto_type_p || specs->constexpr_p) > @@ -2912,14 +2942,19 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > "%qs requires an initialized data declaration", > any_auto_type_p ? auto_type_keyword : "constexpr"); > c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + return result; > } > else if (!fndef_ok) > { > - c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, " > - "%<asm%> or %<__attribute__%>"); > - c_parser_skip_to_end_of_block_or_statement (parser); > - return; > + if (simple_ok && c_parser_next_token_is (parser, CPP_CLOSE_PAREN)) > + /* Let c_parser_selection_header emit the error. */; > + else > + { > + c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, " > + "%<asm%> or %<__attribute__%>"); > + c_parser_skip_to_end_of_block_or_statement (parser); > + } > + return result; > } > /* Function definition (nested or otherwise). */ > if (nested) > @@ -2988,7 +3023,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > while (c_parser_next_token_is_not (parser, CPP_EOF) > && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE)) > c_parser_declaration_or_fndef (parser, false, false, false, > - true, false); > + true, false, false); > debug_nonbind_markers_p = save_debug_nonbind_markers_p; > store_parm_decls (); > if (omp_declare_simd_clauses) > @@ -3018,7 +3053,7 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > pop_scope (); > > finish_function (endloc); > - return; > + return result; > } > /* If the definition was marked with __GIMPLE then parse the > function body as GIMPLE. */ > @@ -3059,6 +3094,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool > fndef_ok, > > break; > } > + > + return result; > } > > /* Parse an asm-definition (asm() outside a function body). This is a > @@ -7378,7 +7415,7 @@ c_parser_compound_statement_nostart (c_parser *parser) > mark_valid_location_for_stdc_pragma (false); > bool fallthru_attr_p = false; > c_parser_declaration_or_fndef (parser, true, !have_std_attrs, > - true, true, true, NULL, > + true, true, true, false, NULL, > NULL, have_std_attrs, std_attrs, > NULL, &fallthru_attr_p); > > @@ -7421,7 +7458,7 @@ c_parser_compound_statement_nostart (c_parser *parser) > } > mark_valid_location_for_stdc_pragma (false); > c_parser_declaration_or_fndef (parser, true, true, true, true, > - true); > + true, false); > if (in_omp_loop_block) > omp_for_parse_state->want_nested_loop = want_nested_loop; > /* Following the old parser, __extension__ does not > @@ -8075,11 +8112,12 @@ c_parser_condition (c_parser *parser) > return cond; > } > > -/* Parse a parenthesized condition from an if, do or while statement. > +/* Parse a parenthesized condition from a do or while statement. > > condition: > ( expression ) > */ > + > static tree > c_parser_paren_condition (c_parser *parser) > { > @@ -8092,6 +8130,103 @@ c_parser_paren_condition (c_parser *parser) > return cond; > } > > +/* Parse a selection-header: > + > + selection-header: > + expression > + declaration expression > + simple-declaration > + > + simple-declaration: > + attribute-specifier-sequence[opt] declaration-specifiers declarator > + = initializer > + > + SWITCH_P is true if we are called from c_parser_switch_statement; in > + that case, don't perform the truthvalue conversion. */ > + > +static c_expr > +c_parser_selection_header (c_parser *parser, bool switch_p) > +{ > + location_t loc = c_parser_peek_token (parser)->location; > + c_expr expr; > + bool parse_expr = true; > + tree std_attrs; > + bool have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1); > + if (have_std_attrs) > + std_attrs = c_parser_std_attribute_specifier_sequence (parser); > + else > + std_attrs = NULL_TREE; > + if (c_parser_next_tokens_start_declaration (parser)) > + { > + pedwarn_c23 (loc, OPT_Wpedantic, > + "ISO C does not support if declarations before C2Y"); > + expr.value > + = c_parser_declaration_or_fndef (parser, > + /*fndef_ok=*/false, > + /*static_assert_ok=*/false, > + /*empty_ok=*/false, > + /*nested=*/true, > + /*start_attr_ok=*/true, > + /*simple_ok=*/true, > + /*objc_foreach_object_decl=*/nullptr, > + /*omp_declare_simd_clauses=*/nullptr, > + have_std_attrs, > + std_attrs); > + if (c_parser_next_token_is (parser, CPP_SEMICOLON)) > + c_parser_consume_token (parser); > + else > + { > + /* A simple-declaration is a declaration that can appear in > + place of the controlling expression of a selection statement. > + In that case, there shall be an initializer. */ > + if (!expr.value) > + { > + error_at (loc, "declaration in the controlling expression must " > + "have an initializer"); > + expr.original_type = error_mark_node; > + expr.set_error (); > + return expr; > + } > + parse_expr = false; > + expr.original_type = TREE_TYPE (expr.value); > + } > + } > + else if (have_std_attrs) > + { > + c_parser_error (parser, "expected declaration"); > + expr.original_type = error_mark_node; > + expr.set_error (); > + return expr; > + } > + > + if (parse_expr) > + expr = c_parser_expression_conv (parser); > + if (!switch_p) > + { > + expr.value = c_objc_common_truthvalue_conversion (loc, expr.value); > + expr.value = c_fully_fold (expr.value, false, NULL); > + if (warn_sequence_point) > + verify_sequence_points (expr.value); > + } > + return expr; > +} > + > +/* Parse a selection-header enclosed in parentheses: > + > + ( selection-header ) > +*/ > + > +static tree > +c_parser_paren_selection_header (c_parser *parser) > +{ > + matching_parens parens; > + if (!parens.require_open (parser)) > + return error_mark_node; > + tree cond = c_parser_selection_header (parser, /*switch_p=*/false).value; > + parens.skip_until_found_close (parser); > + return cond; > +} > + > /* Parse a statement which is a block in C99. > > IF_P is used to track whether there's a (possibly labeled) if statement > @@ -8244,8 +8379,8 @@ c_parser_maybe_reclassify_token (c_parser *parser) > /* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4). > > if-statement: > - if ( expression ) statement > - if ( expression ) statement else statement > + if ( selection-header ) statement > + if ( selection-header ) statement else statement > > CHAIN is a vector of if-else-if conditions. > IF_P is used to track whether there's a (possibly labeled) if statement > @@ -8268,7 +8403,7 @@ c_parser_if_statement (c_parser *parser, bool *if_p, > vec<tree> *chain) > c_parser_consume_token (parser); > block = c_begin_compound_stmt (flag_isoc99); > loc = c_parser_peek_token (parser)->location; > - cond = c_parser_paren_condition (parser); > + cond = c_parser_paren_selection_header (parser); > in_if_block = parser->in_if_block; > parser->in_if_block = true; > first_body = c_parser_if_body (parser, &nested_if, if_tinfo); > @@ -8355,7 +8490,9 @@ c_parser_switch_statement (c_parser *parser, bool > *if_p, tree before_labels) > if (c_parser_next_token_is (parser, CPP_OPEN_PAREN) > && c_token_starts_typename (c_parser_peek_2nd_token (parser))) > explicit_cast_p = true; > - ce = c_parser_expression (parser); > + ce = c_parser_selection_header (parser, /*switch_p=*/true); > + /* The call above already performed convert_lvalue_to_rvalue, but with > + read_p=false. */ > ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true); > expr = ce.value; > /* ??? expr has no valid location? */ > @@ -8667,7 +8804,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, > unsigned short unroll, > || c_parser_nth_token_starts_std_attributes (parser, 1)) > { > c_parser_declaration_or_fndef (parser, true, true, true, true, true, > - &object_expression); > + false, &object_expression); > parser->objc_could_be_foreach_context = false; > > if (c_parser_next_token_is_keyword (parser, RID_IN)) > @@ -8698,7 +8835,7 @@ c_parser_for_statement (c_parser *parser, bool ivdep, > unsigned short unroll, > ext = disable_extension_diagnostics (); > c_parser_consume_token (parser); > c_parser_declaration_or_fndef (parser, true, true, true, true, > - true, &object_expression); > + true, false, &object_expression); > parser->objc_could_be_foreach_context = false; > > restore_extension_diagnostics (ext); > @@ -14050,7 +14187,7 @@ c_parser_objc_methodprotolist (c_parser *parser) > } > else > c_parser_declaration_or_fndef (parser, false, false, true, > - false, true); > + false, true, false); > break; > } > } > @@ -21170,12 +21307,12 @@ c_parser_oacc_routine (c_parser *parser, enum > pragma_context context) > while (c_parser_next_token_is (parser, CPP_KEYWORD) > && c_parser_peek_token (parser)->keyword == RID_EXTENSION); > c_parser_declaration_or_fndef (parser, true, true, true, false, true, > - NULL, NULL, false, NULL, &data); > + false, NULL, NULL, false, NULL, &data); > restore_extension_diagnostics (ext); > } > else > c_parser_declaration_or_fndef (parser, true, true, true, false, true, > - NULL, NULL, false, NULL, &data); > + false, NULL, NULL, false, NULL, &data); > } > } > > @@ -23136,7 +23273,8 @@ c_parser_omp_loop_nest (c_parser *parser, bool *if_p) > /* This is a declaration, which must be added to the pre_body code. */ > tree this_pre_body = push_stmt_list (); > c_in_omp_for = true; > - c_parser_declaration_or_fndef (parser, true, true, true, true, true); > + c_parser_declaration_or_fndef (parser, true, true, true, true, true, > + false); > c_in_omp_for = false; > this_pre_body = pop_stmt_list (this_pre_body); > append_to_statement_list_force (this_pre_body, > @@ -25378,12 +25516,12 @@ c_parser_omp_declare_simd (c_parser *parser, enum > pragma_context context) > while (c_parser_next_token_is (parser, CPP_KEYWORD) > && c_parser_peek_token (parser)->keyword == RID_EXTENSION); > c_parser_declaration_or_fndef (parser, true, true, true, false, true, > - NULL, &clauses); > + false, NULL, &clauses); > restore_extension_diagnostics (ext); > } > else > c_parser_declaration_or_fndef (parser, true, true, true, false, true, > - NULL, &clauses); > + false, NULL, &clauses); > break; > case pragma_struct: > case pragma_param: > @@ -25412,7 +25550,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum > pragma_context context) > || c_parser_nth_token_starts_std_attributes (parser, 1)) > { > c_parser_declaration_or_fndef (parser, true, true, true, true, > - true, NULL, &clauses, > + true, false, NULL, &clauses, > have_std_attrs, std_attrs); > restore_extension_diagnostics (ext); > break; > @@ -25422,7 +25560,7 @@ c_parser_omp_declare_simd (c_parser *parser, enum > pragma_context context) > else if (c_parser_next_tokens_start_declaration (parser)) > { > c_parser_declaration_or_fndef (parser, true, true, true, true, true, > - NULL, &clauses, have_std_attrs, > + false, NULL, &clauses, have_std_attrs, > std_attrs); > break; > } > diff --git a/gcc/testsuite/gcc.dg/c23-if-decls-1.c > b/gcc/testsuite/gcc.dg/c23-if-decls-1.c > new file mode 100644 > index 00000000000..ea968c67c6a > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c23-if-decls-1.c > @@ -0,0 +1,15 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=c23 -pedantic-errors" } */ > + > +void > +g () > +{ > + if (int i = 42); /* { dg-error "ISO C does not support if > declarations before C2Y" } */ > + if (int i = 42; i > 10); /* { dg-error "ISO C does not support if > declarations before C2Y" } */ > + if (int i, j; i = 42); /* { dg-error "ISO C does not support if > declarations before C2Y" } */ > + switch (int i = 42); /* { dg-error "ISO C does not support > if declarations before C2Y" } */ > + switch (int i = 42; i); /* { dg-error "ISO C does not support if > declarations before C2Y" } */ > + switch (int i, j; i = 42); /* { dg-error "ISO C does not support if > declarations before C2Y" } */ > +} > diff --git a/gcc/testsuite/gcc.dg/c23-if-decls-2.c > b/gcc/testsuite/gcc.dg/c23-if-decls-2.c > new file mode 100644 > index 00000000000..d53db715377 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c23-if-decls-2.c > @@ -0,0 +1,6 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=c23 -pedantic-errors -Wno-c23-c2y-compat" } */ > + > +#include "c23-if-decls-1.c" > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-1.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-1.c > new file mode 100644 > index 00000000000..417b8052775 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-1.c > @@ -0,0 +1,154 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do run } */ > +/* { dg-options "-std=c2y -Wc23-c2y-compat" } */ > +/* Test C2Y if declarations. Valid usages. */ > + > +int get () { return 42; } > +int foo (int i) { return i; } > + > +enum E { X = 1, Y }; > + > +void > +simple () > +{ > + if (int i = get ()) /* { dg-warning "if declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (int i = 0) /* { dg-warning "if declarations before C2Y" } */ > + __builtin_abort (); > + else > + foo (i); > + > + if (auto i = get ()) /* { dg-warning "if declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (__typeof__(get ()) i = get ()) /* { dg-warning "if declarations > before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (auto i = 0) /* { dg-warning "if declarations before C2Y" } */ > + __builtin_abort (); > + else > + foo (i); > + > + if (int (*f)(int) = foo) /* { dg-warning "if declarations before C2Y" } */ > + f (1); > + else > + __builtin_abort (); > + > + if ([[maybe_unused]] int i = get ()) /* { dg-warning "if declarations > before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (__attribute__((unused)) int i = get ()) /* { dg-warning "if > declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (enum E e = X) /* { dg-warning "if declarations before C2Y" } */ > + foo (e); > + else > + __builtin_abort (); > + > + if (constexpr int i = 42) /* { dg-warning "if declarations before C2Y" } > */ > + foo (i); > + else > + __builtin_abort (); > + > + if (int i = 1) /* { dg-warning "if declarations before C2Y" } */ > + if (int j = 2) /* { dg-warning "if declarations before C2Y" } */ > + if (int k = 3) /* { dg-warning "if declarations before C2Y" } */ > + foo (i + j + k); > + > + double i; > +} > + > +void > +expr () > +{ > + if (int i = get (); i == 42) /* { dg-warning "if declarations before > C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (int i = get (); i != 42) /* { dg-warning "if declarations before C2Y" > } */ > + __builtin_abort (); > + else > + foo (i); > + > + if (auto i = get (); i == 42) /* { dg-warning "if declarations before > C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (__typeof__(get ()) i = get (); i == 42) /* { dg-warning "if > declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (auto i = get (); i != 42) /* { dg-warning "if declarations before > C2Y" } */ > + __builtin_abort (); > + else > + foo (i); > + > + if (int (*f)(int) = foo; f (42)) /* { dg-warning "if declarations before > C2Y" } */ > + f (1); > + else > + __builtin_abort (); > + > + if ([[maybe_unused]] int i = get (); i == 42) /* { dg-warning "if > declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (__attribute__((unused)) int i = get (); i == 42) /* { dg-warning "if > declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (enum E e = X; e == X) /* { dg-warning "if declarations before C2Y" } > */ > + foo (e); > + else > + __builtin_abort (); > + > + if (constexpr int i = 42; i == 42) /* { dg-warning "if declarations > before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (int i = 1; i) /* { dg-warning "if declarations before C2Y" } */ > + if (int j = 2; j) /* { dg-warning "if declarations before C2Y" } */ > + if (int k = 3; k) /* { dg-warning "if declarations before C2Y" } */ > + foo (i + j + k); > + > + if (int i = 2, j = get (); i + j > 0) /* { dg-warning "if declarations > before C2Y" } */ > + foo (i + j); > + else > + __builtin_abort (); > + > + if (int i; i = 1) /* { dg-warning "if declarations before C2Y" } */ > + foo (i); > + else > + __builtin_abort (); > + > + if (int arr[] = { 1, 2, 3}; arr[0]) /* { dg-warning "if declarations > before C2Y" } */ > + foo (arr[0]); > + else > + __builtin_abort (); > + > + double i; > +} > + > +int > +main () > +{ > + simple (); > + expr (); > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-2.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-2.c > new file mode 100644 > index 00000000000..e06344e4fe0 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-2.c > @@ -0,0 +1,38 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=c2y" } */ > +/* Test C2Y if declarations. Invalid usages. */ > + > +void > +g (int g) > +{ > + if (;); /* { dg-error "expected" } */ > + if (int); /* { dg-error "expected|initializer" } */ > + if (auto); /* { dg-error "expected|initializer" } */ > + if (int;); /* { dg-error "initializer" } */ > + /* { dg-warning "empty" "" { target *-*-* } .-1 } */ > + if (auto;); /* { dg-error "empty|initializer" } */ > + if (int i); /* { dg-error "initializer" } */ > + if (int i;); /* { dg-error "expected" } */ > + if (int i = 0;); /* { dg-error "expected" } */ > + > + if (extern int i = 0); /* { dg-error "in condition|both .extern. and > initializer" } */ > + if (register int i = 0); /* { dg-error "in condition" } */ > + if (static int i = 0); /* { dg-error "in condition" } */ > + if (thread_local int i = 0); /* { dg-error "in condition|function-scope" } > */ > + if (typedef int i); /* { dg-error "in condition|initializer" } */ > + if (typedef int i = 0); /* { dg-error "in condition|initialized" } */ > + > + if (int i = 2, j = 3); /* { dg-error "only declare a single object" } */ > + > + if (void (*fp)(int)); /* { dg-error "initializer" } */ > + if ([[maybe_unused]] g); /* { dg-error "expected" } */ > + if ([[maybe_unused]] 42); /* { dg-error "expected" } */ > + if ([[maybe_unused]] int); /* { dg-error "expected|initializer" } */ > + if (__attribute__((unused)) g); /* { dg-error "initializer" } */ > + if (__attribute__((unused)) 42); /* { dg-error "expected|initializer" } */ > + if (__attribute__((unused)) int); /* { dg-error "expected|initializer" } > */ > + > + if (int arr[] = { 1 }); /* { dg-error "scalar is required" } */ > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-3.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-3.c > new file mode 100644 > index 00000000000..685f826e695 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-3.c > @@ -0,0 +1,40 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=c2y" } */ > +/* Test C2Y if declarations. Invalid usages. */ > + > +void > +g (int g) > +{ > + switch (;); /* { dg-error "expected" } */ > + switch (int); /* { dg-error "expected identifier" } */ > + /* { dg-error "declaration" "" { target *-*-* } .-1 } */ > + switch (auto); /* { dg-error "expected identifier" } */ > + /* { dg-error "declaration" "" { target *-*-* } .-1 } */ > + switch (int;); /* { dg-error "declaration" } */ > + /* { dg-warning "empty" "" { target *-*-* } .-1 } */ > + switch (auto;); /* { dg-error "empty|initializer" } */ > + switch (int i); /* { dg-error "initializer" } */ > + switch (int i;); /* { dg-error "expected" } */ > + switch (int i = 0;); /* { dg-error "expected" } */ > + > + switch (extern int i = 0); /* { dg-error "in condition|both .extern. and > initializer" } */ > + switch (register int i = 0); /* { dg-error "in condition" } */ > + switch (static int i = 0); /* { dg-error "in condition" } */ > + switch (thread_local int i = 0); /* { dg-error "in > condition|function-scope" } */ > + switch (typedef int i); /* { dg-error "in condition|initializer" } */ > + switch (typedef int i = 0); /* { dg-error "in condition|initialized" } */ > + > + switch (int i = 2, j = 3); /* { dg-error "only declare a single object" } > */ > + > + switch (void (*fp)(int)); /* { dg-error "initializer" } */ > + switch ([[maybe_unused]] g); /* { dg-error "expected" } */ > + switch ([[maybe_unused]] 42); /* { dg-error "expected" } */ > + switch ([[maybe_unused]] int); /* { dg-error "expected|initializer" } */ > + switch (__attribute__((unused)) g); /* { dg-error "initializer" } */ > + switch (__attribute__((unused)) 42); /* { dg-error "expected|initializer" > } */ > + switch (__attribute__((unused)) int); /* { dg-error > "expected|initializer" } */ > + > + switch (int arr[] = { 1 }); /* { dg-error "switch quantity not an > integer" } */ > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-4.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-4.c > new file mode 100644 > index 00000000000..f518adf7dd1 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-4.c > @@ -0,0 +1,191 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do run } */ > +/* { dg-options "-std=c2y -Wc23-c2y-compat" } */ > +/* Test C2Y if declarations. Valid usages. */ > + > +int get () { return 42; } > +int foo (int i) { return i; } > + > +enum E { X = 1, Y }; > + > +void > +simple () > +{ > + switch (int i = get ()) /* { dg-warning "if declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (int i = 0) /* { dg-warning "if declarations before C2Y" } */ > + { > + case 0: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (auto i = get ()) /* { dg-warning "if declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (__typeof__(get ()) i = get ()) /* { dg-warning "if declarations > before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (auto i = 0) /* { dg-warning "if declarations before C2Y" } */ > + { > + case 0: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch ([[maybe_unused]] int i = get ()) /* { dg-warning "if declarations > before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (__attribute__((unused)) int i = get ()) /* { dg-warning "if > declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (enum E e = X) /* { dg-warning "if declarations before C2Y" } */ > + { > + case X: > + foo (X); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (constexpr int i = 42) /* { dg-warning "if declarations before > C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + double i; > +} > + > +void > +expr () > +{ > + switch (int i = get (); i) /* { dg-warning "if declarations before C2Y" } > */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (auto i = get (); i) /* { dg-warning "if declarations before C2Y" > } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (__typeof__(get ()) i = get (); i) /* { dg-warning "if > declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (int (*f)(int) = foo; f (42)) /* { dg-warning "if declarations > before C2Y" } */ > + { > + case 42: > + foo (42); > + break; > + default: > + __builtin_abort (); > + } > + > + switch ([[maybe_unused]] int i = get (); i) /* { dg-warning "if > declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (__attribute__((unused)) int i = get (); i) /* { dg-warning "if > declarations before C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (enum E e = X; e) /* { dg-warning "if declarations before C2Y" } */ > + { > + case X: > + foo (X); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (constexpr int i = 42; i) /* { dg-warning "if declarations before > C2Y" } */ > + { > + case 42: > + foo (i); > + break; > + default: > + __builtin_abort (); > + } > + > + switch (int arr[] = { 1, 2, 3}; arr[0]) /* { dg-warning "if declarations > before C2Y" } */ > + { > + case 1: > + foo (arr[0]); > + break; > + default: > + __builtin_abort (); > + } > + > + double i; > +} > + > +int > +main () > +{ > + simple (); > + expr (); > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-5.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-5.c > new file mode 100644 > index 00000000000..dfab357c312 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-5.c > @@ -0,0 +1,35 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do run } */ > +/* { dg-options "-std=c2y" } */ > + > +int g; > +int get () { ++g; return 42; } > + > +struct S { int i; }; > + > +int > +main () > +{ > + if (auto x = get (); get (), x); > + if (g != 2) > + __builtin_abort (); > + > + switch (auto x = get (); get (), x); > + if (g != 4) > + __builtin_abort (); > + > + if (struct S s = { 42 }; s.i != 42) > + __builtin_abort (); > + > + if (int i = 42) > + { > + i = 0; > + if (int j = 42) > + j = 0; > + else > + j = 42; > + } > + else > + i = 42; > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-6.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-6.c > new file mode 100644 > index 00000000000..57dd9e01bde > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-6.c > @@ -0,0 +1,27 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do run } */ > +/* { dg-options "-std=c2y -Wall -Wextra" } */ > +/* Test VLAs. */ > + > +void foo (int) { } > + > +int > +main () > +{ > + int i = 3; > + > + if (int arr[i] = { }; !arr[0]) > + foo (arr[0]); > + else > + __builtin_abort (); > + > + switch (int arr[i] = { }; arr[0]) > + { > + case 0: > + foo (arr[0]); > + break; > + default: > + __builtin_abort (); > + } > +} > diff --git a/gcc/testsuite/gcc.dg/c2y-if-decls-7.c > b/gcc/testsuite/gcc.dg/c2y-if-decls-7.c > new file mode 100644 > index 00000000000..df451e3e779 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/c2y-if-decls-7.c > @@ -0,0 +1,21 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=c2y -Wall -Wextra" } */ > +/* Test VLAs. Invalid code. */ > + > +void foo (int) { } > + > +void > +g () > +{ > + int i = 3; > + > + switch (i) /* { dg-message "switch starts here" } */ > + { /* { dg-warning "statement will never be executed" } */ > + int arr[i] = { }; > + default: /* { dg-error "switch jumps into scope" } */ > + i = arr[0]; > + break; > + } > +} > diff --git a/gcc/testsuite/gcc.dg/gnu2y-if-decls-1.c > b/gcc/testsuite/gcc.dg/gnu2y-if-decls-1.c > new file mode 100644 > index 00000000000..65f526e9dc2 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/gnu2y-if-decls-1.c > @@ -0,0 +1,15 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu2y" } */ > + > +void > +g () > +{ > + if (int i = 42); > + if (int i = 42; i > 10); > + if (int i, j; i = 42); > + switch (int i = 42); > + switch (int i = 42; i); > + switch (int i, j; i = 42); > +} > diff --git a/gcc/testsuite/gcc.dg/gnu99-if-decls-1.c > b/gcc/testsuite/gcc.dg/gnu99-if-decls-1.c > new file mode 100644 > index 00000000000..6d7a3bc196b > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/gnu99-if-decls-1.c > @@ -0,0 +1,15 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu99 -Wpedantic" } */ > + > +void > +g () > +{ > + if (int i = 42); /* { dg-warning "ISO C does not support if > declarations before C2Y" } */ > + if (int i = 42; i > 10); /* { dg-warning "ISO C does not support if > declarations before C2Y" } */ > + if (int i, j; i = 42); /* { dg-warning "ISO C does not support if > declarations before C2Y" } */ > + switch (int i = 42); /* { dg-warning "ISO C does not support > if declarations before C2Y" } */ > + switch (int i = 42; i); /* { dg-warning "ISO C does not support if > declarations before C2Y" } */ > + switch (int i, j; i = 42); /* { dg-warning "ISO C does not support if > declarations before C2Y" } */ > +} > diff --git a/gcc/testsuite/gcc.dg/gnu99-if-decls-2.c > b/gcc/testsuite/gcc.dg/gnu99-if-decls-2.c > new file mode 100644 > index 00000000000..82f779c71c2 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/gnu99-if-decls-2.c > @@ -0,0 +1,15 @@ > +/* N3356 - if declarations. */ > +/* PR c/117019 */ > +/* { dg-do compile } */ > +/* { dg-options "-std=gnu99" } */ > + > +void > +g () > +{ > + if (int i = 42); > + if (int i = 42; i > 10); > + if (int i, j; i = 42); > + switch (int i = 42); > + switch (int i = 42; i); > + switch (int i, j; i = 42); > +} > > base-commit: fe97ac43e05a8da8a12fbad2208a1ebb19d2d6c9 > -- > 2.47.0 >
Marek