https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125304
--- Comment #6 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by David Malcolm <[email protected]>: https://gcc.gnu.org/g:573b66baa6cb8d38771b864d40a42ca2401ac5b9 commit r17-609-g573b66baa6cb8d38771b864d40a42ca2401ac5b9 Author: David Malcolm <[email protected]> Date: Tue May 19 15:04:30 2026 -0400 analyzer: fix pointer comparisons [PR125304] PR analyzer/125304 describes a false positive from -fanalyzer on a trivial use of std::string, due to the analyzer getting confused about the paths for the small-string optimization versus heap-allocated strings. The root cause is a bug in region_svalue::eval_condition which handles many kinds of pointer comparison, but which seems to have often been hidden by the optimizer. Previously, it simply compared for identity of the underlying "region" instance, returning true if identical, false otherwise. This is wrong: (a) for some cases, including the above one, different "region" instances might represent the same memory (and thus we were returning "false" when we should have returned "true") (b) for some cases, different "region" instances we might not be able to determine if they are the same address (and thus we were returning "false" when we should have returned "unknown") This patch rewrites region_svalue::eval_condition so that rather than comparing the regions by identity, it compares their region_offset values, taking into account their base regions and byte offsets within those regions. Doing so requires using store::eval_alias, and so the patch extends that to handle more cases precisely. This new implementation fixes (a) and (b) above. There are some cases where precision could be improved (where with the patch we return "unknown" when we ought to return a known bool), but fixing these would be more invasive and so are left to followup work. gcc/analyzer/ChangeLog: PR analyzer/125304 * common.h (compare_bit_offsets_p): New decl. (eval_region_offset_comparison): New decl. * region-model.cc (region_model::on_assignment): Pass *this to store::set_value to help determination of aliasing. (region_model::set_value): Likewise. (region_model::eval_condition): Likewise for region_svalue::eval_condition. * region.cc (compare_bit_offsets_p): New. (region_offset::dump_to_pp): Dump the base region, wrapping the whole thing in braces. (eval_byte_offset_comparison): New. (eval_region_offset_comparison): New. * store.cc (store::set_value): Add "model" param and pass it to eval_alias. (store::eval_alias): Add "model" param and pass to eval_alias_1. Add early return of true when checking a base region against itself. Replace final return of "unknown" with logic that compares the kinds of the two base regions, and may be able to return "false" rather than "unknown". (store::eval_alias_1): Add "model" param and pass to eval_alias. Assert that we have two different base_regions. (store::replay_call_summary_cluster): Pass model to set_value. * store.h (store::set_value): Add "model" param. (store::eval_alias): Likewise. (store::eval_alias_1): Likewise. * svalue.cc (region_svalue::eval_condition): Likewise. Reimplement in terms of eval_region_offset_comparison. * svalue.h (region_svalue::eval_condition): Add "model" param. gcc/testsuite/ChangeLog: PR analyzer/125304 * c-c++-common/analyzer/pointer-comparison-pr125304-eq.c: New test. * c-c++-common/analyzer/pointer-comparison-pr125304-ge.c: New test. * c-c++-common/analyzer/pointer-comparison-pr125304-gt.c: New test. * c-c++-common/analyzer/pointer-comparison-pr125304-le.c: New test. * c-c++-common/analyzer/pointer-comparison-pr125304-lt.c: New test. * g++.dg/analyzer/pointer-casts-pr125304.C: New test. Signed-off-by: David Malcolm <[email protected]>
