From ed9267cf218a8c2bf1b5c2f01a5cfd6595c328ce Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 6 Mar 2019 15:13:42 -0500
Subject: [PATCH 069/217] FIXME: start adding event subclasses

---
 gcc/analyzer/engine.cc | 201 ++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 149 insertions(+), 52 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 32c5eee..1a21e4a 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -337,40 +337,8 @@ struct per_node_t
 
 /* FIXME.  */
 
-class checker_event : public diagnostic_event
+char *print (const char *fmt, ...)
 {
-public:
-  checker_event (location_t loc, tree fndecl, int depth,
-		 const char *desc)
-  : diagnostic_event (loc, fndecl, depth, desc)
-  {
-  }
-
-  // FIXME
-};
-
-/* FIXME.  */
-
-class checker_path : public diagnostic_path
-{
-public:
-  checker_path () : diagnostic_path () {}
-  checker_path (const checker_path &other);
-  checker_path& operator= (const checker_path &other);
-
-  unsigned num_events () const FINAL OVERRIDE
-  {
-    return m_events.length ();
-  }
-
-  const diagnostic_event & get_event (int idx) const FINAL OVERRIDE
-  {
-    return *m_events[idx];
-  }
-
-  void add_event (location_t loc, tree fndecl, int depth, const char *fmt, ...)
-    ATTRIBUTE_GCC_DIAG(5,6)
-  {
   /* FIXME: use global_dc's pp.  */
 #if 1
   pretty_printer *pp = global_dc->printer;
@@ -402,16 +370,138 @@ public:
   pp_output_formatted_text (pp);
 
   va_end (ap);
-
-  checker_event *new_event
-    = new checker_event (loc, fndecl, depth, pp_formatted_text (pp));
-  m_events.safe_push (new_event);
-#if 0  
-  fprintf (stderr, "DBG: added to path %p: %s\n", this, new_event->m_desc);
-#endif
+  char *result = xstrdup (pp_formatted_text (pp));
 
   pp_clear_output_area (pp);
 
+  return result;
+}
+
+/* FIXME.  */
+
+enum event_kind
+{
+  EK_STATE_CHANGE,
+  EK_EDGE,
+  EK_WARNING
+};
+
+/* FIXME.  */
+
+class checker_event : public diagnostic_event
+{
+public:
+  checker_event (enum event_kind kind,
+		 location_t loc, tree fndecl, int depth,
+		 const char *desc)
+  : diagnostic_event (loc, fndecl, depth, desc),
+    m_kind (kind)
+  {
+  }
+
+  virtual checker_event *clone () const = 0;
+
+  enum event_kind m_kind;
+};
+
+class state_change_event : public checker_event
+{
+public:
+  state_change_event (const supernode *node, const gimple *stmt,
+		      const state_machine &sm,
+		      tree var,
+		      state_machine::state_t from,
+		      state_machine::state_t to)
+  : checker_event (EK_STATE_CHANGE,
+		   stmt->location, node->m_fun->decl,
+		   0, /*state.get_stack_depth ()*/
+		   make_desc (var, sm, from, to)),
+    m_node (node), m_stmt (stmt), m_sm (sm),
+    m_var (var), m_from (from), m_to (to)
+  {
+  }
+
+  static char *make_desc (tree var,
+			  const state_machine &sm,
+			  state_machine::state_t from,
+			  state_machine::state_t to)
+  {
+    return print ("state of %qE: %qs -> %qs", var,
+		  sm.get_state_name (from),
+		  sm.get_state_name (to));
+  }
+
+  checker_event *clone () const FINAL OVERRIDE
+  {
+    return new state_change_event (m_node, m_stmt, m_sm, m_var, m_from, m_to);
+  }
+
+  const supernode *m_node;
+  const gimple *m_stmt;
+  const state_machine &m_sm;
+  tree m_var;
+  state_machine::state_t m_from;
+  state_machine::state_t m_to;
+};
+
+class edge_event : public checker_event
+{
+public:
+  edge_event (location_t loc, tree fndecl, int depth,
+	      const char *desc)
+  : checker_event (EK_EDGE, loc, fndecl, depth, desc)
+  {
+  }
+
+  checker_event *clone () const FINAL OVERRIDE
+  {
+    return new edge_event (m_loc, m_fndecl, m_depth, m_desc);
+  }
+
+  // FIXME
+};
+
+/* FIXME: a repeat of the warning message at the end of the path.  */
+
+class warning_event : public checker_event
+{
+public:
+  warning_event (location_t loc, tree fndecl, int depth,
+		 const char *desc)
+  : checker_event (EK_WARNING, loc, fndecl, depth, desc)
+  {
+  }
+
+  warning_event *clone () const FINAL OVERRIDE
+  {
+    return new warning_event (m_loc, m_fndecl, m_depth, m_desc);
+  }
+
+  // FIXME
+};
+
+/* FIXME.  */
+
+class checker_path : public diagnostic_path
+{
+public:
+  checker_path () : diagnostic_path () {}
+  checker_path (const checker_path &other);
+  checker_path& operator= (const checker_path &other);
+
+  unsigned num_events () const FINAL OVERRIDE
+  {
+    return m_events.length ();
+  }
+
+  const diagnostic_event & get_event (int idx) const FINAL OVERRIDE
+  {
+    return *m_events[idx];
+  }
+
+  void add_event (checker_event *event)
+  {
+    m_events.safe_push (event);
   }
 
   auto_delete_vec<checker_event> m_events;
@@ -423,8 +513,7 @@ checker_path::checker_path (const checker_path &other)
   checker_event *e;
   int i;
   FOR_EACH_VEC_ELT (other.m_events, i, e)
-    m_events.safe_push (new checker_event (e->m_loc, e->m_fndecl, e->m_depth,
-					   e->m_desc));
+    m_events.safe_push (e->clone ());
   // FIXME: quick push
 #if 0
   fprintf (stderr, "DBG: diagnostic_path copy-ctor (length=%i)\n", m_events.length ());
@@ -707,6 +796,7 @@ engine::prune_active_vars_to_cache_misses (sm_instance *sm_inst,
     }
 }
 
+#if 0
 static void
 make_path_from_backtrace (checker_path *out_path,
 			  engine *e, const backtrace &b,
@@ -729,6 +819,7 @@ make_path_from_backtrace (checker_path *out_path,
 	}
     }
 }
