This is the mail archive of the gdb-patches@sources.redhat.com 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/cp] method stub assertions


On Mon, Jan 05, 2004 at 11:28:41PM -0500, Michael Chastain wrote:
>   (gdb) ptype pfii
>   type = int (*)(int)
> 
>   (gdb) ptype pfiAi
>   type = int (*)(A &, int)
> 
>   (gdb) ptype pfAii
>   type = struct {
>       int (*__pfn)(A *, int);
>       int __delta;
>   }
> 
>   (gdb) ptype A::bad6
>   type = int (A * const, int)
> 
>   (gdb) ptype &A::bad6
>   type = int (*)(A * const, int)
> 
> The first four of those are okay with me.  pfAii is not only a
> different type from a pointer to an ordinary function,
> but the type has a different size!

That's really unfortunate debug info.  Of course, GDB isn't prepared to
handle DW_TAG_ptr_to_member_type.  But now that we have a working
location expression parser it would not be difficult.  Then GCC could
emit the right information.

> The last one, &A::bad6, bothers me a lot.  The address-of operator
> applied to a (non-static) member function should *not* return a
> plain pointer-to-function.  Output #5 should *not* look like #2.
> It should look like:
> 
>   (gdb) ptype &A::bad6
>   type = int (A::*)(int)
> 
> I'm willing to slide on the "A * const" hidden parameter,
> but not on the "A::*" instead of "*".
> 
> I think that gdb does not distinguish between pointer-to-function and
> PMF.  PMF's always carry a class argument with them, but plain PF's
> never need them.  I suspect gdb is mixing the TYPE_CODE's instead of using
> separate TYPE_CODE's.
> 
> The existing scheme is something like:
> 
>   TYPE_CODE_MEMBER
>     TYPE_CODE_METHOD
>       domain type
> 
> But I want it to be more:
> 
>   TYPE_CODE_MEMBER
>     domain type
>     TYPE_CODE_METHOD

That's a nice hypothesis.  Unfortunately it's completely wrong :)
First of all, TYPE_CODE_MEMBER and TYPE_CODE_METHOD are siblings. 
MEMBER is used for data variables, not to wrap methods.

Secondly, take a look at the type of A::bad6 - put a breakpoint in
c_type_print_varspec_prefix.  It's a TYPE_CODE_FUNCTION.  Why is that? 
It's because A::bad6 is a function.  Now, if you take a look at its
first argument, and walk the chain down:

(top-gdb) p *type.main_type
$19 = {code = TYPE_CODE_FUNC, upper_bound_type = BOUND_SIMPLE,
  lower_bound_type = BOUND_SIMPLE, name = 0x0, tag_name = 0x0, objfile =
  0x82cfea0, target_type = 0x82d8320, flags = 128, nfields = 2, 
  vptr_fieldno = -1, fields = 0x82d85a8, vptr_basetype = 0x0,
  type_specific = {cplus_stuff = 0x0, floatformat = 0x0}}

(top-gdb) p type.main_type.fields.type.main_type.target_type.main_type.type_specific.cplus_stuff.fn_fieldlists[3].fn_fields[0].type.main_type[0]
$18 = {code = TYPE_CODE_METHOD, upper_bound_type = BOUND_SIMPLE,
  lower_bound_type = BOUND_SIMPLE,  name = 0x0, tag_name = 0x0,
  objfile = 0x82cfea0, target_type = 0x82d8320, flags = 0, nfields = 2,
  vptr_fieldno = 0, fields = 0x82d8440, vptr_basetype = 0x82d7fd4,
  type_specific = {cplus_stuff = 0x0, floatformat = 0x0}}

The debug information for A::bad6 does not specify that it is a method. 
Rather only the debug info for class A specifies that it has a method
named A::bad6.  Take a look at a readelf -wi dump of your testcase to
see how this works.

It may be that A::bad6 should have TYPE_CODE_METHOD.  Fixing this would
require some surgery to the stabs and dwarf readers.  I suspect that
hpread does it already.  Or it may be that TYPE_CODE_METHOD should be
eliminated and they both should be TYPE_CODE_FUNCTION.  That's hard to
say.

> Every time you create a TYPE_CODE_MEMBER, you should know what the
> domain type is, and store it up one node, not down in the
> TYPE_CODE_METHOD node.  And every time you use a TYPE_CODE_MEMBER, you
> have to use the domain type.  And if you're not dealing with
> pointer-to-member, you don't need the domain type.  It's an attribute
> of the pointer-to-member, not an attribute of the member!
> 
> Bleagh.  I'm probably butchering the actual gdb data structures here.
> Need to read more.

The current structure of this says that if we get a TYPE_CODE_POINTER
and its target type is TYPE_CODE_METHOD or TYPE_CODE_MEMBER, then it's
a pointer-to-member.  You're suggesting that we have a TYPE_CODE_PTRMEM
instead.  This matches what a lot of other similar programs do, so
maybe it makes sense.  But unless we can make A::bad6 have
TYPE_CODE_METHOD we still won't know to create a TYPE_CODE_PTRMEM when
its address is taken, so I think this can come later.

> > Do static methods have TYPE_CODE_METHOD, and should they?
> > That's the question.
> 
> I think they currently do.  And then they have TYPE_FLAG_STATIC to
> distinguish them from other types.
> 
> Static methods have to appear with other methods because they
> participate in overload resolution.

Currently they do appear as TYPE_CODE_METHOD.  I think that they
probably shouldn't.  A pointer to a static method is a function
pointer, not a pointer-to-member.  Similarly static variables should
probably not be TYPE_CODE_MEMBER.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer


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