From 95c2fa3ac9bdadb55019883616593ea7020b4016 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 7 May 2020 09:20:15 -0400
Subject: [PATCH 107/132] FIXME: WIP on leak detection

---
 gcc/analyzer/engine.cc        | 19 ++++++++++++++++++-
 gcc/analyzer/program-state.cc | 35 +++++++++++++++++++++++++++++------
 gcc/analyzer/program-state.h  |  2 ++
 3 files changed, 49 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index cec8dcf945b..be7a3411557 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -2570,6 +2570,7 @@ exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
 					sedge, change, custom_info);
   digraph<eg_traits>::add_edge (e);
 
+#if 0
   // TODO: detect leaks
   if (dest->get_state ().m_region_model2)
     {
@@ -2578,7 +2579,8 @@ exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
 				    dest->get_state (),
 				    m_ext_state);
     }
-  
+#endif
+
   return e;
 }
 
@@ -3039,6 +3041,8 @@ exploded_graph::process_node (exploded_node *node)
 		}
 	    prev_stmt = stmt;
 
+	    program_state old_state (next_state);
+
 	    /* Process the stmt.  */
 	    exploded_node::on_stmt_flags flags
 	      = node->on_stmt (*this, snode, stmt, &next_state, &change);
@@ -3048,6 +3052,19 @@ exploded_graph::process_node (exploded_node *node)
 	    if (flags.m_terminate_path)
 	      return;
 
+	    program_state::detect_leaks2 (old_state, next_state,
+					  get_ext_state ());
+
+	    unsigned next_idx = stmt_idx + 1;
+	    program_point next_point
+	      = (next_idx < point.get_supernode ()->m_stmts.length ()
+		 ? program_point::before_stmt (point.get_supernode (), next_idx,
+					       point.get_call_string ())
+		 : program_point::after_supernode (point.get_supernode (),
+						   point.get_call_string ()));
+	    next_state
+	      = next_state.prune_for_point (*this, next_point, &change);
+
 	    if (flags.m_sm_changes || flag_analyzer_fine_grained)
 	      break;
 	  }
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index a2e9e3b7063..2cee8a16c79 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1713,6 +1713,13 @@ program_state::prune_for_point2 (exploded_graph &eg,
 #endif
     }
 
+  /* FIXME.  Do this here rather than at add_edge, to cover the
+     fine-grained cases.  */
+  // FIXME: maybe only do this if anything was pruned
+#if 1
+  detect_leaks2 (*this, new_state, eg.get_ext_state ());
+#endif
+
   /* Purge unused svalues.  */
   /* FIXME: this makes no sense in the revamped model.
      Instead, we're interested in which svalues are no longer referenced
@@ -1903,7 +1910,7 @@ log_set_of_svalue2s (logger *logger, const char *name,
 }
 
 /* FIXME.  */
-
+// FIXME: do this at each fine-grained state, not just at edges
 void
 program_state::detect_leaks2 (const program_state &src_state,
 			      const program_state &dest_state,
@@ -1911,6 +1918,18 @@ program_state::detect_leaks2 (const program_state &src_state,
 {
   logger *logger = ext_state.get_logger ();
   LOG_SCOPE (logger);
+  if (logger)
+    {
+      pretty_printer *pp = logger->get_printer ();
+      logger->start_log_line ();
+      pp_string (pp, "src_state: ");
+      src_state.dump_to_pp (ext_state, true, false, pp);
+      logger->end_log_line ();
+      logger->start_log_line ();
+      pp_string (pp, "dest_state: ");
+      dest_state.dump_to_pp (ext_state, true, false, pp);
+      logger->end_log_line ();
+    }
 
   /* Get svalues reachable from each of src_state and dst_state.  */
   hash_set<const svalue2 *> src_svalues;
@@ -1931,14 +1950,18 @@ program_state::detect_leaks2 (const program_state &src_state,
       const svalue2 *sval = (*iter);
       if (!dest_svalues.contains (sval))
 	{
-	  pretty_printer pp1, pp2;
+	  pretty_printer pp1, pp2, pp3;
 	  pp_format_decoder (&pp1) = default_tree_printer;
 	  pp_format_decoder (&pp2) = default_tree_printer;
-	  sval->dump_to_pp (&pp1, true);
-	  sval->dump_to_pp (&pp2, false);
-	  error ("possible leak: %qs %qs",
+	  pp_format_decoder (&pp3) = default_tree_printer;
+	  pp_pointer (&pp1, sval);
+	  sval->dump_to_pp (&pp2, true);
+	  sval->dump_to_pp (&pp3, false);
+	  error ("possible leak: %qs, %qs %qs",
 		 pp_formatted_text (&pp1),
-		 pp_formatted_text (&pp2));
+		 pp_formatted_text (&pp2),
+		 pp_formatted_text (&pp3));
+	  // TODO: wire this up to the sm states
 	  //gcc_unreachable (); // TODO
 	}
     }
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 3338a24d680..a8e1562d419 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -346,7 +346,9 @@ public:
 
 #if __cplusplus >= 201103
   program_state (program_state &&other);
+#if 0
   program_state& operator= (program_state &&other); // doesn't seem to be used
+#endif
 #endif
 
   ~program_state ();
-- 
2.21.0

