analyzer: handle compound assignments [PR94378]
authorDavid Malcolm <dmalcolm@redhat.com>
Mon, 30 Mar 2020 21:02:59 +0000 (17:02 -0400)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 1 Apr 2020 19:34:40 +0000 (15:34 -0400)
commita96f1c38a787fbc847cb014d4b094e2787d539a7
tree344b4bab5c1d19a4e87aac09abbd98c82c9c74b2
parent7546463b9f7a0b001cf61a94dcfc18f540721390
analyzer: handle compound assignments [PR94378]

PR analyzer/94378 reports a false -Wanalyzer-malloc-leak
when returning a struct containing a malloc-ed pointer.

The issue is that the assignment code was not handling
compound copies, only copying top-level values from region to region,
and not copying child values.

This patch introduces a region_model::copy_region function, using
it for assignments and when analyzing function return values.
It recursively copies nested values within structs, unions, and
arrays, fixing the bug.

gcc/analyzer/ChangeLog:
PR analyzer/94378
* checker-path.cc: Include "bitmap.h".
* constraint-manager.cc: Likewise.
* diagnostic-manager.cc: Likewise.
* engine.cc: Likewise.
(exploded_node::detect_leaks): Pass null region_id to pop_frame.
* program-point.cc: Include "bitmap.h".
* program-state.cc: Likewise.
* region-model.cc (id_set<region_id>::id_set): Convert to...
(region_id_set::region_id_set): ...this.
(svalue_id_set::svalue_id_set): New ctor.
(region_model::copy_region): New function.
(region_model::copy_struct_region): New function.
(region_model::copy_union_region): New function.
(region_model::copy_array_region): New function.
(stack_region::pop_frame): Drop return value.  Add
"result_dst_rid" param; if it is non-null, use copy_region to copy
the result to it.  Rather than capture and pass a single "known
used" return value to be used by purge_unused_values, instead
gather and pass a set of known used return values.
(root_region::pop_frame): Drop return value.  Add "result_dst_rid"
param.
(region_model::on_assignment): Use copy_region.
(region_model::on_return): Likewise for the result.
(region_model::on_longjmp): Pass null for pop_frame's
result_dst_rid.
(region_model::update_for_return_superedge): Pass the region for the
return value of the call, if any, to pop_frame, rather than setting
the lvalue for the lhs of the result.
(region_model::pop_frame): Drop return value.  Add
"result_dst_rid" param.
(region_model::purge_unused_svalues): Convert third param from an
svalue_id * to an svalue_id_set *, updating the initial populating
of the "used" bitmap accordingly.  Don't remap it when done.
(struct selftest::coord_test): New selftest fixture, extracted from...
(selftest::test_dump_2): ...here.
(selftest::test_compound_assignment): New selftest.
(selftest::test_stack_frames): Pass null to new param of pop_frame.
(selftest::analyzer_region_model_cc_tests): Call the new selftest.
* region-model.h (class id_set): Delete template.
(class region_id_set): Reimplement, using old id_set implementation.
(class svalue_id_set): Likewise.  Convert from auto_sbitmap to
auto_bitmap.
(region::get_active_view): New accessor.
(stack_region::pop_frame): Drop return value.  Add
"result_dst_rid" param.
(root_region::pop_frame): Likewise.
(region_model::pop_frame): Likewise.
(region_model::copy_region): New decl.
(region_model::purge_unused_svalues): Convert third param from an
svalue_id * to an svalue_id_set *.
(region_model::copy_struct_region): New decl.
(region_model::copy_union_region): New decl.
(region_model::copy_array_region): New decl.

gcc/testsuite/ChangeLog:
PR analyzer/94378
* gcc.dg/analyzer/compound-assignment-1.c: New test.
* gcc.dg/analyzer/compound-assignment-2.c: New test.
* gcc.dg/analyzer/compound-assignment-3.c: New test.
13 files changed:
gcc/analyzer/ChangeLog
gcc/analyzer/checker-path.cc
gcc/analyzer/constraint-manager.cc
gcc/analyzer/diagnostic-manager.cc
gcc/analyzer/engine.cc
gcc/analyzer/program-point.cc
gcc/analyzer/program-state.cc
gcc/analyzer/region-model.cc
gcc/analyzer/region-model.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/compound-assignment-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/compound-assignment-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/compound-assignment-3.c [new file with mode: 0644]