From eb839598f923c78191f97cc92da2991f7ee42b23 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 16 Apr 2020 13:36:17 -0400
Subject: [PATCH 048/179] FIXME: implement symbolic_region2

---
 gcc/analyzer/region-model2.cc | 109 ++++++++++++++++++++++------------
 gcc/analyzer/region-model2.h  |  37 ++++++------
 2 files changed, 90 insertions(+), 56 deletions(-)

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index d128cf4b460..0e3aa2f7c63 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -2654,15 +2654,6 @@ root_region2::get_value_by_name (tree identifier,
 
 /* class symbolic_region2 : public map_region2.  */
 
-#if 0
-/* symbolic_region2's copy ctor.  */
-
-symbolic_region2::symbolic_region2 (const symbolic_region2 &other)
-: region2 (other),
-  m_possibly_null (other.m_possibly_null)
-{
-}
-
 /* Compare the fields of this symbolic_region2 with OTHER, returning true
    if they are equal.
    For use by region2::operator==.  */
@@ -2670,11 +2661,34 @@ symbolic_region2::symbolic_region2 (const symbolic_region2 &other)
 bool
 symbolic_region2::compare_fields (const symbolic_region2 &other) const
 {
-  return m_possibly_null == other.m_possibly_null;
+  return m_sval_ptr == other.m_sval_ptr;
+}
+
+/* FIXME.  */
+
+void
+symbolic_region2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    {
+      pp_string (pp, "*");
+      m_sval_ptr->dump_to_pp (pp, simple);
+    }
+  else
+    {
+      pp_string (pp, "symbolic_region2(");
+      get_parent_region ()->dump_to_pp (pp, simple);
+      pp_string (pp, ", ");
+      print_quoted_type (pp, get_type ());
+      pp_string (pp, ", ");
+      m_sval_ptr->dump_to_pp (pp, simple);
+      pp_string (pp, ")");
+    }
 }
 
 /* Implementation of region2::print_fields vfunc for symbolic_region2.  */
 
+#if 0
 void
 symbolic_region2::print_fields (const region_model2 &model,
 			       region2_id this_reg,
@@ -2928,6 +2942,8 @@ region_model2_manager::region_model2_manager ()
   // TODO
 }
 
+/* svalue2 consolidation.  */
+
 /* Return an svalue2 *for a constant_svalue2 for CST_EXPR,
    creating the constant_svalue2 if necessary.
    The constant_svalue2 instances are reused, based on pointer equality
@@ -2946,6 +2962,35 @@ region_model2_manager::get_or_create_constant_svalue2 (tree cst_expr)
   // TODO: cst equality vs tree pointer equality?
 }
 
+svalue2 *
+region_model2_manager::get_or_create_initial_value (const region2 *reg)
+{
+  if (initial_svalue2 **slot = m_initial_values_map.get (reg))
+    return *slot;
+  initial_svalue2 *initial_sval = new initial_svalue2 (reg->get_type (), reg);
+  m_initial_values_map.put (reg, initial_sval);
+  return initial_sval;
+}
+
+svalue2 *
+region_model2_manager::get_ptr_svalue2 (tree ptr_type, region2 *pointee)
+{
+  /* If this is a symbolic region from dereferencing a pointer, and the types
+     match, then return the original pointer.  */
+  if (symbolic_region2 *sym_reg = pointee->dyn_cast_symbolic_region2 ())
+    if (ptr_type == sym_reg->get_pointer ()->get_type ())
+      return sym_reg->get_pointer ();
+
+  // FIXME: use ptr_type here:
+  if (region_svalue2 **slot = m_pointer_values_map.get (pointee))
+    return *slot;
+  region_svalue2 *sval = new region_svalue2 (ptr_type, pointee);
+  m_pointer_values_map.put (pointee, sval);
+  return sval;
+}
+
+/* region2 consolidation.  */
+
 /* FIXME.  */
 
 decl_region2 *
@@ -2996,6 +3041,17 @@ region_model2_manager::get_frame_region (frame_region2 *calling_frame,
   return const_cast <frame_region2 *> (m_frames.consolidate (frame_reg));
 }
 
+region2 *
+region_model2_manager::get_symbolic_region (svalue2 *sval)
+{
+  // FIXME: should only alloc_region_id if consolidation fails
+  region2 *reg
+    = new symbolic_region2 (alloc_region_id (), &m_root_region, sval);
+  return const_cast <region2 *> (m_symbolic_regions.consolidate (reg));
+}
+
+/* binding consolidation.  */
+
 const concrete_binding2 *
 region_model2_manager::get_concrete_binding (const region2 *reg,
 					     enum binding_key2::kind kind,
@@ -3015,27 +3071,6 @@ region_model2_manager::get_symbolic_binding (const region2 *reg,
   return m_symbolic_binding_key_mgr.consolidate (b);
 }
 
-svalue2 *
-region_model2_manager::get_or_create_initial_value (const region2 *reg)
-{
-  if (initial_svalue2 **slot = m_initial_values_map.get (reg))
-    return *slot;
-  initial_svalue2 *initial_sval = new initial_svalue2 (reg->get_type (), reg);
-  m_initial_values_map.put (reg, initial_sval);
-  return initial_sval;
-}
-
-svalue2 *
-region_model2_manager::get_ptr_svalue2 (tree ptr_type, region2 *pointee)
-{
-  // FIXME: use ptr_type here:
-  if (region_svalue2 **slot = m_pointer_values_map.get (pointee))
-    return *slot;
-  region_svalue2 *sval = new region_svalue2 (ptr_type, pointee);
-  m_pointer_values_map.put (pointee, sval);
-  return sval;
-}
-
 /* class region_model2.  */
 
 /* FIXME: region_model2's default ctor.  */
@@ -4922,10 +4957,10 @@ region_model2::deref_rvalue (svalue2 *ptr_sval, region_model2_context *ctxt)
 	return region2_sval->get_pointee ();
       }
 