+#endif
 
 class engine_sm_context : public sm_context
 {
@@ -796,11 +887,12 @@ public:
 	m_sm_inst->m_active_vars.m_set.add (var_state_t (ec_var->m_tree, to));
 
 	if (m_path)
-	  m_path->add_event (stmt->location,
-			     node->m_fun->decl, 0,/*state.get_stack_depth ()*/
-			     "state of %qE: %qs -> %qs", ec_var->m_tree,
-			     m_engine->m_sm.get_state_name (from),
-			     m_engine->m_sm.get_state_name (to));
+	  {
+	    checker_event *event
+	      = new state_change_event (node, stmt, m_engine->m_sm,
+					var, from, to);
+	    m_path->add_event (event);
+	  }
       }
 
     if (m_engine->get_logger ())
@@ -1840,11 +1932,16 @@ engine::maybe_emit (const candidate_diagnostic &cd)
 #else
   checker_path path (cd.m_path);
 #endif
-  path.add_event (cd.m_stmt->location,
-		  cd.m_node->m_fun->decl, 0,/*state.get_stack_depth ()*/
-		  "here (%qE is in state %qs)", cd.m_var,
-		  m_sm.get_state_name (cd.m_state));
-  // FIXME: ideally would show the message here, too?
+
+  char *msg = print ("here (%qE is in state %qs)", cd.m_var,
+		     m_sm.get_state_name (cd.m_state));
+
+  checker_event *end_of_path
+   = new warning_event (cd.m_stmt->location,
+			cd.m_node->m_fun->decl, 0,/*state.get_stack_depth ()*/
+			msg);
+  path.add_event (end_of_path);
+  // FIXME: ideally would show the full message here, too?
 
   rich_loc.set_path (&path);
 
-- 
1.8.5.3

