analyzer: fix ICE in binding_cluster::purge_state_involving [PR101522]

gcc/analyzer/ChangeLog:
	PR analyzer/101522
	* store.cc (binding_cluster::purge_state_involving): Don't change
	m_map whilst iterating through it.

gcc/testsuite/ChangeLog:
	PR analyzer/101522
	* g++.dg/analyzer/pr101522.C: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
diff --git a/gcc/analyzer/store.cc b/gcc/analyzer/store.cc
index 0042a20..8ee414d 100644
--- a/gcc/analyzer/store.cc
+++ b/gcc/analyzer/store.cc
@@ -1323,6 +1323,7 @@
 					region_model_manager *sval_mgr)
 {
   auto_vec<const binding_key *> to_remove;
+  auto_vec<std::pair<const binding_key *, tree> > to_make_unknown;
   for (auto iter : m_map)
     {
       const binding_key *iter_key = iter.first;
@@ -1335,17 +1336,20 @@
 	}
       const svalue *iter_sval = iter.second;
       if (iter_sval->involves_p (sval))
-	{
-	  const svalue *new_sval
-	    = sval_mgr->get_or_create_unknown_svalue (iter_sval->get_type ());
-	  m_map.put (iter_key, new_sval);
-	}
+	to_make_unknown.safe_push (std::make_pair(iter_key,
+						  iter_sval->get_type ()));
     }
   for (auto iter : to_remove)
     {
       m_map.remove (iter);
       m_touched = true;
     }
+  for (auto iter : to_make_unknown)
+    {
+      const svalue *new_sval
+	= sval_mgr->get_or_create_unknown_svalue (iter.second);
+      m_map.put (iter.first, new_sval);
+    }
 }
 
 /* Get any SVAL bound to REG within this cluster via kind KIND,
diff --git a/gcc/testsuite/g++.dg/analyzer/pr101522.C b/gcc/testsuite/g++.dg/analyzer/pr101522.C
new file mode 100644
index 0000000..634a2ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/pr101522.C
@@ -0,0 +1,31 @@
+// { dg-do compile { target c++11 } }
+
+double
+sqrt ();
+
+namespace std {
+  class gamma_distribution {
+  public:
+    gamma_distribution () : _M_param () {}
+
+  private:
+    struct param_type {
+      param_type () : _M_beta () { _M_a2 = 1 / ::sqrt (); }
+      double _M_beta, _M_a2;
+    };
+    param_type _M_param;
+    int _M_saved_available, _M_saved = 0, _M_param0 = 0;
+  };
+
+  struct fisher_f_distribution {
+    gamma_distribution _M_gd_x, _M_gd_y;
+  };
+}
+
+int
+main ()
+{
+  std::fisher_f_distribution d;
+
+  return 0;
+}