This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] [patch] 'p->x' vs. 'p.x' and 'print object on'


On Mon, Jul 21, 2008 at 5:52 PM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:
>
> Paul> Long time GDB users are somewhat used to 'p->x' and 'p.x' meaning
> Paul> the same thing. But, as test case below demonstrates, they don't
> Paul> mean the same thing when 'set print object on' is in effect.
>
> FWIW, I like this.  I was always confused when I printed an object and
> saw a field, but was then unable to print the field directly.
>
> However, I recall bringing this up once, in the distant past.  Someone
> pointed out a difficulty with this approach: there might be one field
> 'x' that would be used with the declared type, but another field, also
> named 'x', that would be used with the actual type.  So, this could
> potentially be confusing (albeit in an already confusing situation).

Thanks for bringing that up. I've modified the test case to have
a field 'y' in both the base and derived classes (attached at the
end), and the current situation is (IMHO) just as confusing before
the patch as it is after :(

Before patch (current behavior):

  Breakpoint 1, fn (f=0x7fffffffe690) at print-obj.cc:16
  16        return f->y;
  (gdb) p *f
  $3 = {_vptr.Foo = 0x400570, x = 1, y = 2}
  (gdb) p f->y
  $4 = 2
  (gdb) p f.y
  $5 = 2
  (gdb) set print object on
  (gdb) p *f
  $6 = (Bar) {<Foo> = {_vptr.Foo = 0x400570, x = 1, y = 2}, y = 20, z = 30}
  (gdb) p f->y
  $7 = 20
  (gdb) p f.y
  $8 = 2

// f.y and f->y do not mean the same thing :(

  (gdb) finish
  0x0000000000400305 in main () at print-obj.cc:22
  22        return fn(&b);
  Value returned is $9 = 2

// Confusing: 'print f->y' says '20'; but 'finish' says '2'

After:

  Breakpoint 1, fn (f=0x7fffffffe660) at print-obj.cc:16
  16        return f->y;
  (gdb) p *f
  $1 = {_vptr.Foo = 0x400570, x = 1, y = 2}
  (gdb) p f->y
  $2 = 2
  (gdb) p f.y
  $3 = 2

// without "print object on" patch makes no difference

  (gdb) set print object on
  (gdb) p *f
  $4 = (Bar) {<Foo> = {_vptr.Foo = 0x400570, x = 1, y = 2}, y = 20, z = 30}
  (gdb) p f->y
  $5 = 20
  (gdb) p f.y
  $6 = 20

// with "print object on" GDB is consistently treating f.y and f->y
// as the same expression.

  (gdb) finish
  0x0000000000400305 in main () at print-obj.cc:22
  22        return fn(&b);
  Value returned is $7 = 2

// Still confusing ...

> Maybe this can be documented or otherwise resolved.

Some other alternatives (hand-simulated):

A) Print both:

  (gbd) p f->y
  $14 = 2      (f->Foo::y)
  $15 = 20     (f->Bar::y)

  (gbd) p f.y
  $16 = 2      (f->Foo::y)
  $17 = 20     (f->Bar::y)

B) Print warning:

  (gdb) p f.y
  Warning: more than one field 'y' resulted from lookup in dynamic
  type of 'f'; set 'print object off' to see the other 'y'.
  $18 = 20

C) Do what the language does: lookup field 'x' in the static type,
   and only try dynamic type if the first lookup failed:

  (gdb) p f.y
  $19 = 2
  (gdb) p f->y
  $20 = 2

// The other field still accessible:
  (gdb) p f->Bar::y
  $21 = 20

// Lookup in Foo fails; try Bar
  (gdb) p f->z
  $22 = 30


I think "C" is the least confusing alternative.
It may actually be good to do "C" independent of the 'print object'
setting.

> Also, IMO this patch could use an associated test case.

Yes, I just wanted to see what people think about this before
creating the test case.

Thanks again.
-- 
Paul Pluzhnikov

// test case
struct Foo {
  int x, y;
  Foo() : x(1), y(2) { }
  virtual ~Foo() { }
  virtual int method() = 0;
};

struct Bar : public Foo {
  Bar() : y(20), z(30) { }
  int method() { return 42; }
  int y, z;
};

int fn(Foo *f)
{
  return f->y;
}

int main()
{
  Bar b;
  return fn(&b);
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]