C++-ify varobj iteration
authorTom Tromey <tom@tromey.com>
Fri, 11 Dec 2020 16:33:36 +0000 (09:33 -0700)
committerTom Tromey <tom@tromey.com>
Fri, 11 Dec 2020 16:33:38 +0000 (09:33 -0700)
This changes the varobj iteration code to use a C++ class rather than
a C struct with a separate "ops" structure.  The only implementation
is updated to use inheritance.  This simplifies the code quite nicely.

gdb/ChangeLog
2020-12-11  Tom Tromey  <tom@tromey.com>

* varobj.c (update_dynamic_varobj_children, install_visualizer)
(varobj::~varobj): Update.
* varobj-iter.h (struct varobj_iter): Change to interface class.
(struct varobj_iter_ops): Remove.
(varobj_iter_next, varobj_iter_delete): Remove.
* python/py-varobj.c (struct py_varobj_iter): Derive from
varobj_iter.  Add constructor, destructor.  Rename members.
(py_varobj_iter::~py_varobj_iter): Rename from
py_varobj_iter_dtor.
(py_varobj_iter::next): Rename from py_varobj_iter_next.
(py_varobj_iter_ops): Remove.
(py_varobj_iter): Rename from py_varobj_iter_ctor.
(py_varobj_iter_new): Remove.
(py_varobj_get_iterator): Update.

gdb/ChangeLog
gdb/python/py-varobj.c
gdb/varobj-iter.h
gdb/varobj.c

index d724e742f887d300f56b78ff4bd463ad9b588a23..53f87d9b940f8ee7e0c5b855492477aa5e13e303 100644 (file)
@@ -1,3 +1,20 @@
+2020-12-11  Tom Tromey  <tom@tromey.com>
+
+       * varobj.c (update_dynamic_varobj_children, install_visualizer)
+       (varobj::~varobj): Update.
+       * varobj-iter.h (struct varobj_iter): Change to interface class.
+       (struct varobj_iter_ops): Remove.
+       (varobj_iter_next, varobj_iter_delete): Remove.
+       * python/py-varobj.c (struct py_varobj_iter): Derive from
+       varobj_iter.  Add constructor, destructor.  Rename members.
+       (py_varobj_iter::~py_varobj_iter): Rename from
+       py_varobj_iter_dtor.
+       (py_varobj_iter::next): Rename from py_varobj_iter_next.
+       (py_varobj_iter_ops): Remove.
+       (py_varobj_iter): Rename from py_varobj_iter_ctor.
+       (py_varobj_iter_new): Remove.
+       (py_varobj_get_iterator): Update.
+
 2020-12-11  Tom Tromey  <tom@tromey.com>
 
        * varobj.h (all_root_varobjs): Take a function_view.
index 9c791f64df139ed838717ecb1a1b3915bbabfdca..df6f9c5a953f2dbe642c8a08af3782841a4150e3 100644 (file)
 /* A dynamic varobj iterator "class" for python pretty-printed
    varobjs.  This inherits struct varobj_iter.  */
 
-struct py_varobj_iter
+struct py_varobj_iter : public varobj_iter
 {
-  /* The 'base class'.  */
-  struct varobj_iter base;
+  py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter);
+  ~py_varobj_iter () override;
+
+  varobj_item *next () override;
+
+private:
+
+  /* The varobj this iterator is listing children for.  */
+  struct varobj *m_var;
+
+  /* The next raw index we will try to check is available.  If it is
+     equal to number_of_children, then we've already iterated the
+     whole set.  */
+  int m_next_raw_index = 0;
 
   /* The python iterator returned by the printer's 'children' method,
      or NULL if not available.  */
-  PyObject *iter;
+  PyObject *m_iter;
 };
 
 /* Implementation of the 'dtor' method of pretty-printed varobj
    iterators.  */
 
