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.

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?

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);
-- 
2.55.0

Reply via email to