https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127577

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |NEW
            Summary|[[no_unique_address]]/base  |[14/15/16/17 Regression]
                   |tail padding member lost    |[[no_unique_address]]/base
                   |after aggregate init with   |tail padding member lost
                   |-fstore-merging             |after aggregate init with
                   |                            |-fstore-merging
                 CC|                            |jakub at gcc dot gnu.org
     Ever confirmed|0                           |1
   Last reconfirmed|                            |2026-09-24
           Priority|P3                          |P2
   Target Milestone|---                         |14.5

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
   4. During the store-merging pass:
      - The stores s = {} (0..2112), s.a = 42 (2080..2112), and s.base = {}
        (0..2080) are coalesced into a single merged store group.
      - To compute the merged byte values, merged_store_group::apply_stores
        applies each store in execution order to the byte buffer val.
      - When applying Store 3 (s.base = {}), encode_tree_to_bitpos is invoked
        with bitlen = 2080 and bitpos = 0.
      - However, in encode_tree_to_bitpos:
   1      unsigned HOST_WIDE_INT rhs_bytes
   2        = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (expr)));
   3      if (rhs_bytes > total_bytes)
   4        return false;
   5      memset (ptr + first_byte, '\0', rhs_bytes);
       TREE_TYPE (expr) is struct Base, for which TYPE_SIZE_UNIT is 264 bytes.
      - Instead of clearing only bitlen / BITS_PER_UNIT (260 bytes), memset
        zeroed rhs_bytes (264 bytes), clobbering byte 260 (s.a = 42) in val
back
        to 0.
      - Because byte 260 was zeroed and the merged group had bzero_first = true
        (from s = {}), the store for s.a was discarded as redundant zeros,
        leaving s.a uninitialized (zero) at runtime.

getting the size from the RHS is fragile - get_inner_reference from the LHS is
the way to obtain it, so yes, it's about DECL_SIZE (FIELD_DECL) vs. TYPE_SIZE
(RHS CTOR type).  Both do not have to agree in the case of tail-padding.

In particular it's not clear why the empty_ctor_p case in encode_tree_to_bitpos
does not honor 'bitlen' or why it would bail for rhs_bytes > total_bytes.

This is Jakub's code, so he probably remembers.

Reply via email to