Fix Python pretty-printing bug in Rust
authorTom Tromey <tom@tromey.com>
Sat, 15 May 2021 01:54:35 +0000 (19:54 -0600)
committerTom Tromey <tom@tromey.com>
Sat, 15 May 2021 02:01:12 +0000 (20:01 -0600)
An upstream Rust bug notes notes that the Python pretty-printing
feature is broken for values that appear as members of certain types
in Rust.

The bug here is that some of the Rust value-printing code calls
value_print_inner, a method on rust_language.  This bypasses the
common code that calls into Python.

I'm checking this in.

gdb/ChangeLog
2021-05-14  Tom Tromey  <tom@tromey.com>

* rust-lang.c (rust_language::val_print_struct)
(rust_language::print_enum): Use common_val_print, not
value_print_inner.

gdb/testsuite/ChangeLog
2021-05-14  Tom Tromey  <tom@tromey.com>

* gdb.rust/pp.exp: New file.
* gdb.rust/pp.py: New file.
* gdb.rust/pp.rs: New file.

gdb/ChangeLog
gdb/rust-lang.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.rust/pp.exp [new file with mode: 0644]
gdb/testsuite/gdb.rust/pp.py [new file with mode: 0644]
gdb/testsuite/gdb.rust/pp.rs [new file with mode: 0644]

index d44b06d955940fb598eb337373b9f90f492b359a..8e1e00250b89477f81ea41652ec2bc92ae014218 100644 (file)
@@ -1,3 +1,9 @@
+2021-05-14  Tom Tromey  <tom@tromey.com>
+
+       * rust-lang.c (rust_language::val_print_struct)
+       (rust_language::print_enum): Use common_val_print, not
+       value_print_inner.
+
 2021-05-14  Tankut Baris Aktemur  <tankut.baris.aktemur@intel.com>
 
        * python/py-inferior.c (infpy_get_connection_num): New function.
index 8c4d209b07ad5bc3f04f1fa546418a0993a2348b..3b15bb22a27c0e7c7b2b4a755bcee57f7c740111 100644 (file)
@@ -386,7 +386,8 @@ rust_language::val_print_struct
          fputs_filtered (": ", stream);
        }
 
-      value_print_inner (value_field (val, i), stream, recurse + 1, &opts);
+      common_val_print (value_field (val, i), stream, recurse + 1, &opts,
+                       this);
     }
 
   if (options->prettyformat)
@@ -464,7 +465,8 @@ rust_language::print_enum (struct value *val, struct ui_file *stream,
                          styled_string (variable_name_style.style (),
                                         TYPE_FIELD_NAME (variant_type, j)));
 
-      value_print_inner (value_field (val, j), stream, recurse + 1, &opts);
+      common_val_print (value_field (val, j), stream, recurse + 1, &opts,
+                       this);
     }
 
   if (is_tuple)
index c723a9a0a8e41ec46257f1428a4c9b225efd1b6b..c7e7152eee08f46982cd3302e5bd4b8da9b10b47 100644 (file)
@@ -1,3 +1,9 @@
+2021-05-14  Tom Tromey  <tom@tromey.com>
+
+       * gdb.rust/pp.exp: New file.
+       * gdb.rust/pp.py: New file.
+       * gdb.rust/pp.rs: New file.
+
 2021-05-14  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        * gdb.base/index-cache.exp: Cleanup $cache_dir/*.gdb-index and
diff --git a/gdb/testsuite/gdb.rust/pp.exp b/gdb/testsuite/gdb.rust/pp.exp
new file mode 100644 (file)
index 0000000..abe2168
--- /dev/null
@@ -0,0 +1,42 @@
+# Copyright (C) 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test expression parsing and evaluation that requires Rust compiler.
+
+load_lib gdb-python.exp
+load_lib rust-support.exp
+if {[skip_rust_tests]} {
+    continue
+}
+
+standard_testfile .rs
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} {
+    return -1
+}
+
+if { [skip_python_tests] } { continue }
+
+set remote_python_file [gdb_remote_download host \
+                           ${srcdir}/${subdir}/${testfile}.py]
+gdb_test_no_output "source ${remote_python_file}" "load python file"
+
+set line [gdb_get_line_number "set breakpoint here"]
+if {![runto ${srcfile}:$line]} {
+    untested "could not run to breakpoint"
+    return -1
+}
+
+gdb_test "print outer" " = pp::Outer \\(x\\(5\\)\\)"
+gdb_test "print outer.0" " = x\\(5\\)"
diff --git a/gdb/testsuite/gdb.rust/pp.py b/gdb/testsuite/gdb.rust/pp.py
new file mode 100644 (file)
index 0000000..57c8cc3
--- /dev/null
@@ -0,0 +1,49 @@
+# Copyright (C) 2021 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# This file is part of the GDB testsuite.  It tests python pretty
+# printers.
+
+import re
+import gdb
+
+
+# Printer for Inner.
+class inner_print(object):
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        return "x(" + str(self.val["x"]) + ")"
+
+
+def lookup_function(val):
+    "Look-up and return a pretty-printer that can print val."
+
+    # Get the type.
+    type = val.type
+
+    # Get the type name.
+    typename = type.tag
+
+    if typename == None:
+        return None
+
+    if typename == "pp::Inner":
+        return inner_print(val)
+    return None
+
+
+gdb.pretty_printers.append(lookup_function)
diff --git a/gdb/testsuite/gdb.rust/pp.rs b/gdb/testsuite/gdb.rust/pp.rs
new file mode 100644 (file)
index 0000000..23e85af
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright (C) 2021 Free Software Foundation, Inc.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#![allow(dead_code)]
+#![allow(unused_variables)]
+#![allow(unused_assignments)]
+
+struct Inner{ x : u8 }
+struct Outer(Inner);
+
+fn main () {
+    let outer = Outer(Inner{x: 5});
+    println!("{}", outer.0.x);        // set breakpoint here
+}