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