From d42a7cd9dc2ed892c65564f06e9378ca1275cd92 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 28 Jun 2019 16:42:23 -0400
Subject: [PATCH 49/63] FIXME: common graph subclasses; include paths

---
 gcc/analyzer/analyzer-logging.cc   |   2 +-
 gcc/analyzer/analyzer-pass.cc      |   4 +-
 gcc/analyzer/analyzer-plugin.cc    |   3 +-
 gcc/analyzer/analyzer.h            |   1 +
 gcc/analyzer/constraint-manager.cc |  10 +-
 gcc/analyzer/constraint-manager.h  |   2 +-
 gcc/analyzer/digraph.cc            | 152 +++++++++++++-------------
 gcc/analyzer/digraph.h             | 216 ++++++++++++++++++++++++-------------
 gcc/analyzer/graphviz.cc           |   2 +-
 gcc/analyzer/impl-2.cc             |  21 ++--
 gcc/analyzer/impl-3.cc             |  20 ++--
 gcc/analyzer/impl-4.cc             | 162 ++++++++++++++--------------
 gcc/analyzer/path-state.cc         |   8 +-
 gcc/analyzer/pending-diagnostic.cc |   8 +-
 gcc/analyzer/pending-diagnostic.h  |   2 +-
 gcc/analyzer/region-model.cc       |  14 +--
 gcc/analyzer/region-model.h        |   2 +-
 gcc/analyzer/sm-file.cc            |  10 +-
 gcc/analyzer/sm-malloc.cc          |  10 +-
 gcc/analyzer/sm-pattern-test.cc    |  10 +-
 gcc/analyzer/sm-sensitive.cc       |  10 +-
 gcc/analyzer/sm-taint.cc           |  10 +-
 gcc/analyzer/sm.cc                 |   6 +-
 gcc/analyzer/sm.h                  |   2 +-
 gcc/analyzer/supergraph.cc         |  48 ++++-----
 gcc/analyzer/supergraph.h          |  48 ++++++---
 gcc/analyzer/tristate.cc           |   2 +-
 27 files changed, 439 insertions(+), 346 deletions(-)

diff --git a/gcc/analyzer/analyzer-logging.cc b/gcc/analyzer/analyzer-logging.cc
index 179d3a3..6f2343e 100644
--- a/gcc/analyzer/analyzer-logging.cc
+++ b/gcc/analyzer/analyzer-logging.cc
@@ -26,7 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic.h"
 #include "tree-diagnostic.h"
 
-#include "analyzer-logging.h"
+#include "analyzer/analyzer-logging.h"
 
 /* Implementation of class gcc::jit::logger.  */
 
diff --git a/gcc/analyzer/analyzer-pass.cc b/gcc/analyzer/analyzer-pass.cc
index be676d4..40989f5 100644
--- a/gcc/analyzer/analyzer-pass.cc
+++ b/gcc/analyzer/analyzer-pass.cc
@@ -26,8 +26,8 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 
-#include "analyzer.h"
-#include "engine.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/engine.h"
 
 namespace {
 
diff --git a/gcc/analyzer/analyzer-plugin.cc b/gcc/analyzer/analyzer-plugin.cc
index 5dc89bb..86585b8 100644
--- a/gcc/analyzer/analyzer-plugin.cc
+++ b/gcc/analyzer/analyzer-plugin.cc
@@ -26,7 +26,7 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 
-#include "analyzer.h"
+#include "analyzer/analyzer.h"
 
 int plugin_is_GPL_compatible;
 
@@ -41,6 +41,7 @@ analyzer_selftests (void */*gcc_data*/, void */*user_data*/)
   analyzer_checker_script_cc_tests ();
 #endif
   analyzer_constraint_manager_cc_tests ();
+  analyzer_digraph_cc_tests ();
   analyzer_impl_2_cc_tests ();
   analyzer_impl_4_cc_tests ();
   analyzer_path_state_cc_tests ();
diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index a74ca58..a1b0a8a 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -66,6 +66,7 @@ extern tree build_global_decl (const char *name, tree type);
    alphabetical order, for the checker plugin.  */
 extern void analyzer_checker_script_cc_tests ();
 extern void analyzer_constraint_manager_cc_tests ();
+extern void analyzer_digraph_cc_tests ();
 extern void analyzer_impl_2_cc_tests ();
 extern void analyzer_impl_4_cc_tests ();
 extern void analyzer_path_state_cc_tests ();
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 03f64fc..8a159bb 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -33,14 +33,14 @@
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "analyzer-logging.h"
+#include "analyzer/analyzer-logging.h"
 #include "stringpool.h"
 #include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "path-state.h"
-#include "supergraph.h"
-#include "constraint-manager.h"
+#include "analyzer/tristate.h"
+#include "analyzer/path-state.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/constraint-manager.h"
 #include "tree-diagnostic.h"
 
 /* A subclass of purge_criteria: purge a specific svalue_id.  */
diff --git a/gcc/analyzer/constraint-manager.h b/gcc/analyzer/constraint-manager.h
index 0ceba72..66dad50 100644
--- a/gcc/analyzer/constraint-manager.h
+++ b/gcc/analyzer/constraint-manager.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_CONSTRAINT_MANAGER_H
 #define GCC_ANALYZER_CONSTRAINT_MANAGER_H
 
-#include "region-model.h" // for svalue_id
+#include "analyzer/region-model.h" // for svalue_id
 
 class superedge;
 class call_superedge;
diff --git a/gcc/analyzer/digraph.cc b/gcc/analyzer/digraph.cc
index f7c1ce1..6ddb33a 100644
--- a/gcc/analyzer/digraph.cc
+++ b/gcc/analyzer/digraph.cc
@@ -45,90 +45,96 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
-#include "digraph.h"
-#include "tree-diagnostic.h"
+#include "analyzer/digraph.h"
+#include "selftest.h"
 
-void
-digraph::dump_dot_to_pp (pretty_printer *pp, cluster *root_cluster) const
+/* TODO: selftests.  */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* A family of digraph classes for writing selftests.  */
+
+struct test_node;
+struct test_edge;
+struct test_graph;
+struct test_dump_args_t {};
+struct test_cluster;
+
+struct test_graph_traits
 {
-  graphviz_out gv (pp);
-
-  pp_string (pp, "digraph \"");
-  pp_write_text_to_stream (pp);
-  pp_string (pp, "FIXME: base");
-  pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
-  pp_string (pp, "\" {\n");
-
-  gv.indent ();
-
-  pp_string (pp, "overlap=false;\n");
-  pp_string (pp, "compound=true;\n");
-
-  // TODO: maybe (optionally) sub-subdivide by TU, for LTO
-
-  /* TODO: see also:
-     https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png
-  */
-
-  /* If using clustering, emit all nodes via clusters.  */
-  if (root_cluster)
-    {
-      int i;
-      dnode *n;
-      FOR_EACH_VEC_ELT (m_nodes, i, n)
-	root_cluster->add_node (n);
-      root_cluster->dump_dot (&gv);
-    }
-  else
-    {
-      /* Otherwise, display all nodes at top level.  */
-      int i;
-      dnode *n;
-      FOR_EACH_VEC_ELT (m_nodes, i, n)
-	n->dump_dot (&gv);
-    }
-
-  /* Edges.  */
-  int i;
-  dedge *e;
-  FOR_EACH_VEC_ELT (m_edges, i, e)
-    e->dump_dot (&gv);
-
-  /* Terminate "digraph" */
-  gv.outdent ();
-  pp_string (pp, "}");
-  pp_newline (pp);
-}
+  typedef test_node node_t;
+  typedef test_edge edge_t;
+  typedef test_graph graph_t;
+  typedef test_dump_args_t dump_args_t;
+  typedef test_cluster cluster_t;
+};
+
+struct test_node : public dnode<test_graph_traits>
+{
+  test_node (const char *name) : m_name (name) {}
+  void dump_dot (graphviz_out *, const dump_args_t &) const OVERRIDE
+  {
+  }
 
-void
-digraph::dump_dot_to_file (FILE *fp, cluster *root_cluster) const
+  const char *m_name;
+};
+
+struct test_edge : public dedge<test_graph_traits>
 {
-  pretty_printer pp;
-  pp_format_decoder (&pp) = default_tree_printer;
-  pp.buffer->stream = fp;
-  dump_dot_to_pp (&pp, root_cluster);
-  pp_flush (&pp);
-}
+  test_edge (node_t *src, node_t *dest)
+  : dedge (src, dest)
+  {}
+
+  void dump_dot (graphviz_out *gv, const dump_args_t &) const OVERRIDE
+  {
+    pp_printf (gv->m_pp, "%s -> %s;\n",
+	       m_src->m_name, m_dest->m_name);
+  }
+};
+
+struct test_graph : public digraph<test_graph_traits>
+{
+};
 
