binding_cluster::can_merge_p (const binding_cluster *cluster_a,
const binding_cluster *cluster_b,
binding_cluster *out_cluster,
+ store *out_store,
store_manager *mgr,
model_merger *merger)
{
{
gcc_assert (cluster_b != NULL);
gcc_assert (cluster_b->m_base_region == out_cluster->m_base_region);
- out_cluster->make_unknown_relative_to (cluster_b, mgr);
+ out_cluster->make_unknown_relative_to (cluster_b, out_store, mgr);
return true;
}
if (cluster_b == NULL)
{
gcc_assert (cluster_a != NULL);
gcc_assert (cluster_a->m_base_region == out_cluster->m_base_region);
- out_cluster->make_unknown_relative_to (cluster_a, mgr);
+ out_cluster->make_unknown_relative_to (cluster_a, out_store, mgr);
return true;
}
void
binding_cluster::make_unknown_relative_to (const binding_cluster *other,
+ store *out_store,
store_manager *mgr)
{
for (map_t::iterator iter = other->m_map.begin ();
= mgr->get_svalue_manager ()->get_or_create_unknown_svalue
(iter_sval->get_type ());
m_map.put (iter_key, unknown_sval);
+
+ /* For any pointers in OTHER, the merger means that the
+ concrete pointer becomes an unknown value, which could
+ show up as a false report of a leak when considering what
+ pointers are live before vs after.
+ Avoid this by marking the base regions they point to as having
+ escaped. */
+ if (const region_svalue *region_sval
+ = iter_sval->dyn_cast_region_svalue ())
+ {
+ const region *base_reg
+ = region_sval->get_pointee ()->get_base_region ();
+ binding_cluster *c = out_store->get_or_create_cluster (base_reg);
+ c->mark_as_escaped ();
+ }
}
}
binding_cluster *out_cluster
= out_store->get_or_create_cluster (base_reg);
if (!binding_cluster::can_merge_p (cluster_a, cluster_b,
- out_cluster, mgr, merger))
+ out_cluster, out_store, mgr, merger))
return false;
}
return true;
m_reg->accept (v);
}
+/* Implementation of svalue::implicitly_live_p vfunc for region_svalue. */
+
+bool
+region_svalue::implicitly_live_p (const svalue_set &,
+ const region_model *model) const
+{
+ /* Pointers into clusters that have escaped should be treated as live. */
+ const region *base_reg = get_pointee ()->get_base_region ();
+ const store *store = model->get_store ();
+ if (const binding_cluster *c = store->get_cluster (base_reg))
+ if (c->escaped_p ())
+ return true;
+
+ return false;
+}
+
/* Evaluate the condition LHS OP RHS.
Subroutine of region_model::eval_condition for when we have a pair of
pointers. */