aboutsummaryrefslogtreecommitdiff
path: root/gdb/cp-support.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/cp-support.c')
-rw-r--r--gdb/cp-support.c289
1 files changed, 187 insertions, 102 deletions
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index ecda4a5..9f39b5a 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1,5 +1,5 @@
/* Helper routines for C++ support in GDB.
- Copyright 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by MontaVista Software.
@@ -35,9 +35,10 @@
#include "complaints.h"
#include "gdbtypes.h"
-/* Functions related to demangled name parsing. */
+#define d_left(dc) (dc)->u.s_binary.left
+#define d_right(dc) (dc)->u.s_binary.right
-static const char *find_last_component (const char *name);
+/* Functions related to demangled name parsing. */
static unsigned int cp_find_first_component_aux (const char *name,
int permissive);
@@ -71,78 +72,76 @@ struct cmd_list_element *maint_cplus_cmd_list = NULL;
static void maint_cplus_command (char *arg, int from_tty);
static void first_component_command (char *arg, int from_tty);
-/* Here are some random pieces of trivia to keep in mind while trying
- to take apart demangled names:
+/* Return the canonicalized form of STRING, or NULL if STRING can not be
+ parsed. The return value is allocated via xmalloc.
- - Names can contain function arguments or templates, so the process
- has to be, to some extent recursive: maybe keep track of your
- depth based on encountering <> and ().
+ drow/2005-03-07: Should we also return NULL for things that trivially do
+ not require any change? e.g. simple identifiers. This could be more
+ efficient. */
- - Parentheses don't just have to happen at the end of a name: they
- can occur even if the name in question isn't a function, because
- a template argument might be a type that's a function.
+char *
+cp_canonicalize_string (const char *string)
+{
+ void *storage;
+ struct demangle_component *ret_comp;
+ char *ret;
+ int len = strlen (string);
- - Conversely, even if you're trying to deal with a function, its
- demangled name might not end with ')': it could be a const or
- volatile class method, in which case it ends with "const" or
- "volatile".
+ len = len + len / 8;
- - Parentheses are also used in anonymous namespaces: a variable
- 'foo' in an anonymous namespace gets demangled as "(anonymous
- namespace)::foo".
+ ret_comp = cp_demangled_name_to_comp (string, &storage, NULL);
+ if (ret_comp == NULL)
+ return NULL;
- - And operator names can contain parentheses or angle brackets. */
+ ret = cp_comp_to_string (ret_comp, len);
-/* FIXME: carlton/2003-03-13: We have several functions here with
- overlapping functionality; can we combine them? Also, do they
- handle all the above considerations correctly? */
+ xfree (storage);
-/* 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.
+ return ret;
+}
- This function return a pointer to the first colon before the
- last component, or NULL if the name had only one component. */
+/* Convert a mangled name to a demangle_component tree. *MEMORY is set to the
+ block of used memory that should be freed when finished with the tree.
+ DEMANGLED_P is set to the char * that should be freed when finished with
+ the tree, or NULL if none was needed. OPTIONS will be passed to the
+ demangler. */
-static const char *
-find_last_component (const char *name)
+static struct demangle_component *
+mangled_name_to_comp (const char *mangled_name, int options,
+ void **memory, char **demangled_p)
{
- 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;
+ struct demangle_component *ret;
+ char *demangled_name;
+ int len;
- /* 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 it looks like a v3 mangled name, then try to go directly
+ to trees. */
+ if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
{
- if (*p == '<' || *p == '(')
- depth--;
- else if (*p == '>' || *p == ')')
- depth++;
- p--;
+ ret = cplus_demangle_v3_components (mangled_name, options, memory);
+ if (ret)
+ {
+ *demangled_p = NULL;
+ return ret;
+ }
}
- if (p == name)
- return NULL;
-
- while (p > name && *p != ':')
- p--;
+ /* If it doesn't, or if that failed, then try to demangle the name. */
+ demangled_name = cplus_demangle (mangled_name, options);
+ if (demangled_name == NULL)
+ return NULL;
+
+ /* If we could demangle the name, parse it to build the component tree. */
+ ret = cp_demangled_name_to_comp (demangled_name, memory, NULL);
- if (p == name || p == name + 1 || p[-1] != ':')
- return NULL;
+ if (ret == NULL)
+ {
+ free (demangled_name);
+ return NULL;
+ }
- return p - 1;
+ *demangled_p = demangled_name;
+ return ret;
}
/* Return the name of the class containing method PHYSNAME. */
@@ -150,23 +149,66 @@ find_last_component (const char *name)
char *
cp_class_name_from_physname (const char *physname)
{
- char *ret = NULL;
- const char *end;
- int depth = 0;
- char *demangled_name = cplus_demangle (physname, DMGL_ANSI | DMGL_PARAMS);
-
- if (demangled_name == NULL)
+ void *storage;
+ char *demangled_name = NULL, *ret;
+ struct demangle_component *ret_comp, *prev_comp;
+ int done;
+
+ ret_comp = mangled_name_to_comp (physname, DMGL_ANSI, &storage,
+ &demangled_name);
+ if (ret_comp == NULL)
return NULL;
- end = find_last_component (demangled_name);
- if (end != NULL)
+ done = 0;
+ prev_comp = NULL;
+ 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:
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ 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:
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ prev_comp = NULL;
+ ret_comp = NULL;
+ break;
+ }
+
+ ret = NULL;
+ if (prev_comp != NULL)
{
- ret = xmalloc (end - demangled_name + 1);
- memcpy (ret, demangled_name, end - demangled_name);
- ret[end - demangled_name] = '\0';
+ *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);
}
- xfree (demangled_name);
+ xfree (storage);
+ if (demangled_name)
+ xfree (demangled_name);
return ret;
}
@@ -175,42 +217,85 @@ cp_class_name_from_physname (const char *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 | DMGL_PARAMS);
-
- if (demangled_name == NULL)
+ 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;
- end = find_last_component (demangled_name);
- if (end != NULL)
- {
- char *args;
- int len;
+ done = 0;
+ 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_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;
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_CTOR:
+ case DEMANGLE_COMPONENT_DTOR:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ done = 1;
+ break;
+ default:
+ done = 1;
+ ret_comp = NULL;
+ break;
+ }
+
+ ret = NULL;
+ if (ret_comp != NULL)
+ /* The ten is completely arbitrary; we don't have a good estimate. */
+ ret = cp_comp_to_string (ret_comp, 10);
+
+ xfree (storage);
+ if (demangled_name)
+ xfree (demangled_name);
+ return ret;
+}
- /* Skip "::". */
- end = end + 2;
+/* Here are some random pieces of trivia to keep in mind while trying
+ to take apart demangled names:
- /* 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;
- }
+ - Names can contain function arguments or templates, so the process
+ has to be, to some extent recursive: maybe keep track of your
+ depth based on encountering <> and ().
+
+ - Parentheses don't just have to happen at the end of a name: they
+ can occur even if the name in question isn't a function, because
+ a template argument might be a type that's a function.
+
+ - Conversely, even if you're trying to deal with a function, its
+ demangled name might not end with ')': it could be a const or
+ volatile class method, in which case it ends with "const" or
+ "volatile".
+
+ - Parentheses are also used in anonymous namespaces: a variable
+ 'foo' in an anonymous namespace gets demangled as "(anonymous
+ namespace)::foo".
+
+ - And operator names can contain parentheses or angle brackets. */
+
+/* FIXME: carlton/2003-03-13: We have several functions here with
+ overlapping functionality; can we combine them? Also, do they
+ handle all the above considerations correctly? */
- xfree (demangled_name);
- return ret;
-}
/* This returns the length of first component of NAME, which should be
the demangled name of a C++ variable/function/method/etc.