https://gcc.gnu.org/bugzilla/show_bug.cgi?id=125304

--- Comment #3 from David Malcolm <dmalcolm at gcc dot gnu.org> ---
FWIW I've been using Claude Code to help debug this.  Here's the summary it
came up with of our conversation:

Root cause analysis:

At the comparison `_M_data() == _M_local_data()` in the _M_is_local() method
(line 84 of the test case):

- _M_data() returns a plain pointer: &s._M_local_buf
- _M_local_data() calls
std::pointer_traits<pointer>::pointer_to(*_M_local_buf), which creates a
CAST_REG wrapper: &CAST_REG(..., s._M_local_buf)

Both point to the same location, but the analyzer's region/svalue comparison
logic incorrectly concludes the pointers are "definitely non-equal" when one is
wrapped in CAST_REG and the other is not.

This causes the analyzer to only explore the false branch of the comparison,
skipping the `return true;` early exit. The false branch leads to _M_destroy()
being called on stack memory, producing the false positive.

The correct behavior would be to either:
1. Recognize that both pointers refer to the same location (best)
2. Return "unknown" and explore both branches conservatively (acceptable)

The current behavior of concluding "definitely non-equal" is incorrect and
leads to false positives.

Exploded graph analysis (using -fdump-analyzer-exploded-graph and
-fdiagnostics-add-output=sarif:analyzer-graphs=yes) confirms that at the
comparison point, the analyzer creates only one outgoing edge (false branch)
instead of exploring both branches or just the true branch.

Reply via email to