FYI: fix PR python/12070

Tom Tromey tromey@redhat.com
Fri Feb 17 19:36:00 GMT 2012


I'm checking this in.

This fixes PR python/12070.  The bug is that the built-in 'dir' function
doesn't show attributes of gdb.Field.

I fixed this by adding a __dict__ attribute to Field, which lets 'dir'
do the right thing.  I'm not sure why this isn't the default for classes
with a non-zero tp_dictoffset.

I also looked for other instances of the bug, and fixed the one I found,
in gdb.Event.

Built and regtested on x86-64 Fedora 16.
I added new test cases.

Tom

2012-02-17  Tom Tromey  <tromey@redhat.com>

	PR python/12070:
	* python/py-event.c (event_object_getset): New global.
	(event_object_type): Reference it.
	* python/py-type.c (field_object_getset): New global.
	(field_object_type): Reference it.
	* python/python-internal.h (gdb_py_generic_dict): Declare.
	* python/py-utils.c (gdb_py_generic_dict): New function.

2012-02-17  Tom Tromey  <tromey@redhat.com>

	* gdb.python/py-events.py (exit_handler): Add test for 'dir'.
	* gdb.python/py-events.exp: Check 'dir' output.
	* gdb.python/py-type.exp (test_fields): Add test for 'dir'.

diff --git a/gdb/python/py-event.c b/gdb/python/py-event.c
index 7d4ff14..4789761 100644
--- a/gdb/python/py-event.c
+++ b/gdb/python/py-event.c
@@ -132,6 +132,13 @@ evpy_emit_event (PyObject *event,
   return -1;
 }
 
+static PyGetSetDef event_object_getset[] =
+{
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this event.", &event_object_type },
+  { NULL }
+};
+
 PyTypeObject event_object_type =
 {
   PyObject_HEAD_INIT (NULL)
@@ -164,7 +171,7 @@ PyTypeObject event_object_type =
   0,                                          /* tp_iternext */
   0,                                          /* tp_methods */
   0,                                          /* tp_members */
-  0,                                          /* tp_getset */
+  event_object_getset,			      /* tp_getset */
   0,                                          /* tp_base */
   0,                                          /* tp_dict */
   0,                                          /* tp_descr_get */
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index 70ed5d6..d47d4c8 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1681,6 +1681,13 @@ static PyTypeObject type_object_type =
   0,				  /* tp_new */
 };
 
+static PyGetSetDef field_object_getset[] =
+{
+  { "__dict__", gdb_py_generic_dict, NULL,
+    "The __dict__ for this field.", &field_object_type },
+  { NULL }
+};
+
 static PyTypeObject field_object_type =
 {
   PyObject_HEAD_INIT (NULL)
@@ -1713,7 +1720,7 @@ static PyTypeObject field_object_type =
   0,				  /* tp_iternext */
   0,				  /* tp_methods */
   0,				  /* tp_members */
-  0,				  /* tp_getset */
+  field_object_getset,		  /* tp_getset */
   0,				  /* tp_base */
   0,				  /* tp_dict */
   0,				  /* tp_descr_get */
diff --git a/gdb/python/py-utils.c b/gdb/python/py-utils.c
index 3579720..bf50e37 100644
--- a/gdb/python/py-utils.c
+++ b/gdb/python/py-utils.c
@@ -373,3 +373,23 @@ gdb_py_int_as_long (PyObject *obj, long *result)
   *result = PyInt_AsLong (obj);
   return ! (*result == -1 && PyErr_Occurred ());
 }
+
+
+
+/* Generic implementation of the __dict__ attribute for objects that
+   have a dictionary.  The CLOSURE argument should be the type object.
+   This only handles positive values for tp_dictoffset.  */
+
+PyObject *
+gdb_py_generic_dict (PyObject *self, void *closure)
+{
+  PyObject *result;
+  PyTypeObject *type_obj = closure;
+  char *raw_ptr;
+
+  raw_ptr = (char *) self + type_obj->tp_dictoffset;
+  result = * (PyObject **) raw_ptr;
+
+  Py_INCREF (result);
+  return result;
+}
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 1d6247d..bae61c2 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -342,4 +342,6 @@ PyObject *gdb_py_object_from_longest (LONGEST l);
 PyObject *gdb_py_object_from_ulongest (ULONGEST l);
 int gdb_py_int_as_long (PyObject *, long *);
 
+PyObject *gdb_py_generic_dict (PyObject *self, void *closure);
+
 #endif /* GDB_PYTHON_INTERNAL_H */
diff --git a/gdb/testsuite/gdb.python/py-events.exp b/gdb/testsuite/gdb.python/py-events.exp
index 18d3380..d872daf 100644
--- a/gdb/testsuite/gdb.python/py-events.exp
+++ b/gdb/testsuite/gdb.python/py-events.exp
@@ -85,10 +85,12 @@ delete_breakpoints
 gdb_test "continue" ".*event type: continue.*
 .*event type: exit.*
 .*exit code: 12.*
-.*exit inf: 1.*" "Inferior 1 terminated."
+.*exit inf: 1.*
+dir ok: True.*" "Inferior 1 terminated."
 
 gdb_test "inferior 2" ".*Switching to inferior 2.*"
 gdb_test "continue" ".*event type: continue.*
 .*event type: exit.*
 .*exit code: 12.*
-.*exit inf: 2.*" "Inferior 2 terminated."
+.*exit inf: 2.*
+dir ok: True.*" "Inferior 2 terminated."
diff --git a/gdb/testsuite/gdb.python/py-events.py b/gdb/testsuite/gdb.python/py-events.py
index 122def0..f7e45f5 100644
--- a/gdb/testsuite/gdb.python/py-events.py
+++ b/gdb/testsuite/gdb.python/py-events.py
@@ -44,6 +44,7 @@ def exit_handler (event):
         print "event type: exit"
     print "exit code: %d" % (event.exit_code)
     print "exit inf: %d" % (event.inferior.num)
+    print "dir ok: %s" % str('exit_code' in dir(event))
 
 def continue_handler (event):
     if (isinstance (event, gdb.ContinueEvent)):
diff --git a/gdb/testsuite/gdb.python/py-type.exp b/gdb/testsuite/gdb.python/py-type.exp
index e4729ad..feb76ba 100644
--- a/gdb/testsuite/gdb.python/py-type.exp
+++ b/gdb/testsuite/gdb.python/py-type.exp
@@ -86,6 +86,11 @@ proc test_fields {lang} {
   gdb_test "python print fields\[0\].name" "a" "Check structure field a name"
   gdb_test "python print fields\[1\].name" "b" "Check structure field b name"
 
+  # Regression test for
+  # http://sourceware.org/bugzilla/show_bug.cgi?id=12070.
+  gdb_test "python print 'type' in dir(fields\[0\])" "True" \
+    "Check that dir includes name"
+
   # Test Python mapping behavior of gdb.Type for structs/classes
   gdb_test "python print len(st.type)" "2" "Check number of fields"
   gdb_test "python print st.type\['a'\].name" "a" "Check fields lookup by name"



More information about the Gdb-patches mailing list