From 7e3059394d61c4a2d21d8754877cbdb4a1055c9b Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 6 Apr 2020 17:27:38 -0400
Subject: [PATCH 09/96] FIXME: use uniq_manager more in revamp-state.h/cc

---
 gcc/analyzer/revamp-state.cc | 42 +++++++++++++++++++++++-------------
 gcc/analyzer/revamp-state.h  | 14 +++++++-----
 gcc/analyzer/uniq-manager.h  | 17 ++++++++-------
 3 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/gcc/analyzer/revamp-state.cc b/gcc/analyzer/revamp-state.cc
index bccd4a61992..84fa12e03bf 100644
--- a/gcc/analyzer/revamp-state.cc
+++ b/gcc/analyzer/revamp-state.cc
@@ -393,36 +393,38 @@ void
 revamp_state::bind (const extrinsic_state &ext_state,
 		    tree lhs, tree rhs)
 {
-  loc_val *dst = get_lvalue (ext_state, lhs);
-  sval *src = get_rvalue (ext_state, rhs);
-  if (region_val *rval = dst->dyn_cast_region_val ())
+  const loc_val *dst = get_lvalue (ext_state, lhs);
+  const sval *src = get_rvalue (ext_state, rhs);
+  if (const region_val *rval = dst->dyn_cast_region_val ())
     m_store->bind (rval, src);
   else
     gcc_unreachable (); // unknown loc_val; what could be clobbered?
 }
 
-loc_val *
+const loc_val *
 revamp_state::get_lvalue (const extrinsic_state &ext_state, tree expr)
 {
+  engine *eng = ext_state.get_engine ();
   switch (TREE_CODE (expr))
     {
     case VAR_DECL:
-      return new var_decl_region (expr); // TODO: uniquify
+      return eng->consolidate_sval (new var_decl_region (expr));
     case SSA_NAME:
-      return new ssa_name_region (expr); // TODO: uniquify
+      return eng->consolidate_sval (new ssa_name_region (expr));
     default:
       gcc_unreachable ();
       //return ext_state::new_unknown_sval (expr);
     }
 }
 
