[commit] Remove more ad-hoc C++ name parsing

Daniel Jacobowitz drow@false.org
Sat Mar 26 22:02:00 GMT 2005


I promised David Carlton last February that I would remove cp_func_name's
parsing in place of my unified name parser; this patch finally gets around
to it.  I did the same for remove_params, and I reimplemented the existing
functions after some more thorough unit testing.  It turns out that the name
parser, and the v3 demangler, generate different hierarchies in some
important cases; for instance, the parser generates template nodes whose
left branch is just a name, but the demangler puts the entire qualified name
subtree under the template.  So a little more care is needed when trying to
break the tree apart.

This leaves only cp_find_first_componenet_len as an ad-hoc name parser.  It
has a lot of users; they'll all need some adjustment before it can be
removed.  Project for another rainy day.

Checked in after testing on i686-pc-linux-gnu.

-- 
Daniel Jacobowitz
CodeSourcery, LLC

2005-03-26  Daniel Jacobowitz  <dan@codesourcery.com>

	* cp-support.c (cp_class_name_from_physname): Rewrite.
	(unqualified_name_from_comp): New function, broken out from
	method_name_from_physname.  Correct handling for typed names
	and templates.
	(method_name_from_physname): Use unqualified_name_from_comp.
	(cp_func_name, remove_params): Move earlier in the file.  Add
	better comments.  Use the component tree to parse the name.
	(_initialize_cp_support): Remove stray whitespace.

Index: cp-support.c
===================================================================
RCS file: /cvs/src/src/gdb/cp-support.c,v
retrieving revision 1.19
diff -u -p -r1.19 cp-support.c
--- cp-support.c	11 Mar 2005 02:24:22 -0000	1.19
+++ cp-support.c	26 Mar 2005 21:53:59 -0000
@@ -51,8 +51,6 @@ static int sym_return_val_size;
 static int sym_return_val_index;
 static struct symbol **sym_return_val;
 
-static char *remove_params (const char *demangled_name);
-
 static void overload_list_add_symbol (struct symbol *sym,
 				      const char *oload_name);
 
