From f4ab6a3a00bb9c17a0b5a14221be5b24489de30e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 22 May 2019 14:55:48 -0400
Subject: [PATCH 62/66] FIXME: 2019-05-22 work on region model

---
 gcc/analyzer/impl-4.cc | 164 ++++++++++++++++++++++++++++---------------------
 1 file changed, 93 insertions(+), 71 deletions(-)

diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index 2363421..623cd55 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -584,13 +584,17 @@ namespace impl_4 {
 /* Map from var to state machine state, also capturing the origin of
    each state.  */
 
+template<typename Expr_T>
 class sm_state_map
 {
 public:
+  typedef Expr_T expr_t;
+
+  /* An entry in a hash_map.  */
   struct entry_t
   {
     entry_t (state_machine::state_t state,
-	     path_var origin)
+	     expr_t origin)
     : m_state (state), m_origin (origin)
     {}
 
@@ -605,10 +609,10 @@ public:
     }
 
     state_machine::state_t m_state;
-    path_var m_origin;
+    expr_t m_origin;
   };
-  typedef hash_map <path_var, entry_t> map_t;
-  typedef map_t::iterator iterator_t;
+  typedef hash_map <expr_t, entry_t> map_t;
+  typedef typename map_t::iterator iterator_t;
 
   sm_state_map *clone () const;
 
@@ -625,17 +629,17 @@ public:
     return !(*this == other);
   }
 
-  state_machine::state_t get_state (path_var pv) const;
-  path_var get_origin (path_var pv) const;
+  state_machine::state_t get_state (expr_t pv) const;
+  expr_t get_origin (expr_t pv) const;
 
-  void set_state (path_state *ps, path_var pv, state_machine::state_t state,
-		  path_var origin);
+  void set_state (path_state *ps, expr_t pv, state_machine::state_t state,
+		  expr_t origin);
   void set_state (const psn::equiv_class &ec,
 		  state_machine::state_t state,
-		  path_var origin);
-  void impl_set_state (path_var pv,
+		  expr_t origin);
+  void impl_set_state (expr_t pv,
 		       state_machine::state_t state,
-		       path_var origin);
+		       expr_t origin);
 
   void purge_stack_frame (int callee_stack_depth);
 
@@ -698,7 +702,7 @@ public:
 
   region_model *m_region_model;
 
-  auto_delete_vec<sm_state_map> m_checker_states;
+  auto_delete_vec<sm_state_map<path_var> > m_checker_states;
 };
 
 /* A <program_point, program_state> pair, used internally by
@@ -1878,19 +1882,21 @@ program_point::get_stmt () const
 
 /* FIXME.  */
 
-sm_state_map *
-sm_state_map::clone () const
+template <typename Expr_T>
+sm_state_map<Expr_T> *
+sm_state_map<Expr_T>::clone () const
 {
   return new sm_state_map (*this);
 }
 
 /* FIXME.  */
 
+template <typename Expr_T>
 void
