RFA: Correct field names for class methods

Daniel Jacobowitz drow@mvista.com
Fri Aug 30 00:14:00 GMT 2002


On Thu, Aug 29, 2002 at 10:48:05PM -0500, Jim Blandy wrote:
> 
> I understand the method code very little, so I have only superficial
> comments.  I'll try to do a more thorough reading next week, if Elena
> doesn't beat me to it.

Thanks.

> 
> Daniel Jacobowitz <drow@mvista.com> writes:
> > @@ -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;
> >  	    }
> >  	}
> >      }
> 
> Not that it matters much, but why are you removing the QUIT from this
> loop?

Exactly... because I moved the check_stub_method outside of the loop,
there is no longer any possible justification to QUIT; there.  It's a
loop of strcmp calls!  If you want, I could add the QUIT in
check_stub_method_group, but I don't think it's necessary.

> > +/* Find the last component of the demangled C++ name NAME.
> > +
> > +   This function return a pointer to the first colon before the
> > +   last component, or NULL if the name had only one component.  */
> 
> Hmm, not every demangled name contains a closing paren.  Shouldn't this
> comment clarify that it only works on demangled method names?

Yes, you're right.  It used to not require the closing paren, and then
I realized unpleasant things about the ways some local inner classes
are mangled.

> > @@ -3377,6 +3378,127 @@ read_member_functions (struct field_info
> >  	}
> >        else
> >  	{
> > +	  int has_stub = 0;
> > +	  int has_nondestructor = 0, has_destructor = 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 some methods, we have a complete physname, so we
> > +	     could fix this up now.  For stub methods we will do this
> > +	     later, in check_stub_method_group.  For non-stub methods,
> > +	     we have no clear way to know whether or not the physname
> > +	     is correct; g++ 2.95.x only reliably emits full physnames
> > +	     for operators which do not start with the method name
> > +	     (constructors, destructors fall in this category; there
> > +	     may be others?).  But for other methods it may or may not
> > +	     emit a full physname depending on the platform (if
> > +	     CPLUS_MARKER can be `$' or `.', it will use minimal debug
> > +	     information, but not otherwise).
> > +
> > +	     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, because the only interesting
> > +	     names are all operators.  Skip if any method in the group
> > +	     is a stub, to prevent our fouling up the workings of
> > +	     gdb_mangle_name.
> > +
> > +	     Another thing that we need to clean up here: GCC 2.95.x
> > +	     puts constructors and destructors in the same group.  We
> > +	     need to split this into two groups.  */
> > +
> > +	  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++;
> > +
> > +	      tmp_sublist = tmp_sublist->next;
> > +	    }
> > +
> > +	  if (has_destructor && has_nondestructor)
> > +	    {
> > +	      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, who 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_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);
> > +	    }
> > +
> 
> Is there any way we could pull this out into a separate function or
> functions?  read_member_functions is bad enough already.

Hmm... I'm not sure.  In particular, when splitting constructors from
destructors it tramples on the function state a bit: fip, nfn_fields,
total_length, length, and new_fnlist.  My usual criterion for breaking
out a function is whether its arguments would make any sense on their
own (outside of the calling function's control flow), and these wouldn't.

-- 
Daniel Jacobowitz
MontaVista Software                         Debian GNU/Linux Developer



More information about the Gdb-patches mailing list