From 17f34fa316cc44468a9626b8d9483fd1f075fe10 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 15 May 2019 15:59:21 -0400
Subject: [PATCH 52/67] FIXME: more on better memory model

---
 gcc/analyzer/region-model.cc                 | 256 +++++++++++++++++++++++----
 gcc/analyzer/region-model.h                  | 116 ++++++++----
 gcc/testsuite/gcc.dg/analyzer/data-model-1.c |  29 +++
 3 files changed, 334 insertions(+), 67 deletions(-)

diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 7acbc10..645adb8 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -42,6 +42,7 @@
 #include "supergraph.h"
 #include "region-model.h"
 #include "tree-diagnostic.h"
+#include "diagnostic-color.h"
 
 ////////////////////////////////////////////////////////////////////////////
 
@@ -82,6 +83,23 @@ region_id::dump_node_name_to_pp (pretty_printer *pp) const
 /* class svalue.  */
 
 void
+svalue::print (const region_model &model,
+	       svalue_id this_sid,
+	       pretty_printer *pp) const
+{
+  this_sid.print (pp);
+  pp_string (pp, ": {");
+
+  if (m_type)
+    pp_printf (pp, "type: %qT, ", m_type);
+
+  /* vfunc.  */
+  print_details (model, this_sid, pp);
+
+  pp_string (pp, "}");
+}
+
+void
 svalue::dump_dot_to_pp (const region_model &model,
 			svalue_id this_sid,
 			pretty_printer *pp) const
@@ -118,9 +136,9 @@ region_svalue::hash () const
 }
 
 void
