[committed] analyzer: fix ICEs seen with call summaries on PR 107060
Commit Message
This doesn't fix the various false positives seen with
-fanalyzer-call-summaries on PR 107060, but stops it crashing at -O2.
Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Pushed to trunk as r13-3094-g6832c95c0e1a58.
gcc/analyzer/ChangeLog:
PR analyzer/107060
* call-summary.cc
(call_summary_replay::convert_svalue_from_summary_1): Handle NULL
results from convert_svalue_from_summary in SK_UNARY_OP and
SK_BIN_OP.
* engine.cc (impl_region_model_context::on_unknown_change): Bail
out on svalues that can't have associated state.
* region-model-impl-calls.cc
(region_model::impl_call_analyzer_get_unknown_ptr): New.
* region-model.cc (region_model::on_stmt_pre): Handle
"__analyzer_get_unknown_ptr".
* region-model.h
(region_model::impl_call_analyzer_get_unknown_ptr): New decl.
* store.cc (store::replay_call_summary_cluster): Avoid trying to
create binding clusters for base regions that shouldn't have them.
gcc/ChangeLog:
PR analyzer/107060
* doc/analyzer.texi (__analyzer_get_unknown_ptr): Document.
gcc/testsuite/ChangeLog:
PR analyzer/107060
* gcc.dg/analyzer/analyzer-decls.h (__analyzer_get_unknown_ptr):
New decl.
* gcc.dg/analyzer/call-summaries-2.c
(test_summarized_writes_param_to_ptr_unknown): New test.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
gcc/analyzer/call-summary.cc | 28 +++++++++++++------
gcc/analyzer/engine.cc | 2 ++
gcc/analyzer/region-model-impl-calls.cc | 10 +++++++
gcc/analyzer/region-model.cc | 6 ++++
gcc/analyzer/region-model.h | 1 +
gcc/analyzer/store.cc | 16 +++++++----
gcc/doc/analyzer.texi | 4 +++
.../gcc.dg/analyzer/analyzer-decls.h | 3 ++
.../gcc.dg/analyzer/call-summaries-2.c | 7 +++++
9 files changed, 62 insertions(+), 15 deletions(-)
@@ -298,23 +298,33 @@ call_summary_replay::convert_svalue_from_summary_1 (const svalue *summary_sval)
{
const unaryop_svalue *unaryop_summary_sval
= as_a <const unaryop_svalue *> (summary_sval);
+ const svalue *summary_arg = unaryop_summary_sval->get_arg ();
+ const svalue *caller_arg = convert_svalue_from_summary (summary_arg);
+ if (!caller_arg)
+ return NULL;
region_model_manager *mgr = get_manager ();
- return mgr->get_or_create_unaryop
- (summary_sval->get_type (),
- unaryop_summary_sval->get_op (),
- convert_svalue_from_summary (unaryop_summary_sval->get_arg ()));
+ return mgr->get_or_create_unaryop (summary_sval->get_type (),
+ unaryop_summary_sval->get_op (),
+ caller_arg);
}
break;
case SK_BINOP:
{
const binop_svalue *binop_summary_sval
= as_a <const binop_svalue *> (summary_sval);
+ const svalue *summary_arg0 = binop_summary_sval->get_arg0 ();
+ const svalue *caller_arg0 = convert_svalue_from_summary (summary_arg0);
+ if (!caller_arg0)
+ return NULL;
+ const svalue *summary_arg1 = binop_summary_sval->get_arg1 ();
+ const svalue *caller_arg1 = convert_svalue_from_summary (summary_arg1);
+ if (!caller_arg1)
+ return NULL;
region_model_manager *mgr = get_manager ();
- return mgr->get_or_create_binop
- (summary_sval->get_type (),
- binop_summary_sval->get_op (),
- convert_svalue_from_summary (binop_summary_sval->get_arg0 ()),
- convert_svalue_from_summary (binop_summary_sval->get_arg1 ()));
+ return mgr->get_or_create_binop (summary_sval->get_type (),
+ binop_summary_sval->get_op (),
+ caller_arg0,
+ caller_arg1);
}
break;
case SK_SUB:
@@ -172,6 +172,8 @@ void
impl_region_model_context::on_unknown_change (const svalue *sval,
bool is_mutable)
{
+ if (!sval->can_have_associated_state_p ())
+ return;
for (sm_state_map *smap : m_new_state->m_checker_states)
smap->on_unknown_change (sval, is_mutable, m_ext_state);
}
@@ -374,6 +374,16 @@ region_model::impl_call_analyzer_eval (const gcall *call,
warning_at (call->location, 0, "%s", t.as_string ());
}
+/* Handle the on_call_pre part of "__analyzer_get_unknown_ptr". */
+
+void
+region_model::impl_call_analyzer_get_unknown_ptr (const call_details &cd)
+{
+ const svalue *ptr_sval
+ = m_mgr->get_or_create_unknown_svalue (cd.get_lhs_type ());
+ cd.maybe_set_lhs (ptr_sval);
+}
+
/* Handle the on_call_pre part of "__builtin_expect" etc. */
void
@@ -1256,6 +1256,12 @@ region_model::on_stmt_pre (const gimple *stmt,
{
/* This is handled elsewhere. */
}
+ else if (is_special_named_call_p (call, "__analyzer_get_unknown_ptr",
+ 0))
+ {
+ call_details cd (call, this, ctxt);
+ impl_call_analyzer_get_unknown_ptr (cd);
+ }
else
*out_unknown_side_effects = on_call_pre (call, ctxt,
out_terminate_path);
@@ -344,6 +344,7 @@ class region_model
void impl_call_analyzer_dump_escaped (const gcall *call);
void impl_call_analyzer_eval (const gcall *call,
region_model_context *ctxt);
+ void impl_call_analyzer_get_unknown_ptr (const call_details &cd);
void impl_call_builtin_expect (const call_details &cd);
void impl_call_calloc (const call_details &cd);
bool impl_call_error (const call_details &cd, unsigned min_args,
@@ -3176,12 +3176,16 @@ store::replay_call_summary_cluster (call_summary_replay &r,
= r.convert_region_from_summary (summary_base_reg))
{
const region *caller_base_reg = caller_reg->get_base_region ();
- binding_cluster *caller_cluster
- = get_or_create_cluster (caller_base_reg);
- if (summary_cluster->escaped_p ())
- caller_cluster->mark_as_escaped ();
- if (summary_cluster->touched_p ())
- caller_cluster->m_touched = true;
+ if (caller_base_reg->tracked_p ()
+ && !caller_base_reg->symbolic_for_unknown_ptr_p ())
+ {
+ binding_cluster *caller_cluster
+ = get_or_create_cluster (caller_base_reg);
+ if (summary_cluster->escaped_p ())
+ caller_cluster->mark_as_escaped ();
+ if (summary_cluster->touched_p ())
+ caller_cluster->m_touched = true;
+ }
}
switch (summary_base_reg->get_kind ())
@@ -544,6 +544,10 @@ __analyzer_eval (expr);
will emit a warning with text "TRUE", FALSE" or "UNKNOWN" based on the
truthfulness of the argument. This is useful for writing DejaGnu tests.
+@smallexample
+__analyzer_get_unknown_ptr ();
+@end smallexample
+will obtain an unknown @code{void *}.
@subsection Other Debugging Techniques
@@ -47,4 +47,7 @@ extern void __analyzer_dump_state (const char *name, ...);
truthfulness of the argument. */
extern void __analyzer_eval (int);
+/* Obtain an "unknown" void *. */
+extern void *__analyzer_get_unknown_ptr (void);
+
#endif /* #ifndef ANALYZER_DECLS_H. */
@@ -72,6 +72,13 @@ void test_summarized_writes_param_to_ptr (int j)
__analyzer_eval (y == j); /* { dg-warning "TRUE" } */
}
+void test_summarized_writes_param_to_ptr_unknown (int j)
+{
+ int *p = (int *)__analyzer_get_unknown_ptr ();
+ writes_param_to_ptr (j, p);
+ __analyzer_eval (*p == j); /* { dg-warning "UNKNOWN" } */
+}
+
int g;
void writes_to_global (int i)