-void
-digraph::dump_dot (const char *path, cluster *root_cluster) const
+struct test_cluster : public cluster<test_graph_traits>
 {
-  FILE *fp = fopen (path, "w");
-  dump_dot_to_file (fp, root_cluster);
-  fclose (fp);
-}
+};
 
-void
-digraph::add_node (dnode *node)
+/* FIXME.  */
+
+static void
+test_dump_to_dot ()
 {
-  m_nodes.safe_push (node);
+  test_graph g;
+  test_node *a = new test_node ("a");
+  test_node *b = new test_node ("b");
+  test_edge *e = new test_edge (a, b);
+  g.add_node (a);
+  g.add_node (b);
+  g.add_edge (e);
+
+  pretty_printer pp;
+  pp.buffer->stream = NULL;
+  test_dump_args_t dump_args;
+  g.dump_dot_to_pp (&pp, NULL, dump_args);
+
+  ASSERT_STR_CONTAINS (pp_formatted_text (&pp),
+		       "a -> b;\n");
 }
 
+/* Run all of the selftests within this file.  */
+
 void
-digraph::add_edge (dedge *edge)
+analyzer_digraph_cc_tests ()
 {
-  m_edges.safe_push (edge);
+  test_dump_to_dot ();
 }
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
diff --git a/gcc/analyzer/digraph.h b/gcc/analyzer/digraph.h
index 6f923ee..7240f7b 100644
--- a/gcc/analyzer/digraph.h
+++ b/gcc/analyzer/digraph.h
@@ -21,49 +21,82 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_DIGRAPH_H
 #define GCC_ANALYZER_DIGRAPH_H
 
-/* Forwards decls.  */
-class dnode;
-class dedge;
-class cluster;
+#include "tree-diagnostic.h" /* for default_tree_printer.  */
+
+/* Templates for a family of classes: digraph, node, edge, and cluster.
+   This assumes a traits type with the following typedefs:
+   node_t: the node class
+   edge_t: the edge class
+   dump_args_t: additional args for dot-dumps
+   cluster_t: the cluster class.  */
 
 /* Abstract base class for a node in a directed graph.  */
 
+template <typename GraphTraits>
 class dnode
 {
  public:
+  typedef typename GraphTraits::edge_t edge_t;
+  typedef typename GraphTraits::dump_args_t dump_args_t;
+
   virtual ~dnode () {}
+  virtual void dump_dot (graphviz_out *gv, const dump_args_t &args) const = 0;
 
-  virtual void dump_dot (graphviz_out *gv) const = 0;
+  auto_vec<edge_t *> m_preds;
+  auto_vec<edge_t *> m_succs;
 };
 
 /* Abstract base class for an edge in a directed graph.  */
 
+template <typename GraphTraits>
 class dedge
 {
  public:
+  typedef typename GraphTraits::node_t node_t;
+  typedef typename GraphTraits::dump_args_t dump_args_t;
+
+  dedge (node_t *src, node_t *dest)
+  : m_src (src), m_dest (dest) {}
+
   virtual ~dedge () {}
 
-  virtual void dump_dot (graphviz_out *gv) const = 0;
+  virtual void dump_dot (graphviz_out *gv, const dump_args_t &args) const = 0;
+
+  node_t *const m_src;
+  node_t *const m_dest;
 };
 
-/* Abstract base class for a directed graph.  */
+/* Abstract base class for a directed graph.
+   This class maintains the vectors of nodes and edges,
+   and owns the nodes and edges.  */
 
+template <typename GraphTraits>
 class digraph
 {
  public:
+  typedef typename GraphTraits::node_t node_t;
+  typedef typename GraphTraits::edge_t edge_t;
+  typedef typename GraphTraits::dump_args_t dump_args_t;
+  typedef typename GraphTraits::cluster_t cluster_t;
+
   digraph () {}
   virtual ~digraph () {}
 
-  void dump_dot_to_pp (pretty_printer *pp, cluster *root_cluster) const;
-  void dump_dot_to_file (FILE *fp, cluster *root_cluster) const;
-  void dump_dot (const char *path, cluster *root_cluster) const;
-
-  void add_node (dnode *node);
-  void add_edge (dedge *edge);
-
-  //protected:
-  auto_delete_vec<dnode> m_nodes;
-  auto_delete_vec<dedge> m_edges;
+  void dump_dot_to_pp (pretty_printer *pp,
+		       cluster_t *root_cluster,
+		       const dump_args_t &args) const;
+  void dump_dot_to_file (FILE *fp,
+			 cluster_t *root_cluster,
+			 const dump_args_t &args) const;
+  void dump_dot (const char *path,
+		 cluster_t *root_cluster,
+		 const dump_args_t &args) const;
+
+  void add_node (node_t *node);
+  void add_edge (edge_t *edge);
+
+  auto_delete_vec<node_t> m_nodes;
+  auto_delete_vec<edge_t> m_edges;
 };
 
 /* Abstract base class for splitting dnodes into hierarchical clusters
@@ -83,88 +116,123 @@ class digraph
    After all nodes are added to the root cluster, dump_dot will then
    be called on it (and not on the nodes themselves).  */
 
