On Wed, 29 Jul 2026, Martin Jambor wrote:

> Hi,
> 
> PR 126310 was a miscompilation which happened because the code
> inferring value range from loads from a constant global variable with
> a static constructor missed an element and assumed the value thus had
> to be zero.  This happened because the C++ front end used a different
> field_decl in the component_ref accessing the file and in the
> constructor element and the ranger code relied on simple pointer
> equality.
>
> Jason has already fixed the issue on the C++ side but noted that the
> middle-end should probably also be more robust and so I have written
> this patch which also compare offsets of the fields when the
> field_decls are different.

Huh.  Did the FIELD_DECL have the record type as DECL_CONTEXT?
ISTR we do often see the FIELD_DECLs being those of the main
variant, that is, variant types usually share the FIELD_DECL chain.
But then there should not be another set of FIELD_DECLs.  Even
distinct type copies will start with the same FIELD_DECL chain.
 
> I have tested it by a normal bootstrap and testing on x86_64 and by
> making sure the miscompilation did not happen on a revision before
> Jason's fix.  The testcase is already in the testsuite.
> 
> I would like to commit this to master and also the the gcc-16 branch,
> possibly with the gcc_checking_assert replaced with an early return
> false.  OK?

I'm not sure.  What about variable record layout where you cannot
detect overlaps conservatively?  What about weird cases where you'd
have partial overlaps?

I'd say you should at least return false when there's no exact match.

But, as we already check

          if (!useless_type_conversion_p (TREE_TYPE (expr),
                                          TREE_TYPE (TREE_OPERAND (expr, 
1))))
            {
              error ("type mismatch in %qs", code_name);
              debug_generic_stmt (TREE_TYPE (expr));
              debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1)));
              return true;

in verify_types_in_gimple_reference we may as well check that
the FIELD_DECL in operand 1 belongs to the record type of operand 0
(or its main variant)?  Would that have catched it or was the
mismatch only in the CTOR?  Then we might want to check it somewhere
else, like when we process global CTORs for IPA reference analysis?

Richard.

> Thanks,
> 
> Martin
> 
> 
> gcc/ChangeLog:
> 
> 2026-07-29  Martin Jambor  <[email protected]>
> 
>       PR c++/126310
>       * gimple-range-fold.cc (range_from_readonly_load): Also check if the
>       offset of the index field in the constructor element matches the
>       offset of the field from the reference.
> ---
>  gcc/gimple-range-fold.cc | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
> index 5a2736c6ebc..57f8917b6b6 100644
> --- a/gcc/gimple-range-fold.cc
> +++ b/gcc/gimple-range-fold.cc
> @@ -1035,11 +1035,24 @@ range_from_readonly_load (vrange &r, tree type, tree 
> cst,
>    if (TREE_CODE (expr) == COMPONENT_REF)
>      {
>        tree ref_fld = TREE_OPERAND (expr, 1);
> +      tree ref_pos = bit_position (ref_fld);
> +      if (!tree_fits_shwi_p (ref_pos))
> +     return false;
> +      HOST_WIDE_INT ref_offset = tree_to_shwi (ref_pos);
> +
>        FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (cst), ix, index, val)
>       {
> -       if (index != ref_fld)
> +       if (index == ref_fld)
> +         return range_from_readonly_load (r, type, val, comps, i);
> +
> +       /* In case of a union we want an exact field match.  */
> +       if (TREE_CODE (TREE_TYPE (cst)) != RECORD_TYPE)
>           continue;
> -       return range_from_readonly_load (r, type, val, comps, i);
> +       tree idx_pos = bit_position (index);
> +       gcc_checking_assert (tree_fits_shwi_p (idx_pos));
> +       HOST_WIDE_INT idx_offset = tree_to_shwi (idx_pos);
> +       if (idx_offset == ref_offset)
> +         return range_from_readonly_load (r, type, val, comps, i);
>       }
>        if (TREE_CODE (TREE_TYPE (cst)) == RECORD_TYPE)
>       return range_from_missing_constructor_part (r, type);
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to