From b89c930b8de11accf7a33195dfe3d050b51ff02a Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 13 Apr 2020 21:23:20 -0400
Subject: [PATCH 026/237] FIXME: start reworking region subclasses

---
 gcc/analyzer/region-model2.cc | 158 ++++++++++++++++++++++++++--------
 gcc/analyzer/region-model2.h  |  88 +++++++++++++++----
 2 files changed, 191 insertions(+), 55 deletions(-)

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 15e6302f5da..fbf29bce590 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -65,9 +65,11 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace ana {
 
+#if 0
 static region2 *
 make_region_for_type (region2 *parent_reg, tree type,
 		      region_model2_context *ctxt);
+#endif
 
 /* Dump T to PP in language-independent form, for debugging/logging/dumping
    purposes.  */
@@ -220,13 +222,13 @@ svalue2::dump_dot_to_pp (const region_model2 &model,
 /* FIXME.  */
 
 DEBUG_FUNCTION void
-svalue2::dump () const
+svalue2::dump (bool simple) const
 {
   pretty_printer pp;
   pp_format_decoder (&pp) = default_tree_printer;
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   pp.buffer->stream = stderr;
-  dump_to_pp (&pp);
+  dump_to_pp (&pp, simple);
   pp_newline (&pp);
   pp_flush (&pp);
 }
@@ -248,13 +250,21 @@ svalue2::maybe_get_constant () const
 /* FIXME.  */
 
 void
-region_svalue2::dump_to_pp (pretty_printer *pp) const
+region_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
 {
-  pp_string (pp, "region_svalue2(");
-  print_quoted_type (pp, get_type ());
-  pp_string (pp, ", ");
-  m_reg->dump_to_pp (pp);
-  pp_string (pp, ")");
+  if (simple)
+    {
+      pp_string (pp, "&");
+      m_reg->dump_to_pp (pp, simple);
+    }
+  else
+    {
+      pp_string (pp, "region_svalue2(");
+      print_quoted_type (pp, get_type ());
+      pp_string (pp, ", ");
+      m_reg->dump_to_pp (pp, simple);
+      pp_string (pp, ")");
+    }
 }
 
 /* Compare the fields of this region_svalue2 with OTHER, returning true
@@ -466,13 +476,18 @@ region_svalue2::eval_condition (region_svalue2 *lhs,
 /* FIXME.  */
 
 void
-constant_svalue2::dump_to_pp (pretty_printer *pp) const
+constant_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
 {
-  pp_string (pp, "constant_svalue2(");
-  print_quoted_type (pp, get_type ());
-  pp_string (pp, ", ");
-  dump_tree (pp, m_cst_expr);
-  pp_string (pp, ")");
+  if (simple)
+    dump_tree (pp, m_cst_expr);
+  else
+    {
+      pp_string (pp, "constant_svalue2(");
+      print_quoted_type (pp, get_type ());
+      pp_string (pp, ", ");
+      dump_tree (pp, m_cst_expr);
+      pp_string (pp, ")");
+    }
 }
 
 /* Compare the fields of this constant_svalue2 with OTHER, returning true
@@ -664,6 +679,7 @@ region2::kind_to_str (enum kind kind)
     {
     default:
       gcc_unreachable ();
+#if 0
     case RK_PRIMITIVE:
       return "primitive";
     case RK_STRUCT:
@@ -672,6 +688,7 @@ region2::kind_to_str (enum kind kind)
       return "union";
     case RK_ARRAY:
       return "array";
+#endif
     case RK_FRAME:
       return "frame";
     case RK_GLOBALS:
@@ -686,8 +703,10 @@ region2::kind_to_str (enum kind kind)
       return "heap";
     case RK_ROOT:
       return "root";
+#if 0
     case RK_SYMBOLIC:
       return "symbolic";
+#endif
     }
 }
 
@@ -826,6 +845,14 @@ region2::operator== (const region2 &other) const
 	return this_sub.compare_fields (other_sub);
       }
 #endif
+    case RK_DECL:
+      {
+	const decl_region2 &this_sub
+	  = (const decl_region2 &)*this;
+	const decl_region2 &other_sub
+	  = (const decl_region2 &)other;
+	return this_sub.compare_fields (other_sub);
+      }
     case RK_FIELD:
       {
 	const field_region2 &this_sub
@@ -1308,20 +1335,14 @@ region2::dump_to_pp (const region_model2 &model,
 }
 #endif
 
-void
-region2::dump_to_pp (pretty_printer *pp) const
-{
-  pp_string (pp, "region2()"); // TODO: eliminate this base class impl
-}
-
 DEBUG_FUNCTION void
-region2::dump () const
+region2::dump (bool simple) const
 {
   pretty_printer pp;
   pp_format_decoder (&pp) = default_tree_printer;
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   pp.buffer->stream = stderr;
-  dump_to_pp (&pp);
+  dump_to_pp (&pp, simple);
   pp_newline (&pp);
   pp_flush (&pp);
 }
@@ -1956,6 +1977,7 @@ map_region2::get_value_by_name (tree identifier,
 
 /* class struct_or_union_region2 : public map_region2.  */
 
+#if 0
 /* Implementation of map_region2::valid_key_p vfunc for
    struct_or_union_region2.  */
 
@@ -2003,6 +2025,8 @@ union_region2::compare_fields (const union_region2 &other) const
 }
 #endif
 
+#endif
+
 /* class frame_region2 : public map_region2.  */
 
 /* Compare the fields of this frame_region2 with OTHER, returning true
@@ -2069,6 +2093,15 @@ globals_region2::compare_fields (const globals_region2 &other) const
 }
 #endif
 
+void
+globals_region2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    pp_string (pp, "::");
+  else
+    pp_string (pp, "globals");
+}
+
 /* Implementation of map_region2::valid_key_p vfunc for globals_region2.  */
 
 bool
@@ -2100,6 +2133,8 @@ code_region2::valid_key_p (tree key) const
 
 /* class array_region2 : public region2.  */
 
+#if 0
+
 /* array_region2's copy ctor.  */
 
 array_region2::array_region2 (const array_region2 &other)
@@ -2354,6 +2389,8 @@ array_region2::constant_from_key (key_t key)
   return build_int_cst (index_type, key);
 }
 
