diff options
author | David Malcolm <dmalcolm@redhat.com> | 2020-02-05 21:29:04 -0500 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2020-02-11 21:06:43 -0500 |
commit | 91f993b7e31ce85676148dca180bc0d827d4245e (patch) | |
tree | 0b46c2995392b7a5f7721524ae2c42f91a8b0ce5 /gcc/analyzer | |
parent | d9e067f98b0c4f57d8acd60526b6fa11a1d109e5 (diff) | |
download | gcc-91f993b7e31ce85676148dca180bc0d827d4245e.zip gcc-91f993b7e31ce85676148dca180bc0d827d4245e.tar.gz gcc-91f993b7e31ce85676148dca180bc0d827d4245e.tar.bz2 |
analyzer: use ultimate alias target at calls (PR 93288)
PR analyzer/93288 reports an ICE in a C++ testcase when calling a
constructor.
The issue is that when building the supergraph, we encounter the
cgraph edge to "__ct_comp ", the DECL_COMPLETE_CONSTRUCTOR_P, and
this node's DECL_STRUCT_FUNCTION has a NULL CFG, which the analyzer
reads through, leading to the ICE.
This patch reworks function and fndecl lookup at calls throughout the
analyzer so that it looks for the ultimate_alias_target of the callee.
In the case above, this means using the "__ct_base " for the ctor,
which has a CFG, fixing the ICE.
Getting this right allows for some simple C++ cases involving ctors to
work, so the patch also adds some test coverage for that.
gcc/analyzer/ChangeLog:
PR analyzer/93288
* analysis-plan.cc (analysis_plan::use_summary_p): Look through
the ultimate_alias_target when getting the called function.
* engine.cc (exploded_node::on_stmt): Rename second "ctxt" to
"sm_ctxt". Use the region_model's get_fndecl_for_call rather than
gimple_call_fndecl.
* region-model.cc (region_model::get_fndecl_for_call): Use
ultimate_alias_target on fndecl.
* supergraph.cc (get_ultimate_function_for_cgraph_edge): New
function.
(supergraph_call_edge): Use it when rejecting edges without
functions.
(supergraph::supergraph): Use it to get the function for the
cgraph_edge when building interprocedural superedges.
(callgraph_superedge::get_callee_function): Use it.
* supergraph.h (supergraph::get_num_snodes): Make param const.
(supergraph::function_to_num_snodes_t): Make first type param
const.
gcc/testsuite/ChangeLog:
PR analyzer/93288
* g++.dg/analyzer/malloc.C: Add test coverage for a double-free
called in a constructor.
* g++.dg/analyzer/pr93288.C: New test.
Diffstat (limited to 'gcc/analyzer')
-rw-r--r-- | gcc/analyzer/ChangeLog | 21 | ||||
-rw-r--r-- | gcc/analyzer/analysis-plan.cc | 6 | ||||
-rw-r--r-- | gcc/analyzer/engine.cc | 12 | ||||
-rw-r--r-- | gcc/analyzer/region-model.cc | 5 | ||||
-rw-r--r-- | gcc/analyzer/supergraph.cc | 28 | ||||
-rw-r--r-- | gcc/analyzer/supergraph.h | 4 |
6 files changed, 60 insertions, 16 deletions
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog index 0313e43..eda1052 100644 --- a/gcc/analyzer/ChangeLog +++ b/gcc/analyzer/ChangeLog @@ -1,5 +1,26 @@ 2020-02-11 David Malcolm <dmalcolm@redhat.com> + PR analyzer/93288 + * analysis-plan.cc (analysis_plan::use_summary_p): Look through + the ultimate_alias_target when getting the called function. + * engine.cc (exploded_node::on_stmt): Rename second "ctxt" to + "sm_ctxt". Use the region_model's get_fndecl_for_call rather than + gimple_call_fndecl. + * region-model.cc (region_model::get_fndecl_for_call): Use + ultimate_alias_target on fndecl. + * supergraph.cc (get_ultimate_function_for_cgraph_edge): New + function. + (supergraph_call_edge): Use it when rejecting edges without + functions. + (supergraph::supergraph): Use it to get the function for the + cgraph_edge when building interprocedural superedges. + (callgraph_superedge::get_callee_function): Use it. + * supergraph.h (supergraph::get_num_snodes): Make param const. + (supergraph::function_to_num_snodes_t): Make first type param + const. + +2020-02-11 David Malcolm <dmalcolm@redhat.com> + PR analyzer/93374 * engine.cc (exploded_edge::exploded_edge): Add ext_state param and pass it to change.validate. diff --git a/gcc/analyzer/analysis-plan.cc b/gcc/analyzer/analysis-plan.cc index 8ad2fa2..3c8b10b 100644 --- a/gcc/analyzer/analysis-plan.cc +++ b/gcc/analyzer/analysis-plan.cc @@ -120,7 +120,11 @@ analysis_plan::use_summary_p (const cgraph_edge *edge) const /* Require the callee to be sufficiently complex to be worth summarizing. */ - if ((int)m_sg.get_num_snodes (callee->get_fun ()) + const function *fun + = const_cast <cgraph_node *> (callee)->ultimate_alias_target ()->get_fun (); + /* TODO(stage1): can ultimate_alias_target be made const? */ + + if ((int)m_sg.get_num_snodes (fun) < param_analyzer_min_snodes_for_call_summary) return false; diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc index 4d329e2..7860da0 100644 --- a/gcc/analyzer/engine.cc +++ b/gcc/analyzer/engine.cc @@ -1044,19 +1044,19 @@ exploded_node::on_stmt (exploded_graph &eg, const sm_state_map *old_smap = old_state.m_checker_states[sm_idx]; sm_state_map *new_smap = state->m_checker_states[sm_idx]; - impl_sm_context ctxt (eg, sm_idx, sm, this, &old_state, state, - change, - old_smap, new_smap); + impl_sm_context sm_ctxt (eg, sm_idx, sm, this, &old_state, state, + change, + old_smap, new_smap); /* Allow the state_machine to handle the stmt. */ - if (sm.on_stmt (&ctxt, snode, stmt)) + if (sm.on_stmt (&sm_ctxt, snode, stmt)) unknown_side_effects = false; else { /* For those stmts that were not handled by the state machine. */ if (const gcall *call = dyn_cast <const gcall *> (stmt)) { - tree callee_fndecl = gimple_call_fndecl (call); - // TODO: maybe we can be smarter about handling function pointers? + tree callee_fndecl + = state->m_region_model->get_fndecl_for_call (call, &ctxt); if (!fndecl_has_gimple_body_p (callee_fndecl)) new_smap->purge_for_unknown_fncall (eg, sm, call, callee_fndecl, diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index b9d52f6..ae810f5 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -6676,7 +6676,10 @@ region_model::get_fndecl_for_call (const gcall *call, if (code) { tree fn_decl = code->get_tree_for_child_region (fn_rid); - return fn_decl; + const cgraph_node *ultimate_node + = cgraph_node::get (fn_decl)->ultimate_alias_target (); + if (ultimate_node) + return ultimate_node->decl; } } diff --git a/gcc/analyzer/supergraph.cc b/gcc/analyzer/supergraph.cc index b20daa0..fb4dbdf 100644 --- a/gcc/analyzer/supergraph.cc +++ b/gcc/analyzer/supergraph.cc @@ -56,6 +56,18 @@ along with GCC; see the file COPYING3. If not see namespace ana { +/* Get the function of the ultimate alias target being called at EDGE, + if any. */ + +static function * +get_ultimate_function_for_cgraph_edge (cgraph_edge *edge) +{ + cgraph_node *ultimate_node = edge->callee->ultimate_alias_target (); + if (!ultimate_node) + return NULL; + return ultimate_node->get_fun (); +} + /* Get the cgraph_edge, but only if there's an underlying function body. */ cgraph_edge * @@ -69,7 +81,7 @@ supergraph_call_edge (function *fun, gimple *stmt) return NULL; if (!edge->callee) return NULL; /* e.g. for a function pointer. */ - if (!edge->callee->get_fun ()) + if (!get_ultimate_function_for_cgraph_edge (edge)) return NULL; return edge; } @@ -178,8 +190,10 @@ supergraph::supergraph (logger *logger) { cgraph_edge *edge = (*iter).first; supernode *caller_prev_supernode = (*iter).second; - basic_block callee_cfg_block - = ENTRY_BLOCK_PTR_FOR_FN (edge->callee->get_fun ()); + function* callee_fn = get_ultimate_function_for_cgraph_edge (edge); + if (!callee_fn || !callee_fn->cfg) + continue; + basic_block callee_cfg_block = ENTRY_BLOCK_PTR_FOR_FN (callee_fn); supernode *callee_supernode = *m_bb_to_initial_node.get (callee_cfg_block); call_superedge *sedge @@ -199,8 +213,10 @@ supergraph::supergraph (logger *logger) { cgraph_edge *edge = (*iter).first; supernode *caller_next_supernode = (*iter).second; - basic_block callee_cfg_block - = EXIT_BLOCK_PTR_FOR_FN (edge->callee->get_fun ()); + function* callee_fn = get_ultimate_function_for_cgraph_edge (edge); + if (!callee_fn || !callee_fn->cfg) + continue; + basic_block callee_cfg_block = EXIT_BLOCK_PTR_FOR_FN (callee_fn); supernode *callee_supernode = *m_bb_to_initial_node.get (callee_cfg_block); return_superedge *sedge @@ -840,7 +856,7 @@ callgraph_superedge::dump_label_to_pp (pretty_printer *pp, function * callgraph_superedge::get_callee_function () const { - return m_cedge->callee->get_fun (); + return get_ultimate_function_for_cgraph_edge (m_cedge); } /* Get the calling function at this interprocedural call/return edge. */ diff --git a/gcc/analyzer/supergraph.h b/gcc/analyzer/supergraph.h index 0eac0b8..2c94f05 100644 --- a/gcc/analyzer/supergraph.h +++ b/gcc/analyzer/supergraph.h @@ -156,7 +156,7 @@ public: return m_nodes[idx]; } - unsigned get_num_snodes (function *fun) const + unsigned get_num_snodes (const function *fun) const { function_to_num_snodes_t &map = const_cast <function_to_num_snodes_t &>(m_function_to_num_snodes); @@ -201,7 +201,7 @@ private: typedef ordered_hash_map<gimple *, supernode *> stmt_to_node_t; stmt_to_node_t m_stmt_to_node_t; - typedef hash_map<function *, unsigned> function_to_num_snodes_t; + typedef hash_map<const function *, unsigned> function_to_num_snodes_t; function_to_num_snodes_t m_function_to_num_snodes; }; |