From da2c081734c298eeaed707d2f4de371368379616 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 2 Apr 2026 18:27:47 -0400
Subject: [PATCH 39/98] FIXME: create data flow events whilst rewinding data
 flow

---
 gcc/analyzer/checker-event.cc      |   5 ++
 gcc/analyzer/checker-event.h       |  13 ++++
 gcc/analyzer/diagnostic-manager.cc |  33 ++++++++-
 gcc/analyzer/diagnostic-manager.h  |   2 +
 gcc/analyzer/engine.cc             |  30 +++++++-
 gcc/analyzer/exploded-path.h       |  24 +++++++
 gcc/analyzer/ops.cc                | 109 ++++++++++++++++-------------
 gcc/analyzer/ops.h                 |  11 +++
 8 files changed, 177 insertions(+), 50 deletions(-)

diff --git a/gcc/analyzer/checker-event.cc b/gcc/analyzer/checker-event.cc
index 6bd6bc71d2ac..94bdd212b07f 100644
--- a/gcc/analyzer/checker-event.cc
+++ b/gcc/analyzer/checker-event.cc
@@ -341,6 +341,11 @@ data_flow_event::print_desc (pretty_printer &pp) const
     }
 }
 
+std::unique_ptr<data_flow_event>
+data_flow_event::clone () const
+{
+  return std::make_unique<data_flow_event> (*this);
+}
 
 /* class region_creation_event : public checker_event.  */
 
diff --git a/gcc/analyzer/checker-event.h b/gcc/analyzer/checker-event.h
index 8d2098c2991a..ec683db22710 100644
--- a/gcc/analyzer/checker-event.h
+++ b/gcc/analyzer/checker-event.h
@@ -252,12 +252,21 @@ public:
 class data_flow_event : public checker_event
 {
 public:
+  enum class kind
+  {
+    origin,
+    at_call,
+    at_return
+  };
+
   data_flow_event (const event_loc_info &loc_info,
+		   enum kind kind,
 		   const region *src_reg,
 		   tree src_reg_expr,
 		   const region *dst_reg,
 		   tree dst_reg_expr)
   : checker_event (event_kind::data_flow, loc_info),
+    m_kind (kind),
     m_src_reg (src_reg),
     m_src_reg_expr (src_reg_expr),
     m_dst_reg (dst_reg),
@@ -268,8 +277,12 @@ public:
     gcc_assert (dst_reg);
   }
 
+  virtual std::unique_ptr<data_flow_event>
+  clone () const;
+
   void print_desc (pretty_printer &) const final override;
 
+  enum kind m_kind;
   const region *m_src_reg;
   tree m_src_reg_expr;
   const region *m_dst_reg;
diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 6c06f140f456..68d2bf7ce1da 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -1643,6 +1643,28 @@ diagnostic_manager::get_logical_location_manager () const
   return *mgr;
 }
 
+class epath_rewind_context : public rewind_context
+{
+public:
+  epath_rewind_context (const exploded_edge &eedge,
+			logger *logger,
+			eedge_annotation input_ann,
+			exploded_path::element_t &epath_element)
+  : rewind_context (eedge, logger, input_ann),
+    m_epath_element (epath_element)
+  {
+  }
+
+  void
+  add_event (std::unique_ptr<data_flow_event> ev) final override
+  {
+    m_epath_element.m_data_flow_event = std::move (ev);
+  }
+
+private:
+  exploded_path::element_t &m_epath_element;
+};
+
 // FIXME
 
 void
