https://gcc.gnu.org/g:bc668cf6c94a2607f280fa2447095e5f7cb81c2e

commit r16-6668-gbc668cf6c94a2607f280fa2447095e5f7cb81c2e
Author: David Malcolm <[email protected]>
Date:   Fri Jan 9 15:54:16 2026 -0500

    analyzer: port pop_frame_callbacks to pub/sub
    
    More simplification/consolidation of some callback logic in analyzer in
    favor of using the analyzer pub/sub channel.
    
    No functional change intended.
    
    gcc/analyzer/ChangeLog:
            * common.h (struct on_frame_popped): New.
            (subscriber::on_message): New vfunc for on_frame_popped.
            * region-model.cc: Include "context.h" and "channels.h".
            (region_model::pop_frame_callbacks): Delete.
            (region_model::pop_frame): Port from notify_on_pop_frame to
            using pub/sub channel.
            * region-model.h (pop_frame_callback): Delete typedef.
            (region_model::register_pop_frame_callback): Delete.
            (region_model::pop_frame_callbacks): Delete.
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/plugin/analyzer_cpython_plugin.cc
            (cpython_analyzer_events_subscriber::on_message): Implement for
            on_frame_popped.
            (plugin_init): Drop call to
            region_model::register_pop_frame_callback in favor of the above
            pub/sub handler.
    
    Signed-off-by: David Malcolm <[email protected]>

Diff:
---
 gcc/analyzer/common.h                              | 12 ++++++++++++
 gcc/analyzer/region-model.cc                       | 12 +++++++++---
 gcc/analyzer/region-model.h                        | 22 ----------------------
 .../gcc.dg/plugin/analyzer_cpython_plugin.cc       | 10 +++++++++-
 4 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/gcc/analyzer/common.h b/gcc/analyzer/common.h
index d66c1a86e613..27ca49ee1c81 100644
--- a/gcc/analyzer/common.h
+++ b/gcc/analyzer/common.h
@@ -638,12 +638,24 @@ struct on_ana_init
   get_logger () const = 0;
 };
 
+/* A message published by the analyzer when it simulates popping a stack
+   frame.  */
+
+struct on_frame_popped
+{
+  const ana::region_model *m_new_model;
+  const ana::region_model *m_old_model;
+  const ana::svalue *m_retval;
+  ana::region_model_context *m_ctxt;
+};
+
 struct subscriber {
 
   virtual ~subscriber () = default;
 
   virtual void on_message (const on_tu_finished &) {}
   virtual void on_message (const on_ana_init &) {}
+  virtual void on_message (const on_frame_popped &) {}
 };
 
 } // namespace gcc::topics::analyzer_events
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 573680500e8a..be7b3d7b95c0 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -44,6 +44,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-pretty-print.h"
 #include "fold-const.h"
 #include "selftest-tree.h"
+#include "context.h"
+#include "channels.h"
 
 #include "text-art/tree-widget.h"
 
@@ -70,8 +72,6 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace ana {
 
-auto_vec<pop_frame_callback> region_model::pop_frame_callbacks;
-
 /* Dump T to PP in language-independent form, for debugging/logging/dumping
    purposes.  */
 
@@ -6501,7 +6501,13 @@ region_model::pop_frame (tree result_lvalue,
     }
 
   unbind_region_and_descendents (frame_reg,poison_kind::popped_stack);
-  notify_on_pop_frame (this, &pre_popped_model, retval, ctxt);
+
+  if (auto chan = g->get_channels ().analyzer_events_channel.get_if_active ())
+    {
+      gcc::topics::analyzer_events::on_frame_popped msg
+       {this, &pre_popped_model, retval, ctxt};
+      chan->publish (msg);
+    }
 }
 
 /* Get the number of frames in this region_model's stack.  */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index df0c128a764e..6e9129a6dca1 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -246,11 +246,6 @@ public:
 
 struct append_regions_cb_data;
 
-typedef void (*pop_frame_callback) (const region_model *model,
-                                   const region_model *prev_model,
-                                   const svalue *retval,
-                                   region_model_context *ctxt);
-
 /* Roughly equivalent to a struct __cxa_exception, except we store a 
std::vector
    rather than a linked list.    */
 
@@ -591,22 +586,6 @@ class region_model
   get_builtin_kf (const gcall &call,
                  region_model_context *ctxt = nullptr) const;
 
-  static void
-  register_pop_frame_callback (const pop_frame_callback &callback)
-  {
-    pop_frame_callbacks.safe_push (callback);
-  }
-
-  static void
-  notify_on_pop_frame (const region_model *model,
-                      const region_model *prev_model,
-                      const svalue *retval,
-                      region_model_context *ctxt)
-  {
-    for (auto &callback : pop_frame_callbacks)
-       callback (model, prev_model, retval, ctxt);
-  }
-
   bool called_from_main_p () const;
 
   void push_thrown_exception (const exception_node &node)
@@ -736,7 +715,6 @@ private:
                                    tree fndecl,
                                    region_model_context *ctxt);
 
-  static auto_vec<pop_frame_callback> pop_frame_callbacks;
   /* Storing this here to avoid passing it around everywhere.  */
   region_model_manager *const m_mgr;
 
diff --git a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc 
b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
index fc677c5ec541..cde45c438763 100644
--- a/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
+++ b/gcc/testsuite/gcc.dg/plugin/analyzer_cpython_plugin.cc
@@ -1216,6 +1216,15 @@ public:
       ("__analyzer_cpython_dump_refcounts",
        std::make_unique<kf_analyzer_cpython_dump_refcounts> ());
   }
+
+  void
+  on_message (const analyzer_events::on_frame_popped &msg) final override
+  {
+    pyobj_refcnt_checker (msg.m_new_model,
+                         msg.m_old_model,
+                         msg.m_retval,
+                         msg.m_ctxt);
+  }
 } cpython_sub;
 
 } // namespace ana
@@ -1230,7 +1239,6 @@ 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);
-  region_model::register_pop_frame_callback(pyobj_refcnt_checker);
   g->get_channels ().analyzer_events_channel.add_subscriber (ana::cpython_sub);
 #else
   sorry_no_analyzer ();

Reply via email to