Add addrmap_mutable::clear

It was convenient to add a 'clear' method to addrmap_mutable.  The
cleanest way to do this was to change the class to lazily initialize
its 'tree' member.  This also makes addrmap_mutable::operator= a bit
less weird.

Approved-By: Simon Marchi <simon.marchi@efficios.com>


diff --git a/gdb/addrmap.c b/gdb/addrmap.c
index 9eb330b..e6799cc 100644
--- a/gdb/addrmap.c
+++ b/gdb/addrmap.c
@@ -178,6 +178,29 @@ addrmap_mutable::force_transition (CORE_ADDR addr)
 }
 
 
+/* Compare keys as CORE_ADDR * values.  */
+static int
+splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
+{
+  CORE_ADDR a = * (CORE_ADDR *) ak;
+  CORE_ADDR b = * (CORE_ADDR *) bk;
+
+  /* We can't just return a-b here, because of over/underflow.  */
+  if (a < b)
+    return -1;
+  else if (a == b)
+    return 0;
+  else
+    return 1;
+}
+
+
+static void
+xfree_wrapper (splay_tree_key key)
+{
+  xfree ((void *) key);
+}
+
 void
 addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
 			    void *obj)
@@ -185,6 +208,10 @@ addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
   splay_tree_node n, next;
   void *prior_value;
 
+  if (tree == nullptr)
+    tree = splay_tree_new (splay_compare_CORE_ADDR_ptr, xfree_wrapper,
+			   nullptr /* no delete value */);
+
   /* If we're being asked to set all empty portions of the given
      address range to empty, then probably the caller is confused.
      (If that turns out to be useful in some cases, then we can change
@@ -233,6 +260,9 @@ addrmap_mutable::set_empty (CORE_ADDR start, CORE_ADDR end_inclusive,
 void *
 addrmap_mutable::do_find (CORE_ADDR addr) const
 {
+  if (tree == nullptr)
+    return nullptr;
+
   splay_tree_node n = splay_tree_lookup (addr);
   if (n != nullptr)
     {
@@ -311,43 +341,20 @@ addrmap_mutable_foreach_worker (splay_tree_node node, void *data)
 int
 addrmap_mutable::do_foreach (addrmap_foreach_fn fn) const
 {
+  if (tree == nullptr)
+    return 0;
   return splay_tree_foreach (tree, addrmap_mutable_foreach_worker, &fn);
 }
 
 
-/* Compare keys as CORE_ADDR * values.  */
-static int
-splay_compare_CORE_ADDR_ptr (splay_tree_key ak, splay_tree_key bk)
-{
-  CORE_ADDR a = * (CORE_ADDR *) ak;
-  CORE_ADDR b = * (CORE_ADDR *) bk;
-
-  /* We can't just return a-b here, because of over/underflow.  */
-  if (a < b)
-    return -1;
-  else if (a == b)
-    return 0;
-  else
-    return 1;
-}
-
-
-static void
-xfree_wrapper (splay_tree_key key)
-{
-  xfree ((void *) key);
-}
-
-addrmap_mutable::addrmap_mutable ()
-  : tree (splay_tree_new (splay_compare_CORE_ADDR_ptr, xfree_wrapper,
-			  nullptr /* no delete value */))
-{
-}
-
-addrmap_mutable::~addrmap_mutable ()
+void
+addrmap_mutable::clear ()
 {
   if (tree != nullptr)
-    splay_tree_delete (tree);
+    {
+      splay_tree_delete (tree);
+      tree = nullptr;
+    }
 }
 
 
diff --git a/gdb/addrmap.h b/gdb/addrmap.h
index 95f6ec8..06fc175 100644
--- a/gdb/addrmap.h
+++ b/gdb/addrmap.h
@@ -126,8 +126,12 @@ struct addrmap_mutable final : public addrmap
 {
 public:
 
-  addrmap_mutable ();
-  ~addrmap_mutable ();
+  addrmap_mutable () = default;
+  ~addrmap_mutable ()
+  {
+    clear ();
+  }
+
   DISABLE_COPY_AND_ASSIGN (addrmap_mutable);
 
   addrmap_mutable (addrmap_mutable &&other)
@@ -138,7 +142,13 @@ struct addrmap_mutable final : public addrmap
 
   addrmap_mutable &operator= (addrmap_mutable &&other)
   {
-    std::swap (tree, other.tree);
+    /* Handle self-move.  */
+    if (this != &other)
+      {
+	clear ();
+	tree = other.tree;
+	other.tree = nullptr;
+      }
     return *this;
   }
 
@@ -183,6 +193,9 @@ struct addrmap_mutable final : public addrmap
 		  void *obj);
   void relocate (CORE_ADDR offset) override;
 
+  /* Clear this addrmap.  */
+  void clear ();
+
 private:
   void *do_find (CORE_ADDR addr) const override;
   int do_foreach (addrmap_foreach_fn fn) const override;
@@ -204,7 +217,7 @@ struct addrmap_mutable final : public addrmap
      function, we can't keep a freelist for keys.  Since mutable
      addrmaps are only used temporarily right now, we just leak keys
      from deleted nodes; they'll be freed when the obstack is freed.  */
-  splay_tree tree;
+  splay_tree tree = nullptr;
 
   /* Various helper methods.  */
   splay_tree_key allocate_key (CORE_ADDR addr);