From 22015ffff2ea661eaaa316b33122fc87dd277bfd Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 24 Jun 2019 10:56:40 -0400
Subject: [PATCH 036/108] FIXME: move pending_diagnostic from sm.h/cc to its
 own .h/.cc

---
 gcc/analyzer/Make-lang.in          |   1 +
 gcc/analyzer/impl-2.cc             |   1 +
 gcc/analyzer/impl-3.cc             |   1 +
 gcc/analyzer/impl-4.cc             |   1 +
 gcc/analyzer/pending-diagnostic.cc |  62 ++++++++
 gcc/analyzer/pending-diagnostic.h  | 281 +++++++++++++++++++++++++++++++++++++
 gcc/analyzer/region-model.cc       |   2 +-
 gcc/analyzer/sm-file.cc            |   1 +
 gcc/analyzer/sm-malloc.cc          |   1 +
 gcc/analyzer/sm-pattern-test.cc    |   1 +
 gcc/analyzer/sm-sensitive.cc       |   1 +
 gcc/analyzer/sm-taint.cc           |   1 +
 gcc/analyzer/sm.cc                 |  25 ----
 gcc/analyzer/sm.h                  | 267 +----------------------------------
 14 files changed, 354 insertions(+), 292 deletions(-)
 create mode 100644 gcc/analyzer/pending-diagnostic.cc
 create mode 100644 gcc/analyzer/pending-diagnostic.h

diff --git a/gcc/analyzer/Make-lang.in b/gcc/analyzer/Make-lang.in
index e1497c3..9f27ff76 100644
--- a/gcc/analyzer/Make-lang.in
+++ b/gcc/analyzer/Make-lang.in
@@ -64,6 +64,7 @@ ANALYZER_PLUGIN_SO_OBJS = \
 	analyzer/impl-3.o \
 	analyzer/impl-4.o \
 	analyzer/path-state.o \
+	analyzer/pending-diagnostic.o \
 	analyzer/region-model.o \
 	analyzer/sm.o \
 	analyzer/sm-file.o \
diff --git a/gcc/analyzer/impl-2.cc b/gcc/analyzer/impl-2.cc
index beb1b9d..a6aa3e5 100644
--- a/gcc/analyzer/impl-2.cc
+++ b/gcc/analyzer/impl-2.cc
@@ -40,6 +40,7 @@
 #include "selftest.h"
 #include "fold-const.h"
 #include "tristate.h"
+#include "pending-diagnostic.h"
 #include "selftest.h"
 
 ////////////////////////////////////////////////////////////////////////////
diff --git a/gcc/analyzer/impl-3.cc b/gcc/analyzer/impl-3.cc
index 1095b72..ef79051 100644
--- a/gcc/analyzer/impl-3.cc
+++ b/gcc/analyzer/impl-3.cc
@@ -40,6 +40,7 @@
 #include "selftest.h"
 #include "fold-const.h"
 #include "tristate.h"
+#include "pending-diagnostic.h"
 #include "selftest.h"
 #include "path-state.h"
 
diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index cd3daf9..43e7e08 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -52,6 +52,7 @@
 #include "region-model.h"
 #include "tree-diagnostic.h"
 #include "constraint-manager.h"
