RFC: fix PR 14386

Tom Tromey tromey@redhat.com
Wed Aug 1 18:11:00 GMT 2012


This fixes PR python/14386.

I'd like to commit this to the trunk and the 7.5 branch; the latter
because it is a reasonably obvious, low-risk, and useful bug fix.

The bug here is that a certain libstdc++ pretty-printer doesn't work in
MI.

What is going on is that the printer in question returns a Python list
object from its 'children' method.  This is perfectly fine.  However,
the varobj code uses PyIter_Check on the returned object, and this
evaluates to false for a list.

I think this is arguably a bug in Python, so I filed:

    http://bugs.python.org/issue15529

Meanwhile, it seems safest not to call PyIter_Check.  We certainly don't
need to -- the CLI doesn't -- because we can just call PyObject_GetIter
and react appropriately if that fails.

Built and tested on x86-64 Fedora 16.
New test case included.

Tom

commit 4074f681d23d3ee12c92bbe128e55f9e0d5a142e
Author: Tom Tromey <tromey@redhat.com>
Date:   Wed Aug 1 10:30:11 2012 -0600

    fix PR python/14386
    
    	PR python/14386:
    	* varobj.c (update_dynamic_varobj_children): Don't call
    	PyIter_Check.
    
    	* gdb.python/py-mi.exp: Add test for printer whose children
    	are a list.
    	* gdb.python/py-prettyprint.c (struct children_as_list): New.
    	(main): New variable children_as_list.
    	* gdb.python/py-prettyprint.py (class pp_children_as_list):
    	New.
    	(register_pretty_printers): Register new printer.

diff --git a/gdb/testsuite/gdb.python/py-mi.exp b/gdb/testsuite/gdb.python/py-mi.exp
index a792e44..e7034a1 100644
--- a/gdb/testsuite/gdb.python/py-mi.exp
+++ b/gdb/testsuite/gdb.python/py-mi.exp
@@ -289,6 +289,10 @@ mi_gdb_test "-var-evaluate-expression me" \
 	"\\^done,value=\"<error reading variable: Cannot access memory.>.*\"" \
 	"evaluate me varobj"
 
+# Regression test for python/14836.
+mi_create_dynamic_varobj children_as_list children_as_list \
+    "printer whose children are returned as a list"
+
 # C++ MI tests
 gdb_exit
 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}-cxx" \
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 1ff9e05..b1a12b1 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -48,6 +48,10 @@ struct hint_error {
   int x;
 };
 
+struct children_as_list {
+  int x;
+};
+
 #ifdef __cplusplus
 struct S : public s {
   int zs;
@@ -252,6 +256,7 @@ main ()
   struct ns ns, ns2;
   struct lazystring estring, estring2;
   struct hint_error hint_error;
+  struct children_as_list children_as_list;
 
   nstype.elements = narray;
   nstype.len = 0;
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index b02b90f..6e960e6 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -174,6 +174,18 @@ class pp_hint_error:
     def display_hint (self):
         raise Exception("hint failed")
 
+class pp_children_as_list:
+    "Throw error from display_hint"
+
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        return 'children_as_list_val'
+
+    def children (self):
+        return [('one', 1)]
+
 class pp_outer:
     "Print struct outer"
 
@@ -282,6 +294,9 @@ def register_pretty_printers ():
     pretty_printers_dict[re.compile ('^struct hint_error$')]  = pp_hint_error
     pretty_printers_dict[re.compile ('^hint_error$')]  = pp_hint_error
 
+    pretty_printers_dict[re.compile ('^struct children_as_list$')]  = pp_children_as_list
+    pretty_printers_dict[re.compile ('^children_as_list$')]  = pp_children_as_list
+
     pretty_printers_dict[re.compile ('^memory_error$')]  = MemoryErrorString
 
     pretty_printers_dict[re.compile ('^eval_type_s$')] = pp_eval_type
diff --git a/gdb/varobj.c b/gdb/varobj.c
index a75a40d..71b6436 100644
--- a/gdb/varobj.c
+++ b/gdb/varobj.c
@@ -1114,9 +1114,6 @@ update_dynamic_varobj_children (struct varobj *var,
 
       make_cleanup_py_decref (children);
 
-      if (!PyIter_Check (children))
-	error (_("Returned value is not iterable"));
-
       Py_XDECREF (var->child_iter);
       var->child_iter = PyObject_GetIter (children);
       if (!var->child_iter)



More information about the Gdb-patches mailing list