From 233b58dbc75d5d0e90e643453db3b13ea2786612 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 30 Apr 2020 11:51:04 -0400
Subject: [PATCH 094/237] FIXME: handle sm-state changes from conditionals

---
 gcc/analyzer/engine.cc        | 20 +++++-----
 gcc/analyzer/program-state.cc | 33 ++++++++++++----
 gcc/analyzer/region-model2.cc | 71 +++++++++++++++++++++--------------
 gcc/analyzer/region-model2.h  | 36 +++++++++++++++---
 4 files changed, 109 insertions(+), 51 deletions(-)

diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index cafbc031a07..9d9307a646e 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -966,11 +966,11 @@ impl_region_model2_context::on_condition (tree lhs, enum tree_code op, tree rhs)
   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
     {
       const state_machine &sm = m_ext_state.get_sm (sm_idx);
-      impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
-			       m_old_state, m_new_state,
-			       m_change,
-			       m_old_state->m_checker_states[sm_idx],
-			       m_new_state->m_checker_states[sm_idx]);
+      impl_sm_context2 sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
+				m_old_state, m_new_state,
+				m_change,
+				m_old_state->m_checker_states2[sm_idx],
+				m_new_state->m_checker_states2[sm_idx]);
       sm.on_condition (&sm_ctxt,
 		       m_enode_for_diag->get_supernode (), m_stmt,
 		       lhs, op, rhs);
