public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* RTTI working for G++
@ 2000-03-13 16:53 Daniel Berlin
  2000-03-15 13:20 ` Jimmy Guo
  2000-04-01  0:00 ` Daniel Berlin
  0 siblings, 2 replies; 10+ messages in thread
From: Daniel Berlin @ 2000-03-13 16:53 UTC (permalink / raw)
  To: gdb

Okay, i have RTTI working for g++.
Well, all except for multiple inheritance.

Scratch that last part, i just made it offset properly if you have >1
baseclass, so al is good.

If i could have one or two volunteers to make sure it's not just my setup,
and that all is well, before i post the patches asking for comments, i'd
appreciate it.
In any case, let me know what you guys think of it so far.
If you look at the output, you'll notice that while for printing, it will
print the object as if it was it's derived type, when it comes to
accessing members/methods, just like in C++, you can't access the members,
unless you specifically cast it to that derived type.

 For those wondering what the patch will do, check this out:

The inheritance on these classes in the example looks like this

fred is a base
dan and bob both inherit directly from fred.
george is another base.
george2 inherits from george and bob (public george, public bob)

I'll rename them so they make more sense as i work up testcases.

But anyway, here's some output:

GNU gdb 20000204
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsdelf4.0".
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
No symbol table is loaded.  Use the "file" command.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) b main
Breakpoint 1 at 0x8048918: file a.cc, line 29.
(gdb) set print object on
(gdb) set print pretty on
(gdb) set print vtbl on
(gdb) set print array on
(gdb) r
Starting program: /usr/local/gdb/src/gdb/a.out 

Breakpoint 1, 0x8048918 in main () at a.cc:29

29	{
(gdb) n
31		dan=new daniel();
(gdb) n
32		cout <<typeid(*dan).name()<<endl;
(gdb) p dan
$1 = (daniel *) 0x8051030
(gdb) p dan[0]
$2 = (daniel) {
  <fred> = {
    a = 0, 
    _vptr$ = 0x804f390
  }, 
  members of daniel: 
  b = 0
}
(gdb) ptype dan
type = class fred {
  public:
    int a;

    fred & operator=(fred const &);
    fred(fred const &);
    fred(void);
    virtual int ab(void);
} *
(gdb) p dan[0]->b
There is no member or method named b.
(gdb) n
6daniel
33		dan=new bob();
(gdb) 
34		dan=new george2();
(gdb) p dan
$3 = (bob *) 0x8051040
(gdb) p dan[0]
$4 = (bob) {
  <fred> = {
    a = 0, 
    _vptr$ = 0x804f378
  }, 
  members of bob: 
  c = 0
}
(gdb) p dan[0].c
There is no member or method named c.
(gdb) n
35		dan->a=55;
(gdb) p dan[0]
$5 = (george2 [incomplete object]) {
  <george> = {
    d = 0
  }, 
  <bob> = {
    <fred> = {
      a = 0, 
      _vptr$ = 0x804f360
    }, 
    members of bob: 
    c = 0
  }, 
  members of george2: 
  e = 0
}
(gdb) l
30		fred *dan;
31		dan=new daniel();
32		cout <<typeid(*dan).name()<<endl;
33		dan=new bob();
34		dan=new george2();
35		dan->a=55;
36		cout <<typeid(*dan).name()<<endl;
37	}
38	
(gdb) n
36		cout <<typeid(*dan).name()<<endl;
(gdb) p dan
$7 = (suspicious *) 0x8050064
(gdb) p dan[0]
$8 = (george2 [incomplete object]) {
  <george> = {
    d = 0
  }, 
  <bob> = {
    <fred> = {
      a = 55, 
      _vptr$ = 0x804f360
    }, 
    members of bob: 
    c = 0
  }, 
  members of george2: 
  e = 0
}
(gdb) c
Continuing.
7george2

Program exited normally.
(gdb) q

Script done on Mon Mar 13 19:34:51 2000

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

* Re: RTTI working for G++
  2000-03-13 16:53 RTTI working for G++ Daniel Berlin
@ 2000-03-15 13:20 ` Jimmy Guo
  2000-03-15 20:33   ` Daniel Berlin+mail.gdb
  2000-04-01  0:00   ` Jimmy Guo
  2000-04-01  0:00 ` Daniel Berlin
  1 sibling, 2 replies; 10+ messages in thread
From: Jimmy Guo @ 2000-03-15 13:20 UTC (permalink / raw)
  To: Daniel Berlin; +Cc: gdb

Daniel,

I recently looked into rtti print support and fixed several bugs in that
area.  Also I've created a test case under gdb.hp/gdb.aCC/.  Looks like
what I changed might work with G++ as well now that you're adding
support to it.  The fix is against HP WDB source, which is based on
sourceware's as of 1/10/00, so I'm not ready to submit against
sourceware's tree yet.  However, one of the fixes was that when print
object is on, and one wants to print member / methods of the derived
type, you can now do so.  Besides, there're some fixes to handle pointer
to a derived type and explicit casting of a pointer to a base to a
derived type.  I feel that these fixes will complement yours.  If
possible I want to send the diffs of the fixes to you to see if that
would make it into your patch.  Also I can look at your patches as well.

- Jimmy Guo, guo@cup.hp.com


On Mon, 13 Mar 2000, Daniel Berlin wrote:

>Okay, i have RTTI working for g++.
>Well, all except for multiple inheritance.
>
>Scratch that last part, i just made it offset properly if you have >1
>baseclass, so al is good.
>
>If i could have one or two volunteers to make sure it's not just my setup,
>and that all is well, before i post the patches asking for comments, i'd
>appreciate it.
>In any case, let me know what you guys think of it so far.
>If you look at the output, you'll notice that while for printing, it will
>print the object as if it was it's derived type, when it comes to
>accessing members/methods, just like in C++, you can't access the members,
>unless you specifically cast it to that derived type.
>
> For those wondering what the patch will do, check this out:
>
>The inheritance on these classes in the example looks like this
>
>fred is a base
>dan and bob both inherit directly from fred.
>george is another base.
>george2 inherits from george and bob (public george, public bob)
>
>I'll rename them so they make more sense as i work up testcases.
>
>But anyway, here's some output:
>
>GNU gdb 20000204
>Copyright 1998 Free Software Foundation, Inc.
>GDB is free software, covered by the GNU General Public License, and you are
>welcome to change it and/or distribute copies of it under certain conditions.
>Type "show copying" to see the conditions.
>There is absolutely no warranty for GDB.  Type "show warranty" for details.
>This GDB was configured as "i386-unknown-freebsdelf4.0".
>Setting up the environment for debugging gdb.
>.gdbinit:5: Error in sourced command file:
>No symbol table is loaded.  Use the "file" command.
>(gdb) file a.out
>Reading symbols from a.out...done.
>(gdb) b main
>Breakpoint 1 at 0x8048918: file a.cc, line 29.
>(gdb) set print object on
>(gdb) set print pretty on
>(gdb) set print vtbl on
>(gdb) set print array on
>(gdb) r
>Starting program: /usr/local/gdb/src/gdb/a.out 
>
>Breakpoint 1, 0x8048918 in main () at a.cc:29
>
>29	{
>(gdb) n
>31		dan=new daniel();
>(gdb) n
>32		cout <<typeid(*dan).name()<<endl;
>(gdb) p dan
>$1 = (daniel *) 0x8051030
>(gdb) p dan[0]
>$2 = (daniel) {
>  <fred> = {
>    a = 0, 
>    _vptr$ = 0x804f390
>  }, 
>  members of daniel: 
>  b = 0
>}
>(gdb) ptype dan
>type = class fred {
>  public:
>    int a;
>
>    fred & operator=(fred const &);
>    fred(fred const &);
>    fred(void);
>    virtual int ab(void);
>} *
>(gdb) p dan[0]->b
>There is no member or method named b.
>(gdb) n
>6daniel
>33		dan=new bob();
>(gdb) 
>34		dan=new george2();
>(gdb) p dan
>$3 = (bob *) 0x8051040
>(gdb) p dan[0]
>$4 = (bob) {
>  <fred> = {
>    a = 0, 
>    _vptr$ = 0x804f378
>  }, 
>  members of bob: 
>  c = 0
>}
>(gdb) p dan[0].c
>There is no member or method named c.
>(gdb) n
>35		dan->a=55;
>(gdb) p dan[0]
>$5 = (george2 [incomplete object]) {
>  <george> = {
>    d = 0
>  }, 
>  <bob> = {
>    <fred> = {
>      a = 0, 
>      _vptr$ = 0x804f360
>    }, 
>    members of bob: 
>    c = 0
>  }, 
>  members of george2: 
>  e = 0
>}
>(gdb) l
>30		fred *dan;
>31		dan=new daniel();
>32		cout <<typeid(*dan).name()<<endl;
>33		dan=new bob();
>34		dan=new george2();
>35		dan->a=55;
>36		cout <<typeid(*dan).name()<<endl;
>37	}
>38	
>(gdb) n
>36		cout <<typeid(*dan).name()<<endl;
>(gdb) p dan
>$7 = (suspicious *) 0x8050064
>(gdb) p dan[0]
>$8 = (george2 [incomplete object]) {
>  <george> = {
>    d = 0
>  }, 
>  <bob> = {
>    <fred> = {
>      a = 55, 
>      _vptr$ = 0x804f360
>    }, 
>    members of bob: 
>    c = 0
>  }, 
>  members of george2: 
>  e = 0
>}
>(gdb) c
>Continuing.
>7george2
>
>Program exited normally.
>(gdb) q
>
>Script done on Mon Mar 13 19:34:51 2000

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

