From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 14185 invoked by alias); 10 Sep 2002 22:20:12 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 14178 invoked from network); 10 Sep 2002 22:20:12 -0000 Received: from unknown (HELO crack.them.org) (65.125.64.184) by sources.redhat.com with SMTP; 10 Sep 2002 22:20:12 -0000 Received: from nevyn.them.org ([66.93.61.169] ident=mail) by crack.them.org with asmtp (Exim 3.12 #1 (Debian)) id 17ouIp-000623-00; Tue, 10 Sep 2002 18:20:15 -0500 Received: from drow by nevyn.them.org with local (Exim 3.35 #1 (Debian)) id 17otMs-0001aK-00; Tue, 10 Sep 2002 18:20:22 -0400 Date: Tue, 10 Sep 2002 15:20:00 -0000 From: Daniel Jacobowitz To: Elena Zannoni Cc: gdb-patches@sources.redhat.com Subject: Re: RFA: Correct field names for class methods Message-ID: <20020910222022.GA5819@nevyn.them.org> Mail-Followup-To: Elena Zannoni , gdb-patches@sources.redhat.com References: <20020827031346.GA16591@nevyn.them.org> <15741.12051.396773.949592@localhost.redhat.com> <20020910163610.GA10920@nevyn.them.org> <15742.28309.864077.222180@localhost.redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <15742.28309.864077.222180@localhost.redhat.com> User-Agent: Mutt/1.5.1i X-SW-Source: 2002-09/txt/msg00163.txt.bz2 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. - I'm going to need class_name_from_physname in other parts of GDB; at least in the DWARF-2 reader. 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. > > > > -- > > Daniel Jacobowitz > > MontaVista Software Debian GNU/Linux Developer > > > > 2002-09-10 Daniel Jacobowitz > > > > * 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 > > > > @@ -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