Re: [rfc/cp] method stub assertions

Daniel Jacobowitz
2004-01-06T17:05:33Z

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.