* Re: RTTI working for G++
  2000-03-15 13:20 ` Jimmy Guo
@ 2000-03-15 20:33   ` Daniel Berlin+mail.gdb
  2000-03-16 15:53     ` Jimmy Guo
  2000-04-01  0:00     ` Daniel Berlin+mail.gdb
  2000-04-01  0:00   ` Jimmy Guo
  1 sibling, 2 replies; 10+ messages in thread
From: Daniel Berlin+mail.gdb @ 2000-03-15 20:33 UTC (permalink / raw)
  To: Jimmy Guo; +Cc: Daniel Berlin, gdb

Jimmy Guo <guo@cup.hp.com> writes:

> Daniel,
> 
> I recently looked into rtti print support and fixed several bugs in that
> area. 

As have I.
>  Also I've created a test case under gdb.hp/gdb.aCC/.  Looks like
> what I changed might work with G++ as well now that you're adding
> support to it.  

Possibly, i have a feeling we fixed the same bugs.
> The fix is against HP WDB source, which is based on
> sourceware's as of 1/10/00, so I'm not ready to submit against
> sourceware's tree yet.  However, one of the fixes was that when print
> object is on, and one wants to print member / methods of the derived
> type, you can now do so. 

See, i didn't consider that a bug, i considered it a lacking
feature. It just wasn't doing the lookup it would need to do, and i've
been too busy to fix it.

> Besides, there're some fixes to handle pointer
> to a derived type and explicit casting of a pointer to a base to a
> derived type. 

This i ran up against. I also handled reference types (By pretending
they were pointers).

> I feel that these fixes will complement yours.  
Most likely you are correct.
I wasn't ready to go all out and make all the symbol readers fill in
the vtable stuff like it does for HP (it's on my list for sometime).
Seeing as how i would have had to do that, as well as differentiate
between HP aCC debug symbols and other forms of debug symbols, with
another flag, i decided for right now to just put the RTTI stuff for
G++ where it was already, the else block of all the "HAS_VTABLE" if
blocks.
I only actually added one more if, in value_rtti_type, right before
the HP specific stuff starts, that says
"if(TYPE_HAS_VTABLE(known_type)) { do hp stuff } else { do g++ stuff}"

That way, i didn't break any of your HP specific stuff.

Did you notice that it's not really fun to use value_nid (damn
flyspell keeps "correcting" the IND to nid, as if "nid" was really a word
either.) in value_rtti_type? value_nid will call the RTTI routine
during it's lazy evaluation, which gets you into a recursive nightmare
if you aren't careful.


> If
> possible I want to send the diffs of the fixes to you to see if that
> would make it into your patch.  Also I can look at your patches as
> well.

I'd be glad to incorporate your fixes into my patch, and i'd
appreciate it if you'd look at mine.
I'll post it to gdb-patches in a few days.

I'm a little confused about the semantics of using_enc/full/top in value_rtti_type.

It seems if i set full to 0, on multiple inheritance, it gets the name
right, but the offset wrong, so you have the right name, and the wrong
values.
If i set full to 1, it gets the name wrong ("suspicious *", which
means it couldn't look it up right), but the values right.
Example of what i mean (when i have bar multiple inheriting 

class foo
{
public:
int a;
};
class foo2
{
public:
int b;
};
class bar:public foo1, public foo2
{
public:
int c;
};

foo *foo1=new bar();

print foo1 (full==1 will give "suspicious *", full==0 will give "bar
*")
print *foo1 (full==1 will give the proper values, full==0 gets the
offset wrong, and thus, prints the wrong values)

Even more convoluted,
print foo1->a (with full==1) will access the wrong memory, even though it had it
right 2 seconds before when it printed the full object.
I know i'm setting top properly in all cases.
I have a feeling i'm not quite grasping the way it lays out in memory
yet.

--Dan

> 
> - Jimmy Guo, guo@cup.hp.com
> 
> On Mon, 13 Mar 2000, Daniel Berlin wrote:
> 
> >Okay, i have RTTI working for g++.
> >Well, all except for multiple inheritance.
> >
> >Scratch that last part, i just made it offset properly if you have >1
> >baseclass, so al is good.
> >
> >If i could have one or two volunteers to make sure it's not just my setup,
> >and that all is well, before i post the patches asking for comments, i'd
> >appreciate it.
> >In any case, let me know what you guys think of it so far.
> >If you look at the output, you'll notice that while for printing, it will
> >print the object as if it was it's derived type, when it comes to
> >accessing members/methods, just like in C++, you can't access the members,
> >unless you specifically cast it to that derived type.
> >
> > For those wondering what the patch will do, check this out:
> >
> >The inheritance on these classes in the example looks like this
> >
> >fred is a base
> >dan and bob both inherit directly from fred.
> >george is another base.
> >george2 inherits from george and bob (public george, public bob)
> >
> >I'll rename them so they make more sense as i work up testcases.
> >
> >But anyway, here's some output:
> >
> >GNU gdb 20000204
> >Copyright 1998 Free Software Foundation, Inc.
> >GDB is free software, covered by the GNU General Public License, and you are
> >welcome to change it and/or distribute copies of it under certain conditions.
> >Type "show copying" to see the conditions.
> >There is absolutely no warranty for GDB.  Type "show warranty" for details.
> >This GDB was configured as "i386-unknown-freebsdelf4.0".
> >Setting up the environment for debugging gdb.
> >.gdbinit:5: Error in sourced command file:
> >No symbol table is loaded.  Use the "file" command.
> >(gdb) file a.out
> >Reading symbols from a.out...done.
> >(gdb) b main
> >Breakpoint 1 at 0x8048918: file a.cc, line 29.
> >(gdb) set print object on
> >(gdb) set print pretty on
> >(gdb) set print vtbl on
> >(gdb) set print array on
> >(gdb) r
> >Starting program: /usr/local/gdb/src/gdb/a.out 
> >
> >Breakpoint 1, 0x8048918 in main () at a.cc:29
> >
> >29	{
> >(gdb) n
> >31		dan=new daniel();
> >(gdb) n
> >32		cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$1 = (daniel *) 0x8051030
> >(gdb) p dan[0]
> >$2 = (daniel) {
> >  <fred> = {
> >    a = 0, 
> >    _vptr$ = 0x804f390
> >  }, 
> >  members of daniel: 
> >  b = 0
> >}
> >(gdb) ptype dan
> >type = class fred {
> >  public:
> >    int a;
> >
> >    fred & operator=(fred const &);
> >    fred(fred const &);
> >    fred(void);
> >    virtual int ab(void);
> >} *
> >(gdb) p dan[0]->b
> >There is no member or method named b.
> >(gdb) n
> >6daniel
> >33		dan=new bob();
> >(gdb) 
> >34		dan=new george2();
> >(gdb) p dan
> >$3 = (bob *) 0x8051040
> >(gdb) p dan[0]
> >$4 = (bob) {
> >  <fred> = {
> >    a = 0, 
> >    _vptr$ = 0x804f378
> >  }, 
> >  members of bob: 
> >  c = 0
> >}
> >(gdb) p dan[0].c
> >There is no member or method named c.
> >(gdb) n
> >35		dan->a=55;
> >(gdb) p dan[0]
> >$5 = (george2 [incomplete object]) {
> >  <george> = {
> >    d = 0
> >  }, 
> >  <bob> = {
> >    <fred> = {
> >      a = 0, 
> >      _vptr$ = 0x804f360
> >    }, 
> >    members of bob: 
> >    c = 0
> >  }, 
> >  members of george2: 
> >  e = 0
> >}
> >(gdb) l
> >30		fred *dan;
> >31		dan=new daniel();
> >32		cout <<typeid(*dan).name()<<endl;
> >33		dan=new bob();
> >34		dan=new george2();
> >35		dan->a=55;
> >36		cout <<typeid(*dan).name()<<endl;
> >37	}
> >38	
> >(gdb) n
> >36		cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$7 = (suspicious *) 0x8050064
> >(gdb) p dan[0]
> >$8 = (george2 [incomplete object]) {
> >  <george> = {
> >    d = 0
> >  }, 
> >  <bob> = {
> >    <fred> = {
> >      a = 55, 
> >      _vptr$ = 0x804f360
> >    }, 
> >    members of bob: 
> >    c = 0
> >  }, 
> >  members of george2: 
> >  e = 0
> >}
> >(gdb) c
> >Continuing.
> >7george2
> >
> >Program exited normally.
> >(gdb) q
> >
> >Script done on Mon Mar 13 19:34:51 2000

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

* Re: RTTI working for G++
  2000-03-15 20:33   ` Daniel Berlin+mail.gdb
