]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
analyzer: replace PLUGIN_ANALYZER_INIT with a pub/sub channel
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 9 Jan 2026 20:54:16 +0000 (15:54 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Fri, 9 Jan 2026 20:54:16 +0000 (15:54 -0500)
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 <dmalcolm@redhat.com>
gcc/analyzer/common.h
gcc/analyzer/engine.cc
gcc/channels.h
gcc/doc/plugins.texi
gcc/plugin.cc
gcc/plugin.def
gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc
gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc
gcc/testsuite/gcc.dg/plugin/analyzer_known_fns_plugin.cc

index f97cfef295d920614cb4afd0d4fed18686c311c3..8928cc771daf8a94a761a7fba506595f9d02b153 100644 (file)
@@ -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_SET
 #define INCLUDE_STRING
@@ -362,17 +363,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
@@ -612,6 +602,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 */
index d4da04595e5fae6cf1b1af2fa2cc9591f5367a5c..5222f9e32dd68d39db58ab9af5cf0ca50f954ee4 100644 (file)
@@ -35,6 +35,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "attribs.h"
 #include "tree-dfa.h"
 #include "gimple-predict.h"
+#include "context.h"
+#include "channels.h"
 
 #include "text-art/dump.h"
 
@@ -5096,34 +5098,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;
   }
@@ -5218,10 +5225,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)
     {
index 433a1e7fcf62aed70591166f5c0d669eb4804c80..f03aa259037aeec05f3e88235a3d43398771e185 100644 (file)
@@ -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;
 };
 
index bc1e6f84acdb6882576db7dd102ab51401b0e713..ff0b5866f25d78243cc40778d21477bf109bf557 100644 (file)
@@ -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.  */
 @};
index c00ef95b1420df5b597b8a2938efb81406482f79..7e8837c53017e47f64930a9bb6cb14c510b4321c 100644 (file)
@@ -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.  */
index d54551663ed1a8ca7c0d874c9c7c7e7deced7bd1..b2fd27fa6e12bd5e5f78e2efba7a9db810068709 100644 (file)
@@ -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!  */
index c88e35f50f8389cc1c678df5b165b80e82049554..ce8d41289d7abd430a566f9eabaef92781008e40 100644 (file)
@@ -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"
@@ -1178,33 +1180,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 */
@@ -1220,9 +1225,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
index 74e2d73179c45fc14d961cccd3b6a4d11d69144c..dfc44ef07061068475fd6d3698165f9330c76723 100644 (file)
@@ -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"
@@ -410,19 +413,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
 
@@ -436,10 +439,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
index 5918bd159f86f4cfb1e06152b54a5fabbb3163dc..57d55e7a75d14fd3301d6f6a8589282b7d5b1869 100644 (file)
@@ -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
index d61b69942cdb6ed957a48e06e57e2a0b16fa2629..7080fe3b984bb0874a3e764380c85e22f6843990 100644 (file)
@@ -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