This patch eliminates the PLUGIN_ANALYZER_INIT event in favor of a new
analyzer_events_channel that can be subscribed to, and ports all the
in-tree analyzer plugins to using it.

The PLUGIN_* approach isn't typesafe, and the name suggests it's only
meant to be used for plugins, whereas the pub/sub approach is typesafe,
and treats the publish/subscribe network as orthogonal to whether the
code is built into the executable or is a plugin.

gcc/analyzer/ChangeLog:
        * common.h: Define INCLUDE_LIST.
        (class plugin_analyzer_init_iface): Replace with...
        (gcc::topics::analyzer_events::on_ana_init): ...this.
        (gcc::topics::analyzer_events::subscriber): New.
        * engine.cc: Include "context.h" and "channels.h".
        (class plugin_analyzer_init_impl): Replace with...
        (class impl_on_ana_init): ...this.  Fix some overlong lines.
        (impl_run_checkers): Port from PLUGIN_ANALYZER_INIT to using
        publish/subscribe framework.

gcc/ChangeLog:
        * channels.h (gcc::topics::analyzer_events::subscriber): New
        forward decl.
        (compiler_channels::analyzer_events_channel): New field.
        * doc/plugins.texi (PLUGIN_ANALYZER_INIT): Delete.
        * plugin.cc (register_callback): Delete PLUGIN_ANALYZER_INIT.
        (invoke_plugin_callbacks_full): Likewise.
        * plugin.def (PLUGIN_ANALYZER_INIT): Delete this event.

gcc/testsuite/ChangeLog:
        * gcc.dg/plugin/analyzer_cpython_plugin.cc: Port from
        PLUGIN_ANALYZER_INIT to subscribing to analyzer_events_channel.
        * gcc.dg/plugin/analyzer_gil_plugin.cc: Likewise.
        * gcc.dg/plugin/analyzer_kernel_plugin.cc: Likewise.
        * gcc.dg/plugin/analyzer_known_fns_plugin.cc: Likewise.

Signed-off-by: David Malcolm <[email protected]>
---
 gcc/analyzer/common.h                         | 47 ++++++++++++----
 gcc/analyzer/engine.cc                        | 36 ++++++++-----
 gcc/channels.h                                |  2 +
 gcc/doc/plugins.texi                          |  4 --
 gcc/plugin.cc                                 |  2 -
 gcc/plugin.def                                |  4 --
 .../gcc.dg/plugin/analyzer_cpython_plugin.cc  | 53 ++++++++++---------
 .../gcc.dg/plugin/analyzer_gil_plugin.cc      | 30 +++++------
 .../gcc.dg/plugin/analyzer_kernel_plugin.cc   | 43 ++++++++-------
 .../plugin/analyzer_known_fns_plugin.cc       | 37 +++++++------
 10 files changed, 142 insertions(+), 116 deletions(-)

diff --git a/gcc/analyzer/common.h b/gcc/analyzer/common.h
index ac3048c796e3d..a30dbc1e6bcc0 100644
--- a/gcc/analyzer/common.h
+++ b/gcc/analyzer/common.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_COMMON_H
 
 #include "config.h"
+#define INCLUDE_LIST
 #define INCLUDE_MAP
 #define INCLUDE_STRING
 #define INCLUDE_VECTOR
@@ -354,17 +355,6 @@ extern void register_known_file_functions 
(known_function_manager &kfm);
 extern void register_known_functions_lang_cp (known_function_manager &kfm);
 extern void register_varargs_builtins (known_function_manager &kfm);
 
-/* Passed by pointer to PLUGIN_ANALYZER_INIT callbacks.  */
-
-class plugin_analyzer_init_iface
-{
-public:
-  virtual void register_state_machine (std::unique_ptr<state_machine>) = 0;
-  virtual void register_known_function (const char *name,
-                                       std::unique_ptr<known_function>) = 0;
-  virtual logger *get_logger () const = 0;
-};
-
 /* An enum for describing the direction of an access to memory.  */
 
 enum class access_direction
@@ -598,6 +588,41 @@ private:
 #pragma GCC diagnostic ignored "-Wformat-diag"
 #endif
 