@ 2000-03-16 15:53     ` Jimmy Guo
  2000-03-16 16:29       ` Jimmy Guo
  2000-04-01  0:00       ` Jimmy Guo
  2000-04-01  0:00     ` Daniel Berlin+mail.gdb
  1 sibling, 2 replies; 10+ messages in thread
From: Jimmy Guo @ 2000-03-16 15:53 UTC (permalink / raw)
  To: Daniel Berlin+mail.gdb; +Cc: gdb

>> ... However, one of the fixes was that when print
>> object is on, and one wants to print member / methods of the derived
>> type, you can now do so. 
>
>See, i didn't consider that a bug, i considered it a lacking
>feature. It just wasn't doing the lookup it would need to do, and i've
>been too busy to fix it.

If 'print foo' says it's a pointer to something, and 'print foo->a' says
'There is no member or method named a.', it's very confusing to the
user.  When print object is on, this could happen.  I'd be more willing
to say it's a bug, since the error message contradicts with what print
says and just misleads user ('which one should I believe from this
debugger?').

The fix is in eval.c (evaluate_subexp_standard): it needs to know if
objectprint is set, and if so, return the pointer to the rtti type when
dealing with STUCTOP_PTR (if target type code is TYPE_CODE_CLASS).

>> Besides, there're some fixes to handle pointer
>> to a derived type and explicit casting of a pointer to a base to a
>> derived type. 
>
>This i ran up against. I also handled reference types (By pretending
>they were pointers).

Actually the example you gave at the end of this email looks like
something I fixed, in the casting code.  I'm not familiar with
value_rtti_type and don't quite understand what you were dealing with --
full, etc. are all reset to initial values upon entry into
value_rtti_type ().

>Did you notice that it's not really fun to use value_nid (damn
>flyspell keeps "correcting" the IND to nid, as if "nid" was really a word
>either.) in value_rtti_type? value_nid will call the RTTI routine
>during it's lazy evaluation, which gets you into a recursive nightmare
>if you aren't careful.

I wasn't adventuring into that area since I'm looking at the higher
layer of the proper handling of casting, printing, and expression
evaluation.

>I'd be glad to incorporate your fixes into my patch, and i'd
>appreciate it if you'd look at mine.
>I'll post it to gdb-patches in a few days.

Mine is enclosed in this email.

>I'm a little confused about the semantics of using_enc/full/top in value_rtti_type.
>
>It seems if i set full to 0, on multiple inheritance, it gets the name
>right, but the offset wrong, so you have the right name, and the wrong
>values.
>If i set full to 1, it gets the name wrong ("suspicious *", which
>means it couldn't look it up right), but the values right.

See if my changes to c-valprint.c and valops.c solved your problem.  I
think at least part of the problem is that the pointer value was _not_
adjusted when you change the type of the thing to a rtti type, which is
fixed in these two files.  c-valprint.c deals with printing the pointer
value itself; valops.c deals with printing a member of the pointer value.

Patch follows (the change to typeprint.c probably conflicts with your
version, and I like the output you provided).

- Jimmy Guo, guo@cup.hp.com

Thu Mar 16 15:49:56 2000	Jimmy guo	<guo@cup.hp.com>

	* c-valprint.c (c_value_print): adjust pointer value when
	objectprint is set and pointer type is changed to point to the
	rtti type.

	* eval.c (evaluate_subexp_standard): for OP_VAR_VALUE, always
	return full value object; for STRUCTOP_PTR, use pointer to
	rtti type to get member / method if objectprint is set and
	target type of pointer is class.

	* typeprint.c (whatis_exp): if objectprint is set and exp is of
	pointer / reference type to a class object, look up and print
	the pointer / reference to rtti type.

	* valops.c (value_cast): when casting a pointer / reference type
	of a class object to pointer / refer to its rtti type, adjust
	the new pointer value accordingly.


Index: c-valprint.c
/usr/local/bin/diff -c -w -L c-valprint.c c-valprint.c@@/main/cygnus/7 c-valprint.c
*** c-valprint.c
--- c-valprint.c	Thu Mar 16 10:21:16 2000
***************
*** 497,502 ****
--- 497,505 ----
                    /* create a reference type referencing the real type */
                    type = lookup_reference_type (real_type);
                  }
+ 	      /* JYG: Need to adjust pointer value. */
+               val->aligner.contents[0] -= top;
+ 
                /* Note: When we look up RTTI entries, we don't get any 
                   information on const or volatile attributes */
              }
