This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
Re: RFA: Correct field names for class methods
Daniel Jacobowitz writes:
> On Tue, Sep 10, 2002 at 06:13:41PM -0400, Elena Zannoni wrote:
> > Approved, except for moving the functions to stabsread.c.
> >
> > Elena
>
> Well, that ulterior motive is showing again.
>
> - I can't move method_name_from_physname unless I move the existing
> check_stub_method routine. I could do this, and it might even be a
> good idea, since it's so patently stabs-only.
OK I like the idea.
>
> - I'm going to need class_name_from_physname in other parts of GDB; at
> least in the DWARF-2 reader.
>
Ah.
> I'd feel a little silly moving method_name_from_physname and leaving
> class_name_from_physname. What do you think? I should probably
> (separate patch) move check_stub_method and check_stub_method_group,
> but the _from_physname functions seem like gdbtypes.c material to me.
>
As you mentioned in a [private] e-mail maybe now the time has come to
start separating the c++ support into its own file. I think we could
move a few other things into such a file. I recall this being proposed
before, but I cannot do a successful search in the archives. All the
words I try to match are too common and the search only returns the
first N matches.
Elena
> >
> >
> > > --
> > > Daniel Jacobowitz
> > > MontaVista Software Debian GNU/Linux Developer
> > >
> > > 2002-09-10 Daniel Jacobowitz <drow@mvista.com>
> > >
> > > * gdbtypes.c (check_stub_method): Make static.
> > > (check_stub_method_group, find_last_component)
> > > (class_name_from_physname, method_name_from_physname): New functions.
> > > * gdbtypes.h: Update prototypes.
> > >
> > > * stabsread.c: Include "cp-abi.h".
> > > (update_method_name_from_physname): New function.
> > > (read_member_functions): Correct method names for operators
> > > and v3 constructors/destructors. Separate v2 constructors and
> > > destructors.
> > > * Makefile.in (stabsread.o): Update dependencies.
> > >
> > > * cp-valprint.c (cp_print_class_method): Call
> > > check_stub_method_group instead of check_stub_method. Remove
> > > extraneous QUITs.
> > > * p-valprint.c (pascal_object_print_class_method): Likewise.
> > > * valops.c (search_struct_method): Likewise.
> > > (find_method_list, value_struct_elt_for_reference): Likewise.
> > >
> > > Index: Makefile.in
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/Makefile.in,v
> > > retrieving revision 1.257
> > > diff -u -p -r1.257 Makefile.in
> > > --- Makefile.in 2 Sep 2002 18:09:06 -0000 1.257
> > > +++ Makefile.in 10 Sep 2002 16:35:15 -0000
> > > @@ -2174,7 +2174,7 @@ stabsread.o: stabsread.c $(defs_h) $(gdb
> > > $(symtab_h) $(gdbtypes_h) $(expression_h) $(symfile_h) $(objfiles_h) \
> > > $(aout_stab_gnu_h) $(libaout_h) $(aout_aout64_h) $(gdb_stabs_h) \
> > > $(buildsym_h) $(complaints_h) $(demangle_h) $(language_h) \
> > > - $(doublest_h) $(stabsread_h)
> > > + $(doublest_h) $(stabsread_h) $(cp_abi_h)
> > > stack.o: stack.c $(defs_h) $(gdb_string_h) $(value_h) $(symtab_h) \
> > > $(gdbtypes_h) $(expression_h) $(language_h) $(frame_h) $(gdbcmd_h) \
> > > $(gdbcore_h) $(target_h) $(breakpoint_h) $(demangle_h) $(inferior_h) \
> > > Index: cp-valprint.c
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/cp-valprint.c,v
> > > retrieving revision 1.13
> > > diff -u -p -r1.13 cp-valprint.c
> > > --- cp-valprint.c 29 Jul 2002 22:55:26 -0000 1.13
> > > +++ cp-valprint.c 10 Sep 2002 16:35:15 -0000
> > > @@ -97,13 +97,11 @@ cp_print_class_method (char *valaddr,
> > > f = TYPE_FN_FIELDLIST1 (domain, i);
> > > len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
> > >
> > > + check_stub_method_group (domain, i);
> > > for (j = 0; j < len2; j++)
> > > {
> > > - QUIT;
> > > if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
> > > {
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (domain, i, j);
> > > kind = "virtual ";
> > > goto common;
> > > }
> > > @@ -129,15 +127,11 @@ cp_print_class_method (char *valaddr,
> > > f = TYPE_FN_FIELDLIST1 (domain, i);
> > > len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
> > >
> > > + check_stub_method_group (f, j);
> > > for (j = 0; j < len2; j++)
> > > {
> > > - QUIT;
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (domain, i, j);
> > > if (STREQ (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
> > > - {
> > > - goto common;
> > > - }
> > > + goto common;
> > > }
> > > }
> > > }
> > > Index: gdbtypes.c
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/gdbtypes.c,v
> > > retrieving revision 1.56
> > > diff -u -p -r1.56 gdbtypes.c
> > > --- gdbtypes.c 20 Aug 2002 19:57:32 -0000 1.56
> > > +++ gdbtypes.c 10 Sep 2002 16:35:16 -0000
> > > @@ -1672,7 +1672,7 @@ safe_parse_type (char *p, int length)
> > > which info used to be in the stab's but was removed to hack back
> > > the space required for them. */
> > >
> > > -void
> > > +static void
> > > check_stub_method (struct type *type, int method_id, int signature_id)
> > > {
> > > struct fn_field *f;
> > > @@ -1781,6 +1781,49 @@ check_stub_method (struct type *type, in
> > > xfree (demangled_name);
> > > }
> > >
> > > +/* This is the external interface to check_stub_method, above. This function
> > > + unstubs all of the signatures for TYPE's METHOD_ID method name. After
> > > + calling this function TYPE_FN_FIELD_STUB will be cleared for each signature
> > > + and TYPE_FN_FIELDLIST_NAME will be correct.
> > > +
> > > + This function unfortunately can not die until stabs do. */
> > > +
> > > +void
> > > +check_stub_method_group (struct type *type, int method_id)
> > > +{
> > > + int len = TYPE_FN_FIELDLIST_LENGTH (type, method_id);
> > > + struct fn_field *f = TYPE_FN_FIELDLIST1 (type, method_id);
> > > + int j, found_stub;
> > > +
> > > + for (j = 0; j < len; j++)
> > > + if (TYPE_FN_FIELD_STUB (f, j))
> > > + {
> > > + found_stub = 1;
> > > + check_stub_method (type, method_id, j);
> > > + }
> > > +
> > > + /* GNU v3 methods with incorrect names were corrected when we read in
> > > + type information, because it was cheaper to do it then. The only GNU v2
> > > + methods with incorrect method names are operators and destructors;
> > > + destructors were also corrected when we read in type information.
> > > +
> > > + Therefore the only thing we need to handle here are v2 operator
> > > + names. */
> > > + if (found_stub && strncmp (TYPE_FN_FIELD_PHYSNAME (f, 0), "_Z", 2) != 0)
> > > + {
> > > + int ret;
> > > + char dem_opname[256];
> > > +
> > > + ret = cplus_demangle_opname (TYPE_FN_FIELDLIST_NAME (type, method_id),
> > > + dem_opname, DMGL_ANSI);
> > > + if (!ret)
> > > + ret = cplus_demangle_opname (TYPE_FN_FIELDLIST_NAME (type, method_id),
> > > + dem_opname, 0);
> > > + if (ret)
> > > + TYPE_FN_FIELDLIST_NAME (type, method_id) = xstrdup (dem_opname);
> > > + }
> > > +}
> > > +
> > > const struct cplus_struct_type cplus_struct_default;
> > >
> > > void
> > > @@ -3435,6 +3478,120 @@ build_gdbtypes (void)
> > > "__bfd_vma", (struct objfile *) NULL);
> > > }
> > >
> > > +/* Find the last component of the demangled C++ name NAME. NAME
> > > + must be a method name including arguments, in order to correctly
> > > + locate the last component.
> > > +
> > > + This function return a pointer to the first colon before the
> > > + last component, or NULL if the name had only one component. */
> > > +
> > > +static const char *
> > > +find_last_component (const char *name)
> > > +{
> > > + const char *p;
> > > + int depth;
> > > +
> > > + /* Functions can have local classes, so we need to find the
> > > + beginning of the last argument list, not the end of the first
> > > + one. */
> > > + p = name + strlen (name) - 1;
> > > + while (p > name && *p != ')')
> > > + p--;
> > > +
> > > + if (p == name)
> > > + return NULL;
> > > +
> > > + /* P now points at the `)' at the end of the argument list. Walk
> > > + back to the beginning. */
> > > + p--;
> > > + depth = 1;
> > > + while (p > name && depth > 0)
> > > + {
> > > + if (*p == '<' || *p == '(')
> > > + depth--;
> > > + else if (*p == '>' || *p == ')')
> > > + depth++;
> > > + p--;
> > > + }
> > > +
> > > + if (p == name)
> > > + return NULL;
> > > +
> > > + while (p > name && *p != ':')
> > > + p--;
> > > +
> > > + if (p == name || p == name + 1 || p[-1] != ':')
> > > + return NULL;
> > > +
> > > + return p - 1;
> > > +}
> > > +
> > > +/* Return the name of the class containing method PHYSNAME. */
> > > +
> > > +char *
> > > +class_name_from_physname (const char *physname)
> > > +{
> > > + char *ret = NULL;
> > > + const char *end;
> > > + int depth = 0;
> > > + char *demangled_name = cplus_demangle (physname, DMGL_ANSI);
> > > +
> > > + if (demangled_name == NULL)
> > > + return NULL;
> > > +
> > > + end = find_last_component (demangled_name);
> > > + if (end != NULL)
> > > + {
> > > + ret = xmalloc (end - demangled_name + 1);
> > > + memcpy (ret, demangled_name, end - demangled_name);
> > > + ret[end - demangled_name] = '\0';
> > > + }
> > > +
> > > + xfree (demangled_name);
> > > + return ret;
> > > +}
> > > +
> > > +/* Return the name of the method whose linkage name is PHYSNAME. */
> > > +
> > > +char *
> > > +method_name_from_physname (const char *physname)
> > > +{
> > > + char *ret = NULL;
> > > + const char *end;
> > > + int depth = 0;
> > > + char *demangled_name = cplus_demangle (physname, DMGL_ANSI);
> > > +
> > > + if (demangled_name == NULL)
> > > + return NULL;
> > > +
> > > + end = find_last_component (demangled_name);
> > > + if (end != NULL)
> > > + {
> > > + char *args;
> > > + int len;
> > > +
> > > + /* Skip "::". */
> > > + end = end + 2;
> > > +
> > > + /* Find the argument list, if any. */
> > > + args = strchr (end, '(');
> > > + if (args == NULL)
> > > + len = strlen (end + 2);
> > > + else
> > > + {
> > > + args --;
> > > + while (*args == ' ')
> > > + args --;
> > > + len = args - end + 1;
> > > + }
> > > + ret = xmalloc (len + 1);
> > > + memcpy (ret, end, len);
> > > + ret[len] = 0;
> > > + }
> > > +
> > > + xfree (demangled_name);
> > > + return ret;
> > > +}
> > >
> > > extern void _initialize_gdbtypes (void);
> > > void
> > > Index: gdbtypes.h
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/gdbtypes.h,v
> > > retrieving revision 1.35
> > > diff -u -p -r1.35 gdbtypes.h
> > > --- gdbtypes.h 10 Aug 2002 05:12:40 -0000 1.35
> > > +++ gdbtypes.h 10 Sep 2002 16:35:16 -0000
> > > @@ -1124,11 +1124,15 @@ extern struct type *check_typedef (struc
> > >
> > > #define CHECK_TYPEDEF(TYPE) (TYPE) = check_typedef (TYPE)
> > >
> > > -extern void check_stub_method (struct type *, int, int);
> > > +extern void check_stub_method_group (struct type *, int);
> > >
> > > extern struct type *lookup_primitive_typename (char *);
> > >
> > > extern char *gdb_mangle_name (struct type *, int, int);
> > > +
> > > +extern char *class_name_from_physname (const char *physname);
> > > +
> > > +extern char *method_name_from_physname (const char *physname);
> > >
> > > extern struct type *builtin_type (char **);
> > >
> > > Index: p-valprint.c
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/p-valprint.c,v
> > > retrieving revision 1.13
> > > diff -u -p -r1.13 p-valprint.c
> > > --- p-valprint.c 19 Aug 2002 13:12:09 -0000 1.13
> > > +++ p-valprint.c 10 Sep 2002 16:35:16 -0000
> > > @@ -620,13 +620,11 @@ pascal_object_print_class_method (char *
> > > f = TYPE_FN_FIELDLIST1 (domain, i);
> > > len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
> > >
> > > + check_stub_method_group (domain, i);
> > > for (j = 0; j < len2; j++)
> > > {
> > > - QUIT;
> > > if (TYPE_FN_FIELD_VOFFSET (f, j) == offset)
> > > {
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (domain, i, j);
> > > kind = "virtual ";
> > > goto common;
> > > }
> > > @@ -646,15 +644,11 @@ pascal_object_print_class_method (char *
> > > f = TYPE_FN_FIELDLIST1 (domain, i);
> > > len2 = TYPE_FN_FIELDLIST_LENGTH (domain, i);
> > >
> > > + check_stub_method_group (domain, i);
> > > for (j = 0; j < len2; j++)
> > > {
> > > - QUIT;
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (domain, i, j);
> > > if (STREQ (SYMBOL_NAME (sym), TYPE_FN_FIELD_PHYSNAME (f, j)))
> > > - {
> > > - goto common;
> > > - }
> > > + goto common;
> > > }
> > > }
> > > }
> > > Index: stabsread.c
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/stabsread.c,v
> > > retrieving revision 1.38
> > > diff -u -p -r1.38 stabsread.c
> > > --- stabsread.c 1 Aug 2002 17:18:32 -0000 1.38
> > > +++ stabsread.c 10 Sep 2002 16:35:17 -0000
> > > @@ -44,6 +44,7 @@
> > > #include "demangle.h"
> > > #include "language.h"
> > > #include "doublest.h"
> > > +#include "cp-abi.h"
> > >
> > > #include <ctype.h>
> > >
> > > @@ -3080,6 +3081,27 @@ rs6000_builtin_type (int typenum)
> > >
> > > /* This page contains subroutines of read_type. */
> > >
> > > +/* Replace *OLD_NAME with the method name portion of PHYSNAME. */
> > > +
> > > +static void
> > > +update_method_name_from_physname (char **old_name, char *physname)
> > > +{
> > > + char *method_name;
> > > +
> > > + method_name = method_name_from_physname (physname);
> > > +
> > > + if (method_name == NULL)
> > > + error ("bad physname %s\n", physname);
> > > +
> > > + if (strcmp (*old_name, method_name) != 0)
> > > + {
> > > + xfree (*old_name);
> > > + *old_name = method_name;
> > > + }
> > > + else
> > > + xfree (method_name);
> > > +}
> > > +
> > > /* Read member function stabs info for C++ classes. The form of each member
> > > function data is:
> > >
> > > @@ -3377,6 +3399,164 @@ read_member_functions (struct field_info
> > > }
> > > else
> > > {
> > > + int has_stub = 0;
> > > + int has_destructor = 0, has_other = 0;
> > > + int is_v3 = 0;
> > > + struct next_fnfield *tmp_sublist;
> > > +
> > > + /* Various versions of GCC emit various mostly-useless
> > > + strings in the name field for special member functions.
> > > +
> > > + For stub methods, we need to defer correcting the name
> > > + until we are ready to unstub the method, because the current
> > > + name string is used by gdb_mangle_name. The only stub methods
> > > + of concern here are GNU v2 operators; other methods have their
> > > + names correct (see caveat below).
> > > +
> > > + For non-stub methods, in GNU v3, we have a complete physname.
> > > + Therefore we can safely correct the name now. This primarily
> > > + affects constructors and destructors, whose name will be
> > > + __comp_ctor or __comp_dtor instead of Foo or ~Foo. Cast
> > > + operators will also have incorrect names; for instance,
> > > + "operator int" will be named "operator i" (i.e. the type is
> > > + mangled).
> > > +
> > > + For non-stub methods in GNU v2, we have no easy way to
> > > + know if we have a complete physname or not. For most
> > > + methods the result depends on the platform (if CPLUS_MARKER
> > > + can be `$' or `.', it will use minimal debug information, or
> > > + otherwise the full physname will be included).
> > > +
> > > + Rather than dealing with this, we take a different approach.
> > > + For v3 mangled names, we can use the full physname; for v2,
> > > + we use cplus_demangle_opname (which is actually v2 specific),
> > > + because the only interesting names are all operators - once again
> > > + barring the caveat below. Skip this process if any method in the
> > > + group is a stub, to prevent our fouling up the workings of
> > > + gdb_mangle_name.
> > > +
> > > + The caveat: GCC 2.95.x (and earlier?) put constructors and
> > > + destructors in the same method group. We need to split this
> > > + into two groups, because they should have different names.
> > > + So for each method group we check whether it contains both
> > > + routines whose physname appears to be a destructor (the physnames
> > > + for and destructors are always provided, due to quirks in v2
> > > + mangling) and routines whose physname does not appear to be a
> > > + destructor. If so then we break up the list into two halves.
> > > + Even if the constructors and destructors aren't in the same group
> > > + the destructor will still lack the leading tilde, so that also
> > > + needs to be fixed.
> > > +
> > > + So, to summarize what we expect and handle here:
> > > +
> > > + Given Given Real Real Action
> > > + method name physname physname method name
> > > +
> > > + __opi [none] __opi__3Foo operator int opname
> > > + [now or later]
> > > + Foo _._3Foo _._3Foo ~Foo separate and
> > > + rename
> > > + operator i _ZN3FoocviEv _ZN3FoocviEv operator int demangle
> > > + __comp_ctor _ZN3FooC1ERKS_ _ZN3FooC1ERKS_ Foo demangle
> > > + */
> > > +
> > > + tmp_sublist = sublist;
> > > + while (tmp_sublist != NULL)
> > > + {
> > > + if (tmp_sublist->fn_field.is_stub)
> > > + has_stub = 1;
> > > + if (tmp_sublist->fn_field.physname[0] == '_'
> > > + && tmp_sublist->fn_field.physname[1] == 'Z')
> > > + is_v3 = 1;
> > > +
> > > + if (is_destructor_name (tmp_sublist->fn_field.physname))
> > > + has_destructor++;
> > > + else
> > > + has_other++;
> > > +
> > > + tmp_sublist = tmp_sublist->next;
> > > + }
> > > +
> > > + if (has_destructor && has_other)
> > > + {
> > > + struct next_fnfieldlist *destr_fnlist;
> > > + struct next_fnfield *last_sublist;
> > > +
> > > + /* Create a new fn_fieldlist for the destructors. */
> > > +
> > > + destr_fnlist = (struct next_fnfieldlist *)
> > > + xmalloc (sizeof (struct next_fnfieldlist));
> > > + make_cleanup (xfree, destr_fnlist);
> > > + memset (destr_fnlist, 0, sizeof (struct next_fnfieldlist));
> > > + destr_fnlist->fn_fieldlist.name
> > > + = obconcat (&objfile->type_obstack, "", "~",
> > > + new_fnlist->fn_fieldlist.name);
> > > +
> > > + destr_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
> > > + obstack_alloc (&objfile->type_obstack,
> > > + sizeof (struct fn_field) * has_destructor);
> > > + memset (destr_fnlist->fn_fieldlist.fn_fields, 0,
> > > + sizeof (struct fn_field) * has_destructor);
> > > + tmp_sublist = sublist;
> > > + last_sublist = NULL;
> > > + i = 0;
> > > + while (tmp_sublist != NULL)
> > > + {
> > > + if (!is_destructor_name (tmp_sublist->fn_field.physname))
> > > + {
> > > + tmp_sublist = tmp_sublist->next;
> > > + continue;
> > > + }
> > > +
> > > + destr_fnlist->fn_fieldlist.fn_fields[i++]
> > > + = tmp_sublist->fn_field;
> > > + if (last_sublist)
> > > + last_sublist->next = tmp_sublist->next;
> > > + else
> > > + sublist = tmp_sublist->next;
> > > + last_sublist = tmp_sublist;
> > > + tmp_sublist = tmp_sublist->next;
> > > + }
> > > +
> > > + destr_fnlist->fn_fieldlist.length = has_destructor;
> > > + destr_fnlist->next = fip->fnlist;
> > > + fip->fnlist = destr_fnlist;
> > > + nfn_fields++;
> > > + total_length += has_destructor;
> > > + length -= has_destructor;
> > > + }
> > > + else if (is_v3)
> > > + {
> > > + /* v3 mangling prevents the use of abbreviated physnames,
> > > + so we can do this here. There are stubbed methods in v3
> > > + only:
> > > + - in -gstabs instead of -gstabs+
> > > + - or for static methods, which are output as a function type
> > > + instead of a method type. */
> > > +
> > > + update_method_name_from_physname (&new_fnlist->fn_fieldlist.name,
> > > + sublist->fn_field.physname);
> > > + }
> > > + else if (has_destructor && new_fnlist->fn_fieldlist.name[0] != '~')
> > > + {
> > > + new_fnlist->fn_fieldlist.name = concat ("~", main_fn_name, NULL);
> > > + xfree (main_fn_name);
> > > + }
> > > + else if (!has_stub)
> > > + {
> > > + char dem_opname[256];
> > > + int ret;
> > > + ret = cplus_demangle_opname (new_fnlist->fn_fieldlist.name,
> > > + dem_opname, DMGL_ANSI);
> > > + if (!ret)
> > > + ret = cplus_demangle_opname (new_fnlist->fn_fieldlist.name,
> > > + dem_opname, 0);
> > > + if (ret)
> > > + new_fnlist->fn_fieldlist.name
> > > + = obsavestring (dem_opname, strlen (dem_opname),
> > > + &objfile->type_obstack);
> > > + }
> > > +
> > > new_fnlist->fn_fieldlist.fn_fields = (struct fn_field *)
> > > obstack_alloc (&objfile->type_obstack,
> > > sizeof (struct fn_field) * length);
> > > Index: valops.c
> > > ===================================================================
> > > RCS file: /cvs/src/src/gdb/valops.c,v
> > > retrieving revision 1.69
> > > diff -u -p -r1.69 valops.c
> > > --- valops.c 21 Aug 2002 17:24:31 -0000 1.69
> > > +++ valops.c 10 Sep 2002 16:35:18 -0000
> > > @@ -2302,12 +2302,11 @@ search_struct_method (char *name, struct
> > > struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
> > > name_matched = 1;
> > >
> > > + check_stub_method_group (type, i);
> > > if (j > 0 && args == 0)
> > > error ("cannot resolve overloaded method `%s': no arguments supplied", name);
> > > else if (j == 0 && args == 0)
> > > {
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (type, i, j);
> > > v = value_fn_field (arg1p, f, j, type, offset);
> > > if (v != NULL)
> > > return v;
> > > @@ -2315,8 +2314,6 @@ search_struct_method (char *name, struct
> > > else
> > > while (j >= 0)
> > > {
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (type, i, j);
> > > if (!typecmp (TYPE_FN_FIELD_STATIC_P (f, j),
> > > TYPE_VARARGS (TYPE_FN_FIELD_TYPE (f, j)),
> > > TYPE_NFIELDS (TYPE_FN_FIELD_TYPE (f, j)),
> > > @@ -2555,20 +2552,15 @@ find_method_list (struct value **argp, c
> > > char *fn_field_name = TYPE_FN_FIELDLIST_NAME (type, i);
> > > if (fn_field_name && (strcmp_iw (fn_field_name, method) == 0))
> > > {
> > > - /* Resolve any stub methods. */
> > > int len = TYPE_FN_FIELDLIST_LENGTH (type, i);
> > > struct fn_field *f = TYPE_FN_FIELDLIST1 (type, i);
> > > - int j;
> > >
> > > *num_fns = len;
> > > *basetype = type;
> > > *boffset = offset;
> > >
> > > - for (j = 0; j < len; j++)
> > > - {
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (type, i, j);
> > > - }
> > > + /* Resolve any stub methods. */
> > > + check_stub_method_group (type, i);
> > >
> > > return f;
> > > }
> > > @@ -3094,6 +3086,8 @@ value_struct_elt_for_reference (struct t
> > > int j = TYPE_FN_FIELDLIST_LENGTH (t, i);
> > > struct fn_field *f = TYPE_FN_FIELDLIST1 (t, i);
> > >
> > > + check_stub_method_group (t, i);
> > > +
> > > if (intype == 0 && j > 1)
> > > error ("non-unique member `%s' requires type instantiation", name);
> > > if (intype)
> > > @@ -3107,8 +3101,6 @@ value_struct_elt_for_reference (struct t
> > > else
> > > j = 0;
> > >
> > > - if (TYPE_FN_FIELD_STUB (f, j))
> > > - check_stub_method (t, i, j);
> > > if (TYPE_FN_FIELD_VIRTUAL_P (f, j))
> > > {
> > > return value_from_longest
> >
>
> --
> Daniel Jacobowitz
> MontaVista Software Debian GNU/Linux Developer