From 19d1b2a671ab426fdb7c797e8c0f9de8454bfdce Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 6 Mar 2019 13:58:38 -0500
Subject: [PATCH 067/217] FIXME: subclassing diagnostic_path and events

---
 gcc/analyzer/engine.cc | 134 ++++++++++++++++++++++++++++++++++++++++++-------
 gcc/diagnostic-path.h  |  54 ++++++++++++--------
 gcc/diagnostic.c       |  16 +++---
 gcc/tree-diagnostic.c  |  61 +++++++++++-----------
 4 files changed, 192 insertions(+), 73 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index c75d58a..983f506 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -335,6 +335,108 @@ struct per_node_t
   set_of_summary_edges m_sfx_transition;
 };
 
+/* FIXME.  */
+
+class checker_event : public diagnostic_event
+{
+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;
+  pp_clear_output_area (pp);
+#else
+  pretty_printer tmp_pp;
+  pretty_printer *pp = &tmp_pp;
+#endif
+
+  text_info ti;
+  rich_location rich_loc (line_table, UNKNOWN_LOCATION);
+
+  va_list ap;
+
+  va_start (ap, fmt);
+
+  ti.format_spec = _(fmt);
+  ti.args_ptr = &ap;
+  ti.err_no = 0;
+  ti.x_data = NULL;
+  ti.m_richloc = &rich_loc;
+
+#if 1
+#else
+  pp_show_color (pp) = pp_show_color (global_dc->printer);
+  pp_format_decoder (pp) = pp_format_decoder (global_dc->printer);
+#endif
+  pp_format (pp, &ti);
+  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
+
+  pp_clear_output_area (pp);
+
+  }
+
+  auto_delete_vec<checker_event> m_events;
+};
+
+checker_path::checker_path (const checker_path &other)
+: m_events ()//other.m_events.length ())
+{
+  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));
+  // FIXME: quick push
+#if 0
+  fprintf (stderr, "DBG: diagnostic_path copy-ctor (length=%i)\n", m_events.length ());
+#endif
+}
+
+checker_path&
+checker_path::operator= (const checker_path &other)
+{
+  gcc_unreachable (); // FIXME
+}
+
 class backtrace
 {
 public:
@@ -396,7 +498,7 @@ public:
     return NULL;
   }
 
-  diagnostic_path m_path;
+  checker_path m_path;
   auto_vec <link> m_links; // FIXME: copy-ctor etc
 };
 
@@ -407,7 +509,7 @@ class candidate_diagnostic
 public:
   candidate_diagnostic (const supernode *node, const gimple *stmt,
 			tree var, state_machine::state_t state,
-			pending_diagnostic *pd, const diagnostic_path *path)
+			pending_diagnostic *pd, const checker_path *path)
   : m_node (node), m_stmt (stmt), m_var (var), m_state (state), m_pd (pd), 
     m_path (*path)
   {
@@ -423,7 +525,7 @@ public:
   tree m_var;
   state_machine::state_t m_state;
   pending_diagnostic *m_pd;
-  diagnostic_path m_path;
+  checker_path m_path;
 };
 
 class engine : public log_user
