From 3f05bcbf27b5eba4260850e248bb95d0c309f626 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Tue, 5 Nov 2019 10:27:23 -0500
Subject: [PATCH 112/119] FIXME: split out function_point from program_point

---
 gcc/analyzer/diagnostic-manager.cc |  38 ++++----
 gcc/analyzer/engine.cc             | 103 ++++++++++----------
 gcc/analyzer/exploded-graph.h      |   2 +-
 gcc/analyzer/program-point.cc      | 192 ++++++++++++++++++++++---------------
 gcc/analyzer/program-point.h       | 185 +++++++++++++++++++++++++++++------
 gcc/analyzer/program-state.cc      |   9 +-
 gcc/analyzer/state-purge.cc        |  81 +++++++---------
 gcc/analyzer/state-purge.h         |  50 +++++-----
 8 files changed, 406 insertions(+), 254 deletions(-)

diff --git a/gcc/analyzer/diagnostic-manager.cc b/gcc/analyzer/diagnostic-manager.cc
index 2c39115..a0109c2 100644
--- a/gcc/analyzer/diagnostic-manager.cc
+++ b/gcc/analyzer/diagnostic-manager.cc
@@ -565,34 +565,34 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
     {
       emission_path->add_event
 	(new rewind_from_longjmp_event
-	 (&eedge, src_point.m_supernode->get_end_location (),
-	  src_point.m_supernode->m_fun->decl,
+	 (&eedge, src_point.get_supernode ()->get_end_location (),
+	  src_point.get_fndecl (),
 	  src_stack_depth));
       emission_path->add_event
 	(new rewind_to_setjmp_event
 	 (&eedge, eedge.m_rewind_info->get_setjmp_call ()->location,
-	  dst_point.m_supernode->m_fun->decl,
+	  dst_point.get_fndecl (),
 	  dst_stack_depth));
     }
 
   /* Add events for superedges, function entries, and for statements.  */
-  switch (dst_point.m_kind)
+  switch (dst_point.get_kind ())
     {
     default:
       break;
     case PK_BEFORE_SUPERNODE:
-      if (src_point.m_kind == PK_AFTER_SUPERNODE)
+      if (src_point.get_kind () == PK_AFTER_SUPERNODE)
 	{
 	  if (eedge.m_sedge)
 	    add_events_for_superedge (eedge, emission_path);
 	}
       /* Add function entry events.  */
-      if (dst_point.m_supernode->entry_p ())
+      if (dst_point.get_supernode ()->entry_p ())
 	{
 	  emission_path->add_event
 	    (new function_entry_event
-	     (dst_point.m_supernode->get_start_location (),
-	      dst_point.m_supernode->m_fun->decl,
+	     (dst_point.get_supernode ()->get_start_location (),
+	      dst_point.get_fndecl (),
 	      dst_stack_depth));
 	}
       break;
@@ -603,12 +603,12 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
 	  emission_path->add_event
 	    (new setjmp_event (stmt->location,
 			       dst_node,
-			       dst_point.m_supernode->m_fun->decl,
+			       dst_point.get_fndecl (),
 			       dst_stack_depth));
 	else
 	  emission_path->add_event
 	    (new statement_event (stmt,
-				  dst_point.m_supernode->m_fun->decl,
+				  dst_point.get_fndecl (),
 				  dst_stack_depth, dst_state));
       }
       break;
@@ -633,7 +633,7 @@ diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
   const program_point &dst_point = dst_node->get_point ();
   const int src_stack_depth = src_point.get_stack_depth ();
   const int dst_stack_depth = dst_point.get_stack_depth ();
-  const gimple *last_stmt = src_point.m_supernode->get_last_stmt ();
+  const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
 
   switch (eedge.m_sedge->m_kind)
     {
@@ -644,12 +644,12 @@ diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
 			       (last_stmt
 				? last_stmt->location
 				: UNKNOWN_LOCATION),
-			       src_point.m_supernode->m_fun->decl,
+			       src_point.get_fndecl (),
 			       src_stack_depth));
 	emission_path->add_event
 	  (new end_cfg_edge_event (eedge,
-				   dst_point.m_supernode->get_start_location (),
-				   dst_point.m_supernode->m_fun->decl,
+				   dst_point.get_supernode ()->get_start_location (),
+				   dst_point.get_fndecl (),
 				   dst_stack_depth));
       }
       break;
@@ -661,7 +661,7 @@ diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
 			   (last_stmt
 			    ? last_stmt->location
 			    : UNKNOWN_LOCATION),
-			   src_point.m_supernode->m_fun->decl,
+			   src_point.get_fndecl (),
 			   src_stack_depth));
       }
       break;
@@ -674,7 +674,7 @@ diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
 	  (new debug_event ((last_stmt
 			     ? last_stmt->location
 			     : UNKNOWN_LOCATION),
-			    src_point.m_supernode->m_fun->decl,
+			    src_point.get_fndecl (),
 			    src_stack_depth,
 			    "call summary"));
       }
@@ -691,7 +691,7 @@ diagnostic_manager::add_events_for_superedge (const exploded_edge &eedge,
 			     (call_stmt
 			      ? call_stmt->location
 			      : UNKNOWN_LOCATION),
-			     dst_point.m_supernode->m_fun->decl,
+			     dst_point.get_fndecl (),
 			     dst_stack_depth));
       }
       break;
