> Am 06.02.2026 um 23:19 schrieb Martin Jambor <[email protected]>:
>
> Hi,
>
> on master at least, this is a bug which no longer reproduces with the
> provided test-cases because after r15-5747-gfd62fdc5e1b3c4:(Jakub
> Jelinek: c++: Small initial fixes for zeroing of padding bits
> [PR117256]), the input to SRA looks very different and SRA does not do
> anything.
>
> However, before that commit, SRA sees the following input and if it
> encountered something similar now, it could still misbehave in the
> same way:
>
> D.2908.i = 0;
> D.2908.b = 0;
> e ={v} {CLOBBER(bob)};
> e.b = MEM[(const struct B &)&D.2908];
> D.2908 ={v} {CLOBBER(eos)};
>
> (Where the "e" in "e.b" is actually a MEM_REF of the union type into
> &e so that is why the "data" field is missing.)
>
> Field D.2908.b is a SRA candidate of boolean type and has size 1 bit
> because its decl has size 1 bit even though its type has size 8 bits.
>
> The SRA access representing the store to D.2908.b is then propagated
> across the assignment to e and in the process
> build_user_friendly_ref_for_offset tries to find a nice expression for
> it to possibly use in warnings. It finds types_compatible_p
> e.data.a.b which however has size 8 bits and so the verifier screams
> when it discovers the discrepancy from the copied-over size of 1 bit.
>
> This patch avoids the situation by refusing to propagate
> non-byte-sized accesses across assignments.
>
> The patch has passed bootstrap and test on x86_64 on master, I am now
> running the same on top of the gcc-14 branch. OK for master and all
> active release branches if it passes there as well?
Ok
Richard
> Thanks,
>
> Martin
>
>
> gcc/ChangeLog:
>
> 2026-02-06 Martin Jambor <[email protected]>
>
> PR tree-optimization/117217
> * tree-sra.cc (propagate_subaccesses_from_rhs): Do not propagate
> bit-field children.
> (propagate_subaccesses_from_lhs): Likewise.
>
> gcc/testsuite/ChangeLog:
>
> 2026-02-06 Martin Jambor <[email protected]>
>
> PR tree-optimization/117217
> * g++.dg/torture/pr117217-1.C: New test.
> * g++.dg/torture/pr117217-2.C: Likewise.
> ---
> gcc/testsuite/g++.dg/torture/pr117217-1.C | 24 +++++++++++++++++++++++
> gcc/testsuite/g++.dg/torture/pr117217-2.C | 24 +++++++++++++++++++++++
> gcc/tree-sra.cc | 2 ++
> 3 files changed, 50 insertions(+)
> create mode 100644 gcc/testsuite/g++.dg/torture/pr117217-1.C
> create mode 100644 gcc/testsuite/g++.dg/torture/pr117217-2.C
>
> diff --git a/gcc/testsuite/g++.dg/torture/pr117217-1.C
> b/gcc/testsuite/g++.dg/torture/pr117217-1.C
> new file mode 100644
> index 00000000000..887ab694535
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/torture/pr117217-1.C
> @@ -0,0 +1,24 @@
> +struct [[gnu::packed]] A {
> + int i;
> + bool b;
> +};
> +
> +struct [[gnu::packed]] B {
> + int i;
> + bool b : 1;
> +};
> +
> +struct E {
> + union Data {
> + A a;
> + B b;
> + Data(const B &b) : b(b) {}
> + } data;
> +};
> +
> +extern B copy;
> +
> +int main() {
> + E e{{B()}};
> + copy = e.data.b; // NEEDED FOR ICE
> +}
> diff --git a/gcc/testsuite/g++.dg/torture/pr117217-2.C
> b/gcc/testsuite/g++.dg/torture/pr117217-2.C
> new file mode 100644
> index 00000000000..19390212b48
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/torture/pr117217-2.C
> @@ -0,0 +1,24 @@
> +struct a {
> + int b;
> + long c;
> + long d;
> + bool f;
> +};
> +struct g {
> + int b;
> + long c;
> + long d;
> + bool : 1;
> +} h;
> +struct l {
> + union i {
> + a j;
> + g k;
> + i(g m) : k(m) {}
> + } data;
> +};
> +int main() {
> + l e{g()};
> + h = e.data.k;
> + return 0;
> +}
> diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc
> index 151f6005ff3..1f5219d78b2 100644
> --- a/gcc/tree-sra.cc
> +++ b/gcc/tree-sra.cc
> @@ -3258,6 +3258,7 @@ propagate_subaccesses_from_rhs (struct access *lacc,
> struct access *racc)
> }
>
> if (rchild->grp_unscalarizable_region
> + || (rchild->size % BITS_PER_UNIT) != 0
> || !budget_for_propagation_access (lacc->base))
> {
> if (!lacc->grp_write && access_or_its_child_written (rchild))
> @@ -3317,6 +3318,7 @@ propagate_subaccesses_from_lhs (struct access *lacc,
> struct access *racc)
> HOST_WIDE_INT norm_offset = lchild->offset + norm_delta;
>
> if (lchild->grp_unscalarizable_region
> + || (lchild->size % BITS_PER_UNIT) != 0
> || child_would_conflict_in_acc (racc, norm_offset, lchild->size,
> &matching_acc)
> || !budget_for_propagation_access (racc->base))
> --
> 2.52.0
>