diff --git a/gcc/analyzer/call-summary.cc b/gcc/analyzer/call-summary.cc
index a8e881472ea..33916547e1e 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 735b5a3c061..faef0bd15b0 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 71fb2770143..5cc590716b4 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 d14f3a1840e..aa3d2054131 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 6903090fcd3..e81595e8bc4 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 74b481dce48..1ca12142e47 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 06eb98fe4d3..ec49f951435 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 d05257949ff..4478d740b58 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 0aaf67b8fd4..85cece72b34 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)
