From 6480ed61b411c603273dc6764c0174597ef504e4 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 27 Jul 2020 10:27:25 -0400
Subject: [PATCH 336/377] FIXME: add NULL_POINTER_TYPE_CONSOLIDATION, disabled
 for now

---
 gcc/analyzer/analyzer.h             |  1 +
 gcc/analyzer/constraint-manager2.cc |  9 +++++++
 gcc/analyzer/program-state.cc       | 41 ++++++++++++++++++++++++++---
 gcc/analyzer/program-state.h        |  6 ++++-
 4 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/gcc/analyzer/analyzer.h b/gcc/analyzer/analyzer.h
index 540667821d0..3baba6ce7a1 100644
--- a/gcc/analyzer/analyzer.h
+++ b/gcc/analyzer/analyzer.h
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3.  If not see
 #define GCC_ANALYZER_ANALYZER_H
 
 #define ITERATED_BINOPS 0
+#define NULL_POINTER_TYPE_CONSOLIDATION 0
 
 class graphviz_out;
 
diff --git a/gcc/analyzer/constraint-manager2.cc b/gcc/analyzer/constraint-manager2.cc
index 45cdbed94eb..e0bca2a149b 100644
--- a/gcc/analyzer/constraint-manager2.cc
+++ b/gcc/analyzer/constraint-manager2.cc
@@ -1132,6 +1132,15 @@ constraint_manager2::get_or_add_equiv_class2 (const svalue2 *sval)
 
   gcc_assert (sval->get_kind () != svalue2::SK_UNKNOWN);
 
+  /* Convert all NULL pointers to (void *) to avoid state explosions
+     involving all of the various (foo *)NULL vs (bar *)NULL.  */
+#if NULL_POINTER_TYPE_CONSOLIDATION
+  if (POINTER_TYPE_P (sval->get_type ()))
+    if (tree cst = sval->maybe_get_constant ())
+      if (zerop (cst))
+	sval = m_mgr->get_or_create_constant_svalue2 (null_pointer_node);
+#endif
+
   /* Try svalue2 match.  */
   if (get_equiv_class2_by_svalue2 (sval, &result))
     return result;
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 947b4494ab7..b4a10cf5b66 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -777,6 +777,10 @@ sm_state_map2::get_state (const svalue2 *sval,
 {
   gcc_assert (sval);
 
+#if NULL_POINTER_TYPE_CONSOLIDATION
+  sval = canonicalize_svalue2 (sval, ext_state);
+#endif
+
   if (entry_t *slot
       = const_cast <map_t &> (m_map).get (sval))
     return slot->m_state;
@@ -810,10 +814,15 @@ sm_state_map2::get_state (const svalue2 *sval,
 /* Get the "origin" svalue2 for any state of SVAL.  */
 
 const svalue2 *
-sm_state_map2::get_origin (const svalue2 *sval) const
+sm_state_map2::get_origin (const svalue2 *sval,
+			   const extrinsic_state &ext_state) const
 {
   gcc_assert (sval);
 
+#if NULL_POINTER_TYPE_CONSOLIDATION
+  sval = canonicalize_svalue2 (sval, ext_state);
+#endif
+
   entry_t *slot
     = const_cast <map_t &> (m_map).get (sval);
   if (slot)
@@ -887,6 +896,10 @@ sm_state_map2::impl_set_state (const svalue2 *sval,
 			       const svalue2 *origin,
 			       const extrinsic_state &ext_state)
 {
+#if NULL_POINTER_TYPE_CONSOLIDATION
+  sval = canonicalize_svalue2 (sval, ext_state);
+#endif
+
   if (get_state (sval, ext_state) == state)
     return false;
 
@@ -1131,6 +1144,26 @@ sm_state_map2::validate (const state_machine &sm,
     }
 }
 #endif
+
+/* FIXME.  */
+
+#if NULL_POINTER_TYPE_CONSOLIDATION
+
+const svalue2 *
+sm_state_map2::canonicalize_svalue2 (const svalue2 *sval,
+				     const extrinsic_state &ext_state)
+{
+  region_model2_manager *mgr = ext_state.get_model_manager ();
+  if (mgr && sval->get_type () && POINTER_TYPE_P (sval->get_type ()))
+    if (tree cst = sval->maybe_get_constant ())
+      if (zerop (cst))
+	return mgr->get_or_create_constant_svalue2 (null_pointer_node);
+
+  return sval;
+}
+
+#endif
+
 /* class program_state.  */
 
 /* program_state's ctor.  */
@@ -2721,7 +2754,7 @@ test_sm_state_map2 ()
 
     map.impl_set_state (x_sval, 42, z_sval, ext_state);
     ASSERT_EQ (map.get_state (x_sval, ext_state), 42);
-    ASSERT_EQ (map.get_origin (x_sval), z_sval);
+    ASSERT_EQ (map.get_origin (x_sval, ext_state), z_sval);
     ASSERT_EQ (map.get_state (y_sval, ext_state), 0);
     ASSERT_FALSE (map.is_empty_p ());
 
@@ -2753,8 +2786,8 @@ test_sm_state_map2 ()
     map.set_state (&model, x_sval, 5, z_sval, ext_state);
     ASSERT_EQ (map.get_state (x_sval, ext_state), 5);
     ASSERT_EQ (map.get_state (y_sval, ext_state), 5);
-    ASSERT_EQ (map.get_origin (x_sval), z_sval);
-    ASSERT_EQ (map.get_origin (y_sval), z_sval);
+    ASSERT_EQ (map.get_origin (x_sval, ext_state), z_sval);
+    ASSERT_EQ (map.get_origin (y_sval, ext_state), z_sval);
   }
 
   /* Test equality and hashing.  */
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index 376174fb382..fdf330155c9 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -276,7 +276,8 @@ public:
 
   state_machine::state_t get_state (const svalue2 *sval,
 				    const extrinsic_state &ext_state) const;
-  const svalue2 *get_origin (const svalue2 *sval) const;
+  const svalue2 *get_origin (const svalue2 *sval,
+			     const extrinsic_state &ext_state) const;
 
   void set_state (region_model2 *model,
 		  const svalue2 *sval,
@@ -321,6 +322,9 @@ public:
   iterator_t begin () const { return m_map.begin (); }
   iterator_t end () const { return m_map.end (); }
 
+  static const svalue2 *
+  canonicalize_svalue2 (const svalue2 *sval, const extrinsic_state &ext_state);
+
 private:
   const state_machine &m_sm;
   int m_sm_idx;
-- 
2.26.2