+namespace gcc {
+namespace topics {
+
+/* A topic for messages relating to the analyzer.  */
+
+namespace analyzer_events {
+
+/* A message published by the analyzer as it starts up, intended for
+   subsystems/plugins that want to register additional functionality
+   within the analyzer.  */
+
+struct on_ana_init
+{
+  virtual void
+  register_state_machine (std::unique_ptr<ana::state_machine>) const = 0;
+
+  virtual void
+  register_known_function (const char *name,
+                          std::unique_ptr<ana::known_function>) const = 0;
+
+  virtual ana::logger *
+  get_logger () const = 0;
+};
+
+struct subscriber {
+
+  virtual ~subscriber () = default;
+
+  virtual void on_message (const on_ana_init &) = 0;
+};
+
+} // namespace gcc::topics::analyzer_events
+} // namespace gcc::topics
+} // namespace gcc
+
 #if !ENABLE_ANALYZER
 extern void sorry_no_analyzer ();
 #endif /* #if !ENABLE_ANALYZER */
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 9d22950d79b14..0a560462acce3 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -34,6 +34,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "stringpool.h"
 #include "attribs.h"
 #include "tree-dfa.h"
+#include "context.h"
+#include "channels.h"
 
 #include "text-art/dump.h"
 
@@ -6479,34 +6481,39 @@ dump_analyzer_json (const supergraph &sg,
   free (filename);
 }
 
-/* Concrete subclass of plugin_analyzer_init_iface, allowing plugins
-   to register new state machines.  */
+/* Concrete subclass of on_ana_init, allowing plugins to register
+   new state machines.  */
 