-static void
-py_varobj_iter_dtor (struct varobj_iter *self)
+py_varobj_iter::~py_varobj_iter ()
 {
-  struct py_varobj_iter *dis = (struct py_varobj_iter *) self;
-  gdbpy_enter_varobj enter_py (self->var);
-  Py_XDECREF (dis->iter);
+  gdbpy_enter_varobj enter_py (m_var);
+  Py_XDECREF (m_iter);
 }
 
 /* Implementation of the 'next' method of pretty-printed varobj
    iterators.  */
 
-static varobj_item *
-py_varobj_iter_next (struct varobj_iter *self)
+varobj_item *
+py_varobj_iter::next ()
 {
-  struct py_varobj_iter *t = (struct py_varobj_iter *) self;
   PyObject *py_v;
   varobj_item *vitem;
   const char *name = NULL;
@@ -56,9 +65,9 @@ py_varobj_iter_next (struct varobj_iter *self)
   if (!gdb_python_initialized)
     return NULL;
 
-  gdbpy_enter_varobj enter_py (self->var);
+  gdbpy_enter_varobj enter_py (m_var);
 
-  gdbpy_ref<> item (PyIter_Next (t->iter));
+  gdbpy_ref<> item (PyIter_Next (m_iter));
 
   if (item == NULL)
     {
@@ -78,7 +87,7 @@ py_varobj_iter_next (struct varobj_iter *self)
            }
 
          std::string name_str = string_printf ("<error at %d>",
-                                               self->next_raw_index++);
+                                               m_next_raw_index++);
          item.reset (Py_BuildValue ("(ss)", name_str.c_str (),
                                     value_str.get ()));
          if (item == NULL)
@@ -107,45 +116,18 @@ py_varobj_iter_next (struct varobj_iter *self)
     gdbpy_print_stack ();
   vitem->name = name;
 
-  self->next_raw_index++;
+  m_next_raw_index++;
   return vitem;
 }
 
-/* The 'vtable' of pretty-printed python varobj iterators.  */
-
-static const struct varobj_iter_ops py_varobj_iter_ops =
-{
-  py_varobj_iter_dtor,
-  py_varobj_iter_next
-};
-
 /* Constructor of pretty-printed varobj iterators.  VAR is the varobj
    whose children the iterator will be iterating over.  PYITER is the
    python iterator actually responsible for the iteration.  */
 
-static void
-py_varobj_iter_ctor (struct py_varobj_iter *self,
-                    struct varobj *var, gdbpy_ref<> &&pyiter)
+py_varobj_iter::py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter)
+  : m_var (var),
+    m_iter (pyiter.release ())
 {
-  self->base.var = var;
-  self->base.ops = &py_varobj_iter_ops;
-  self->base.next_raw_index = 0;
-  self->iter = pyiter.release ();
-}
-
-/* Allocate and construct a pretty-printed varobj iterator.  VAR is
-   the varobj whose children the iterator will be iterating over.
-   PYITER is the python iterator actually responsible for the
-   iteration.  */
-
-static struct py_varobj_iter *
-py_varobj_iter_new (struct varobj *var, gdbpy_ref<> &&pyiter)
-{
-  struct py_varobj_iter *self;
-
-  self = XNEW (struct py_varobj_iter);
-  py_varobj_iter_ctor (self, var, std::move (pyiter));
-  return self;
 }
 
 /* Return a new pretty-printed varobj iterator suitable to iterate
@@ -154,8 +136,6 @@ py_varobj_iter_new (struct varobj *var, gdbpy_ref<> &&pyiter)
 struct varobj_iter *
 py_varobj_get_iterator (struct varobj *var, PyObject *printer)
 {
-  struct py_varobj_iter *py_iter;
-
   gdbpy_enter_varobj enter_py (var);
 
   if (!PyObject_HasAttr (printer, gdbpy_children_cst))
@@ -176,7 +156,5 @@ py_varobj_get_iterator (struct varobj *var, PyObject *printer)
       error (_("Could not get children iterator"));
     }
 
-  py_iter = py_varobj_iter_new (var, std::move (iter));
-
-  return &py_iter->base;
+  return new py_varobj_iter (var, std::move (iter));
 }
index 240b686b256e4d90e7a28109cdf8a0549310f940..ed654190ca539e27553c1da3b1aa4596fc660001 100644 (file)
@@ -28,50 +28,15 @@ struct varobj_item
   struct value *value;
 };
 
-struct varobj_iter_ops;
-
 /* A dynamic varobj iterator "class".  */
 
 struct varobj_iter
 {
-  /* The 'vtable'.  */
-  const struct varobj_iter_ops *ops;
-
-  /* The varobj this iterator is listing children for.  */
-  struct varobj *var;
-
-  /* The next raw index we will try to check is available.  If it is
-     equal to number_of_children, then we've already iterated the
-     whole set.  */
-  int next_raw_index;
-};
-
-/* The vtable of the varobj iterator class.  */
+public:
 