-#if 0
     case svalue2::SK_CONSTANT:
       goto create_symbolic_region2;
 
+#if 0
     case svalue2::SK_POISONED:
       {
 	if (ctxt)
@@ -4938,16 +4973,17 @@ region_model2::deref_rvalue (svalue2 *ptr_sval, region_model2_context *ctxt)
 	    }
 	goto create_symbolic_region2;
       }
+#endif
 
     case svalue2::SK_UNKNOWN:
       {
       create_symbolic_region2:
 	/* We need a symbolic_region2 to represent this unknown region2.
+	   FIXME:
 	   We don't know if it on the heap, stack, or a global,
 	   so use the root region2 as parent.  */
-	region2 *new_reg
-	  = add_region2 (new symbolic_region2 (m_root_reg, NULL_TREE, false));
-
+	region2 *new_reg = m_mgr->get_symbolic_region (ptr_sval);
+#if 0
 	/* We need to write the region2 back into the pointer,
 	   or we'll get a new, different region2 each time.
 	   We do this by changing the meaning of ptr_sval, replacing
@@ -4958,13 +4994,12 @@ region_model2::deref_rvalue (svalue2 *ptr_sval, region_model2_context *ctxt)
 	svalue2 *ptr_val
 	  = new region_svalue2 (ptr_sval->get_type (), new_reg);
 	replace_svalue2 (ptr_sval, ptr_val);
-
+#endif
 	return new_reg;
       }
 
     case svalue2::SK_SETJMP:
       goto create_symbolic_region2;
-#endif
     }
 
   gcc_unreachable ();
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index 15ee9ef6bc4..49d168f7f37 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -601,7 +601,7 @@ public:
    RK_STACK,
    RK_HEAP,
    RK_ROOT,
-   //RK_SYMBOLIC,
+   RK_SYMBOLIC,
    RK_DECL,
    RK_FIELD,
    RK_ELEMENT
@@ -1180,18 +1180,15 @@ is_a_helper <root_region2 *>::test (region2 *reg)
 
 namespace ana {
 
-#if 0
 /* Concrete region2 subclass: a region2 to use when dereferencing an unknown
    pointer.  */
 
 class symbolic_region2 : public region2
 {
 public:
-  symbolic_region2 (unsigned id, region2 *parent, tree type, bool possibly_null)
-  : region2 (parent, type),
-    m_possibly_null (possibly_null)
+  symbolic_region2 (unsigned id, region2 *parent, svalue2 *sval_ptr)
+  : region2 (id, parent, TREE_TYPE (sval_ptr->get_type ()))
   {}
-  symbolic_region2 (const symbolic_region2 &other);
 
   const symbolic_region2 *dyn_cast_symbolic_region2 () const FINAL OVERRIDE
   { return this; }
@@ -1200,22 +1197,21 @@ public:
 
   bool compare_fields (const symbolic_region2 &other) const;
 
-#if 0
-  region2 *clone () const FINAL OVERRIDE;
-#endif
+  enum kind get_kind () const FINAL OVERRIDE { return region2::RK_SYMBOLIC; }
+
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
-  enum kind get_kind () const FINAL OVERRIDE { return RK_SYMBOLIC; }
+  svalue2 *get_pointer () const { return m_sval_ptr; }
 
 #if 0
   void print_fields (const region_model2 &model,
 		     pretty_printer *pp) const FINAL OVERRIDE;
 #endif
 
-  bool m_possibly_null;
+private:
+  svalue2 *m_sval_ptr;
 };
 
-#endif
-
 /* FIXME.  */
 
 class decl_region2 : public region2
@@ -1454,8 +1450,12 @@ class region_model2_manager
 public:
   region_model2_manager ();
 
+  /* svalue2 consolidation.  */
   svalue2 *get_or_create_constant_svalue2 (tree cst_expr);
+  svalue2 *get_or_create_initial_value (const region2 *reg);
+  svalue2 *get_ptr_svalue2 (tree ptr_type, region2 *pointee);
 
+  /* region2 consolidation.  */
   function_region2 *get_region_for_fndecl (tree fndecl,
 					   region_model2_context *ctxt);
   region2 *get_region_for_label (tree label,
@@ -1468,10 +1468,13 @@ public:
 			       tree element_type,
 			       svalue2 *index,
 			       region_model2_context *ctxt);
-
   frame_region2 *get_frame_region (frame_region2 *calling_frame,
 				   function *fun);
+  region2 *get_symbolic_region (svalue2 *sval);
+
+  unsigned alloc_region_id () { return m_next_region_id++; }
 
+  /* binding consolidation.  */
   const concrete_binding2 *
   get_concrete_binding (const region2 *region,
 			enum binding_key2::kind kind,
@@ -1482,11 +1485,6 @@ public:
 			enum binding_key2::kind kind,
 			region2 *concrete_offset_region);
 
-  svalue2 *get_or_create_initial_value (const region2 *reg);
-  svalue2 *get_ptr_svalue2 (tree ptr_type, region2 *pointee);
-
-  unsigned alloc_region_id () { return m_next_region_id++; }
-
 private:
   unsigned m_next_region_id;
   root_region2 m_root_region;
@@ -1519,6 +1517,7 @@ private:
 #endif
   uniq_manager<region2> m_elements;
   uniq_manager<frame_region2> m_frames;
+  uniq_manager<region2> m_symbolic_regions;
 
   uniq_manager<concrete_binding2> m_concrete_binding_key_mgr;
   uniq_manager<symbolic_binding2> m_symbolic_binding_key_mgr;
-- 
2.21.0

