aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/analyzer/call-summary.cc28
-rw-r--r--gcc/analyzer/engine.cc2
-rw-r--r--gcc/analyzer/region-model-impl-calls.cc10
-rw-r--r--gcc/analyzer/region-model.cc6
-rw-r--r--gcc/analyzer/region-model.h1
-rw-r--r--gcc/analyzer/store.cc16
-rw-r--r--gcc/doc/analyzer.texi4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h3
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c7
9 files changed, 62 insertions, 15 deletions
diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a8e8814..3391654 100644
--- a/gcc/analyzer/call-summary.cc
+++ b/gcc/analyzer/call-summary.cc
@@ -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:
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 735b5a3..faef0bd 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -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);
}
diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc
index 71fb277..5cc5907 100644
--- a/gcc/analyzer/region-model-impl-calls.cc
+++ b/gcc/analyzer/region-model-impl-calls.cc
@@ -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
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index d14f3a1..aa3d205 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -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);
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 6903090..e81595e 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -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,
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 74b481d..1ca1214 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -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 ())
diff --git a/gcc/doc/analyzer.texi b/gcc/doc/analyzer.texi
index 06eb98f..ec49f95 100644
--- a/gcc/doc/analyzer.texi
+++ b/gcc/doc/analyzer.texi
@@ -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
diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h
index d052579..4478d74 100644
--- a/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h
+++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-decls.h
@@ -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. */
diff --git a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
index 0aaf67b..85cece7 100644
--- a/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/call-summaries-2.c
@@ -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)