The analyzer appeared to enter an infinite loop on malloc-1.c when -fanalyzer-verbosity=0 was used. In fact, it was slowly counting from 0 to 0xffffffff.
Root cause is looping up to effectively ((unsigned)0) - 1 in diagnostic_manager::consolidate_conditions when there are no events in the path. Fixed by the following, which uses signed integers when subtracting from path->num_events () when simplifying checker_paths. Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu. Pushed to trunk as r11-7987-g69b66ff02353a87585329bb3cf4ac20d6dee1b16. gcc/analyzer/ChangeLog: PR analyzer/99886 * diagnostic-manager.cc (diagnostic_manager::prune_interproc_events): Use signed integers when subtracting one from path->num_events (). (diagnostic_manager::consolidate_conditions): Likewise. Convert next_idx to a signed int. gcc/testsuite/ChangeLog: PR analyzer/99886 * gcc.dg/analyzer/pr99886.c: New test. --- gcc/analyzer/diagnostic-manager.cc | 8 +++++--- gcc/testsuite/gcc.dg/analyzer/pr99886.c | 21 +++++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/analyzer/pr99886.c diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc index 9ec3e899e85..443ff058f65 100644 --- a/gcc/analyzer/diagnostic-manager.cc +++ b/gcc/analyzer/diagnostic-manager.cc @@ -2081,7 +2081,7 @@ diagnostic_manager::prune_interproc_events (checker_path *path) const do { changed = false; - int idx = path->num_events () - 1; + int idx = (signed)path->num_events () - 1; while (idx >= 0) { /* Prune [..., call, function-entry, return, ...] triples. */ @@ -2200,7 +2200,9 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const if (flag_analyzer_verbose_edges) return; - for (unsigned start_idx = 0; start_idx < path->num_events () - 1; start_idx++) + for (int start_idx = 0; + start_idx < (signed)path->num_events () - 1; + start_idx++) { if (path->cfg_edge_pair_at_p (start_idx)) { @@ -2231,7 +2233,7 @@ diagnostic_manager::consolidate_conditions (checker_path *path) const [start_idx, next_idx) where all apart from the final event are on the same line, and all are either TRUE or FALSE edges, matching the initial. */ - unsigned next_idx = start_idx + 2; + int next_idx = start_idx + 2; while (path->cfg_edge_pair_at_p (next_idx) && same_line_as_p (start_exp_loc, path, next_idx)) { diff --git a/gcc/testsuite/gcc.dg/analyzer/pr99886.c b/gcc/testsuite/gcc.dg/analyzer/pr99886.c new file mode 100644 index 00000000000..da768ba6298 --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/pr99886.c @@ -0,0 +1,21 @@ +/* Regression test for hang with -fanalyzer-verbosity=0. */ +/* { dg-additional-options "-fanalyzer-verbosity=0" } */ + +#include <stdlib.h> + +struct coord { + float x; + float y; +}; + +void test_34 (void) +{ + float *q; + struct coord *p = malloc (sizeof (struct coord)); + if (!p) + return; + p->x = 0.0f; + q = &p->x; + free (p); + *q = 1.0f; /* { dg-warning "use after 'free' of 'q'" } */ +}; -- 2.26.2