Allow a pretty-printer without a to_string method

Message ID 20180908204210.22927-1-tom@tromey.com
State New, archived
Headers

Commit Message

Tom Tromey Sept. 8, 2018, 8:42 p.m. UTC
  PR python/16047 points out that, while the documentation says that the
to_string method is optional for a pretty-printer, the code disagrees
and throws an exception.  This patch fixes the problem.  varobj is
already ok here.

Tested on x86-64 Fedora 26.

gdb/ChangeLog
2018-09-08  Tom Tromey  <tom@tromey.com>

	PR python/16047:
	* python/py-prettyprint.c (pretty_print_one_value): Check for
	to_string method.

gdb/testsuite/ChangeLog
2018-09-08  Tom Tromey  <tom@tromey.com>

	PR python/16047:
	* gdb.python/py-prettyprint.py (pp_int_typedef3): New class.
	(register_pretty_printers): Register new printer.
	* gdb.python/py-prettyprint.exp (run_lang_tests): Add int_type3
	test.
	* gdb.python/py-prettyprint.c (int_type3): New typedef.
	(an_int_type3): New global.
---
 gdb/ChangeLog                               |  6 ++++++
 gdb/python/py-prettyprint.c                 | 25 +++++++++++++++----------
 gdb/testsuite/ChangeLog                     | 10 ++++++++++
 gdb/testsuite/gdb.python/py-prettyprint.c   |  2 ++
 gdb/testsuite/gdb.python/py-prettyprint.exp |  2 ++
 gdb/testsuite/gdb.python/py-prettyprint.py  | 10 ++++++++++
 6 files changed, 45 insertions(+), 10 deletions(-)
  

Comments

Simon Marchi Sept. 8, 2018, 11:09 p.m. UTC | #1
> diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
> index 2671cb8471b..fe7774fa886 100644
> --- a/gdb/testsuite/gdb.python/py-prettyprint.exp
> +++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
> @@ -127,6 +127,8 @@ proc run_lang_tests {exefile lang} {
>      gdb_test "print (int_type) an_int_type2" " = type=int_type, val=2"
>      gdb_test "print (int_type2) an_int_type2" " = type=int_type2, val=2"
>  
> +    gdb_test "print (int_type3) an_int_type2" " = {s = 27}"

Maybe just add a comment above this to indicate what this tests?  It's clear once
you go read the comment in the .py file, but it isn't here.

Otherwise, LGTM.

Simon
  
Tom Tromey Sept. 9, 2018, 2:50 a.m. UTC | #2
>>>>> "Simon" == Simon Marchi <simon.marchi@ericsson.com> writes:

>> diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
>> index 2671cb8471b..fe7774fa886 100644
>> --- a/gdb/testsuite/gdb.python/py-prettyprint.exp
>> +++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
>> @@ -127,6 +127,8 @@ proc run_lang_tests {exefile lang} {
>> gdb_test "print (int_type) an_int_type2" " = type=int_type, val=2"
>> gdb_test "print (int_type2) an_int_type2" " = type=int_type2, val=2"
>> 
>> +    gdb_test "print (int_type3) an_int_type2" " = {s = 27}"

Simon> Maybe just add a comment above this to indicate what this tests?  It's clear once
Simon> you go read the comment in the .py file, but it isn't here.

Simon> Otherwise, LGTM.

Thanks, I'm checking it in with that fixed.

Tom
  

Patch

diff --git a/gdb/python/py-prettyprint.c b/gdb/python/py-prettyprint.c
index a8a84899309..df0266b2613 100644
--- a/gdb/python/py-prettyprint.c
+++ b/gdb/python/py-prettyprint.c
@@ -195,18 +195,23 @@  pretty_print_one_value (PyObject *printer, struct value **out_value)
   *out_value = NULL;
   TRY
     {
-      result.reset (PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst,
-						NULL));
-      if (result != NULL)
+      if (!PyObject_HasAttr (printer, gdbpy_to_string_cst))
+	result = gdbpy_ref<>::new_reference (Py_None);
+      else
 	{
-	  if (! gdbpy_is_string (result.get ())
-	      && ! gdbpy_is_lazy_string (result.get ())
-	      && result != Py_None)
+	  result.reset (PyObject_CallMethodObjArgs (printer, gdbpy_to_string_cst,
+						    NULL));
+	  if (result != NULL)
 	    {
-	      *out_value = convert_value_from_python (result.get ());
-	      if (PyErr_Occurred ())
-		*out_value = NULL;
-	      result = NULL;
+	      if (! gdbpy_is_string (result.get ())
+		  && ! gdbpy_is_lazy_string (result.get ())
+		  && result != Py_None)
+		{
+		  *out_value = convert_value_from_python (result.get ());
+		  if (PyErr_Occurred ())
+		    *out_value = NULL;
+		  result = NULL;
+		}
 	    }
 	}
     }
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.c b/gdb/testsuite/gdb.python/py-prettyprint.c
index 35ef5e0756b..ef5b0c3c5ea 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.c
+++ b/gdb/testsuite/gdb.python/py-prettyprint.c
@@ -271,10 +271,12 @@  bug_14741()
    when looking for a printer.  */
 typedef int int_type;
 typedef int_type int_type2;
+typedef int_type int_type3;
 
 int an_int = -1;
 int_type an_int_type = 1;
 int_type2 an_int_type2 = 2;
+int_type3 an_int_type3 = 3;
 
 int
 main ()
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.exp b/gdb/testsuite/gdb.python/py-prettyprint.exp
index 2671cb8471b..fe7774fa886 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.exp
+++ b/gdb/testsuite/gdb.python/py-prettyprint.exp
@@ -127,6 +127,8 @@  proc run_lang_tests {exefile lang} {
     gdb_test "print (int_type) an_int_type2" " = type=int_type, val=2"
     gdb_test "print (int_type2) an_int_type2" " = type=int_type2, val=2"
 
+    gdb_test "print (int_type3) an_int_type2" " = {s = 27}"
+
     gdb_continue_to_end
 }
 
diff --git a/gdb/testsuite/gdb.python/py-prettyprint.py b/gdb/testsuite/gdb.python/py-prettyprint.py
index 7357f05cc93..91592b4ec79 100644
--- a/gdb/testsuite/gdb.python/py-prettyprint.py
+++ b/gdb/testsuite/gdb.python/py-prettyprint.py
@@ -253,6 +253,15 @@  class pp_int_typedef (object):
     def to_string(self):
         return "type=%s, val=%s" % (self.val.type, int(self.val))
 
+class pp_int_typedef3 (object):
+    "A printer without a to_string method"
+
+    def __init__(self, val):
+        self.val = val
+
+    def children(self):
+        yield 's', 27
+
 def lookup_function (val):
     "Look-up and return a pretty-printer that can print val."
 
@@ -362,6 +371,7 @@  def register_pretty_printers ():
 
     typedefs_pretty_printers_dict[re.compile ('^int_type$')] = pp_int_typedef
     typedefs_pretty_printers_dict[re.compile ('^int_type2$')] = pp_int_typedef
+    typedefs_pretty_printers_dict[re.compile ('^int_type3$')] = pp_int_typedef3
 
 # Dict for struct types with typedefs fully stripped.
 pretty_printers_dict = {}