From 7d61c79df2caf5df43d90b48c80ea6c1be4f5088 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 15 Mar 2019 15:34:04 -0400
Subject: [PATCH 120/217] FIXME: call apply_constraints_for_call/return

---
 gcc/analyzer/constraints.cc              | 23 +++++++++++++++++++----
 gcc/analyzer/constraints.h               |  2 ++
 gcc/analyzer/engine.cc                   | 19 ++++++++++++++++++-
 gcc/testsuite/gcc.dg/analyzer/params-2.c | 20 ++++++++++++++++++++
 4 files changed, 59 insertions(+), 5 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/params-2.c

diff --git a/gcc/analyzer/constraints.cc b/gcc/analyzer/constraints.cc
index d86faaa..c7a0844 100644
--- a/gcc/analyzer/constraints.cc
+++ b/gcc/analyzer/constraints.cc
@@ -147,6 +147,20 @@ equiv_class::del (path_var v)
 
 /* FIXME.  */
 
+int
+equiv_class::get_min_stack_depth () const
+{
+  int result = INT_MAX;
+
+  int i;
+  path_var *iv;
+  FOR_EACH_VEC_ELT (m_vars, i, iv)
+    result = std::min (result, iv->m_stack_depth);
+  return result;
+}
+
+/* FIXME.  */
+
 void
 equiv_class::purge_stack_frame (int callee_stack_depth)
 {
@@ -347,10 +361,11 @@ path_state::apply_constraints_for_call (const call_superedge& edge)
        parm = DECL_CHAIN (parm), ++i)
     {
       tree parm_default_ssa = ssa_default_def (edge.m_dest->m_fun, parm);
-      add_constraint (path_var (parm_default_ssa, callee_stack_depth),
-		      EQ_EXPR,
-		      path_var (gimple_call_arg (call_stmt, i),
-				caller_stack_depth));
+      if (parm_default_ssa)
+	add_constraint (path_var (parm_default_ssa, callee_stack_depth),
+			EQ_EXPR,
+			path_var (gimple_call_arg (call_stmt, i),
+				  caller_stack_depth));
     }
   return true;
 }
diff --git a/gcc/analyzer/constraints.h b/gcc/analyzer/constraints.h
index adf5269..97149ba 100644
--- a/gcc/analyzer/constraints.h
+++ b/gcc/analyzer/constraints.h
@@ -64,6 +64,8 @@ public:
 
   tree get_any_constant () const { return m_constant; }
 
+  int get_min_stack_depth () const;
+
   void purge_stack_frame (int callee_stack_depth);
 
   /* An equivalence class can contain at most one constant.  */
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index de8d48e..520f9ce 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -2131,6 +2131,9 @@ engine::follow_call (sm_instance sm_inst, backtrace b, path_state ps,
     }
   b_in_callee.m_path.m_stack_depth++;
 
+  const call_superedge &call_sedge = *m_sg.get_edge_for_call (edge);
+  ps.apply_constraints_for_call (call_sedge);
+
   dfs_traverse (callee_sm_inst, callee_sm_inst, b_in_callee, ps, callee_node,
 		NULL /* FIXME */);
 
@@ -2221,6 +2224,13 @@ engine::follow_call (sm_instance sm_inst, backtrace b, path_state ps,
       = new call_summary (caller_node, edge, 0/*int depth,*/);
     new_b.m_path.add_event (event);
 
+    if (get_logger ())
+      log ("ps before applying return edge: %s", ps.to_str ().c_str ());
+    const call_superedge &return_sedge = *m_sg.get_edge_for_return (edge);
+    ps.apply_constraints_for_return (return_sedge);
+    if (get_logger ())
+      log ("ps after applying return edge: %s", ps.to_str ().c_str ());
+
     sm_instance restored_sm
       = restore_after_call (callee_summary_sm_inst, sm_inst, edge,
 			    rest_of_caller_node, new_b);
@@ -2397,6 +2407,13 @@ engine::detect_leaks (const supernode *node, const sm_instance &sm_inst,
 	  continue;
 	}
 
+      // FIXME: is anything in this ec still alive in parent stack frames?
+      if (ec.get_min_stack_depth () < old_ps.m_stack_depth)
+	{
+	  log ("alive within ancestor stack frame");
+	  continue;
+	}
+
       // TODO: determine most appropriate stmt
       const gimple *stmt = get_stmt_for_leak ((*iter).m_var, b);
 
@@ -2661,7 +2678,7 @@ engine::expand_path (const checker_path &in_path,
 		  tree maybe_parm = var;
 		  if (TREE_CODE (maybe_parm) == SSA_NAME)
 		    maybe_parm = SSA_NAME_VAR (maybe_parm);
-		  if (TREE_CODE (maybe_parm) == PARM_DECL)
+		  if (maybe_parm && TREE_CODE (maybe_parm) == PARM_DECL)
 		    {
 		      // TODO: what about ecs?
 		      tree arg = call_edge->get_arg_for_parm (maybe_parm);
diff --git a/gcc/testsuite/gcc.dg/analyzer/params-2.c b/gcc/testsuite/gcc.dg/analyzer/params-2.c
new file mode 100644
index 0000000..a670283
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/params-2.c
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+
+static void ensure_equal (int a, int b)
+{
+  if (a != b)
+    abort ();
+}
+
+void test(int i, int j)
+{
+  __analyzer_eval (i == j); /* { dg-warning "UNKNOWN" } */
+
+  ensure_equal (i, j);
+
+  __analyzer_eval (i == j); /* { dg-warning "TRUE" "" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "" { target *-*-* } .-1 } */
+  /* TODO(xfail): follow_call doesn't capture state changes within the
+     function into the resulting path_state, and so we don't retain the
+     "a@1 == i@0" etc info.  */
+}
-- 
1.8.5.3