Index: eval.c
/usr/local/bin/diff -c -w -L eval.c eval.c@@/main/cygnus/9 eval.c
*** eval.c
--- eval.c	Thu Mar 16 15:41:34 2000
***************
*** 37,42 ****
--- 37,45 ----
  /* This is defined in valops.c */
  extern int overload_resolution;
  
+ /* JYG: lookup rtti type of STRUCTOP_PTR when this is set to continue
+    on with successful lookup for member/method of the rtti type. */
+ extern int objectprint;
  
  /* Prototypes for local functions. */
  
***************
*** 428,459 ****
        (*pos) += 3;
        if (noside == EVAL_SKIP)
  	goto nosideret;
-       if (noside == EVAL_AVOID_SIDE_EFFECTS)
- 	{
- 	  struct symbol *sym = exp->elts[pc + 2].symbol;
- 	  enum lval_type lv;
- 
- 	  switch (SYMBOL_CLASS (sym))
- 	    {
- 	    case LOC_CONST:
- 	    case LOC_LABEL:
- 	    case LOC_CONST_BYTES:
- 	      lv = not_lval;
- 	      break;
  
! 	    case LOC_REGISTER:
! 	    case LOC_REGPARM:
! 	      lv = lval_register;
! 	      break;
  
- 	    default:
- 	      lv = lval_memory;
- 	      break;
- 	    }
- 
- 	  return value_zero (SYMBOL_TYPE (sym), lv);
- 	}
-       else
  	return value_of_variable (exp->elts[pc + 2].symbol,
  				  exp->elts[pc + 1].block);
  
--- 431,446 ----
        (*pos) += 3;
        if (noside == EVAL_SKIP)
  	goto nosideret;
  
!       /* JYG: We used to just return value_zero of the symbol type
! 	 if we're asked to avoid side effects.  Otherwise we return
! 	 value_of_variable (...).  However I'm not sure if
! 	 value_of_variable () has any side effect.
! 	 We need a full value object returned here for whatis_exp ()
! 	 to call evaluate_type () and then pass the full value to
! 	 value_rtti_target_type () if we are dealing with a pointer
! 	 or reference to a base class and print object is on. */
  
        return value_of_variable (exp->elts[pc + 2].symbol,
  				exp->elts[pc + 1].block);
  
***************
*** 1051,1056 ****
--- 1038,1068 ----
        arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
        if (noside == EVAL_SKIP)
  	goto nosideret;
