From e1e10d47f2532969d441c9263ed8b9c8ec233b99 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 28 Jun 2019 17:58:51 -0400
Subject: [PATCH 50/85] FIXME: fix merging of more than two nodes

---
 gcc/analyzer/impl-4.cc                  | 35 +++++++++++++++++++++++++--------
 gcc/testsuite/gcc.dg/analyzer/paths-1.c |  1 +
 gcc/testsuite/gcc.dg/analyzer/paths-2.c |  4 ++++
 gcc/testsuite/gcc.dg/analyzer/zlib-1.c  | 10 +++++-----
 4 files changed, 37 insertions(+), 13 deletions(-)

diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index b6e4454..b5256d4 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -5202,6 +5202,8 @@ exploded_graph::process_worklist ()
 	    gcc_assert (node->m_succs.length () == 0);
 	    gcc_assert (node_2->m_succs.length () == 0);
 
+	    gcc_assert (node != node_2);
+
 	    log ("peek worklist: EN: %i", node_2->m_index);
 
 	    if (node->get_point () == node_2->get_point ())
@@ -5264,15 +5266,32 @@ exploded_graph::process_worklist ()
 			     node->m_index, node_2->m_index,
 			     merged_enode->m_index);
 
-			/* Add edges from the unmerged nodes to the
-			   merged node.  */
-			add_edge (node, merged_enode, NULL);
-			add_edge (node_2, merged_enode, NULL);
-
 			/* "node" and "node_2" have both now been removed
-			   from the worklist.  Don't process them.
-			   The merged node will be processed in a
-			   subsequent iteration.  */
+			   from the worklist; we should not process them.
+
+			   "merged_enode" may be a new node; if so it will be
+			   processed in a subsequent iteration.
+			   Alternatively, "merged_enode" could be an existing
+			   node; one way the latter can
+			   happen is if we end up merging a succession of
+			   similar nodes into one.  */
+
+			/* If merged_node is one of the two we were merging,
+			   add it back to the worklist to ensure it gets
+			   processed.
+
+			   Add edges from the merged nodes to it (but not a
+			   self-edge).  */
+			if (merged_enode == node)
+			  m_worklist.add_node (merged_enode);
+			else
+			  add_edge (node, merged_enode, NULL);
+
+			if (merged_enode == node_2)
+			  m_worklist.add_node (merged_enode);
+			else
+			  add_edge (node_2, merged_enode, NULL);
+
 			continue;
 		      }
 		  }
diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-1.c b/gcc/testsuite/gcc.dg/analyzer/paths-1.c
index 7c299c4..45a83e7 100644
--- a/gcc/testsuite/gcc.dg/analyzer/paths-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/paths-1.c
@@ -15,4 +15,5 @@ void test (struct foo *pf)
     bar (1);
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
   /* TODO: consolidating 2 nodes into 1 leads to 2 + 1 == 3 resulting nodes.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/paths-2.c b/gcc/testsuite/gcc.dg/analyzer/paths-2.c
index f1013e8..babdeb0 100644
--- a/gcc/testsuite/gcc.dg/analyzer/paths-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/paths-2.c
@@ -9,6 +9,8 @@ int test (int a)
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
   /* TODO: consolidating 2 nodes into 1 leads to 2 + 1 == 3 resulting nodes.  */
 
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
+
   return 0;
 }
 
@@ -21,5 +23,7 @@ int test_2 (int a)
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
   /* TODO: consolidating 3 nodes into 1 leads to 3 + 1 == 4.  */
 
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
+
   return 0;
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/zlib-1.c b/gcc/testsuite/gcc.dg/analyzer/zlib-1.c
index 5d8f543..b74c9f1 100644
--- a/gcc/testsuite/gcc.dg/analyzer/zlib-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/zlib-1.c
@@ -36,31 +36,31 @@ int deflateEnd(z_stream *strm)
   }
 
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "4 exploded nodes" } */
-  /* TODO: consolidate them; see paths-2.c.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 
   if (strm->state->pending_buf)
     (*(strm->zfree))(strm->opaque, (void *)(strm->state->pending_buf));
 
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
-  /* TODO: consolidate them.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 
   if (strm->state->head)
       (*(strm->zfree))(strm->opaque, (void *)(strm->state->head));
 
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
-  /* TODO: consolidate them.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 
   if (strm->state->prev)
     (*(strm->zfree))(strm->opaque, (void *)(strm->state->prev));
 
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
-  /* TODO: consolidate them.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 
   if (strm->state->window)
     (*(strm->zfree))(strm->opaque, (void *)(strm->state->window));
 
   __analyzer_dump_exploded_nodes (0); /* { dg-warning "3 exploded nodes" } */
-  /* TODO: consolidate them.  */
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 exploded node" } */
 
   (*(strm->zfree))(strm->opaque, (void *)(strm->state));
   strm->state = 0;
-- 
1.8.5.3