+#endif
+
 /* class function_region2 : public map_region2.  */
 
 /* Compare the fields of this function_region2 with OTHER, returning true
@@ -2684,6 +2721,12 @@ root_region2::compare_fields (const root_region2 &other) const
 }
 #endif
 
+void
+root_region2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  gcc_unreachable ();
+}
+
 /* Implementation of region2::print_fields vfunc for root_region2.  */
 #if 0
 void
@@ -3079,6 +3122,38 @@ symbolic_region2::print_fields (const region_model2 &model,
 }
 #endif
 
+/* class decl_region2 : public region2.  */
+
+void
+decl_region2::add_to_hash (inchash::hash &hstate) const
+{
+  region2::add_to_hash (hstate);
+  hstate.add_ptr (m_decl);
+}
+
+bool
+decl_region2::compare_fields (const decl_region2 &other) const
+{
+  return m_decl == other.m_decl;
+}
+
+void
+decl_region2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    pp_printf (pp, "%E", m_decl);
+  else
+    {
+      pp_string (pp, "decl_region2(");
+      get_parent_region ()->dump_to_pp (pp, simple);
+      pp_string (pp, ", ");
+      print_quoted_type (pp, get_type ());
+      pp_printf (pp, ", %qE)", m_decl);
+    }
+}
+
+/* class field_region2 : public region2.  */
+
 void
 field_region2::add_to_hash (inchash::hash &hstate) const
 {
@@ -3093,13 +3168,22 @@ field_region2::compare_fields (const field_region2 &other) const
 }
 
 void
