From 9e04ff46157c6f0572e6a5a50085bf25e5679bee Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 22 May 2020 17:05:54 -0400
Subject: [PATCH 179/315] FIXME: WIP on symbolic-5.c (aliasing)

---
 gcc/analyzer/store2.cc | 86 +++++++++++++++++++++++++++++++++++++++++-
 gcc/analyzer/store2.h  |  7 +++-
 gcc/tristate.h         |  2 +
 3 files changed, 92 insertions(+), 3 deletions(-)

diff --git a/gcc/analyzer/store2.cc b/gcc/analyzer/store2.cc
index af61e45b908..20d014ff916 100644
--- a/gcc/analyzer/store2.cc
+++ b/gcc/analyzer/store2.cc
@@ -1069,7 +1069,91 @@ store2::set_value (store2_manager *mgr, const region2 *lhs_reg,
   const region2 *base_reg = lhs_reg->get_base_region ();
   binding_cluster2 *cluster = get_or_create_cluster (base_reg);
   cluster->bind (mgr, lhs_reg, rhs_sval, kind);
-  // TODO: various kinds of invalidation etc
+
+#if 0
+  if (const symbolic_region2 *sym_base_reg
+	= base_reg->dyn_cast_symbolic_region2 ())
+    {
+      /* If we set the value to a symbolic region, the code might have
+	 written to other regions.  Invalidate our knowledge of regions
+	 that might have been affected by the write.  */
+      /* FIXME: but what about things that don't even have a
+	 binding cluster yet?
+	 Does initial_value mean
+	 - "the state of the region at the first time that we look at it" or
+	 - "the state of the region at the start of any paths"?   */
+      for (cluster_map_t::iterator iter = m_cluster_map.begin ();
+	   iter != m_cluster_map.end (); ++iter)
+	{
+	  const region2 *iter_base_reg = (*iter).first;
+	  binding_cluster2 *iter_cluster = (*iter).second;
+	  if (iter_base_reg != base_reg)
+	    {
+	      tristate t_alias = eval_alias (sym_base_reg, iter_base_reg);
+	      switch (t_alias.get_value ())
+		{
+		default:
+		  gcc_unreachable ();
+
+		case tristate::TS_UNKNOWN:
+		  {
+		    iter_cluster->mark_region_as_unknown (mgr, iter_base_reg);
+		    //iter_cluster->m_touched = true;
+		  }
+		  break;
+
+		case tristate::TS_TRUE:
+		  {
+		    gcc_unreachable ();
+		    // TODO: apply the same change to iter_cluster
+		    /* TODO: guard against infinite recursion
+		       maybe with a hash_set of processed regions?  */
+		  }
+		  break;
+
+		case tristate::TS_FALSE:
+		  /* If they can't be aliases, then don't invalidate this
+		     cluster.  */
+		  break;
+		}
+	    }
+	}
+    }
+#endif
+}
+
+/* Determine if SYM_BASE_REG could be an alias of OTHER_BASE_REG.  */
+
+tristate
+store2::eval_alias (const symbolic_region2 *sym_base_reg,
+		    const region2 *other_base_reg)
+{
+  const svalue2 *sval = sym_base_reg->get_pointer ();
+
+  if (const decl_region2 *decl_reg = other_base_reg->dyn_cast_decl_region2 ())
+    {
+      tree decl = decl_reg->get_decl ();
+      if (TREE_CODE (decl) == SSA_NAME)
+	{
+	  /* Can't have pointers to SSA names.  */
+	  return tristate::TS_FALSE;
+	}
+
+      if (sval->get_kind () == svalue2::SK_INITIAL)
+	if (!is_global_var (decl) && !escaped_p (decl_reg))
+	  {
+	    /* The initial value of a pointer can't point to an
+	       unescaped local.  */
+	    return tristate::TS_FALSE;
+	  }
+    }
+
+  // TODO: any other logic?
+  /* TODO: perhaps convert this to an alias_oracle * ABC that you ask
+     questions of, and have a concrete implementation in terms of
+     region model, so that we can use constraint_manager knowledge?
+     (and also maybe frontend knowledge?)  */
+  return tristate::TS_UNKNOWN;
 }
 
 /* FIXME.  */
diff --git a/gcc/analyzer/store2.h b/gcc/analyzer/store2.h
index 54c33dddc68..7aa3d464966 100644
--- a/gcc/analyzer/store2.h
+++ b/gcc/analyzer/store2.h
@@ -95,8 +95,8 @@ along with GCC; see the file COPYING3.  If not see
        accesses to other elements are "UNKNOWN" rather than
        "UNINITIALIZED".
 
-   TODO: turn this into symbolic-1.c
-   TODO: example of memset to zero.  */
+   TODO: example of memset to zero.
+   TODO: example of pointer aliasing.  */
 
 namespace ana {
 
@@ -394,6 +394,9 @@ public:
   cluster_map_t::iterator begin () const { return m_cluster_map.begin (); }
   cluster_map_t::iterator end () const { return m_cluster_map.end (); }
 
+  tristate eval_alias (const symbolic_region2 *sym_base_reg,
+		       const region2 *other_base_reg);
+
 private:
   void remove_overlapping_bindings (store2_manager *mgr, const region2 *reg);
 
diff --git a/gcc/tristate.h b/gcc/tristate.h
index e65cb6a09ac..dcd096bf77b 100644
--- a/gcc/tristate.h
+++ b/gcc/tristate.h
@@ -55,6 +55,8 @@ class tristate {
     return m_value != other.m_value;
   }
 
+  enum value get_value () const { return m_value; }
+
  private:
   enum value m_value;
 };
-- 
2.26.2

