From faa6796767db3260ede0f9b180999377ccd01cda Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 15 May 2020 12:19:06 -0400
Subject: [PATCH 138/159] FIXME: subvalues of 'unknown' are unknown

---
 gcc/analyzer/region-model2.cc | 68 +++++++++++++++++++++++++++++++----
 gcc/analyzer/region-model2.h  |  3 ++
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 4723d8577f4..17c8f9a5739 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -525,9 +525,17 @@ void
 unknown_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
 {
   if (simple)
-    pp_printf (pp, "UNKNOWN");
+    {
+      pp_string (pp, "UNKNOWN(");
+      dump_tree (pp, get_type ());
+      pp_character (pp, ')');
+    }
   else
-    pp_printf (pp, "unknown_svalue2()");
+    {
+      pp_string (pp, "unknown_svalue2(");
+      dump_tree (pp, get_type ());
+      pp_character (pp, ')');
+    }
 }
 
 /* class poisoned_svalue2 : public svalue2.  */
@@ -2824,14 +2832,19 @@ maybe_get_char_from_string_cst (tree string_cst, tree byte_offset_cst,
   return NULL;
 }
 
-/* FIXME.  */
+/* Subroutine of region_model2_manager::get_or_create_sub_svalue2.
+   Return a folded svalue2, or NULL.  */
 
 const svalue2 *
-region_model2_manager::get_or_create_sub_svalue2 (tree type,
-						  const svalue2 *parent_svalue2,
-						  const region2 *subregion)
+region_model2_manager::maybe_fold_sub_svalue2 (tree type,
+					       const svalue2 *parent_svalue2,
+					       const region2 *subregion)
 {
-  /* Specialcase: if we have a subregion of a zero-fill, it's zero.  */
+  /* Subvalues of "unknown" are unknown.  */
+  if (parent_svalue2->get_kind () == svalue2::SK_UNKNOWN)
+    return get_or_create_unknown_svalue2 (type);
+
+  /* If we have a subregion of a zero-fill, it's zero.  */
   if (const unaryop_svalue2 *unary
       = parent_svalue2->dyn_cast_unaryop_svalue2 ())
     {
@@ -2858,6 +2871,20 @@ region_model2_manager::get_or_create_sub_svalue2 (tree type,
 	      return get_or_create_cast (type, char_sval);
 	}
 
+  return NULL;
+}
+
+/* FIXME.  */
+
+const svalue2 *
+region_model2_manager::get_or_create_sub_svalue2 (tree type,
+						  const svalue2 *parent_svalue2,
+						  const region2 *subregion)
+{
+  if (const svalue2 *folded
+	= maybe_fold_sub_svalue2 (type, parent_svalue2, subregion))
+    return folded;
+
   sub_svalue2::key_t key (type, parent_svalue2, subregion);
   if (sub_svalue2 **slot = m_sub_values_map.get (key))
     return *slot;
@@ -7958,6 +7985,32 @@ test_binop_svalue2_folding ()
 
   /* FIXME: do we want to canonicalize binops to put constants on the RHS ?  */
 }
+
+/* Verify that sub_svalue2s are folded as expected.  */
+
+static void
+test_sub_svalue2_folding ()
+{
+  coord_test2 ct;
+  tree c = build_global_decl ("c", ct.m_coord_type);
+  tree c_x = build3 (COMPONENT_REF, TREE_TYPE (ct.m_x_field),
+		     c, ct.m_x_field, NULL_TREE);
+
+  region_model2_manager mgr;
+  region_model2 model (&mgr);
+  test_region_model2_context ctxt;
+  const region2 *c_x_reg = model.get_lvalue (c_x, &ctxt);
+
+  /* Verify that sub_svalue2 of "unknown" simply
+     yields an unknown.  */
+
+  const svalue2 *unknown = mgr.get_or_create_unknown_svalue2 (ct.m_coord_type);
+  const svalue2 *sub = mgr.get_or_create_sub_svalue2 (TREE_TYPE (ct.m_x_field),
+						      unknown, c_x_reg);
+  ASSERT_EQ (sub->get_kind (), svalue2::SK_UNKNOWN);
+  ASSERT_EQ (sub->get_type (), TREE_TYPE (ct.m_x_field));
+}
+
 #if 0
 /* A subclass of purge_criteria for selftests: purge all const svalue2 *instances.  */
 
@@ -9352,6 +9405,7 @@ analyzer_region_model2_cc_tests ()
   test_initial_svalue2_folding ();
   test_unaryop_svalue2_folding ();
   test_binop_svalue2_folding ();
+  test_sub_svalue2_folding ();
 #if 0
   test_purging_by_criteria ();
   test_purge_unused_svalue2s ();
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index c84999a72a2..0aee4001d7e 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -1616,6 +1616,9 @@ private:
 				     const svalue2 *arg);
   const svalue2 *maybe_fold_binop (tree type, enum tree_code op,
 				   const svalue2 *arg0, const svalue2 *arg1);
+  const svalue2 *maybe_fold_sub_svalue2 (tree type,
+					 const svalue2 *parent_svalue,
+					 const region2 *subregion);
 
   unsigned m_next_region_id;
   root_region2 m_root_region;
-- 
2.21.0