-field_region2::dump_to_pp (pretty_printer *pp) const
+field_region2::dump_to_pp (pretty_printer *pp, bool simple) const
 {
-  pp_string (pp, "field_region2(");
-  get_parent_region ()->dump_to_pp (pp);
-  pp_string (pp, ", ");
-  print_quoted_type (pp, get_type ());
-  pp_printf (pp, ", %qE)", m_field);
+  if (simple)
+    {
+      get_parent_region ()->dump_to_pp (pp, simple);
+      pp_string (pp, ".");
+      pp_printf (pp, "%E", m_field);
+    }
+  else
+    {
+      pp_string (pp, "field_region2(");
+      get_parent_region ()->dump_to_pp (pp, simple);
+      pp_string (pp, ", ");
+      print_quoted_type (pp, get_type ());
+      pp_printf (pp, ", %qE)", m_field);
+    }
 }
 
 /* class region_model2_manager.  */
@@ -3132,17 +3216,17 @@ region_model2_manager::get_or_create_constant_svalue2 (tree cst_expr)
 
 /* FIXME.  */
 
-region2 *
+decl_region2 *
 region_model2_manager::get_region_for_global (tree expr,
 					      region_model2_context *ctxt)
 {
   gcc_assert (TREE_CODE (expr) == VAR_DECL);
 
-  region2 **slot = m_globals_map.get (expr);
+  decl_region2 **slot = m_globals_map.get (expr);
   if (slot)
     return *slot;
-  region2 *reg = make_region_for_type (&m_globals_region, TREE_TYPE (expr),
-				       ctxt);
+  decl_region2 *reg
+    = new decl_region2 (&m_globals_region, expr);
   m_globals_map.put (expr, reg);
   return reg;
 }
@@ -3399,9 +3483,9 @@ region_model2::dump_to_pp (pretty_printer *pp, bool summarize) const
 	pp_string (pp, ", ");
       region2 *reg = (*iter).first;
       svalue2 *sval = (*iter).second;
-      reg->dump_to_pp (pp);
+      reg->dump_to_pp (pp, summarize);
       pp_string (pp, ": ");
-      sval->dump_to_pp (pp);
+      sval->dump_to_pp (pp, summarize);
     }
 #if 0
   if (summarize)
@@ -3502,6 +3586,7 @@ region_model2::dump (FILE *fp, bool summarize) const
   pp_show_color (&pp) = pp_show_color (global_dc->printer);
   pp.buffer->stream = fp;
   dump_to_pp (&pp, summarize);
+  pp_newline (&pp);
   pp_flush (&pp);
 }
 
@@ -6052,7 +6137,7 @@ region_model2::replace_svalue2 (svalue2 *sval, svalue2 *new_sval)
 /* Make a region2 of an appropriate subclass for TYPE,
    with parent PARENT_REG, or return NULL for types we don't yet know
    how to handle.  */
-
+#if 0
 static region2 *
 make_region_for_type (region2 *parent_reg, tree type,
 		      region_model2_context *ctxt)
@@ -6090,6 +6175,7 @@ make_region_for_type (region2 *parent_reg, tree type,
 						dump_location_t ());
 #endif
 }
+#endif
 
 /* Helper class for region_model2::purge_unused_svalue2s.  */
 
