From 673eef3052a76417549bd2316e3289c6b571edd4 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 1 Oct 2020 14:32:40 -0400
Subject: [PATCH 27/47] FIXME: get callbacks-1.c to work

---
 gcc/analyzer/region-model-reachability.cc   |  6 ++--
 gcc/analyzer/region-model-reachability.h    |  3 +-
 gcc/analyzer/region-model.cc                | 31 ++++++++++++++++++---
 gcc/testsuite/gcc.dg/analyzer/callbacks-1.c |  2 +-
 4 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/gcc/analyzer/region-model-reachability.cc b/gcc/analyzer/region-model-reachability.cc
index 239dbb58e42..53a87e0dfb2 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -58,9 +58,9 @@ along with GCC; see the file COPYING3.  If not see
 
 namespace ana {
 
-reachable_regions::reachable_regions (store *store,
+reachable_regions::reachable_regions (region_model *model,
 				      region_model_manager *mgr)
-: m_store (store), m_mgr (mgr),
+: m_model (model), m_store (model->get_store ()), m_mgr (mgr),
   m_reachable_base_regs (), m_mutable_base_regs ()
 {
 }
@@ -135,7 +135,7 @@ reachable_regions::add (const region *reg, bool is_mutable)
   if (binding_cluster *bind_cluster = m_store->get_cluster (base_reg))
     bind_cluster->for_each_value (handle_sval_cb, this);
   else
-    handle_sval (m_mgr->get_or_create_initial_value (base_reg));
+    handle_sval (m_model->get_store_value (reg));
 }
 
 void
diff --git a/gcc/analyzer/region-model-reachability.h b/gcc/analyzer/region-model-reachability.h
index 7d51c547676..7d551e0a4a2 100644
--- a/gcc/analyzer/region-model-reachability.h
+++ b/gcc/analyzer/region-model-reachability.h
@@ -35,7 +35,7 @@ namespace ana {
 class reachable_regions
 {
 public:
-  reachable_regions (store *store, region_model_manager *mgr);
+  reachable_regions (region_model *model, region_model_manager *mgr);
 
   /* Callback called for each cluster when initializing this object.  */
   static void init_cluster_cb (const region *base_reg,
@@ -95,6 +95,7 @@ public:
   DEBUG_FUNCTION void dump () const;
 
 private:
+  region_model *m_model;
   store *m_store;
   region_model_manager *m_mgr;
 
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index f35b8be0a9f..258e81b9d65 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -836,7 +836,7 @@ region_model::handle_unrecognized_call (const gcall *call,
 {
   tree fndecl = get_fndecl_for_call (call, ctxt);
 
-  reachable_regions reachable_regs (&m_store, m_mgr);
+  reachable_regions reachable_regs (this, m_mgr);
 
   /* Determine the reachable regions and their mutability.  */
   {
@@ -904,7 +904,7 @@ void
 region_model::get_reachable_svalues (svalue_set *out,
 				     const svalue *extra_sval)
 {
-  reachable_regions reachable_regs (&m_store, m_mgr);
+  reachable_regions reachable_regs (this, m_mgr);
 
   /* Add globals and regions that already escaped in previous
      unknown calls.  */
@@ -1328,19 +1328,41 @@ region_model::get_initial_value_for_global (const region *reg) const
   gcc_assert (base_reg);
   tree decl = base_reg->get_decl ();
 
+#if 0
+  if (TREE_READONLY (decl))
+    {
+      gcc_unreachable ();
+    }
+#endif
+
+#if 0
+  if (use_initializer_for_global_p (decl))
+    {
+    }
+#endif
+
   /* Special-case: to avoid having to explicitly update all previously
      untracked globals when calling an unknown fn, they implicitly have
      an unknown value if an unknown call has occurred, unless this is
      static to-this-TU and hasn't escaped.  Globals that have escaped
      are explicitly tracked, so we shouldn't hit this case for them.  */
-  if (m_store.called_unknown_fn_p () && TREE_PUBLIC (decl))
+  if (m_store.called_unknown_fn_p ()
+      && TREE_PUBLIC (decl)
+      && !TREE_READONLY (decl))
     return m_mgr->get_or_create_unknown_svalue (reg->get_type ());
 
   /* If we are on a path from the entrypoint from "main" and we have a
      global decl defined in this TU that hasn't been touched yet, then
      the initial value of REG can be taken from the initialization value
      of the decl.  */
-  if (called_from_main_p () && !DECL_EXTERNAL (decl))
+  if ((called_from_main_p () && !DECL_EXTERNAL (decl))
+      || TREE_READONLY (decl))
+#if 0
+    if (const svalue *init_sval = reg->get_svalue_for_any_initializer (m_mgr))
+	return init_sval;
+   // FIXME
+#error
+#else
     {
       /* Get the initializer value for base_reg.  */
       const svalue *base_reg_init
@@ -1365,6 +1387,7 @@ region_model::get_initial_value_for_global (const region *reg) const
 	    }
 	}
     }
+#endif
 
   /* Otherwise, return INIT_VAL(REG).  */
   return m_mgr->get_or_create_initial_value (reg);
diff --git a/gcc/testsuite/gcc.dg/analyzer/callbacks-1.c b/gcc/testsuite/gcc.dg/analyzer/callbacks-1.c
index 6608aa3992f..8539baf099d 100644
--- a/gcc/testsuite/gcc.dg/analyzer/callbacks-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/callbacks-1.c
@@ -6,7 +6,7 @@
 static void callback_1 (void *p)
 {
   free (p);
-  free (p);
+  free (p); /* { dg-warning "double-'free' of 'p'" } */
 }
 
 struct ops {
-- 
2.26.2