+template <typename GraphTraits>
 class cluster
 {
  public:
+  typedef typename GraphTraits::node_t node_t;
+  typedef typename GraphTraits::dump_args_t dump_args_t;
+
   virtual ~cluster () {}
 
-  virtual void add_node (dnode *node) = 0;
+  virtual void add_node (node_t *node) = 0;
 
   /* Recursively dump the cluster, all nodes, and child clusters.  */
-  virtual void dump_dot (graphviz_out *gv) const = 0;
+  virtual void dump_dot (graphviz_out *gv, const dump_args_t &) const = 0;
 };
 
-#if 0
 ////////////////////////////////////////////////////////////////////////////
 
+/* FIXME.  */
+
 template <typename GraphTraits>
-class base_node
+inline void
+digraph<GraphTraits>::dump_dot_to_pp (pretty_printer *pp,
+				      cluster_t *root_cluster,
+				      const dump_args_t &args) const
 {
- public:
-  typedef typename GraphTraits::edge_t edge_t;
-
-  void dump_dot (graphviz_out *gv) const;
-
- protected:
-  auto_vec<edge_t *> m_succs;
-};
+  graphviz_out gv (pp);
+
+  pp_string (pp, "digraph \"");
+  pp_string (pp, "FIXME: base");
+  pp_string (pp, "\" {\n");
+
+  gv.indent ();
+
+  pp_string (pp, "overlap=false;\n");
+  pp_string (pp, "compound=true;\n");
+
+  // TODO: maybe (optionally) sub-subdivide by TU, for LTO
+
+  /* TODO: see also:
+     https://gcc-python-plugin.readthedocs.io/en/latest/_images/sample-supergraph.png
+  */
+
+  /* If using clustering, emit all nodes via clusters.  */
+  if (root_cluster)
+    {
+      int i;
+      node_t *n;
+      FOR_EACH_VEC_ELT (m_nodes, i, n)
+	root_cluster->add_node (n);
+      root_cluster->dump_dot (&gv, args);
+    }
+  else
+    {
+      /* Otherwise, display all nodes at top level.  */
+      int i;
+      node_t *n;
+      FOR_EACH_VEC_ELT (m_nodes, i, n)
+	n->dump_dot (&gv, args);
+    }
+
+  /* Edges.  */
+  int i;
+  edge_t *e;
+  FOR_EACH_VEC_ELT (m_edges, i, e)
+    e->dump_dot (&gv, args);
+
+  /* Terminate "digraph" */
+  gv.outdent ();
+  pp_string (pp, "}");
+  pp_newline (pp);
+}
+
+/* FIXME.  */
 
 template <typename GraphTraits>
-class base_edge
+inline void
+digraph<GraphTraits>::dump_dot_to_file (FILE *fp,
+					cluster_t *root_cluster,
+					const dump_args_t &args) const
 {
- public:
-  typedef typename GraphTraits::node_t node_t;
+  pretty_printer pp;
+  // TODO:
+  pp_format_decoder (&pp) = default_tree_printer;
+  pp.buffer->stream = fp;
+  dump_dot_to_pp (&pp, root_cluster, args);
+  pp_flush (&pp);
+}
 
-  base_edge (node_t *src, node_t *dest)
-  : m_src (src), m_dest (dest) {}
-
-  void dump_dot (graphviz_out *gv) const;
-
- protected:
-  node_t *m_src;
-  node_t *m_dest;
-};
+/* FIXME.  */
 
 template <typename GraphTraits>
-class base_graph
+inline void
+digraph<GraphTraits>::dump_dot (const char *path,
+				cluster_t *root_cluster,
+				const dump_args_t &args) const
 {
- public:
-  typedef typename GraphTraits::node_t node_t;
-  typedef typename GraphTraits::edge_t edge_t;
+  FILE *fp = fopen (path, "w");
+  dump_dot_to_file (fp, root_cluster, args);
+  fclose (fp);
+}
 
-  void dump_dot (graphviz_out *gv) const;
+/* FIXME.  */
 
- protected:
-  auto_vec<node_t *> m_nodes;
-  auto_vec<edge_t *> m_edge;
-};
-
-////////////////////////////////////////////////////////////////////////////
-
-/* Curiously-recurring template pattern, for node/edge/graph.  */
-
-struct test_node;
-struct test_edge;
-struct test_graph;
-
-struct test_traits
-{
-  typedef test_node node_t;
-  typedef test_edge edge_t;
-  typedef test_graph graph_t;
-};
-
-struct test_node : public base_node<test_traits>
+template <typename GraphTraits>
+inline void
+digraph<GraphTraits>::add_node (node_t *node)
 {
-};
+  m_nodes.safe_push (node);
+}
 
-struct test_edge : public base_edge<test_traits>
-{
-};
+/* FIXME.  */
 
-struct test_graph : public base_graph<test_traits>
+template <typename GraphTraits>
+inline void
+digraph<GraphTraits>::add_edge (edge_t *edge)
 {
-};
-#endif
+  m_edges.safe_push (edge);
+}
 
 #endif /* GCC_ANALYZER_DIGRAPH_H */
diff --git a/gcc/analyzer/graphviz.cc b/gcc/analyzer/graphviz.cc
index 6121ca4..c878d7b 100644
--- a/gcc/analyzer/graphviz.cc
+++ b/gcc/analyzer/graphviz.cc
@@ -27,7 +27,7 @@
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
 
-#include "graphviz.h"
+#include "analyzer/graphviz.h"
 
 graphviz_out::graphviz_out (pretty_printer *pp)
 : m_pp (pp),
diff --git a/gcc/analyzer/impl-2.cc b/gcc/analyzer/impl-2.cc
index 413ed6e..c6656ee 100644
--- a/gcc/analyzer/impl-2.cc
+++ b/gcc/analyzer/impl-2.cc
@@ -33,14 +33,14 @@
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "analyzer-logging.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/analyzer-logging.h"
 #include "stringpool.h"
 #include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "pending-diagnostic.h"
