This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
Re: [patch] Fix glitches with libstdc++ pretty printers
On Mon, Dec 22, 2008 at 2:26 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:
>
> Paul> Hmm, an easy way to solve this would be to say that if Foo inherits
> Paul> from Bar, and if Bar has a pretty-printer but Foo doesn't, then
> Paul> the Bar pretty-printer is used.
>
> Paul> With that, I only need to define one pretty-printer :)
>
> This same problem came up in the GObject context.
>
> I do wonder whether regexp on the type name is the best way to
> associate types with printer constructors.
>
>
> One idea I had was that the -gdb.py code could iterate over the types
> defined in the current objfile and set up the dictionary using the
> results. We'd have to write some more Python glue to make this
> possible, but we'll need that anyway.
>
> This would let you implement printing-via-inheritance. We could even
> supply a utility function to make it simple.
>
> The down side of this approach is that (I think) it requires loading
> the symbols, which interacts poorly with the lazy-reading branch,
> which we also want.
>
>
> Another idea is to run a hook when a type is created, and do the
> association directly, not by name. My worry here is that we'd see a
> noticeable performance hit.
In a given GDB session, a great majority of types will not be
examined by the end-user, so it seems wasteful to examine type
hierarchies and create pretty-printers for the types which will
never be accesses.
It appears to me that the current "on demand" solution is better.
> Finally, you can do it already, with a bit of difficulty. You can
> install a printer constructor for any struct type, and then have it
> examine the type hierarchy.
Except (AFAICT) gdb.Type doesn't (yet) give access to ancestors.
So I believe I can't do it this way just yet.
The other difficulty is that (in C++) the type is (somewhat
unintuitively) called '^Foo$' (unlike C, where it is called
'^struct Foo$'), so I'd have to examine every possible type, not
just structs.
> If the desired ancestor is not found, it
> can return None, and the C code will look for the next printer. You
> can even register the newly discovered type in the map for faster
> access the next time.
>
> I imagine this is pretty slow, but I have not tried it. I think it
> would be preferable to come up with something nicer if we can.
>
> Right now I'm not sure what exactly I want to do. Gathering
> requirements is always a good first step...
>
> Tom
>
I've implemented the "automatically recursively search ancestors"
solution (patch attached), and will "unleash" it on my users.
We'll know in about a month how well (or how poorly) this works here.
Thanks,
--
Paul Pluzhnikov
From b3072c1e2734e83ce2d45ec755de0089d2125845 Mon Sep 17 00:00:00 2001
From: Paul Pluzhnikov <ppluzhnikov@google.com>
Date: Mon, 22 Dec 2008 14:09:16 -0800
Subject: [PATCH] Recursive search for pretty-printers.
---
gdb/ChangeLog | 5 +++++
gdb/python/python.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 38 insertions(+), 1 deletions(-)
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 05cfb87..d08ea03 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2008-12-22 Paul Pluzhnikov <ppluzhnikov@google.com>
+
+ * python/python.c (find_pretty_printer): Recursive search
+ for base class pretty-printer.
+
2008-12-17 Paul Pluzhnikov <ppluzhnikov@google.com>
* python/lib/gdb/libstdcxx/v6/printers.py: Iterator pretty-printers.
diff --git a/gdb/python/python.c b/gdb/python/python.c
index c2943cc..b662f7f 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -863,7 +863,7 @@ search_pp_dictionary (PyObject *dict, char *type_name)
pretty-printer exists, return NULL. If one exists, return a new
reference. */
static PyObject *
-find_pretty_printer (struct type *type)
+find_pretty_printer_1 (struct type *type)
{
PyObject *dict, *found = NULL;
char *type_name = NULL;
@@ -920,6 +920,38 @@ find_pretty_printer (struct type *type)
return found;
}
+static PyObject *
+find_pretty_printer (struct type *type)
+{
+ extern int opaque_type_resolution;
+ int i;
+ PyObject *printer;
+
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ type = TYPE_TARGET_TYPE (type);
+
+ printer = find_pretty_printer_1 (type);
+ if (printer
+ || (TYPE_CODE (type) != TYPE_CODE_STRUCT
+ && TYPE_CODE (type) != TYPE_CODE_UNION))
+ return printer;
+
+ if (TYPE_IS_OPAQUE (type) && opaque_type_resolution)
+ {
+ char *name = type_name_no_tag (type);
+ if (name != NULL)
+ type = lookup_transparent_type (name);
+ }
+ for (i = TYPE_N_BASECLASSES (type) - 1; i >= 0; i--)
+ {
+ struct type *t = TYPE_BASECLASS (type, i);
+ printer = find_pretty_printer (t);
+ if (printer)
+ return printer;
+ }
+ return NULL;
+}
+
/* Pretty-print a single value, via the printer object PRINTER. If
the function returns a string, an xmalloc()d copy is returned.
Otherwise, if the function returns a value, a *OUT_VALUE is set to
--
1.5.4.5