+#include "pending-diagnostic.h"
 
 /* Overview:
 
diff --git a/gcc/analyzer/pending-diagnostic.cc b/gcc/analyzer/pending-diagnostic.cc
new file mode 100644
index 0000000..c989609
--- /dev/null
+++ b/gcc/analyzer/pending-diagnostic.cc
@@ -0,0 +1,62 @@
+/* FIXME.  */
+#include "config.h"
+#include "gcc-plugin.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "toplev.h"
+#include "hash-table.h"
+#include "vec.h"
+#include "ggc.h"
+#include "basic-block.h"
+#include "tree-ssa-alias.h"
+#include "internal-fn.h"
+#include "gimple-fold.h"
+#include "tree-eh.h"
+#include "gimple-expr.h"
+#include "is-a.h"
+#include "gimple.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "context.h"
+#include "diagnostic.h"
+#include "bitmap.h"
+#include "gimple.h"
+#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 <string>
+#include "supergraph.h"
+#include "pending-diagnostic.h"
+
+label_text
+pending_diagnostic::formatted_print (const char *fmt, ...)
+{
+  pretty_printer *pp = global_dc->printer->clone ();
+
+  /* FIXME.  */
+  pp_show_color (pp) = false;
+
+  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;
+  pp_format (pp, &ti);
+  pp_output_formatted_text (pp);
+  va_end (ap);
+
+  label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
+  delete pp;
+  return result;
+}
diff --git a/gcc/analyzer/pending-diagnostic.h b/gcc/analyzer/pending-diagnostic.h
new file mode 100644
index 0000000..672340a
--- /dev/null
+++ b/gcc/analyzer/pending-diagnostic.h
@@ -0,0 +1,281 @@
+/* FIXME.
+   Copyright (C) 2019 Free Software Foundation, Inc.
+   Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_ANALYZER_PENDING_DIAGNOSTIC_H
+#define GCC_ANALYZER_PENDING_DIAGNOSTIC_H
+
+#include "sm.h"
+#include "diagnostic-metadata.h"
+
+/* FIXME.  */
+
+// TODO: maybe capture which sm and pending_diagnostic emitted the error?
+// FIXME: is this needed?
+
+class metadata : public diagnostic_metadata
+{
+ public:
+
+ private:
+};
+
+/* FIXME.  */
+
+class event_id_t
+{
+ public:
+  event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
+  event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
+
+  bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
+
+  int one_based () const
+  {
+    gcc_assert (known_p ());
+    return m_index + 1;
+  }
+
+ private:
+  static const int UNKNOWN_EVENT_IDX = -1;
+  int m_index; // zero-based
+};
+
+/* Various bundles of information used for generating more precise
+   messages for events within a diagnostic_path, for passing to the
+   various "describe_*" vfuncs of pending_diagnostic.  See those
+   for more information.  */
+
+namespace evdesc {
+
+/* For use by pending_diagnostic::describe_state_change.  */
+
+struct state_change
+{
+  state_change (tree expr,
+		state_machine::state_t old_state,
+		state_machine::state_t new_state,
+		event_id_t event_id)
+  : m_expr (expr), m_old_state (old_state),
+    m_new_state (new_state), m_event_id (event_id)
+  {}
+
+  tree m_expr;
+  state_machine::state_t m_old_state;
+  state_machine::state_t m_new_state;
+  event_id_t m_event_id;
+};
+
+/* For use by pending_diagnostic::describe_call_with_state.  */
+
+struct call_with_state
+{
+  call_with_state (tree caller_fndecl, tree callee_fndecl,
+		   tree expr, state_machine::state_t state)
+  : m_caller_fndecl (caller_fndecl),
+    m_callee_fndecl (callee_fndecl),
+    m_expr (expr),
+    m_state (state)
+  {
+  }
+
+  tree m_caller_fndecl;
+  tree m_callee_fndecl;
+  tree m_expr;
+  state_machine::state_t m_state;
+};
+
+/* For use by pending_diagnostic::describe_return_of_state.  */
+
+struct return_of_state
+{
+  return_of_state (tree caller_fndecl, tree callee_fndecl,
+		   state_machine::state_t state)
+  : m_caller_fndecl (caller_fndecl),
+    m_callee_fndecl (callee_fndecl),
+    m_state (state)
+  {
+  }
+
+  tree m_caller_fndecl;
+  tree m_callee_fndecl;
+  state_machine::state_t m_state;
+};
+
+/* For use by pending_diagnostic::describe_final_event.  */
+
+struct final_event
+{
+  final_event (tree expr, state_machine::state_t state)
+  : m_expr (expr), m_state (state)
+  {}
+
+  tree m_expr;
+  state_machine::state_t m_state;
+};
+
+} /* end of namespace evdesc */
+
+/* An abstract base class for capturing information about a diagnostic in
+   a form that is ready to emit at a later point (or be rejected).
+   Each kind of diagnostic will have a concrete subclass of
+   pending_diagnostic.
+
+   Normally, gcc diagnostics are emitted using va_list, which can't be
+   portably stored for later use, so we have to use an "emit" virtual
+   function.
+
+   This class also supports comparison, so that multiple pending_diagnostic
+   instances can be de-duplicated.
+
+   As well as emitting a diagnostic, the class has various "precision of
+   wording" virtual functions, for generating descriptions for events
+   within a diagnostic_path.  These are optional, but implementing these
+   allows for more precise wordings than the more generic
+   implementation.  */
+
+class pending_diagnostic
+{
+ public:
+  virtual ~pending_diagnostic () {}
+
+  /* Vfunc for emitting the diagnostic.  The rich_location will have been
+     populated with a diagnostic_path.  */
+  virtual void emit (rich_location *) = 0;
+
+  /* Hand-coded RTTI: get an ID for the subclass.  */
+  virtual const char *get_kind () const = 0;
+
+  /* Compare for equality with OTHER, which might be of a different
+     subclass.  */
+
+  bool equal_p (const pending_diagnostic &other)
+  {
+    /* Check for pointer equality on the IDs from get_kind.  */
+    if (get_kind () != other.get_kind ())
+      return false;
+    /* Call vfunc now we know they have the same ID: */
+    return subclass_equal_p (other);
+  }
+
+  /* A vfunc for testing for equality, where we've already
+     checked they have the same ID.  See pending_diagnostic_subclass
+     below for a convenience subclass for implementing this.  */
+  virtual bool subclass_equal_p (const pending_diagnostic &other) const = 0;
+
+  /* For greatest precision-of-wording, the various following "describe_*"
+     virtual functions give the pending diagnostic a way to describe events
+     in a diagnostic_path in terms that make sense for that diagnostic.
+
+     In each case, return a non-NULL label_text to give the event a custom
+     description; NULL otherwise (falling back on a more generic
+     description).  */
+
+  /* Precision-of-wording vfunc for describing a critical state change
+     within the diagnostic_path.
+
+     For example, a double-free diagnostic might use the descriptions:
+     - "first 'free' happens here"
+     - "second 'free' happens here"
+     for the pertinent events, whereas a use-after-free might use the
+     descriptions:
+     - "freed here"
+     - "use after free here"
+     Note how in both cases the first event is a "free": the best
+     description to use depends on the diagnostic.  */
+
+  virtual label_text describe_state_change (const evdesc::state_change &)
+  {
+    /* Default no-op implementation.  */
+    return label_text ();
+  }
+
+  /* Precision-of-wording vfunc for describing an interprocedural call
+     carrying critial state for the diagnostic, from caller to callee.
+
+     For example a double-free diagnostic might use:
+     - "passing freed pointer 'ptr' in call to 'deallocator' from 'test'"
+     to make it clearer how the unchecked value moves from caller
+     to callee.  */
+
+  virtual label_text describe_call_with_state (const evdesc::call_with_state &)
+  {
+    /* Default no-op implementation.  */
+    return label_text ();
+  }
+
+  /* Precision-of-wording vfunc for describing an interprocedural return
+     within the diagnostic_path that carries critial state for the
+     diagnostic, from callee back to caller.
+
+     For example, a deref-of-unchecked-malloc diagnostic might use:
+     - "returning possibly-NULL pointer to 'make_obj' from 'allocator'"
+     to make it clearer how the unchecked value moves from callee
+     back to caller.  */
+
+  virtual label_text describe_return_of_state (const evdesc::return_of_state &)
+  {
+    /* Default no-op implementation.  */
+    return label_text ();
+  }
+
+  /* Precision-of-wording vfunc for describing the final event within a
+     diagnostic_path.
+
+     For example a double-free diagnostic might use:
+      - "second 'free' here; first 'free' was at (3)"
+     and a use-after-free might use
+      - "use after 'free' here; memory was freed at (2)".  */
+
+  virtual label_text describe_final_event (const evdesc::final_event &)
+  {
+    /* Default no-op implementation.  */
+    return label_text ();
+  }
+
+  /* End of precision-of-wording vfuncs.  */
+
+  /* Utility function for implementing the above vfuncs.  */
+
+  static label_text formatted_print (const char *fmt, ...)
+    ATTRIBUTE_GCC_DIAG(1,2);
+};
+
+/* A template to make it easier to make subclasses of pending_diagnostic.
+
+   This uses the curiously-recurring template pattern, to implement
+   pending_diagnostic::subclass_equal_p by casting and calling
+   the operator==
+
+   This assumes that BASE_OTHER has already been checked to have
+   been of the same subclass (which pending_diagnostic::equal_p does).  */
+
+template <class Subclass>
+class pending_diagnostic_subclass : public pending_diagnostic
+{
+ public:
+  bool subclass_equal_p (const pending_diagnostic &base_other) const
+    FINAL OVERRIDE
+  {
+    const Subclass &other = (const Subclass &)base_other;
+    return *(const Subclass*)this == other;
+  }
+};
+
+#endif /* GCC_ANALYZER_PENDING_DIAGNOSTIC_H */
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 52e8979..2993798 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -44,7 +44,7 @@
 #include "tree-diagnostic.h"
 #include "diagnostic-color.h"
 #include "constraint-manager.h"
