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
