From 63ab2dccbcbfa634e33d047526d42e63ae79f16d Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 9 Jun 2020 16:56:24 -0400
Subject: [PATCH 221/237] FIXME: fix uniqueness of UNKNOWN(NULL_TREE)

---
 gcc/analyzer/region-model2.cc | 42 ++++++++++++++++++++++++++++++++++-
 gcc/analyzer/region-model2.h  |  1 +
 2 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index d12db69078a..6dcad63c2ea 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -2910,6 +2910,7 @@ region_model2_manager::region_model2_manager ()
   m_root_region (alloc_region_id ()),
   m_stack_region (alloc_region_id (), &m_root_region),
   m_heap_region (alloc_region_id (), &m_root_region),
+  m_unknown_NULL (NULL),
   m_code_region (alloc_region_id (), &m_root_region),
   m_fndecls_map (), m_labels_map (),
   m_globals_region (alloc_region_id (), &m_root_region),
@@ -2928,6 +2929,7 @@ region_model2_manager::~region_model2_manager ()
   for (unknowns_map_t::iterator iter = m_unknowns_map.begin ();
        iter != m_unknowns_map.end (); ++iter)
     delete (*iter).second;
+  delete m_unknown_NULL;
   for (setjmp_values_map_t::iterator iter = m_setjmp_values_map.begin ();
        iter != m_setjmp_values_map.end (); ++iter)
     delete (*iter).second;
@@ -3000,6 +3002,15 @@ region_model2_manager::get_or_create_constant_svalue2 (tree cst_expr)
 const svalue2 *
 region_model2_manager::get_or_create_unknown_svalue2 (tree type)
 {
+  /* FIXME: remove this special case in favor of fixing traits to
+     allow for a NULL key (as opposed to it being the "empty" value) .  */
+  if (type == NULL_TREE)
+    {
+      if (!m_unknown_NULL)
+	m_unknown_NULL = new unknown_svalue2 (type);
+      return m_unknown_NULL;
+    }
+
   unknown_svalue2 **slot = m_unknowns_map.get (type);
   if (slot)
     return *slot;
@@ -3663,6 +3674,8 @@ region_model2_manager::log_stats (logger *logger, bool show_objs) const
   logger->log ("svalue2 consolidation");
   log_uniq_map (logger, show_objs, "constant_svalue2", m_constants_map);
   log_uniq_map (logger, show_objs, "unknown_svalue2", m_unknowns_map);
+  if (m_unknown_NULL)
+    log_managed_object (logger, m_unknown_NULL);
   log_uniq_map (logger, show_objs, "poisoned_svalue2", m_poisoned_values_map);
   log_uniq_map (logger, show_objs, "setjmp_svalue2", m_setjmp_values_map);
   log_uniq_map (logger, show_objs, "initial_svalue2", m_initial_values_map);
@@ -8452,7 +8465,7 @@ test_get_representative_tree ()
 }
 
 /* Verify that calling region_model2::get_rvalue repeatedly on the same
-   tree constant retrieves the same svalue2_id.  */
+   tree constant retrieves the same svalue2 *.  */
 
 static void
 test_unique_constants ()
@@ -8483,6 +8496,32 @@ test_unique_constants ()
   ASSERT_CONDITION_FALSE2 (model, int_42_sval, NE_EXPR, const_int_42_sval);
 }
 
+/* Verify that each type gets its own singleton unknown_svalue2 within a
+   region_model2_manager, and that NULL_TREE gets its own singleton.  */
+
+static void
+test_unique_unknowns ()
+{
+  region_model2_manager mgr;
+  const svalue2 *unknown_int
+    = mgr.get_or_create_unknown_svalue2 (integer_type_node);
+  /* Repeated calls with the same type should get the same "unknown"
+     svalue2.  */
+  const svalue2 *unknown_int_2
+    = mgr.get_or_create_unknown_svalue2 (integer_type_node);
+  ASSERT_EQ (unknown_int, unknown_int_2);
+
+  /* Different types (or the NULL type) should have different
+     unknown_svalue2s.  */
+  const svalue2 *unknown_NULL_type = mgr.get_or_create_unknown_svalue2 (NULL);
+  ASSERT_NE (unknown_NULL_type, unknown_int);
+
+  /* Repeated calls with NULL for the type should get the same "unknown"
+     svalue2.  */
+  const svalue2 *unknown_NULL_type_2 = mgr.get_or_create_unknown_svalue2 (NULL);
+  ASSERT_EQ (unknown_NULL_type, unknown_NULL_type_2);
+}
+
 #if 0
 /* Check that operator== and hashing works as expected for the
    various svalue2 subclasses.  */
@@ -10134,6 +10173,7 @@ analyzer_region_model2_cc_tests ()
 #endif
   test_get_representative_tree ();
   test_unique_constants ();
+  test_unique_unknowns ();
 #if 0
   test_svalue2_equality ();
   test_region2_equality ();
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index e4a48f2469f..014b8a47995 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -1923,6 +1923,7 @@ private:
 
   typedef hash_map<tree, unknown_svalue2 *> unknowns_map_t;
   unknowns_map_t m_unknowns_map;
+  const unknown_svalue2 *m_unknown_NULL;
 
   typedef hash_map<poisoned_svalue2::key_t,
 		   poisoned_svalue2 *> poisoned_values_map_t;
-- 
2.26.2