-#include "sm.h" // for pending_diagnostic
+#include "pending-diagnostic.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
diff --git a/gcc/analyzer/sm-file.cc b/gcc/analyzer/sm-file.cc
index adbfe59..3133277 100644
--- a/gcc/analyzer/sm-file.cc
+++ b/gcc/analyzer/sm-file.cc
@@ -34,6 +34,7 @@
 #include <string>
 #include "supergraph.h"
 #include "sm.h"
+#include "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 8be83e1..cd40dec 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -34,6 +34,7 @@
 #include <string>
 #include "supergraph.h"
 #include "sm.h"
+#include "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 5f9bfd3..9a1f6b4 100644
--- a/gcc/analyzer/sm-pattern-test.cc
+++ b/gcc/analyzer/sm-pattern-test.cc
@@ -34,6 +34,7 @@
 #include <string>
 #include "supergraph.h"
 #include "sm.h"
+#include "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 d49441f..056d6fa 100644
--- a/gcc/analyzer/sm-sensitive.cc
+++ b/gcc/analyzer/sm-sensitive.cc
@@ -34,6 +34,7 @@
 #include <string>
 #include "supergraph.h"
 #include "sm.h"
+#include "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 0063f1c..26a2b55 100644
--- a/gcc/analyzer/sm-taint.cc
+++ b/gcc/analyzer/sm-taint.cc
@@ -34,6 +34,7 @@
 #include <string>
 #include "supergraph.h"
 #include "sm.h"