@@ -451,11 +553,11 @@ public:
 		     const superedge *last_edge);
   void on_phi (const supernode *node, const gphi *phi,
 	       sm_instance *sm_inst, const sm_instance *old_sm_inst,
-	       const backtrace &b, diagnostic_path *path, path_state *ps,
+	       const backtrace &b, checker_path *path, path_state *ps,
 	       const superedge *last_edge);
   void on_stmt (const supernode *node, const gimple *stmt,
 		sm_instance *sm_inst, const sm_instance *old_sm_inst,
-		const backtrace &b, diagnostic_path *path, path_state *ps);
+		const backtrace &b, checker_path *path, path_state *ps);
   void on_assignment (const supernode *node, const gimple *stmt,
 		      sm_instance *sm_inst, const sm_instance *old_sm_inst,
 		      tree lhs, tree rhs, const backtrace &b,
@@ -606,7 +708,7 @@ engine::prune_active_vars_to_cache_misses (sm_instance *sm_inst,
 }
 
 static void
-make_path_from_backtrace (diagnostic_path *out_path,
+make_path_from_backtrace (checker_path *out_path,
 			  engine *e, const backtrace &b,
 			  const gimple *final_stmt)
 {
@@ -632,7 +734,7 @@ class engine_sm_context : public sm_context
 {
 public:
   engine_sm_context (engine *e, const backtrace &b, sm_instance *sm_inst,
-		     const sm_instance *old_sm_inst, diagnostic_path *path,
+		     const sm_instance *old_sm_inst, checker_path *path,
 		     path_state *ps)
     : m_engine (e), m_backtrace (b),
       m_sm_inst (sm_inst), m_old_sm_inst (old_sm_inst),
@@ -763,7 +865,7 @@ private:
   const backtrace &m_backtrace;
   sm_instance *m_sm_inst;
   const sm_instance *m_old_sm_inst;
-  diagnostic_path *m_path;
+  checker_path *m_path;
   path_state *m_ps;
 };
 
@@ -971,7 +1073,7 @@ void
 engine::on_phi (const supernode *node, const gphi *phi,
 		sm_instance *sm_inst, const sm_instance *old_sm_inst,
 		const backtrace &b, /* FIXME: <<< this is purely so that we can generate full paths for debugging */
-		diagnostic_path *path, path_state *ps,
+		checker_path *path, path_state *ps,
 		const superedge *last_edge)
 {
   JIT_LOG_FUNC (get_logger ());
@@ -1010,7 +1112,7 @@ void
 engine::on_stmt (const supernode *node, const gimple *stmt,
 		 sm_instance *sm_inst, const sm_instance *old_sm_inst,
 		 const backtrace &b, /* FIXME: <<< this is purely so that we can generate full paths for debugging */
-		 diagnostic_path *path, path_state *ps)
+		 checker_path *path, path_state *ps)
 {
   JIT_LOG_FUNC (get_logger ());
   if (get_logger ())
@@ -1107,7 +1209,7 @@ engine::on_stmt (const supernode *node, const gimple *stmt,
 	{
 	  gcc_rich_location rich_loc (stmt->location);
 #if 0
-	  diagnostic_path full_path;
+	  checker_path full_path;
 	  int i;
 	  const supernode *iter;
 	  FOR_EACH_VEC_ELT (b.m_nodes, i, iter)
@@ -1682,7 +1784,7 @@ engine::detect_leaks (const supernode *node, const sm_instance &sm_inst,
       const gimple *stmt = get_stmt_for_leak ((*iter).m_var, b);
 
       // FIXME: various redundant copies here:
-      diagnostic_path p (b.m_path);
+      checker_path p (b.m_path);
       sm_instance new_sm_inst (sm_inst);
       engine_sm_context ctxt (this, b,
 			      &new_sm_inst,
@@ -1709,8 +1811,6 @@ engine::emit_candidate_diagnostics ()
 void
 engine::maybe_emit (const candidate_diagnostic &cd)
 {
-  // FIXME: for now, no filtering
-
   gcc_rich_location rich_loc (cd.m_stmt->location);
 #if 0
   backtrace full_backtrace;
@@ -1721,10 +1821,10 @@ engine::maybe_emit (const candidate_diagnostic &cd)
 		       m_engine->m_sm.get_state_name (state));
       return;
     }
-  diagnostic_path path;
+  checker_path path;
   make_path_from_backtrace (&path, m_engine, full_backtrace, stmt);
 #else
-  diagnostic_path path (cd.m_path);
+  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 ()*/
@@ -1915,7 +2015,7 @@ run_one_checker (const supergraph &sg, const state_machine &sm, logger *logger)
       log_scope s (logger, "top-level traversal", "%s", function_name (fun));
 
       backtrace b;
-      //	diagnostic_path path;
+      //	checker_path path;
       path_state ps;
 
       sm_instance sm_inst;
diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index cde0ea5..11f3382 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -55,36 +55,50 @@ along with GCC; see the file COPYING3.  If not see
     function; more complicated examples (such as interprocedural paths)
     might be printed as multiple notes.  */
 
-struct diagnostic_path
+/* One event with a diagnostic_path.  */
+
+struct diagnostic_event
 {
-  /* One event within the path.  */
-  struct event
-  {
-    event (location_t loc, tree fndecl, int depth, const char *desc);
-    ~event ();
+ public:
+  diagnostic_event (location_t loc, tree fndecl, int depth, const char *desc);
+  virtual ~diagnostic_event ();
+
+  location_t m_loc;
+  /* TODO: generalize this to a "backtrace", so that consumers can
+     decipher interprocedural sequences of events:  */
+  tree m_fndecl;
+
+  /* Stack depth, so that consumers can visualizes the interprocedural
+     calls, returns, and frame nesting.  */
+  int m_depth;
+
+  char *m_desc; // has been i18n-ed and formatted
+};
 
-    location_t m_loc;
-    /* TODO: generalize this to a "backtrace", so that consumers can
-       decipher interprocedural sequences of events:  */
-    tree m_fndecl;
+/* Abstract base class for getting at a sequence of events.  */
 
-    /* Stack depth, so that consumers can visualizes the interprocedural
-       calls, returns, and frame nesting.  */
-    int m_depth;
+class diagnostic_path
+{
+ public:
+  virtual unsigned num_events () const = 0;
+  virtual const diagnostic_event & get_event (int idx) const = 0;
+};
 
-    char *m_desc; // has been i18n-ed and formatted
-  };
+/* Concrete subclass: a simple vector of events.  */
 
-  diagnostic_path ();
-  diagnostic_path (const diagnostic_path &other);
-  diagnostic_path& operator= (const diagnostic_path &other);
+class simple_diagnostic_path : public diagnostic_path
+{
+ public:
+  simple_diagnostic_path ();
 
-  ~diagnostic_path ();
+  unsigned num_events () const FINAL OVERRIDE;
+  const diagnostic_event & get_event (int idx) const FINAL OVERRIDE;
 
   void add_event (location_t loc, tree fndecl, int depth, const char *fmt, ...)
     ATTRIBUTE_GCC_DIAG(5,6);
 
-  auto_vec<event *> m_events;
+ private:
+  auto_delete_vec<diagnostic_event> m_events;
 };
 
 // FIXME:
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 3a7f831..e1de579 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -1750,6 +1750,7 @@ auto_diagnostic_group::~auto_diagnostic_group ()
     }
 }
 
+#if 0
 /* struct diagnostic_path */
 
 diagnostic_path::diagnostic_path () : m_events ()
@@ -1787,10 +1788,12 @@ diagnostic_path::~diagnostic_path ()
     delete n;
 }
 
+#endif
+
 /* FIXME.  */
 
 void
-diagnostic_path::add_event (location_t loc, tree fndecl, int depth, const char *fmt, ...)
+simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth, const char *fmt, ...)
 {
   /* FIXME: use global_dc's pp.  */
 #if 1
@@ -1824,7 +1827,8 @@ diagnostic_path::add_event (location_t loc, tree fndecl, int depth, const char *
 
   va_end (ap);
 
-  event *new_event = new event (loc, fndecl, depth, pp_formatted_text (pp));
+  diagnostic_event *new_event
+    = new diagnostic_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);
@@ -1833,15 +1837,15 @@ diagnostic_path::add_event (location_t loc, tree fndecl, int depth, const char *
   pp_clear_output_area (pp);
 }
 
-/* struct diagnostic_path::event.  */
+/* struct diagnostic_event.  */
 
-diagnostic_path::event::event (location_t loc, tree fndecl, int depth,
-			       const char *desc)
+diagnostic_event::diagnostic_event (location_t loc, tree fndecl, int depth,
+				    const char *desc)
 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
 {
 }
 
-diagnostic_path::event::~event ()
+diagnostic_event::~diagnostic_event ()
 {
   free (m_desc);
 }
diff --git a/gcc/tree-diagnostic.c b/gcc/tree-diagnostic.c
index 162b31f..af7db2c 100644
--- a/gcc/tree-diagnostic.c
+++ b/gcc/tree-diagnostic.c
@@ -322,9 +322,9 @@ class path_label : public range_label
   label_text get_text (unsigned range_idx) const FINAL OVERRIDE
   {
     unsigned event_idx = m_start_idx + range_idx;
-    const diagnostic_path::event *event = m_path->m_events[event_idx];
+    const diagnostic_event &event = m_path->get_event (event_idx);
 
-    return label_text (xasprintf ("(%i) %s", event_idx + 1, event->m_desc),
+    return label_text (xasprintf ("(%i) %s", event_idx + 1, event.m_desc),
 		       true);
   }
 
@@ -334,26 +334,26 @@ class path_label : public range_label
 };
 
 static bool
-can_consolidate_events (diagnostic_path::event *e1,
-			diagnostic_path::event *e2)
+can_consolidate_events (const diagnostic_event &e1,
+			const diagnostic_event &e2)
 {
   // FIXME: might want to simply group them by function, and also
   // split whenever there's a backward jump?
-  if (e1->m_fndecl != e2->m_fndecl)
+  if (e1.m_fndecl != e2.m_fndecl)
     return false;
 
 #if 0
   // FIXME: do we need this?
-  if (e1->m_depth != e2->m_depth)
+  if (e1.m_depth != e2.m_depth)
     return false;
 #endif
 
   /* Neither can be macro-based.  */
   if (linemap_location_from_macro_expansion_p (line_table,
-					       e1->m_loc))
+					       e1.m_loc))
     return false;
   if (linemap_location_from_macro_expansion_p (line_table,
-					       e2->m_loc))
+					       e2.m_loc))
     return false;
 
   // TODO:
@@ -377,18 +377,18 @@ tree_print_diagnostic_path (diagnostic_context *context,
     {
       /* Try consolidating events into rich locations.  */
       unsigned start_idx = 0;
-      while (start_idx < path->m_events.length ())
+      while (start_idx < path->num_events ())
 	{
 	  path_label label (path, start_idx);
-	  diagnostic_path::event *event = path->m_events[start_idx];
-	  gcc_rich_location richloc (event->m_loc);
+	  const diagnostic_event &event = path->get_event (start_idx);
+	  gcc_rich_location richloc (event.m_loc);
 	  unsigned j;
-	  for (j = start_idx + 1; j < path->m_events.length (); j++)
+	  for (j = start_idx + 1; j < path->num_events (); j++)
 	    {
-	      diagnostic_path::event *other = path->m_events[j];
+	      const diagnostic_event &other = path->get_event (j);
 	      // TODO: label, and slacken the constraint
 	      if (can_consolidate_events (event, other))
-		if (richloc.add_location_if_nearby (other->m_loc, false,
+		if (richloc.add_location_if_nearby (other.m_loc, false,
 						    &label))
 		  continue;
 	      break;
@@ -399,8 +399,8 @@ tree_print_diagnostic_path (diagnostic_context *context,
 	     function name changes.  */
 	  tree saved_current_function_decl = current_function_decl;
 	  location_t saved_input_location = input_location;
-	  current_function_decl = event->m_fndecl;
-	  input_location = event->m_loc;
+	  current_function_decl = event.m_fndecl;
+	  input_location = event.m_loc;
 #endif
 
 #if 0
@@ -422,7 +422,7 @@ tree_print_diagnostic_path (diagnostic_context *context,
 	  free ((char*) new_prefix);
 #endif
 
-	  inform (&richloc, "(%i) %s", start_idx + 1, event->m_desc);
+	  inform (&richloc, "(%i) %s", start_idx + 1, event.m_desc);
 	  start_idx = j;
 
 #if 1
@@ -434,10 +434,11 @@ tree_print_diagnostic_path (diagnostic_context *context,
   else
     {
       /* Simpler implementation: a note per event.  */
-      diagnostic_path::event *event;
-      int i;
-      FOR_EACH_VEC_ELT (path->m_events, i, event)
-	inform (event->m_loc, "(%i) %s", i + 1, event->m_desc);
+      for (unsigned i = 0; i < path->num_events (); i++)
+	{
+	  const diagnostic_event &event = path->get_event (i);
+	  inform (event.m_loc, "(%i) %s", i + 1, event.m_desc);
+	}
     }
 }
 
@@ -449,21 +450,21 @@ static json::value *
 tree_make_json_for_path (diagnostic_context *, const diagnostic_path *path)
 {
   json::array *path_array = new json::array ();
-  int i;
-  diagnostic_path::event *event;
-  FOR_EACH_VEC_ELT (path->m_events, i, event)
+  for (unsigned i = 0; i < path->num_events (); i++)
     {
+      const diagnostic_event &event = path->get_event (i);
+
       json::object *event_obj = new json::object ();
-      if (event->m_loc)
-	event_obj->set ("location", json_from_expanded_location (event->m_loc));
-      event_obj->set ("description", new json::string (event->m_desc));
-      if (event->m_fndecl)
+      if (event.m_loc)
+	event_obj->set ("location", json_from_expanded_location (event.m_loc));
+      event_obj->set ("description", new json::string (event.m_desc));
+      if (event.m_fndecl)
 	{
 	  const char *function
-	    = identifier_to_locale (lang_hooks.decl_printable_name (event->m_fndecl, 2));
+	    = identifier_to_locale (lang_hooks.decl_printable_name (event.m_fndecl, 2));
 	  event_obj->set ("function", new json::string (function));
 	}
-      event_obj->set ("depth", new json::number (event->m_depth));
+      event_obj->set ("depth", new json::number (event.m_depth));
       path_array->append (event_obj);
     }
   return path_array;
-- 
1.8.5.3