-class plugin_analyzer_init_impl : public plugin_analyzer_init_iface
+class impl_on_ana_init : public gcc::topics::analyzer_events::on_ana_init
 {
 public:
-  plugin_analyzer_init_impl (std::vector<std::unique_ptr<state_machine>> 
&checkers,
-                            known_function_manager &known_fn_mgr,
-                            logger *logger)
+  impl_on_ana_init (std::vector<std::unique_ptr<state_machine>> &checkers,
+                   known_function_manager &known_fn_mgr,
+                   logger *logger)
   : m_checkers (checkers),
     m_known_fn_mgr (known_fn_mgr),
     m_logger (logger)
   {}
 
-  void register_state_machine (std::unique_ptr<state_machine> sm) final 
override
+  void
+  register_state_machine (std::unique_ptr<state_machine> sm)
+    const final override
   {
     LOG_SCOPE (m_logger);
     m_checkers.push_back (std::move (sm));
   }
 
-  void register_known_function (const char *name,
-                               std::unique_ptr<known_function> kf) final 
override
+  void
+  register_known_function (const char *name,
+                          std::unique_ptr<known_function> kf)
+    const final override
   {
     LOG_SCOPE (m_logger);
     m_known_fn_mgr.add (name, std::move (kf));
   }
 
-  logger *get_logger () const final override
+  logger *
+  get_logger () const final override
   {
     return m_logger;
   }
@@ -6572,10 +6579,11 @@ impl_run_checkers (logger *logger)
   register_known_functions (*eng.get_known_function_manager (),
                            *eng.get_model_manager ());
 
-  plugin_analyzer_init_impl data (checkers,
-                                 *eng.get_known_function_manager (),
-                                 logger);
-  invoke_plugin_callbacks (PLUGIN_ANALYZER_INIT, &data);
+  if (auto channel
+       = g->get_channels ().analyzer_events_channel.get_if_active ())
+    channel->publish (impl_on_ana_init (checkers,
+                                       *eng.get_known_function_manager (),
+                                       logger));
 
   if (logger)
     {
diff --git a/gcc/channels.h b/gcc/channels.h
index 433a1e7fcf62a..f03aa259037ae 100644
--- a/gcc/channels.h
+++ b/gcc/channels.h
@@ -28,6 +28,7 @@ namespace gcc {
 /* Forward decls of subscribers for the various topics we have
    publish/subscribe channels for.  */
 namespace topics {
+  namespace analyzer_events { struct subscriber; }
   namespace pass_events { struct subscriber; }
 } // namespace gcc::topics
 
@@ -35,6 +36,7 @@ namespace topics {
 
 struct compiler_channels
 {
+  pub_sub::channel<topics::analyzer_events::subscriber> 
analyzer_events_channel;
   pub_sub::channel<topics::pass_events::subscriber> pass_events_channel;
 };
 
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index c11167a34ef87..a909686154ef7 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -218,10 +218,6 @@ enum plugin_event
    as a const char* pointer.  */
   PLUGIN_INCLUDE_FILE,
 
-  /* Called when -fanalyzer starts. The event data is an
-     ana::plugin_analyzer_init_iface *.  */
-  PLUGIN_ANALYZER_INIT,
-
   PLUGIN_EVENT_FIRST_DYNAMIC    /* Dummy event used for indexing callback
                                    array.  */
 @};
diff --git a/gcc/plugin.cc b/gcc/plugin.cc
index 0de2cc2dd2c2d..d5150341b1498 100644
--- a/gcc/plugin.cc
+++ b/gcc/plugin.cc
@@ -499,7 +499,6 @@ register_callback (const char *plugin_name,
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
       case PLUGIN_INCLUDE_FILE:
-      case PLUGIN_ANALYZER_INIT:
         {
           struct callback_info *new_callback;
           if (!callback)
@@ -580,7 +579,6 @@ invoke_plugin_callbacks_full (int event, void *gcc_data)
       case PLUGIN_EARLY_GIMPLE_PASSES_END:
       case PLUGIN_NEW_PASS:
       case PLUGIN_INCLUDE_FILE:
-      case PLUGIN_ANALYZER_INIT:
         {
           /* Iterate over every callback registered with this event and
              call it.  */
diff --git a/gcc/plugin.def b/gcc/plugin.def
index 94e012a1e0064..2cdea1f75d9cc 100644
--- a/gcc/plugin.def
+++ b/gcc/plugin.def
@@ -99,10 +99,6 @@ DEFEVENT (PLUGIN_NEW_PASS)
    as a const char* pointer.  */
 DEFEVENT (PLUGIN_INCLUDE_FILE)
 
-/* Called when -fanalyzer starts. The event data is an
-   ana::plugin_analyzer_init_iface *.  */
-DEFEVENT (PLUGIN_ANALYZER_INIT)
-
 /* When adding a new hard-coded plugin event, don't forget to edit in
    file plugin.cc the functions register_callback and
    invoke_plugin_callbacks_full accordingly!  */
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc 
b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
index c80b2dae66bab..d0950a85a3819 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
@@ -35,6 +35,8 @@
 #include "digraph.h"
 #include "analyzer/supergraph.h"
 #include "sbitmap.h"
+#include "context.h"
+#include "channels.h"
 #include "analyzer/call-string.h"
 #include "analyzer/program-point.h"
 #include "analyzer/store.h"
@@ -1268,33 +1270,36 @@ sorry_no_cpython_plugin ()
         "Python/C API", "#include <Python.h>");
 }
 
-static void
-cpython_analyzer_init_cb (void *gcc_data, void * /*user_data */)
+namespace analyzer_events = ::gcc::topics::analyzer_events;
+
+class cpython_analyzer_events_subscriber : public analyzer_events::subscriber
 {
-  ana::plugin_analyzer_init_iface *iface
-      = (ana::plugin_analyzer_init_iface *)gcc_data;
-  LOG_SCOPE (iface->get_logger ());
-  if (0)
-    inform (input_location, "got here: cpython_analyzer_init_cb");
+public:
+  void
+  on_message (const analyzer_events::on_ana_init &m) final override
+  {
+    LOG_SCOPE (m.get_logger ());
 
-  init_py_structs ();
+    init_py_structs ();
 
-  if (pyobj_record == NULL_TREE)
-    {
-      sorry_no_cpython_plugin ();
-      return;
-    }
+    if (pyobj_record == NULL_TREE)
+      {
+       sorry_no_cpython_plugin ();
+       return;
+      }
 
-  iface->register_known_function ("PyList_Append",
-                                  std::make_unique<kf_PyList_Append> ());
-  iface->register_known_function ("PyList_New", 
std::make_unique<kf_PyList_New> ());
-  iface->register_known_function ("PyLong_FromLong",
-                                  std::make_unique<kf_PyLong_FromLong> ());
+    m.register_known_function ("PyList_Append",
+                              std::make_unique<kf_PyList_Append> ());
+    m.register_known_function ("PyList_New",
+                              std::make_unique<kf_PyList_New> ());
+    m.register_known_function ("PyLong_FromLong",
+                              std::make_unique<kf_PyLong_FromLong> ());
+    m.register_known_function
+      ("__analyzer_cpython_dump_refcounts",
+       std::make_unique<kf_analyzer_cpython_dump_refcounts> ());
+  }
+} cpython_sub;
 
-  iface->register_known_function (
-      "__analyzer_cpython_dump_refcounts",
-      std::make_unique<kf_analyzer_cpython_dump_refcounts> ());
-}
 } // namespace ana
 
 #endif /* #if ENABLE_ANALYZER */
@@ -1310,9 +1315,7 @@ plugin_init (struct plugin_name_args *plugin_info,
   register_finish_translation_unit_callback (&stash_named_types);
   register_finish_translation_unit_callback (&stash_global_vars);
   region_model::register_pop_frame_callback(pyobj_refcnt_checker);
-  register_callback (plugin_info->base_name, PLUGIN_ANALYZER_INIT,
-                     ana::cpython_analyzer_init_cb,
-                     NULL); /* void *user_data */
+  g->get_channels ().analyzer_events_channel.add_subscriber (ana::cpython_sub);
 #else
   sorry_no_analyzer ();
 #endif
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc 
b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
index c101c45b541af..563da2f3a933c 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
@@ -4,6 +4,7 @@
 */
 /* { dg-options "-g" } */
 
+#define INCLUDE_LIST
 #define INCLUDE_MEMORY
 #define INCLUDE_STRING
 #define INCLUDE_VECTOR
@@ -17,6 +18,8 @@
 #include "gimple-iterator.h"
 #include "gimple-walk.h"
 #include "diagnostics/event-id.h"
+#include "context.h"
+#include "channels.h"
 #include "analyzer/common.h"
 #include "analyzer/analyzer-logging.h"
 #include "json.h"
@@ -417,19 +420,19 @@ gil_state_machine::check_for_pyobject_usage_without_gil 
(sm_context &sm_ctxt,
     }
 }
 
-/* Callback handler for the PLUGIN_ANALYZER_INIT event.  */
+namespace analyzer_events = ::gcc::topics::analyzer_events;
 
-static void
-gil_analyzer_init_cb (void *gcc_data, void */*user_data*/)
+class gil_analyzer_events_subscriber : public analyzer_events::subscriber
 {
-  ana::plugin_analyzer_init_iface *iface
-    = (ana::plugin_analyzer_init_iface *)gcc_data;
-  LOG_SCOPE (iface->get_logger ());
-  if (0)
-    inform (input_location, "got here: gil_analyzer_init_cb");
-  iface->register_state_machine
-    (std::make_unique<gil_state_machine> (iface->get_logger ()));
-}
+public:
+  void
+  on_message (const analyzer_events::on_ana_init &m) final override
+  {
+    LOG_SCOPE (m.get_logger ());
+    m.register_state_machine
+      (std::make_unique<gil_state_machine> (m.get_logger ()));
+  }
+} gil_sub;
 
 } // namespace ana
 
