Use pretty printers for struct member stubs

Message ID 20231207195331.3250-1-ssbssa@yahoo.de
State New
Headers
Series Use pretty printers for struct member stubs |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Testing passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Testing passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Testing passed

Commit Message

Hannes Domani Dec. 7, 2023, 7:53 p.m. UTC
  PR29079 shows that pretty printers can be used for an incomplete
type (stub), but only when printing it directly, not if it's
part of another struct:
```
(gdb) p s
$1 = {pp m_i = 5}
(gdb) p s2
$2 = {m_s = <incomplete type>, m_l = 20}
```

The reason is simply that in common_val_print the check for stubs
is before any pretty printer is tried.
It works if the pretty printer is tried before the stub check:
```
(gdb) p s
$1 = {pp m_i = 5}
(gdb) p s2
$2 = {m_s = {pp m_i = 10}, m_l = 20}
```

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29079
---
 .../gdb.python/py-prettyprint-stub-2.cc       | 26 ++++++++
 .../gdb.python/py-prettyprint-stub.cc         | 36 +++++++++++
 .../gdb.python/py-prettyprint-stub.exp        | 59 +++++++++++++++++++
 .../gdb.python/py-prettyprint-stub.h          | 24 ++++++++
 .../gdb.python/py-prettyprint-stub.py         | 38 ++++++++++++
 gdb/valprint.c                                | 20 +++----
 6 files changed, 193 insertions(+), 10 deletions(-)
 create mode 100644 gdb/testsuite/gdb.python/py-prettyprint-stub-2.cc
 create mode 100644 gdb/testsuite/gdb.python/py-prettyprint-stub.cc
 create mode 100644 gdb/testsuite/gdb.python/py-prettyprint-stub.exp
 create mode 100644 gdb/testsuite/gdb.python/py-prettyprint-stub.h
 create mode 100644 gdb/testsuite/gdb.python/py-prettyprint-stub.py
  

Comments

Tom Tromey Dec. 8, 2023, 4:19 p.m. UTC | #1
>>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:

Hannes> PR29079 shows that pretty printers can be used for an incomplete
Hannes> type (stub), but only when printing it directly, not if it's
Hannes> part of another struct:
[...]

Thank you for the patch and the explanation -- I had seen that bug but
didn't realize that this already worked for the top-level.

This is ok.

Approved-By: Tom Tromey <tom@tromey.com>

Tom
  
Hannes Domani Dec. 8, 2023, 5:24 p.m. UTC | #2
Am Freitag, 8. Dezember 2023, 17:19:36 MEZ hat Tom Tromey <tom@tromey.com> Folgendes geschrieben:

> >>>>> "Hannes" == Hannes Domani <ssbssa@yahoo.de> writes:
>
> Hannes> PR29079 shows that pretty printers can be used for an incomplete
> Hannes> type (stub), but only when printing it directly, not if it's
> Hannes> part of another struct:
> [...]
>
> Thank you for the patch and the explanation -- I had seen that bug but
> didn't realize that this already worked for the top-level.
>
> This is ok.
>
> Approved-By: Tom Tromey <tom@tromey.com>

Pushed, thanks.
  

Patch

diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub-2.cc b/gdb/testsuite/gdb.python/py-prettyprint-stub-2.cc
new file mode 100644
index 00000000000..41a949d4425
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub-2.cc
@@ -0,0 +1,26 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 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/>.  */
+
+#include "py-prettyprint-stub.h"
+
+S::S (int i) : m_i (i)
+{
+}
+
+S::~S ()
+{
+}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub.cc b/gdb/testsuite/gdb.python/py-prettyprint-stub.cc
new file mode 100644
index 00000000000..9b0aef3bf8e
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub.cc
@@ -0,0 +1,36 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 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/>.  */
+
+#include "py-prettyprint-stub.h"
+
+struct S2
+{
+  S2 (int i, long l) : m_s (i), m_l (l)
+  {
+  }
+
+  S m_s;
+  long m_l;
+};
+
+int main ()
+{
+  S s (5);
+  S2 s2 (10, 20);
+
+  return 0; /* Break here.  */
+}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub.exp b/gdb/testsuite/gdb.python/py-prettyprint-stub.exp
new file mode 100644
index 00000000000..79492ec5e5d
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub.exp
@@ -0,0 +1,59 @@ 
+# Copyright (C) 2023 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-based pretty-printing of stubs.
+
+load_lib gdb-python.exp
+
+require allow_python_tests
+
+standard_testfile .cc py-prettyprint-stub-2.cc
+
+set srcfiles [list $srcfile $srcfile2]
+
+if { [build_executable_from_specs \
+	  "failed to prepare" \
+	  $testfile {c++} \
+	  $srcfile {c++ debug} \
+	  $srcfile2 {c++}] == -1 } {
+    return -1
+}
+
+# Start with a fresh gdb.
+clean_restart $testfile
+
+if {![runto_main]} {
+    return
+}
+
+set remote_python_file [gdb_remote_download host \
+			${srcdir}/${subdir}/${testfile}.py]
+
+gdb_breakpoint [gdb_get_line_number "Break here."]
+gdb_continue_to_breakpoint "Break here" ".*Break here.*"
+
+# First test without pretty printer.
+gdb_test "print s" " = <incomplete type>"
+gdb_test "print s2" " = {m_s = <incomplete type>, m_l = 20}"
+
+# Load pretty printer.
+gdb_test_no_output "source ${remote_python_file}" "load python file"
+
+# Test with pretty printer.
+with_test_prefix pp {
+    gdb_test "print s" " = {pp m_i = 5}"
+    gdb_test "print s2" " = {m_s = {pp m_i = 10}, m_l = 20}"
+}
diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub.h b/gdb/testsuite/gdb.python/py-prettyprint-stub.h
new file mode 100644
index 00000000000..1bb56c7c65a
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub.h
@@ -0,0 +1,24 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2023 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/>.  */
+
+struct S
+{
+  S (int);
+  virtual ~S ();
+
+  int m_i;
+};
diff --git a/gdb/testsuite/gdb.python/py-prettyprint-stub.py b/gdb/testsuite/gdb.python/py-prettyprint-stub.py
new file mode 100644
index 00000000000..2315494c121
--- /dev/null
+++ b/gdb/testsuite/gdb.python/py-prettyprint-stub.py
@@ -0,0 +1,38 @@ 
+# Copyright (C) 2023 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-based pretty-printing of stubs.
+
+
+class SPrinter:
+    def __init__(self, val):
+        self.val = val
+
+    def to_string(self):
+        char_ptr = gdb.lookup_type("char").pointer()
+        int_ptr = gdb.lookup_type("int").pointer()
+        # m_i should be after the vtable, which has the size of a pointer
+        i = (
+            (self.val.address.cast(char_ptr) + int_ptr.sizeof)
+            .cast(int_ptr)
+            .dereference()
+        )
+        return "{pp m_i = %d}" % int(i)
+
+
+pp = gdb.printing.RegexpCollectionPrettyPrinter("S")
+pp.add_printer("S", "^S$", SPrinter)
+gdb.printing.register_pretty_printer(gdb.current_objfile(), pp, True)
diff --git a/gdb/valprint.c b/gdb/valprint.c
index d48c599c832..00943c1111a 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -1054,16 +1054,6 @@  common_val_print (struct value *value, struct ui_file *stream, int recurse,
 
   QUIT;
 
-  /* Ensure that the type is complete and not just a stub.  If the type is
-     only a stub and we can't find and substitute its complete type, then
-     print appropriate string and return.  */
-
-  if (real_type->is_stub ())
-    {
-      fprintf_styled (stream, metadata_style.style (), _("<incomplete type>"));
-      return;
-    }
-
   if (!valprint_check_validity (stream, real_type, 0, value))
     return;
 
@@ -1074,6 +1064,16 @@  common_val_print (struct value *value, struct ui_file *stream, int recurse,
 	return;
     }
 
+  /* Ensure that the type is complete and not just a stub.  If the type is
+     only a stub and we can't find and substitute its complete type, then
+     print appropriate string and return.  */
+
+  if (real_type->is_stub ())
+    {
+      fprintf_styled (stream, metadata_style.style (), _("<incomplete type>"));
+      return;
+    }
+
   /* Handle summary mode.  If the value is a scalar, print it;
      otherwise, print an ellipsis.  */
   if (options->summary && !val_print_scalar_type_p (type))