From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11841 invoked by alias); 10 Sep 2002 22:15:36 -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 11833 invoked from network); 10 Sep 2002 22:15:34 -0000 Received: from unknown (HELO localhost.redhat.com) (66.30.197.194) by sources.redhat.com with SMTP; 10 Sep 2002 22:15:34 -0000 Received: by localhost.redhat.com (Postfix, from userid 469) id DDB87106CC; Tue, 10 Sep 2002 18:13:42 -0400 (EDT) From: Elena Zannoni MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Message-ID: <15742.28309.864077.222180@localhost.redhat.com> Date: Tue, 10 Sep 2002 15:15:00 -0000 To: Daniel Jacobowitz Cc: Elena Zannoni , gdb-patches@sources.redhat.com Subject: Re: RFA: Correct field names for class methods In-Reply-To: <20020910163610.GA10920@nevyn.them.org> References: <20020827031346.GA16591@nevyn.them.org> <15741.12051.396773.949592@localhost.redhat.com> <20020910163610.GA10920@nevyn.them.org> X-SW-Source: 2002-09/txt/msg00162.txt.bz2 Daniel Jacobowitz writes: > On Mon, Sep 09, 2002 at 07:30:27PM -0400, Elena Zannoni wrote: > > Daniel Jacobowitz writes: > > > Right now, the "name" field of a method is not always reliable. There's > > > special-cased code all over the linespec, function calling, struct lookup, > > > etc. code to handle this. Among the problems: > > > > > > - v3 stabs emit __comp_ctor etc. > > > - v2 stabs emit constructors and destructors in the same fieldlist > > > - v2 stabs emit mangled operator names > > > > > > This patch does not remove any of the special cases, but renders it > > > all obsolete, to be cleaned up in a forthcoming patch. This will greatly > > > simplify the revised method printing code that I'm working on, a necessary > > > cleanup as we move towards namespace support. It pushes the stabs special > > > casing back into stabs related code as much as practical. > > > > > > Elena, this does a bit of its ugliness in read_member_functions, so I'd like > > > your approval before I go ahead with it. > > > > > > See below. I have some questions and some general comments on the > > structure of the patch. > > > > > > > > Comments, anyone? > > > > > > -- > > > Daniel Jacobowitz > > > MontaVista Software Debian GNU/Linux Developer > > > > > > 2002-08-26 Daniel Jacobowitz > > > > > > * gdbtypes.c (check_stub_method): Make static. > > > (update_method_from_physname, 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". > > > > Makefile? > > Oops, thank you. > > > > > > (read_member_functions): Correct method names for operators > > > and v3 constructors/destructors. Separate v2 constructors and > > > destructors. > > > > > > * cp-valprint.c (cp_print_class_method): Call > > > check_stub_method_group instead of check_stub_method. > > > * 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: 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 27 Aug 2002 02:02:55 -0000 > > > @@ -97,13 +97,12 @@ 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; > > > > Did you mean to leave this QUIT? > > No, it should probably go, for the same reasons as the others. OK. > > > > 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 +128,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 27 Aug 2002 02:02:55 -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,54 @@ check_stub_method (struct type *type, in > > > xfree (demangled_name); > > > } > > > > > > > Could you add some comments about what this function does? > > Actually, since it is used only in stabsread.c, why not move it there? > > I think a lot of this c++ specific stuff really doesn't belong in gdbtypes.c. > > You can move all the new functions, except for check_stub_method_group to > > stabsread.c. They are called from there only. > > update_method_name_from_physname? OK - at first I thought I would need > it in more places but that doesn't seem to be true. DWARF-2 has its > own quirks, but it always gets the method's _name_ right. I'll move it > to stabsread.c and make it static. That even lets me plug the memory > leak. > Yes! could you also pull the other new functions in stabsread.c? They seem to be used there only. > > > +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) > > > + *old_name = method_name; > > > + else > > > + xfree (method_name); > > > +} > > > + > > > > Could you add some comments here too? > > Sure. > > > > > > +void > > > +check_stub_method_group (struct type *type, int method_id) > > > +{ > > > > Did you forget to post a piece of the patch? I don't see the function > > below being called anywhere. > > My ulterior motives are leaking again! I added > class_name_from_physname because it is the exact parallel to > method_name_from_physname, and because I will need it in future > patches. I can hold it till later if you prefer, but I'd rather just > slip it in now. It's a pretty obvious function. If you put it in stabsread.c. > > > > +/* Return the name of the class containing method PHYSNAME. */ > > > + > > > +char * > > > +class_name_from_physname (const char *physname) > > > +{ > > > > Since you are at it, could you insert examples of mangled names, > > physnames, etc in the comment? > > Sure. I wrote up a big table for it and then I even fixed the bug the > table pointed out to me (needed a case to handle just destructors). > ok > > > > > > > + 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_nondestructor++; > > > > Dumb question, but, what is a nondestructor? Maybe a different variable > > name would be a bit more enlightening. > > Anything that isn't a destructor. I've changed it to has_other - is > that clearer? > Yes thanks. > > > + > > > + tmp_sublist = tmp_sublist->next; > > > + } > > > + > > > + if (has_destructor && has_nondestructor) > > > > > > Comments needed, for the c++ challenged. What does it mean to have both > > a destructor and a nondestructor? > > It's explained in the big comment up above; I've clarified the wording. > Basically, what happens is... wait... let me paste the revised comment: > > 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 > 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. > Ahhhh. > > > > > + { > > > + 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; > > > > I am confused. Why is i always 0? Or it isn't? > > Oops! It doesn't really matter, since there's always one destructor > (until we support in-charge/not-in-charge destructors eventually). But > I've fixed that. Should have been i++ below. > > Thanks for all the comments; here's a revised version. > Approved, except for moving the functions to stabsread.c. Elena > -- > 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