From eac5007753e774b8f102a6304e1fc78f8b779943 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 28 Apr 2020 19:06:13 -0400
Subject: [PATCH 086/237] FIXME: initial implementation of labels

---
 gcc/analyzer/analyzer.h       |   1 +
 gcc/analyzer/region-model2.cc | 101 +++++++++++++++++-----------------
 gcc/analyzer/region-model2.h  |  50 ++++++++++++++---
 3 files changed, 93 insertions(+), 59 deletions(-)

diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index ee416f0e347..a1141765332 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -63,6 +63,7 @@ class svalue2;
   class initial_svalue2;
 class region2;
   class function_region2;
+  class label_region2;
   class symbolic_region2;
   class element_region2;
   class offset_region2;
diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 1c4155f05ee..6e1d279e1cd 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -1927,7 +1927,7 @@ code_region2::dump_to_pp (pretty_printer *pp, bool simple) const
     pp_string (pp, "code_region2()");
 }
 
-/* class function_region2 : public map_region2.  */
+/* class function_region2 : public region2.  */
 
 /* Compare the fields of this function_region2 with OTHER, returning true
    if they are equal.
@@ -1957,15 +1957,24 @@ function_region2::dump_to_pp (pretty_printer *pp, bool simple) const
     }
 }
 
-/* Implementation of map_region2::valid_key_p vfunc for function_region2.  */
+/* class label_region2 : public region2.  */
 
-#if 0
-bool
-function_region2::valid_key_p (tree key) const
+/* FIXME.  */
+
+void
+label_region2::dump_to_pp (pretty_printer *pp, bool simple) const
 {
-  return TREE_CODE (key) == LABEL_DECL;
+  if (simple)
+    {
+      dump_quoted_tree (pp, m_label);
+    }
+  else
+    {
+      pp_string (pp, "label_region2(");
+      dump_quoted_tree (pp, m_label);
+      pp_string (pp, ")");
+    }
 }
-#endif
 
 /* class stack_region2 : public region2.  */
 
@@ -2702,7 +2711,7 @@ region_model2_manager::region_model2_manager ()
   m_stack_region (alloc_region_id (), &m_root_region),
   m_heap_region (alloc_region_id (), &m_root_region),
   m_code_region (alloc_region_id (), &m_root_region),