+#include "analyzer/tristate.h"
+#include "analyzer/pending-diagnostic.h"
 #include "selftest.h"
 
 ////////////////////////////////////////////////////////////////////////////
@@ -1076,7 +1076,7 @@ public:
   auto_vec <link> m_links; // FIXME: copy-ctor etc
 };
 
-#include "path-state.h" // FIXME
+#include "analyzer/path-state.h" // FIXME
 
 class candidate_diagnostic
 {
@@ -3759,7 +3759,8 @@ run_one_checker (const supergraph &sg, const state_machine &sm, logger *logger)
       engine_annotator a (e);
       char *filename
 	= concat (dump_base_name, ".", sm.get_name (), ".1.dot", NULL);
-      sg.dump_dot (filename, (enum supergraph_dot_flags)0, &a);
+      supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
+      sg.dump_dot (filename, args);
       free (filename);
     }
 
@@ -3768,7 +3769,8 @@ run_one_checker (const supergraph &sg, const state_machine &sm, logger *logger)
       engine_annotator_2 a (e);
       char *filename
 	= concat (dump_base_name, ".", sm.get_name (), ".2.dot", NULL);
-      sg.dump_dot (filename, (enum supergraph_dot_flags)0, &a);
+      supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
+      sg.dump_dot (filename, args);
       free (filename);
     }
 
@@ -3818,7 +3820,8 @@ run_checkers_impl_2 ()
     if (1)
       {
 	char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
-	sg.dump_dot (filename, (enum supergraph_dot_flags)0);
+	supergraph::dump_args_t args ((enum supergraph_dot_flags)0, NULL);
+	sg.dump_dot (filename, args);
 	free (filename);
       }
 
diff --git a/gcc/analyzer/impl-3.cc b/gcc/analyzer/impl-3.cc
index c16b6ef..fbd7ad5 100644
--- a/gcc/analyzer/impl-3.cc
+++ b/gcc/analyzer/impl-3.cc
@@ -26,23 +26,22 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "analyzer-logging.h"
 #include "stringpool.h"
-#include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "pending-diagnostic.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/analyzer-logging.h"
+#include "analyzer/tristate.h"
+#include "analyzer/pending-diagnostic.h"
+#include "analyzer/path-state.h"
 #include "selftest.h"
-#include "path-state.h"
 
 using namespace psn;
 
@@ -1591,7 +1590,8 @@ run_checkers_impl_3 ()
     if (1)
       {
 	char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
-	sg.dump_dot (filename, (enum supergraph_dot_flags)0);
+	supergraph::dump_args_t args ((enum supergraph_dot_flags)0, NULL);
+	sg.dump_dot (filename, args);
 	free (filename);
       }
 
diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index 2e9ec03..b6e4454 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -26,33 +26,32 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "analyzer-logging.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/analyzer-logging.h"
 #include "stringpool.h"
 #include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "selftest.h"
-#include "digraph.h"
-#include "path-state.h"
+#include "analyzer/tristate.h"
+#include "analyzer/digraph.h"
+#include "analyzer/path-state.h"
 #include "tree-ssa-operands.h"
 #include "tree-vrp.h"
 #include "gimple-ssa.h"
 #include "tree-ssanames.h"
 #include "tree-phinodes.h"
 #include "ssa-iterators.h"
-#include "region-model.h"
+#include "analyzer/region-model.h"
 #include "tree-diagnostic.h"
-#include "constraint-manager.h"
-#include "pending-diagnostic.h"
+#include "analyzer/constraint-manager.h"
+#include "analyzer/pending-diagnostic.h"
 #include "fibonacci_heap.h"
 #include "params.h"
 
@@ -111,6 +110,7 @@ namespace impl_4 {
 class exploded_graph;
 class exploded_node;
 class exploded_edge;
+class exploded_cluster;
 class exploded_path;
 class checker4_path;
 class stmt_finder;
@@ -784,12 +784,23 @@ struct point_and_state
   hashval_t m_hash;
 };
 
+/* FIXME.  */
+
+struct eg_traits
+{
+  typedef exploded_node node_t;
+  typedef exploded_edge edge_t;
+  typedef exploded_graph graph_t;
+  struct dump_args_t {};
+  typedef exploded_cluster cluster_t;
+};
+
 /* An exploded_node is a unique, immutable <point, state> pair within the
    exploded_graph.
    Each exploded_node has a unique index within the graph
    (for ease of debugging).  */
 