-sval *
+const sval *
 revamp_state::get_rvalue (const extrinsic_state &ext_state, tree expr)
 {
+  engine *eng = ext_state.get_engine ();
   switch (TREE_CODE (expr))
     {
     case INTEGER_CST:
-      return new cst_sval (expr); //ext_state.get_or_add_cst_sval (expr);
+      return eng->consolidate_sval (new cst_sval (expr));
     default:
       gcc_unreachable ();
       //return ext_state::new_unknown_sval (expr);
@@ -449,12 +451,6 @@ engine::~engine ()
   delete m_sval_mgr;
 }
 
-const sval *
-engine::consolidate_sval (sval *s)
-{
-  return m_sval_mgr->consolidate (s);
-}
-
 size_t
 engine::get_num_svals () const
 {
@@ -471,6 +467,7 @@ test_consolidation ()
   engine eng;
   ASSERT_EQ (eng.get_num_svals (), 0);
 
+  /* Create and consolidate some svals.  */
   tree int_17 = build_int_cst (integer_type_node, 17);
   const sval *cst17_0 = eng.consolidate_sval (new cst_sval (int_17));
   ASSERT_EQ (eng.get_num_svals (), 1);
@@ -484,8 +481,23 @@ test_consolidation ()
   const sval *cst42_1 = eng.consolidate_sval (new cst_sval (int_42));
   ASSERT_EQ (eng.get_num_svals (), 2);
   ASSERT_EQ (cst42_0, cst42_1);
-
   ASSERT_NE (cst17_0, cst42_0);
+
+  tree x = build_global_decl ("x", integer_type_node);
+  tree y = build_global_decl ("y", integer_type_node);
+  const region_val* x_decl = eng.consolidate_sval (new var_decl_region (x));
+  const region_val* y_decl = eng.consolidate_sval (new var_decl_region (y));
+  ASSERT_EQ (eng.get_num_svals (), 4);
+  ASSERT_NE (x_decl, y_decl);
+
+  auto_delete_vec <state_machine> checkers;
+  extrinsic_state ext_state (checkers, NULL, &eng);
+
+  revamp_state s (ext_state);
+  ASSERT_EQ (s.get_lvalue (ext_state, x), x_decl);
+  ASSERT_EQ (s.get_lvalue (ext_state, y), y_decl);
+  ASSERT_EQ (s.get_rvalue (ext_state, int_17), cst17_0);
+  ASSERT_EQ (s.get_rvalue (ext_state, int_42), cst42_0);
 }
 
 /* Run all of the selftests within this file.  */
diff --git a/gcc/analyzer/revamp-state.h b/gcc/analyzer/revamp-state.h
index a7a04f63761..16472d19c04 100644
--- a/gcc/analyzer/revamp-state.h
+++ b/gcc/analyzer/revamp-state.h
@@ -48,7 +48,7 @@ public:
 
   void dump ();
   virtual void dump_to_pp (pretty_printer *pp) const = 0;
-  virtual region_val *dyn_cast_region_val () { return NULL; }
+  virtual const region_val *dyn_cast_region_val () const { return NULL; }
 
  protected:
   virtual void add_to_hash (inchash::hash &hstate) const = 0;
@@ -97,7 +97,7 @@ class unknown_loc_val : public loc_val
 class region_val : public loc_val
 {
  public:
-  region_val *dyn_cast_region_val () FINAL OVERRIDE { return this; }
+  const region_val *dyn_cast_region_val () const FINAL OVERRIDE { return this; }
 };
 
 class var_decl_region : public region_val
@@ -172,8 +172,8 @@ public:
   void bind (const extrinsic_state &ext_state,
 	     tree lhs, tree rhs);
 
-  loc_val *get_lvalue (const extrinsic_state &ext_state, tree expr);
-  sval *get_rvalue (const extrinsic_state &ext_state, tree expr);
+  const loc_val *get_lvalue (const extrinsic_state &ext_state, tree expr);
+  const sval *get_rvalue (const extrinsic_state &ext_state, tree expr);
 
 private:
   bool on_gassign (const extrinsic_state &ext_state,
@@ -201,7 +201,11 @@ class engine
   engine ();
   ~engine ();
 
-  const sval *consolidate_sval (sval *s);
+  template <typename SvalSubclass>
+  const SvalSubclass *consolidate_sval (SvalSubclass *s)
+  {
+    return m_sval_mgr->consolidate (s);
+  }
   size_t get_num_svals () const;
 
  private:
diff --git a/gcc/analyzer/uniq-manager.h b/gcc/analyzer/uniq-manager.h
index bee9167f0e8..8a6451bb641 100644
--- a/gcc/analyzer/uniq-manager.h
+++ b/gcc/analyzer/uniq-manager.h
@@ -133,25 +133,26 @@ class uniq_manager
   typedef hash_map <T *, T *, traits_t> map_t;
   typedef typename map_t::iterator iterator_t;
 
-  /* Takes ownership of t, deleting it if there's a duplicate.  */
-  const T *consolidate (T *t)
+  /* Takes ownership of S, deleting it if there's a duplicate.  */
+  template <typename SubclassOfT>
+  const SubclassOfT *consolidate (SubclassOfT *s)
   {
 #if 1
-    gcc_assert (t);
+    gcc_assert (s);
     //uniq_id_t *id = new uniq_id_t ();
     //t->add_to_uniq_id (id);
     bool existed;
-    T *&ptr = m_map.get_or_insert (t, &existed);  // FIXME: hash function!
+    T *&ptr = m_map.get_or_insert (s, &existed);  // FIXME: hash function!
     if (existed)
       {
 	//delete id;
-	delete t;
-	return ptr;
+	delete s;
+	return static_cast <SubclassOfT*> (ptr);
       }
     else
       {
-	ptr = t;
-	return t;
+	ptr = s;
+	return s;
       }
 #else
     uniq_id_t id;
-- 
2.21.0

