summaryrefslogtreecommitdiff
path: root/0234-Backport-SME-c-Support-C2x-empty-initializer-braces.patch
diff options
context:
space:
mode:
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.patch672
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
+