From f635f0ce87d687b177b734968f18226d50499e75 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 28 Oct 2020 20:11:41 -0400 Subject: [PATCH] analyzer: more non-determinism fixes 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 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 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 escaped_fn_regs + (m_mutable_base_regs.elements ()); for (hash_set::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.30.2