From c05a36cb6b7d2de95c078b2bc8239bb658b0ef7f Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 18 Jul 2019 21:20:55 -0400
Subject: [PATCH 105/108] FIXME: group worklist by sm-state, and canonicalize
 after merging

---
 gcc/analyzer/impl-4.cc                            | 22 ++++++++++++++++++++++
 gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c | 14 +++++++-------
 gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c |  4 +---
 gcc/testsuite/gcc.dg/analyzer/paths-6.c           |  7 +++----
 gcc/testsuite/gcc.dg/analyzer/paths-7.c           |  8 ++++----
 5 files changed, 37 insertions(+), 18 deletions(-)

diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index 16442f1..911702c 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -3766,6 +3766,9 @@ program_state::can_merge_with_p (const program_state &other,
       result.m_checker_states.safe_push (merged_smap);
     }
 
+  impl_region_model_context ctxt (&result, ext_state);
+  result.m_region_model->canonicalize (&ctxt);
+
   if (out)
     *out = result;
 
@@ -3914,8 +3917,10 @@ exploded_node::dump_dot (graphviz_out *gv, const dump_args_t &) const
   m_ps.m_point.print (pp, f);
   pp_newline (pp);
 
+#if 0
   m_ps.m_state.dump_to_pp (m_ext_state, pp);
   pp_newline (pp);
+#endif
 
   pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
 
@@ -5604,6 +5609,23 @@ worklist::key_t::cmp_1 (const worklist::key_t &ka, const worklist::key_t &kb)
   /* Otherwise, we ought to have the same program_point.  */
   gcc_assert (point_a == point_b);
 
+  const program_state &state_a = ka.m_enode->get_state ();
+  const program_state &state_b = kb.m_enode->get_state ();
+
+  /* FIXME: sort by sm-state, so that identical sm-states are grouped
+     together in the worklist.  */
+  // for now, try the hash value (might not be deterministic)
+  for (unsigned sm_idx = 0; sm_idx < state_a.m_checker_states.length ();
+       ++sm_idx)
+    {
+      sm_state_map *smap_a = state_a.m_checker_states[sm_idx];
+      sm_state_map *smap_b = state_b.m_checker_states[sm_idx];
+
+      int sm_cmp = smap_a->hash () - smap_b->hash ();
+      if (sm_cmp)
+	return sm_cmp;
+    }
+
   /* Otherwise, we have two enodes at the same program point but with
      different states.  We don't have a good total ordering on states,
      so order them by enode index, so that we have at least have a
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c
index f252df1..16f4a5f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-2.c
@@ -39,9 +39,9 @@ int test_repeated_predicate_1 (int n)
     result = sum;
   }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "8 exploded nodes" } */
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "8 exploded nodes" } */
-  // FIXME: why 8 here?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
+  // FIXME: why 4 here?
 
   if (n > 10)
     free (ptr); /* { dg-bogus "not on the heap" } */
@@ -104,8 +104,8 @@ int test_explicit_flag (int n)
     result = sum;
   }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "8 exploded nodes" } */
-  // FIXME: why 8 here?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
+  // FIXME: why 4 here?
 
   if (need_to_free)
     free (ptr); /* { dg-bogus "not on the heap" } */
@@ -139,8 +139,8 @@ int test_pointer_comparison (int n)
     result = sum;
   }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "8 exploded nodes" } */
-  // FIXME: why 8 here?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
+  // FIXME: why 4 here?
 
   if (ptr != buf)
     free (ptr); /* { dg-bogus "not on the heap" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c
index d3bff3f..b76f06b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-vs-local-3.c
@@ -38,9 +38,7 @@ int test_1 (int n)
     result = sum;
   }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" "" { xfail *-*-* } } */
-  /* { dg-bogus "5 exploded nodes" "" { xfail *-*-* } .-1 } */
-  /* TODO(xfail): should be 2 nodes here, for the malloc-vs-non-malloc case; erroneously getting more.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */
 
   return result; /* { dg-message "leak of 'ptr'" } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-6.c b/gcc/testsuite/gcc.dg/analyzer/paths-6.c
index b72111e..eb3882b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/paths-6.c
+++ b/gcc/testsuite/gcc.dg/analyzer/paths-6.c
@@ -43,7 +43,7 @@ void test_2 (int flag)
       f = 3;
     }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
   __analyzer_eval (f == 3); /* { dg-warning "TRUE" } */
   __analyzer_eval (g == 4); /* { dg-warning "TRUE" } */
@@ -93,7 +93,7 @@ void test_3 (int i)
       break;
     }
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "8 exploded nodes" } */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "6 exploded nodes" } */
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
   __analyzer_eval (f == 3); /* { dg-warning "TRUE" } */
   __analyzer_eval (g == 4); /* { dg-warning "TRUE" } */
@@ -114,8 +114,7 @@ void test_4 (int flag)
       p = malloc (256);
     }
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 exploded nodes" } */
-  // FIXME: should the above be 1 node?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
   free (p);
   free (q);
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-7.c b/gcc/testsuite/gcc.dg/analyzer/paths-7.c
index 905bded..f841756 100644
--- a/gcc/testsuite/gcc.dg/analyzer/paths-7.c
+++ b/gcc/testsuite/gcc.dg/analyzer/paths-7.c
@@ -23,8 +23,8 @@ int test (int flag, void *ptr, int *p, int n)
     sum += foo (p[i]); /* { dg-bogus "uninitialized" } */
   result = sum;
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "5 exploded nodes" } */
-  // FIXME: why 5 here?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
+  // FIXME: why 3 here?
 
   if (flag)
     free (ptr); /* { dg-warning "double-free of 'ptr'" } */
@@ -52,8 +52,8 @@ int test_2 (int flag, int *p, int n)
     sum += foo (p[i]); /* { dg-bogus "uninitialized" } */
   result = sum;
 
-  __analyzer_dump_exploded_nodes (0); /* { dg-warning "5 exploded nodes" } */
-  // FIXME: why 5 here?
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "6 exploded nodes" } */
+  // FIXME: why 6 here?
 
   free (ptr); /* { dg-warning "double-free of 'ptr'" } */
   return result;
-- 
1.8.5.3

