From 70a8608e40f17eed7b1d0c3a55e625492d221821 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 7 Mar 2019 15:44:42 -0500
Subject: [PATCH 080/169] FIXME: experiments at reconstructing paths from call
 summaries

---
 gcc/analyzer/engine.cc | 127 +++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 124 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index f3dfc8ef..0734686 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -2090,6 +2090,20 @@ engine::emit_candidate_diagnostics ()
     maybe_emit (*cd);
 }
 
+#if 0
+class expand_call_sm_context : public sm_context
+{
+};
+#endif
+
+#if 0
+checker_path *
+engine::dfs_reconstruct (const supernode *node,
+			 tree var, state_machine::state_t state)
+{
+}
+#endif
+
 checker_path *
 engine::expand_call_summary (const call_summary *summary_event,
 			     tree var, state_machine::state_t state)
@@ -2118,16 +2132,123 @@ engine::expand_call_summary (const call_summary *summary_event,
 
   // TODO: body of function
 
+  /* Reconstruct a path (ideally feasible) within the function that makes
+     the state change happen.  We can probably figure that out from
+     the suffix summaries.  */
+  {
+    const int callee_stack_depth = summary_event->m_depth + 1;
+    const supernode *node = callee_node;
+    while (node)
+      {
+	/* FIXME: look in sfx_add/sfx_transition.  */
+
+	result->add_event (new debug_event (node->get_start_location (),
+					    node->m_fun->decl,
+					    callee_stack_depth,
+					    print ("SN: %i", node->m_index)));
+
+	/* Stmts.  */
+	int i;
+	gimple *stmt;
+	FOR_EACH_VEC_ELT (node->m_stmts, i, stmt)
+	  {
+	    if (m_verbosity >= 2)
+	      {
+		pretty_printer pp;
+		pp_string (&pp, "stmt: ");
+		pp_gimple_stmt_1 (&pp, const_cast <gimple *> (stmt),
+				  0, (dump_flags_t)0);
+		checker_event *event
+		  = new debug_event (stmt->location,
+				     node->m_fun->decl,
+				     callee_stack_depth,
+				     pp_formatted_text (&pp));
+		result->add_event (event);
+
+		per_stmt_t &data = get_data_for_stmt (stmt);
+		// TODO: add events for transitions
+		event
+		  = new debug_event (stmt->location,
+				     node->m_fun->decl,
+				     callee_stack_depth,
+				     data.m_transitions.to_str (m_sm).c_str ());
+		result->add_event (event);
+
+		for (set_of_summary_edges::iterator iter
+		       = data.m_transitions.begin ();
+		     iter != data.m_transitions.end ();
+		     ++iter)
+		  {
+		    const summary_edge &e = (*iter);
+		    event
+		      = new state_change_event (node, stmt,
+						callee_stack_depth,
+						m_sm,
+						e.m_start.m_varstate.m_var,
+						e.m_start.m_varstate.m_state,
+						e.m_end.m_varstate.m_state);
+		    result->add_event (event);
+		  }
+
+#if 0
+		expand_call_sm_context ctxt (this, b, sm_inst,
+					     old_sm_inst, path, ps);
+		m_sm.on_stmt (&ctxt, node, stmt);
+		m_on_stmt_calls++;
+#endif
+
+		// FIXME: We only really care about the stmts and edges
+		// that are required to get into the target state
+	      }
+	  }
+
+	// TODO: find better successor; track state etc in case of loops:
+	// FIXME: termination!
+	// TODO: we may need to recurse to handle
+	// TODO: we probably want to access recorded transitions about stmts
+	// TODO: alternatively: have a different context, and replay
+	// transitions using it
+	/* Or would dfs_traverse with a different "mode" be a better way of
+	   doing things:
+	   mode 1:
+	     get an overapproximation of states, and gather
+	     candidate diagnostics
+	   mode 2:
+	     during a candidate diagnostic, reconstruct a full
+	     path to said diagnostic (maybe using the suffix summaries?).
+
+	   Possibly a backwards DFS traversal, starting at endpoint, and
+	   exploring to find a route to an entrypoint?
+
+	   Should we tag the candidate diagnostics with the input state
+	   to their supernode that triggered them?
+
+	   Do we want to tag the blk_ edges with a "how this can happen?"
+	   object?  What if several ways?  */
+
+	if (node->return_p ())
+	  break;
+	if (node->m_succs.length () > 0)
+	  {
+	    node = node->m_succs[0]->m_dest;
+	    // FIXME: must be in same function, etc etc
+	  }
+	else
+	  break;
+      }
+  }
+
+#if 0
   result->add_event (new debug_event (callee_node->get_start_location (),
 				      callee_node->m_fun->decl,
 				      summary_event->m_depth + 1,
 				      print ("within %qE",
 					     callee_node->m_fun->decl)));
-
+#endif
 
   result->add_event (new debug_event (summary_event->m_loc, // FIXME
-				      callee_node->m_fun->decl,
-				      summary_event->m_depth + 1,
+				      caller_node->m_fun->decl,
+				      summary_event->m_depth,
 				      print ("returning to %qE from %qE",
 					     caller_node->m_fun->decl,
 					     callee_node->m_fun->decl)));
-- 
1.8.5.3

