From 3ade8743950279331a4512823933a0fb7f7b013b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Sat, 25 Jul 2020 13:14:12 -0400
Subject: [PATCH 334/377] FIXME: consider the effect of all stmts in an enode
 in feasibility-checking, not just the first

---
 gcc/analyzer/engine.cc                        | 52 ++++++++++++++-----
 gcc/analyzer/exploded-graph.h                 |  1 +
 gcc/testsuite/gcc.dg/analyzer/feasibility-1.c |  2 +-
 3 files changed, 40 insertions(+), 15 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 72187831dfe..42d80bdeac7 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1363,6 +1363,21 @@ exploded_node::exploded_node (const point_and_state &ps,
     gcc_checking_assert (ps.get_state ().m_region_model2->canonicalized_p ());
 }
 
+/* Get the stmt that was processed in this enode at index IDX.  */
+
+const gimple *
+exploded_node::get_processed_stmt (unsigned idx) const
+{
+  gcc_assert (idx < m_num_processed_stmts);
+  const program_point &point = get_point ();
+  gcc_assert (point.get_kind () == PK_BEFORE_STMT);
+  const supernode *snode = get_supernode ();
+  const unsigned int point_stmt_idx = point.get_stmt_idx ();
+  const unsigned int idx_within_snode = point_stmt_idx + idx;
+  const gimple *stmt = snode->m_stmts[idx_within_snode];
+  return stmt;
+}
+
 /* For use by dump_dot, get a value for the .dot "fillcolor" attribute.
    Colorize by sm-state, to make it easier to see how sm-state propagates
    through the exploded_graph.  */
@@ -3883,12 +3898,12 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out) const
 
   /* Traverse the path, updating this model.  */
   region_model model;
-  for (unsigned i = 0; i < m_edges.length (); i++)
+  for (unsigned edge_idx = 0; edge_idx < m_edges.length (); edge_idx++)
     {
-      const exploded_edge *eedge = m_edges[i];
+      const exploded_edge *eedge = m_edges[edge_idx];
       if (logger)
 	logger->log ("considering edge %i: EN:%i -> EN:%i",
-		     i,
+		     edge_idx,
 		     eedge->m_src->m_index,
 		     eedge->m_dest->m_index);
       const exploded_node &src_enode = *eedge->m_src;
@@ -3900,8 +3915,12 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out) const
 	  logger->end_log_line ();
 	}
 
-      if (const gimple *stmt = src_point.get_stmt ())
+      /* Update state for the stmts that were processed in each enode.  */
+      for (unsigned stmt_idx = 0; stmt_idx < src_enode.m_num_processed_stmts;
+	   stmt_idx++)
 	{
+	  const gimple *stmt = src_enode.get_processed_stmt (stmt_idx);
+
 	  /* Update cfun and input_location in case of ICE: make it easier to
 	     track down which source construct we're failing to handle.  */
 	  auto_cfun sentinel (src_point.get_function ());
@@ -3931,7 +3950,8 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out) const
 		  model.dump_to_pp (logger->get_printer (), false);
 		}
 	      if (out)
-		*out = new feasibility_problem (i, model, *eedge, last_stmt);
+		*out = new feasibility_problem (edge_idx, model, *eedge,
+						last_stmt);
 	      return false;
 	    }
 	}
@@ -3939,7 +3959,7 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out) const
 	{
 	  /* Special-case the initial eedge from the origin node to the
 	     initial function by pushing a frame for it.  */
-	  if (i == 0)
+	  if (edge_idx == 0)
 	    {
 	      gcc_assert (eedge->m_src->m_index == 0);
 	      gcc_assert (src_point.get_kind () == PK_ORIGIN);
@@ -3975,7 +3995,7 @@ exploded_path::feasible_p (logger *logger, feasibility_problem **out) const
       if (logger)
 	{
 	  logger->log ("state after edge %i: EN:%i -> EN:%i",
-		       i,
+		       edge_idx,
 		       eedge->m_src->m_index,
 		       eedge->m_dest->m_index);
 	  logger->start_log_line ();
@@ -3999,12 +4019,12 @@ exploded_path::feasible2_p (logger *logger, feasibility_problem **out,
 
   /* Traverse the path, updating this model.  */
   region_model2 model (eng->get_model_manager ());
-  for (unsigned i = 0; i < m_edges.length (); i++)
+  for (unsigned edge_idx = 0; edge_idx < m_edges.length (); edge_idx++)
     {
-      const exploded_edge *eedge = m_edges[i];
+      const exploded_edge *eedge = m_edges[edge_idx];
       if (logger)
 	logger->log ("considering edge %i: EN:%i -> EN:%i",
-		     i,
+		     edge_idx,
 		     eedge->m_src->m_index,
 		     eedge->m_dest->m_index);
       const exploded_node &src_enode = *eedge->m_src;
@@ -4016,8 +4036,12 @@ exploded_path::feasible2_p (logger *logger, feasibility_problem **out,
 	  logger->end_log_line ();
 	}
 
-      if (const gimple *stmt = src_point.get_stmt ())
+      /* Update state for the stmts that were processed in each enode.  */
+      for (unsigned stmt_idx = 0; stmt_idx < src_enode.m_num_processed_stmts;
+	   stmt_idx++)
 	{
+	  const gimple *stmt = src_enode.get_processed_stmt (stmt_idx);
+
 	  /* Update cfun and input_location in case of ICE: make it easier to
 	     track down which source construct we're failing to handle.  */
 	  auto_cfun sentinel (src_point.get_function ());
@@ -4051,7 +4075,7 @@ exploded_path::feasible2_p (logger *logger, feasibility_problem **out,
 		  /* FIXME: ideally feasibility_problem should use a
 		     region_model2.  However, I don't think the model
 		     is used; it's for debugging.  */
-		  *out = new feasibility_problem (i, /*model, */ *eedge,
+		  *out = new feasibility_problem (edge_idx, /*model, */ *eedge,
 						  last_stmt);
 		}
 	      return false;
@@ -4061,7 +4085,7 @@ exploded_path::feasible2_p (logger *logger, feasibility_problem **out,
 	{
 	  /* Special-case the initial eedge from the origin node to the
 	     initial function by pushing a frame for it.  */
-	  if (i == 0)
+	  if (edge_idx == 0)
 	    {
 	      gcc_assert (eedge->m_src->m_index == 0);
 	      gcc_assert (src_point.get_kind () == PK_ORIGIN);
@@ -4099,7 +4123,7 @@ exploded_path::feasible2_p (logger *logger, feasibility_problem **out,
       if (logger)
 	{
 	  logger->log ("state after edge %i: EN:%i -> EN:%i",
-		       i,
+		       edge_idx,
 		       eedge->m_src->m_index,
 		       eedge->m_dest->m_index);
 	  logger->start_log_line ();
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 3fa01822ad3..b2056e411a7 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -334,6 +334,7 @@ class exploded_node : public dnode<eg_traits>
     return get_point ().get_stack_depth ();
   }
   const gimple *get_stmt () const { return get_point ().get_stmt (); }
+  const gimple *get_processed_stmt (unsigned idx) const;
 
   const program_state &get_state () const { return m_ps.get_state (); }
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c b/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c
index 09d4181cf66..60c4e92a5ef 100644
--- a/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/feasibility-1.c
@@ -29,5 +29,5 @@ void test_4 (void)
   /* Thwart the optimizer.  */
   called_by_test_4 ();
   if (global_for_test_4)
-    __analyzer_dump_path (); /* { dg-message "path" "" { xfail *-*-* } } */
+    __analyzer_dump_path (); /* { dg-message "path" } */
 }
-- 
2.26.2