+#include "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 dedf389..8ea064a 100644
--- a/gcc/analyzer/sm.cc
+++ b/gcc/analyzer/sm.cc
@@ -116,31 +116,6 @@ state_machine::validate (state_t s) const
 
 ////////////////////////////////////////////////////////////////////////////
 
-label_text
-pending_diagnostic::formatted_print (const char *fmt, ...)
-{
-  pretty_printer *pp = global_dc->printer->clone ();
-
-  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;
-  pp_format (pp, &ti);
-  pp_output_formatted_text (pp);
-  va_end (ap);
-
-  label_text result = label_text::take (xstrdup (pp_formatted_text (pp)));
-  delete pp;
-  return result;
-}
-
-////////////////////////////////////////////////////////////////////////////
-
 void
 make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
 {
diff --git a/gcc/analyzer/sm.h b/gcc/analyzer/sm.h
index dfcaa90..90d52fd 100644
--- a/gcc/analyzer/sm.h
+++ b/gcc/analyzer/sm.h
@@ -22,7 +22,6 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_SM_H
 
 #include "analyzer-logging.h"
-#include "diagnostic-metadata.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -35,6 +34,7 @@ extern bool any_pointer_p (tree var);
 
 class state_machine;
 class sm_context;
+class pending_diagnostic;
 
 /* A state machine describing an API.
    A mapping from state IDs to names, and (for now) a vfunc implementation
@@ -101,271 +101,6 @@ start_start_p (state_machine::state_t state)
 
 ////////////////////////////////////////////////////////////////////////////
 
-/* FIXME.  */
-
-// TODO: maybe capture which sm and pending_diagnostic emitted the error?
-// FIXME: is this needed?
-
-class metadata : public diagnostic_metadata
-{
- public:
-
- private:
-};
-
-/* FIXME.  */
-
-class event_id_t
-{
- public:
-  event_id_t () : m_index (UNKNOWN_EVENT_IDX) {}
-  event_id_t (int zero_based_idx) : m_index (zero_based_idx) {}
-
-  bool known_p () const { return m_index != UNKNOWN_EVENT_IDX; }
-
-  int one_based () const
-  {
-    gcc_assert (known_p ());
-    return m_index + 1;
-  }
-
- private:
-  static const int UNKNOWN_EVENT_IDX = -1;
-  int m_index; // zero-based
-};
-
-/* Various bundles of information used for generating more precise
-   messages for events within a diagnostic_path, for passing to the
-   various "describe_*" vfuncs of pending_diagnostic.  See those
-   for more information.  */
-
-namespace evdesc {
-
-/* For use by pending_diagnostic::describe_state_change.  */
-
-struct state_change
-{
-  state_change (tree expr,
-		state_machine::state_t old_state,
-		state_machine::state_t new_state,
-		event_id_t event_id)
-  : m_expr (expr), m_old_state (old_state),
-    m_new_state (new_state), m_event_id (event_id)
-  {}
-
-  tree m_expr;
-  state_machine::state_t m_old_state;
-  state_machine::state_t m_new_state;
-  event_id_t m_event_id;
-};
-
-/* For use by pending_diagnostic::describe_call_with_state.  */
-
-struct call_with_state
-{
-  call_with_state (tree caller_fndecl, tree callee_fndecl,
-		   tree expr, state_machine::state_t state)
-  : m_caller_fndecl (caller_fndecl),
-    m_callee_fndecl (callee_fndecl),
-    m_expr (expr),
-    m_state (state)
-  {
-  }
-
-  tree m_caller_fndecl;
-  tree m_callee_fndecl;
-  tree m_expr;
-  state_machine::state_t m_state;
-};
-
-/* For use by pending_diagnostic::describe_return_of_state.  */
-
-struct return_of_state
-{
-  return_of_state (tree caller_fndecl, tree callee_fndecl,
-		   state_machine::state_t state)
-  : m_caller_fndecl (caller_fndecl),
-    m_callee_fndecl (callee_fndecl),
-    m_state (state)
-  {
-  }
-
-  tree m_caller_fndecl;
-  tree m_callee_fndecl;
-  state_machine::state_t m_state;
-};
-
-/* For use by pending_diagnostic::describe_final_event.  */
-
-struct final_event
-{
-  final_event (tree expr, state_machine::state_t state)
-  : m_expr (expr), m_state (state)
-  {}
-
-  tree m_expr;
-  state_machine::state_t m_state;
-};
-
-} /* end of namespace evdesc */
-
-/* An abstract base class for capturing information about a diagnostic in
-   a form that is ready to emit at a later point (or be rejected).
-   Each kind of diagnostic will have a concrete subclass of
-   pending_diagnostic.
-
-   Normally, gcc diagnostics are emitted using va_list, which can't be
-   portably stored for later use, so we have to use an "emit" virtual
-   function.
-
-   This class also supports comparison, so that multiple pending_diagnostic
-   instances can be de-duplicated.
-
-   As well as emitting a diagnostic, the class has various "precision of
-   wording" virtual functions, for generating descriptions for events
-   within a diagnostic_path.  These are optional, but implementing these
-   allows for more precise wordings than the more generic
-   implementation.  */
-
-class pending_diagnostic
-{
- public:
-  virtual ~pending_diagnostic () {}
-
-  /* Vfunc for emitting the diagnostic.  The rich_location will have been
-     populated with a diagnostic_path.  */
-  virtual void emit (rich_location *) = 0;
-
-  /* Hand-coded RTTI: get an ID for the subclass.  */
-  virtual const char *get_kind () const = 0;
-
-  /* Compare for equality with OTHER, which might be of a different
-     subclass.  */
-
-  bool equal_p (const pending_diagnostic &other)
-  {
-    /* Check for pointer equality on the IDs from get_kind.  */
-    if (get_kind () != other.get_kind ())
-      return false;
-    /* Call vfunc now we know they have the same ID: */
-    return subclass_equal_p (other);
-  }
-
-  /* A vfunc for testing for equality, where we've already
-     checked they have the same ID.  See pending_diagnostic_subclass
-     below for a convenience subclass for implementing this.  */
-  virtual bool subclass_equal_p (const pending_diagnostic &other) const = 0;
-
-  /* For greatest precision-of-wording, the various following "describe_*"
-     virtual functions give the pending diagnostic a way to describe events
-     in a diagnostic_path in terms that make sense for that diagnostic.
-
-     In each case, return a non-NULL label_text to give the event a custom
-     description; NULL otherwise (falling back on a more generic
-     description).  */
-
-  /* Precision-of-wording vfunc for describing a critical state change
-     within the diagnostic_path.
-
-     For example, a double-free diagnostic might use the descriptions:
-     - "first 'free' happens here"
-     - "second 'free' happens here"
-     for the pertinent events, whereas a use-after-free might use the
-     descriptions:
-     - "freed here"
-     - "use after free here"
-     Note how in both cases the first event is a "free": the best
-     description to use depends on the diagnostic.  */
-
-  virtual label_text describe_state_change (const evdesc::state_change &)
-  {
-    /* Default no-op implementation.  */
-    return label_text ();
-  }
-
-  /* Precision-of-wording vfunc for describing an interprocedural call
-     carrying critial state for the diagnostic, from caller to callee.
-
-     For example a double-free diagnostic might use:
-     - "passing freed pointer 'ptr' in call to 'deallocator' from 'test'"
-     to make it clearer how the unchecked value moves from caller
-     to callee.  */
-
-  virtual label_text describe_call_with_state (const evdesc::call_with_state &)
-  {
-    /* Default no-op implementation.  */
-    return label_text ();
-  }
-
-  /* Precision-of-wording vfunc for describing an interprocedural return
-     within the diagnostic_path that carries critial state for the
-     diagnostic, from callee back to caller.
-
-     For example, a deref-of-unchecked-malloc diagnostic might use:
-     - "returning possibly-NULL pointer to 'make_obj' from 'allocator'"
-     to make it clearer how the unchecked value moves from callee
-     back to caller.  */
-
-  virtual label_text describe_return_of_state (const evdesc::return_of_state &)
-  {
-    /* Default no-op implementation.  */
-    return label_text ();
-  }
-
-  /* Precision-of-wording vfunc for describing the final event within a
-     diagnostic_path.
-
-     For example a double-free diagnostic might use:
-      - "second 'free' here; first 'free' was at (3)"
-     and a use-after-free might use
-      - "use after 'free' here; memory was freed at (2)".  */
-
-  virtual label_text describe_final_event (const evdesc::final_event &)
-  {
-    /* Default no-op implementation.  */
-    return label_text ();
-  }
-
-  /* End of precision-of-wording vfuncs.  */
-
-  /* Utility function for implementing the above vfuncs.  */
-
-  static label_text formatted_print (const char *fmt, ...)
-    ATTRIBUTE_GCC_DIAG(1,2);
-};
-
-/* A template to make it easier to make subclasses of pending_diagnostic.
-
-   This uses the curiously-recurring template pattern, to implement
-   pending_diagnostic::subclass_equal_p by casting and calling
-   the operator==
-
-   This assumes that BASE_OTHER has already been checked to have
-   been of the same subclass (which pending_diagnostic::equal_p does).  */
-
-template <class Subclass>
-class pending_diagnostic_subclass : public pending_diagnostic
-{
- public:
-  bool subclass_equal_p (const pending_diagnostic &base_other) const
-    FINAL OVERRIDE
-  {
-    const Subclass &other = (const Subclass &)base_other;
-    return *(const Subclass*)this == other;
-  }
-};
-
-#if 0
-/* A thing for state machines to pass to the engine to create
-   pending_diagnostic instances (so that we can filter without having 
-   to create pending_diagnostic instances first).  */
-
-class diagnostic_emitter
-{
-  virtual pending_diagnostic *make_diagnostic () = 0;
-};
-#endif
-
 /* Interface for the state machine to call the checker engine, at a
    particular stmt.  */
 
-- 
1.8.5.3

