diff options
Diffstat (limited to '0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch')
-rw-r--r-- | 0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch | 672 |
1 files changed, 672 insertions, 0 deletions
diff --git a/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch b/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch new file mode 100644 index 0000000..f4b1efd --- /dev/null +++ b/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch @@ -0,0 +1,672 @@ +From 0a34bb6b18cdf34cb9d4f34b1697e1bcfcff139b Mon Sep 17 00:00:00 2001 +From: Joseph Myers <joseph@codesourcery.com> +Date: Thu, 25 Aug 2022 21:02:57 +0000 +Subject: [PATCH 135/157] [Backport][SME] c: Support C2x empty initializer + braces + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=14cfa01755a66afbae2539f8b5796c960ddcecc6 + +ISO C2x standardizes empty initializer braces {}. Implement this +feature accordingly. The basic case was already supported and so just +needed diagnostic adjustments. However, the standard feature also +includes two cases that were not previously supported: empty +initializer braces for scalars, and empty initializer braces for +VLAs. Thus, add support for those features as well, updating existing +tests that expected them to be diagnosed. + +There was already some gimplifier support for converting +variable-sized initializations with empty CONSTRUCTORs to memset. +However, it didn't apply here; code earlier in gimplify_modify_expr +ended up calling gimplify_init_constructor via +gimplify_modify_expr_rhs, which ended up handling the CONSTRUCTOR in a +way that generated an ICE later. Add a check for this case earlier in +gimplify_modify_expr to avoid that issue. + +Bootstrapped with no regressions for x86_64-pc-linux-gnu. + +gcc/ + * gimplify.cc (gimplify_modify_expr): Convert initialization from + a variable-size CONSTRUCTOR to memset before call to + gimplify_modify_expr_rhs. + +gcc/c/ + * c-decl.cc (start_decl): Do not diagnose initialization of + variable-sized objects here. + * c-parser.cc (c_parser_braced_init): Add argument DECL. All + callers changed. + (c_parser_initializer): Diagnose initialization of variable-sized + objects other than with braced initializer. + (c_parser_braced_init): Use pedwarn_c11 for empty initializer + braces and update diagnostic text. Diagnose initialization of + variable-sized objects with nonempty braces. + * c-typeck.cc (digest_init): Update diagnostic for initialization + of variable-sized objects. + (really_start_incremental_init, set_designator) + (process_init_element): Update comments. + (pop_init_level): Allow scalar empty initializers. + +gcc/testsuite/ + * gcc.dg/c11-empty-init-1.c, gcc.dg/c11-empty-init-2.c, + gcc.dg/c11-empty-init-3.c, gcc.dg/c2x-empty-init-1.c, + gcc.dg/c2x-empty-init-2.c, gcc.dg/c2x-empty-init-3.c, + gcc.dg/gnu2x-empty-init-1.c, gcc.dg/gnu2x-empty-init-2.c: New + tests. + * gcc.dg/torture/dfp-default-init-1.c: Also test empty + initializers. + * gcc.dg/init-bad-1.c, gcc.dg/noncompile/pr71583.c, + gcc.dg/pr61096-1.c, gcc.dg/vla-init-2.c, gcc.dg/vla-init-3.c, + gcc.target/i386/sse2-bfloat16-scalar-typecheck.c: Update expected + diagnostics. + * gcc.dg/ubsan/c-shift-1.c: Use nonempty initializers for VLA + initializations expected to be diagnosed. +--- + gcc/c/c-decl.cc | 20 +----- + gcc/c/c-parser.cc | 24 +++++-- + gcc/c/c-typeck.cc | 23 ++++--- + gcc/gimplify.cc | 15 +++++ + gcc/testsuite/gcc.dg/c11-empty-init-1.c | 25 +++++++ + gcc/testsuite/gcc.dg/c11-empty-init-2.c | 25 +++++++ + gcc/testsuite/gcc.dg/c11-empty-init-3.c | 25 +++++++ + gcc/testsuite/gcc.dg/c2x-empty-init-1.c | 80 +++++++++++++++++++++++ + gcc/testsuite/gcc.dg/c2x-empty-init-2.c | 18 +++++ + gcc/testsuite/gcc.dg/c2x-empty-init-3.c | 25 +++++++ + gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c | 29 ++++++++ + gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c | 16 +++++ + gcc/testsuite/gcc.dg/init-bad-1.c | 3 +- + gcc/testsuite/gcc.dg/noncompile/pr71583.c | 2 +- + gcc/testsuite/gcc.dg/pr61096-1.c | 2 +- + gcc/testsuite/gcc.dg/ubsan/c-shift-1.c | 12 ++-- + gcc/testsuite/gcc.dg/vla-init-2.c | 1 - + gcc/testsuite/gcc.dg/vla-init-3.c | 1 - + 18 files changed, 301 insertions(+), 45 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-1.c + create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-2.c + create mode 100644 gcc/testsuite/gcc.dg/c11-empty-init-3.c + create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-1.c + create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-2.c + create mode 100644 gcc/testsuite/gcc.dg/c2x-empty-init-3.c + create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c + create mode 100644 gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c + +diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc +index 9d87a8cdb..685bb1757 100644 +--- a/gcc/c/c-decl.cc ++++ b/gcc/c/c-decl.cc +@@ -5166,29 +5166,15 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, + initialized = false; + else if (COMPLETE_TYPE_P (TREE_TYPE (decl))) + { +- /* A complete type is ok if size is fixed. */ +- +- if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl))) +- || C_DECL_VARIABLE_SIZE (decl)) +- { +- error ("variable-sized object may not be initialized"); +- initialized = false; +- } ++ /* A complete type is ok if size is fixed. If the size is ++ variable, an empty initializer is OK and nonempty ++ initializers will be diagnosed in the parser. */ + } + else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE) + { + error ("variable %qD has initializer but incomplete type", decl); + initialized = false; + } +- else if (C_DECL_VARIABLE_SIZE (decl)) +- { +- /* Although C99 is unclear about whether incomplete arrays +- of VLAs themselves count as VLAs, it does not make +- sense to permit them to be initialized given that +- ordinary VLAs may not be initialized. */ +- error ("variable-sized object may not be initialized"); +- initialized = false; +- } + } + + if (initialized) +diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc +index 486f46e1c..6db535d11 100644 +--- a/gcc/c/c-parser.cc ++++ b/gcc/c/c-parser.cc +@@ -1515,7 +1515,7 @@ static tree c_parser_simple_asm_expr (c_parser *); + static tree c_parser_gnu_attributes (c_parser *); + static struct c_expr c_parser_initializer (c_parser *, tree); + static struct c_expr c_parser_braced_init (c_parser *, tree, bool, +- struct obstack *); ++ struct obstack *, tree); + static void c_parser_initelt (c_parser *, struct obstack *); + static void c_parser_initval (c_parser *, struct c_expr *, + struct obstack *); +@@ -5247,11 +5247,15 @@ static struct c_expr + c_parser_initializer (c_parser *parser, tree decl) + { + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE)) +- return c_parser_braced_init (parser, NULL_TREE, false, NULL); ++ return c_parser_braced_init (parser, NULL_TREE, false, NULL, decl); + else + { + struct c_expr ret; + location_t loc = c_parser_peek_token (parser)->location; ++ if (decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) ++ error_at (loc, ++ "variable-sized object may not be initialized except " ++ "with an empty initializer"); + ret = c_parser_expr_no_commas (parser, NULL); + /* This is handled mostly by gimplify.cc, but we have to deal with + not warning about int x = x; as it is a GCC extension to turn off +@@ -5278,11 +5282,12 @@ location_t last_init_list_comma; + compound literal, and NULL_TREE for other initializers and for + nested braced lists. NESTED_P is true for nested braced lists, + false for the list of a compound literal or the list that is the +- top-level initializer in a declaration. */ ++ top-level initializer in a declaration. DECL is the declaration for ++ the top-level initializer for a declaration, otherwise NULL_TREE. */ + + static struct c_expr + c_parser_braced_init (c_parser *parser, tree type, bool nested_p, +- struct obstack *outer_obstack) ++ struct obstack *outer_obstack, tree decl) + { + struct c_expr ret; + struct obstack braced_init_obstack; +@@ -5300,10 +5305,15 @@ c_parser_braced_init (c_parser *parser, tree type, bool nested_p, + really_start_incremental_init (type); + if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)) + { +- pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces"); ++ pedwarn_c11 (brace_loc, OPT_Wpedantic, ++ "ISO C forbids empty initializer braces before C2X"); + } + else + { ++ if (decl && decl != error_mark_node && C_DECL_VARIABLE_SIZE (decl)) ++ error_at (brace_loc, ++ "variable-sized object may not be initialized except " ++ "with an empty initializer"); + /* Parse a non-empty initializer list, possibly with a trailing + comma. */ + while (true) +@@ -5559,7 +5569,7 @@ c_parser_initval (c_parser *parser, struct c_expr *after, + + if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after) + init = c_parser_braced_init (parser, NULL_TREE, true, +- braced_init_obstack); ++ braced_init_obstack, NULL_TREE); + else + { + init = c_parser_expr_no_commas (parser, after); +@@ -10312,7 +10322,7 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser, + error_at (type_loc, "compound literal has variable size"); + type = error_mark_node; + } +- init = c_parser_braced_init (parser, type, false, NULL); ++ init = c_parser_braced_init (parser, type, false, NULL, NULL_TREE); + finish_init (); + maybe_warn_string_init (type_loc, type, init); + +diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc +index 603b03fe1..0889dd4cb 100644 +--- a/gcc/c/c-typeck.cc ++++ b/gcc/c/c-typeck.cc +@@ -8267,7 +8267,9 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, + + if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST) + { +- error_init (init_loc, "variable-sized object may not be initialized"); ++ error_init (init_loc, ++ "variable-sized object may not be initialized except " ++ "with an empty initializer"); + return error_mark_node; + } + +@@ -8617,8 +8619,9 @@ really_start_incremental_init (tree type) + constructor_max_index = integer_minus_one_node; + + /* constructor_max_index needs to be an INTEGER_CST. Attempts +- to initialize VLAs will cause a proper error; avoid tree +- checking errors as well by setting a safe value. */ ++ to initialize VLAs with a nonempty initializer will cause a ++ proper error; avoid tree checking errors as well by setting a ++ safe value. */ + if (constructor_max_index + && TREE_CODE (constructor_max_index) != INTEGER_CST) + constructor_max_index = integer_minus_one_node; +@@ -9000,12 +9003,14 @@ pop_init_level (location_t loc, int implicit, + && !gnu_vector_type_p (constructor_type)) + { + /* A nonincremental scalar initializer--just return +- the element, after verifying there is just one. */ ++ the element, after verifying there is just one. ++ Empty scalar initializers are supported in C2X. */ + if (vec_safe_is_empty (constructor_elements)) + { +- if (!constructor_erroneous && constructor_type != error_mark_node) +- error_init (loc, "empty scalar initializer"); +- ret.value = error_mark_node; ++ if (constructor_erroneous || constructor_type == error_mark_node) ++ ret.value = error_mark_node; ++ else ++ ret.value = build_zero_cst (constructor_type); + } + else if (vec_safe_length (constructor_elements) != 1) + { +@@ -9090,7 +9095,7 @@ set_designator (location_t loc, bool array, + return true; + + /* Likewise for an initializer for a variable-size type. Those are +- diagnosed in digest_init. */ ++ diagnosed in the parser, except for empty initializer braces. */ + if (COMPLETE_TYPE_P (constructor_type) + && TREE_CODE (TYPE_SIZE (constructor_type)) != INTEGER_CST) + return true; +@@ -10251,7 +10256,7 @@ process_init_element (location_t loc, struct c_expr value, bool implicit, + return; + + /* Ignore elements of an initializer for a variable-size type. +- Those are diagnosed in digest_init. */ ++ Those are diagnosed in the parser (empty initializer braces are OK). */ + if (COMPLETE_TYPE_P (constructor_type) + && !poly_int_tree_p (TYPE_SIZE (constructor_type))) + return; +diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc +index a551c574a..91500e2fb 100644 +--- a/gcc/gimplify.cc ++++ b/gcc/gimplify.cc +@@ -6026,6 +6026,21 @@ gimplify_modify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, + return GS_ALL_DONE; + } + ++ /* Convert initialization from an empty variable-size CONSTRUCTOR to ++ memset. */ ++ if (TREE_TYPE (*from_p) != error_mark_node ++ && TYPE_SIZE_UNIT (TREE_TYPE (*from_p)) ++ && !poly_int_tree_p (TYPE_SIZE_UNIT (TREE_TYPE (*from_p))) ++ && TREE_CODE (*from_p) == CONSTRUCTOR ++ && CONSTRUCTOR_NELTS (*from_p) == 0) ++ { ++ maybe_with_size_expr (from_p); ++ gcc_assert (TREE_CODE (*from_p) == WITH_SIZE_EXPR); ++ return gimplify_modify_expr_to_memset (expr_p, ++ TREE_OPERAND (*from_p, 1), ++ want_value, pre_p); ++ } ++ + /* Insert pointer conversions required by the middle-end that are not + required by the frontend. This fixes middle-end type checking for + for example gcc.dg/redecl-6.c. */ +diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-1.c b/gcc/testsuite/gcc.dg/c11-empty-init-1.c +new file mode 100644 +index 000000000..120c28225 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c11-empty-init-1.c +@@ -0,0 +1,25 @@ ++/* Test C11 does not support empty initializers. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c11 -pedantic-errors" } */ ++ ++struct s { int a; }; ++struct s s = {}; /* { dg-error "empty initializer" } */ ++int x = {}; /* { dg-error "empty initializer" } */ ++float y = {}; /* { dg-error "empty initializer" } */ ++void *p = {}; /* { dg-error "empty initializer" } */ ++union u { int a; long b; }; ++union u z = {}; /* { dg-error "empty initializer" } */ ++int aa[2] = {}; /* { dg-error "empty initializer" } */ ++ ++void ++f (int a) ++{ ++ int vla[a] = {}; /* { dg-error "empty initializer" } */ ++ struct s as = {}; /* { dg-error "empty initializer" } */ ++ int ax = {}; /* { dg-error "empty initializer" } */ ++ float ay = {}; /* { dg-error "empty initializer" } */ ++ void *ap = {}; /* { dg-error "empty initializer" } */ ++ union u az = {}; /* { dg-error "empty initializer" } */ ++ int aaa[2] = {}; /* { dg-error "empty initializer" } */ ++ int t = (int) {}; /* { dg-error "empty initializer" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-2.c b/gcc/testsuite/gcc.dg/c11-empty-init-2.c +new file mode 100644 +index 000000000..3ec7c512a +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c11-empty-init-2.c +@@ -0,0 +1,25 @@ ++/* Test C11 does not support empty initializers. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c11 -pedantic" } */ ++ ++struct s { int a; }; ++struct s s = {}; /* { dg-warning "empty initializer" } */ ++int x = {}; /* { dg-warning "empty initializer" } */ ++float y = {}; /* { dg-warning "empty initializer" } */ ++void *p = {}; /* { dg-warning "empty initializer" } */ ++union u { int a; long b; }; ++union u z = {}; /* { dg-warning "empty initializer" } */ ++int aa[2] = {}; /* { dg-warning "empty initializer" } */ ++ ++void ++f (int a) ++{ ++ int vla[a] = {}; /* { dg-warning "empty initializer" } */ ++ struct s as = {}; /* { dg-warning "empty initializer" } */ ++ int ax = {}; /* { dg-warning "empty initializer" } */ ++ float ay = {}; /* { dg-warning "empty initializer" } */ ++ void *ap = {}; /* { dg-warning "empty initializer" } */ ++ union u az = {}; /* { dg-warning "empty initializer" } */ ++ int aaa[2] = {}; /* { dg-warning "empty initializer" } */ ++ int t = (int) {}; /* { dg-warning "empty initializer" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/c11-empty-init-3.c b/gcc/testsuite/gcc.dg/c11-empty-init-3.c +new file mode 100644 +index 000000000..fd43fa789 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c11-empty-init-3.c +@@ -0,0 +1,25 @@ ++/* Test C11 does not support empty initializers. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c11 -Wc11-c2x-compat" } */ ++ ++struct s { int a; }; ++struct s s = {}; /* { dg-warning "empty initializer" } */ ++int x = {}; /* { dg-warning "empty initializer" } */ ++float y = {}; /* { dg-warning "empty initializer" } */ ++void *p = {}; /* { dg-warning "empty initializer" } */ ++union u { int a; long b; }; ++union u z = {}; /* { dg-warning "empty initializer" } */ ++int aa[2] = {}; /* { dg-warning "empty initializer" } */ ++ ++void ++f (int a) ++{ ++ int vla[a] = {}; /* { dg-warning "empty initializer" } */ ++ struct s as = {}; /* { dg-warning "empty initializer" } */ ++ int ax = {}; /* { dg-warning "empty initializer" } */ ++ float ay = {}; /* { dg-warning "empty initializer" } */ ++ void *ap = {}; /* { dg-warning "empty initializer" } */ ++ union u az = {}; /* { dg-warning "empty initializer" } */ ++ int aaa[2] = {}; /* { dg-warning "empty initializer" } */ ++ int t = (int) {}; /* { dg-warning "empty initializer" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-1.c b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c +new file mode 100644 +index 000000000..1487a2b23 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-1.c +@@ -0,0 +1,80 @@ ++/* Test C2X support for empty initializers: valid use cases. */ ++/* { dg-do run } */ ++/* { dg-options "-std=c2x -pedantic-errors" } */ ++ ++extern void exit (int); ++extern void abort (void); ++ ++struct s { int a; }; ++struct s s = {}; ++int x = {}; ++float y = {}; ++void *p = {}; ++union u { int a; long b; }; ++union u z = {}; ++int aa[2] = {}; ++ ++void ++f (int a) ++{ ++ volatile int vla[a] = {}; ++ struct s as = {}; ++ int ax = {}; ++ float ay = {}; ++ void *ap = {}; ++ union u az = {}; ++ int aaa[2] = {}; ++ for (int i = 0; i < a; i++) ++ if (vla[i] != 0) ++ abort (); ++ if (as.a != 0) ++ abort (); ++ if (ax != 0) ++ abort (); ++ if (ay != 0) ++ abort (); ++ if (ap != 0) ++ abort (); ++ if (az.a != 0) ++ abort (); ++ if (aaa[0] != 0) ++ abort (); ++ if (aaa[1] != 0) ++ abort (); ++ if ((int) {} != 0) ++ abort (); ++ if ((float) {} != 0) ++ abort (); ++ if ((struct s) {}.a != 0) ++ abort (); ++ if ((union u) {}.a != 0) ++ abort (); ++ if ((int [5]) {}[2] != 0) ++ abort (); ++ /* Overwrite contents of vla before second call to make it more likely stack ++ contents are nonzero if proper initialization did not occur. */ ++ for (int i = 0; i < a; i++) ++ vla[i] = -1; ++} ++ ++int ++main (void) ++{ ++ f (100); ++ f (100); ++ if (s.a != 0) ++ abort (); ++ if (x != 0) ++ abort (); ++ if (y != 0) ++ abort (); ++ if (p != 0) ++ abort (); ++ if (z.a != 0) ++ abort (); ++ if (aa[0] != 0) ++ abort (); ++ if (aa[1] != 0) ++ abort (); ++ exit (0); ++} +diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-2.c b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c +new file mode 100644 +index 000000000..0dc81ce5b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-2.c +@@ -0,0 +1,18 @@ ++/* Test C2X support for empty initializers: invalid use cases. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c2x -pedantic-errors" } */ ++ ++/* Empty initialization is invalid for arrays of unknown size. This is ++ diagnosed via the diagnostic for zero-size arrays. */ ++int x[] = {}; /* { dg-error "zero or negative size array" } */ ++ ++void ++f (int a) ++{ ++ int x1[] = {}; /* { dg-error "zero or negative size array" } */ ++ int x2[][a] = {}; /* { dg-error "zero or negative size array" } */ ++ /* Nonempty VLA initializers are still invalid. */ ++ int x3[a] = { 0 }; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */ ++ /* Variable-size compound literals are still invalid. */ ++ (void) (int [a]) {}; /* { dg-error "compound literal has variable size" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/c2x-empty-init-3.c b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c +new file mode 100644 +index 000000000..472f8169c +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c2x-empty-init-3.c +@@ -0,0 +1,25 @@ ++/* Test empty initializers diagnosed in C2X mode with -Wc11-c2x-compat. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c2x -Wc11-c2x-compat" } */ ++ ++struct s { int a; }; ++struct s s = {}; /* { dg-warning "empty initializer" } */ ++int x = {}; /* { dg-warning "empty initializer" } */ ++float y = {}; /* { dg-warning "empty initializer" } */ ++void *p = {}; /* { dg-warning "empty initializer" } */ ++union u { int a; long b; }; ++union u z = {}; /* { dg-warning "empty initializer" } */ ++int aa[2] = {}; /* { dg-warning "empty initializer" } */ ++ ++void ++f (int a) ++{ ++ int vla[a] = {}; /* { dg-warning "empty initializer" } */ ++ struct s as = {}; /* { dg-warning "empty initializer" } */ ++ int ax = {}; /* { dg-warning "empty initializer" } */ ++ float ay = {}; /* { dg-warning "empty initializer" } */ ++ void *ap = {}; /* { dg-warning "empty initializer" } */ ++ union u az = {}; /* { dg-warning "empty initializer" } */ ++ int aaa[2] = {}; /* { dg-warning "empty initializer" } */ ++ int t = (int) {}; /* { dg-warning "empty initializer" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c +new file mode 100644 +index 000000000..e7dc9dfde +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-1.c +@@ -0,0 +1,29 @@ ++/* Test C2X support for empty initializers: valid use cases with GNU ++ extensions. */ ++/* { dg-do run } */ ++/* { dg-options "-std=gnu2x" } */ ++ ++extern void exit (int); ++extern void abort (void); ++ ++void ++f (int a) ++{ ++ struct s { volatile int x[a]; }; ++ struct s b = {}; ++ for (int i = 0; i < a; i++) ++ if (b.x[i] != 0) ++ abort (); ++ /* Overwrite contents of b.x before second call to make it more likely stack ++ contents are nonzero if proper initialization did not occur. */ ++ for (int i = 0; i < a; i++) ++ b.x[i] = -1; ++} ++ ++int ++main (void) ++{ ++ f (100); ++ f (100); ++ exit (0); ++} +diff --git a/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c +new file mode 100644 +index 000000000..69ee4e36b +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/gnu2x-empty-init-2.c +@@ -0,0 +1,16 @@ ++/* Test C2X support for empty initializers: invalid use cases with GNU ++ extensions. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=gnu2x" } */ ++ ++void ++f (int a) ++{ ++ /* Make sure a non-braced initializer for a VLA-in-struct is still not ++ allowed. */ ++ struct s { int x[a]; }; ++ struct s b; ++ for (int i = 0; i < a; i++) ++ b.x[i] = 0; ++ struct s c = b; /* { dg-error "variable-sized object may not be initialized except with an empty initializer" } */ ++} +diff --git a/gcc/testsuite/gcc.dg/init-bad-1.c b/gcc/testsuite/gcc.dg/init-bad-1.c +index 61734045f..0da10c315 100644 +--- a/gcc/testsuite/gcc.dg/init-bad-1.c ++++ b/gcc/testsuite/gcc.dg/init-bad-1.c +@@ -21,8 +21,7 @@ char t1[1] = { "xy" }; /* { dg-warning "initializer-string for array of 'char' i + char u[1] = { "x", "x" }; /* { dg-error "excess elements in 'char' array initializer" } */ + /* { dg-message "near init" "near" { target *-*-* } .-1 } */ + +-int i = { }; /* { dg-error "empty scalar initializer" } */ +-/* { dg-message "near init" "near" { target *-*-* } .-1 } */ ++int i = { }; + + int j = { 1 }; + +diff --git a/gcc/testsuite/gcc.dg/noncompile/pr71583.c b/gcc/testsuite/gcc.dg/noncompile/pr71583.c +index 5045b88b6..fe6e556ad 100644 +--- a/gcc/testsuite/gcc.dg/noncompile/pr71583.c ++++ b/gcc/testsuite/gcc.dg/noncompile/pr71583.c +@@ -5,7 +5,7 @@ void + f (int i) + { + (int (*)[++i]) { int }; /* { dg-error "expected" } */ +- (int (*)[++i]) { }; /* { dg-error "empty" } */ ++ (int (*)[++i]) { }; + (int (*)[++i]) { , }; /* { dg-error "expected" } */ + (int (*)[++i]) { f () }; /* { dg-error "too few" } */ + } +diff --git a/gcc/testsuite/gcc.dg/pr61096-1.c b/gcc/testsuite/gcc.dg/pr61096-1.c +index e707904c0..f41789c5f 100644 +--- a/gcc/testsuite/gcc.dg/pr61096-1.c ++++ b/gcc/testsuite/gcc.dg/pr61096-1.c +@@ -36,7 +36,7 @@ struct S s = { { 1 }, { 3 } }; /* { dg-error "23:extra brace group at end of ini + struct g g1 = { {0, { 1 } } }; /* { dg-error "21:initialization of flexible array member in a nested context" } */ + struct g g2 = { .f[0] = 1 }; /* { dg-error "20:array index in non-array initializer" } */ + +-__extension__ int a8 = { }; /* { dg-error "24:empty scalar initializer" } */ ++__extension__ int a8 = { }; + int a9[10] = {[1.2] = 2 }; /* { dg-error "16:array index in initializer not of integer type" } */ + int a10[10] = {[e] = 2 }; /* { dg-error "17:nonconstant array index in initializer" } */ + __extension__ int a11[10] = {[1 ... e] = 1 }; /* { dg-error "31:nonconstant array index in initializer" } */ +diff --git a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c +index 9d561016f..f88ee2de3 100644 +--- a/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c ++++ b/gcc/testsuite/gcc.dg/ubsan/c-shift-1.c +@@ -7,12 +7,12 @@ int + main (void) + { + /* None of the following should pass. */ +- int A[1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ +- int B[-1 >> -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ +- int D[1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ +- int E[-1 << -1] = {}; /* { dg-error "variable-sized object may not be initialized" } */ +- int F[-1 >> 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */ +- int G[1 << 200] = {}; /* { dg-error "variable-sized object may not be initialized" } */ ++ int A[1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ ++ int B[-1 >> -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ ++ int D[1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ ++ int E[-1 << -1] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ ++ int F[-1 >> 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ ++ int G[1 << 200] = { 0 }; /* { dg-error "variable-sized object may not be initialized" } */ + + return 0; + } +diff --git a/gcc/testsuite/gcc.dg/vla-init-2.c b/gcc/testsuite/gcc.dg/vla-init-2.c +index 19fbffc26..f23630a36 100644 +--- a/gcc/testsuite/gcc.dg/vla-init-2.c ++++ b/gcc/testsuite/gcc.dg/vla-init-2.c +@@ -7,4 +7,3 @@ + + const int i = 1; + void foo() { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */ +-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */ +diff --git a/gcc/testsuite/gcc.dg/vla-init-3.c b/gcc/testsuite/gcc.dg/vla-init-3.c +index 55e1de69c..a854f1268 100644 +--- a/gcc/testsuite/gcc.dg/vla-init-3.c ++++ b/gcc/testsuite/gcc.dg/vla-init-3.c +@@ -6,4 +6,3 @@ + /* { dg-options "" } */ + + void foo(int i) { char a[][i] = {""}; } /* { dg-error "variable-sized object may not be initialized" } */ +-/* { dg-error "array size missing in 'a'" "extra error" { target *-*-* } .-1 } */ +-- +2.33.0 + |