@@ -151,7 +149,7 @@ cp_class_name_from_physname (const char 
 {
   void *storage;
   char *demangled_name = NULL, *ret;
-  struct demangle_component *ret_comp, *prev_comp;
+  struct demangle_component *ret_comp, *prev_comp, *cur_comp;
   int done;
 
   ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
@@ -160,19 +158,11 @@ cp_class_name_from_physname (const char 
     return NULL;
 
   done = 0;
-  prev_comp = NULL;
+
+  /* First strip off any qualifiers, if we have a function or method.  */
   while (!done)
     switch (ret_comp->type)
       {
-      case DEMANGLE_COMPONENT_TYPED_NAME:
-	prev_comp = NULL;
-        ret_comp = d_right (ret_comp);
-        break;
-      case DEMANGLE_COMPONENT_QUAL_NAME:
-      case DEMANGLE_COMPONENT_LOCAL_NAME:
-	prev_comp = ret_comp;
-        ret_comp = d_right (ret_comp);
-        break;
       case DEMANGLE_COMPONENT_CONST:
       case DEMANGLE_COMPONENT_RESTRICT:
       case DEMANGLE_COMPONENT_VOLATILE:
@@ -180,11 +170,38 @@ cp_class_name_from_physname (const char 
       case DEMANGLE_COMPONENT_RESTRICT_THIS:
       case DEMANGLE_COMPONENT_VOLATILE_THIS:
       case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
-	prev_comp = NULL;
         ret_comp = d_left (ret_comp);
         break;
-      case DEMANGLE_COMPONENT_NAME:
+      default:
+	done = 1;
+	break;
+      }
+
+  /* If what we have now is a function, discard the argument list.  */
+  if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+    ret_comp = d_left (ret_comp);
+
+  /* If what we have now is a template, strip off the template
+     arguments.  The left subtree may be a qualified name.  */
+  if (ret_comp->type == DEMANGLE_COMPONENT_TEMPLATE)
+    ret_comp = d_left (ret_comp);
+
+  /* What we have now should be a name, possibly qualified.  Additional
+     qualifiers could live in the left subtree or the right subtree.  Find
+     the last piece.  */
+  done = 0;
+  prev_comp = NULL;
+  cur_comp = ret_comp;
+  while (!done)
+    switch (cur_comp->type)
+      {
+      case DEMANGLE_COMPONENT_QUAL_NAME:
+      case DEMANGLE_COMPONENT_LOCAL_NAME:
+	prev_comp = cur_comp;
+        cur_comp = d_right (cur_comp);
+        break;
       case DEMANGLE_COMPONENT_TEMPLATE:
+      case DEMANGLE_COMPONENT_NAME:
       case DEMANGLE_COMPONENT_CTOR:
       case DEMANGLE_COMPONENT_DTOR:
       case DEMANGLE_COMPONENT_OPERATOR:
@@ -193,17 +210,17 @@ cp_class_name_from_physname (const char 
 	break;
       default:
 	done = 1;
-	prev_comp = NULL;
-	ret_comp = NULL;
+	cur_comp = NULL;
 	break;
       }
 
   ret = NULL;
-  if (prev_comp != NULL)
+  if (cur_comp != NULL && prev_comp != NULL)
     {
+      /* We want to discard the rightmost child of PREV_COMP.  */
       *prev_comp = *d_left (prev_comp);
       /* The ten is completely arbitrary; we don't have a good estimate.  */
-      ret = cp_comp_to_string (prev_comp, 10);
+      ret = cp_comp_to_string (ret_comp, 10);
     }
 
   xfree (storage);
@@ -212,30 +229,33 @@ cp_class_name_from_physname (const char 
   return ret;
 }
 
-/* Return the name of the method whose linkage name is PHYSNAME.  */
+/* Return the child of COMP which is the basename of a method, variable,
+   et cetera.  All scope qualifiers are discarded, but template arguments
+   will be included.  The component tree may be modified.  */
 
-char *
-method_name_from_physname (const char *physname)
+static struct demangle_component *
+unqualified_name_from_comp (struct demangle_component *comp)
 {
-  void *storage;
-  char *demangled_name = NULL, *ret;
-  struct demangle_component *ret_comp;
+  struct demangle_component *ret_comp = comp, *last_template;
   int done;
 
-  ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
-				   &demangled_name);
-  if (ret_comp == NULL)
-    return NULL;
-
   done = 0;
+  last_template = NULL;
   while (!done)
     switch (ret_comp->type)
       {
       case DEMANGLE_COMPONENT_QUAL_NAME:
       case DEMANGLE_COMPONENT_LOCAL_NAME:
-      case DEMANGLE_COMPONENT_TYPED_NAME:
         ret_comp = d_right (ret_comp);
         break;
+      case DEMANGLE_COMPONENT_TYPED_NAME:
+        ret_comp = d_left (ret_comp);
+        break;
+      case DEMANGLE_COMPONENT_TEMPLATE:
+	gdb_assert (last_template == NULL);
+	last_template = ret_comp;
+	ret_comp = d_left (ret_comp);
+	break;
       case DEMANGLE_COMPONENT_CONST:
       case DEMANGLE_COMPONENT_RESTRICT:
       case DEMANGLE_COMPONENT_VOLATILE:
@@ -246,7 +266,6 @@ method_name_from_physname (const char *p
         ret_comp = d_left (ret_comp);
         break;
       case DEMANGLE_COMPONENT_NAME:
-      case DEMANGLE_COMPONENT_TEMPLATE:
       case DEMANGLE_COMPONENT_CTOR:
       case DEMANGLE_COMPONENT_DTOR:
       case DEMANGLE_COMPONENT_OPERATOR:
@@ -254,11 +273,36 @@ method_name_from_physname (const char *p
 	done = 1;
 	break;
       default:
-	done = 1;
-	ret_comp = NULL;
+	return NULL;
 	break;
       }
 
+  if (last_template)
+    {
+      d_left (last_template) = ret_comp;
+      return last_template;
+    }
+
+  return ret_comp;
+}
+
+/* Return the name of the method whose linkage name is PHYSNAME.  */
+
+char *
+method_name_from_physname (const char *physname)
+{
+  void *storage;
+  char *demangled_name = NULL, *ret;
+  struct demangle_component *ret_comp;
+  int done;
+
+  ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
+				   &demangled_name);
+  if (ret_comp == NULL)
+    return NULL;
+
+  ret_comp = unqualified_name_from_comp (ret_comp);
+
   ret = NULL;
   if (ret_comp != NULL)
     /* The ten is completely arbitrary; we don't have a good estimate.  */
@@ -270,6 +314,79 @@ method_name_from_physname (const char *p
   return ret;
 }
 
+/* If FULL_NAME is the demangled name of a C++ function (including an
+   arg list, possibly including namespace/class qualifications),
+   return a new string containing only the function name (without the
+   arg list/class qualifications).  Otherwise, return NULL.  The
+   caller is responsible for freeing the memory in question.  */
+
+char *
+cp_func_name (const char *full_name)
+{
+  void *storage;
+  char *ret;
+  struct demangle_component *ret_comp;
+  int done;
+
+  ret_comp = cp_demangled_name_to_comp (full_name, &storage, NULL);
+  if (!ret_comp)
+    return NULL;
+
+  ret_comp = unqualified_name_from_comp (ret_comp);
+
+  ret = NULL;
+  if (ret_comp != NULL)
+    ret = cp_comp_to_string (ret_comp, 10);
+
+  xfree (storage);
+  return ret;
+}
+
+/* DEMANGLED_NAME is the name of a function, including parameters and
+   (optionally) a return type.  Return the name of the function without
+   parameters or return type, or NULL if we can not parse the name.  */
+
+static char *
+remove_params (const char *demangled_name)
+{
+  int done = 0;
+  struct demangle_component *ret_comp;
+  void *storage;
+  char *ret = NULL;
+
+  if (demangled_name == NULL)
+    return NULL;
+
+  ret_comp = cp_demangled_name_to_comp (demangled_name, &storage, NULL);
+  if (ret_comp == NULL)
+    return NULL;
+
+  /* First strip off any qualifiers, if we have a function or method.  */
+  while (!done)
+    switch (ret_comp->type)
+      {
+      case DEMANGLE_COMPONENT_CONST:
+      case DEMANGLE_COMPONENT_RESTRICT:
+      case DEMANGLE_COMPONENT_VOLATILE:
+      case DEMANGLE_COMPONENT_CONST_THIS:
+      case DEMANGLE_COMPONENT_RESTRICT_THIS:
+      case DEMANGLE_COMPONENT_VOLATILE_THIS:
+      case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+        ret_comp = d_left (ret_comp);
+        break;
+      default:
+	done = 1;
+	break;
+      }
+
+  /* What we have now should be a function.  Return its name.  */
+  if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+    ret = cp_comp_to_string (d_left (ret_comp), 10);
+
+  xfree (storage);
+  return ret;
+}
+
 /* Here are some random pieces of trivia to keep in mind while trying
    to take apart demangled names:
 
@@ -479,78 +596,8 @@ cp_entire_prefix_len (const char *name)
   return previous_len;
 }
 
-/* If FULL_NAME is the demangled name of a C++ function (including an
-   arg list, possibly including namespace/class qualifications),
-   return a new string containing only the function name (without the
-   arg list/class qualifications).  Otherwise, return NULL.  The
-   caller is responsible for freeing the memory in question.  */
-
-char *
-cp_func_name (const char *full_name)
-{
-  const char *previous_component = full_name;
-  const char *next_component;
-
-  if (!full_name)
-    return NULL;
-
-  for (next_component = (previous_component
-			 + cp_find_first_component (previous_component));
-       *next_component == ':';
-       next_component = (previous_component
-			 + cp_find_first_component (previous_component)))
-    {
-      /* Skip '::'.  */
-      previous_component = next_component + 2;
-    }
-
-  return remove_params (previous_component);
-}
-
 /* Overload resolution functions.  */
 
-static char *
-remove_params (const char *demangled_name)
-{
-  const char *argp;
-  char *new_name;
-  int depth;
-
-  if (demangled_name == NULL)
-    return NULL;
-
-  /* First find the end of the arg list.  */
-  argp = strrchr (demangled_name, ')');
-  if (argp == NULL)
-    return NULL;
-
-  /* Back up to the beginning.  */
-  depth = 1;
-
-  while (argp-- > demangled_name)
-    {
-      if (*argp == ')')
-	depth ++;
-      else if (*argp == '(')
-	{
-	  depth --;
-
-	  if (depth == 0)
-	    break;
-	}
-    }
-  if (depth != 0)
-    internal_error (__FILE__, __LINE__,
-		    _("bad demangled name %s\n"), demangled_name);
-  while (argp[-1] == ' ' && argp > demangled_name)
-    argp --;
-
-  new_name = xmalloc (argp - demangled_name + 1);
-  memcpy (new_name, demangled_name, argp - demangled_name);
-  new_name[argp - demangled_name] = '\0';
-  return new_name;
-}
-
 /* Test to see if SYM is a symbol that we haven't seen corresponding
    to a function named OLOAD_NAME.  If so, add it to the current
    completion list. */
@@ -838,5 +885,4 @@ _initialize_cp_support (void)
   add_cmd ("first_component", class_maintenance, first_component_command,
 	   _("Print the first class/namespace component of NAME."),
 	   &maint_cplus_cmd_list);
-		  
 }



More information about the Gdb-patches mailing list