@@ -443,10 +446,7 @@ plugin_init (struct plugin_name_args *plugin_info,
   const char *plugin_name = plugin_info->base_name;
   if (0)
     inform (input_location, "got here; %qs", plugin_name);
-  register_callback (plugin_info->base_name,
-                    PLUGIN_ANALYZER_INIT,
-                    ana::gil_analyzer_init_cb,
-                    NULL); /* void *user_data */
+  g->get_channels ().analyzer_events_channel.add_subscriber (ana::gil_sub);
 #else
   sorry_no_analyzer ();
 #endif
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc 
b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
index 5918bd159f86f..57d55e7a75d14 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
@@ -34,6 +34,8 @@
 #include "digraph.h"
 #include "analyzer/supergraph.h"
 #include "sbitmap.h"
+#include "context.h"
+#include "channels.h"
 #include "analyzer/call-string.h"
 #include "analyzer/program-point.h"
 #include "analyzer/store.h"
@@ -221,26 +223,26 @@ class known_function___check_object_size : public 
known_function
   }
 };
 
-/* Callback handler for the PLUGIN_ANALYZER_INIT event.  */
+namespace analyzer_events = ::gcc::topics::analyzer_events;
 
-static void
-kernel_analyzer_init_cb (void *gcc_data, void */*user_data*/)
+class kernel_analyzer_events_subscriber : public analyzer_events::subscriber
 {
-  ana::plugin_analyzer_init_iface *iface
-    = (ana::plugin_analyzer_init_iface *)gcc_data;
-  LOG_SCOPE (iface->get_logger ());
-  if (0)
-    inform (input_location, "got here: kernel_analyzer_init_cb");
-  iface->register_known_function
-    ("copy_from_user",
-     std::make_unique<known_function_copy_from_user> ());
-  iface->register_known_function
-    ("copy_to_user",
-     std::make_unique<known_function_copy_to_user> ());
-  iface->register_known_function
-    ("__check_object_size",
-     std::make_unique<known_function___check_object_size> ());
-}
+public:
+  void
+  on_message (const analyzer_events::on_ana_init &m) final override
+  {
+    LOG_SCOPE (m.get_logger ());
+    m.register_known_function
+      ("copy_from_user",
+       std::make_unique<known_function_copy_from_user> ());
+    m.register_known_function
+      ("copy_to_user",
+       std::make_unique<known_function_copy_to_user> ());
+    m.register_known_function
+      ("__check_object_size",
+       std::make_unique<known_function___check_object_size> ());
+  }
+} kernel_sub;
 
 } // namespace ana
 