@@ -989,11 +989,11 @@ impl_region_model2_context::on_phi (const gphi *phi, tree rhs)
   FOR_EACH_VEC_ELT (m_new_state->m_checker_states, sm_idx, smap)
     {
       const state_machine &sm = m_ext_state.get_sm (sm_idx);
-      impl_sm_context sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
-			       m_old_state, m_new_state,
-			       m_change,
-			       m_old_state->m_checker_states[sm_idx],
-			       m_new_state->m_checker_states[sm_idx]);
+      impl_sm_context2 sm_ctxt (*m_eg, sm_idx, sm, m_enode_for_diag,
+				m_old_state, m_new_state,
+				m_change,
+				m_old_state->m_checker_states2[sm_idx],
+				m_new_state->m_checker_states2[sm_idx]);
       sm.on_phi (&sm_ctxt, m_enode_for_diag->get_supernode (), phi, rhs);
     }
 }
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 77f15827cd9..214efbd22d2 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1186,11 +1186,13 @@ program_state::hash () const
 bool
 program_state::operator== (const program_state &other) const
 {
-  if (!m_region_model)
-    return true; // FIXME
+  if (m_region_model)
+    if (!(*m_region_model == *other.m_region_model))
+      return false;
 
-  if (!(*m_region_model == *other.m_region_model))
-    return false;
+  if (m_region_model2)
+    if (!(*m_region_model2 == *other.m_region_model2))
+      return false;
 
   int i;
   sm_state_map *smap;
@@ -1401,9 +1403,22 @@ program_state::on_edge (exploded_graph &eg,
     }
   else if (m_region_model2)
     {
-      return m_region_model2->maybe_update_for_edge (*succ,
-						     last_stmt,
-						     NULL); // FIXME: ctxt!
+      impl_region_model2_context ctxt (eg, &enode,
+				      &enode.get_state (),
+				      this, change,
+				      last_stmt);
+      if (!m_region_model2->maybe_update_for_edge (*succ,
+						   last_stmt,
+						   &ctxt))
+	{
+	  logger * const logger = eg.get_logger ();
+	  if (logger)
+	    logger->log ("edge to SN: %i is impossible"
+			 " due to region_model2 constraints",
+			 succ->m_dest->m_index);
+	  return false;
+	}
+      return true;
     }
 
   impl_region_model_context ctxt (eg, &enode,
@@ -1600,6 +1615,10 @@ program_state::can_merge_with_p (const program_state &other,
      falsely rejecting merger opportunities for states where the
      only difference was in svalue_id ordering.  */
 
+  // FIXME:
+  if (m_region_model2)
+    return false;
+
   /* Attempt to merge the region_models.  */
 
   svalue_id_merger_mapping sid_mapping (*m_region_model,
diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 4aae073e73c..ccbea2468e5 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -1686,16 +1686,18 @@ region2::cmp_ptrs (const void *p1, const void *p2)
 bool
 region2::non_null_p (const region_model2 &model) const
 {
-#if 0
+#if 1
   /* FIXME: malloc is now simulated via a heap_allocated_region2.
      That said, maybe we do want the possibilty of NULL for symbolic
      regions too.  */
-  /* Are we within a symbolic_region2?  If so, it could be NULL.  */
+  /* Are we within a symbolic_region2?  If so, it could be NULL, and we
+     have to fall back on the constraints.  */
   if (const symbolic_region2 *sym_reg = dyn_cast_symbolic_region2 ())
     {
-      if (sym_reg->m_possibly_null)
-	return false;
+      return false; // TODO: really?
     }
+  if (get_kind () == RK_HEAP_ALLOCATED)
+    return false;
 #endif
 
   return true;
@@ -2719,6 +2721,14 @@ string_region2::dump_to_pp (pretty_printer *pp, bool simple) const
     }
 }
 
+/* class unknown_region2 : public region2.  */
+
+void
+unknown_region2::dump_to_pp (pretty_printer *pp, bool /*simple*/) const
+{
+  pp_string (pp, "UNKNOWN_REGION");
+}
+
 /* class region_model2_manager.  */
 
 region_model2_manager::region_model2_manager ()
@@ -2994,6 +3004,28 @@ region_model2_manager::get_region_for_string (tree string_cst)
   return reg;
 }
 
+/* If we see a tree code we don't know how to handle, rather than
+   ICE or generate bogus results, create a dummy region2, and notify
+   CTXT so that it can mark the new state as being not properly
+   modelled.  The exploded graph can then stop exploring that path,
+   since any diagnostics we might issue will have questionable
+   validity.  */
+
+region2 *
+region_model2_manager::
+get_region2_for_unexpected_tree_code (region_model2_context *ctxt,
+				      tree t,
+				      const dump_location_t &loc)
+{
+  gcc_assert (ctxt);
+  tree type = TYPE_P (t) ? t : TREE_TYPE (t);
+  region2 *new_reg
+    = new unknown_region2 (alloc_region_id (), &m_root_region, type); // FIXME
+  // or should this be something else?
+  ctxt->on_unexpected_tree_code (t, loc);
+  return new_reg;
+}
+
 /* FIXME.  */
 
 region2 *
@@ -4468,10 +4500,11 @@ region_model2::get_lvalue_1 (path_var pv,
   switch (TREE_CODE (expr))
     {
     default:
+#if 1
+      return m_mgr->get_region2_for_unexpected_tree_code (ctxt, expr,
+							  dump_location_t ());
+#else
       gcc_unreachable (); // FIXME
-#if 0
-      return make_region2_for_unexpected_tree_code (ctxt, expr,
-						   dump_location_t ());
 #endif
 
     case ARRAY_REF:
@@ -4608,26 +4641,6 @@ region_model2::get_lvalue_1 (path_var pv,
     }
 }
 
-/* If we see a tree code we don't know how to handle, rather than
-   ICE or generate bogus results, create a dummy region2, and notify
-   CTXT so that it can mark the new state as being not properly
-   modelled.  The exploded graph can then stop exploring that path,
-   since any diagnostics we might issue will have questionable
-   validity.  */
-#if 0
-region2 *
-region_model2::make_region2_for_unexpected_tree_code (region_model2_context *ctxt,
-						    tree t,
-						    const dump_location_t &loc)
-{
-  gcc_assert (ctxt);
-  region2 *new_reg
-    = add_region2 (new symbolic_region2 (m_root_reg, NULL_TREE, false));
-  ctxt->on_unexpected_tree_code (t, loc);
-  return new_reg;
-}
-#endif
-
 /* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op.  */
 
 static void
@@ -5310,6 +5323,7 @@ region_model2::add_constraint (tree lhs, enum tree_code op, tree rhs,
 	if (symbolic_region2 *sym_reg = pointee->dyn_cast_symbolic_region2 ())
 	  sym_reg->m_possibly_null = false;
       }
+#endif
 
   /* Notify the context, if any.  This exists so that the state machines
      in a program_state can be notified about the condition, and so can
@@ -5317,7 +5331,6 @@ region_model2::add_constraint (tree lhs, enum tree_code op, tree rhs,
      when synthesizing constraints as above.  */
   if (ctxt)
     ctxt->on_condition (lhs, op, rhs);
-#endif
 
   return true;
 }
@@ -5515,6 +5528,8 @@ region_model2::get_representative_tree (svalue2 *sval) const
       const region2 *reg = init_sval->get_region ();
       pvs.safe_push (reg->get_representative_path_var ());
     }
+  if (tree cst = sval->maybe_get_constant ())
+    pvs.safe_push (path_var (cst, 0));
 
   // TODO: sort; pick the best; handle the empty case
   return pvs[0].m_tree;
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index c1cff246f2b..4378a9eb820 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -756,7 +756,8 @@ namespace ana {
      offset_region2 (RK_OFFSET)
      heap_allocated_region2 (RK_HEAP_ALLOCATED)
      alloca_region2 (RK_ALLOCA)
-     string_region2 (RK_STRING).  */
+     string_region2 (RK_STRING)
+     unknown_region2 (RK_UNKNOWN).  */
 
 /* Abstract base class representing a chunk of memory.
 
@@ -793,7 +794,8 @@ public:
    RK_OFFSET,
    RK_HEAP_ALLOCATED,
    RK_ALLOCA,
-   RK_STRING
+   RK_STRING,
+   RK_UNKNOWN
   };
   static const char *kind_to_str (enum kind);
 
@@ -1520,6 +1522,28 @@ private:
   tree m_string_cst;
 };
 
+/* An unknown region, for handling unimplemented tree codes.  */
+
+class unknown_region2 : public region2
+{
+public:
+  unknown_region2 (unsigned id, region2 *parent, tree type)
+  : region2 (id, parent, type)
+  {}
+
+#if 0
+  bool compare_fields (const element_region2 &other) const;
+#endif
+  enum region2::kind get_kind () const FINAL OVERRIDE { return RK_UNKNOWN; }
+
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+protected:
+#if 0
+  void add_to_hash (inchash::hash &hstate) const OVERRIDE;
+#endif
+};
+
 /* A class responsible for owning and consolidating region2 and svalue2
    instances.    */
 
@@ -1560,6 +1584,10 @@ public:
   region2 *get_symbolic_region (svalue2 *sval);
   string_region2 *get_region_for_string (tree string_cst);
 
+  region2 *get_region2_for_unexpected_tree_code (region_model2_context *ctxt,
+						 tree t,
+						 const dump_location_t &loc);
+
   unsigned alloc_region_id () { return m_next_region_id++; }
 
   store2_manager *get_store2_manager () { return &m_store2_mgr; }
@@ -1847,10 +1875,6 @@ class region_model2
   void copy_array_region2 (region2_id dst_rid, array_region2 *dst_reg,
 			  array_region2 *src_reg, region_model2_context *ctxt);
 
-  region2_id make_region2_for_unexpected_tree_code (region_model2_context *ctxt,
-						  tree t,
-						  const dump_location_t &loc);
-
   void add_any_constraints_from_ssa_def_stmt (tree lhs,
 					      enum tree_code op,
 					      tree rhs,
-- 
2.26.2

