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]>

Reply via email to