-struct varobj_iter_ops
-{
-  /* Destructor.  Releases everything from SELF (but not SELF
-     itself).  */
-  void (*dtor) (struct varobj_iter *self);
+  virtual ~varobj_iter () = default;
 
-  /* Returns the next object or NULL if it has reached the end.  */
-  varobj_item *(*next) (struct varobj_iter *self);
+  virtual varobj_item *next () = 0;
 };
 
-/* Returns the next varobj or NULL if it has reached the end.  */
-
-#define varobj_iter_next(ITER) (ITER)->ops->next (ITER)
-
-/* Delete a varobj_iter object.  */
-
-#define varobj_iter_delete(ITER)              \
-  do                                          \
-    {                                         \
-      if ((ITER) != NULL)                     \
-       {                                      \
-         (ITER)->ops->dtor (ITER);            \
-         xfree (ITER);                \
-       }                                      \
-    } while (0)
-
 #endif /* VAROBJ_ITER_H */
index e4d640f9d611c94f2d2f601c2683d2cc1f8a5f29..80de679a60799b2bc4d3ada4d56771973e719b47 100644 (file)
@@ -702,7 +702,7 @@ update_dynamic_varobj_children (struct varobj *var,
 
   if (update_children || var->dynamic->child_iter == NULL)
     {
-      varobj_iter_delete (var->dynamic->child_iter);
+      delete var->dynamic->child_iter;
       var->dynamic->child_iter = varobj_get_iterator (var);
 
       varobj_clear_saved_item (var->dynamic);
@@ -729,7 +729,7 @@ update_dynamic_varobj_children (struct varobj *var,
        }
       else
        {
-         item = varobj_iter_next (var->dynamic->child_iter);
+         item = var->dynamic->child_iter->next ();
          /* Release vitem->value so its lifetime is not bound to the
             execution of a command.  */
          if (item != NULL && item->value != NULL)
@@ -739,7 +739,7 @@ update_dynamic_varobj_children (struct varobj *var,
       if (item == NULL)
        {
          /* Iteration is done.  Remove iterator from VAR.  */
-         varobj_iter_delete (var->dynamic->child_iter);
+         delete var->dynamic->child_iter;
          var->dynamic->child_iter = NULL;
          break;
        }
@@ -1070,7 +1070,7 @@ install_visualizer (struct varobj_dynamic *var, PyObject *constructor,
   Py_XDECREF (var->pretty_printer);
   var->pretty_printer = visualizer;
 
-  varobj_iter_delete (var->child_iter);
+  delete var->child_iter;
   var->child_iter = NULL;
 }
 
@@ -1881,7 +1881,7 @@ varobj::~varobj ()
     }
 #endif
 
-  varobj_iter_delete (var->dynamic->child_iter);
+  delete var->dynamic->child_iter;
   varobj_clear_saved_item (var->dynamic);
 
   if (is_root_p (var))