[PATCH 04/11] C++-ify varobj iteration

Tom Tromey tom@tromey.com
Sat Oct 24 21:08:49 GMT 2020


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-10-24  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          | 17 +++++++++
 gdb/python/py-varobj.c | 80 +++++++++++++++---------------------------
 gdb/varobj-iter.h      | 41 ++--------------------
 gdb/varobj.c           | 10 +++---
 4 files changed, 54 insertions(+), 94 deletions(-)

diff --git a/gdb/python/py-varobj.c b/gdb/python/py-varobj.c
index 9c791f64df1..df6f9c5a953 100644
--- a/gdb/python/py-varobj.c
+++ b/gdb/python/py-varobj.c
@@ -21,34 +21,43 @@
 /* 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));
 }
diff --git a/gdb/varobj-iter.h b/gdb/varobj-iter.h
index 240b686b256..ed654190ca5 100644
--- a/gdb/varobj-iter.h
+++ b/gdb/varobj-iter.h
@@ -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 */
diff --git a/gdb/varobj.c b/gdb/varobj.c
index ce5c85f163b..edcaad417f6 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -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))
-- 
2.17.2



More information about the Gdb-patches mailing list