PR analyzer/93778 reports an ICE with -fanalyzer on a gfortran test case
at this gimple stmt:
_gfortran_st_set_nml_var (&dt_parm.0, &ro.xi.jq, &"ro%xi%jq"[1]{lb: 1 sz: 1}, 4, 0, D.3913);
where ro.xi.jq is a COMPONENT_REF, but ro.xi is of type "struct bl[3]".
The analyzer's handling of COMPONENT_REF assumes that the type of the
1st argument is a RECORD_TYPE or UNION_TYPE, whereas in this case it's
an ARRAY_TYPE, leading to a failed as_a inside
region_model::get_field_region.
This patch fixes the ICE by generalizing the "give up on this tree code"
logic from
r10-6667-gf76a88ebf089871dcce215aa0cb1956ccc060895 for
PR analyzer/93388, so that the analyzer gives up when it needs to get an
lvalue for a COMPONENT_REF on something other than a RECORD_TYPE or
UNION_TYPE.
gcc/analyzer/ChangeLog:
PR analyzer/93778
* engine.cc (impl_region_model_context::on_unknown_tree_code):
Rename to...
(impl_region_model_context::on_unexpected_tree_code): ...this and
convert first argument from path_var to tree.
(exploded_node::on_stmt): Pass ctxt to purge_for_unknown_fncall.
* exploded-graph.h (region_model_context::on_unknown_tree_code):
Rename to...
(region_model_context::on_unexpected_tree_code): ...this and
convert first argument from path_var to tree.
* program-state.cc (sm_state_map::purge_for_unknown_fncall): Add
ctxt param and pass on to calls to get_rvalue.
* program-state.h (sm_state_map::purge_for_unknown_fncall): Add
ctxt param.
* region-model.cc (region_model::handle_unrecognized_call): Pass
ctxt on to call to get_rvalue.
(region_model::get_lvalue_1): Move body of default case to
region_model::make_region_for_unexpected_tree_code and call it.
Within COMPONENT_REF case, reject attempts to handle types other
than RECORD_TYPE and UNION_TYPE.
(region_model::make_region_for_unexpected_tree_code): New
function, based on default case of region_model::get_lvalue_1.
* region-model.h
(region_model::make_region_for_unexpected_tree_code): New decl.
(region_model::on_unknown_tree_code): Rename to...
(region_model::on_unexpected_tree_code): ...this and convert first
argument from path_var to tree.
(class test_region_model_context): Update vfunc implementation for
above change.
gcc/testsuite/ChangeLog:
PR analyzer/93778
* gfortran.dg/analyzer/pr93778.f90: New test.
+2020-02-18 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/93778
+ * engine.cc (impl_region_model_context::on_unknown_tree_code):
+ Rename to...
+ (impl_region_model_context::on_unexpected_tree_code): ...this and
+ convert first argument from path_var to tree.
+ (exploded_node::on_stmt): Pass ctxt to purge_for_unknown_fncall.
+ * exploded-graph.h (region_model_context::on_unknown_tree_code):
+ Rename to...
+ (region_model_context::on_unexpected_tree_code): ...this and
+ convert first argument from path_var to tree.
+ * program-state.cc (sm_state_map::purge_for_unknown_fncall): Add
+ ctxt param and pass on to calls to get_rvalue.
+ * program-state.h (sm_state_map::purge_for_unknown_fncall): Add
+ ctxt param.
+ * region-model.cc (region_model::handle_unrecognized_call): Pass
+ ctxt on to call to get_rvalue.
+ (region_model::get_lvalue_1): Move body of default case to
+ region_model::make_region_for_unexpected_tree_code and call it.
+ Within COMPONENT_REF case, reject attempts to handle types other
+ than RECORD_TYPE and UNION_TYPE.
+ (region_model::make_region_for_unexpected_tree_code): New
+ function, based on default case of region_model::get_lvalue_1.
+ * region-model.h
+ (region_model::make_region_for_unexpected_tree_code): New decl.
+ (region_model::on_unknown_tree_code): Rename to...
+ (region_model::on_unexpected_tree_code): ...this and convert first
+ argument from path_var to tree.
+ (class test_region_model_context): Update vfunc implementation for
+ above change.
+
2020-02-18 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93774
}
}
-/* Implementation of region_model_context::on_unknown_tree_code vfunc.
+/* Implementation of region_model_context::on_unexpected_tree_code vfunc.
Mark the new state as being invalid for further exploration.
TODO(stage1): introduce a warning for when this occurs. */
void
-impl_region_model_context::on_unknown_tree_code (path_var pv,
- const dump_location_t &loc)
+impl_region_model_context::on_unexpected_tree_code (tree t,
+ const dump_location_t &loc)
{
logger * const logger = get_logger ();
if (logger)
logger->log ("unhandled tree code: %qs in %qs at %s:%i",
- get_tree_code_name (TREE_CODE (pv.m_tree)),
+ get_tree_code_name (TREE_CODE (t)),
loc.get_impl_location ().m_function,
loc.get_impl_location ().m_file,
loc.get_impl_location ().m_line);
if (!fndecl_has_gimple_body_p (callee_fndecl))
new_smap->purge_for_unknown_fncall (eg, sm, call, callee_fndecl,
- state->m_region_model);
+ state->m_region_model,
+ &ctxt);
}
}
if (*old_smap != *new_smap)
void on_phi (const gphi *phi, tree rhs) FINAL OVERRIDE;
- void on_unknown_tree_code (path_var pv,
- const dump_location_t &loc) FINAL OVERRIDE;
+ void on_unexpected_tree_code (tree t,
+ const dump_location_t &loc) FINAL OVERRIDE;
exploded_graph *m_eg;
log_user m_logger;
const state_machine &sm,
const gcall *call,
tree fndecl,
- region_model *new_model)
+ region_model *new_model,
+ region_model_context *ctxt)
{
logger * const logger = eg.get_logger ();
if (logger)
continue;
}
tree parm = gimple_call_arg (call, arg_idx);
- svalue_id parm_sid = new_model->get_rvalue (parm, NULL);
+ svalue_id parm_sid = new_model->get_rvalue (parm, ctxt);
set_state (new_model, parm_sid, 0, svalue_id::null ());
/* Also clear sm-state from svalue_ids that are passed via a
if (TREE_CODE (parm) == ADDR_EXPR)
{
tree pointee = TREE_OPERAND (parm, 0);
- svalue_id parm_sid = new_model->get_rvalue (pointee, NULL);
+ svalue_id parm_sid = new_model->get_rvalue (pointee, ctxt);
set_state (new_model, parm_sid, 0, svalue_id::null ());
}
}
/* Purge any state for any LHS. */
if (tree lhs = gimple_call_lhs (call))
{
- svalue_id lhs_sid = new_model->get_rvalue (lhs, NULL);
+ svalue_id lhs_sid = new_model->get_rvalue (lhs, ctxt);
set_state (new_model, lhs_sid, 0, svalue_id::null ());
}
}
void purge_for_unknown_fncall (const exploded_graph &eg,
const state_machine &sm,
const gcall *call, tree fndecl,
- region_model *new_model);
+ region_model *new_model,
+ region_model_context *ctxt);
void remap_svalue_ids (const svalue_id_map &map);
}
tree parm = gimple_call_arg (call, arg_idx);
- svalue_id parm_sid = get_rvalue (parm, NULL);
+ svalue_id parm_sid = get_rvalue (parm, ctxt);
svalue *parm_sval = get_svalue (parm_sid);
if (parm_sval)
if (region_svalue *parm_ptr = parm_sval->dyn_cast_region_svalue ())
switch (TREE_CODE (expr))
{
default:
- {
- /* If we see a tree code we we don't know how to handle, rather than
- ICE or generate bogus results, create a dummy region, and notify
- CTXT so that it can mark the new state as being not properly
- modelled. The exploded graph can then stop exploring that path,
- since any diagnostics we might issue will have questionable
- validity. */
- region_id new_rid
- = add_region (new symbolic_region (m_root_rid, NULL_TREE, false));
- ctxt->on_unknown_tree_code (pv, dump_location_t ());
- return new_rid;
- }
- break;
+ return make_region_for_unexpected_tree_code (ctxt, expr,
+ dump_location_t ());
case ARRAY_REF:
{
/* obj.field */
tree obj = TREE_OPERAND (expr, 0);
tree field = TREE_OPERAND (expr, 1);
+ tree obj_type = TREE_TYPE (obj);
+ if (TREE_CODE (obj_type) != RECORD_TYPE
+ && TREE_CODE (obj_type) != UNION_TYPE)
+ return make_region_for_unexpected_tree_code (ctxt, obj_type,
+ dump_location_t ());
region_id obj_rid = get_lvalue (obj, ctxt);
region_id struct_or_union_rid
= get_or_create_view (obj_rid, TREE_TYPE (obj));
}
}
+/* If we see a tree code we we don't know how to handle, rather than
+ ICE or generate bogus results, create a dummy region, and notify
+ CTXT so that it can mark the new state as being not properly
+ modelled. The exploded graph can then stop exploring that path,
+ since any diagnostics we might issue will have questionable
+ validity. */
+
+region_id
+region_model::make_region_for_unexpected_tree_code (region_model_context *ctxt,
+ tree t,
+ const dump_location_t &loc)
+{
+ region_id new_rid
+ = add_region (new symbolic_region (m_root_rid, NULL_TREE, false));
+ ctxt->on_unexpected_tree_code (t, loc);
+ return new_rid;
+}
+
/* Assert that SRC_TYPE can be converted to DST_TYPE as a no-op. */
static void
region_id get_lvalue_1 (path_var pv, region_model_context *ctxt);
svalue_id get_rvalue_1 (path_var pv, region_model_context *ctxt);
+ region_id make_region_for_unexpected_tree_code (region_model_context *ctxt,
+ tree t,
+ const dump_location_t &loc);
+
void add_any_constraints_from_ssa_def_stmt (tree lhs,
enum tree_code op,
tree rhs,
virtual void on_phi (const gphi *phi, tree rhs) = 0;
/* Hooks for clients to be notified when the region model doesn't
- know how to handle the tree code of PV at LOC. */
- virtual void on_unknown_tree_code (path_var pv,
- const dump_location_t &loc) = 0;
+ know how to handle the tree code of T at LOC. */
+ virtual void on_unexpected_tree_code (tree t,
+ const dump_location_t &loc) = 0;
};
/* A bundle of data for use when attempting to merge two region_model
{
}
- void on_unknown_tree_code (path_var pv, const dump_location_t &)
+ void on_unexpected_tree_code (tree t, const dump_location_t &)
FINAL OVERRIDE
{
internal_error ("unhandled tree code: %qs",
- get_tree_code_name (TREE_CODE (pv.m_tree)));
+ get_tree_code_name (TREE_CODE (t)));
}
private:
+2020-02-18 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/93778
+ * gfortran.dg/analyzer/pr93778.f90: New test.
+
2020-02-18 David Malcolm <dmalcolm@redhat.com>
PR analyzer/93774
--- /dev/null
+program h0
+ type bl
+ integer jq
+ end type bl
+ type qn
+ type (bl), dimension(3) :: xi
+ end type qn
+ type (qn) ro
+ namelist /i2/ ro
+ read(10, nml = i2)
+end program h0