From de5f72df479d809fd9dc12fbb54d0b06271ca02e Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 3 Jun 2020 18:26:02 -0400
Subject: [PATCH 197/237] FIXME: add placeholder_svalue2; use it to start
 populating test_get_representative_tree

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

diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc
index 2e1386d13b1..3fcdb62bf2f 100644
--- a/gcc/analyzer/region-model2.cc
+++ b/gcc/analyzer/region-model2.cc
@@ -711,6 +711,22 @@ sub_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
     }
 }
 
+/* class placeholder_svalue2 : public svalue2.  */
+
+void
+placeholder_svalue2::dump_to_pp (pretty_printer *pp, bool simple) const
+{
+  if (simple)
+    {
+      pp_printf (pp, "PLACEHOLDER(%qs)", m_name);
+    }
+  else
+    {
+      pp_printf (pp, "placeholder_svalue2 (%qs)", m_name);
+      // TODO: type?
+    }
+}
+
 /* class region2 and its various subclasses.  */
 
 /* Get a string for KIND for use in debug dumps.  */
@@ -8142,6 +8158,61 @@ test_get_representative_tree ()
     tree rep = m.get_representative_tree (str_sval);
     ASSERT_DUMP_TREE_EQ (rep, "&\"foo\"[0]");
   }
+
+  /* Value of a primitive local.  */
+  {
+    // TODO
+  }
+
+  /* Value of an element within an array.  */
+  {
+    tree tlen = size_int (10);
+    tree arr_type = build_array_type (char_type_node, build_index_type (tlen));
+    tree a = build_global_decl ("a", arr_type);
+    placeholder_svalue2 test_sval (char_type_node, "test value");
+
+    /* Value of a[3].  */
+    {
+      test_region_model2_context ctxt;
+      region_model2 model (&mgr);
+      tree int_3 = build_int_cst (integer_type_node, 3);
+      tree a_3 = build4 (ARRAY_REF, char_type_node,
+			 a, int_3, NULL_TREE, NULL_TREE);
+      const region2 *a_3_reg = model.get_lvalue (a_3, &ctxt);
+      model.set_value (a_3_reg, &test_sval, &ctxt);
+#if 0
+      tree rep = model.get_representative_tree (&test_sval);
+      // TODO: this currently ICEs
+      ASSERT_DUMP_TREE_EQ (rep, "a[3]");
+#endif
+    }
+
+    /* Value of a[0].  */
+    {
+      test_region_model2_context ctxt;
+      region_model2 model (&mgr);
+      tree idx = build_int_cst (integer_type_node, 0);
+      tree a_0 = build4 (ARRAY_REF, char_type_node,
+			 a, idx, NULL_TREE, NULL_TREE);
+      const region2 *a_0_reg = model.get_lvalue (a_0, &ctxt);
+      model.set_value (a_0_reg, &test_sval, &ctxt);
+      tree rep = model.get_representative_tree (&test_sval);
+#if 0
+      // TODO: this currently gets just "a", rather than "a[0]":
+      ASSERT_DUMP_TREE_EQ (rep, "a[0]");
+#endif
+    }
+  }
+
+  /* Value of a field within a struct.  */
+  {
+    // TODO: initial vs non-initial
+  }
+
+  /* Value of a field within a union.  */
+  {
+    // TODO
+  }
 }
 
 /* Verify that calling region_model2::get_rvalue repeatedly on the same
diff --git a/gcc/analyzer/region-model2.h b/gcc/analyzer/region-model2.h
index bebbd3a7a90..1d201882efd 100644
--- a/gcc/analyzer/region-model2.h
+++ b/gcc/analyzer/region-model2.h
@@ -133,7 +133,8 @@ struct purge_stats2
      initial2_svalue2 (SK_INITIAL): the initial value of a region2
      unaryop_svalue2 (SK_UNARYOP): unary operation on another svalue2
      binop_svalue2 (SK_BINOP): binary operation on two svalue2s
-     sub_svalue2 (SK_SUB): the result of accessing a subregion.  */
+     sub_svalue2 (SK_SUB): the result of accessing a subregion
+     placeholder_svalue2 (SK_PLACEHOLDER): for use in selftests.  */
 
 /* An abstract base class representing a value held by a region of memory.  */
 
@@ -153,6 +154,7 @@ public:
    SK_UNARYOP,
    SK_BINOP,
    SK_SUB,
+   SK_PLACEHOLDER
   };
 
   virtual ~svalue2 () {}
@@ -771,6 +773,49 @@ template <> struct default_hash_traits<sub_svalue2::key_t>
 
 namespace ana {
 
+/* Concrete subclass of svalue2 for use in selftests, where
+   we want a specific but unknown svalue2.
+   Unlike other svalue2 subclasses these aren't managed by
+   region_model2_manager.  */
+
+class placeholder_svalue2 : public svalue2
+{
+public:
+  placeholder_svalue2 (tree type, const char *name)
+  : svalue2 (type), m_name (name)
+  {
+  }
+
+  enum kind get_kind () const FINAL OVERRIDE { return SK_PLACEHOLDER; }
+
+#if 0
+  void dump_dot_to_pp (const region_model2 &model,
+		       pretty_printer *pp) const
+    FINAL OVERRIDE;
+#endif
+
+  void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
+
+#if 0
+  binop_svalue2 *dyn_cast_placeholder_svalue2 () FINAL OVERRIDE { return this; }
+#endif
+
+ private:
+  const char *m_name;
+};
+
+} // namespace ana
+
+template <>
+template <>
+inline bool
+is_a_helper <placeholder_svalue2 *>::test (svalue2 *sval)
+{
+  return sval->get_kind () == svalue2::SK_PLACEHOLDER;
+}
+
+namespace ana {
+
 /* Region and its subclasses.
 
    The class hierarchy looks like this (using indentation to show
-- 
2.26.2

