diff options
Diffstat (limited to 'gcc/analyzer/program-state.cc')
-rw-r--r-- | gcc/analyzer/program-state.cc | 129 |
1 files changed, 94 insertions, 35 deletions
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc index 7501103..7ad581c 100644 --- a/gcc/analyzer/program-state.cc +++ b/gcc/analyzer/program-state.cc @@ -1122,52 +1122,90 @@ program_state::prune_for_point (exploded_graph &eg, if (pm) { unsigned num_ssas_purged = 0; - auto_vec<const decl_region *> ssa_name_regs; - new_state.m_region_model->get_ssa_name_regions_for_current_frame - (&ssa_name_regs); - ssa_name_regs.qsort (region::cmp_ptr_ptr); + unsigned num_decls_purged = 0; + auto_vec<const decl_region *> regs; + new_state.m_region_model->get_regions_for_current_frame (®s); + regs.qsort (region::cmp_ptr_ptr); unsigned i; const decl_region *reg; - FOR_EACH_VEC_ELT (ssa_name_regs, i, reg) + FOR_EACH_VEC_ELT (regs, i, reg) { - tree ssa_name = reg->get_decl (); - const state_purge_per_ssa_name &per_ssa - = pm->get_data_for_ssa_name (ssa_name); - if (!per_ssa.needed_at_point_p (point.get_function_point ())) + const tree node = reg->get_decl (); + if (TREE_CODE (node) == SSA_NAME) { - /* Don't purge bindings of SSA names to svalues - that have unpurgable sm-state, so that leaks are - reported at the end of the function, rather than - at the last place that such an SSA name is referred to. - - But do purge them for temporaries (when SSA_NAME_VAR is - NULL), so that we report for cases where a leak happens when - a variable is overwritten with another value, so that the leak - is reported at the point of overwrite, rather than having - temporaries keep the value reachable until the frame is - popped. */ - const svalue *sval - = new_state.m_region_model->get_store_value (reg, NULL); - if (!new_state.can_purge_p (eg.get_ext_state (), sval) - && SSA_NAME_VAR (ssa_name)) + const tree ssa_name = node; + const state_purge_per_ssa_name &per_ssa + = pm->get_data_for_ssa_name (node); + if (!per_ssa.needed_at_point_p (point.get_function_point ())) { - /* (currently only state maps can keep things - alive). */ - if (logger) - logger->log ("not purging binding for %qE" - " (used by state map)", ssa_name); - continue; + /* Don't purge bindings of SSA names to svalues + that have unpurgable sm-state, so that leaks are + reported at the end of the function, rather than + at the last place that such an SSA name is referred to. + + But do purge them for temporaries (when SSA_NAME_VAR is + NULL), so that we report for cases where a leak happens when + a variable is overwritten with another value, so that the leak + is reported at the point of overwrite, rather than having + temporaries keep the value reachable until the frame is + popped. */ + const svalue *sval + = new_state.m_region_model->get_store_value (reg, NULL); + if (!new_state.can_purge_p (eg.get_ext_state (), sval) + && SSA_NAME_VAR (ssa_name)) + { + /* (currently only state maps can keep things + alive). */ + if (logger) + logger->log ("not purging binding for %qE" + " (used by state map)", ssa_name); + continue; + } + + new_state.m_region_model->purge_region (reg); + num_ssas_purged++; } - - new_state.m_region_model->purge_region (reg); - num_ssas_purged++; + } + else + { + const tree decl = node; + gcc_assert (TREE_CODE (node) == VAR_DECL + || TREE_CODE (node) == PARM_DECL + || TREE_CODE (node) == RESULT_DECL); + if (const state_purge_per_decl *per_decl + = pm->get_any_data_for_decl (decl)) + if (!per_decl->needed_at_point_p (point.get_function_point ())) + { + /* Don't purge bindings of decls if there are svalues + that have unpurgable sm-state within the decl's cluster, + so that leaks are reported at the end of the function, + rather than at the last place that such a decl is + referred to. */ + if (!new_state.can_purge_base_region_p (eg.get_ext_state (), + reg)) + { + /* (currently only state maps can keep things + alive). */ + if (logger) + logger->log ("not purging binding for %qE" + " (value in binding used by state map)", + decl); + continue; + } + + new_state.m_region_model->purge_region (reg); + num_decls_purged++; + } } } - if (num_ssas_purged > 0) + if (num_ssas_purged > 0 || num_decls_purged > 0) { if (logger) - logger->log ("num_ssas_purged: %i", num_ssas_purged); + { + logger->log ("num_ssas_purged: %i", num_ssas_purged); + logger->log ("num_decl_purged: %i", num_decls_purged); + } impl_region_model_context ctxt (eg, enode_for_diag, this, &new_state, @@ -1182,6 +1220,27 @@ program_state::prune_for_point (exploded_graph &eg, return new_state; } +/* Return true if there are no unpurgeable bindings within BASE_REG. */ + +bool +program_state::can_purge_base_region_p (const extrinsic_state &ext_state, + const region *base_reg) const +{ + binding_cluster *cluster + = m_region_model->get_store ()->get_cluster (base_reg); + if (!cluster) + return true; + + for (auto iter : *cluster) + { + const svalue *sval = iter.second; + if (!can_purge_p (ext_state, sval)) + return false; + } + + return true; +} + /* Get a representative tree to use for describing SVAL. */ tree |