-class exploded_node : public dnode
+class exploded_node : public dnode<eg_traits>
 {
  public:
   exploded_node (point_and_state ps,
@@ -801,7 +812,8 @@ class exploded_node : public dnode
 
   hashval_t hash () const { return m_ps.hash (); }
 
-  void dump_dot (graphviz_out *gv) const FINAL OVERRIDE;
+  void dump_dot (graphviz_out *gv, const dump_args_t &args)
+    const FINAL OVERRIDE;
   void dump_dot_id (pretty_printer *pp) const;
 
   void dump_to_pp (pretty_printer *pp) const;
@@ -848,23 +860,20 @@ public: // FIXME
 
   /* The index of this exploded_node.  */
   const int m_index;
-
-  auto_vec<exploded_edge *> m_succs;
 };
 
 /* An edge within the exploded graph.
    Some exploded_edges have an underlying superedge; others don't.  */
 
-class exploded_edge : public dedge
+class exploded_edge : public dedge<eg_traits>
 {
  public:
   exploded_edge (exploded_node *src, exploded_node *dest,
 		 const superedge *sedge);
-  void dump_dot (graphviz_out *gv) const FINAL OVERRIDE;
+  void dump_dot (graphviz_out *gv, const dump_args_t &args)
+    const FINAL OVERRIDE;
 
   //private:
-  exploded_node *const m_src;
-  exploded_node *const m_dest;
   const superedge *const m_sedge;
 };
 
@@ -1116,7 +1125,7 @@ private:
    It also has a worklist of nodes that are waiting for their successors
    to be added to the graph.  */
 
-class exploded_graph : public digraph, public log_user
+class exploded_graph : public digraph<eg_traits>, public log_user
 {
 public:
   exploded_graph (const supergraph &sg, logger *logger,
@@ -3296,7 +3305,7 @@ program_state::validate (const extrinsic_state &ext_state) const
 /* FIXME.  */
 
 void
-exploded_node::dump_dot (graphviz_out *gv) const
+exploded_node::dump_dot (graphviz_out *gv, const dump_args_t &) const
 {
   pretty_printer *pp = gv->m_pp;
 
@@ -3771,14 +3780,14 @@ program_state::on_edge (exploded_graph &eg,
 
 exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
 			      const superedge *sedge)
-: m_src (src), m_dest (dest), m_sedge (sedge)
+: dedge (src, dest), m_sedge (sedge)
 {
 }
 
 /* FIXME.  */
 
 void
-exploded_edge::dump_dot (graphviz_out *gv) const
+exploded_edge::dump_dot (graphviz_out *gv, const dump_args_t &) const
 {
   pretty_printer *pp = gv->m_pp;
 
@@ -5186,7 +5195,7 @@ exploded_graph::process_worklist ()
 
       /* Avoid exponential explosions of nodes by attempting to merge
 	 nodes that are at the same program point and which have
-	 sufficiently similar state..  */
+	 sufficiently similar state.  */
       if (flag_analyzer_state_merge && node != m_origin)
 	if (exploded_node *node_2 = m_worklist.peek_next ())
 	  {
@@ -5221,18 +5230,19 @@ exploded_graph::process_worklist ()
 
 		    if (merged_state == state)
 		      {
-			/* Then merge node_2 into node.  */
+			/* Then merge node_2 into node by adding an edge.  */
 			add_edge (node_2, node, NULL);
 
-			/* Consume node_2.  */
+			/* Remove node_2 from the worklist.  */
 			m_worklist.take_next ();
 
-			/* Continue processing node.  */
+			/* Continue processing "node" below.  */
 		      }
 		    else if (merged_state == state_2)
 		      {
-			/* Then merge node into node_2, and continue
-			   processing node_2 (it's still in the worklist).  */
+			/* Then merge node into node_2, and leave node_2
+			   in the worklist, to be processed on the next
+			   iteration.  */
 			add_edge (node, node_2, NULL);
 			continue;
 		      }
@@ -5241,28 +5251,32 @@ exploded_graph::process_worklist ()
 			/* We have a merged state that differs from
 			   both state and state_2.  */
 
-			/* Consume node_2.  */
+			/* Remove node_2 from the worklist.  */
 			m_worklist.take_next ();
 
-			/* Create an exploded node for the merged states,
-			   adding to the worklist.  */
+			/* Create (or get) an exploded node for the merged
+			   states, adding to the worklist.  */
 			exploded_node *merged_enode
-			  = get_or_create_node (node->get_point (), merged_state);
+			  = get_or_create_node (node->get_point (),
+						merged_state);
 
 			log ("merged EN: %i and EN: %i into EN: %i",
-			     node->m_index, node_2->m_index, merged_enode->m_index);
+			     node->m_index, node_2->m_index,
+			     merged_enode->m_index);
 
-			/* Add edges from the unmerged nodes to the merged node.  */
+			/* Add edges from the unmerged nodes to the
+			   merged node.  */
 			add_edge (node, merged_enode, NULL);
 			add_edge (node_2, merged_enode, NULL);
 
-			/* Don't process the two merged nodes.  */
+			/* "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.  */
 			continue;
 		      }
 		  }
 
-		// TODO: are the states similar enough?
-		// TODO: attempt the merger
 		/* TODO: should we attempt more than two nodes,
 		   or just do pairs of nodes?  (and hope that we get
 		   a cascade of mergers).  */
@@ -5515,11 +5529,10 @@ exploded_graph::dump_states_for_supernode (FILE *out,
 {
   fprintf (out, "PK_AFTER_SUPERNODE nodes for SN: %i\n", snode->m_index);
   int i;
-  dnode *node;
+  exploded_node *enode;
   int state_idx = 0;
-  FOR_EACH_VEC_ELT (m_nodes, i, node)
+  FOR_EACH_VEC_ELT (m_nodes, i, enode)
     {
-      exploded_node *enode = (exploded_node *)node;
       const supernode *iter_snode = enode->get_supernode ();
       if (enode->get_point ().m_kind == PK_AFTER_SUPERNODE
 	  && iter_snode == snode)
@@ -5844,29 +5857,23 @@ private:
 
 ////////////////////////////////////////////////////////////////////////////
 
+// FIXME:
 /* Subclass of cluster which casts the dnode instances to exploded_node.  */
 
-class en_cluster : public cluster
+class exploded_cluster : public cluster<eg_traits>
 {
-public:
-  void add_node (dnode *node) FINAL OVERRIDE
-  {
-    exploded_node *en = static_cast <exploded_node *> (node);
-    add_exploded_node (en);
-  }
-  virtual void add_exploded_node (exploded_node *en) = 0;
 };
 
 /* Cluster containing all exploded_node instances for one supernode.  */
 
-class supernode_cluster : public en_cluster
+class supernode_cluster : public exploded_cluster
 {
 public:
   supernode_cluster (const supernode *supernode) : m_supernode (supernode) {}
 
   // TODO: dtor?
 
-  void dump_dot (graphviz_out *gv) const FINAL OVERRIDE
+  void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
   {
     gv->println ("subgraph \"cluster_supernode_%p\" {",
 		 (const void *)this);
@@ -5877,14 +5884,14 @@ public:
     int i;
     exploded_node *enode;
     FOR_EACH_VEC_ELT (m_enodes, i, enode)
-      enode->dump_dot (gv);
+      enode->dump_dot (gv, args);
 
     /* Terminate subgraph.  */
     gv->outdent ();
     gv->println ("}");
   }
 
-  void add_exploded_node (exploded_node *en) FINAL OVERRIDE
+  void add_node (exploded_node *en) FINAL OVERRIDE
   {
     m_enodes.safe_push (en);
   }
@@ -5897,7 +5904,7 @@ private:
 /* Cluster containing all supernode_cluster instances for one
    (function, call_string) pair.  */
 
-class function_call_string_cluster : public en_cluster
+class function_call_string_cluster : public exploded_cluster
 {
 public:
   function_call_string_cluster (function *fun, call_string cs)
@@ -5911,7 +5918,7 @@ public:
       delete (*iter).second;
   }
 
-  void dump_dot (graphviz_out *gv) const FINAL OVERRIDE
+  void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
   {
     const char *funcname = function_name (m_fun);
 
@@ -5923,25 +5930,25 @@ public:
     for (map_t::iterator iter = m_map.begin ();
 	 iter != m_map.end ();
 	 ++iter)
-      (*iter).second->dump_dot (gv);
+      (*iter).second->dump_dot (gv, args);
 
     /* Terminate subgraph.  */
     gv->outdent ();
     gv->println ("}");
   }
 
-  void add_exploded_node (exploded_node *en) FINAL OVERRIDE
+  void add_node (exploded_node *en) FINAL OVERRIDE
   {
     const supernode *supernode = en->get_supernode ();
     gcc_assert (supernode);
     supernode_cluster **slot = m_map.get (supernode);
     if (slot)
-      (*slot)->add_exploded_node (en);
+      (*slot)->add_node (en);
     else
       {
 	supernode_cluster *child = new supernode_cluster (supernode);
 	m_map.put (supernode, child);
-	child->add_exploded_node (en);
+	child->add_node (en);
       }
   }
 
@@ -6020,7 +6027,7 @@ namespace impl_4 {
 /* Top-level cluster for printing exploded graphs, handling the functionless
    nodes, and grouping the remaining nodes by callstring.  */
 
-class root_cluster : public en_cluster
+class root_cluster : public exploded_cluster
 {
 public:
   ~root_cluster ()
@@ -6031,20 +6038,20 @@ public:
       delete (*iter).second;
   }
 
-  void dump_dot (graphviz_out *gv) const FINAL OVERRIDE
+  void dump_dot (graphviz_out *gv, const dump_args_t &args) const FINAL OVERRIDE
   {
     int i;
     exploded_node *enode;
     FOR_EACH_VEC_ELT (m_functionless_enodes, i, enode)
-      enode->dump_dot (gv);
+      enode->dump_dot (gv, args);
 
     for (map_t::iterator iter = m_map.begin ();
 	 iter != m_map.end ();
 	 ++iter)
-      (*iter).second->dump_dot (gv);
+      (*iter).second->dump_dot (gv, args);
   }
 
-  void add_exploded_node (exploded_node *en) FINAL OVERRIDE
+  void add_node (exploded_node *en) FINAL OVERRIDE
   {
     function *fun = en->get_function ();
     if (!fun)
@@ -6057,13 +6064,13 @@ public:
     function_call_string key (fun, cs);
     function_call_string_cluster **slot = m_map.get (key);
     if (slot)
-      (*slot)->add_exploded_node (en);
+      (*slot)->add_node (en);
     else
       {
 	function_call_string_cluster *child
 	  = new function_call_string_cluster (fun, cs);
 	m_map.put (key, child);
-	child->add_exploded_node (en);
+	child->add_node (en);
       }
   }
 
@@ -6676,10 +6683,9 @@ exploded_graph::dump_exploded_nodes () const
     {
       gcc_rich_location richloc (UNKNOWN_LOCATION);
       unsigned i;
-      dnode *node;
-      FOR_EACH_VEC_ELT (m_nodes, i, node)
+      exploded_node *enode;
+      FOR_EACH_VEC_ELT (m_nodes, i, enode)
 	{
-	  exploded_node *enode = (exploded_node *)node;
 	  //const supernode *iter_snode = enode->get_supernode ();
 	  if (const gimple *stmt = enode->get_stmt ())
 	    {
@@ -6708,11 +6714,10 @@ exploded_graph::dump_exploded_nodes () const
      IDs.  */
 
   unsigned i;
-  dnode *node;
+  exploded_node *enode;
   hash_set<const gimple *> seen;
-  FOR_EACH_VEC_ELT (m_nodes, i, node)
+  FOR_EACH_VEC_ELT (m_nodes, i, enode)
     {
-      exploded_node *enode = (exploded_node *)node;
       if (enode->get_point ().m_kind != PK_BEFORE_STMT)
 	continue;
 
@@ -6726,10 +6731,9 @@ exploded_graph::dump_exploded_nodes () const
 	      /* This is O(N^2).  */
 	      unsigned j;
 	      auto_vec<exploded_node *> enodes;
-	      dnode *other_node;
-	      FOR_EACH_VEC_ELT (m_nodes, j, other_node)
+	      exploded_node *other_enode;
+	      FOR_EACH_VEC_ELT (m_nodes, j, other_enode)
 		{
-		  exploded_node *other_enode = (exploded_node *)other_node;
 		  if (other_enode->get_point ().m_kind != PK_BEFORE_STMT)
 		    continue;
 		  if (other_enode->get_stmt () == stmt)
@@ -6789,7 +6793,8 @@ impl_run_checkers (logger *logger)
       auto_client_timevar tv ("writing .supergraph.dot");
       state_purge_annotator a (purge_map);
       char *filename = concat (dump_base_name, ".supergraph.dot", NULL);
-      sg.dump_dot (filename, (enum supergraph_dot_flags)0, &a);
+      supergraph::dump_args_t args ((enum supergraph_dot_flags)0, &a);
+      sg.dump_dot (filename, args);
       free (filename);
     }
 
@@ -6835,8 +6840,9 @@ impl_run_checkers (logger *logger)
       auto_client_timevar tv ("writing .eg.dot");
       char *filename
 	= concat (dump_base_name, ".eg.dot", NULL);
+      exploded_graph::dump_args_t args;
       root_cluster c;
-      eg.dump_dot (filename, &c);
+      eg.dump_dot (filename, &c, args);
       free (filename);
     }
 
diff --git a/gcc/analyzer/path-state.cc b/gcc/analyzer/path-state.cc
index 34a91d9..d8ce6a6 100644
--- a/gcc/analyzer/path-state.cc
+++ b/gcc/analyzer/path-state.cc
@@ -33,13 +33,13 @@
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "analyzer-logging.h"
+#include "analyzer/analyzer-logging.h"
 #include "stringpool.h"
 #include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "path-state.h"
-#include "supergraph.h"
+#include "analyzer/tristate.h"
+#include "analyzer/path-state.h"
+#include "analyzer/supergraph.h"
 
 using namespace psn;
 
diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc
index c989609..bf2efc5 100644
--- a/gcc/analyzer/pending-diagnostic.cc
+++ b/gcc/analyzer/pending-diagnostic.cc
@@ -26,14 +26,14 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/pending-diagnostic.h"
 
 label_text
 pending_diagnostic::formatted_print (const char *fmt, ...)
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
index 672340a..a63b824 100644
--- a/gcc/analyzer/pending-diagnostic.h
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
 #define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
 
-#include "sm.h"
+#include "analyzer/sm.h"
 #include "diagnostic-metadata.h"
 
 /* FIXME.  */
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 2ff23a2..8501c32 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -33,18 +33,18 @@
 #include "gcc-rich-location.h"
 #include "tree-dfa.h"
 #include <string>
-#include "analyzer-logging.h"
+#include "analyzer/analyzer-logging.h"
 #include "stringpool.h"
 #include "selftest.h"
 #include "fold-const.h"
-#include "tristate.h"
-#include "path-state.h"
-#include "supergraph.h"
-#include "region-model.h"
+#include "analyzer/tristate.h"
+#include "analyzer/path-state.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/region-model.h"
 #include "tree-diagnostic.h"
 #include "diagnostic-color.h"
-#include "constraint-manager.h"
-#include "pending-diagnostic.h"
+#include "analyzer/constraint-manager.h"
+#include "analyzer/pending-diagnostic.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index a68dfa7..4ed7f01 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_REGION_MODEL_H
 #define GCC_ANALYZER_REGION_MODEL_H
 
-#include "sm.h"
+#include "analyzer/sm.h"
 
 /* Implemention of the region-based ternary model described in:
      "A Memory Model for Static Analysis of C Programs"
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index 3579f88..7d3b747 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -27,15 +27,15 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index d238a5a..5d3c333 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -27,15 +27,15 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm-pattern-test.cc b/gcc/analyzer/sm-pattern-test.cc
index 6fbb8c5..5e4c8a6 100644
--- a/gcc/analyzer/sm-pattern-test.cc
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -26,15 +26,15 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm-sensitive.cc b/gcc/analyzer/sm-sensitive.cc
index 3a2a582..c998da5 100644
--- a/gcc/analyzer/sm-sensitive.cc
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -26,15 +26,15 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm-taint.cc b/gcc/analyzer/sm-taint.cc
index 4881702..c2deb7f 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -26,15 +26,15 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
-#include "graphviz.h"
+#include "analyzer/analyzer.h"
+#include "analyzer/graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
-#include "pending-diagnostic.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
+#include "analyzer/pending-diagnostic.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm.cc b/gcc/analyzer/sm.cc
index 8c4bb06..539986a 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -26,14 +26,14 @@
 #include "gimple-iterator.h"
 #include "gimple-pretty-print.h"
 #include "tree-pretty-print.h"
-#include "analyzer.h"
+#include "analyzer/analyzer.h"
 #include "graphviz.h"
 #include "cgraph.h"
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "sm.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/sm.h"
 
 static const bool DEBUG = false;
 //static const bool DEBUG = true;
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index a6d0122..cd2e4a3 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -21,7 +21,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_SM_H
 #define GCC_ANALYZER_SM_H
 
-#include "analyzer-logging.h"
+#include "analyzer/analyzer-logging.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc
index 2c2535d..2d23eb3 100644
--- a/gcc/analyzer/supergraph.cc
+++ b/gcc/analyzer/supergraph.cc
@@ -51,8 +51,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-path.h"
 #include "gcc-rich-location.h"
 #include <string>
-#include "supergraph.h"
-#include "analyzer-logging.h"
+#include "analyzer/supergraph.h"
+#include "analyzer/analyzer-logging.h"
 #include "tree-diagnostic.h"
 #include "tree-dfa.h"
 
@@ -232,8 +232,7 @@ supergraph::supergraph (logger *logger)
 
 void
 supergraph::dump_dot_to_pp (pretty_printer *pp,
-			    enum supergraph_dot_flags flags,
-			    const dot_annotator *a) const
+			    const dump_args_t &dump_args) const
 {
   graphviz_out gv (pp);
 
@@ -274,7 +273,7 @@ supergraph::dump_dot_to_pp (pretty_printer *pp,
 	basic_block bb;
 	FOR_ALL_BB_FN (bb, fun)
 	  {
-	    if (flags & SUPERGRAPH_DOT_SHOW_BBS)
+	    if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
 	      {
 		gv.println ("subgraph \"cluster_%s_bb_%i\" {",
 			    funcname, bb->index);
@@ -291,9 +290,9 @@ supergraph::dump_dot_to_pp (pretty_printer *pp,
 	    supernode *n;
 	    FOR_EACH_VEC_ELT (m_nodes, i, n)
 	      if (n->m_fun == fun && n->m_bb == bb)
-		n->dump_dot (&gv, flags, a);
+		n->dump_dot (&gv, dump_args);
 
-	    if (flags & SUPERGRAPH_DOT_SHOW_BBS)
+	    if (dump_args.m_flags & SUPERGRAPH_DOT_SHOW_BBS)
 	      {
 		/* Terminate per-bb "subgraph" */
 		gv.outdent ();
@@ -321,7 +320,7 @@ supergraph::dump_dot_to_pp (pretty_printer *pp,
   int i;
   superedge *e;
   FOR_EACH_VEC_ELT (m_edges, i, e)
-    e->dump_dot (&gv, flags);
+    e->dump_dot (&gv, dump_args);
 
   /* Terminate "digraph" */
   gv.outdent ();
@@ -329,8 +328,7 @@ supergraph::dump_dot_to_pp (pretty_printer *pp,
 }
 
 void
-supergraph::dump_dot_to_file (FILE *fp, enum supergraph_dot_flags flags,
-			      const dot_annotator *a) const
+supergraph::dump_dot_to_file (FILE *fp, const dump_args_t &dump_args) const
 {
   pretty_printer *pp = global_dc->printer->clone ();
   pp_show_color (pp) = 0;
@@ -339,17 +337,16 @@ supergraph::dump_dot_to_file (FILE *fp, enum supergraph_dot_flags flags,
   pp_format_decoder (pp) = default_tree_printer;
 
   pp->buffer->stream = fp;
-  dump_dot_to_pp (pp, flags, a);
+  dump_dot_to_pp (pp, dump_args);
   pp_flush (pp);
   delete pp;
 }
 
 void
-supergraph::dump_dot (const char *path, enum supergraph_dot_flags flags,
-		      const dot_annotator *a) const
+supergraph::dump_dot (const char *path, const dump_args_t &dump_args) const
 {
   FILE *fp = fopen (path, "w");
-  dump_dot_to_file (fp, flags, a);
+  dump_dot_to_file (fp, dump_args);
   fclose (fp);
 }
 
@@ -412,9 +409,7 @@ supernode::to_str () const
 }
 
 void
-supernode::dump_dot (graphviz_out *gv,
-		     enum supergraph_dot_flags flags ATTRIBUTE_UNUSED,
-		     const dot_annotator *a) const
+supernode::dump_dot (graphviz_out *gv, const dump_args_t &args) const
 {
   gv->println ("subgraph cluster_node_%i {",
 	       m_index);
@@ -427,8 +422,8 @@ supernode::dump_dot (graphviz_out *gv,
 
   pretty_printer *pp = gv->m_pp;
 
-  if (a)
-    a->add_node_annotations (pp, *this);
+  if (args.m_node_annotator)
+    args.m_node_annotator->add_node_annotations (pp, *this);
 
   gv->write_indent ();
   dump_dot_id (pp);
@@ -442,8 +437,8 @@ supernode::dump_dot (graphviz_out *gv,
     {
       pp_string (pp, "returning call: ");
       pp_gimple_stmt_1 (pp, m_returning_call, 0, (dump_flags_t)0);
-      if (a)
-	a->add_stmt_annotations (pp, m_returning_call);
+      if (args.m_node_annotator)
+	args.m_node_annotator->add_stmt_annotations (pp, m_returning_call);
       pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
       pp_newline (pp);
     }
@@ -466,8 +461,8 @@ supernode::dump_dot (graphviz_out *gv,
     {
       gimple *stmt = gsi_stmt (gpi);
       pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
-      if (a)
-	a->add_stmt_annotations (pp, stmt);
+      if (args.m_node_annotator)
+	args.m_node_annotator->add_stmt_annotations (pp, stmt);
       pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
       pp_newline (pp);
     }
@@ -478,8 +473,8 @@ supernode::dump_dot (graphviz_out *gv,
   FOR_EACH_VEC_ELT (m_stmts, i, stmt)
     {
       pp_gimple_stmt_1 (pp, stmt, 0, (dump_flags_t)0);
-      if (a)
-	a->add_stmt_annotations (pp, stmt);
+      if (args.m_node_annotator)
+	args.m_node_annotator->add_stmt_annotations (pp, stmt);
       pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/true);
       pp_newline (pp);
     }
@@ -601,8 +596,7 @@ supernode::get_stmt_index (const gimple *stmt) const
 }
 
 void
-superedge::dump_dot (graphviz_out *gv,
-		     enum supergraph_dot_flags flags ATTRIBUTE_UNUSED) const
+superedge::dump_dot (graphviz_out *gv, const dump_args_t &) const
 {
   const char *style = "\"solid,bold\"";
   const char *color = "black";
diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h
index 6caf015..dfd8465 100644
--- a/gcc/analyzer/supergraph.h
+++ b/gcc/analyzer/supergraph.h
@@ -21,6 +21,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_ANALYZER_SUPERGRAPH_H
 #define GCC_ANALYZER_SUPERGRAPH_H
 
+#include "analyzer/digraph.h"
+
 /* Forward decls, using indentation to show inheritance.  */
 
 class supergraph;
@@ -31,6 +33,7 @@ class superedge;
     class return_superedge;
   class cfg_superedge;
     class switch_cfg_superedge;
+class supercluster;
 class dot_annotator;
 
 class logger;
@@ -71,10 +74,28 @@ enum supergraph_dot_flags
   SUPERGRAPH_DOT_SHOW_BBS = (1 << 0)
 };
 
+struct supergraph_traits
+{
+  typedef supernode node_t;
+  typedef superedge edge_t;
+  typedef supergraph graph_t;
+  struct dump_args_t
+  {
+    dump_args_t (enum supergraph_dot_flags flags,
+		 const dot_annotator *node_annotator)
+    : m_flags (flags),
+      m_node_annotator (node_annotator)
+    {}
+
+    enum supergraph_dot_flags m_flags;
+    const dot_annotator *m_node_annotator;
+  };
+  typedef supercluster cluster_t;
+};
 
 /* FIXME.  */
 
-class supergraph
+class supergraph : public digraph<supergraph_traits>
 {
 public:
   supergraph (logger *logger);
@@ -126,12 +147,9 @@ public:
 	    (const_cast <gimple *> (stmt)));
   }
 
-  void dump_dot_to_pp (pretty_printer *pp, enum supergraph_dot_flags flags,
-		       const dot_annotator *a = NULL) const;
-  void dump_dot_to_file (FILE *fp, enum supergraph_dot_flags flags,
-			 const dot_annotator *a = NULL) const;
-  void dump_dot (const char *path, enum supergraph_dot_flags flags,
-		 const dot_annotator *a = NULL) const;
+  void dump_dot_to_pp (pretty_printer *pp, const dump_args_t &) const;
+  void dump_dot_to_file (FILE *fp, const dump_args_t &) const;
+  void dump_dot (const char *path, const dump_args_t &) const;
 
   int num_nodes () const { return m_nodes.length (); }
   int num_edges () const { return m_edges.length (); }
@@ -182,7 +200,7 @@ private:
 
 /* A node within a supergraph.  */
 
-class supernode
+class supernode : public dnode<supergraph_traits>
 {
  public:
   supernode (function *fun, basic_block bb, gcall *returning_call,
@@ -203,8 +221,7 @@ class supernode
 
   std::string to_str () const;
 
-  void dump_dot (graphviz_out *gv, enum supergraph_dot_flags flags,
-		 const dot_annotator *a) const;
+  void dump_dot (graphviz_out *gv, const dump_args_t &args) const OVERRIDE;
   void dump_dot_id (pretty_printer *pp) const;
 
   location_t get_start_location () const;
@@ -248,19 +265,17 @@ class supernode
   gcall * const m_returning_call; // for handling the result of a returned call
   gimple_seq m_phi_nodes; // ptr to that of the underlying BB, for the first supernode for the BB
   auto_vec<gimple *> m_stmts;
-  auto_vec<superedge *> m_preds;
-  auto_vec<superedge *> m_succs;
   const int m_index; /* unique within the supergraph as a whole.  */
 };
 
 /* An abstract base class encapsulating an edge within a supergraph.  */
 
-class superedge
+class superedge : public dedge<supergraph_traits>
 {
  public:
   virtual ~superedge () {}
 
-  void dump_dot (graphviz_out *gv, enum supergraph_dot_flags flags) const;
+  void dump_dot (graphviz_out *gv, const dump_args_t &args) const;
 
   virtual void dump_label_to_pp (pretty_printer *pp,
 				 bool user_facing) const = 0;
@@ -283,12 +298,11 @@ class superedge
 
  protected:
   superedge (supernode *src, supernode *dest, enum edge_kind kind)
-    : m_src (src), m_dest (dest), m_kind (kind)
+  : dedge (src, dest),
+    m_kind (kind)
   {}
 
  public:
-  supernode *const m_src;
-  supernode *const m_dest;
   const enum edge_kind m_kind;
 };
 
diff --git a/gcc/analyzer/tristate.cc b/gcc/analyzer/tristate.cc
index 7e16418..ebc2555 100644
--- a/gcc/analyzer/tristate.cc
+++ b/gcc/analyzer/tristate.cc
@@ -2,7 +2,7 @@
 #include "gcc-plugin.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tristate.h"
+#include "analyzer/tristate.h"
 #include "selftest.h"
 
 const char *
-- 
1.8.5.3

