https://gcc.gnu.org/g:f68343c2543ab65d75ef88bd920dfa209c7cbe20
commit r16-6666-gf68343c2543ab65d75ef88bd920dfa209c7cbe20 Author: David Malcolm <[email protected]> Date: Fri Jan 9 15:54:16 2026 -0500 analyzer: replace PLUGIN_ANALYZER_INIT with a pub/sub channel 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]> Diff: --- 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/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc | 30 ++++++------ .../gcc.dg/plugin/analyzer_kernel_plugin.cc | 43 +++++++++--------- .../gcc.dg/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 f97cfef295d9..8928cc771daf 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_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 */ diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index d4da04595e5f..5222f9e32dd6 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -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) { diff --git a/gcc/channels.h b/gcc/channels.h index 433a1e7fcf62..f03aa259037a 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 bc1e6f84acdb..ff0b5866f25d 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 c00ef95b1420..7e8837c53017 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 d54551663ed1..b2fd27fa6e12 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 c88e35f50f83..ce8d41289d7a 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" @@ -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 diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc b/gcc/testsuite/gcc.dg/plugin/analyzer_gil_plugin.cc index 74e2d73179c4..dfc44ef07061 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" @@ -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 diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc b/gcc/testsuite/gcc.dg/plugin/analyzer_kernel_plugin.cc index 5918bd159f86..57d55e7a75d1 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 d61b69942cdb..7080fe3b984b 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