-  m_fndecls_map (),
+  m_fndecls_map (), m_labels_map (),
   m_globals_region (alloc_region_id (), &m_root_region),
   m_globals_map ()
 {
@@ -2732,6 +2741,9 @@ region_model2_manager::~region_model2_manager ()
   for (fndecls_map_t::iterator iter = m_fndecls_map.begin ();
        iter != m_fndecls_map.end (); ++iter)
     delete (*iter).second;
+  for (labels_map_t::iterator iter = m_labels_map.begin ();
+       iter != m_labels_map.end (); ++iter)
+    delete (*iter).second;
   for (globals_map_t::iterator iter = m_globals_map.begin ();
        iter != m_globals_map.end (); ++iter)
     delete (*iter).second;
@@ -2843,6 +2855,28 @@ region_model2_manager::get_region_for_fndecl (tree fndecl,
 
 /* FIXME.  */
 
+label_region2 *
+region_model2_manager::get_region_for_label (tree label,
+					     region_model2_context *ctxt)
+{
+  gcc_assert (TREE_CODE (label) == LABEL_DECL);
+
+  label_region2 **slot = m_labels_map.get (label);
+  if (slot)
+    return *slot;
+
+  tree fndecl = DECL_CONTEXT (label);
+  gcc_assert (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL);
+
+  function_region2 *func_reg = get_region_for_fndecl (fndecl, ctxt);
+  label_region2 *reg
+    = new label_region2 (alloc_region_id (), func_reg, label);
+  m_labels_map.put (label, reg);
+  return reg;
+}
+
+/* FIXME.  */
+
 decl_region2 *
 region_model2_manager::get_region_for_global (tree expr,
 					      region_model2_context */*ctxt*/)
@@ -3507,6 +3541,10 @@ region_model2::on_stmt (const supernode *snode,
 	 superedges.  */
       return true;
 
+    case GIMPLE_GOTO:
+      /* TODO: GIMPLE_GOTO needs to be handled by the engine, not the
+	 region_model2, but I don't think this is a regression relative to
+	 the old implementation.  */
     case GIMPLE_LABEL:
       /* No-op.  */
       return true;
@@ -4456,6 +4494,9 @@ region_model2::get_lvalue_1 (path_var pv,
     case FUNCTION_DECL:
       return m_mgr->get_region_for_fndecl (expr, ctxt);
 
+    case LABEL_DECL:
+      return m_mgr->get_region_for_label (expr, ctxt);
+
     case VAR_DECL:
       /* Handle globals.  */
       if (is_global_var (expr))
@@ -4761,50 +4802,6 @@ region_model2::get_or_create_ptr_svalue2 (tree ptr_type, region2 *reg)
 }
 #endif
 
-/* Return an svalue2 *for a region_svalue2 for FNDECL,
-   creating the function_region2 if necessary.  */
-#if 0
-svalue2_id
-region_model2::get_svalue2_for_fndecl (tree ptr_type, tree fndecl,
-				     region_model2_context *ctxt)
-{
-  gcc_assert (TREE_CODE (fndecl) == FUNCTION_DECL);
-  region2 *function_reg = get_region2_for_fndecl (fndecl, ctxt);
-  return get_or_create_ptr_svalue2 (ptr_type, function_reg);
-}
-#endif
-
-/* Return an svalue2 *for a region_svalue2 for LABEL,
-   creating the label_region2 if necessary.  */
-#if 0
-svalue2_id
-region_model2::get_svalue2_for_label (tree ptr_type, tree label,
-				    region_model2_context *ctxt)
-{
-  gcc_assert (TREE_CODE (label) == LABEL_DECL);
-  region2 *label_reg = get_region2_for_label (label, ctxt);
-  return get_or_create_ptr_svalue2 (ptr_type, label_reg);
-}
-#endif
-
-/* Return a region2 *for a label_region2 for LABEL,
-   creating it if necessary.  */
-#if 0
-region2 *
-region_model2_manager::get_region2_for_label (tree label,
-					      region_model2_context *ctxt)
-{
-  gcc_assert (TREE_CODE (label) == LABEL_DECL);
-
-  tree fndecl = DECL_CONTEXT (label);
-  gcc_assert (fndecl && TREE_CODE (fndecl) == FUNCTION_DECL);
-
-  function_region2 *func_reg = get_region2_for_fndecl (fndecl, ctxt);
-  return func_reg->get_or_create (this, func_reg, label, TREE_TYPE (label),
-				  ctxt);
-}
-#endif
-
 /* Build a cast of SRC_EXPR to DST_TYPE, or return NULL_TREE.
 
    Adapted from gcc::jit::playback::context::build_cast, which in turn is
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index 9d8d4fd8fb4..b30b8bc6714 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -749,7 +749,7 @@ namespace ana {
        heap_region (RK_HEAP)
        root_region (RK_ROOT)
      function_region (RK_FUNCTION)
-     label_region (RK_LABEL)
+     label_region2 (RK_LABEL)
      symbolic_region (RK_SYMBOLIC)
      field_region2 (RK_FIELD)
      element_region2 (RK_ELEMENT)
@@ -782,6 +782,7 @@ public:
    RK_GLOBALS,
    RK_CODE,
    RK_FUNCTION,
+   RK_LABEL,
    RK_STACK,
    RK_HEAP,
    RK_ROOT,
@@ -1092,6 +1093,41 @@ is_a_helper <function_region2 *>::test (region2 *reg)
 
 namespace ana {
 
+// FIXME:
+/* Concrete region2 subclass.  A region2 representing a particular label
+   within a function.  */
+
+class label_region2 : public region2
+{
+public:
+  label_region2 (unsigned id, function_region2 *parent, tree label)
+  : region2 (id, parent, NULL_TREE), m_label (label)
+  {
+    gcc_assert (TREE_CODE (label) == LABEL_DECL);
+  }
+
+  /* region2 vfuncs.  */
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+  enum kind get_kind () const FINAL OVERRIDE { return RK_LABEL; }
+
+  //bool compare_fields (const function_region2 &other) const;
+
+private:
+  tree m_label;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <label_region2 *>::test (region2 *reg)
+{
+  return reg->get_kind () == region2::RK_LABEL;
+}
+
+namespace ana {
+
 /* Concrete region2 subclass representing a stack, containing all stack
    frames, and implicitly providing a POISON_KIND_UNINIT value to all
    child region2s by default.  */
@@ -1502,8 +1538,8 @@ public:
   /* region2 consolidation.  */
   function_region2 *get_region_for_fndecl (tree fndecl,
 					   region_model2_context *ctxt);
-  region2 *get_region_for_label (tree label,
-				 region_model2_context *ctxt);
+  label_region2 *get_region_for_label (tree label,
+				       region_model2_context *ctxt);
   decl_region2 *get_region_for_global (tree expr,
 				       region_model2_context *ctxt);
   region2 *get_field_region (region2 *parent, tree field,
@@ -1561,6 +1597,10 @@ private:
   typedef fndecls_map_t::iterator fndecls_iterator_t;
   fndecls_map_t m_fndecls_map;
 
+  typedef hash_map<tree, label_region2 *> labels_map_t;
+  typedef labels_map_t::iterator labels_iterator_t;
+  labels_map_t m_labels_map;
+
   globals_region2 m_globals_region;
   typedef hash_map<tree, decl_region2 *> globals_map_t;
   typedef globals_map_t::iterator globals_iterator_t;
@@ -1694,10 +1734,6 @@ class region_model2
 
 #if 0
   svalue2_id get_or_create_ptr_svalue2 (tree ptr_type, region2_id id);
-  svalue2_id get_svalue2_for_fndecl (tree ptr_type, tree fndecl,
-				   region_model2_context *ctxt);
-  svalue2_id get_svalue2_for_label (tree ptr_type, tree label,
-				  region_model2_context *ctxt);
 
   svalue2_id maybe_cast (tree type, svalue2_id sid, region_model2_context *ctxt);
   svalue2_id maybe_cast_1 (tree type, svalue2_id sid);
-- 
2.26.2

