From b72bb2be79ac4bd04e2a86da2dfd14d275a69668 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 2 Jul 2020 12:00:46 -0400 Subject: [PATCH 277/315] FIXME: fix unknown-fns.c:test_1 by separating marking of escaped clusters from updating on unknown fncall --- gcc/analyzer/region-model2-reachability.cc | 12 +++-- gcc/analyzer/region-model2-reachability.h | 5 +- gcc/analyzer/region-model2.cc | 10 ++-- gcc/analyzer/store2.cc | 54 ++++++++++++++++------ gcc/analyzer/store2.h | 11 +++-- 5 files changed, 62 insertions(+), 30 deletions(-) diff --git a/gcc/analyzer/region-model2-reachability.cc b/gcc/analyzer/region-model2-reachability.cc index 644e330a396..1319ccafbca 100644 --- a/gcc/analyzer/region-model2-reachability.cc +++ b/gcc/analyzer/region-model2-reachability.cc @@ -201,20 +201,22 @@ reachable_region2s::handle_parm (const svalue2 *sval, tree param_type) } } -/* Update m_store to set the clusters that were found to be mutable - to "unknown" values. */ +/* Update m_store to mark the clusters that were found to be mutable + as having escaped. */ void -reachable_region2s::update_bindings (store2_manager *mgr) +reachable_region2s::mark_escaped_clusters (store2_manager *mgr) { for (hash_set::iterator iter = m_mutable_regs.begin (); iter != m_mutable_regs.end (); ++iter) { const region2 *base_reg = *iter; - m_store->on_escape_to_unknown_fncall (mgr, base_reg); + m_store->mark_as_escaped (base_reg); } } +/* Dump a multiline representation of this object to PP. */ + void reachable_region2s::dump_to_pp (pretty_printer *pp) const { @@ -256,6 +258,8 @@ reachable_region2s::dump_to_pp (pretty_printer *pp) const } } +/* Dump a multiline representation of this object to stderr. */ + DEBUG_FUNCTION void reachable_region2s::dump () const { diff --git a/gcc/analyzer/region-model2-reachability.h b/gcc/analyzer/region-model2-reachability.h index bec29216ae9..62acded445f 100644 --- a/gcc/analyzer/region-model2-reachability.h +++ b/gcc/analyzer/region-model2-reachability.h @@ -54,10 +54,9 @@ public: Use PARAM_TYPE for determining mutability. */ void handle_parm (const svalue2 *sval, tree param_type); - /* Update m_store to set the clusters that were found to be mutable - to "unknown" values. */ + /* FIXME. */ - void update_bindings (store2_manager *mgr); + void mark_escaped_clusters (store2_manager *mgr); /* Iteration over reachable regions. */ hash_set::iterator begin () diff --git a/gcc/analyzer/region-model2.cc b/gcc/analyzer/region-model2.cc index 0fdab11b962..101cac7db21 100644 --- a/gcc/analyzer/region-model2.cc +++ b/gcc/analyzer/region-model2.cc @@ -5122,7 +5122,12 @@ region_model2::handle_unrecognized_call (const gcall *call, ctxt->on_unknown_change (sval, true); } - reachable_regs.update_bindings (m_mgr->get_store2_manager ()); + /* Mark any clusters that have escaped. */ + reachable_regs.mark_escaped_clusters (m_mgr->get_store2_manager ()); + + /* Update bindings for all clusters that have escaped, whether above, + or previously. */ + m_store.on_unknown_fncall (); #if 0 /* Purge sm-state for any remaining svalue2s that point to region2s that @@ -7058,8 +7063,7 @@ region_model2::on_top_level_param (tree param, const svalue2 *init_ptr_sval = m_mgr->get_or_create_initial_value (param_reg); const region2 *pointee_reg = m_mgr->get_symbolic_region (init_ptr_sval); - m_store.on_escape_to_unknown_fncall (m_mgr->get_store2_manager (), - pointee_reg); + m_store.mark_as_escaped (pointee_reg); } } diff --git a/gcc/analyzer/store2.cc b/gcc/analyzer/store2.cc index 6d916664b01..75128e4bdc8 100644 --- a/gcc/analyzer/store2.cc +++ b/gcc/analyzer/store2.cc @@ -853,15 +853,11 @@ binding_cluster2::make_unknown_relative_to (const binding_cluster2 *other, } } -/* FIXME. */ +/* Mark this cluster as having escaped. */ void -binding_cluster2::on_escape_to_unknown_fncall (store2_manager *mgr) +binding_cluster2::mark_as_escaped () { - m_map.empty (); - // TODO: need to add an "unknown" default value - - /* Mark this cluster as having escaped. */ /* TODO: but maybe not if it's a global? they have automatically escaped already, and we want to be able to remove the cluster from the store if possible. @@ -871,6 +867,23 @@ binding_cluster2::on_escape_to_unknown_fncall (store2_manager *mgr) m_escaped = true; } +/* If this cluster has escaped (by this call, or by an earlier one, or + by being an external param), then unbind all values and mark it + as "touched", so that it has an unknown value, rather than an + initial_svalue2. */ + +void +binding_cluster2::on_unknown_fncall () +{ + if (m_escaped) + { + m_map.empty (); + // TODO: need to add an "unknown" default value + + m_touched = true; + } +} + /* Return true if this binding_cluster2 has no information i.e. if there are no bindings, and it hasn't been marked as having escaped, or touched symbolically. */ @@ -1569,26 +1582,37 @@ store2::can_merge_p (const store2 *store_a, const store2 *store_b, return true; } -/* FIXME. - For use when handling an unrecognized function call. */ -/* FIXME: do we want to mark the cluster as having escaped? - Further function calls could touch it, even if the cluster +/* Mark the cluster for BASE_REG as having escaped. + For use when handling an unrecognized function call, and + for params to "top-level" calls. + Further unknown function calls could touch it, even if the cluster isn't reachable from args of those calls. */ void -store2::on_escape_to_unknown_fncall (store2_manager *mgr, - const region2 *base_reg) +store2::mark_as_escaped (const region2 *base_reg) { gcc_assert (base_reg); gcc_assert (base_reg->get_base_region () == base_reg); binding_cluster2 *cluster = get_or_create_cluster (base_reg); - cluster->on_escape_to_unknown_fncall (mgr); + cluster->mark_as_escaped (); /* FIXME: but don't bother marking every global as escaped; instead, - clear these. */ + clear these on unknown fncalls. */ } -/* FIXME. */ +/* Handle an unknown fncall by updating any clusters that have escaped + (either in this fncall, or in a prior one). */ + +void +store2::on_unknown_fncall () +{ + for (cluster_map_t::iterator iter = m_cluster_map.begin (); + iter != m_cluster_map.end (); ++iter) + (*iter).second->on_unknown_fncall (); +} + +/* Return true if a non-const pointer to BASE_REG (or something within it) + has escaped to code outside of the TU being analyzed. */ bool store2::escaped_p (const region2 *base_reg) const diff --git a/gcc/analyzer/store2.h b/gcc/analyzer/store2.h index ce1490b78bb..f1dcb6cc74a 100644 --- a/gcc/analyzer/store2.h +++ b/gcc/analyzer/store2.h @@ -385,7 +385,8 @@ public: void make_unknown_relative_to (const binding_cluster2 *other_cluster, store2_manager *mgr); - void on_escape_to_unknown_fncall (store2_manager *mgr); + void mark_as_escaped (); + void on_unknown_fncall (); bool escaped_p () const { return m_escaped; } bool touched_p () const { return m_touched; } @@ -424,7 +425,8 @@ private: binding_map m_map; /* Has a pointer to this cluster "escaped" into a part of the program - we don't know about (via a call to a function with an unknown body). + we don't know about (via a call to a function with an unknown body, + or by being passed in as a pointer param of a "top-level" function call). Such regions could be overwritten when other such functions are called, even if the region is no longer reachable by pointers that we are tracking. */ @@ -496,9 +498,8 @@ public: store2 *out_store, store2_manager *mgr, model2_merger *merger); - void on_escape_to_unknown_fncall (store2_manager *mgr, - const region2 *base_reg); - + void mark_as_escaped (const region2 *base_reg); + void on_unknown_fncall (); bool escaped_p (const region2 *reg) const; void get_representative_path_vars (const region_model2 *model, -- 2.26.2