@@ -753,13 +753,13 @@ diagnostic_manager::add_state_change_events (const exploded_edge &eedge,
 	  if (dst_sm_val != src_sm_val)
 	    {
 	      const gimple *stmt = src_point.get_stmt ();
-	      const supernode *supernode = src_point.m_supernode;
+	      const supernode *supernode = src_point.get_supernode ();
 	      int stack_depth = src_stack_depth;
 
 	      if (eedge.m_sedge
 		  && eedge.m_sedge->m_kind == SUPEREDGE_CFG_EDGE)
 		{
-		  supernode = src_point.m_supernode;
+		  supernode = src_point.get_supernode ();
 		  stmt = supernode->get_last_stmt ();
 		  stack_depth = src_stack_depth;
 		}
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 3d5944e..839c4dd 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -1051,16 +1051,16 @@ static bool
 valid_longjmp_stack_p (const program_point &longjmp_point,
 		       const program_point &setjmp_point)
 {
-  if (longjmp_point.m_call_string.length ()
-      < setjmp_point.m_call_string.length ())
+  const call_string &cs_at_longjmp = longjmp_point.get_call_string ();
+  const call_string &cs_at_setjmp = setjmp_point.get_call_string ();
+
+  if (cs_at_longjmp.length () < cs_at_setjmp.length ())
     return false;
 
   /* Check that the call strings match, up to the depth of the
      setjmp point.  */
-  for (unsigned depth = 0; depth < setjmp_point.m_call_string.length ();
-       depth++)
-    if (longjmp_point.m_call_string[depth]
-	!= setjmp_point.m_call_string[depth])
+  for (unsigned depth = 0; depth < cs_at_setjmp.length (); depth++)
+    if (cs_at_longjmp[depth] != cs_at_setjmp[depth])
       return false;
 
   return true;
@@ -1154,8 +1154,8 @@ exploded_node::on_longjmp (exploded_graph &eg,
 				setjmp_point.get_stack_depth (), ctxt);
 
   program_point next_point
-    = program_point::after_supernode (setjmp_point.m_supernode,
-				      setjmp_point.m_call_string);
+    = program_point::after_supernode (setjmp_point.get_supernode (),
+				      setjmp_point.get_call_string ());
 
   exploded_node *next = eg.get_or_create_node (next_point, *new_state);
 
@@ -1496,8 +1496,8 @@ worklist::key_t::cmp_1 (const worklist::key_t &ka, const worklist::key_t &kb)
 {
   const program_point &point_a = ka.m_enode->get_point ();
   const program_point &point_b = kb.m_enode->get_point ();
-  const call_string &call_string_a = point_a.m_call_string;
-  const call_string &call_string_b = point_b.m_call_string;
+  const call_string &call_string_a = point_a.get_call_string ();
+  const call_string &call_string_b = point_b.get_call_string ();
 
   /* Order empty-callstring points with different functions based on the
      analysis_plan, so that we generate summaries before they are used.  */
@@ -1545,7 +1545,9 @@ worklist::key_t::cmp_1 (const worklist::key_t &ka, const worklist::key_t &kb)
   gcc_assert (snode_a == snode_b);
 
   /* Order within supernode via program point.  */
-  int within_snode_cmp = program_point::cmp_within_supernode (point_a, point_b);
+  int within_snode_cmp
+    = function_point::cmp_within_supernode (point_a.get_function_point (),
+					    point_b.get_function_point ());
   if (within_snode_cmp)
     return within_snode_cmp;
 
@@ -1624,7 +1626,8 @@ exploded_graph::exploded_graph (const supergraph &sg, logger *logger,
   m_functionless_stats (m_sg.num_nodes ()),
   m_PK_AFTER_SUPERNODE_per_snode (m_sg.num_nodes ())
 {
-  m_origin = get_or_create_node (program_point (NULL, NULL, 0, PK_ORIGIN,
+  m_origin = get_or_create_node (program_point (function_point (NULL, NULL,
+								0, PK_ORIGIN),
 						call_string ()),
 				 program_state (ext_state));
   for (int i = 0; i < m_sg.num_nodes (); i++)
@@ -1717,7 +1720,7 @@ exploded_graph::get_or_create_node (const program_point &point,
   stats *per_fn_stats = get_or_create_function_stats (point.get_function ());
 
   stats *per_cs_stats
-    = &get_or_create_per_call_string_data (point.m_call_string)->m_stats;
+    = &get_or_create_per_call_string_data (point.get_call_string ())->m_stats;
 
   point_and_state ps (point, pruned_state);
   if (exploded_node **slot = m_point_and_state_to_node.get (&ps))
@@ -1799,11 +1802,12 @@ exploded_graph::get_or_create_node (const program_point &point,
   /* Update per-program_point data.  */
   per_point_data->m_enodes.safe_push (node);
 
-  m_global_stats.m_num_nodes[node->get_point ().m_kind]++;
-  per_fn_stats->m_num_nodes[node->get_point ().m_kind]++;
-  per_cs_stats->m_num_nodes[node->get_point ().m_kind]++;
+  const enum point_kind node_pk = node->get_point ().get_kind ();
+  m_global_stats.m_num_nodes[node_pk]++;
+  per_fn_stats->m_num_nodes[node_pk]++;
+  per_cs_stats->m_num_nodes[node_pk]++;
 
-  if (node->get_point ().m_kind == PK_AFTER_SUPERNODE)
+  if (node_pk == PK_AFTER_SUPERNODE)
     m_PK_AFTER_SUPERNODE_per_snode[point.get_supernode ()->m_index]++;
 
   if (get_logger ())
@@ -2261,7 +2265,7 @@ exploded_graph::process_node (exploded_node *node)
       end_log_line ();
     }
 
-  switch (point.m_kind)
+  switch (point.get_kind ())
     {
     default:
       gcc_unreachable ();
@@ -2274,12 +2278,12 @@ exploded_graph::process_node (exploded_node *node)
       {
 	program_state next_state (state);
 
-	if (point.m_from_edge)
+	if (point.get_from_edge ())
 	  {
 	    impl_region_model_context ctxt (*this, node,
 					    &state, &next_state, NULL);
 	    const cfg_superedge *last_cfg_superedge
-	      = point.m_from_edge->dyn_cast_cfg_superedge ();
+	      = point.get_from_edge ()->dyn_cast_cfg_superedge ();
 	    if (last_cfg_superedge)
 	      next_state.m_region_model->update_for_phis
 		(node->get_supernode (),
@@ -2287,11 +2291,11 @@ exploded_graph::process_node (exploded_node *node)
 		 &ctxt);
 	  }
 
-	if (point.m_supernode->m_stmts.length () > 0)
+	if (point.get_supernode ()->m_stmts.length () > 0)
 	  {
 	    program_point next_point
-	      = program_point::before_stmt (point.m_supernode, 0,
-					    point.m_call_string);
+	      = program_point::before_stmt (point.get_supernode (), 0,
+					    point.get_call_string ());
 	    exploded_node *next
 	      = get_or_create_node (next_point, next_state);
 	    if (next)
@@ -2300,8 +2304,8 @@ exploded_graph::process_node (exploded_node *node)
 	else
 	  {
 	    program_point next_point
-	      = program_point::after_supernode (point.m_supernode,
-						point.m_call_string);
+	      = program_point::after_supernode (point.get_supernode (),
+						point.get_call_string ());
 	    exploded_node *next = get_or_create_node (next_point, next_state);
 	    if (next)
 	      add_edge (node, next, NULL);
@@ -2326,15 +2330,15 @@ exploded_graph::process_node (exploded_node *node)
 	   Update next_state in-place, to get the result of the one
 	   or more stmts that are processed.  */
 	program_state next_state (state);
-	const supernode *snode = point.m_supernode;
+	const supernode *snode = point.get_supernode ();
 	unsigned stmt_idx;
-	for (stmt_idx = point.m_stmt_idx;
+	for (stmt_idx = point.get_stmt_idx ();
 	     stmt_idx < snode->m_stmts.length ();
 	     stmt_idx++)
 	  {
 	    const gimple *stmt = snode->m_stmts[stmt_idx];
 
-	    if (stmt_idx > point.m_stmt_idx)
+	    if (stmt_idx > point.get_stmt_idx ())
 	      if (stmt_requires_new_enode_p (stmt))
 		{
 		  stmt_idx--;
@@ -2350,11 +2354,11 @@ exploded_graph::process_node (exploded_node *node)
 	  }
 	unsigned next_idx = stmt_idx + 1;
 	program_point next_point
-	  = (next_idx < point.m_supernode->m_stmts.length ()
-	     ? program_point::before_stmt (point.m_supernode, next_idx,
-					   point.m_call_string)
-	     : program_point::after_supernode (point.m_supernode,
-					       point.m_call_string));
+	  = (next_idx < point.get_supernode ()->m_stmts.length ()
+	     ? program_point::before_stmt (point.get_supernode (), next_idx,
+					   point.get_call_string ())
+	     : program_point::after_supernode (point.get_supernode (),
+					       point.get_call_string ()));
 	exploded_node *next = get_or_create_node (next_point,
 						  next_state);
 	if (next)
@@ -2365,11 +2369,11 @@ exploded_graph::process_node (exploded_node *node)
       {
 	/* If this is an EXIT BB, detect leaks, and potentially
 	   create a function summary.  */
-	if (point.m_supernode->return_p ())
+	if (point.get_supernode ()->return_p ())
 	  {
 	    node->detect_leaks (*this);
 	    if (flag_analyzer_call_summaries
-		&& point.m_call_string.empty_p ())
+		&& point.get_call_string ().empty_p ())
 	      {
 		/* TODO: create function summary
 		   There can be more than one; each corresponds to a different
@@ -2380,7 +2384,7 @@ exploded_graph::process_node (exploded_node *node)
 		    start_log_line ();
 		    get_logger ()->log_partial
 		      ("would create function summary for %qE; state: ",
-		       point.get_function ()->decl);
+		       point.get_fndecl ());
 		    state.dump_to_pp (m_ext_state, true, pp);
 		    end_log_line ();
 		  }
@@ -2392,14 +2396,14 @@ exploded_graph::process_node (exploded_node *node)
 	/* Traverse into successors of the supernode.  */
 	int i;
 	superedge *succ;
-	FOR_EACH_VEC_ELT (point.m_supernode->m_succs, i, succ)
+	FOR_EACH_VEC_ELT (point.get_supernode ()->m_succs, i, succ)
 	  {
 	    log ("considering SN: %i -> SN: %i",
 		 succ->m_src->m_index, succ->m_dest->m_index);
 
 	    program_point next_point
 	      = program_point::before_supernode (succ->m_dest, succ,
-						 point.m_call_string);
+						 point.get_call_string ());
 	    program_state next_state (state);
 
 	    if (!node->on_edge (*this, succ, &next_point, &next_state))
@@ -2504,7 +2508,7 @@ exploded_graph::dump_states_for_supernode (FILE *out,
   FOR_EACH_VEC_ELT (m_nodes, i, enode)
     {
       const supernode *iter_snode = enode->get_supernode ();
-      if (enode->get_point ().m_kind == PK_AFTER_SUPERNODE
+      if (enode->get_point ().get_kind () == PK_AFTER_SUPERNODE
 	  && iter_snode == snode)
 	{
 	  pretty_printer pp;
@@ -2602,7 +2606,7 @@ exploded_path::feasible_p (logger *logger) const
 			 sedge->m_dest->m_index,
 			 sedge->get_description (false));
 
-	  const gimple *last_stmt = src_point.m_supernode->get_last_stmt ();
+	  const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
 	  if (!model.maybe_update_for_edge (*sedge, last_stmt, NULL))
 	    {
 	      if (logger)
@@ -2617,8 +2621,8 @@ exploded_path::feasible_p (logger *logger) const
 	  if (i == 0)
 	    {
 	      gcc_assert (eedge->m_src->m_index == 0);
-	      gcc_assert (src_point.m_kind == PK_ORIGIN);
-	      gcc_assert (eedge->m_dest->get_point ().m_kind
+	      gcc_assert (src_point.get_kind () == PK_ORIGIN);
+	      gcc_assert (eedge->m_dest->get_point ().get_kind ()
 			  == PK_BEFORE_SUPERNODE);
 	      function *fun = eedge->m_dest->get_function ();
 	      gcc_assert (fun);
@@ -2631,7 +2635,8 @@ exploded_path::feasible_p (logger *logger) const
 	      /* Update state for the special-case of a rewind of a longjmp
 		 to a setjmp (which doesn't have a superedge, but does affect
 		 state).  */
-	      const gimple *last_stmt = src_point.m_supernode->get_last_stmt ();
+	      const gimple *last_stmt
+		= src_point.get_supernode ()->get_last_stmt ();
 	      gcc_assert (last_stmt);
 	      const gcall *longjmp_call = as_a <const gcall *> (last_stmt);
 
@@ -2650,10 +2655,10 @@ exploded_path::feasible_p (logger *logger) const
       /* Handle phi nodes on an edge leaving a PK_BEFORE_SUPERNODE (to
 	 a PK_BEFORE_STMT, or a PK_AFTER_SUPERNODE if no stmts).
 	 This will typically not be associated with a superedge.  */
-      if (src_point.m_from_edge)
+      if (src_point.get_from_edge ())
 	{
 	  const cfg_superedge *last_cfg_superedge
-	    = src_point.m_from_edge->dyn_cast_cfg_superedge ();
+	    = src_point.get_from_edge ()->dyn_cast_cfg_superedge ();
 	  if (last_cfg_superedge)
 	    {
 	      if (logger)
@@ -2931,7 +2936,7 @@ public:
 	return;
       }
 
-    const call_string &cs = en->get_point ().m_call_string;
+    const call_string &cs = en->get_point ().get_call_string ();
     function_call_string key (fun, cs);
     function_call_string_cluster **slot = m_map.get (key);
     if (slot)
@@ -3122,7 +3127,7 @@ exploded_graph::dump_exploded_nodes () const
   hash_set<const gimple *> seen;
   FOR_EACH_VEC_ELT (m_nodes, i, enode)
     {
-      if (enode->get_point ().m_kind != PK_BEFORE_STMT)
+      if (enode->get_point ().get_kind () != PK_BEFORE_STMT)
 	continue;
 
       if (const gimple *stmt = enode->get_stmt ())
@@ -3138,7 +3143,7 @@ exploded_graph::dump_exploded_nodes () const
 	      exploded_node *other_enode;
 	      FOR_EACH_VEC_ELT (m_nodes, j, other_enode)
 		{
-		  if (other_enode->get_point ().m_kind != PK_BEFORE_STMT)
+		  if (other_enode->get_point ().get_kind () != PK_BEFORE_STMT)
 		    continue;
 		  if (other_enode->get_stmt () == stmt)
 		    enodes.safe_push (other_enode);
@@ -3263,7 +3268,7 @@ public:
 	    FOR_EACH_VEC_ELT (args.m_eg->m_nodes, i, enode)
 	      {
 		if (enode->get_point ().get_function () == m_fun
-		    && enode->get_point ().m_call_string == *cs)
+		    && enode->get_point ().get_call_string () == *cs)
 		  num_enodes++;
 	      }
 	    if (num_enodes > 0)
diff --git a/gcc/analyzer/exploded-graph.h b/gcc/analyzer/exploded-graph.h
index 8eb22c1..c5c33fb 100644
--- a/gcc/analyzer/exploded-graph.h
+++ b/gcc/analyzer/exploded-graph.h
@@ -246,7 +246,7 @@ public:
     const program_point &origin_point = m_enode_origin->get_point ();
 
     /* "origin_point" ought to be before the call to "setjmp".  */
-    gcc_assert (origin_point.m_kind == PK_BEFORE_STMT);
+    gcc_assert (origin_point.get_kind () == PK_BEFORE_STMT);
 
     /* TODO: assert that it's the final stmt in its supernode.  */
 
diff --git a/gcc/analyzer/program-point.cc b/gcc/analyzer/program-point.cc
index 5c32d82..486a6b3 100644
--- a/gcc/analyzer/program-point.cc
+++ b/gcc/analyzer/program-point.cc
@@ -1,4 +1,4 @@
-/* A class for representing a location within the program.
+/* Classes for representing locations within the program.
    Copyright (C) 2019 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -54,16 +54,14 @@ point_kind_to_string (enum point_kind pk)
     }
 }
 
-/* Print this program_point to PP.  */
+/* class function_point.  */
+
+/* Print this function_point to PP.  */
 
 void
-program_point::print (pretty_printer *pp, const format &f) const
+function_point::print (pretty_printer *pp, const format &f) const
 {
-  pp_string (pp, "callstring: ");
-  m_call_string.print (pp);
-  f.spacer (pp);
-
-  switch (m_kind)
+  switch (get_kind ())
     {
     default:
       gcc_unreachable ();
@@ -109,6 +107,57 @@ program_point::print (pretty_printer *pp, const format &f) const
     }
 }
 
+/* Generate a hash value for this function_point.  */
+
+hashval_t
+function_point::hash () const
+{
+  /* FIXME: this was showing up in the profile, but I think it's an
+     underlying O(n^2) issue.  */
+#if 1
+  hashval_t result = 0;
+  if (m_supernode)
+    result ^= m_supernode->m_index;
+  //result ^= (hashval_t)m_from_edge;
+  result ^= (hashval_t)m_stmt_idx;
+  result ^= (hashval_t)m_kind;
+  return result;
+#else
+  inchash::hash hstate;
+  if (m_supernode)
+    hstate.add_int (m_supernode->m_index);
+  hstate.add_ptr (m_from_edge);
+  hstate.add_int (m_stmt_idx);
+  hstate.add_int (m_kind);
+  return hstate.end ();
+#endif
+}
+
+/* Get the gimple stmt for this function_point, if any.  */
+
+const gimple *
+function_point::get_stmt () const
+{
+  if (m_kind == PK_BEFORE_STMT)
+    return m_supernode->m_stmts[m_stmt_idx];
+  else if (m_kind == PK_AFTER_SUPERNODE)
+    return m_supernode->get_last_stmt ();
+  else
+    return NULL;
+}
+
+/* Get a location for this function_point, if any.  */
+
+location_t
+function_point::get_location () const
+{
+  const gimple *stmt = get_stmt ();
+  if (stmt)
+    return stmt->location;
+
+  return UNKNOWN_LOCATION;
+}
+
 /* A subclass of diagnostic_context for use by
    program_point::print_source_line.  */
 
@@ -127,10 +176,10 @@ public:
   }
 };
 
-/* Print the source line (if any) for this program_point to PP.  */
+/* Print the source line (if any) for this function_point to PP.  */
 
 void
-program_point::print_source_line (pretty_printer *pp) const
+function_point::print_source_line (pretty_printer *pp) const
 {
   const gimple *stmt = get_stmt ();
   if (!stmt)
@@ -142,6 +191,20 @@ program_point::print_source_line (pretty_printer *pp) const
   pp_string (pp, pp_formatted_text (tmp_dc.printer));
 }
 
+/* class program_point.  */
+
+/* Print this program_point to PP.  */
+
+void
+program_point::print (pretty_printer *pp, const format &f) const
+{
+  pp_string (pp, "callstring: ");
+  m_call_string.print (pp);
+  f.spacer (pp);
+
+  m_function_point.print (pp, f);
+}
+
 /* Dump this point to stderr.  */
 
 DEBUG_FUNCTION void
@@ -160,40 +223,11 @@ hashval_t
 program_point::hash () const
 {
   inchash::hash hstate;
-  if (m_supernode)
-    hstate.add_int (m_supernode->m_index);
-  hstate.add_ptr (m_from_edge);
-  hstate.add_int (m_stmt_idx);
-  hstate.add_int (m_kind);
+  hstate.merge_hash (m_function_point.hash ());
   hstate.merge_hash (m_call_string.hash ());
   return hstate.end ();
 }
 
-/* Get the gimple stmt for this program_point, if any.  */
-
-const gimple *
-program_point::get_stmt () const
-{
-  if (m_kind == PK_BEFORE_STMT)
-    return m_supernode->m_stmts[m_stmt_idx];
-  else if (m_kind == PK_AFTER_SUPERNODE)
-    return m_supernode->get_last_stmt ();
-  else
-    return NULL;
-}
-
-/* Get a location for this program_point, if any.  */
-
-location_t
-program_point::get_location () const
-{
-  const gimple *stmt = get_stmt ();
-  if (stmt)
-    return stmt->location;
-
-  return UNKNOWN_LOCATION;
-}
-
 /* Check to see if SUCC is a valid edge to take (ensuring that we have
    interprocedurally valid paths in the exploded graph, and enforcing
    recursion limits).
@@ -298,10 +332,10 @@ program_point::on_edge (exploded_graph &eg,
    Return 0 if they are equal.  */
 
 int
-program_point::cmp_within_supernode_1 (const program_point &point_a,
-				       const program_point &point_b)
+function_point::cmp_within_supernode_1 (const function_point &point_a,
+					const function_point &point_b)
 {
-  gcc_assert (point_a.m_supernode == point_b.m_supernode);
+  gcc_assert (point_a.get_supernode () == point_b.get_supernode ());
 
   switch (point_a.m_kind)
     {
@@ -367,8 +401,8 @@ program_point::cmp_within_supernode_1 (const program_point &point_a,
    Return 0 if they are equal.  */
 
 int
-program_point::cmp_within_supernode (const program_point &point_a,
-				     const program_point &point_b)
+function_point::cmp_within_supernode (const function_point &point_a,
+				      const function_point &point_b)
 {
   int result = cmp_within_supernode_1 (point_a, point_b);
 
@@ -385,59 +419,45 @@ program_point::cmp_within_supernode (const program_point &point_a,
 
 namespace selftest {
 
-/* Verify that program_point::operator== works as expected.  */
+/* Verify that function_point::operator== works as expected.  */
 
 static void
-test_program_point_equality ()
+test_function_point_equality ()
 {
   const supernode *snode = NULL;
 
-  const call_string cs;
-
-  program_point a = program_point (snode, NULL, 0,
-				   PK_BEFORE_SUPERNODE,
-				   cs);
-
-  program_point b = program_point (snode, NULL, 0,
-				   PK_BEFORE_SUPERNODE,
-				   cs);
+  function_point a = function_point (snode, NULL, 0,
+				     PK_BEFORE_SUPERNODE);
+  function_point b = function_point::before_supernode (snode, NULL);
   ASSERT_EQ (a, b);
-  // TODO: verify with non-empty callstrings, with different edges
 }
 
-/* Verify that program_point::cmp_within_supernode works as expected.  */
+/* Verify that function_point::cmp_within_supernode works as expected.  */
 
 static void
-test_program_point_ordering ()
+test_function_point_ordering ()
 {
   const supernode *snode = NULL;
   const call_string call_string;
 
   /* Populate an array with various points within the same
      snode, in order.  */
-  auto_delete_vec<program_point> points;
-  points.safe_push (new program_point (snode, NULL, 0,
-				       PK_BEFORE_SUPERNODE,
-				       call_string));
-  points.safe_push (new program_point (snode, NULL, 0,
-				       PK_BEFORE_STMT,
-				       call_string));
-  points.safe_push (new program_point (snode, NULL, 1,
-				       PK_BEFORE_STMT,
-				       call_string));
-  points.safe_push (new program_point (snode, NULL, 0,
-				       PK_AFTER_SUPERNODE,
-				       call_string));
+  auto_vec<function_point> points;
+  points.safe_push (function_point::before_supernode (snode, NULL));
+  points.safe_push (function_point::before_stmt (snode, 0));
+  points.safe_push (function_point::before_stmt (snode, 1));
+  points.safe_push (function_point::after_supernode (snode));
+
   /* Check all pairs.  */
   unsigned i;
-  program_point *point_a;
+  function_point *point_a;
   FOR_EACH_VEC_ELT (points, i, point_a)
     {
       unsigned j;
-      program_point *point_b;
+      function_point *point_b;
       FOR_EACH_VEC_ELT (points, j, point_b)
 	{
-	  int cmp = program_point::cmp_within_supernode (*point_a, *point_b);
+	  int cmp = function_point::cmp_within_supernode (*point_a, *point_b);
 	  if (i == j)
 	    ASSERT_EQ (cmp, 0);
 	  if (i < j)
@@ -448,13 +468,33 @@ test_program_point_ordering ()
     }
 }
 
+/* Verify that program_point::operator== works as expected.  */
+
+static void
+test_program_point_equality ()
+{
+  const supernode *snode = NULL;
+
+  const call_string cs;
+
+  program_point a = program_point::before_supernode (snode, NULL,
+						     cs);
+
+  program_point b = program_point::before_supernode (snode, NULL,
+						     cs);
+
+  ASSERT_EQ (a, b);
+  // TODO: verify with non-empty callstrings, with different edges
+}
+
 /* Run all of the selftests within this file.  */
 
 void
 analyzer_program_point_cc_tests ()
 {
+  test_function_point_equality ();
+  test_function_point_ordering ();
   test_program_point_equality ();
-  test_program_point_ordering ();
 }
 
 } // namespace selftest
diff --git a/gcc/analyzer/program-point.h b/gcc/analyzer/program-point.h
index 86c19c6..8d5f5ac 100644
--- a/gcc/analyzer/program-point.h
+++ b/gcc/analyzer/program-point.h
@@ -1,4 +1,4 @@
-/* A class for representing a location within the program.
+/* Classes for representing locations within the program.
    Copyright (C) 2019 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -65,24 +65,26 @@ public:
 
 ////////////////////////////////////////////////////////////////////////////
 
-/* A class for representing a location within the program.
+/* A class for representing a location within the program, without
+   interprocedural information.
 
    This represents a fine-grained location within the supergraph (or
-   within one of its nodes), along with a call string giving the
-   interprocedural context.  */
+   within one of its nodes).  */
 
-class program_point
+class function_point
 {
 public:
-  program_point (const supernode *supernode,
-		 const superedge *from_edge,
-		 unsigned stmt_idx,
-		 enum point_kind kind,
-		 const call_string &call_string)
+  function_point (const supernode *supernode,
+		  const superedge *from_edge,
+		  unsigned stmt_idx,
+		  enum point_kind kind)
   : m_supernode (supernode), m_from_edge (from_edge),
-    m_stmt_idx (stmt_idx), m_kind (kind),
-    m_call_string (call_string)
+    m_stmt_idx (stmt_idx), m_kind (kind)
   {
+    if (from_edge)
+      gcc_assert (m_kind == PK_BEFORE_SUPERNODE);
+    if (stmt_idx)
+      gcc_assert (m_kind == PK_BEFORE_STMT);
   }
 
   void print (pretty_printer *pp, const format &f) const;
@@ -90,13 +92,12 @@ public:
   void dump () const;
 
   hashval_t hash () const;
-  bool operator== (const program_point &other) const
+  bool operator== (const function_point &other) const
   {
     return (m_supernode == other.m_supernode
 	    && m_from_edge == other.m_from_edge
 	    && m_stmt_idx == other.m_stmt_idx
-	    && m_kind == other.m_kind
-	    && m_call_string == other.m_call_string);
+	    && m_kind == other.m_kind);
   }
 
   /* Accessors.  */
@@ -111,6 +112,134 @@ public:
   }
   const gimple *get_stmt () const;
   location_t get_location () const;
+  enum point_kind get_kind () const { return m_kind; }
+  const superedge *get_from_edge () const
+  {
+    return m_from_edge;
+  }
+  unsigned get_stmt_idx () const
+  {
+    gcc_assert (m_kind == PK_BEFORE_STMT);
+    return m_stmt_idx;
+  }
+
+  /* Factory functions for making various kinds of program_point.  */
+
+  static function_point from_function_entry (const supergraph &sg,
+					    function *fun)
+  {
+    return before_supernode (sg.get_node_for_function_entry (fun),
+			     NULL);
+  }
+
+  static function_point before_supernode (const supernode *supernode,
+					  const superedge *from_edge)
+  {
+    return function_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE);
+  }
+
+  static function_point before_stmt (const supernode *supernode,
+				     unsigned stmt_idx)
+  {
+    return function_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT);
+  }
+
+  static function_point after_supernode (const supernode *supernode)
+  {
+    return function_point (supernode, NULL, 0, PK_AFTER_SUPERNODE);
+  }
+
+  /* Support for hash_map.  */
+
+  static function_point empty ()
+  {
+    return function_point (NULL, NULL, 0, PK_EMPTY);
+  }
+  static function_point deleted ()
+  {
+    return function_point (NULL, NULL, 0, PK_DELETED);
+  }
+
+  static int cmp_within_supernode_1 (const function_point &point_a,
+				     const function_point &point_b);
+  static int cmp_within_supernode (const function_point &point_a,
+				   const function_point &point_b);
+
+//private:
+  const supernode *m_supernode;
+  const superedge *m_from_edge; /* for PK_BEFORE_SUPERNODE.  */
+  unsigned m_stmt_idx;
+  enum point_kind m_kind;
+};
+
+////////////////////////////////////////////////////////////////////////////
+
+/* A class for representing a location within the program, including
+   interprocedural information.
+
+   This represents a fine-grained location within the supergraph (or
+   within one of its nodes), along with a call string giving the
+   interprocedural context.  */
+
+class program_point
+{
+public:
+  program_point (const function_point &fn_point,
+		 const call_string &call_string)
+  : m_function_point (fn_point),
+    m_call_string (call_string)
+  {
+  }
+
+  void print (pretty_printer *pp, const format &f) const;
+  void print_source_line (pretty_printer *pp) const;
+  void dump () const;
+
+  hashval_t hash () const;
+  bool operator== (const program_point &other) const
+  {
+    return (m_function_point == other.m_function_point
+	    && m_call_string == other.m_call_string);
+  }
+
+  /* Accessors.  */
+
+  const function_point &get_function_point () const { return m_function_point; }
+  const call_string &get_call_string () const { return m_call_string; }
+
+  const supernode *get_supernode () const
+  {
+    return m_function_point.get_supernode ();
+  }
+  function *get_function () const
+  {
+    return m_function_point.get_function ();
+  }
+  tree get_fndecl () const
+  {
+    gcc_assert (get_kind () != PK_ORIGIN);
+    return get_function ()->decl;
+  }
+  const gimple *get_stmt () const
+  {
+    return m_function_point.get_stmt ();
+  }
+  location_t get_location () const
+  {
+    return m_function_point.get_location ();
+  }
+  enum point_kind get_kind () const
+  {
+    return m_function_point.get_kind ();
+  }
+  const superedge *get_from_edge () const
+  {
+    return m_function_point.get_from_edge ();
+  }
+  unsigned get_stmt_idx () const
+  {
+    return m_function_point.get_stmt_idx ();
+  }
 
   /* Get the number of frames we expect at this program point.
      This will be one more than the length of the call_string
@@ -118,7 +247,7 @@ public:
      node, which doesn't have any frames.  */
   int get_stack_depth () const
   {
-    if (m_kind == PK_ORIGIN)
+    if (get_kind () == PK_ORIGIN)
       return 0;
     return m_call_string.length () + 1;
   }
@@ -128,15 +257,16 @@ public:
   static program_point from_function_entry (const supergraph &sg,
 					    function *fun)
   {
-    return before_supernode (sg.get_node_for_function_entry (fun),
-			     NULL, call_string ());
+    return program_point (function_point::from_function_entry (sg, fun),
+			  call_string ());
   }
 
   static program_point before_supernode (const supernode *supernode,
 					 const superedge *from_edge,
 					 const call_string &call_string)
   {
-    return program_point (supernode, from_edge, 0, PK_BEFORE_SUPERNODE,
+    return program_point (function_point::before_supernode (supernode,
+							    from_edge),
 			  call_string);
   }
 
@@ -144,14 +274,14 @@ public:
 				    unsigned stmt_idx,
 				    const call_string &call_string)
   {
-    return program_point (supernode, NULL, stmt_idx, PK_BEFORE_STMT,
+    return program_point (function_point::before_stmt (supernode, stmt_idx),
 			  call_string);
   }
 
   static program_point after_supernode (const supernode *supernode,
 					const call_string &call_string)
   {
-    return program_point (supernode, NULL, 0, PK_AFTER_SUPERNODE,
+    return program_point (function_point::after_supernode (supernode),
 			  call_string);
   }
 
@@ -159,25 +289,24 @@ public:
 
   static program_point empty ()
   {
-    return program_point (NULL, NULL, 0, PK_EMPTY, call_string ());
+    return program_point (function_point::empty (), call_string ());
   }
   static program_point deleted ()
   {
-    return program_point (NULL, NULL, 0, PK_DELETED, call_string ());
+    return program_point (function_point::deleted (), call_string ());
   }
 
   bool on_edge (exploded_graph &eg, const superedge *succ);
 
+#if 0
   static int cmp_within_supernode_1 (const program_point &point_a,
 				     const program_point &point_b);
   static int cmp_within_supernode (const program_point &point_a,
 				   const program_point &point_b);
+#endif
 
-//private:
-  const supernode *m_supernode;
-  const superedge *m_from_edge; /* for PK_BEFORE_SUPERNODE.  */
-  unsigned m_stmt_idx;
-  enum point_kind m_kind;
+ private:
+  const function_point m_function_point;
   call_string m_call_string;
 };
 
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index b18f912..95ee0c3 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -657,7 +657,7 @@ program_state::on_edge (exploded_graph &eg,
 {
   /* Update state.  */
   const program_point &point = enode.get_point ();
-  const gimple *last_stmt = point.m_supernode->get_last_stmt ();
+  const gimple *last_stmt = point.get_supernode ()->get_last_stmt ();
 
   /* For conditionals and switch statements, add the
      relevant conditions (for the specific edge) to new_state;
@@ -699,11 +699,6 @@ program_state::prune_for_point (exploded_graph &eg,
   if (!fun)
     return *this;
 
-  /* The points in the state map don't have call strings, so flatten
-     accordingly.  */
-  program_point flat_point (point);
-  flat_point.m_call_string = call_string ();
-
   program_state new_state (*this);
 
   purge_stats stats;
@@ -731,7 +726,7 @@ program_state::prune_for_point (exploded_graph &eg,
 	    {
 	      const state_purge_per_ssa_name &per_ssa
 		= pm->get_data_for_ssa_name (var);
-	      if (!per_ssa.needed_at_point_p (flat_point))
+	      if (!per_ssa.needed_at_point_p (point.get_function_point ()))
 		{
 		  region *region
 		    = new_state.m_region_model->get_region (rid);
diff --git a/gcc/analyzer/state-purge.cc b/gcc/analyzer/state-purge.cc
index 000c3f9..60bbdb9 100644
--- a/gcc/analyzer/state-purge.cc
+++ b/gcc/analyzer/state-purge.cc
@@ -1,4 +1,4 @@
-/* Classes for purging state at program_points.
+/* Classes for purging state at function_points.
    Copyright (C) 2019 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -95,11 +95,7 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
       map.log ("def stmt: %s", pp_formatted_text (&pp));
     }
 
-  /* The worklist for the traversal.
-     We can't have a vec<program_point> here because vec<T> require T to be
-     a POD.  Hence (annoyingly) we use vec<program_point *> and dynamically
-     allocate.  */
-  auto_vec<program_point *> worklist;
+  auto_vec<function_point> worklist;
 
   /* Add all immediate uses of var to the worklist.
      Compare with debug_immediate_uses.  */
@@ -141,9 +137,9 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
 			      edge in_edge = gimple_phi_arg_edge (phi, arg_idx);
 			      const superedge *in_sedge
 				= map.get_sg ().get_edge_for_cfg_edge (in_edge);
-			      program_point point
-				= program_point::before_supernode
-				(snode, in_sedge, call_string ());
+			      function_point point
+				= function_point::before_supernode
+				(snode, in_sedge);
 			      add_to_worklist (point, &worklist,
 					       map.get_logger ());
 			      m_points_needing_var.add (point);
@@ -154,7 +150,7 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
 	    }
 	  else
 	    {
-	      program_point point = before_use_stmt (map, use_stmt);
+	      function_point point = before_use_stmt (map, use_stmt);
 	      add_to_worklist (point, &worklist, map.get_logger ());
 	      m_points_needing_var.add (point);
 
@@ -165,8 +161,8 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
 		{
 		  if (map.get_logger ())
 		    map.log ("last stmt in BB");
-		  program_point point
-		    = program_point::after_supernode (snode, call_string ());
+		  function_point point
+		    = function_point::after_supernode (snode);
 		  add_to_worklist (point, &worklist, map.get_logger ());
 		  m_points_needing_var.add (point);
 		}
@@ -182,10 +178,8 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
     log_scope s (map.get_logger (), "processing worklist");
     while (worklist.length () > 0)
       {
-	program_point *point_ptr = worklist.pop ();
-	program_point point (*point_ptr);
-	process_point (*point_ptr, &worklist, map.get_logger ());
-	delete point_ptr;
+	function_point point = worklist.pop ();
+	process_point (point, &worklist, map.get_logger ());
     }
   }
 
@@ -207,15 +201,15 @@ state_purge_per_ssa_name::state_purge_per_ssa_name (const state_purge_map &map,
 /* Return true if the SSA name is needed at POINT.  */
 
 bool
-state_purge_per_ssa_name::needed_at_point_p (const program_point &point) const
+state_purge_per_ssa_name::needed_at_point_p (const function_point &point) const
 {
   return const_cast <point_set_t &> (m_points_needing_var).contains (point);
 }
 
-/* Get the program_point representing immediately before USE_STMT.
+/* Get the function_point representing immediately before USE_STMT.
    Subroutine of ctor.  */
 
-program_point
+function_point
 state_purge_per_ssa_name::before_use_stmt (const state_purge_map &map,
 					   const gimple *use_stmt)
 {
@@ -224,15 +218,15 @@ state_purge_per_ssa_name::before_use_stmt (const state_purge_map &map,
   const supernode *supernode
     = map.get_sg ().get_supernode_for_stmt (use_stmt);
   unsigned int stmt_idx = supernode->get_stmt_index (use_stmt);
-  return program_point::before_stmt (supernode, stmt_idx, call_string ());
+  return function_point::before_stmt (supernode, stmt_idx);
 }
 
 /* Add POINT to *WORKLIST if the point has not already been seen.
    Subroutine of ctor.  */
 
 void
-state_purge_per_ssa_name::add_to_worklist (const program_point &point,
-					   auto_vec<program_point *> *worklist,
+state_purge_per_ssa_name::add_to_worklist (const function_point &point,
+					   auto_vec<function_point> *worklist,
 					   logger *logger)
 {
   LOG_FUNC (logger);
@@ -254,7 +248,7 @@ state_purge_per_ssa_name::add_to_worklist (const program_point &point,
     {
       if (logger)
 	logger->log ("not seen; adding to worklist for %qE", m_var);
-      worklist->safe_push (new program_point (point));
+      worklist->safe_push (point);
     }
 }
 
@@ -262,8 +256,8 @@ state_purge_per_ssa_name::add_to_worklist (const program_point &point,
    Iterate over predecessors of POINT, adding to WORKLIST.  */
 
 void
-state_purge_per_ssa_name::process_point (const program_point &point,
-					 auto_vec<program_point *> *worklist,
+state_purge_per_ssa_name::process_point (const function_point &point,
+					 auto_vec<function_point> *worklist,
 					 logger *logger)
 {
   LOG_FUNC (logger);
@@ -282,7 +276,7 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 
   const supernode *snode = point.get_supernode ();
 
-  switch (point.m_kind)
+  switch (point.get_kind ())
     {
     default:
       gcc_unreachable ();
@@ -310,8 +304,7 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 	  {
 	    if (point.m_from_edge->m_src)
 	      add_to_worklist
-		(program_point::after_supernode (point.m_from_edge->m_src,
-						 call_string ()),
+		(function_point::after_supernode (point.m_from_edge->m_src),
 		 worklist, logger);
 	  }
 	else
@@ -328,9 +321,8 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 	    return;
 	  }
 	if (point.m_stmt_idx > 0)
-	  add_to_worklist (program_point::before_stmt (snode,
-						       point.m_stmt_idx - 1,
-						       call_string ()),
+	  add_to_worklist (function_point::before_stmt (snode,
+							point.m_stmt_idx - 1),
 			   worklist, logger);
 	else
 	{
@@ -339,9 +331,8 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 	  unsigned i;
 	  superedge *pred;
 	  FOR_EACH_VEC_ELT (snode->m_preds, i, pred)
-	    add_to_worklist (program_point::before_supernode (snode,
-							      pred,
-							      call_string ()),
+	    add_to_worklist (function_point::before_supernode (snode,
+							       pred),
 			     worklist, logger);
 	}
       }
@@ -351,9 +342,8 @@ state_purge_per_ssa_name::process_point (const program_point &point,
       {
 	if (snode->m_stmts.length ())
 	  add_to_worklist
-	    (program_point::before_stmt (snode,
-					 snode->m_stmts.length () - 1,
-					 call_string ()),
+	    (function_point::before_stmt (snode,
+					  snode->m_stmts.length () - 1),
 	     worklist, logger);
 	else
 	  {
@@ -362,9 +352,8 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 	    unsigned i;
 	    superedge *pred;
 	    FOR_EACH_VEC_ELT (snode->m_preds, i, pred)
-	      add_to_worklist (program_point::before_supernode (snode,
-								pred,
-								call_string ()),
+	      add_to_worklist (function_point::before_supernode (snode,
+								 pred),
 			       worklist, logger);
 	    /* If it's the initial BB, add it, to ensure that we
 	       have "before supernode" for the initial ENTRY block, and don't
@@ -372,9 +361,7 @@ state_purge_per_ssa_name::process_point (const program_point &point,
 	    if (snode->entry_p ())
 	      {
 		add_to_worklist
-		  (program_point::before_supernode (snode,
-						    NULL,
-						    call_string ()),
+		  (function_point::before_supernode (snode, NULL),
 		   worklist, logger);
 	      }
 	  }
@@ -400,8 +387,8 @@ state_purge_annotator::add_node_annotations (pretty_printer *pp,
    pp_left_brace (pp);
    pp_write_text_to_stream (pp);
 
-   program_point before_supernode
-     (program_point::before_supernode (&n, NULL, call_string ()));
+   function_point before_supernode
+     (function_point::before_supernode (&n, NULL));
 
    for (state_purge_map::iterator iter = m_map->begin ();
 	iter != m_map->end ();
@@ -438,8 +425,8 @@ state_purge_annotator::add_stmt_annotations (pretty_printer *pp,
 
   const supernode *supernode = m_map->get_sg ().get_supernode_for_stmt (stmt);
   unsigned int stmt_idx = supernode->get_stmt_index (stmt);
-  program_point before_stmt
-    (program_point::before_stmt (supernode, stmt_idx, call_string ()));
+  function_point before_stmt
+    (function_point::before_stmt (supernode, stmt_idx));
 
   auto_vec<tree> needed;
   auto_vec<tree> not_needed;
diff --git a/gcc/analyzer/state-purge.h b/gcc/analyzer/state-purge.h
index adeaa63..bec7003 100644
--- a/gcc/analyzer/state-purge.h
+++ b/gcc/analyzer/state-purge.h
@@ -1,4 +1,4 @@
-/* Classes for purging state at program_points.
+/* Classes for purging state at function_points.
    Copyright (C) 2019 Free Software Foundation, Inc.
    Contributed by David Malcolm <dmalcolm@redhat.com>.
 
@@ -26,50 +26,50 @@ along with GCC; see the file COPYING3.  If not see
 
 ///////////////////////////////////////////////////////////////////////////
 
-/* Hash traits for program_point.  */
+/* Hash traits for function_point.  */
 
-template <> struct default_hash_traits<program_point>
-: public pod_hash_traits<program_point>
+template <> struct default_hash_traits<function_point>
+: public pod_hash_traits<function_point>
 {
 };
 
 template <>
 inline hashval_t
-pod_hash_traits<program_point>::hash (value_type v)
+pod_hash_traits<function_point>::hash (value_type v)
 {
   return v.hash ();
 }
 
 template <>
 inline bool
-pod_hash_traits<program_point>::equal (const value_type &existing,
+pod_hash_traits<function_point>::equal (const value_type &existing,
                                  const value_type &candidate)
 {
   return existing == candidate;
 }
 template <>
 inline void
-pod_hash_traits<program_point>::mark_deleted (value_type &v)
+pod_hash_traits<function_point>::mark_deleted (value_type &v)
 {
-  v = program_point::deleted ();
+  v = function_point::deleted ();
 }
 template <>
 inline void
-pod_hash_traits<program_point>::mark_empty (value_type &v)
+pod_hash_traits<function_point>::mark_empty (value_type &v)
 {
-  v = program_point::empty ();
+  v = function_point::empty ();
 }
 template <>
 inline bool
-pod_hash_traits<program_point>::is_deleted (value_type v)
+pod_hash_traits<function_point>::is_deleted (value_type v)
 {
-  return v.m_kind == PK_DELETED;
+  return v.get_kind () == PK_DELETED;
 }
 template <>
 inline bool
-pod_hash_traits<program_point>::is_empty (value_type v)
+pod_hash_traits<function_point>::is_empty (value_type v)
 {
-  return v.m_kind == PK_EMPTY;
+  return v.get_kind () == PK_EMPTY;
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -110,7 +110,7 @@ private:
 /* The part of a state_purge_map relating to a specific SSA name.
 
    The result of analyzing a given SSA name, recording which
-   program_points need to retain state information about it to handle
+   function_points need to retain state information about it to handle
    their successor states, so that we can simplify program_state objects,
    in the hope of reducing state-blowup.  */
 
@@ -121,25 +121,21 @@ public:
 			    tree var,
 			    function *fun);
 
-  bool needed_at_point_p (const program_point &point) const;
-
-  /* This stores points, but ignores interprocedural issues;
-     everything will be at depth 0.
-     TODO: should we build a program_point graph first???  */
+  bool needed_at_point_p (const function_point &point) const;
 
 private:
-  static program_point before_use_stmt (const state_purge_map &map,
-					const gimple *use_stmt);
+  static function_point before_use_stmt (const state_purge_map &map,
+					 const gimple *use_stmt);
 
-  void add_to_worklist (const program_point &point,
-			auto_vec<program_point *> *worklist,
+  void add_to_worklist (const function_point &point,
+			auto_vec<function_point> *worklist,
 			logger *logger);
 
-  void process_point (const program_point &point,
-		      auto_vec<program_point *> *worklist,
+  void process_point (const function_point &point,
+		      auto_vec<function_point> *worklist,
 		      logger *logger);
 
-  typedef hash_set<program_point> point_set_t;
+  typedef hash_set<function_point> point_set_t;
   point_set_t m_points_needing_var;
   tree m_var;
 };
-- 
1.8.5.3