-sm_state_map::print (const state_machine &sm, pretty_printer *pp) const
+sm_state_map<Expr_T>::print (const state_machine &sm, pretty_printer *pp) const
 {
   pp_string (pp, "{");
-  for (map_t::iterator iter = m_map.begin ();
+  for (typename map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
     {
@@ -1909,8 +1915,9 @@ sm_state_map::print (const state_machine &sm, pretty_printer *pp) const
 
 /* FIXME.  */
 
+template <typename Expr_T>
 std::string
-sm_state_map::to_str (const state_machine &sm) const
+sm_state_map<Expr_T>::to_str (const state_machine &sm) const
 {
   pretty_printer pp;
   print (sm, &pp);
@@ -1919,19 +1926,21 @@ sm_state_map::to_str (const state_machine &sm) const
 
 /* FIXME.  */
 
+template <typename Expr_T>
 bool
-sm_state_map::is_empty_p () const
+sm_state_map<Expr_T>::is_empty_p () const
 {
   return m_map.elements () == 0;
 }
 
 /* FIXME.  */
 
+template <typename Expr_T>
 hashval_t
-sm_state_map::hash () const
+sm_state_map<Expr_T>::hash () const
 {
   inchash::hash hstate;
-  for (map_t::iterator iter = m_map.begin ();
+  for (typename map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
     {
@@ -1946,13 +1955,14 @@ sm_state_map::hash () const
 
 /* FIXME.  */
 
+template <typename Expr_T>
 bool
-sm_state_map::operator== (const sm_state_map &other) const
+sm_state_map<Expr_T>::operator== (const sm_state_map &other) const
 {
   if (m_map.elements () != other.m_map.elements ())
     return false;
 
-  for (map_t::iterator iter = m_map.begin ();
+  for (typename map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
     {
@@ -1969,8 +1979,9 @@ sm_state_map::operator== (const sm_state_map &other) const
 
 /* FIXME.  */
 
+template <typename Expr_T>
 state_machine::state_t
-sm_state_map::get_state (path_var pv) const
+sm_state_map<Expr_T>::get_state (Expr_T pv) const
 {
   if (entry_t *slot
       = const_cast <map_t &> (m_map).get (pv))
@@ -1981,8 +1992,9 @@ sm_state_map::get_state (path_var pv) const
 
 /* FIXME.  */
 
-path_var
-sm_state_map::get_origin (path_var pv) const
+template <typename Expr_T>
+Expr_T
+sm_state_map<Expr_T>::get_origin (Expr_T pv) const
 {
   entry_t *slot
     = const_cast <map_t &> (m_map).get (pv);
@@ -1992,11 +2004,12 @@ sm_state_map::get_origin (path_var pv) const
 
 /* FIXME.  */
 
+template <typename Expr_T>
 void
-sm_state_map::set_state (path_state *ps,
-			 path_var pv,
+sm_state_map<Expr_T>::set_state (path_state *ps,
+			 Expr_T pv,
 			 state_machine::state_t state,
-			 path_var origin)
+			 Expr_T origin)
 {
   psn::equiv_class &ec = ps->get_equiv_class (pv);
   set_state (ec, state, origin);
@@ -2004,22 +2017,24 @@ sm_state_map::set_state (path_state *ps,
 
 /* FIXME.  */
 
+template <typename Expr_T>
 void
-sm_state_map::set_state (const psn::equiv_class &ec,
+sm_state_map<Expr_T>::set_state (const psn::equiv_class &ec,
 			 state_machine::state_t state,
-			 path_var origin)
+			 Expr_T origin)
 {
   int i;
-  path_var *pv;
+  Expr_T *pv;
   FOR_EACH_VEC_ELT (ec.m_vars, i, pv)
     impl_set_state (*pv, state, origin);
 }
 
 /* Set state of PV to STATE, bypassing equivalence classes.  */
 
+template <typename Expr_T>
 void
-sm_state_map::impl_set_state (path_var pv, state_machine::state_t state,
-			      path_var origin)
+sm_state_map<Expr_T>::impl_set_state (Expr_T pv, state_machine::state_t state,
+				      Expr_T origin)
 {
   /* Special-case state 0 as the default value.  */
   if (state == 0)
@@ -2033,19 +2048,20 @@ sm_state_map::impl_set_state (path_var pv, state_machine::state_t state,
 
 /* FIXME.  */
 
+template <typename Expr_T>
 void
-sm_state_map::purge_stack_frame (int callee_stack_depth)
+sm_state_map<Expr_T>::purge_stack_frame (int callee_stack_depth)
 {
   /* FIXME: not sure how to safely remove during a traversal, so for now
      do it in two stages.  */
-  auto_vec <path_var> keys;
-  for (map_t::iterator iter = m_map.begin ();
+  auto_vec <Expr_T> keys;
+  for (typename map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
     keys.safe_push ((*iter).first);
 
   int i;
-  path_var *pv;
+  Expr_T *pv;
   FOR_EACH_VEC_ELT (keys, i, pv)
     if (pv->m_stack_depth >= callee_stack_depth)
       m_map.remove (*pv);
@@ -2053,11 +2069,13 @@ sm_state_map::purge_stack_frame (int callee_stack_depth)
 
 /* FIXME.  */
 
+template <>
 void
-sm_state_map::purge_for_unknown_fncall (const exploded_graph &eg,
-					const state_machine &sm,
-					const gcall *call, tree fndecl,
-					path_state *new_ps)
+sm_state_map<path_var>::purge_for_unknown_fncall (const exploded_graph &eg,
+						  const state_machine &sm,
+						  const gcall *call,
+						  tree fndecl,
+						  path_state *new_ps)
 {
   if (fndecl)
     eg.log ("function %qE is unknown to checker %qs",
@@ -2099,14 +2117,15 @@ sm_state_map::purge_for_unknown_fncall (const exploded_graph &eg,
 	       0, path_var (NULL_TREE, 0));
 }
 
+template <>
 int
-sm_state_map::purge (const state_machine &sm,
-		     const psn::purge_criteria &p)
+sm_state_map<path_var>::purge (const state_machine &sm,
+			       const psn::purge_criteria &p)
 {
   /* FIXME: not sure how to safely remove during a traversal, so for now
      do it in two stages.  */
   auto_vec<path_var> to_remove;
-  for (map_t::iterator iter = m_map.begin ();
+  for (typename map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
     {
@@ -2138,8 +2157,8 @@ public:
 		      old state, rather than the new?  */
 		   program_state *new_state,
 
-		   const sm_state_map &old_smap,
-		   sm_state_map *new_smap,
+		   const sm_state_map<path_var> &old_smap,
+		   sm_state_map<path_var> *new_smap,
 
 		   stmt_finder *stmt_finder = NULL)
   : log_user (eg.get_logger ()), m_eg (eg), m_sm (sm), m_node (node),
@@ -2196,8 +2215,8 @@ public:
   const state_machine &m_sm;
   const exploded_node *m_node;
   program_state *m_new_state;
-  const sm_state_map &m_old_smap;
-  sm_state_map *m_new_smap;
+  const sm_state_map<path_var> &m_old_smap;
+  sm_state_map<path_var> *m_new_smap;
   impl_4::stmt_finder *m_stmt_finder;
 };
 
@@ -2214,7 +2233,7 @@ program_state::program_state (const extrinsic_state &ext_state)
 
   int num_states = ext_state.m_checkers.length ();
   for (int i = 0; i < num_states; i++)
-    m_checker_states.safe_push (new sm_state_map ());
+    m_checker_states.safe_push (new sm_state_map<path_var> ());
 }
 
 /* FIXME.  */
@@ -2226,7 +2245,7 @@ program_state::program_state (const program_state &other)
 		  : NULL)
 {
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
     m_checker_states.safe_push (smap->clone ());
 }
@@ -2248,7 +2267,7 @@ program_state::operator= (const program_state &other)
   gcc_assert (m_checker_states.length () == 0);
 
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (other.m_checker_states, i, smap)
     m_checker_states.safe_push (smap->clone ());
 
@@ -2266,7 +2285,7 @@ program_state::hash () const
     result ^= m_region_model->hash ();
 
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
     result ^= smap->hash ();
   return result;
@@ -2291,7 +2310,7 @@ program_state::operator== (const program_state &other) const
     return false;
 
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
     if (!(*smap == *other.m_checker_states[i]))
       return false;
@@ -2315,7 +2334,7 @@ program_state::print (const extrinsic_state &ext_state,
     }
 
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (m_checker_states, i, smap)
     {
       if (!smap->is_empty_p ())
@@ -2377,7 +2396,7 @@ public:
 	/* Don't purge vars that have sm state, to avoid
 	   losing leak complaints.  */
 	int i;
-	sm_state_map *smap;
+	sm_state_map<path_var> *smap;
 	FOR_EACH_VEC_ELT (m_old_state.m_checker_states, i, smap)
 	  {
 	    const state_machine &sm = m_ext_state.get_sm (i);
@@ -2432,7 +2451,7 @@ program_state::prune_for_point (exploded_graph &eg,
 
   // FIXME: state maps also
   int i;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   int num_sm_purged = 0;
   FOR_EACH_VEC_ELT (new_state.m_checker_states, i, smap)
     {
@@ -2622,12 +2641,13 @@ exploded_node::on_stmt (exploded_graph &eg) const
   input_location = stmt->location;
 
   int sm_idx;
-  sm_state_map *smap;
+  sm_state_map<path_var> *smap;
   FOR_EACH_VEC_ELT (old_state.m_checker_states, sm_idx, smap)
     {
       const state_machine &sm = m_ext_state.get_sm (sm_idx);
-      const sm_state_map &old_smap = *old_state.m_checker_states[sm_idx];
-      sm_state_map *new_smap = new_state.m_checker_states[sm_idx];
+      const sm_state_map<path_var> &old_smap
+	= *old_state.m_checker_states[sm_idx];
+      sm_state_map<path_var> *new_smap = new_state.m_checker_states[sm_idx];
       impl_sm_context ctxt (eg, sm, this,
 			    &new_state,
 			    old_smap, new_smap);
@@ -2845,8 +2865,8 @@ exploded_node::copy_sm_state (const exploded_graph &eg,
   for (unsigned i = 0; i < ext_state.m_checkers.length (); i++)
     {
       const state_machine &sm = ext_state.get_sm (i);
-      const sm_state_map *src_smap = old_state.m_checker_states[i];
-      sm_state_map *dst_smap = new_state->m_checker_states[i];
+      const sm_state_map<path_var> *src_smap = old_state.m_checker_states[i];
+      sm_state_map<path_var> *dst_smap = new_state->m_checker_states[i];
       state_machine::state_t rhs_state = src_smap->get_state (rhs);
       dst_smap->set_state (&new_state->m_path_state, lhs, rhs_state, rhs);
       if (eg.get_logger ())
@@ -3104,7 +3124,7 @@ exploded_node::detect_leaks (exploded_graph &eg) const
       leak_stmt_finder stmt_finder (eg, best_pv);
 
       int i;
-      sm_state_map *smap;
+      sm_state_map<path_var> *smap;
       FOR_EACH_VEC_ELT (old_state.m_checker_states, i, smap)
 	{
 	  const state_machine &sm = m_ext_state.get_sm (i);
@@ -3296,7 +3316,7 @@ program_state::on_edge (exploded_graph &eg,
   /* Pass the edge to the various state machines to see if any transitions
      or warnings occur.  */
   int i;
-  sm_state_map *old_smap;
+  sm_state_map<path_var> *old_smap;
   FOR_EACH_VEC_ELT (old_state.m_checker_states, i, old_smap)
     {
       const state_machine &sm = eg.get_ext_state ().get_sm (i);
@@ -3851,9 +3871,11 @@ diagnostic_manager::emit_saved_diagnostic (const exploded_graph &eg,
       for (unsigned i = 0; i < ext_state.m_checkers.length (); i++)
 	{
 	  const state_machine &sm = ext_state.get_sm (i);
-	  const sm_state_map &src_smap = *src_state.m_checker_states[i];
-	  const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
-	  for (sm_state_map::iterator_t iter = dst_smap.begin ();
+	  const sm_state_map<path_var> &src_smap
+	    = *src_state.m_checker_states[i];
+	  const sm_state_map<path_var> &dst_smap
+	    = *dst_state.m_checker_states[i];
+	  for (sm_state_map<path_var>::iterator_t iter = dst_smap.begin ();
 	       iter != dst_smap.end ();
 	       ++iter)
 	    {
@@ -5600,7 +5622,7 @@ test_sm_state_map ()
 
   /* Test setting states on path_var instances directly.  */
   {
-    impl_4::sm_state_map map;
+    impl_4::sm_state_map<path_var> map;
     ASSERT_TRUE (map.is_empty_p ());
     ASSERT_EQ (map.get_state (x0), 0);
 
@@ -5620,7 +5642,7 @@ test_sm_state_map ()
 
   /* Test setting states via equivalence classes.  */
   {
-    impl_4::sm_state_map map;
+    impl_4::sm_state_map<path_var> map;
     ASSERT_TRUE (map.is_empty_p ());
     ASSERT_EQ (map.get_state (x0), 0);
     ASSERT_EQ (map.get_state (y0), 0);
@@ -5639,9 +5661,9 @@ test_sm_state_map ()
 
   /* Test equality and hashing.  */
   {
-    impl_4::sm_state_map map0;
-    impl_4::sm_state_map map1;
-    impl_4::sm_state_map map2;
+    impl_4::sm_state_map<path_var> map0;
+    impl_4::sm_state_map<path_var> map1;
+    impl_4::sm_state_map<path_var> map2;
 
     ASSERT_EQ (map0.hash (), map1.hash ());
     ASSERT_EQ (map0, map1);
-- 
1.8.5.3