@@ -1683,7 +1705,7 @@ diagnostic_manager::annotate_exploded_path (const path_builder &pb,
       const exploded_edge *eedge = iter_element.m_eedge;
       gcc_assert (eedge);
 
-      rewind_context ctxt (*eedge, logger, curr_annotation);
+      epath_rewind_context ctxt (*eedge, logger, curr_annotation, iter_element);
       if (eedge->m_custom_info)
 	{
 	  if (logger)
@@ -1778,7 +1800,10 @@ diagnostic_manager::build_emission_path (const path_builder &pb,
       const exploded_edge *eedge = epath.m_elements[i].m_eedge;
       gcc_assert (eedge);
       add_events_for_eedge (pb, *eedge, emission_path, &interest);
-
+#if 1
+      if (auto &ev = epath.m_elements[i].m_data_flow_event)
+	emission_path->add_event (ev->clone ());
+#else
       if (epath.m_elements[i].m_annotation_at_src
 	  != epath.m_elements[i].m_annotation_at_dst)
 	maybe_add_dataflow_event
@@ -1787,6 +1812,7 @@ diagnostic_manager::build_emission_path (const path_builder &pb,
 	   epath.m_elements[i].m_annotation_at_src,
 	   epath.m_elements[i].m_annotation_at_dst,
 	   *emission_path);
+#endif
     }
   add_event_on_final_node (pb, epath.get_final_enode (),
 			   emission_path, &interest);
@@ -2146,6 +2172,7 @@ diagnostic_manager::add_events_for_eedge (const path_builder &pb,
     }
 }
 
+#if 0
 void
 diagnostic_manager::maybe_add_dataflow_event (const path_builder &pb,
 					      const exploded_edge &eedge,
@@ -2153,6 +2180,7 @@ diagnostic_manager::maybe_add_dataflow_event (const path_builder &pb,
 					      const eedge_annotation &dst_ann,
 					      checker_path &emission_path) const
 {
+  gcc_assert (eedge.m_);
   gcc_assert (src_ann.m_region_holding_value
 	      != dst_ann.m_region_holding_value);
   gcc_assert (dst_ann.m_region_holding_value);
@@ -2176,6 +2204,7 @@ diagnostic_manager::maybe_add_dataflow_event (const path_builder &pb,
 					dst_reg,
 					dst_reg_expr));
 }
+#endif
 
 /* Return true if EEDGE is a significant edge in the path to the diagnostic
    for PB.
diff --git a/gcc/analyzer/diagnostic-manager.h b/gcc/analyzer/diagnostic-manager.h
index 5ccbf09d91c6..7b2f0913d7b6 100644
--- a/gcc/analyzer/diagnostic-manager.h
+++ b/gcc/analyzer/diagnostic-manager.h
@@ -219,12 +219,14 @@ private:
 			     checker_path *emission_path,
 			     interesting_t *interest) const;
 
+#if 0
   void
   maybe_add_dataflow_event (const path_builder &pb,
 			    const exploded_edge &eedge,
 			    const eedge_annotation &src_ann,
 			    const eedge_annotation &dst_ann,
 			    checker_path &emission_path) const;
+#endif
 
   bool significant_edge_p (const path_builder &pb,
 			   const exploded_edge &eedge) const;
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index bc37c35315a9..03adb4a1fbbd 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1701,10 +1701,21 @@ interprocedural_call::try_to_rewind_data_flow (rewind_context &ctxt) const
 		= ctxt.m_eedge.m_src->get_state ().m_region_model;
 	      ctxt.m_output.m_region_holding_value
 		= src_enode_model->get_lvalue (src_tree, nullptr);
+
+	      // FIXME:
+	      ctxt.add_event
+		(std::make_unique<data_flow_event>
+		 (ctxt.m_eedge.m_src->get_point (),
+		  data_flow_event::kind::at_call,
+		  ctxt.m_output.m_region_holding_value,
+		  src_tree,
+		  ctxt.m_input.m_region_holding_value,
+		  dst_tree));
+	      // FIXME: do something with callsite_expr?
+
 	      if (logger)
 		logger->log ("updating m_region_holding_value from %qE to %qE",
 			     dst_tree, src_tree);
-	      // FIXME: do something with callsite_expr?
 	    }
 	}
     }
@@ -1774,6 +1785,14 @@ interprocedural_return::try_to_rewind_data_flow (rewind_context &ctxt) const
   if (!lhs)
     return true;
 
+  const region_model *src_enode_model
+    = ctxt.m_eedge.m_src->get_state ().m_region_model;
+  tree fndecl = src_enode_model->get_current_function ()->decl;
+  tree fn_result = DECL_RESULT (fndecl);
+
+  ctxt.on_data_flow (DECL_RESULT (fndecl), lhs);
+
+#if 0
   const region_model *dst_enode_model
     = ctxt.m_eedge.m_dest->get_state ().m_region_model;
   const region *dst_reg_in_dst_enode
@@ -1792,7 +1811,16 @@ interprocedural_return::try_to_rewind_data_flow (rewind_context &ctxt) const
       const region *src_reg_in_src_enode
 	= src_enode_model->get_lvalue (fn_result, nullptr);
       ctxt.m_output.m_region_holding_value = src_reg_in_src_enode;
+      ctxt.add_event
+	(std::make_unique<data_flow_event>
+	 (ctxt.m_eedge.m_src->get_point (),
+	  data_flow_event::kind::at_return,
+	  ctxt.m_output.m_region_holding_value,
+	  fn_result,
+	  ctxt.m_input.m_region_holding_value,
+	  lhs));
     }
+#endif
 
   return true;
 }
diff --git a/gcc/analyzer/exploded-path.h b/gcc/analyzer/exploded-path.h
index cfa7513b2554..3946ee63d1cb 100644
--- a/gcc/analyzer/exploded-path.h
+++ b/gcc/analyzer/exploded-path.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_EXPLODED_PATH_H
 
 #include "analyzer/exploded-graph.h"
+#include "analyzer/checker-event.h"
 
 namespace ana {
 
@@ -36,10 +37,33 @@ public:
     : m_eedge (eedge)
     {
     }
+    element_t (const element_t &other)
+    : m_eedge (other.m_eedge),
+      m_annotation_at_src (other.m_annotation_at_src),
+      m_annotation_at_dst (other.m_annotation_at_dst),
+      m_data_flow_event (nullptr)
+    {
+      if (other.m_data_flow_event)
+	m_data_flow_event = other.m_data_flow_event->clone ();
+    }
+
+    element_t (element_t &&other) = default;
+
+    element_t &operator= (const element_t &other)
+    {
+      m_eedge = other.m_eedge;
+      m_annotation_at_src = other.m_annotation_at_src;
+      m_annotation_at_dst = other.m_annotation_at_dst;
+      m_data_flow_event = (other.m_data_flow_event
+			  ? other.m_data_flow_event->clone ()
+			  : nullptr);
+      return *this;
+    }
 
     const exploded_edge *m_eedge;
     eedge_annotation m_annotation_at_src;
     eedge_annotation m_annotation_at_dst;
+    std::unique_ptr<data_flow_event> m_data_flow_event;
   };
 
   exploded_path () = default;
diff --git a/gcc/analyzer/ops.cc b/gcc/analyzer/ops.cc
index 1993a23f5888..5b3c7b22bbf7 100644
--- a/gcc/analyzer/ops.cc
+++ b/gcc/analyzer/ops.cc
@@ -190,6 +190,62 @@ private:
   } m_path_context;
 };
 
+// struct rewind_context
+
+void
+rewind_context::on_data_origin (tree dst_tree)
+{
+  gcc_assert (dst_tree);
+  const region_model *dst_enode_model
+    = m_eedge.m_dest->get_state ().m_region_model;
+  const region *dst_reg_in_dst_enode
+    = dst_enode_model->get_lvalue (dst_tree, nullptr);
+  if (m_input.m_region_holding_value == dst_reg_in_dst_enode)
+    {
+      if (m_logger)
+	m_logger->log ("data origin, into %qE", dst_tree);
+      m_output.m_region_holding_value = nullptr;
+      add_event
+	(std::make_unique<data_flow_event>
+	 (m_eedge.m_src->get_point (),
+	  data_flow_event::kind::at_call, // FIXME
+	  nullptr,
+	  NULL_TREE,
+	  m_input.m_region_holding_value,
+	  dst_tree));
+    }
+}
+
+void
+rewind_context::on_data_flow (tree src_tree, tree dst_tree)
+{
+  gcc_assert (src_tree);
+  gcc_assert (dst_tree);
+  const region_model *dst_enode_model
+    = m_eedge.m_dest->get_state ().m_region_model;
+  const region *dst_reg_in_dst_enode
+    = dst_enode_model->get_lvalue (dst_tree, nullptr);
+  if (m_input.m_region_holding_value == dst_reg_in_dst_enode)
+    {
+      if (m_logger)
+	m_logger->log ("rewinding from %qE to %qE", dst_tree, src_tree);
+      const region_model *src_enode_model
+	= m_eedge.m_src->get_state ().m_region_model;
+      const region *src_reg_in_src_enode
+	= src_enode_model->get_lvalue (src_tree, nullptr);
+      m_output.m_region_holding_value = src_reg_in_src_enode;
+
+      add_event
+	(std::make_unique<data_flow_event>
+	 (m_eedge.m_src->get_point (),
+	  data_flow_event::kind::at_call, // FIXME
+	  m_output.m_region_holding_value,
+	  src_tree,
+	  m_input.m_region_holding_value,
+	  dst_tree));
+    }
+}
+
 // class gimple_stmt_op : public operation
 
 void
@@ -694,27 +750,14 @@ gassign_op::try_to_rewind_data_flow (rewind_context &ctxt) const
     case VAR_DECL:
     case PARM_DECL:
     case COMPONENT_REF:
-      {
-	const region *dst_reg_in_dst_enode
-	  = ctxt.m_eedge.m_dest->get_state ().m_region_model->get_lvalue
-	      (lhs, nullptr);
-	if (ctxt.m_input.m_region_holding_value == dst_reg_in_dst_enode)
-	  {
-	    if (logger)
-	      logger->log ("updating m_region_holding_value for assign");
-	    const region *src_reg_in_src_enode
-	      = ctxt.m_eedge.m_src->get_state ().m_region_model->get_lvalue
-		  (rhs1, nullptr);
-	    ctxt.m_output.m_region_holding_value = src_reg_in_src_enode;
-	  }
-      }
+      ctxt.on_data_flow (rhs1, lhs);
       break;
 
     case INTEGER_CST:
     case REAL_CST:
       if (logger)
 	logger->log ("value comes from here");
-      ctxt.m_output.m_region_holding_value = nullptr;
+      ctxt.on_data_origin (lhs);
       break;
     }
 
@@ -799,27 +842,12 @@ greturn_op::try_to_rewind_data_flow (rewind_context &ctxt) const
   auto logger = ctxt.m_logger;
   LOG_SCOPE (logger);
 
-  const region_model *dst_enode_model
-    = ctxt.m_eedge.m_dest->get_state ().m_region_model;
-  const region_model *src_enode_model
-    = ctxt.m_eedge.m_src->get_state ().m_region_model;
-
-  tree fndecl = src_enode_model->get_current_function ()->decl;
-  tree lhs = DECL_RESULT (fndecl);
-
-    const region *dst_reg_in_dst_enode
-    = dst_enode_model->get_lvalue (lhs, nullptr);
-
-  if (ctxt.m_input.m_region_holding_value == dst_reg_in_dst_enode)
+  if (get_retval ())
     {
-      if (logger)
-	logger->log ("updating m_region_holding_value for greturn_op");
-
       const region_model *src_enode_model
 	= ctxt.m_eedge.m_src->get_state ().m_region_model;
-      const region *src_reg_in_src_enode
-	= src_enode_model->get_lvalue (get_retval (), nullptr);
-      ctxt.m_output.m_region_holding_value = src_reg_in_src_enode;
+      tree fndecl = src_enode_model->get_current_function ()->decl;
+      ctxt.on_data_flow (get_retval (), DECL_RESULT (fndecl));
     }
 
   return true;
@@ -2455,20 +2483,7 @@ phis_for_edge_op::try_to_rewind_data_flow (rewind_context &ctxt) const
   auto logger = ctxt.m_logger;
   LOG_SCOPE (logger);
   for (auto iter : m_pairs)
-    {
-      const region *dst_reg_in_dst_enode
-	= ctxt.m_eedge.m_dest->get_state ().m_region_model->get_lvalue
-	    (iter.m_dst, nullptr);
-      if (ctxt.m_input.m_region_holding_value == dst_reg_in_dst_enode)
-	{
-	  if (logger)
-	    logger->log ("updating m_region_holding_value_at_dst for phi");
-	  const region *src_reg_in_src_enode
-	    = ctxt.m_eedge.m_src->get_state ().m_region_model->get_lvalue
-	    (iter.m_src, nullptr);
-	  ctxt.m_output.m_region_holding_value = src_reg_in_src_enode;
-	}
-    }
+    ctxt.on_data_flow (iter.m_src, iter.m_dst);
   return true;
 }
 
diff --git a/gcc/analyzer/ops.h b/gcc/analyzer/ops.h
index ebb747549f6c..b2ea643926b8 100644
--- a/gcc/analyzer/ops.h
+++ b/gcc/analyzer/ops.h
@@ -33,6 +33,8 @@ class operation;
 
 class callsite_expr;
 
+class data_flow_event;
+
 struct operation_context
 {
   operation_context (exploded_graph &eg,
@@ -86,6 +88,15 @@ struct rewind_context
   {
   }
 
+  void
+  on_data_origin (tree dst);
+
+  void
+  on_data_flow (tree src, tree dst);
+
+  virtual void
+  add_event (std::unique_ptr<data_flow_event>) = 0;
+
   const exploded_edge &m_eedge;
   logger *m_logger;
   eedge_annotation m_input;
-- 
2.49.0

