From 5b1bc5c14c9b0d401b5f42190c5062ed939deddc Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 6 May 2020 17:42:40 -0400
Subject: [PATCH 104/315] FIXME: implement poisoned_svalue2

---
 gcc/analyzer/region-model2.cc | 26 ++++++++++++
 gcc/analyzer/region-model2.h  | 78 ++++++++++++++++++++++++++---------
 2 files changed, 84 insertions(+), 20 deletions(-)

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index ecc0d68e434..19856d4288b 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -663,6 +663,17 @@ poisoned_svalue2::print_details (const region_model2 &model ATTRIBUTE_UNUSED,
 }
 #endif
 
+/* FIXME.  */
+
+void
+poisoned_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    pp_printf (pp, "POISONED(%s)", poison_kind_to_str (m_kind));
+  else
+    pp_printf (pp, "poisoned_svalue2(%s)", poison_kind_to_str (m_kind));
+}
+
 /* class setjmp_svalue2's implementation is in engine.cc, so that it can use
    the declaration of exploded_node.  */
 
@@ -2758,6 +2769,9 @@ region_model2_manager::~region_model2_manager ()
   for (constants_map_t::iterator iter = m_constants_map.begin ();
        iter != m_constants_map.end (); ++iter)
     delete (*iter).second;
+  for (poisoned_values_map_t::iterator iter = m_poisoned_values_map.begin ();
+       iter != m_poisoned_values_map.end (); ++iter)
+    delete (*iter).second;
   for (initial_values_map_t::iterator iter = m_initial_values_map.begin ();
        iter != m_initial_values_map.end (); ++iter)
     delete (*iter).second;
@@ -2816,6 +2830,18 @@ region_model2_manager::get_or_create_initial_value (const region2 *reg)
   return initial_sval;
 }
 
+const svalue2 *
+region_model2_manager::get_or_create_poisoned_svalue2 (enum poison_kind kind,
+						       tree type)
+{
+  poisoned_svalue2::key_t key (kind, type);
+  if (poisoned_svalue2 **slot = m_poisoned_values_map.get (key))
+    return *slot;
+  poisoned_svalue2 *poisoned_sval = new poisoned_svalue2 (kind, type);
+  m_poisoned_values_map.put (key, poisoned_sval);
+  return poisoned_sval;
+}
+
 const svalue2 *
 region_model2_manager::get_ptr_svalue2 (tree ptr_type, const region2 *pointee)
 {
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index ddf8109ec0c..560ffa46d4f 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -72,6 +72,26 @@ namespace inchash
 
 namespace ana {
 
+/* A hash traits class that uses member functions to implement
+   the various required ops.  */
+
+template <typename Type>
+struct member_function_hash_traits : public typed_noop_remove<Type>
+{
+  typedef Type value_type;
+  typedef Type compare_type;
+  static inline hashval_t hash (value_type v) { return v.hash (); }
+  static inline bool equal (const value_type &existing,
+			    const value_type &candidate)
+  {
+    return existing == candidate;
+  }
+  static inline void mark_deleted (Type &t) { t.mark_deleted (); }
+  static inline void mark_empty (Type &t) { t.mark_empty (); }
+  static inline bool is_deleted (Type t) { return t.is_deleted (); }
+  static inline bool is_empty (Type t) { return t.is_empty (); }
+};
+
 /* A region_model2 is effectively a graph of regions and symbolic values.
    FIXME: we're eliminating IDs in this prototype.
    We store per-model IDs rather than pointers to make it easier to clone
@@ -375,6 +395,32 @@ extern const char *poison_kind_to_str (enum poison_kind);
 class poisoned_svalue2 : public svalue2
 {
 public:
+  /* A support class for uniquifying instances of poisoned_svalue2.  */
+  struct key_t
+  {
+    key_t (enum poison_kind kind, tree type)
+    : m_kind (kind), m_type (type)
+    {}
+
+    hashval_t hash () const
+    {
+      return 42; // FIXME
+    }
+
+    bool operator== (const key_t &other) const
+    {
+      return (m_kind == other.m_kind && m_type == other.m_type);
+    }
+
+    void mark_deleted () { m_type = reinterpret_cast<tree> (1); }
+    void mark_empty () { m_type = NULL_TREE; }
+    bool is_deleted () const { return m_type == reinterpret_cast<tree> (1); }
+    bool is_empty () const { return m_type == NULL_TREE; }
+
+    enum poison_kind m_kind;
+    tree m_type;
+  };
+
   poisoned_svalue2 (enum poison_kind kind, tree type)
   : svalue2 (type), m_kind (kind) {}
 
@@ -415,6 +461,12 @@ is_a_helper <const poisoned_svalue2 *>::test (const svalue2 *sval)
   return sval->get_kind () == svalue2::SK_POISONED;
 }
 
+template <> struct default_hash_traits<poisoned_svalue2::key_t>
+: public member_function_hash_traits<poisoned_svalue2::key_t>
+{
+  static const bool empty_zero_p = true;
+};
+
 namespace ana {
 
 #if 0
@@ -540,26 +592,6 @@ is_a_helper <const initial_svalue2 *>::test (const svalue2 *sval)
 
 namespace ana {
 
-/* A hash traits class that uses member functions to implement
-   the various required ops.  */
-
-template <typename Type>
-struct member_function_hash_traits : public typed_noop_remove<Type>
-{
-  typedef Type value_type;
-  typedef Type compare_type;
-  static inline hashval_t hash (value_type v) { return v.hash (); }
-  static inline bool equal (const value_type &existing,
-			    const value_type &candidate)
-  {
-    return existing == candidate;
-  }
-  static inline void mark_deleted (Type &t) { t.mark_deleted (); }
-  static inline void mark_empty (Type &t) { t.mark_empty (); }
-  static inline bool is_deleted (Type t) { return t.is_deleted (); }
-  static inline bool is_empty (Type t) { return t.is_empty (); }
-};
-
 /* Concrete subclass of svalue2 representing a unary operation on
    another svalue2s (e.g. a cast).  */
 
@@ -1584,6 +1616,8 @@ public:
 
   /* svalue2 consolidation.  */
   const svalue2 *get_or_create_constant_svalue2 (tree cst_expr);
+  const svalue2 *get_or_create_poisoned_svalue2 (enum poison_kind kind,
+						 tree type);
   const svalue2 *get_or_create_initial_value (const region2 *reg);
   const svalue2 *get_ptr_svalue2 (tree ptr_type, const region2 *pointee);
   const svalue2 *get_or_create_unaryop (tree type, enum tree_code op,
@@ -1644,6 +1678,10 @@ private:
   typedef hash_map<tree, constant_svalue2 *> constants_map_t;
   constants_map_t m_constants_map;
 
+  typedef hash_map<poisoned_svalue2::key_t,
+		   poisoned_svalue2 *> poisoned_values_map_t;
+  poisoned_values_map_t m_poisoned_values_map;
+
   typedef hash_map<const region2 *, initial_svalue2 *> initial_values_map_t;
   initial_values_map_t m_initial_values_map;
 
-- 
2.26.2