@@ -6658,7 +6744,7 @@ region_model2::get_fndecl_for_call (const gcall *call,
 /* Dump a multiline representation of this merger to PP.  */
 #if 0
 void
-model_merger::dump_to_pp (pretty_printer *pp) const
+model_merger::dump_to_pp (pretty_printer *pp, bool simple) const
 {
   pp_string (pp, "model A:");
   pp_newline (pp);
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index 69905fb9d94..81e8542c949 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -49,7 +49,12 @@ along with GCC; see the file COPYING3.  If not see
    - should there still be a root_region?  or should those things go in the
      ext_state (or something owned by ext_state: region_model2_manager)
    Hopefully this is a huge simplification, and (I hope) avoids lots of heap
-   churn as states are copied.  */
+   churn as states are copied.
+
+   Other ideas:
+   - region subclasses no longer represent internal structure, but instead
+     represent how the regions are reached.  So e.g. a global
+     "struct coord c;" is now a decl_region, rather than a struct_region.  */
 
 /* A tree, extended with stack frame information for locals, so that
    we can distinguish between different values of locals within a potentially
@@ -169,8 +174,8 @@ public:
 			       pretty_printer *pp) const;
 #endif
 
-  virtual void dump_to_pp (pretty_printer *pp) const = 0;
-  void dump () const;
+  virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
+  void dump (bool simple=true) const;
 
   virtual region_svalue2 *dyn_cast_region_svalue2 () { return NULL; }
   virtual constant_svalue2 *dyn_cast_constant_svalue2 () { return NULL; }
@@ -221,7 +226,7 @@ public:
     FINAL OVERRIDE;
 #endif
 
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
   region_svalue2 *dyn_cast_region_svalue2 () FINAL OVERRIDE { return this; }
 
@@ -282,7 +287,7 @@ public:
 #endif
 
   enum kind get_kind () const FINAL OVERRIDE { return SK_CONSTANT; }
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 #if 0
   void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
@@ -344,7 +349,7 @@ public:
 #endif
 
   enum kind get_kind () const FINAL OVERRIDE { return SK_UNKNOWN; }
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 #if 0
   void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
@@ -391,7 +396,7 @@ public:
 #endif
 
   enum kind get_kind () const FINAL OVERRIDE { return SK_POISONED; }
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 #if 0
   void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
@@ -462,7 +467,7 @@ public:
 #endif
 
   enum kind get_kind () const FINAL OVERRIDE { return SK_SETJMP; }
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 #if 0
   void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
@@ -489,6 +494,10 @@ public:
    The class hierarchy looks like this (using indentation to show
    inheritance, and with region_kinds shown for the concrete subclasses):
 
+   FIXME: this needs a rewrite; reorganizing regions by identity, rather than
+   structure.  So e.g. a global "struct coord c;" is now a decl_region, rather
+   than a struct_region.
+
    region
      primitive_region (RK_PRIMITIVE)
      map_region
@@ -528,18 +537,19 @@ public:
      of region2.  */
   enum kind
   {
-   RK_PRIMITIVE,
-   RK_STRUCT,
-   RK_UNION,
+   //RK_PRIMITIVE,
+   //RK_STRUCT,
+   //RK_UNION,
    RK_FRAME,
    RK_GLOBALS,
    RK_CODE,
    RK_FUNCTION,
-   RK_ARRAY,
+   //RK_ARRAY,
    RK_STACK,
    RK_HEAP,
    RK_ROOT,
-   RK_SYMBOLIC,
+   //RK_SYMBOLIC,
+   RK_DECL,
    RK_FIELD
   };
   static const char *kind_to_str (enum kind);
@@ -589,8 +599,8 @@ public:
 		   const char *prefix,
 		   bool is_last_child) const;
 
-  virtual void dump_to_pp (pretty_printer *pp) const; // = 0;
-  void dump () const;
+  virtual void dump_to_pp (pretty_printer *pp, bool simple) const = 0;
+  void dump (bool simple) const;
 
 #if 0
   virtual void dump_child_label (const region_model2 &model,
@@ -643,6 +653,8 @@ is_a_helper <region *>::test (region *)
 
 namespace ana {
 
+#if 0
+
 /* Concrete region subclass for storing "primitive" types (integral types,
    pointers, etc).  */
 
@@ -660,6 +672,7 @@ public:
   enum region2::kind get_kind () const FINAL OVERRIDE { return RK_PRIMITIVE; }
 };
 
+#endif
 /* A region2 that has children identified by tree keys.
    For example a stack frame has subregion2s per local, and a region2
    for a struct has subregion2s per field.  */
@@ -742,6 +755,7 @@ is_a_helper <map_region2 *>::test (region2 *reg)
   return (reg->dyn_cast_map_region2 () != NULL);
 }
 
+#if 0
 namespace ana {
 
 /* Abstract subclass representing a region2 with fields
@@ -832,6 +846,8 @@ is_a_helper <union_region2 *>::test (region2 *reg)
   return reg->get_kind () == region2::RK_UNION;
 }
 
+#endif
+
 namespace ana {
 
 /* Abstract map_region2 subclass for accessing decls, used as a base class
@@ -925,6 +941,7 @@ class globals_region2 : public scope_region2
   region2 *clone () const FINAL OVERRIDE;
 #endif
   enum kind get_kind () const FINAL OVERRIDE { return RK_GLOBALS; }
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
   /* map_region2 vfuncs.  */
   bool valid_key_p (tree key) const FINAL OVERRIDE;
@@ -1026,6 +1043,7 @@ is_a_helper <function_region2 *>::test (region2 *reg)
   return reg->get_kind () == region2::RK_FUNCTION;
 }
 
+#if 0
 namespace ana {
 
 /* Concrete region2 subclass representing an array (or an array-like view
@@ -1244,6 +1262,8 @@ is_a_helper <heap_region2 *>::test (region2 *reg)
   return reg->get_kind () == region2::RK_HEAP;
 }
 
+#endif
+
 namespace ana {
 
 /* Concrete region2 subclass.  The root region2, containing all region2s
@@ -1263,6 +1283,7 @@ public:
 #endif
 
   enum kind get_kind () const FINAL OVERRIDE { return RK_ROOT; }
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 #if 0
   void dump_child_label (const region_model2 &model,
@@ -1333,6 +1354,7 @@ is_a_helper <root_region2 *>::test (region2 *reg)
 
 namespace ana {
 
+#if 0
 /* Concrete region2 subclass: a region2 to use when dereferencing an unknown
    pointer.  */
 
@@ -1366,6 +1388,34 @@ public:
   bool m_possibly_null;
 };
 
+#endif
+
+/* FIXME.  */
+
+class decl_region2 : public region2
+{
+public:
+  decl_region2 (region2 *parent, tree decl)
+  : region2 (parent, TREE_TYPE (decl)), m_decl (decl)
+  {}
+
+#if 0
+  region2 *clone () const FINAL OVERRIDE;
+#endif
+
+  bool compare_fields (const decl_region2 &other) const;
+
+  enum region2::kind get_kind () const FINAL OVERRIDE { return RK_DECL; }
+
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+protected:
+  void add_to_hash (inchash::hash &hstate) const OVERRIDE;
+
+private:
+  tree m_decl;
+};
+
 /* FIXME.  */
 
 class field_region2 : public region2
@@ -1383,7 +1433,7 @@ public:
 
   enum region2::kind get_kind () const FINAL OVERRIDE { return RK_FIELD; }
 
-  void dump_to_pp (pretty_printer *pp) const FINAL OVERRIDE;
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
 
 protected:
   void add_to_hash (inchash::hash &hstate) const OVERRIDE;
@@ -1405,8 +1455,8 @@ public:
 					   region_model2_context *ctxt);
   region2 *get_region_for_label (tree label,
 				 region_model2_context *ctxt);
-  region2 *get_region_for_global (tree expr,
-				 region_model2_context *ctxt);
+  decl_region2 *get_region_for_global (tree expr,
+				       region_model2_context *ctxt);
   region2 *get_field_region (region2 *parent, tree field,
 			     region_model2_context *ctxt);
 
@@ -1417,7 +1467,7 @@ private:
   constants_map_t m_constants_map;
 
   globals_region2 m_globals_region;
-  typedef hash_map<tree, region2 *> globals_map_t;
+  typedef hash_map<tree, decl_region2 *> globals_map_t;
   typedef globals_map_t::iterator globals_iterator_t;
   globals_map_t m_globals_map;
 
-- 
2.26.2

