Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to master as f635f0ce87d687b177b734968f18226d50499e75.

gcc/analyzer/ChangeLog:
        * program-state.cc (sm_state_map::on_liveness_change): Sort the
        leaking svalues before calling on_state_leak.
        (program_state::detect_leaks): Likewise when calling
        on_svalue_leak.
        * region-model-reachability.cc
        (reachable_regions::mark_escaped_clusters): Likewise when
        calling on_escaped_function.
---
 gcc/analyzer/program-state.cc             | 26 ++++++++++++++++++++---
 gcc/analyzer/region-model-reachability.cc | 10 ++++++++-
 2 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 7d719b1a6da..b39e55a1a1e 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -517,6 +517,7 @@ sm_state_map::on_liveness_change (const svalue_set 
&live_svalues,
 {
   svalue_set svals_to_unset;
 
+  auto_vec<const svalue *> leaked_svals (m_map.elements ());
   for (map_t::iterator iter = m_map.begin ();
        iter != m_map.end ();
        ++iter)
@@ -527,10 +528,20 @@ sm_state_map::on_liveness_change (const svalue_set 
&live_svalues,
          svals_to_unset.add (iter_sval);
          entry_t e = (*iter).second;
          if (!m_sm.can_purge_p (e.m_state))
-           ctxt->on_state_leak (m_sm, iter_sval, e.m_state);
+           leaked_svals.quick_push (iter_sval);
        }
     }
 
+  leaked_svals.qsort (svalue::cmp_ptr_ptr);
+
+  unsigned i;
+  const svalue *sval;
+  FOR_EACH_VEC_ELT (leaked_svals, i, sval)
+    {
+      entry_t e = *m_map.get (sval);
+      ctxt->on_state_leak (m_sm, sval, e.m_state);
+    }
+
   for (svalue_set::iterator iter = svals_to_unset.begin ();
        iter != svals_to_unset.end (); ++iter)
     m_map.remove (*iter);
@@ -1181,6 +1192,7 @@ program_state::detect_leaks (const program_state 
&src_state,
                          dest_svalues);
     }
 
+  auto_vec <const svalue *> dead_svals (src_svalues.elements ());
   for (svalue_set::iterator iter = src_svalues.begin ();
        iter != src_svalues.end (); ++iter)
     {
@@ -1188,11 +1200,19 @@ program_state::detect_leaks (const program_state 
&src_state,
       /* For each sval reachable from SRC_STATE, determine if it is
         live in DEST_STATE: either explicitly reachable, or implicitly
         live based on the set of explicitly reachable svalues.
-        Call CTXT->on_svalue_leak on those that have ceased to be live.  */
+        Record those that have ceased to be live.  */
       if (!sval->live_p (dest_svalues, dest_state.m_region_model))
-       ctxt->on_svalue_leak (sval);
+       dead_svals.quick_push (sval);
     }
 
+  /* Call CTXT->on_svalue_leak on all svals in SRC_STATE  that have ceased
+     to be live, sorting them first to ensure deterministic behavior.  */
+  dead_svals.qsort (svalue::cmp_ptr_ptr);
+  unsigned i;
+  const svalue *sval;
+  FOR_EACH_VEC_ELT (dead_svals, i, sval)
+    ctxt->on_svalue_leak (sval);
+
   /* Purge dead svals from sm-state.  */
   ctxt->on_liveness_change (dest_svalues, dest_state.m_region_model);
 
diff --git a/gcc/analyzer/region-model-reachability.cc 
b/gcc/analyzer/region-model-reachability.cc
index f6f25cc9177..7fd89052737 100644
--- a/gcc/analyzer/region-model-reachability.cc
+++ b/gcc/analyzer/region-model-reachability.cc
@@ -248,6 +248,8 @@ void
 reachable_regions::mark_escaped_clusters (region_model_context *ctxt)
 {
   gcc_assert (ctxt);
+  auto_vec<const function_region *> escaped_fn_regs
+    (m_mutable_base_regs.elements ());
   for (hash_set<const region *>::iterator iter = m_mutable_base_regs.begin ();
        iter != m_mutable_base_regs.end (); ++iter)
     {
@@ -257,8 +259,14 @@ reachable_regions::mark_escaped_clusters 
(region_model_context *ctxt)
       /* If we have a function that's escaped, potentially add
         it to the worklist.  */
       if (const function_region *fn_reg = base_reg->dyn_cast_function_region 
())
-       ctxt->on_escaped_function (fn_reg->get_fndecl ());
+       escaped_fn_regs.quick_push (fn_reg);
     }
+  /* Sort to ensure deterministic results.  */
+  escaped_fn_regs.qsort (region::cmp_ptr_ptr);
+  unsigned i;
+  const function_region *fn_reg;
+  FOR_EACH_VEC_ELT (escaped_fn_regs, i, fn_reg)
+    ctxt->on_escaped_function (fn_reg->get_fndecl ());
 }
 
 /* Dump SET to PP, sorting it to avoid churn when comparing dumps.  */
-- 
2.26.2

Reply via email to