-region_svalue::print (const region_model &model,
-		      svalue_id this_sid,
-		      pretty_printer *pp) const
+region_svalue::print_details (const region_model &model,
+			      svalue_id this_sid,
+			      pretty_printer *pp) const
 {
   if (m_rid.null_p ())
     pp_string (pp, "NULL");
@@ -167,9 +185,9 @@ constant_svalue::hash () const
 /* FIXME.  */
 
 void
-constant_svalue::print (const region_model &model,
-			svalue_id this_sid,
-			pretty_printer *pp) const
+constant_svalue::print_details (const region_model &model,
+				svalue_id this_sid,
+				pretty_printer *pp) const
 {
   pp_printf (pp, "%qE", m_cst_expr);
 }
@@ -203,9 +221,9 @@ poisoned_svalue::hash () const
 /* FIXME.  */
 
 void
-poisoned_svalue::print (const region_model &model,
-			svalue_id this_sid,
-			pretty_printer *pp) const
+poisoned_svalue::print_details (const region_model &model,
+				svalue_id this_sid,
+				pretty_printer *pp) const
 {
   pp_printf (pp, "poisoned: %s", poison_kind_to_str (m_kind));
 }
@@ -236,6 +254,21 @@ region_kind_to_str (enum region_kind kind)
 
 /* class region.  */
 
+void
+region::set_value (const region_model &model, svalue_id rhs_sid)
+{
+  svalue *sval = model.get_svalue (rhs_sid);
+
+  // FIXME: we can't enable this until we have working casts
+#if 0
+  /* Type-check where we can.  */
+  if (m_type && sval->get_type ())
+    gcc_assert (m_type == sval->get_type ());
+#endif
+
+  m_sval_id = rhs_sid;
+}
+
 /* FIXME.  */
 
 svalue_id
@@ -329,13 +362,6 @@ region::dump_to_pp (const region_model &model,
 		    const char *prefix,
 		    bool is_last_child) const
 {
-  if (!m_parent_rid.null_p ())
-    {
-      // FIXME: colorize hierachical ASCII art
-      const char *tail = is_last_child ? "`-" : "|-";
-      pp_printf (pp, "%r%s%s%R", "note", prefix, tail);
-      // FIXME: dedicated color code?
-    }
   print (model, this_rid, pp);
   pp_newline (pp);
 
@@ -345,8 +371,25 @@ region::dump_to_pp (const region_model &model,
   else
     new_prefix = prefix;
 
-  /* TODO: iter children:
-     TODO: we'll also want to label them
+  const char *begin_color = colorize_start (pp_show_color (pp), "note");
+  const char *end_color = colorize_stop (pp_show_color (pp));
+  char *field_prefix
+    = ACONCAT ((begin_color, new_prefix, "|:", end_color, NULL));
+
+  if (!m_sval_id.null_p ())
+    {
+      pp_printf (pp, "%s sval: ", field_prefix);
+      model.get_svalue (m_sval_id)->print (model, m_sval_id, pp);
+      pp_newline (pp);
+    }
+  if (m_type)
+    {
+      pp_printf (pp, "%s type: %qT", field_prefix, m_type);
+      pp_newline (pp);
+    }
+
+  /* Find, then iterate over children.  */
+  /* TODO: we'll also want to label them
      (potentially with tree labels, or with sval labels).  */
 
   auto_vec<region_id> child_rids;
@@ -358,9 +401,31 @@ region::dump_to_pp (const region_model &model,
 
   region_id *child_rid;
   FOR_EACH_VEC_ELT (child_rids, i, child_rid)
-    model.get_region (*child_rid)->dump_to_pp (model, *child_rid, pp,
-					       new_prefix,
-					       i == child_rids.length () - 1);
+    {
+      is_last_child = (i == child_rids.length () - 1);
+      if (!this_rid.null_p ())
+	{
+	  // FIXME: colorize hierachical ASCII art
+	  const char *tail = is_last_child ? "`-" : "|-";
+	  pp_printf (pp, "%r%s%s%R", "note", new_prefix, tail);
+	  // FIXME: dedicated color code?
+	}
+      dump_child_label (model, this_rid, *child_rid, pp);
+      model.get_region (*child_rid)->dump_to_pp (model, *child_rid, pp,
+						 new_prefix,
+						 is_last_child);
+    }
+}
+
+/* FIXME.  */
+
+void
+region::dump_child_label (const region_model &model,
+			  region_id this_rid,
+			  region_id child_rid,
+			  pretty_printer *pp) const
+{
+  /* Empty.  */
 }
 
 #if 0
@@ -398,6 +463,9 @@ region::print_fields (const region_model &model,
 
   pp_printf (pp, ", sval: ");
   m_sval_id.print (pp);
+
+  if (m_type)
+    pp_printf (pp, ", type: %qT", m_type);
 }
 
 /* class map_region : public region.  */
@@ -475,17 +543,38 @@ map_region::dump_dot_to_pp (const region_model &model,
 
 /* FIXME.  */
 
+void
+map_region::dump_child_label (const region_model &model,
+			      region_id this_rid,
+			      region_id child_rid,
+			      pretty_printer *pp) const
+{
+  for (map_t::iterator iter = m_map.begin ();
+       iter != m_map.end ();
+       ++iter)
+    {
+      if (child_rid == (*iter).second)
+	{
+	  tree expr = (*iter).first;
+	  pp_printf (pp, "%qE: ", expr);
+	}
+    }
+}
+
+/* FIXME.  */
+
 region_id
 map_region::get_or_create (region_model *model,
 			   region_id this_rid,
-			   tree expr)
+			   tree expr,
+			   tree type)
 {
   // TODO
   region_id *slot = m_map.get (expr);
   if (slot)
     return *slot;
   // FIXME: what kind of region?
-  region_id child_rid = model->add_region (new map_region (this_rid));
+  region_id child_rid = model->add_region (new map_region (this_rid, type));
   m_map.put (expr, child_rid);
   return child_rid;
 }
@@ -553,8 +642,8 @@ stack_region::clone () const
 
 void
 stack_region::print_fields (const region_model &model,
-				  region_id this_rid,
-				  pretty_printer *pp) const
+			    region_id this_rid,
+			    pretty_printer *pp) const
 {
   region::print_fields (model, this_rid, pp);
   // TODO
@@ -563,6 +652,18 @@ stack_region::print_fields (const region_model &model,
 /* FIXME.  */
 
 void
+stack_region::dump_child_label (const region_model &model,
+				region_id this_rid,
+				region_id child_rid,
+				pretty_printer *pp) const
+{
+  function *fun = model.get_region<frame_region> (child_rid)->get_function ();
+  pp_printf (pp, "frame for %qs: ", function_name (fun));
+}
+
+/* FIXME.  */
+
+void
 stack_region::push_frame (region_id frame_rid)
 {
   m_frame_rids.safe_push (frame_rid);
@@ -598,7 +699,8 @@ stack_region::add_to_hash (inchash::hash &hstate) const
 
 root_region::root_region ()
 : region (region_id::null (),
-	  svalue_id::null ())
+	  svalue_id::null (),
+	  NULL_TREE)
 {
 #if 0
   m_stack_rid (model.add_region (new stack_model ())),
@@ -633,6 +735,22 @@ root_region::print_fields (const region_model &model,
   // TODO
 }
 
+/* FIXME.  */
+
+void
+root_region::dump_child_label (const region_model &model,
+			       region_id this_rid,
+			       region_id child_rid,
+			       pretty_printer *pp) const
+{
+  if (child_rid == m_stack_rid)
+    pp_printf (pp, "stack: ");
+  else if (child_rid == m_globals_rid)
+    pp_printf (pp, "globals: ");
+}
+
+/* FIXME.  */
+
 void
 root_region::push_frame (region_model *model, function *fun)
 {
@@ -846,6 +964,20 @@ void
 region_model::dump_to_pp (pretty_printer *pp) const
 {
   get_region (m_root_rid)->dump_to_pp (*this, m_root_rid, pp, "", true);
+
+  pp_string (pp, "svalues: ");
+  pp_newline (pp);
+  int i;
+  svalue *svalue;
+  FOR_EACH_VEC_ELT (m_svalues, i, svalue)
+    {
+      svalue_id sid = svalue_id::from_int (i);
+      pp_string (pp, "  ");
+      sid.print (pp);
+      pp_string (pp, ": ");
+      svalue->print (*this, sid, pp);
+      pp_newline (pp);
+    }
 }
 
 /* FIXME.  */
@@ -906,6 +1038,24 @@ region_model::on_assignment (const gassign *assign)
       }
       break;
 
+    case POINTER_PLUS_EXPR:
+      {
+	/* e.g. "_1 = a_10(D) + 12;" */
+	tree ptr = rhs1;
+	tree offset = gimple_assign_rhs2 (assign);
+
+	svalue_id buffer_sid = get_rvalue (ptr);
+	region_id buffer_rid = get_lvalue (ptr);
+	svalue_id element_sid = get_rvalue (offset);
+	/* FIXME: offset is in bytes; we presumably want to
+	   map back to an index.  */
+
+	// FIXME
+	gcc_unreachable ();
+	// TODO
+      }
+      break;
+
     case ADDR_EXPR:
       {
 	/* LHS = &RHS;  */
@@ -916,6 +1066,7 @@ region_model::on_assignment (const gassign *assign)
       break;
 
     case INTEGER_CST:
+    case ARRAY_REF:
       {
 	/* LHS = RHS;  */
 	svalue_id cst_sid = get_rvalue (rhs1);
@@ -973,6 +1124,25 @@ region_model::get_lvalue (tree expr)
     default:
       gcc_unreachable ();
 
+    case ARRAY_REF:
+      {
+	tree array = TREE_OPERAND (expr, 0);
+	tree index = TREE_OPERAND (expr, 1);
+	// TODO: operands 2 and 3, if present:
+	gcc_assert (TREE_OPERAND (expr, 2) == NULL_TREE);
+	gcc_assert (TREE_OPERAND (expr, 3) == NULL_TREE);
+	region_id array_rid = get_lvalue (array);
+	svalue_id index_sid = get_rvalue (index);
+	map_region *array_region = get_region<map_region> (array_rid);
+	tree element_type = TREE_TYPE (TREE_TYPE (array));
+	region_id element_rid
+	  = array_region->get_or_create (this, array_rid, index, element_type);
+	/* FIXME: ^^^ should be indexed by svalue, rather than by tree?
+	   What about unknown indices?  */
+	return element_rid;
+      }
+      break; // FIXME
+
     case MEM_REF:
       {
 	tree ptr = TREE_OPERAND (expr, 0);
@@ -997,7 +1167,7 @@ region_model::get_lvalue (tree expr)
 	    /* We need to write the region back into the pointer,
 	       or we'll get a new, different region each time.  */
 	    region_id ptr_rid = get_lvalue (ptr);
-	    ptr_sid = add_svalue (new region_svalue (new_rid));
+	    ptr_sid = add_svalue (new region_svalue (TREE_TYPE (ptr), new_rid));
 	    set_value (ptr_rid, ptr_sid);
 
 	    return new_rid;
@@ -1019,7 +1189,8 @@ region_model::get_lvalue (tree expr)
 
 	region_id frame_rid = get_current_frame_id ();
 	frame_region *frame = get_region <frame_region> (frame_rid);
-	region_id child_rid = frame->get_or_create (this, frame_rid, expr);
+	region_id child_rid = frame->get_or_create (this, frame_rid, expr,
+						    TREE_TYPE (expr));
 	return child_rid;
       }
 
@@ -1030,7 +1201,8 @@ region_model::get_lvalue (tree expr)
 	tree field = TREE_OPERAND (expr, 1);
 	region_id obj_rid = get_lvalue (obj);
 	map_region *obj_region = get_region<map_region> (obj_rid);
-	region_id child_rid = obj_region->get_or_create (this, obj_rid, field);
+	region_id child_rid = obj_region->get_or_create (this, obj_rid, field,
+							 TREE_TYPE (field));
 	return child_rid;
       }
       break;
@@ -1048,6 +1220,12 @@ region_model::get_rvalue (tree expr)
     default:
       gcc_unreachable ();
 
+    case ARRAY_REF:
+      {
+	region_id element_rid = get_lvalue (expr);
+	return get_region (element_rid)->get_value (*this);
+      }
+
     case INTEGER_CST:
       return get_svalue_for_constant (expr);
 
@@ -1066,7 +1244,9 @@ svalue_id
 region_model::get_svalue_for_region (region_id rid)
 {
   // TODO: maybe reuse existing ones? (maybe keep a record in the region?)
-  return add_svalue (new region_svalue (rid));
+  tree type = get_region (rid)->get_type ();
+  // FIXME: ^^^ should this be a pointer type to type?
+  return add_svalue (new region_svalue (type, rid));
 }
 
 /* FIXME.  */
@@ -1082,7 +1262,7 @@ region_model::get_svalue_for_constant (tree cst_expr)
 void
 region_model::set_value (region_id lhs_rid, svalue_id rhs_sid)
 {
-  get_region (lhs_rid)->set_value (rhs_sid);
+  get_region (lhs_rid)->set_value (*this, rhs_sid);
 }
 
 /* FIXME.  */
@@ -1222,6 +1402,19 @@ debug (const region_model &rmodel)
 
 namespace selftest {
 
+static void
+test_dump ()
+{
+  auto_fix_quotes sentinel;
+  region_model model;
+  pretty_printer pp;
+  pp_format_decoder (&pp) = default_tree_printer;
+  model.dump_to_pp (&pp);
+  ASSERT_STREQ (pp_formatted_text (&pp),
+		"r0: {kind: `root', parent: null, sval: null}\n"
+		"svalues: \n");
+}
+
 #if 0
 
 /* Attempt to add the constraint (LHS OP RHS) to PS.
@@ -2091,6 +2284,7 @@ test_purging ()
 void
 analyzer_region_model_cc_tests ()
 {
+  test_dump ();
 #if 0
   test_constraint_conditions ();
   test_transitivity ();
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 1b3f46b..48c0e68 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -105,13 +105,15 @@ public:
 
   virtual svalue *clone () const = 0;
 
+  tree get_type () const { return m_type; }
+
   virtual enum svalue_kind get_kind () const = 0;
 
   virtual hashval_t hash () const = 0;
 
-  virtual void print (const region_model &model,
-		      svalue_id this_sid,
-		      pretty_printer *pp) const = 0;
+  void print (const region_model &model,
+	      svalue_id this_sid,
+	      pretty_printer *pp) const;
 
   virtual void dump_dot_to_pp (const region_model &model,
 			       svalue_id this_sid,
@@ -121,6 +123,16 @@ public:
 
   virtual region_svalue *dyn_cast_region_svalue () { return NULL; }
   virtual constant_svalue *dyn_cast_constant_svalue () { return NULL; }
+
+ protected:
+  svalue (tree type) : m_type (type) {}
+
+ private:
+  virtual void print_details (const region_model &model,
+			      svalue_id this_sid,
+			      pretty_printer *pp) const = 0;
+
+  tree m_type;
 };
 
 /* FIXME.  */
@@ -128,20 +140,15 @@ public:
 class region_svalue : public svalue
 {
 public:
-  region_svalue (region_id rid) : m_rid (rid) {}
+  region_svalue (tree type, region_id rid) : svalue (type), m_rid (rid) {}
 
   svalue *clone () const FINAL OVERRIDE
-  { return new region_svalue (m_rid); }
+  { return new region_svalue (get_type (), m_rid); }
 
   enum svalue_kind get_kind () const FINAL OVERRIDE { return SK_REGION; }
 
   hashval_t hash () const FINAL OVERRIDE;
 
-  void print (const region_model &model,
-	      svalue_id this_sid,
-	      pretty_printer *pp) const
-    FINAL OVERRIDE;
-
   void dump_dot_to_pp (const region_model &model,
 		       svalue_id this_sid,
 		       pretty_printer *pp) const
@@ -152,6 +159,11 @@ public:
   region_id get_pointee () const { return m_rid; }
 
  private:
+  void print_details (const region_model &model,
+		      svalue_id this_sid,
+		      pretty_printer *pp) const
+    FINAL OVERRIDE;
+
   region_id m_rid;
 };
 
@@ -160,7 +172,9 @@ public:
 class constant_svalue : public svalue
 {
 public:
-  constant_svalue (tree cst_expr) : m_cst_expr (cst_expr) {}
+  constant_svalue (tree cst_expr)
+  : svalue (TREE_TYPE (cst_expr)), m_cst_expr (cst_expr)
+  {}
 
   svalue *clone () const FINAL OVERRIDE
   { return new constant_svalue (m_cst_expr); }
@@ -169,16 +183,16 @@ public:
 
   hashval_t hash () const FINAL OVERRIDE;
 
-  void print (const region_model &model,
-	      svalue_id this_sid,
-	      pretty_printer *pp) const
-    FINAL OVERRIDE;
-
   constant_svalue *dyn_cast_constant_svalue () FINAL OVERRIDE { return this; }
 
   tree get_constant () const { return m_cst_expr; }
 
  private:
+  void print_details (const region_model &model,
+		      svalue_id this_sid,
+		      pretty_printer *pp) const
+    FINAL OVERRIDE;
+
   tree m_cst_expr;
 };
 
@@ -197,7 +211,7 @@ extern const char *poison_kind_to_str (enum poison_kind);
 class poisoned_svalue : public svalue
 {
 public:
-  poisoned_svalue (enum poison_kind kind) : m_kind (kind) {}
+  poisoned_svalue (enum poison_kind kind) : svalue (NULL), m_kind (kind) {}
 
   svalue *clone () const FINAL OVERRIDE
   { return new poisoned_svalue (m_kind); }
@@ -206,9 +220,10 @@ public:
 
   hashval_t hash () const FINAL OVERRIDE;
 
-  void print (const region_model &model,
-	      svalue_id this_sid,
-	      pretty_printer *pp) const
+ private:
+  void print_details (const region_model &model,
+		      svalue_id this_sid,
+		      pretty_printer *pp) const
     FINAL OVERRIDE;
 
   enum poison_kind m_kind;
@@ -234,11 +249,12 @@ extern const char *region_kind_to_str (enum region_kind);
 class region
 {
 public:
-  region (region_id parent_rid, svalue_id sval_id)
-  : m_parent_rid (parent_rid), m_sval_id (sval_id) {}
+  region (region_id parent_rid, svalue_id sval_id, tree type)
+  : m_parent_rid (parent_rid), m_sval_id (sval_id), m_type (type) {}
 
   region (const region &other)
-  : m_parent_rid (other.m_parent_rid), m_sval_id (other.m_sval_id)
+  : m_parent_rid (other.m_parent_rid), m_sval_id (other.m_sval_id),
+    m_type (other.m_type)
   {
   }
 
@@ -248,9 +264,11 @@ public:
 
   virtual enum region_kind get_kind () const = 0;
 
-  void set_value (svalue_id rhs_sid) { m_sval_id = rhs_sid; }
+  void set_value (const region_model &model, svalue_id rhs_sid);
   svalue_id get_value (const region_model &model) const;
 
+  tree get_type () const { return m_type; }
+
   hashval_t hash () const;
 
   void print (const region_model &model,
@@ -261,11 +279,15 @@ public:
 			       region_id this_rid,
 			       pretty_printer *pp) const;
 
-  virtual void dump_to_pp (const region_model &model,
-			   region_id this_rid,
-			   pretty_printer *pp,
-			   const char *prefix,
-			   bool is_last_child) const;
+  void dump_to_pp (const region_model &model,
+		   region_id this_rid,
+		   pretty_printer *pp,
+		   const char *prefix,
+		   bool is_last_child) const;
+  virtual void dump_child_label (const region_model &model,
+				 region_id this_rid,
+				 region_id child_rid,
+				 pretty_printer *pp) const;
 
   std::string to_str () const;
 
@@ -278,6 +300,7 @@ public:
  private:
   region_id m_parent_rid;
   svalue_id m_sval_id;
+  tree m_type;
 };
 
 /* FIXME.  */
@@ -285,8 +308,8 @@ public:
 class map_region : public region
 {
 public:
-  map_region (region_id parent_rid)
-  : region (parent_rid, svalue_id::null ())
+  map_region (region_id parent_rid, tree type)
+  : region (parent_rid, svalue_id::null (), type)
   {}
   map_region (const map_region &other);
 
@@ -299,9 +322,15 @@ public:
 		       pretty_printer *pp) const
     FINAL OVERRIDE;
 
+  void dump_child_label (const region_model &model,
+			 region_id this_rid,
+			 region_id child_rid,
+			 pretty_printer *pp) const
+    FINAL OVERRIDE;
+
   region_id get_or_create (region_model *model,
 			   region_id this_rid,
-			   tree expr);
+			   tree expr, tree type);
 
  protected:
   void add_to_hash (inchash::hash &hstate) const OVERRIDE;
@@ -322,7 +351,7 @@ class frame_region : public map_region
 {
 public:
   frame_region (region_id parent_rid, function *fun)
-  : map_region (parent_rid), m_fun (fun)
+  : map_region (parent_rid, NULL_TREE), m_fun (fun)
   {}
 
   frame_region (const frame_region &other)
@@ -334,6 +363,8 @@ public:
 
   enum region_kind get_kind () const FINAL OVERRIDE { return RK_FRAME; }
 
+  function *get_function () const { return m_fun; }
+
  private:
   void add_to_hash (inchash::hash &hstate) const FINAL OVERRIDE;
   void print_fields (const region_model &model,
@@ -348,7 +379,7 @@ class stack_region : public region
 {
 public:
   stack_region (region_id parent_rid, svalue_id sval_id)
-  : region (parent_rid, sval_id)
+  : region (parent_rid, sval_id, NULL_TREE)
   {}
 
   stack_region (const stack_region &other);
@@ -357,6 +388,12 @@ public:
 
   enum region_kind get_kind () const FINAL OVERRIDE { return RK_STACK; }
 
+  void dump_child_label (const region_model &model,
+			 region_id this_rid,
+			 region_id child_rid,
+			 pretty_printer *pp) const
+    FINAL OVERRIDE;
+
   void push_frame (region_id frame_rid);
   region_id get_current_frame_id () const;
 
@@ -380,6 +417,12 @@ public:
 
   enum region_kind get_kind () const FINAL OVERRIDE { return RK_ROOT; }
 
+  void dump_child_label (const region_model &model,
+			 region_id this_rid,
+			 region_id child_rid,
+			 pretty_printer *pp) const
+    FINAL OVERRIDE;
+
   void push_frame (region_model *model, function *fun);
   region_id get_current_frame_id (const region_model &model) const;
 
@@ -400,7 +443,7 @@ class symbolic_region : public map_region
 {
 public:
   symbolic_region (region_id parent_rid)
-  : map_region (parent_rid)
+  : map_region (parent_rid, NULL_TREE)
   {}
   symbolic_region (const symbolic_region &other);
 
@@ -479,8 +522,9 @@ class region_model
 			   enum tree_code op,
 			   tree rhs);
 
-  // private:
+ private:
   auto_delete_vec<svalue> m_svalues;
+ public: // FIXME:
   auto_delete_vec<region> m_regions;
   region_id m_root_rid;
 };
diff --git a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
index ed10f3e..eafea2f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/data-model-1.c
@@ -43,6 +43,35 @@ void test_4 (void)
   __analyzer_eval (i == 2); /* { dg-warning "TRUE" } */
 }
 
+/* Local array.  */
+
+void test_5 (void)
+{
+  int a[10];
+  a[3] = 5; /* ARRAY_REF.  */
+  __analyzer_eval (a[3] == 5); /* { dg-warning "TRUE" } */
+}
+
+/* Local array, but using an unknown index.  */
+
+void test_5a (int idx)
+{
+  int a[10];
+  a[idx] = 5; /* ARRAY_REF.  */
+  __analyzer_eval (a[idx] == 5); /* { dg-warning "TRUE" } */
+}
+
+/* Globals.  */
+
+int glob_a;
+
+void test_10 (void)
+{
+  __analyzer_eval (glob_a == 42); /* { dg-warning "UNKNOWN" } */
+  glob_a = 42;
+  __analyzer_eval (glob_a == 42); /* { dg-warning "TRUE" } */
+}
+
 // TODO:
 
 struct link
-- 
1.8.5.3

