analyzer: add enode status and revamp __analyzer_dump_exploded_nodes
authorDavid Malcolm <dmalcolm@redhat.com>
Tue, 4 Feb 2020 21:23:27 +0000 (16:23 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Wed, 5 Feb 2020 14:49:26 +0000 (09:49 -0500)
commita4d3bfc0851ac1b489c4dea5b57dcc08adb20457
tree14f711db4f537bd3f7ffef85afca7e235ac3a5e4
parentb7b3378f91c0641f2ef4d88db22af62a571c9359
analyzer: add enode status and revamp __analyzer_dump_exploded_nodes

The analyzer recognizes __analyzer_dump_exploded_nodes as a "magic"
function for use in DejaGnu tests: at the end of the pass, it issues
a warning at each such call, dumping the count of exploded nodes seen at
the call, which can be checked in test cases via dg-warning directives,
along with the IDs of the enodes (which is helpful when debugging).

My intent was to give a way of testing the results of the state-merging
code.

The state-merging code can generate duplicate exploded nodes at a point
when state merging occurs, taking a pair of enodes from the worklist
that share a program_point and sufficiently similar state.  For these
cases it generates a merged state, and adds edges from those enodes to
the merged-state enode (potentially a new or a pre-existing enode); the
input enodes don't have process_node called on them.

This means that at a CFG join point there can be an unpredictable number
of enodes that we don't care about, where the precise number depends on
the details of the state-merger code, immediately followed by a more
predictable number that we do care about.

I've been papering over this in the analyzer DejaGnu tests somewhat
by adding pairs of __analyzer_dump_exploded_nodes calls at CFG join
points, where the output at the first call is somewhat arbitrary, and
the second has the number we care about; the first number tends to
change "at random" as I tweak the state merging code, in ways that
aren't interesting, but require the tests to be updated.

See e.g. gcc.dg/analyzer/paths-6.c which had:

  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */
  // FIXME: the above can vary between 2 and 3 exploded nodes
  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */

This patch remedies this situation by tracking which enodes are
processed, and which are merely "merger" enodes.  It updates the
output for __analyzer_dump_exploded_nodes so that count of enodes
only includes the *processed* enodes, and that the IDs are split
into "processed" and "merger" enodes.

The patch simplifies the testsuite by eliminating the redundant calls
described above; the example above becomes:

  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */

where the output in question is now:

  warning: 1 processed enode: [EN: 94] merger(s): [EN: 93]

The patch also adds various checks on the status of enodes, to ensure
e.g. that each enode is processed at most once.

gcc/analyzer/ChangeLog:
* engine.cc (exploded_node::dump_dot): Show merger enodes.
(worklist::add_node): Assert that the node's m_status is
STATUS_WORKLIST.
(exploded_graph::process_worklist): Likewise for nodes from the
worklist.  Set status of merged nodes to STATUS_MERGER.
(exploded_graph::process_node): Set status of node to
STATUS_PROCESSED.
(exploded_graph::dump_exploded_nodes): Rework handling of
"__analyzer_dump_exploded_nodes", splitting enodes by status into
"processed" and "merger", showing the count of just the processed
enodes at the call, rather than the count of all enodes.
* exploded-graph.h (exploded_node::status): New enum.
(exploded_node::exploded_node): Initialize m_status to
STATUS_WORKLIST.
(exploded_node::get_status): New getter.
(exploded_node::set_status): New setter.
(exploded_node::m_status): New field.

gcc/ChangeLog:
* doc/analyzer.texi
(Special Functions for Debugging the Analyzer): Update description
of __analyzer_dump_exploded_nodes.

gcc/testsuite/ChangeLog:
* gcc.dg/analyzer/data-model-1.c: Update for changed output to
__analyzer_dump_exploded_nodes, dropping redundant call at merger.
* gcc.dg/analyzer/data-model-7.c: Likewise.
* gcc.dg/analyzer/loop-2.c: Update for changed output format.
* gcc.dg/analyzer/loop-2a.c: Likewise.
* gcc.dg/analyzer/loop-4.c: Likewise.
* gcc.dg/analyzer/loop.c: Likewise.
* gcc.dg/analyzer/malloc-paths-10.c: Likewise; drop redundant
call at merger.
* gcc.dg/analyzer/malloc-vs-local-1a.c: Likewise.
* gcc.dg/analyzer/malloc-vs-local-1b.c: Likewise.
* gcc.dg/analyzer/malloc-vs-local-2.c: Likewise.
* gcc.dg/analyzer/malloc-vs-local-3.c: Likewise.
* gcc.dg/analyzer/paths-1.c: Likewise.
* gcc.dg/analyzer/paths-1a.c: Likewise.
* gcc.dg/analyzer/paths-2.c: Likewise.
* gcc.dg/analyzer/paths-3.c: Likewise.
* gcc.dg/analyzer/paths-4.c: Update for changed output format.
* gcc.dg/analyzer/paths-5.c: Likewise.
* gcc.dg/analyzer/paths-6.c: Likewise; drop redundant calls
at merger.
* gcc.dg/analyzer/paths-7.c: Likewise.
* gcc.dg/analyzer/torture/conditionals-2.c: Update for changed
output format.
* gcc.dg/analyzer/zlib-1.c: Likewise; drop redundant calls.
* gcc.dg/analyzer/zlib-5.c: Update for changed output format.
28 files changed:
gcc/ChangeLog
gcc/analyzer/ChangeLog
gcc/analyzer/engine.cc
gcc/analyzer/exploded-graph.h
gcc/doc/analyzer.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/data-model-1.c
gcc/testsuite/gcc.dg/analyzer/data-model-7.c
gcc/testsuite/gcc.dg/analyzer/loop-2.c
gcc/testsuite/gcc.dg/analyzer/loop-2a.c
gcc/testsuite/gcc.dg/analyzer/loop-4.c
gcc/testsuite/gcc.dg/analyzer/loop.c
gcc/testsuite/gcc.dg/analyzer/malloc-paths-10.c
gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1a.c
gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-1b.c
gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c
gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c
gcc/testsuite/gcc.dg/analyzer/paths-1.c
gcc/testsuite/gcc.dg/analyzer/paths-1a.c
gcc/testsuite/gcc.dg/analyzer/paths-2.c
gcc/testsuite/gcc.dg/analyzer/paths-3.c
gcc/testsuite/gcc.dg/analyzer/paths-4.c
gcc/testsuite/gcc.dg/analyzer/paths-5.c
gcc/testsuite/gcc.dg/analyzer/paths-6.c
gcc/testsuite/gcc.dg/analyzer/paths-7.c
gcc/testsuite/gcc.dg/analyzer/torture/conditionals-2.c
gcc/testsuite/gcc.dg/analyzer/zlib-1.c
gcc/testsuite/gcc.dg/analyzer/zlib-5.c