First sorry it took someone to review this version of the patch. I
also didn't have it in my inbox due to switching over to a new email
late last year.

>     Commit 0547dbb725b reduced the number of cases in which
>     union padding bits are zeroed when the relevant language
>     standard does not strictly require it, unless gcc was
>     invoked with -fzero-init-padding-bits=unions or
>     -fzero-init-padding-bits=all in order to explicitly
>     request zeroing of padding bits.
>
>     This commit adds a closely related warning,
>     -Wzero-init-padding-bits=, which is intended to help
>     programmers to find code that might now need to be
>     rewritten or recompiled with
>     -fzero-init-padding-bits=unions or
>     -fzero-init-padding-bits=all in order to replicate
>     the behaviour that it had when compiled by older
>     versions of GCC. It can also be used to find struct
>     padding that was never previously guaranteed to be
>     zero initialized and still isn't unless GCC is
>     invoked with -fzero-init-padding-bits=all.

This is definitely useful for the recent changes.

>
>     The new warning can be set to the same three states
>     as -fzero-init-padding-bits ('standard', 'unions'
>     or 'all') and has the same default value ('standard').
>
>     The two options interact as follows:
>
>              f: standard  f: unions   f: all
>     w: standard     X         X         X
>     w: unions       U         X         X
>     w: all          A         S         X
>
>     X = No warnings about padding
>     U = Warnings about padding of unions.
>     S = Warnings about padding of structs.
>     A = Warnings about padding of structs and unions.
>
>     The level of optimisation and whether or not the
>     entire initializer is dropped to memory can both
>     affect whether warnings are produced when compiling
>     a given program. This is intentional, since tying
>     the warnings more closely to the relevant language
>     standard would require a very different approach
>     that would still be target-dependent, might impose
>     an unacceptable burden on programmers, and would
>     risk not satisfying the intended use-case (which
>     is closely tied to a specific optimisation).
>
> gcc/ChangeLog:
>
>         * common.opt: Add Wzero-init-padding-bits=.
>         * doc/invoke.texi: Document Wzero-init-padding-bits=.
>         * expr.cc (categorize_ctor_elements_1): Update new struct type
>         ctor_completeness instead of an integer to indicate presence of
>         padding or missing fields in a constructor. Instead of setting -1
>         upon discovery of padding bits in both structs and unions,
>         set separate flags to indicate the type of padding bits.
>         (categorize_ctor_elements): Update the type and documentation of
>         the p_complete parameter.
>         (mostly_zeros_p): Use new struct type ctor_completeness when
>         calling categorize_ctor_elements.
>         (all_zeros_p): Use new struct type ctor_completeness when
>         calling categorize_ctor_elements.
>         * expr.h (struct ctor_completeness): New struct type to replace an
>         an integer that could take the value -1 ('all fields are
>         initialized, but there's padding'), 0 ('fields are missing') or
>         1 ('all fields are initialized, and there's no padding'). Named
>         bool members make the code easier to understand and make room to
>         disambiguate struct padding bits from union padding bits.
>         (categorize_ctor_elements): Update the function declaration to use
>         the new struct type in the last parameter declaration.
>         * gimplify.cc (gimplify_init_constructor): Replace use of
>         complete_p != 0 ('all fields are initialized') with !sparse,
>         replace use of complete == 0 ('fields are missing') with sparse, and
>         replace use of complete <= 0 ('fields are missing' or 'all fields are
>         initialized, but there's padding') with sparse || padded_union or
>         padded_non_union. Trigger new warnings if storage for the object
>         is not zeroed but padded_union or padded_non_union is set
>         (because this combination implies possible non-zero padding bits).
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.dg/c23-empty-init-warn-1.c: New test.
>         * gcc.dg/c23-empty-init-warn-10.c: New test.
>         * gcc.dg/c23-empty-init-warn-11.c: New test.
>         * gcc.dg/c23-empty-init-warn-12.c: New test.
>         * gcc.dg/c23-empty-init-warn-13.c: New test.
>         * gcc.dg/c23-empty-init-warn-14.c: New test.
>         * gcc.dg/c23-empty-init-warn-15.c: New test.
>         * gcc.dg/c23-empty-init-warn-16.c: New test.
>         * gcc.dg/c23-empty-init-warn-17.c: New test.
>         * gcc.dg/c23-empty-init-warn-2.c: New test.
>         * gcc.dg/c23-empty-init-warn-3.c: New test.
>         * gcc.dg/c23-empty-init-warn-4.c: New test.
>         * gcc.dg/c23-empty-init-warn-5.c: New test.
>         * gcc.dg/c23-empty-init-warn-6.c: New test.
>         * gcc.dg/c23-empty-init-warn-7.c: New test.
>         * gcc.dg/c23-empty-init-warn-8.c: New test.
>         * gcc.dg/c23-empty-init-warn-9.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-1.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-10.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-11.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-12.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-13.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-14.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-15.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-16.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-17.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-2.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-3.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-4.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-5.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-6.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-7.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-8.c: New test.
>         * gcc.dg/gnu11-empty-init-warn-9.c: New test.
> ---
>  gcc/common.opt                                |  4 +
>  gcc/doc/invoke.texi                           | 85 ++++++++++++++++++-
>  gcc/expr.cc                                   | 41 ++++-----
>  gcc/expr.h                                    |  7 +-
>  gcc/gimplify.cc                               | 27 +++++-
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-1.c  | 68 +++++++++++++++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-10.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-11.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-12.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-13.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-14.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-15.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-16.c |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-17.c | 51 +++++++++++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-2.c  | 69 +++++++++++++++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-3.c  |  7 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-4.c  | 69 +++++++++++++++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-5.c  |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-6.c  |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-7.c  |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-8.c  |  8 ++
>  gcc/testsuite/gcc.dg/c23-empty-init-warn-9.c  | 69 +++++++++++++++
>  .../gcc.dg/gnu11-empty-init-warn-1.c          | 52 ++++++++++++
>  .../gcc.dg/gnu11-empty-init-warn-10.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-11.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-12.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-13.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-14.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-15.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-16.c         |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-17.c         | 51 +++++++++++
>  .../gcc.dg/gnu11-empty-init-warn-2.c          | 59 +++++++++++++
>  .../gcc.dg/gnu11-empty-init-warn-3.c          |  7 ++
>  .../gcc.dg/gnu11-empty-init-warn-4.c          | 63 ++++++++++++++
>  .../gcc.dg/gnu11-empty-init-warn-5.c          |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-6.c          |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-7.c          |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-8.c          |  8 ++
>  .../gcc.dg/gnu11-empty-init-warn-9.c          | 55 ++++++++++++
>  39 files changed, 935 insertions(+), 25 deletions(-)
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-10.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-11.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-12.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-13.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-14.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-15.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-16.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-17.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-3.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-4.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-5.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-6.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-7.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-8.c
>  create mode 100644 gcc/testsuite/gcc.dg/c23-empty-init-warn-9.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-1.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-10.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-11.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-12.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-13.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-14.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-15.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-16.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-17.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-2.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-3.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-4.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-5.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-6.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-7.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-8.c
>  create mode 100644 gcc/testsuite/gcc.dg/gnu11-empty-init-warn-9.c
>
> diff --git a/gcc/common.opt b/gcc/common.opt
> index 0e50305dde8..3d8da881aa3 100644
> --- a/gcc/common.opt
> +++ b/gcc/common.opt
> @@ -911,6 +911,10 @@ Wtsan
>  Common Var(warn_tsan) Init(1) Warning
>  Warn about unsupported features in ThreadSanitizer.
>
> +Wzero-init-padding-bits=
> +Common Joined RejectNegative Enum(zero_init_padding_bits_kind)
> Var(warn_zero_init_padding_bits) Init(ZERO_INIT_PADDING_BITS_STANDARD)
> Warning
> +-Wzero-init-padding-bits=[standard|unions|all] Warn about
> initializers that might not zero padding bits.
> +
>  Xassembler
>  Driver Separate
>
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index f31d504f99e..67c2f6a1644 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -446,7 +446,8 @@ Objective-C and Objective-C++ Dialects}.
>  -Wvolatile-register-var  -Wwrite-strings
>  -Wno-xor-used-as-pow
>  -Wzero-as-null-pointer-constant
> --Wzero-length-bounds}
> +-Wzero-length-bounds
> +-Wzero-init-padding-bits=@var{value}}
>
>  @item Static Analyzer Options
>  @gccoptlist{
> @@ -10973,6 +10974,88 @@ Suppress warnings when a positional
> initializer is used to initialize
>  a structure that has been marked with the @code{designated_init}
>  attribute.
>
> +@opindex Wzero-init-padding-bits=
> +@item -Wzero-init-padding-bits=@var{value}
> +Warn about automatic variable initializers that might not zero
> +initialize padding bits.
> +
> +Certain languages guarantee zero initialization of padding bits in
> +certain cases. The @code{-fzero-init-padding-bits=unions} and
> +@code{-fzero-init-padding-bits=all} options provide additional
> +guarantees that padding bits will be zero initialized in other
> +circumstances.
> +
> +This warning is mainly intended to find source code that might need to
> +be modified or else recompiled with
> +@code{-fzero-init-padding-bits=unions} or
> +@code{-fzero-init-padding-bits=all} in order to retain the behaviour
> +that it had when compiled by versions of GCC older than 15. It can also

s/15/15.1/ based on other places which mention the specific version of gcc.

> +be used to find code that might result in uninitialized struct padding
> +unless GCC is invoked with @code{-fzero-init-padding-bits=all}
> +(regardless of the fact that older versions of GCC would not have
> +guaranteed initialization of struct padding either).
> +
> +It does not follow that all source code which causes warnings about
> +uninitialized padding bits has undefined behaviour: usually, the values
s/behaviour/behavior/ That is the American spelling as mentioned on
https://gcc.gnu.org/codingconventions.html#Spelling .

> +of padding bits have no effect on execution of a program.
> +
> +The two options interact as follows:
> +
> +@multitable @columnfractions 0.25 0.25 0.25 0.25
> +@headitem @tab f:standard @tab f:unions @tab f:all
> +@item W:standard @tab X @tab X @tab X
> +@item W:unions @tab U @tab X @tab X
> +@item W:all @tab A @tab S @tab X
> +@end multitable
> +
> +@multitable @columnfractions .10 .90
> +@headitem Letter @tab Meaning
> +@item X @tab No warnings about padding bits.
> +@item U @tab Warnings about padding bits of unions.
> +@item S @tab Warnings about padding bits of structs.
> +@item A @tab Warnings about padding bits of structs and unions.
> +@end multitable
> +
> +Examples of union initialization for ISO C23 with
> +@code{-fzero-init-padding-bits=standard} and
> +@code{-Wzero-init-padding-bits=unions}:
> +
> +@smallexample
> +  long long q;
> +  unsigned char r;
> +  union U @{ unsigned char a; long long b; @};
> +  struct F @{ long long a; union U b; @};
> +
> +  // Padding bits are explicitly initialized
> +  union U h = @{@};
> +
> +  // Padding bits might not be initialized
> +  union U i = @{ r @};
> +
> +  // Padding bits might not be initialized
> +  union U j = @{ .a = r @};
> +
> +  // Union is expected to have no padding bits
> +  union U k = @{ .b = q @};
> +
> +  // Padding bits (of union) are explicitly initialized
> +  struct F l = @{ q, @{@}, .b.a = r @};
> +
> +  // Padding bits (of union) might not be initialized
> +  struct F m = @{ q, @{@}, .b = @{.a = r@} @};
> +@end smallexample
> +
> +In the declaration of @code{m}, an empty initializer that would otherwise
> +guarantee zero initialization of the padding bits of the union (i.e. storage
> +allocated for member @code{b} that is not part of member @code{a}) is
> +overridden by a subsequently listed initializer. This is an anti-pattern.
> +
> +Whether or not a given initializer causes a warning to be produced can be
> +predicted for simple cases but in general it is target-dependent because the
> +layout of storage is target-dependent. The level of optimisation, size, and

s/optimisation/optimization/ American spelling.

> +initial value of the object being initialized also affect whether warnings 
> are
> +produced.
> +
>  @end table
>
>  @node Static Analyzer Options
> diff --git a/gcc/expr.cc b/gcc/expr.cc
> index 3815c565e2d..2e4442ff2f2 100644
> --- a/gcc/expr.cc
> +++ b/gcc/expr.cc
> @@ -7101,7 +7101,8 @@ count_type_elements (const_tree type, bool for_ctor_p)
>  static bool
>  categorize_ctor_elements_1 (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
>                             HOST_WIDE_INT *p_unique_nz_elts,
> -                           HOST_WIDE_INT *p_init_elts, int *p_complete)
> +                           HOST_WIDE_INT *p_init_elts,
> +                           ctor_completeness *p_complete)
>  {
>    unsigned HOST_WIDE_INT idx;
>    HOST_WIDE_INT nz_elts, unique_nz_elts, init_elts, num_fields;
> @@ -7228,34 +7229,38 @@ categorize_ctor_elements_1 (const_tree ctor,
> HOST_WIDE_INT *p_nz_elts,
>         }
>      }
>
> -  if (*p_complete && !complete_ctor_at_level_p (TREE_TYPE (ctor),
> +  if (!p_complete->sparse && !complete_ctor_at_level_p (TREE_TYPE (ctor),
>                                                 num_fields, elt_type))
> -    *p_complete = 0;
> +    p_complete->sparse = true;
>    else if (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
>            || TREE_CODE (TREE_TYPE (ctor)) == QUAL_UNION_TYPE)
>      {
> -      if (*p_complete
> +      if (!p_complete->sparse
>           && CONSTRUCTOR_ZERO_PADDING_BITS (ctor)
>           && (num_fields
>               ? simple_cst_equal (TYPE_SIZE (TREE_TYPE (ctor)),
>                                   TYPE_SIZE (elt_type)) != 1
>               : type_has_padding_at_level_p (TREE_TYPE (ctor))))
> -       *p_complete = 0;
> -      else if (*p_complete > 0
> +       {
> +         p_complete->sparse = true;
> +       }

The braces here are not needed and I think it is recommended not to use them.

> +      else if (!p_complete->sparse && !p_complete->padded_union
>                && (num_fields
>                    ? simple_cst_equal (TYPE_SIZE (TREE_TYPE (ctor)),
>                                        TYPE_SIZE (elt_type)) != 1
>                    : type_has_padding_at_level_p (TREE_TYPE (ctor))))
> -       *p_complete = -1;
> +       p_complete->padded_union = true;
>      }
> -  else if (*p_complete
> +  else if (!p_complete->sparse
>            && (CONSTRUCTOR_ZERO_PADDING_BITS (ctor)
>                || flag_zero_init_padding_bits == ZERO_INIT_PADDING_BITS_ALL)
>            && type_has_padding_at_level_p (TREE_TYPE (ctor)))
> -    *p_complete = 0;
> -  else if (*p_complete > 0
> +    {
> +      p_complete->sparse = true;
> +    }

Likewise.

> +  else if (!p_complete->sparse && !p_complete->padded_non_union
>            && type_has_padding_at_level_p (TREE_TYPE (ctor)))
> -    *p_complete = -1;
> +    p_complete->padded_non_union = true;
>
>    *p_nz_elts += nz_elts;
>    *p_unique_nz_elts += unique_nz_elts;
> @@ -7277,9 +7282,6 @@ categorize_ctor_elements_1 (const_tree ctor,
> HOST_WIDE_INT *p_nz_elts,
>     * whether the constructor is complete -- in the sense that every
>       meaningful byte is explicitly given a value --
>       and place it in *P_COMPLETE:
> -     -  0 if any field is missing
> -     -  1 if all fields are initialized, and there's no padding
> -     - -1 if all fields are initialized, but there's padding
>
>     Return whether or not CTOR is a valid static constant initializer, the 
> same
>     as "initializer_constant_valid_p (CTOR, TREE_TYPE (CTOR)) != 0".  */
> @@ -7287,12 +7289,13 @@ categorize_ctor_elements_1 (const_tree ctor,
> HOST_WIDE_INT *p_nz_elts,
>  bool
>  categorize_ctor_elements (const_tree ctor, HOST_WIDE_INT *p_nz_elts,
>                           HOST_WIDE_INT *p_unique_nz_elts,
> -                         HOST_WIDE_INT *p_init_elts, int *p_complete)
> +                         HOST_WIDE_INT *p_init_elts,
> +                         ctor_completeness *p_complete)
>  {
>    *p_nz_elts = 0;
>    *p_unique_nz_elts = 0;
>    *p_init_elts = 0;
> -  *p_complete = 1;
> +  *p_complete = {};
>
>    return categorize_ctor_elements_1 (ctor, p_nz_elts, p_unique_nz_elts,
>                                      p_init_elts, p_complete);
> @@ -7366,11 +7369,11 @@ mostly_zeros_p (const_tree exp)
>    if (TREE_CODE (exp) == CONSTRUCTOR)
>      {
>        HOST_WIDE_INT nz_elts, unz_elts, init_elts;
> -      int complete_p;
> +      ctor_completeness complete_p;
>
>        categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts,
>                                 &complete_p);
> -      return !complete_p || nz_elts < init_elts / 4;
> +      return complete_p.sparse || nz_elts < init_elts / 4;
>      }
>
>    return initializer_zerop (exp);
> @@ -7384,7 +7387,7 @@ all_zeros_p (const_tree exp)
>    if (TREE_CODE (exp) == CONSTRUCTOR)
>      {
>        HOST_WIDE_INT nz_elts, unz_elts, init_elts;
> -      int complete_p;
> +      ctor_completeness complete_p;
>
>        categorize_ctor_elements (exp, &nz_elts, &unz_elts, &init_elts,
>                                 &complete_p);
> diff --git a/gcc/expr.h b/gcc/expr.h
> index 53ab625787e..a31cdcd54b7 100644
> --- a/gcc/expr.h
> +++ b/gcc/expr.h
> @@ -359,9 +359,14 @@ extern bool can_move_by_pieces (unsigned
> HOST_WIDE_INT, unsigned int);
>
>  extern unsigned HOST_WIDE_INT highest_pow2_factor (const_tree);
>
> +struct ctor_completeness
> +{
> +  bool sparse:1, padded_non_union:1, padded_union:1;

Formatting. I think we specify each field on its own line.
Would be useful to have a comment on what each field means.

> +};
> +
>  extern bool categorize_ctor_elements (const_tree, HOST_WIDE_INT *,
>                                       HOST_WIDE_INT *, HOST_WIDE_INT *,
> -                                     int *);
> +                                     ctor_completeness *);
>  extern bool type_has_padding_at_level_p (tree);
>  extern bool immediate_const_ctor_p (const_tree, unsigned int words = 1);
>  extern void store_constructor (tree, rtx, int, poly_int64, bool);
> diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
> index 4f385b1b779..daf5ce30724 100644
> --- a/gcc/gimplify.cc
> +++ b/gcc/gimplify.cc
> @@ -6360,7 +6360,7 @@ gimplify_init_constructor (tree *expr_p,
> gimple_seq *pre_p, gimple_seq *post_p,
>         struct gimplify_init_ctor_preeval_data preeval_data;
>         HOST_WIDE_INT num_ctor_elements, num_nonzero_elements;
>         HOST_WIDE_INT num_unique_nonzero_elements;
> -       int complete_p;
> +       ctor_completeness complete_p;
>         bool valid_const_initializer;
>
>         /* Aggregate types must lower constructors to initialization of
> @@ -6445,7 +6445,7 @@ gimplify_init_constructor (tree *expr_p,
> gimple_seq *pre_p, gimple_seq *post_p,
>              objects.  Initializers for such objects must explicitly set
>              every field that needs to be set.  */
>           cleared = false;
> -       else if (!complete_p)
> +       else if (complete_p.sparse)
>           /* If the constructor isn't complete, clear the whole object
>              beforehand, unless CONSTRUCTOR_NO_CLEARING is set on it.
>
> @@ -6470,7 +6470,8 @@ gimplify_init_constructor (tree *expr_p,
> gimple_seq *pre_p, gimple_seq *post_p,
>            That will avoid wasting cycles preserving any padding bits
>            that might be there, and if there aren't any, the compiler
>            is smart enough to optimize the clearing out.  */
> -       else if (complete_p <= 0
> +       else if ((complete_p.sparse || complete_p.padded_union
> +                 || complete_p.padded_non_union)
>                  && !TREE_ADDRESSABLE (ctor)
>                  && !TREE_THIS_VOLATILE (object)
>                  && (TYPE_MODE (type) != BLKmode || TYPE_NO_FORCE_BLK (type))
> @@ -6489,7 +6490,7 @@ gimplify_init_constructor (tree *expr_p,
> gimple_seq *pre_p, gimple_seq *post_p,
>            clearing), and don't try to make bitwise copies of
>            TREE_ADDRESSABLE types.  */
>         if (valid_const_initializer
> -           && complete_p
> +           && !complete_p.sparse
>             && !(cleared || num_nonzero_elements == 0)
>             && !TREE_ADDRESSABLE (type))
>           {
> @@ -6544,6 +6545,24 @@ gimplify_init_constructor (tree *expr_p,
> gimple_seq *pre_p, gimple_seq *post_p,
>               }
>           }
>
> +       if (!cleared)
> +         {
> +           if (complete_p.padded_non_union
> +               && warn_zero_init_padding_bits >= ZERO_INIT_PADDING_BITS_ALL)
> +               warning (OPT_Wzero_init_padding_bits_,
> +                        "padding might not be initialized to zero; "
> +                        "if code relies on it being zero, consider "
> +                        "using %<-fzero-init-padding-bits=all%>");
> +           else if (complete_p.padded_union
> +                    && warn_zero_init_padding_bits
> +                       >= ZERO_INIT_PADDING_BITS_UNIONS)
> +               warning (OPT_Wzero_init_padding_bits_,
> +                        "padding might not be initialized to zero; "
> +                        "if code relies on it being zero, consider "
> +                        "using %<-fzero-init-padding-bits=unions%> "
> +                        "or %<-fzero-init-padding-bits=all%>");
> +         }
> +

Ok from me with those changes.

Richard,
  This was submitted back in May of last year and had already 3 other
versions with reviews but this version was not reviewed until today .
Should we wait for GCC 17 stage 1 for this or is this ok now?

Thanks,
Andrew Pinski


>         /* If a single access to the target must be ensured and there are
>            nonzero elements or the zero elements are not assigned en masse,
>            initialize the target from a temporary.  */
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-1.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-1.c
> new file mode 100644
> index 00000000000..c82c4d66e4c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-1.c
> @@ -0,0 +1,68 @@
> +/* Test that C23 warnings are produced about initializers that might
> + * not zero padding bits of structs or unions. Expected results are different
> + * from GNU11 because empty initializers zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=c23 -Wzero-init-padding-bits=all" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c[0] and c[2] as contagious */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> .c[1].b = 6, /* { dg-warning "padding might not be initialized to
> zero" } */
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U j = { .a = argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* All (struct) padding is explicitly initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* All (union) padding is explicitly initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +
> +  /* Empty initializer is overridden and therefore ineffective */
> +  struct F t = { argc, {}, .b = {.a = 2} }; /* { dg-warning "padding
> might not be initialized to zero" } */
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-10.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-10.c
> new file mode 100644
> index 00000000000..2424db8e632
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-10.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (despite being enabled for unions)
> + * about initializers that might not zero padding bits (when configured to 
> zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=unions
> -fzero-init-padding-bits=unions" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-11.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-11.c
> new file mode 100644
> index 00000000000..f11664c3f12
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-11.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured to zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=unions" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-12.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-12.c
> new file mode 100644
> index 00000000000..7971a667535
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-12.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured to zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=unions" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-13.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-13.c
> new file mode 100644
> index 00000000000..900694e2d20
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-13.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (despite being enabled for structs
> + * and unions) about initializers that might not zero padding bits (when
> + * configured to zero padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=all
> -fzero-init-padding-bits=all" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-14.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-14.c
> new file mode 100644
> index 00000000000..08b3ef39987
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-14.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (despite being enabled for unions)
> + * about initializers that might not zero padding bits (when configured to 
> zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=unions
> -fzero-init-padding-bits=all" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-15.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-15.c
> new file mode 100644
> index 00000000000..dd51b1235b3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-15.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured to zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=all" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-16.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-16.c
> new file mode 100644
> index 00000000000..ff503f8fb70
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-16.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured to zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=all" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-17.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-17.c
> new file mode 100644
> index 00000000000..00df5bf82da
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-17.c
> @@ -0,0 +1,51 @@
> +/* Test that no C23 warnings are produced about initializers of objects with
> + * static storage duration that might not have zeroed padding bits if they
> + * instead had automatic storage duration.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=c23 -Wzero-init-padding-bits=all" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main ()
> +{
> +  static struct A a = {};
> +  static struct B b = {};
> +  static struct B c = { 1, 2 };
> +  static struct B d = { .b = 1, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  static struct B e = { 1, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                       .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                       .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static struct B f = { 1, 2, {},
> +                       .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                       .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static struct B g = { 1, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                       .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static union U h = {};
> +  static union U i = { 1 };
> +  static union U j = { .a = 1 };
> +  static union U k = { .b = 1 };
> +  static struct D l = {};
> +  static struct D m = { 1, 2 };
> +  static struct D n = { 1, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +  static struct C o = { {} };
> +  static struct C p = { {}, .a.a = 3, .a.b = 4 };
> +  static struct E q = { 1, 2 };
> +  static union V r = { 1 };
> +  static struct F s = { 1, {}, .b.a = 2 };
> +  static struct F t = { 1, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-2.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-2.c
> new file mode 100644
> index 00000000000..05d236dd685
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-2.c
> @@ -0,0 +1,69 @@
> +/* Test that C23 warnings are only produced (when enabled for unions) about
> + * initializers that might not zero padding bits of unions. Expected
> results are
> + * different from GNU11 because empty initializers zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=c23 -Wzero-init-padding-bits=unions" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c[0] and c[2] as contagious */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U j = { .a = argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* All (struct) padding is explicitly initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* All (union) padding is explicitly initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +
> +  /* Empty initializer is overridden and therefore ineffective */
> +  struct F t = { argc, {}, .b = {.a = 2} }; /* { dg-warning "padding
> might not be initialized to zero" } */
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-3.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-3.c
> new file mode 100644
> index 00000000000..569bfb218ae
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-3.c
> @@ -0,0 +1,7 @@
> +/* Test that no C23 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-4.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-4.c
> new file mode 100644
> index 00000000000..fc4dedb3001
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-4.c
> @@ -0,0 +1,69 @@
> +/* Test that no C23 warnings are produced (by default) about initializers
> + * that might not zero padding bits. Expected results are the same as GNU11
> + * despite the fact that empty initializers zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=c23" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c[0] and c[2] as contagious */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* Padding bits might not be initialized */
> +  union U j = { .a = argc }; /* Padding bits might not be initialized */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* All (struct) padding is explicitly initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* All (union) padding is explicitly initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +
> +  /* Empty initializer is overridden and therefore ineffective */
> +  struct F t = { argc, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-5.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-5.c
> new file mode 100644
> index 00000000000..f9578eb1ee3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-5.c
> @@ -0,0 +1,8 @@
> +/* Test that C23 warnings are produced about initializers that might
> + * not zero padding bits of structs or unions (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "c23-empty-init-warn-1.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-6.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-6.c
> new file mode 100644
> index 00000000000..395dc058c09
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-6.c
> @@ -0,0 +1,8 @@
> +/* Test that C23 warnings are only produced (when enabled for unions) about
> + * initializers that might not zero padding bits of unions (when configured 
> not
> + * to zero padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "c23-empty-init-warn-2.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-7.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-7.c
> new file mode 100644
> index 00000000000..9d8cb8a0509
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-7.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=standard" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-8.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-8.c
> new file mode 100644
> index 00000000000..9a2e4dd33bd
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-8.c
> @@ -0,0 +1,8 @@
> +/* Test that no C23 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "c23-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/c23-empty-init-warn-9.c
> b/gcc/testsuite/gcc.dg/c23-empty-init-warn-9.c
> new file mode 100644
> index 00000000000..3208d85f579
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/c23-empty-init-warn-9.c
> @@ -0,0 +1,69 @@
> +/* Test that C23 warnings are only produced (when enabled for structs and
> + * unions) about initializers that might not zero padding bits of structs 
> (when
> + * configured to only zero padding bits of unions). Expected results are
> + * different from GNU11 because empty initializers zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=c23 -Wzero-init-padding-bits=all
> -fzero-init-padding-bits=unions" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c[0] and c[2] as contagious */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> .c[1].b = 6, /* { dg-warning "padding might not be initialized to
> zero" } */
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* Padding bits might not be initialized */
> +  union U j = { .a = argc }; /* Padding bits might not be initialized */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized according to C23 but GCC treats
> +     the explicitly initialized padding of c as contagious */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* All (struct) padding is explicitly initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* All (union) padding is explicitly initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +
> +  /* Empty initializer is overridden and therefore ineffective */
> +  struct F t = { argc, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-1.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-1.c
> new file mode 100644
> index 00000000000..ca7edf008fc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-1.c
> @@ -0,0 +1,52 @@
> +/* Test that GNU11 warnings are produced about initializers that might
> + * not zero padding bits of structs or unions.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu11 -Wzero-init-padding-bits=all" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {}, /* {
> dg-warning "padding might not be initialized to zero" } */
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B f = { argc, 2, {}, /* { dg-warning "padding might not be
> initialized to zero" } */
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> .c[1].b = 6, /* { dg-warning "padding might not be initialized to
> zero" } */
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U j = { .a = argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 }; /* {
> dg-warning "padding might not be initialized to zero" } */
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 }; /* { dg-warning
> "padding might not be initialized to zero" } */
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +  struct F s = { argc, {}, .b.a = 2 }; /* { dg-warning "padding might
> not be initialized to zero" } */
> +  struct F t = { argc, {}, .b = {.a = 2} }; /* { dg-warning "padding
> might not be initialized to zero" } */
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-10.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-10.c
> new file mode 100644
> index 00000000000..da15fd5e539
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-10.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (despite being enabled for 
> unions)
> + * about initializers that might not zero padding bits (when configured to 
> zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=unions
> -fzero-init-padding-bits=unions" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-11.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-11.c
> new file mode 100644
> index 00000000000..d900f212d6a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-11.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured to zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=unions" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-12.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-12.c
> new file mode 100644
> index 00000000000..072b144d3a0
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-12.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured to zero
> + * only padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=unions" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-13.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-13.c
> new file mode 100644
> index 00000000000..03a690776f1
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-13.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (despite being enabled for 
> structs
> + * and unions) about initializers that might not zero padding bits (when
> + * configured to zero padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=all
> -fzero-init-padding-bits=all" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-14.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-14.c
> new file mode 100644
> index 00000000000..4cf62a7dee5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-14.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (despite being enabled for 
> unions)
> + * about initializers that might not zero padding bits (when configured to 
> zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=unions
> -fzero-init-padding-bits=all" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-15.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-15.c
> new file mode 100644
> index 00000000000..45ce183a757
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-15.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured to zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=all" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-16.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-16.c
> new file mode 100644
> index 00000000000..23519cf8bc3
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-16.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured to zero
> + * padding bits of structs and unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=all" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-17.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-17.c
> new file mode 100644
> index 00000000000..d126844abab
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-17.c
> @@ -0,0 +1,51 @@
> +/* Test that no GNU11 warnings are produced about initializers of objects 
> with
> + * static storage duration that might not have zeroed padding bits if they
> + * instead had automatic storage duration.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu11 -Wzero-init-padding-bits=all" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main ()
> +{
> +  static struct A a = {};
> +  static struct B b = {};
> +  static struct B c = { 1, 2 };
> +  static struct B d = { .b = 1, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  static struct B e = { 1, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                  .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                  .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static struct B f = { 1, 2, {},
> +                  .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                  .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static struct B g = { 1, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> +                  .c[1].b = 6, .c[2].a = 7, .c[2].b = 8 };
> +
> +  static union U h = {};
> +  static union U i = { 1 };
> +  static union U j = { .a = 1 };
> +  static union U k = { .b = 1 };
> +  static struct D l = {};
> +  static struct D m = { 1, 2 };
> +  static struct D n = { 1, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +  static struct C o = { {} };
> +  static struct C p = { {}, .a.a = 3, .a.b = 4 };
> +  static struct E q = { 1, 2 };
> +  static union V r = { 1 };
> +  static struct F s = { 1, {}, .b.a = 2 };
> +  static struct F t = { 1, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-2.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-2.c
> new file mode 100644
> index 00000000000..4837208c2fe
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-2.c
> @@ -0,0 +1,59 @@
> +/* Test that GNU11 warnings are only produced (when enabled for unions) about
> + * initializers that might not zero padding bits of unions.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu11 -Wzero-init-padding-bits=unions" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +  struct B d = { .b = 1, .a = 2, .c[2].a = 3, .c[2].b = 4 }; /* ZI
> because it omits c[0], c[1] */
> +
> +  /* Padding bits might not be initialized */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U j = { .a = argc }; /* { dg-warning "padding might not be
> initialized to zero" } */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* Padding bits might not be initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +  struct F s = { argc, {}, .b.a = 2 }; /* { dg-warning "padding might
> not be initialized to zero" } */
> +  struct F t = { argc, {}, .b = {.a = 2} }; /* { dg-warning "padding
> might not be initialized to zero" } */
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-3.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-3.c
> new file mode 100644
> index 00000000000..499b3f84bb4
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-3.c
> @@ -0,0 +1,7 @@
> +/* Test that no GNU11 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-4.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-4.c
> new file mode 100644
> index 00000000000..6c693d914ed
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-4.c
> @@ -0,0 +1,63 @@
> +/* Test that no GNU11 warnings are produced (by default) about initializers
> + * that might not zero padding bits.
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu11" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B f = { argc, 2, {},
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  /* Padding bits might not be initialized */
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* Padding bits might not be initialized */
> +  union U j = { .a = argc }; /* Padding bits might not be initialized */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +
> +  /* Padding bits might not be initialized */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 };
> +
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +
> +  /* Padding bits might not be initialized */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 };
> +
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* Padding bits (of union) might not be initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +  struct F t = { argc, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-5.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-5.c
> new file mode 100644
> index 00000000000..f6e6e3537fc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-5.c
> @@ -0,0 +1,8 @@
> +/* Test that GNU11 warnings are produced about initializers that might
> + * not zero padding bits of structs or unions (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "gnu11-empty-init-warn-1.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-6.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-6.c
> new file mode 100644
> index 00000000000..41f8f17059a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-6.c
> @@ -0,0 +1,8 @@
> +/* Test that GNU11 warnings are only produced (when enabled for unions) about
> + * initializers that might not zero padding bits of unions (when configured 
> not
> + * to zero padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "gnu11-empty-init-warn-2.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-7.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-7.c
> new file mode 100644
> index 00000000000..6cfa310f5ac
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-7.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (when explicitly disabled) about
> + * initializers that might not zero padding bits (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-Wzero-init-padding-bits=standard
> -fzero-init-padding-bits=standard" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-8.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-8.c
> new file mode 100644
> index 00000000000..57cc58d89f2
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-8.c
> @@ -0,0 +1,8 @@
> +/* Test that no GNU11 warnings are produced (by default) about
> + * initializers that might not zero padding bits (when configured not to zero
> + * padding bits unless mandated by the language standard).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-fzero-init-padding-bits=standard" } */
> +
> +#include "gnu11-empty-init-warn-4.c"
> diff --git a/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-9.c
> b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-9.c
> new file mode 100644
> index 00000000000..d9f4d9a431a
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/gnu11-empty-init-warn-9.c
> @@ -0,0 +1,55 @@
> +/* Test that GNU11 warnings are only produced (when enabled for structs and
> + * unions) about initializers that might not zero padding bits of structs 
> (when
> + * configured to only zero padding bits of unions).
> + */
> +/* { dg-do run } */
> +/* { dg-options "-std=gnu11 -Wzero-init-padding-bits=all
> -fzero-init-padding-bits=unions" } */
> +
> +struct A { unsigned char a; long long b; };
> +struct B { unsigned char a; long long b; struct A c[3]; };
> +struct C { struct A a; };
> +struct D { unsigned char a; long long b; struct C c; };
> +struct E { long long a; long long b; };
> +union U { unsigned char a; long long b; };
> +union V { long long a; long long b; };
> +struct F { long long a; union U b; };
> +
> +int
> +main (int argc, char *argv[])
> +{
> +  struct A a = {}; /* ZI because it omits a, b */
> +  struct B b = {}; /* ZI because it omits a, b, c */
> +  struct B c = { argc, 2 }; /* ZI because it omits c[0], c[1], c[2] */
> +
> +  /* ZI because it omits c[0], c[1] */
> +  struct B d = { .b = argc, .a = 2, .c[2].a = 3, .c[2].b = 4 };
> +
> +  struct B e = { argc, 2, .c[2] = {}, .c[1] = { 9 }, .c[0] = {}, /* {
> dg-warning "padding might not be initialized to zero" } */
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B f = { argc, 2, {}, /* { dg-warning "padding might not be
> initialized to zero" } */
> +                .c[0].a = 3, .c[0].b = 4, .c[1].a = 5, .c[1].b = 6,
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  struct B g = { argc, 2, .c[0].a = 3, .c[0].b = 4, .c[1].a = 5,
> .c[1].b = 6, /* { dg-warning "padding might not be initialized to
> zero" } */
> +                .c[2].a = 7, .c[2].b = 8 };
> +
> +  union U h = {}; /* ZI because it omits a, b */
> +  union U i = { argc }; /* Padding bits might not be initialized */
> +  union U j = { .a = argc }; /* Padding bits might not be initialized */
> +  union U k = { .b = argc }; /* Largest member is initialized */
> +  struct D l = {}; /* ZI because it omits a, b, c */
> +  struct D m = { argc, 2 }; /* ZI because it omits c */
> +  struct D n = { argc, 2, {}, .c.a.a = 3, .c.a.b = 4 }; /* {
> dg-warning "padding might not be initialized to zero" } */
> +  struct C o = { {} }; /* ZI because it omits a.a, a.b */
> +  struct C p = { {}, .a.a = argc, .a.b = 4 }; /* { dg-warning
> "padding might not be initialized to zero" } */
> +  struct E q = { argc, 2 }; /* No padding */
> +  union V r = { argc }; /* No padding */
> +
> +  /* Padding bits (of union) might not be initialized */
> +  struct F s = { argc, {}, .b.a = 2 };
> +  struct F t = { argc, {}, .b = {.a = 2} };
> +
> +  return 0;
> +}
> --
> 2.43.0

Reply via email to