+ 
+       /* JYG: if print object is on we need to replace the base type
+ 	 with rtti type in order to continue on with successful
+ 	 lookup of member / method only available in the rtti type. */
+       {
+         struct type *type = VALUE_TYPE (arg1);
+         struct type *real_type;
+         int full, top, using_enc;
+         
+         if (objectprint &&
+             (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+           {
+             real_type = value_rtti_target_type (arg1, &full, &top, &using_enc);
+             if (real_type)
+               {
+                 if (TYPE_CODE (type) == TYPE_CODE_PTR)
+                   real_type = lookup_pointer_type (real_type);
+                 else
+                   real_type = lookup_reference_type (real_type);
+ 
+                 arg1 = value_cast (real_type, arg1);
+               }
+           }
+       }
+ 
        if (noside == EVAL_AVOID_SIDE_EFFECTS)
  	return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
  						   &exp->elts[pc + 2].string,
Index: typeprint.c
/usr/local/bin/diff -c -w -L typeprint.c typeprint.c@@/main/cygnus/6 typeprint.c
*** typeprint.c
--- typeprint.c	Thu Mar 16 09:59:00 2000
***************
*** 82,87 ****
--- 82,88 ----
    register value_ptr val;
    register struct cleanup *old_chain = NULL;
    struct type *real_type = NULL;
+   struct type *type;
    int full = 0;
    int top = -1;
    int using_enc = 0;
***************
*** 96,112 ****
    else
      val = access_value_history (0);
  
    real_type = value_rtti_type (val, &full, &top, &using_enc);
  
    printf_filtered ("type = ");
  
!   if (real_type && objectprint)
!     printf_filtered ("/* real type = %s%s */\n",
! 		     TYPE_NAME (real_type),
! 		     full ? "" : " (incomplete object)");
!   /* FIXME: maybe better to use type_print (real_type, "", gdb_stdout, -1); */
  
!   type_print (VALUE_TYPE (val), "", gdb_stdout, show);
    printf_filtered ("\n");
  
    if (exp)
--- 97,136 ----
    else
      val = access_value_history (0);
  
+   type = VALUE_TYPE (val);
+ 
+   if (objectprint)
+     {
+       if (((TYPE_CODE (type) == TYPE_CODE_PTR) ||
+            (TYPE_CODE (type) == TYPE_CODE_REF))
+           &&
+           (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+         {
+           real_type = value_rtti_target_type (val, &full, &top, &using_enc);
+           if (real_type)
+             {
+               if (TYPE_CODE (type) == TYPE_CODE_PTR)
+                 real_type = lookup_pointer_type (real_type);
+               else
+                 real_type = lookup_reference_type (real_type);
+             }
+         }
+       else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
          real_type = value_rtti_type (val, &full, &top, &using_enc);
+     }
  
    printf_filtered ("type = ");
  
!   if (real_type)
!     {
!       printf_filtered ("/* real type = ");
!       type_print (real_type, "", gdb_stdout, -1);
!       if (! full)
!         printf_filtered (" (incomplete object)");
!       printf_filtered (" */\n");    
!     }
  
!   type_print (type, "", gdb_stdout, show);
    printf_filtered ("\n");
  
    if (exp)
Index: valops.c
/usr/local/bin/diff -c -w -L valops.c valops.c@@/main/cygnus/15 valops.c
*** valops.c
--- valops.c	Thu Mar 16 10:01:30 2000
***************
*** 326,331 ****
--- 326,337 ----
  		      value_ptr v2 = value_ind (arg2);
  		      VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
  			+ VALUE_OFFSET (v);
+ 
+                       /* JYG: adjust the new pointer value and
+ 			 embedded offset. */
+                       v2->aligner.contents[0] -=  VALUE_EMBEDDED_OFFSET (v);
+                       VALUE_EMBEDDED_OFFSET (v2) = 0;
+ 
  		      v2 = value_addr (v2);
  		      VALUE_TYPE (v2) = type;
  		      return v2;

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

* Re: RTTI working for G++
  2000-03-16 15:53     ` Jimmy Guo
@ 2000-03-16 16:29       ` Jimmy Guo
  2000-04-01  0:00         ` Jimmy Guo
  2000-04-01  0:00       ` Jimmy Guo
  1 sibling, 1 reply; 10+ messages in thread
From: Jimmy Guo @ 2000-03-16 16:29 UTC (permalink / raw)
  To: Daniel Berlin+mail.gdb; +Cc: gdb

A general question about the repositories on sourceware:
Can we use cvsup client tool to maintain a local repository?  Instead of
getting 'snapshots' via the CVS interfaces, I'd like to use the cvsup
tool to get updates to the repositories.  It requires sourceware to run
a cvsupd daemon.

Otherwise, what is the easiest way to maintain local repository?  I want
to create a local repository containing gdb, dejagnu, and binutils
products, and be able to automatically 'synchronize' with sourceware's
every night or on demand (turn-key solution here).

Thanks for any suggestion!

- Jimmy Guo, guo@cup.hp.com

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

* Re: RTTI working for G++
  2000-03-16 16:29       ` Jimmy Guo
@ 2000-04-01  0:00         ` Jimmy Guo
  0 siblings, 0 replies; 10+ messages in thread
From: Jimmy Guo @ 2000-04-01  0:00 UTC (permalink / raw)
  To: Daniel Berlin+mail.gdb; +Cc: gdb

A general question about the repositories on sourceware:
Can we use cvsup client tool to maintain a local repository?  Instead of
getting 'snapshots' via the CVS interfaces, I'd like to use the cvsup
tool to get updates to the repositories.  It requires sourceware to run
a cvsupd daemon.

Otherwise, what is the easiest way to maintain local repository?  I want
to create a local repository containing gdb, dejagnu, and binutils
products, and be able to automatically 'synchronize' with sourceware's
every night or on demand (turn-key solution here).

Thanks for any suggestion!

- Jimmy Guo, guo@cup.hp.com

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

* Re: RTTI working for G++
  2000-03-15 13:20 ` Jimmy Guo
  2000-03-15 20:33   ` Daniel Berlin+mail.gdb
@ 2000-04-01  0:00   ` Jimmy Guo
  1 sibling, 0 replies; 10+ messages in thread
From: Jimmy Guo @ 2000-04-01  0:00 UTC (permalink / raw)
  To: Daniel Berlin; +Cc: gdb

Daniel,

I recently looked into rtti print support and fixed several bugs in that
area.  Also I've created a test case under gdb.hp/gdb.aCC/.  Looks like
what I changed might work with G++ as well now that you're adding
support to it.  The fix is against HP WDB source, which is based on
sourceware's as of 1/10/00, so I'm not ready to submit against
sourceware's tree yet.  However, one of the fixes was that when print
object is on, and one wants to print member / methods of the derived
type, you can now do so.  Besides, there're some fixes to handle pointer
to a derived type and explicit casting of a pointer to a base to a
derived type.  I feel that these fixes will complement yours.  If
possible I want to send the diffs of the fixes to you to see if that
would make it into your patch.  Also I can look at your patches as well.

- Jimmy Guo, guo@cup.hp.com


On Mon, 13 Mar 2000, Daniel Berlin wrote:

>Okay, i have RTTI working for g++.
>Well, all except for multiple inheritance.
>
>Scratch that last part, i just made it offset properly if you have >1
>baseclass, so al is good.
>
>If i could have one or two volunteers to make sure it's not just my setup,
>and that all is well, before i post the patches asking for comments, i'd
>appreciate it.
>In any case, let me know what you guys think of it so far.
>If you look at the output, you'll notice that while for printing, it will
>print the object as if it was it's derived type, when it comes to
>accessing members/methods, just like in C++, you can't access the members,
>unless you specifically cast it to that derived type.
>
> For those wondering what the patch will do, check this out:
>
>The inheritance on these classes in the example looks like this
>
>fred is a base
>dan and bob both inherit directly from fred.
>george is another base.
>george2 inherits from george and bob (public george, public bob)
>
>I'll rename them so they make more sense as i work up testcases.
>
>But anyway, here's some output:
>
>GNU gdb 20000204
>Copyright 1998 Free Software Foundation, Inc.
>GDB is free software, covered by the GNU General Public License, and you are
>welcome to change it and/or distribute copies of it under certain conditions.
>Type "show copying" to see the conditions.
>There is absolutely no warranty for GDB.  Type "show warranty" for details.
>This GDB was configured as "i386-unknown-freebsdelf4.0".
>Setting up the environment for debugging gdb.
>.gdbinit:5: Error in sourced command file:
>No symbol table is loaded.  Use the "file" command.
>(gdb) file a.out
>Reading symbols from a.out...done.
>(gdb) b main
>Breakpoint 1 at 0x8048918: file a.cc, line 29.
>(gdb) set print object on
>(gdb) set print pretty on
>(gdb) set print vtbl on
>(gdb) set print array on
>(gdb) r
>Starting program: /usr/local/gdb/src/gdb/a.out 
>
>Breakpoint 1, 0x8048918 in main () at a.cc:29
>
>29	{
>(gdb) n
>31		dan=new daniel();
>(gdb) n
>32		cout <<typeid(*dan).name()<<endl;
>(gdb) p dan
>$1 = (daniel *) 0x8051030
>(gdb) p dan[0]
>$2 = (daniel) {
>  <fred> = {
>    a = 0, 
>    _vptr$ = 0x804f390
>  }, 
>  members of daniel: 
>  b = 0
>}
>(gdb) ptype dan
>type = class fred {
>  public:
>    int a;
>
>    fred & operator=(fred const &);
>    fred(fred const &);
>    fred(void);
>    virtual int ab(void);
>} *
>(gdb) p dan[0]->b
>There is no member or method named b.
>(gdb) n
>6daniel
>33		dan=new bob();
>(gdb) 
>34		dan=new george2();
>(gdb) p dan
>$3 = (bob *) 0x8051040
>(gdb) p dan[0]
>$4 = (bob) {
>  <fred> = {
>    a = 0, 
>    _vptr$ = 0x804f378
>  }, 
>  members of bob: 
>  c = 0
>}
>(gdb) p dan[0].c
>There is no member or method named c.
>(gdb) n
>35		dan->a=55;
>(gdb) p dan[0]
>$5 = (george2 [incomplete object]) {
>  <george> = {
>    d = 0
>  }, 
>  <bob> = {
>    <fred> = {
>      a = 0, 
>      _vptr$ = 0x804f360
>    }, 
>    members of bob: 
>    c = 0
>  }, 
>  members of george2: 
>  e = 0
>}
>(gdb) l
>30		fred *dan;
>31		dan=new daniel();
>32		cout <<typeid(*dan).name()<<endl;
>33		dan=new bob();
>34		dan=new george2();
>35		dan->a=55;
>36		cout <<typeid(*dan).name()<<endl;
>37	}
>38	
>(gdb) n
>36		cout <<typeid(*dan).name()<<endl;
>(gdb) p dan
>$7 = (suspicious *) 0x8050064
>(gdb) p dan[0]
>$8 = (george2 [incomplete object]) {
>  <george> = {
>    d = 0
>  }, 
>  <bob> = {
>    <fred> = {
>      a = 55, 
>      _vptr$ = 0x804f360
>    }, 
>    members of bob: 
>    c = 0
>  }, 
>  members of george2: 
>  e = 0
>}
>(gdb) c
>Continuing.
>7george2
>
>Program exited normally.
>(gdb) q
>
>Script done on Mon Mar 13 19:34:51 2000

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

* Re: RTTI working for G++
  2000-03-16 15:53     ` Jimmy Guo
  2000-03-16 16:29       ` Jimmy Guo
@ 2000-04-01  0:00       ` Jimmy Guo
  1 sibling, 0 replies; 10+ messages in thread
From: Jimmy Guo @ 2000-04-01  0:00 UTC (permalink / raw)
  To: Daniel Berlin+mail.gdb; +Cc: gdb

>> ... However, one of the fixes was that when print
>> object is on, and one wants to print member / methods of the derived
>> type, you can now do so. 
>
>See, i didn't consider that a bug, i considered it a lacking
>feature. It just wasn't doing the lookup it would need to do, and i've
>been too busy to fix it.

If 'print foo' says it's a pointer to something, and 'print foo->a' says
'There is no member or method named a.', it's very confusing to the
user.  When print object is on, this could happen.  I'd be more willing
to say it's a bug, since the error message contradicts with what print
says and just misleads user ('which one should I believe from this
debugger?').

The fix is in eval.c (evaluate_subexp_standard): it needs to know if
objectprint is set, and if so, return the pointer to the rtti type when
dealing with STUCTOP_PTR (if target type code is TYPE_CODE_CLASS).

>> Besides, there're some fixes to handle pointer
>> to a derived type and explicit casting of a pointer to a base to a
>> derived type. 
>
>This i ran up against. I also handled reference types (By pretending
>they were pointers).

Actually the example you gave at the end of this email looks like
something I fixed, in the casting code.  I'm not familiar with
value_rtti_type and don't quite understand what you were dealing with --
full, etc. are all reset to initial values upon entry into
value_rtti_type ().

>Did you notice that it's not really fun to use value_nid (damn
>flyspell keeps "correcting" the IND to nid, as if "nid" was really a word
>either.) in value_rtti_type? value_nid will call the RTTI routine
>during it's lazy evaluation, which gets you into a recursive nightmare
>if you aren't careful.

I wasn't adventuring into that area since I'm looking at the higher
layer of the proper handling of casting, printing, and expression
evaluation.

>I'd be glad to incorporate your fixes into my patch, and i'd
>appreciate it if you'd look at mine.
>I'll post it to gdb-patches in a few days.

Mine is enclosed in this email.

>I'm a little confused about the semantics of using_enc/full/top in value_rtti_type.
>
>It seems if i set full to 0, on multiple inheritance, it gets the name
>right, but the offset wrong, so you have the right name, and the wrong
>values.
>If i set full to 1, it gets the name wrong ("suspicious *", which
>means it couldn't look it up right), but the values right.

See if my changes to c-valprint.c and valops.c solved your problem.  I
think at least part of the problem is that the pointer value was _not_
adjusted when you change the type of the thing to a rtti type, which is
fixed in these two files.  c-valprint.c deals with printing the pointer
value itself; valops.c deals with printing a member of the pointer value.

Patch follows (the change to typeprint.c probably conflicts with your
version, and I like the output you provided).

- Jimmy Guo, guo@cup.hp.com

Thu Mar 16 15:49:56 2000	Jimmy guo	<guo@cup.hp.com>

	* c-valprint.c (c_value_print): adjust pointer value when
	objectprint is set and pointer type is changed to point to the
	rtti type.

	* eval.c (evaluate_subexp_standard): for OP_VAR_VALUE, always
	return full value object; for STRUCTOP_PTR, use pointer to
	rtti type to get member / method if objectprint is set and
	target type of pointer is class.

	* typeprint.c (whatis_exp): if objectprint is set and exp is of
	pointer / reference type to a class object, look up and print
	the pointer / reference to rtti type.

	* valops.c (value_cast): when casting a pointer / reference type
	of a class object to pointer / refer to its rtti type, adjust
	the new pointer value accordingly.


Index: c-valprint.c
/usr/local/bin/diff -c -w -L c-valprint.c c-valprint.c@@/main/cygnus/7 c-valprint.c
*** c-valprint.c
--- c-valprint.c	Thu Mar 16 10:21:16 2000
***************
*** 497,502 ****
--- 497,505 ----
                    /* create a reference type referencing the real type */
                    type = lookup_reference_type (real_type);
                  }
+ 	      /* JYG: Need to adjust pointer value. */
+               val->aligner.contents[0] -= top;
+ 
                /* Note: When we look up RTTI entries, we don't get any 
                   information on const or volatile attributes */
              }
Index: eval.c
/usr/local/bin/diff -c -w -L eval.c eval.c@@/main/cygnus/9 eval.c
*** eval.c
--- eval.c	Thu Mar 16 15:41:34 2000
***************
*** 37,42 ****
--- 37,45 ----
  /* This is defined in valops.c */
  extern int overload_resolution;
  
+ /* JYG: lookup rtti type of STRUCTOP_PTR when this is set to continue
+    on with successful lookup for member/method of the rtti type. */
+ extern int objectprint;
  
  /* Prototypes for local functions. */
  
***************
*** 428,459 ****
        (*pos) += 3;
        if (noside == EVAL_SKIP)
  	goto nosideret;
-       if (noside == EVAL_AVOID_SIDE_EFFECTS)
- 	{
- 	  struct symbol *sym = exp->elts[pc + 2].symbol;
- 	  enum lval_type lv;
- 
- 	  switch (SYMBOL_CLASS (sym))
- 	    {
- 	    case LOC_CONST:
- 	    case LOC_LABEL:
- 	    case LOC_CONST_BYTES:
- 	      lv = not_lval;
- 	      break;
  
! 	    case LOC_REGISTER:
! 	    case LOC_REGPARM:
! 	      lv = lval_register;
! 	      break;
  
- 	    default:
- 	      lv = lval_memory;
- 	      break;
- 	    }
- 
- 	  return value_zero (SYMBOL_TYPE (sym), lv);
- 	}
-       else
  	return value_of_variable (exp->elts[pc + 2].symbol,
  				  exp->elts[pc + 1].block);
  
--- 431,446 ----
        (*pos) += 3;
        if (noside == EVAL_SKIP)
  	goto nosideret;
  
!       /* JYG: We used to just return value_zero of the symbol type
! 	 if we're asked to avoid side effects.  Otherwise we return
! 	 value_of_variable (...).  However I'm not sure if
! 	 value_of_variable () has any side effect.
! 	 We need a full value object returned here for whatis_exp ()
! 	 to call evaluate_type () and then pass the full value to
! 	 value_rtti_target_type () if we are dealing with a pointer
! 	 or reference to a base class and print object is on. */
  
        return value_of_variable (exp->elts[pc + 2].symbol,
  				exp->elts[pc + 1].block);
  
***************
*** 1051,1056 ****
--- 1038,1068 ----
        arg1 = evaluate_subexp (NULL_TYPE, exp, pos, noside);
        if (noside == EVAL_SKIP)
  	goto nosideret;
+ 
+       /* JYG: if print object is on we need to replace the base type
+ 	 with rtti type in order to continue on with successful
+ 	 lookup of member / method only available in the rtti type. */
+       {
+         struct type *type = VALUE_TYPE (arg1);
+         struct type *real_type;
+         int full, top, using_enc;
+         
+         if (objectprint &&
+             (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+           {
+             real_type = value_rtti_target_type (arg1, &full, &top, &using_enc);
+             if (real_type)
+               {
+                 if (TYPE_CODE (type) == TYPE_CODE_PTR)
+                   real_type = lookup_pointer_type (real_type);
+                 else
+                   real_type = lookup_reference_type (real_type);
+ 
+                 arg1 = value_cast (real_type, arg1);
+               }
+           }
+       }
+ 
        if (noside == EVAL_AVOID_SIDE_EFFECTS)
  	return value_zero (lookup_struct_elt_type (VALUE_TYPE (arg1),
  						   &exp->elts[pc + 2].string,
Index: typeprint.c
/usr/local/bin/diff -c -w -L typeprint.c typeprint.c@@/main/cygnus/6 typeprint.c
*** typeprint.c
--- typeprint.c	Thu Mar 16 09:59:00 2000
***************
*** 82,87 ****
--- 82,88 ----
    register value_ptr val;
    register struct cleanup *old_chain = NULL;
    struct type *real_type = NULL;
+   struct type *type;
    int full = 0;
    int top = -1;
    int using_enc = 0;
***************
*** 96,112 ****
    else
      val = access_value_history (0);
  
    real_type = value_rtti_type (val, &full, &top, &using_enc);
  
    printf_filtered ("type = ");
  
!   if (real_type && objectprint)
!     printf_filtered ("/* real type = %s%s */\n",
! 		     TYPE_NAME (real_type),
! 		     full ? "" : " (incomplete object)");
!   /* FIXME: maybe better to use type_print (real_type, "", gdb_stdout, -1); */
  
!   type_print (VALUE_TYPE (val), "", gdb_stdout, show);
    printf_filtered ("\n");
  
    if (exp)
--- 97,136 ----
    else
      val = access_value_history (0);
  
+   type = VALUE_TYPE (val);
+ 
+   if (objectprint)
+     {
+       if (((TYPE_CODE (type) == TYPE_CODE_PTR) ||
+            (TYPE_CODE (type) == TYPE_CODE_REF))
+           &&
+           (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_CLASS))
+         {
+           real_type = value_rtti_target_type (val, &full, &top, &using_enc);
+           if (real_type)
+             {
+               if (TYPE_CODE (type) == TYPE_CODE_PTR)
+                 real_type = lookup_pointer_type (real_type);
+               else
+                 real_type = lookup_reference_type (real_type);
+             }
+         }
+       else if (TYPE_CODE (type) == TYPE_CODE_CLASS)
          real_type = value_rtti_type (val, &full, &top, &using_enc);
+     }
  
    printf_filtered ("type = ");
  
!   if (real_type)
!     {
!       printf_filtered ("/* real type = ");
!       type_print (real_type, "", gdb_stdout, -1);
!       if (! full)
!         printf_filtered (" (incomplete object)");
!       printf_filtered (" */\n");    
!     }
  
!   type_print (type, "", gdb_stdout, show);
    printf_filtered ("\n");
  
    if (exp)
Index: valops.c
/usr/local/bin/diff -c -w -L valops.c valops.c@@/main/cygnus/15 valops.c
*** valops.c
--- valops.c	Thu Mar 16 10:01:30 2000
***************
*** 326,331 ****
--- 326,337 ----
  		      value_ptr v2 = value_ind (arg2);
  		      VALUE_ADDRESS (v2) -= VALUE_ADDRESS (v)
  			+ VALUE_OFFSET (v);
+ 
+                       /* JYG: adjust the new pointer value and
+ 			 embedded offset. */
+                       v2->aligner.contents[0] -=  VALUE_EMBEDDED_OFFSET (v);
+                       VALUE_EMBEDDED_OFFSET (v2) = 0;
+ 
  		      v2 = value_addr (v2);
  		      VALUE_TYPE (v2) = type;
  		      return v2;

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

* Re: RTTI working for G++
  2000-03-15 20:33   ` Daniel Berlin+mail.gdb
  2000-03-16 15:53     ` Jimmy Guo
@ 2000-04-01  0:00     ` Daniel Berlin+mail.gdb
  1 sibling, 0 replies; 10+ messages in thread
From: Daniel Berlin+mail.gdb @ 2000-04-01  0:00 UTC (permalink / raw)
  To: Jimmy Guo; +Cc: Daniel Berlin, gdb

Jimmy Guo <guo@cup.hp.com> writes:

> Daniel,
> 
> I recently looked into rtti print support and fixed several bugs in that
> area. 

As have I.
>  Also I've created a test case under gdb.hp/gdb.aCC/.  Looks like
> what I changed might work with G++ as well now that you're adding
> support to it.  

Possibly, i have a feeling we fixed the same bugs.
> The fix is against HP WDB source, which is based on
> sourceware's as of 1/10/00, so I'm not ready to submit against
> sourceware's tree yet.  However, one of the fixes was that when print
> object is on, and one wants to print member / methods of the derived
> type, you can now do so. 

See, i didn't consider that a bug, i considered it a lacking
feature. It just wasn't doing the lookup it would need to do, and i've
been too busy to fix it.

> Besides, there're some fixes to handle pointer
> to a derived type and explicit casting of a pointer to a base to a
> derived type. 

This i ran up against. I also handled reference types (By pretending
they were pointers).

> I feel that these fixes will complement yours.  
Most likely you are correct.
I wasn't ready to go all out and make all the symbol readers fill in
the vtable stuff like it does for HP (it's on my list for sometime).
Seeing as how i would have had to do that, as well as differentiate
between HP aCC debug symbols and other forms of debug symbols, with
another flag, i decided for right now to just put the RTTI stuff for
G++ where it was already, the else block of all the "HAS_VTABLE" if
blocks.
I only actually added one more if, in value_rtti_type, right before
the HP specific stuff starts, that says
"if(TYPE_HAS_VTABLE(known_type)) { do hp stuff } else { do g++ stuff}"

That way, i didn't break any of your HP specific stuff.

Did you notice that it's not really fun to use value_nid (damn
flyspell keeps "correcting" the IND to nid, as if "nid" was really a word
either.) in value_rtti_type? value_nid will call the RTTI routine
during it's lazy evaluation, which gets you into a recursive nightmare
if you aren't careful.


> If
> possible I want to send the diffs of the fixes to you to see if that
> would make it into your patch.  Also I can look at your patches as
> well.

I'd be glad to incorporate your fixes into my patch, and i'd
appreciate it if you'd look at mine.
I'll post it to gdb-patches in a few days.

I'm a little confused about the semantics of using_enc/full/top in value_rtti_type.

It seems if i set full to 0, on multiple inheritance, it gets the name
right, but the offset wrong, so you have the right name, and the wrong
values.
If i set full to 1, it gets the name wrong ("suspicious *", which
means it couldn't look it up right), but the values right.
Example of what i mean (when i have bar multiple inheriting 

class foo
{
public:
int a;
};
class foo2
{
public:
int b;
};
class bar:public foo1, public foo2
{
public:
int c;
};

foo *foo1=new bar();

print foo1 (full==1 will give "suspicious *", full==0 will give "bar
*")
print *foo1 (full==1 will give the proper values, full==0 gets the
offset wrong, and thus, prints the wrong values)

Even more convoluted,
print foo1->a (with full==1) will access the wrong memory, even though it had it
right 2 seconds before when it printed the full object.
I know i'm setting top properly in all cases.
I have a feeling i'm not quite grasping the way it lays out in memory
yet.

--Dan

> 
> - Jimmy Guo, guo@cup.hp.com
> 
> On Mon, 13 Mar 2000, Daniel Berlin wrote:
> 
> >Okay, i have RTTI working for g++.
> >Well, all except for multiple inheritance.
> >
> >Scratch that last part, i just made it offset properly if you have >1
> >baseclass, so al is good.
> >
> >If i could have one or two volunteers to make sure it's not just my setup,
> >and that all is well, before i post the patches asking for comments, i'd
> >appreciate it.
> >In any case, let me know what you guys think of it so far.
> >If you look at the output, you'll notice that while for printing, it will
> >print the object as if it was it's derived type, when it comes to
> >accessing members/methods, just like in C++, you can't access the members,
> >unless you specifically cast it to that derived type.
> >
> > For those wondering what the patch will do, check this out:
> >
> >The inheritance on these classes in the example looks like this
> >
> >fred is a base
> >dan and bob both inherit directly from fred.
> >george is another base.
> >george2 inherits from george and bob (public george, public bob)
> >
> >I'll rename them so they make more sense as i work up testcases.
> >
> >But anyway, here's some output:
> >
> >GNU gdb 20000204
> >Copyright 1998 Free Software Foundation, Inc.
> >GDB is free software, covered by the GNU General Public License, and you are
> >welcome to change it and/or distribute copies of it under certain conditions.
> >Type "show copying" to see the conditions.
> >There is absolutely no warranty for GDB.  Type "show warranty" for details.
> >This GDB was configured as "i386-unknown-freebsdelf4.0".
> >Setting up the environment for debugging gdb.
> >.gdbinit:5: Error in sourced command file:
> >No symbol table is loaded.  Use the "file" command.
> >(gdb) file a.out
> >Reading symbols from a.out...done.
> >(gdb) b main
> >Breakpoint 1 at 0x8048918: file a.cc, line 29.
> >(gdb) set print object on
> >(gdb) set print pretty on
> >(gdb) set print vtbl on
> >(gdb) set print array on
> >(gdb) r
> >Starting program: /usr/local/gdb/src/gdb/a.out 
> >
> >Breakpoint 1, 0x8048918 in main () at a.cc:29
> >
> >29	{
> >(gdb) n
> >31		dan=new daniel();
> >(gdb) n
> >32		cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$1 = (daniel *) 0x8051030
> >(gdb) p dan[0]
> >$2 = (daniel) {
> >  <fred> = {
> >    a = 0, 
> >    _vptr$ = 0x804f390
> >  }, 
> >  members of daniel: 
> >  b = 0
> >}
> >(gdb) ptype dan
> >type = class fred {
> >  public:
> >    int a;
> >
> >    fred & operator=(fred const &);
> >    fred(fred const &);
> >    fred(void);
> >    virtual int ab(void);
> >} *
> >(gdb) p dan[0]->b
> >There is no member or method named b.
> >(gdb) n
> >6daniel
> >33		dan=new bob();
> >(gdb) 
> >34		dan=new george2();
> >(gdb) p dan
> >$3 = (bob *) 0x8051040
> >(gdb) p dan[0]
> >$4 = (bob) {
> >  <fred> = {
> >    a = 0, 
> >    _vptr$ = 0x804f378
> >  }, 
> >  members of bob: 
> >  c = 0
> >}
> >(gdb) p dan[0].c
> >There is no member or method named c.
> >(gdb) n
> >35		dan->a=55;
> >(gdb) p dan[0]
> >$5 = (george2 [incomplete object]) {
> >  <george> = {
> >    d = 0
> >  }, 
> >  <bob> = {
> >    <fred> = {
> >      a = 0, 
> >      _vptr$ = 0x804f360
> >    }, 
> >    members of bob: 
> >    c = 0
> >  }, 
> >  members of george2: 
> >  e = 0
> >}
> >(gdb) l
> >30		fred *dan;
> >31		dan=new daniel();
> >32		cout <<typeid(*dan).name()<<endl;
> >33		dan=new bob();
> >34		dan=new george2();
> >35		dan->a=55;
> >36		cout <<typeid(*dan).name()<<endl;
> >37	}
> >38	
> >(gdb) n
> >36		cout <<typeid(*dan).name()<<endl;
> >(gdb) p dan
> >$7 = (suspicious *) 0x8050064
> >(gdb) p dan[0]
> >$8 = (george2 [incomplete object]) {
> >  <george> = {
> >    d = 0
> >  }, 
> >  <bob> = {
> >    <fred> = {
> >      a = 55, 
> >      _vptr$ = 0x804f360
> >    }, 
> >    members of bob: 
> >    c = 0
> >  }, 
> >  members of george2: 
> >  e = 0
> >}
> >(gdb) c
> >Continuing.
> >7george2
> >
> >Program exited normally.
> >(gdb) q
> >
> >Script done on Mon Mar 13 19:34:51 2000

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

* RTTI working for G++
  2000-03-13 16:53 RTTI working for G++ Daniel Berlin
  2000-03-15 13:20 ` Jimmy Guo
@ 2000-04-01  0:00 ` Daniel Berlin
  1 sibling, 0 replies; 10+ messages in thread
From: Daniel Berlin @ 2000-04-01  0:00 UTC (permalink / raw)
  To: gdb

Okay, i have RTTI working for g++.
Well, all except for multiple inheritance.

Scratch that last part, i just made it offset properly if you have >1
baseclass, so al is good.

If i could have one or two volunteers to make sure it's not just my setup,
and that all is well, before i post the patches asking for comments, i'd
appreciate it.
In any case, let me know what you guys think of it so far.
If you look at the output, you'll notice that while for printing, it will
print the object as if it was it's derived type, when it comes to
accessing members/methods, just like in C++, you can't access the members,
unless you specifically cast it to that derived type.

 For those wondering what the patch will do, check this out:

The inheritance on these classes in the example looks like this

fred is a base
dan and bob both inherit directly from fred.
george is another base.
george2 inherits from george and bob (public george, public bob)

I'll rename them so they make more sense as i work up testcases.

But anyway, here's some output:

GNU gdb 20000204
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-unknown-freebsdelf4.0".
Setting up the environment for debugging gdb.
.gdbinit:5: Error in sourced command file:
No symbol table is loaded.  Use the "file" command.
(gdb) file a.out
Reading symbols from a.out...done.
(gdb) b main
Breakpoint 1 at 0x8048918: file a.cc, line 29.
(gdb) set print object on
(gdb) set print pretty on
(gdb) set print vtbl on
(gdb) set print array on
(gdb) r
Starting program: /usr/local/gdb/src/gdb/a.out 

Breakpoint 1, 0x8048918 in main () at a.cc:29

29	{
(gdb) n
31		dan=new daniel();
(gdb) n
32		cout <<typeid(*dan).name()<<endl;
(gdb) p dan
$1 = (daniel *) 0x8051030
(gdb) p dan[0]
$2 = (daniel) {
  <fred> = {
    a = 0, 
    _vptr$ = 0x804f390
  }, 
  members of daniel: 
  b = 0
}
(gdb) ptype dan
type = class fred {
  public:
    int a;

    fred & operator=(fred const &);
    fred(fred const &);
    fred(void);
    virtual int ab(void);
} *
(gdb) p dan[0]->b
There is no member or method named b.
(gdb) n
6daniel
33		dan=new bob();
(gdb) 
34		dan=new george2();
(gdb) p dan
$3 = (bob *) 0x8051040
(gdb) p dan[0]
$4 = (bob) {
  <fred> = {
    a = 0, 
    _vptr$ = 0x804f378
  }, 
  members of bob: 
  c = 0
}
(gdb) p dan[0].c
There is no member or method named c.
(gdb) n
35		dan->a=55;
(gdb) p dan[0]
$5 = (george2 [incomplete object]) {
  <george> = {
    d = 0
  }, 
  <bob> = {
    <fred> = {
      a = 0, 
      _vptr$ = 0x804f360
    }, 
    members of bob: 
    c = 0
  }, 
  members of george2: 
  e = 0
}
(gdb) l
30		fred *dan;
31		dan=new daniel();
32		cout <<typeid(*dan).name()<<endl;
33		dan=new bob();
34		dan=new george2();
35		dan->a=55;
36		cout <<typeid(*dan).name()<<endl;
37	}
38	
(gdb) n
36		cout <<typeid(*dan).name()<<endl;
(gdb) p dan
$7 = (suspicious *) 0x8050064
(gdb) p dan[0]
$8 = (george2 [incomplete object]) {
  <george> = {
    d = 0
  }, 
  <bob> = {
    <fred> = {
      a = 55, 
      _vptr$ = 0x804f360
    }, 
    members of bob: 
    c = 0
  }, 
  members of george2: 
  e = 0
}
(gdb) c
Continuing.
7george2

Program exited normally.
(gdb) q

Script done on Mon Mar 13 19:34:51 2000

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

end of thread, other threads:[~2000-04-01  0:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-13 16:53 RTTI working for G++ Daniel Berlin
2000-03-15 13:20 ` Jimmy Guo
2000-03-15 20:33   ` Daniel Berlin+mail.gdb
2000-03-16 15:53     ` Jimmy Guo
2000-03-16 16:29       ` Jimmy Guo
2000-04-01  0:00         ` Jimmy Guo
2000-04-01  0:00       ` Jimmy Guo
2000-04-01  0:00     ` Daniel Berlin+mail.gdb
2000-04-01  0:00   ` Jimmy Guo
2000-04-01  0:00 ` Daniel Berlin

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).