@@ -254,10 +256,7 @@ plugin_init (struct plugin_name_args *plugin_info,
   const char *plugin_name = plugin_info->base_name;
   if (0)
     inform (input_location, "got here; %qs", plugin_name);
-  register_callback (plugin_info->base_name,
-                    PLUGIN_ANALYZER_INIT,
-                    ana::kernel_analyzer_init_cb,
-                    NULL); /* void *user_data */
+  g->get_channels ().analyzer_events_channel.add_subscriber (ana::kernel_sub);
 #else
   sorry_no_analyzer ();
 #endif
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc 
b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
index d61b69942cdb6..7080fe3b984bb 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc
@@ -34,6 +34,8 @@
 #include "digraph.h"
 #include "analyzer/supergraph.h"
 #include "sbitmap.h"
+#include "context.h"
+#include "channels.h"
 #include "analyzer/call-string.h"
 #include "analyzer/program-point.h"
 #include "analyzer/store.h"
@@ -174,23 +176,23 @@ public:
   }
 };
 
-/* Callback handler for the PLUGIN_ANALYZER_INIT event.  */
+namespace analyzer_events = ::gcc::topics::analyzer_events;
 
-static void
-known_fn_analyzer_init_cb (void *gcc_data, void */*user_data*/)
+class known_fn_analyzer_events_subscriber : public analyzer_events::subscriber
 {
-  ana::plugin_analyzer_init_iface *iface
-    = (ana::plugin_analyzer_init_iface *)gcc_data;
-  LOG_SCOPE (iface->get_logger ());
-  if (0)
-    inform (input_location, "got here: known_fn_analyzer_init_cb");
-  iface->register_known_function
-    ("returns_42",
-     std::make_unique<known_function_returns_42> ());
-  iface->register_known_function
-    ("attempt_to_copy",
-     std::make_unique<known_function_attempt_to_copy> ());
-}
+public:
+  void
+  on_message (const analyzer_events::on_ana_init &m) final override
+  {
+    LOG_SCOPE (m.get_logger ());
+    m.register_known_function
+      ("returns_42",
+       std::make_unique<known_function_returns_42> ());
+    m.register_known_function
+      ("attempt_to_copy",
+       std::make_unique<known_function_attempt_to_copy> ());
+  }
+} known_fn_sub;
 
 } // namespace ana
 
@@ -204,10 +206,7 @@ plugin_init (struct plugin_name_args *plugin_info,
   const char *plugin_name = plugin_info->base_name;
   if (0)
     inform (input_location, "got here; %qs", plugin_name);
-  register_callback (plugin_info->base_name,
-                    PLUGIN_ANALYZER_INIT,
-                    ana::known_fn_analyzer_init_cb,
-                    NULL); /* void *user_data */
+  g->get_channels ().analyzer_events_channel.add_subscriber 
(ana::known_fn_sub);
 #else
   sorry_no_analyzer ();
 #endif
-- 
2.26.3

Reply via email to