public inbox for archer@sourceware.org
 help / color / mirror / Atom feed
* [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
@ 2009-03-27 17:05 Phil Muldoon
  2009-03-27 17:34 ` Tom Tromey
  2009-03-27 17:43 ` Pedro Alves
  0 siblings, 2 replies; 14+ messages in thread
From: Phil Muldoon @ 2009-03-27 17:05 UTC (permalink / raw)
  To: Project Archer

[-- Attachment #1: Type: text/plain, Size: 832 bytes --]

The bug is detailed here: 
http://sourceware.org/bugzilla/show_bug.cgi?id=10008

In summary, given this class:

class Y : public std::tr1::unordered_map<int, char *>
{
public:
  Y()
  {
  }
};

Any Python pretty-printers that have been written and registered to 
print std::tr1::unordered_map will not work on Y. But there is no 
reason, given the lack of a more specialized printer for Y, why the 
printer for unordered_map should not print the parts of Y it can 
accurately print. This patch attempts to find a base class printer if a 
specialized printer does not exist for the class in question.

Built and tested on x8664, with no regressions.

Phil

2009-03-27  Phil Muldoon  <pmuldoon@redhat.com>

       * cp-valprint.c (cp_print_value_fields): Attempt to run
       apply_val_pretty_print on the baseclass of a class.






[-- Attachment #2: derived_class.patch --]
[-- Type: text/x-patch, Size: 1376 bytes --]

diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c
index a96a81a..efc13e5 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -36,6 +36,7 @@
 #include "valprint.h"
 #include "cp-support.h"
 #include "language.h"
+#include "python/python.h"
 
 /* Controls printing of vtbl's */
 static void
@@ -155,16 +156,33 @@ cp_print_value_fields (struct type *type, struct type *real_type,
   int i, len, n_baseclasses;
   char *last_dont_print = obstack_next_free (&dont_print_statmem_obstack);
   int fields_seen = 0;
+  int result = 0;
+  struct type *baseclass;
 
   CHECK_TYPEDEF (type);
 
-  fprintf_filtered (stream, "{");
   len = TYPE_NFIELDS (type);
   n_baseclasses = TYPE_N_BASECLASSES (type);
 
+  /* Attempt to run the Python pretty-printers on the base class of
+  the derived class. */
+  if (!options->raw)
+    if (n_baseclasses > 0)
+      {  
+	
+	baseclass = check_typedef (TYPE_BASECLASS (type,0));
+	result = apply_val_pretty_printer (baseclass, valaddr, offset,
+					   address, stream, recurse, options,
+					   current_language);
+
+	if (result)
+	  return;
+      }
+
   /* First, print out baseclasses such that we don't print
      duplicates of virtual baseclasses.  */
 
+  fprintf_filtered (stream, "{");
   if (n_baseclasses > 0)
     cp_print_value (type, real_type, valaddr, offset, address, stream,
 		    recurse + 1, options, dont_print_vb);

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:05 [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class Phil Muldoon
@ 2009-03-27 17:34 ` Tom Tromey
  2009-03-27 17:43   ` Phil Muldoon
  2009-03-27 17:46   ` Paul Pluzhnikov
  2009-03-27 17:43 ` Pedro Alves
  1 sibling, 2 replies; 14+ messages in thread
From: Tom Tromey @ 2009-03-27 17:34 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Project Archer

>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:

Looking pretty good :)

Phil> +  /* Attempt to run the Python pretty-printers on the base class of
Phil> +  the derived class. */

The second line here needs more indentation.
"the" should line up with "Attempt".
Also you need an extra space after the period.

Silly nit-picking... :)

Phil> +  if (!options->raw)
Phil> +    if (n_baseclasses > 0)
Phil> +      {  
Phil> +	

Declare baseclass and result here, not at the top of the function.

Phil>    /* First, print out baseclasses such that we don't print
Phil>       duplicates of virtual baseclasses.  */
 
Does this logic continue to work properly if one of the virtual
baseclasses has a pretty-printer?

Please write a couple test cases for this functionality.

thanks,
Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:34 ` Tom Tromey
@ 2009-03-27 17:43   ` Phil Muldoon
  2009-03-27 17:47     ` Tom Tromey
  2009-03-27 17:46   ` Paul Pluzhnikov
  1 sibling, 1 reply; 14+ messages in thread
From: Phil Muldoon @ 2009-03-27 17:43 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Project Archer

Tom Tromey wrote:
> Looking pretty good :)
>
> Phil> +  /* Attempt to run the Python pretty-printers on the base class of
> Phil> +  the derived class. */
>
> The second line here needs more indentation.
> "the" should line up with "Attempt".
> Also you need an extra space after the period.
>
> Silly nit-picking... :)
>   


Thanks.


> Phil> +  if (!options->raw)
> Phil> +    if (n_baseclasses > 0)
> Phil> +      {  
> Phil> +	
>
> Declare baseclass and result here, not at the top of the function.
>   


You know I just moved it from here, I guess I'll move it back ;)


> Phil>    /* First, print out baseclasses such that we don't print
> Phil>       duplicates of virtual baseclasses.  */
>  
> Does this logic continue to work properly if one of the virtual
> baseclasses has a pretty-printer?
>   


It works in so much as this is a "do or continue with the old logic"; 
the existing Python pretty-printers would handle these if they were 
called, no?

(I might misunderstand your question)

But good point it needs a test ...


> Please write a couple test cases for this functionality.
>   


Yeah this is not a full patch (though looking at it, it does look like 
one). It's mainly a request for comments and a methodology sanity check 
;) I was thinking of a documentation patch in the narrative regarding 
printer selection too. But is this just going to be superfluous to the 
reader?

Regards

Phil

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:05 [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class Phil Muldoon
  2009-03-27 17:34 ` Tom Tromey
@ 2009-03-27 17:43 ` Pedro Alves
  2009-03-27 17:50   ` Tom Tromey
  1 sibling, 1 reply; 14+ messages in thread
From: Pedro Alves @ 2009-03-27 17:43 UTC (permalink / raw)
  To: archer; +Cc: Phil Muldoon

On Friday 27 March 2009 17:04:48, Phil Muldoon wrote:
> The bug is detailed here: 
> http://sourceware.org/bugzilla/show_bug.cgi?id=10008
> 
> In summary, given this class:
> 
> class Y : public std::tr1::unordered_map<int, char *>
> {
> public:
>   Y()
>   {
>   }
> };
> 
> Any Python pretty-printers that have been written and registered to 
> print std::tr1::unordered_map will not work on Y. But there is no 
> reason, given the lack of a more specialized printer for Y, why the 
> printer for unordered_map should not print the parts of Y it can 
> accurately print. This patch attempts to find a base class printer if a 
> specialized printer does not exist for the class in question.

I don't know a thing about python pretty-printing, so excuse any
silly questions, but, anyway...

Does this do sensible things if class Y has some
fields that mask the Base class's ones, when you only have a
pretty printer for Base?  Say:

class Base
{
public:
   int x;
};

class Y : public Base
{
public:
   int x;
};

What about private inheritance, sometimes used as an implementation
detail, but not representing an is-a relationship?

class Y : private Base
{
public:
   Y ();

   // My API that has nothing to do with Base.
   // my own data members
};

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no  Python pretty-printer for a derived class.
  2009-03-27 17:34 ` Tom Tromey
  2009-03-27 17:43   ` Phil Muldoon
@ 2009-03-27 17:46   ` Paul Pluzhnikov
  2009-03-27 18:00     ` Tom Tromey
  2009-03-27 18:28     ` Phil Muldoon
  1 sibling, 2 replies; 14+ messages in thread
From: Paul Pluzhnikov @ 2009-03-27 17:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Phil Muldoon, Project Archer

On Fri, Mar 27, 2009 at 10:34 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:
>
> Looking pretty good :)
>
> Phil> +  /* Attempt to run the Python pretty-printers on the base class of
> Phil> +  the derived class. */

I can't tell whether the patch would work for 'class X: public Y ...'

Also, here is an earlier thread on the same subject:
http://sourceware.org/ml/archer/2008-q4/msg00503.html


-- 
Paul Pluzhnikov

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:43   ` Phil Muldoon
@ 2009-03-27 17:47     ` Tom Tromey
  0 siblings, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2009-03-27 17:47 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: Project Archer

>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:

Phil> It works in so much as this is a "do or continue with the old logic";
Phil> the existing Python pretty-printers would handle these if they were
Phil> called, no?

My understanding of the current code is that if you have a repeated
virtual base class, it will only be printed once.

So, the test case here would be to have a pretty-printer for the
virtual base -- then, make sure that it is only invoked a single time.

Phil> I was thinking of a documentation patch in the narrative
Phil> regarding printer selection too. But is this just going to be
Phil> superfluous to the reader?

My first reaction is that we don't need a documentation update for
this.  It is just a simple extension of the generic logic to a
different case of printing -- this change is a technical one, related
to the implementation, not really a different use.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:43 ` Pedro Alves
@ 2009-03-27 17:50   ` Tom Tromey
  2009-03-27 18:05     ` Phil Muldoon
  2009-03-27 18:05     ` Pedro Alves
  0 siblings, 2 replies; 14+ messages in thread
From: Tom Tromey @ 2009-03-27 17:50 UTC (permalink / raw)
  To: Pedro Alves; +Cc: archer, Phil Muldoon

>>>>> "Pedro" == Pedro Alves <alves.ped@gmail.com> writes:

Pedro> Does this do sensible things if class Y has some
Pedro> fields that mask the Base class's ones, when you only have a
Pedro> pretty printer for Base?

Yeah... it pretty-prints Base, then goes on to print the subclass
fields as usual (perhaps pretty-printing them as well).

Phil, could you post the before- and after- results of your example?
I think that would clear things up.

Pedro> What about private inheritance, sometimes used as an implementation
Pedro> detail, but not representing an is-a relationship?

This will also work; the code doesn't consider access flags.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no  Python pretty-printer for a derived class.
  2009-03-27 17:46   ` Paul Pluzhnikov
@ 2009-03-27 18:00     ` Tom Tromey
  2009-03-27 18:28     ` Phil Muldoon
  1 sibling, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2009-03-27 18:00 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: Phil Muldoon, Project Archer

>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> I can't tell whether the patch would work for 'class X: public Y ...'

It will.

gdb today has some special code for printing C++ classes.  This code
first recurses into base classes, then prints the derived class' fields.

What Phil's patch does is hook into this to try to pretty-print a base
class.  So, it should apply generally.

Paul> Also, here is an earlier thread on the same subject:
Paul> http://sourceware.org/ml/archer/2008-q4/msg00503.html

Now that pretty-printers are not registered by type, I think the patch
in this thread won't work as-is.  A given printer can still be made
completely generic, though, if that is what you want; it just has to
look at the base classes itself.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:50   ` Tom Tromey
@ 2009-03-27 18:05     ` Phil Muldoon
  2009-03-27 18:05     ` Pedro Alves
  1 sibling, 0 replies; 14+ messages in thread
From: Phil Muldoon @ 2009-03-27 18:05 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, archer, Paul Pluzhnikov

[-- Attachment #1: Type: text/plain, Size: 1396 bytes --]

Tom Tromey wrote:
>>>>>> "Pedro" == Pedro Alves <alves.ped@gmail.com> writes:
>>>>>>             
>
> Pedro> Does this do sensible things if class Y has some
> Pedro> fields that mask the Base class's ones, when you only have a
> Pedro> pretty printer for Base?
>
> Yeah... it pretty-prints Base, then goes on to print the subclass
> fields as usual (perhaps pretty-printing them as well).
>
> Phil, could you post the before- and after- results of your example?
> I think that would clear things up.
>   
Here (attached) is a file I was using today to test some scenarios. They 
do not directly address Pedro's questions (I think your explanation 
does). But they do address on of Paul's.

[pmuldoon@localhost gdb]$ ./gdb ~/derived

(pg-gdb) b 45
Reading in symbols for /home/pmuldoon/derived.cpp...
Breakpoint 1 at 0x400b40: file /home/pmuldoon/derived.cpp, line 45.
(pg-gdb) python import gdb.libstdcxx.v6.printers
(pg-gdb) r

Breakpoint 1, main () at /home/pmuldoon/derived.cpp:45
45 return 0;

(pg-gdb) info locals

map = std::map with 1 elements = {
[0x40363d "one"] = 1
}
uomap = std::tr1::unordered_map with 1 elements = {
[21] = 0x403645 "twenty one"
}
nest = {
<Z> = std::map with 1 elements = {
[0x403650 "twenty-two"] = 22
},
members of X:
map = std::tr1::unordered_map with 1 elements = {
[23] = 0x403638 "test"
},
i = 0
}
base = std::map with 1 elements = {
[0x403641 "two"] = 2
}


[-- Attachment #2: derived.cpp --]
[-- Type: text/x-c++src, Size: 489 bytes --]

#include <map>
#include <tr1/unordered_map>

class Y : public std::tr1::unordered_map<int, char *>
{
public:
  Y()
  {
  }
};

class Z : public std::map<const char *, int>
{
public:
  Z()
  {
  }
};


class X : public Z
{
public:

  Y map;
  int i;
  X ()
  {
    i=0;
    map[23] = "test";
  }
};

int main()
{
  Z map;
  Y uomap;
  X nest;    
  std::map<const char *, int> base;

  map["one"] = 1;
  base["two"] = 2;
  uomap[21] = "twenty one";
  nest["twenty-two"] = 22;
  return 0;
}

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:50   ` Tom Tromey
  2009-03-27 18:05     ` Phil Muldoon
@ 2009-03-27 18:05     ` Pedro Alves
  2009-03-27 18:36       ` Tom Tromey
  2009-03-27 19:08       ` Phil Muldoon
  1 sibling, 2 replies; 14+ messages in thread
From: Pedro Alves @ 2009-03-27 18:05 UTC (permalink / raw)
  To: archer, Tom Tromey; +Cc: Phil Muldoon

On Friday 27 March 2009 17:50:39, Tom Tromey wrote:
> Pedro> Does this do sensible things if class Y has some
> Pedro> fields that mask the Base class's ones, when you only have a
> Pedro> pretty printer for Base?
> 
> Yeah... it pretty-prints Base, then goes on to print the subclass
> fields as usual (perhaps pretty-printing them as well).

Okay, I was concerned if the pretty printer for Base would
access Y::x instead of Base::x.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 17:46   ` Paul Pluzhnikov
  2009-03-27 18:00     ` Tom Tromey
@ 2009-03-27 18:28     ` Phil Muldoon
  1 sibling, 0 replies; 14+ messages in thread
From: Phil Muldoon @ 2009-03-27 18:28 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: Tom Tromey, Project Archer

Paul Pluzhnikov wrote:
> On Fri, Mar 27, 2009 at 10:34 AM, Tom Tromey <tromey@redhat.com> wrote:
>   
>>>>>>> "Phil" == Phil Muldoon <pmuldoon@redhat.com> writes:
>>>>>>>               
>> Looking pretty good :)
>>
>> Phil> +  /* Attempt to run the Python pretty-printers on the base class of
>> Phil> +  the derived class. */
>>     
>
> I can't tell whether the patch would work for 'class X: public Y ...'
>   

It will. I really should have appended my working examples, but decided 
not too. I know better next time ;)

> Also, here is an earlier thread on the same subject:
> http://sourceware.org/ml/archer/2008-q4/msg00503.html
>
>   

I've nothing really to add to what Tom already mentioned. But as  
printer selection criteria for a value is now pretty much deferred to 
the printers themselves, the circumstances discussed in that thread 
changed. In this case it was just easier to add a last-chance effort in 
the c++ class GDB printer itself.  You can always write a base-class 
test which is more specialized in the Python printer  by mining the 
fields for base classes.

Regards

Phil

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 18:05     ` Pedro Alves
@ 2009-03-27 18:36       ` Tom Tromey
  2009-03-27 19:08       ` Phil Muldoon
  1 sibling, 0 replies; 14+ messages in thread
From: Tom Tromey @ 2009-03-27 18:36 UTC (permalink / raw)
  To: Pedro Alves; +Cc: archer, Phil Muldoon

>>>>> "Pedro" == Pedro Alves <pedro@codesourcery.com> writes:

Pedro> Okay, I was concerned if the pretty printer for Base would
Pedro> access Y::x instead of Base::x.

Ah, I see.  Well, we ought to have a test case to make sure :)

But I think it won't, since the printer will see an object of type
Base.

Tom

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 18:05     ` Pedro Alves
  2009-03-27 18:36       ` Tom Tromey
@ 2009-03-27 19:08       ` Phil Muldoon
  2009-03-27 19:25         ` Pedro Alves
  1 sibling, 1 reply; 14+ messages in thread
From: Phil Muldoon @ 2009-03-27 19:08 UTC (permalink / raw)
  To: Pedro Alves; +Cc: archer, Tom Tromey

Pedro Alves wrote:
> On Friday 27 March 2009 17:50:39, Tom Tromey wrote:
>   
>> Pedro> Does this do sensible things if class Y has some
>> Pedro> fields that mask the Base class's ones, when you only have a
>> Pedro> pretty printer for Base?
>>
>> Yeah... it pretty-prints Base, then goes on to print the subclass
>> fields as usual (perhaps pretty-printing them as well).
>>     
>
> Okay, I was concerned if the pretty printer for Base would
> access Y::x instead of Base::x
It is a printer for Base, but that does not mean it will print out the 
Base values. Take this example:

class Base : public std::tr1::unordered_map<int, char *>
{
public:
  std::tr1::unordered_map<int, char *> map;

  Base ()
  {
    map[1]="Base";
  }
};

class Derived : public Base
{
public:
  std::tr1::unordered_map<int, char *> map;

  Derived ()
  {
    map[1]="Derived";
  }
};

If you instantiate Derived and print it with the patch, you will get:

(pg-gdb) python import gdb.libstdcxx.v6.printers
(pg-gdb) p derived
$2 = {
  <Base> = std::tr1::unordered_map with 0 elements,
  members of Derived:
  map = std::tr1::unordered_map with 1 elements = {
    [1] = 0x403952 "Derived"
  }
}


Regards

Phil
Phil

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class.
  2009-03-27 19:08       ` Phil Muldoon
@ 2009-03-27 19:25         ` Pedro Alves
  0 siblings, 0 replies; 14+ messages in thread
From: Pedro Alves @ 2009-03-27 19:25 UTC (permalink / raw)
  To: Phil Muldoon; +Cc: archer, Tom Tromey

On Friday 27 March 2009 19:06:45, Phil Muldoon wrote:
> Pedro Alves wrote:
> > On Friday 27 March 2009 17:50:39, Tom Tromey wrote:
> >   
> >> Pedro> Does this do sensible things if class Y has some
> >> Pedro> fields that mask the Base class's ones, when you only have a
> >> Pedro> pretty printer for Base?
> >>
> >> Yeah... it pretty-prints Base, then goes on to print the subclass
> >> fields as usual (perhaps pretty-printing them as well).
> >>     
> >
> > Okay, I was concerned if the pretty printer for Base would
> > access Y::x instead of Base::x
> It is a printer for Base, but that does not mean it will print out the 
> Base values. Take this example:
> 

<snip example>

I'm not sure if you're talking about what I'm talking.  Here's a
simple example without stl mumbo jumbo, but please don't get caught
up with the actual classes being chosen for the example:

class LibVector
{
private:
	char *data;
        int len;  /* length of data buffer in bytes */
};

class MyApplesVector : public LibVector
{
private:
        int len;  /* length of each apple in the vector in fruitlenght
                     units.  They all must have the same length.  */
}

I was asking if the pretty printer for LibVector, when
applied to MyApplesVector, wouldn't mistake MyApplesVector::len
for LibVector::len, which could cause bad things to happen
when accessing data, or printing the length of the generic
LibVector.

-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2009-03-27 19:25 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-03-27 17:05 [python][rfc] Attempt to print the base class if a there is no Python pretty-printer for a derived class Phil Muldoon
2009-03-27 17:34 ` Tom Tromey
2009-03-27 17:43   ` Phil Muldoon
2009-03-27 17:47     ` Tom Tromey
2009-03-27 17:46   ` Paul Pluzhnikov
2009-03-27 18:00     ` Tom Tromey
2009-03-27 18:28     ` Phil Muldoon
2009-03-27 17:43 ` Pedro Alves
2009-03-27 17:50   ` Tom Tromey
2009-03-27 18:05     ` Phil Muldoon
2009-03-27 18:05     ` Pedro Alves
2009-03-27 18:36       ` Tom Tromey
2009-03-27 19:08       ` Phil Muldoon
2009-03-27 19:25         ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).