PR c++/12266

* cp-name-parser.y (struct demangle_info): Remove unused
	member PREV.
	(d_grab): Likewise.
	(allocate_info): Change return type to struct demangle_info *.
	Always allocate a new demangle_info.
	Remove unused PREV pointer.
	(cp_new_demangle_parse_info): New function.
	(cp_demangled_name_parse_free): New function.
	(do_demangled_name_parse_free_cleanup): New function.
	(make_cleanup_cp_demangled_name_parse_free): New function.
	(cp_demangled_name_to_comp): Change return type to
	struct demangle_parse_info *.
	Allocate a new storage for each call.
	(main): Update usage for cp_demangled_name_to_comp
	API change.
	* cp-support.h (struct demangle_parse_info): New structure.
	(cp_demangled_name_to_comp): Update API change for
	return type.
	(cp_new_demangle_parse_info): Declare.
	(make_cleanup_cp_demangled_name_parse_free): New declaration.
	(cp_demangled_name_parse_free): Declare.
	* cp-support.c (cp_canonicalize_string): Update API
	change for cp_demangled_name_to_comp.
	(mangled_name_to_comp): Likewise.
	Return struct demangle_parse_info, too.
	(cp_class_name_from_physname): Update mangled_name_to_comp
	API change.
	(method_name_from_physname): Likewise.
	(cp_func_name): Update API change for cp_demangled_name_to_comp.
	(cp_remove_params): Likewise.
	* python/py-type.c (typy_legacy_template_argument): Likewise.

	* cp-support.h (cp_canonicalize_string_no_typedefs): Declare.
	(cp_merge_demangle_parse_infos): Declare.
	* cp-support.c (ignore_typedefs): New file global.
	(copy_string_to_obstack): New function.
	(inspect_type): New function.
	(replace_typedefs): New function.
	(replace_typedefs_qualified_name): New function.
	(cp_canonicalize_string_no_typedefs): New function.
	* cp-name-parser.y (cp_merge_demangle_parse_infos): New function.
	(cp_new_demangle__parse_info): Allocate and initialize the obstack.
	* linespec.c (find_methods): Use cp_canonicalize_string_no_typedefs
	instead of cp_canonicalize_string.
	(find_method): Likewise.
	(decode_compound): Before looking up the name, call
	cp_canonicalize_string_no_typedefs.
	(decode_variable): Likewise.
This commit is contained in:
Keith Seitz 2011-08-18 16:17:39 +00:00
parent 7230378dfd
commit 3a93a0c2ef
6 changed files with 665 additions and 62 deletions

View File

@ -1,3 +1,55 @@
2011-08-18 Keith Seitz <keiths@redhat.com>
PR c++/12266
* cp-name-parser.y (struct demangle_info): Remove unused
member PREV.
(d_grab): Likewise.
(allocate_info): Change return type to struct demangle_info *.
Always allocate a new demangle_info.
Remove unused PREV pointer.
(cp_new_demangle_parse_info): New function.
(cp_demangled_name_parse_free): New function.
(do_demangled_name_parse_free_cleanup): New function.
(make_cleanup_cp_demangled_name_parse_free): New function.
(cp_demangled_name_to_comp): Change return type to
struct demangle_parse_info *.
Allocate a new storage for each call.
(main): Update usage for cp_demangled_name_to_comp
API change.
* cp-support.h (struct demangle_parse_info): New structure.
(cp_demangled_name_to_comp): Update API change for
return type.
(cp_new_demangle_parse_info): Declare.
(make_cleanup_cp_demangled_name_parse_free): New declaration.
(cp_demangled_name_parse_free): Declare.
* cp-support.c (cp_canonicalize_string): Update API
change for cp_demangled_name_to_comp.
(mangled_name_to_comp): Likewise.
Return struct demangle_parse_info, too.
(cp_class_name_from_physname): Update mangled_name_to_comp
API change.
(method_name_from_physname): Likewise.
(cp_func_name): Update API change for cp_demangled_name_to_comp.
(cp_remove_params): Likewise.
* python/py-type.c (typy_legacy_template_argument): Likewise.
* cp-support.h (cp_canonicalize_string_no_typedefs): Declare.
(cp_merge_demangle_parse_infos): Declare.
* cp-support.c (ignore_typedefs): New file global.
(copy_string_to_obstack): New function.
(inspect_type): New function.
(replace_typedefs): New function.
(replace_typedefs_qualified_name): New function.
(cp_canonicalize_string_no_typedefs): New function.
* cp-name-parser.y (cp_merge_demangle_parse_infos): New function.
(cp_new_demangle__parse_info): Allocate and initialize the obstack.
* linespec.c (find_methods): Use cp_canonicalize_string_no_typedefs
instead of cp_canonicalize_string.
(find_method): Likewise.
(decode_compound): Before looking up the name, call
cp_canonicalize_string_no_typedefs.
(decode_variable): Likewise.
2011-08-17 Phil Muldoon <pmuldoon@redhat.com>
Tom Tromey <tromey@redhat.com>
Matt Rice <ratmice@gmail.com>

View File

@ -41,6 +41,7 @@
#include "libiberty.h"
#include "demangle.h"
#include "cp-support.h"
#include "gdb_assert.h"
/* Bison does not make it easy to create a parser without global
state, unfortunately. Here are all the global variables used
@ -60,7 +61,7 @@ static const char *lexptr, *prev_lexptr, *error_lexptr, *global_errmsg;
struct demangle_info {
int used;
struct demangle_info *prev, *next;
struct demangle_info *next;
struct demangle_component comps[ALLOC_CHUNK];
};
@ -76,7 +77,6 @@ d_grab (void)
if (demangle_info->next == NULL)
{
more = malloc (sizeof (struct demangle_info));
more->prev = demangle_info;
more->next = NULL;
demangle_info->next = more;
}
@ -1935,20 +1935,14 @@ yyerror (char *msg)
generally allocate too many components, but the extra memory usage
doesn't hurt because the trees are temporary and the storage is
reused. More may be allocated later, by d_grab. */
static void
static struct demangle_info *
allocate_info (void)
{
if (demangle_info == NULL)
{
demangle_info = malloc (sizeof (struct demangle_info));
demangle_info->prev = NULL;
demangle_info->next = NULL;
}
else
while (demangle_info->prev)
demangle_info = demangle_info->prev;
struct demangle_info *info = malloc (sizeof (struct demangle_info));
demangle_info->used = 0;
info->next = NULL;
info->used = 0;
return info;
}
/* Convert RESULT to a string. The return value is allocated
@ -1966,23 +1960,102 @@ cp_comp_to_string (struct demangle_component *result, int estimated_len)
&err);
}
/* A convenience function to allocate and initialize a new struct
demangled_parse_info. */
struct demangle_parse_info *
cp_new_demangle_parse_info (void)
{
struct demangle_parse_info *info;
info = malloc (sizeof (struct demangle_parse_info));
info->info = NULL;
info->tree = NULL;
obstack_init (&info->obstack);
return info;
}
/* Free any memory associated with the given PARSE_INFO. */
void
cp_demangled_name_parse_free (struct demangle_parse_info *parse_info)
{
struct demangle_info *info = parse_info->info;
/* Free any allocated chunks of memory for the parse. */
while (info != NULL)
{
struct demangle_info *next = info->next;
free (info);
info = next;
}
/* Free any memory allocated during typedef replacement. */
obstack_free (&parse_info->obstack, NULL);
/* Free the parser info. */
free (parse_info);
}
/* Merge the two parse trees given by DEST and SRC. The parse tree
in SRC is attached to DEST at the node represented by TARGET.
SRC is then freed.
NOTE 1: Since there is no API to merge obstacks, this function does
even attempt to try it. Fortunately, we do not (yet?) need this ability.
The code will assert if SRC->obstack is not empty.
NOTE 2: The string from which SRC was parsed must not be freed, since
this function will place pointers to that string into DEST. */
void
cp_merge_demangle_parse_infos (struct demangle_parse_info *dest,
struct demangle_component *target,
struct demangle_parse_info *src)
{
struct demangle_info *di;
/* Copy the SRC's parse data into DEST. */
*target = *src->tree;
di = dest->info;
while (di->next != NULL)
di = di->next;
di->next = src->info;
/* Clear the (pointer to) SRC's parse data so that it is not freed when
cp_demangled_parse_info_free is called. */
src->info = NULL;
/* Assert if the SRC obstack is not empty. */
gdb_assert (obstack_empty_p (&src->obstack));
/* Free SRC. */
cp_demangled_name_parse_free (src);
}
/* Convert a demangled name to a demangle_component tree. On success,
the root of the new tree is returned; it is valid until the next
call to this function and should not be freed. On error, NULL is
a structure containing the root of the new tree is returned; it must
be freed by calling cp_demangled_name_parse_free. On error, NULL is
returned, and an error message will be set in *ERRMSG (which does
not need to be freed). */
struct demangle_component *
struct demangle_parse_info *
cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
{
static char errbuf[60];
struct demangle_component *result;
struct demangle_parse_info *result;
prev_lexptr = lexptr = demangled_name;
error_lexptr = NULL;
global_errmsg = NULL;
allocate_info ();
demangle_info = allocate_info ();
result = cp_new_demangle_parse_info ();
result->info = demangle_info;
if (yyparse ())
{
@ -1993,10 +2066,11 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
strcat (errbuf, "'");
*errmsg = errbuf;
}
cp_demangled_name_parse_free (result);
return NULL;
}
result = global_result;
result->tree = global_result;
global_result = NULL;
return result;
@ -2048,6 +2122,20 @@ xfree (void *ptr)
}
}
/* GDB normally defines internal_error itself, but when this file is built
as a standalone program, we must also provide an implementation. */
void
internal_error (const char *file, int line, const char *fmt, ...)
{
va_list ap;
va_start (ap, fmt);
fprintf (stderr, "%s:%d: internal error: ", file, line);
vfprintf (stderr, fmt, ap);
exit (1);
}
int
main (int argc, char **argv)
{
@ -2055,7 +2143,7 @@ main (int argc, char **argv)
char buf[65536];
int arg;
const char *errmsg;
struct demangle_component *result;
struct demangle_parse_info *result;
arg = 1;
if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
@ -2089,7 +2177,8 @@ main (int argc, char **argv)
continue;
}
cp_print (result);
cp_print (result->tree);
cp_demangled_name_parse_free (result);
free (str2);
if (c)
@ -2108,7 +2197,8 @@ main (int argc, char **argv)
fputc ('\n', stderr);
return 0;
}
cp_print (result);
cp_print (result->tree);
cp_demangled_name_parse_free (result);
putchar ('\n');
}
return 0;

View File

@ -86,6 +86,47 @@ static const char *operator_tokens[] =
/* new[] and delete[] require special whitespace handling */
};
/* A list of typedefs which should not be substituted by replace_typedefs. */
static const char * const ignore_typedefs[] =
{
"std::istream", "std::iostream", "std::ostream", "std::string"
};
static void
replace_typedefs (struct demangle_parse_info *info,
struct demangle_component *ret_comp);
/* A convenience function to copy STRING into OBSTACK, returning a pointer
to the newly allocated string and saving the number of bytes saved in LEN.
It does not copy the terminating '\0' byte! */
static char *
copy_string_to_obstack (struct obstack *obstack, const char *string,
long *len)
{
*len = strlen (string);
return obstack_copy (obstack, string, *len);
}
/* A cleanup wrapper for cp_demangled_name_parse_free. */
static void
do_demangled_name_parse_free_cleanup (void *data)
{
struct demangle_parse_info *info = (struct demangle_parse_info *) data;
cp_demangled_name_parse_free (info);
}
/* Create a cleanup for C++ name parsing. */
struct cleanup *
make_cleanup_cp_demangled_name_parse_free (struct demangle_parse_info *info)
{
return make_cleanup (do_demangled_name_parse_free_cleanup, info);
}
/* Return 1 if STRING is clearly already in canonical form. This
function is conservative; things which it does not recognize are
assumed to be non-canonical, and the parser will sort them out
@ -117,6 +158,355 @@ cp_already_canonical (const char *string)
return 0;
}
/* Inspect the given RET_COMP for its type. If it is a typedef,
replace the node with the typedef's tree.
Returns 1 if any typedef substitutions were made, 0 otherwise. */
static int
inspect_type (struct demangle_parse_info *info,
struct demangle_component *ret_comp)
{
int i;
char *name;
struct symbol *sym;
volatile struct gdb_exception except;
/* Copy the symbol's name from RET_COMP and look it up
in the symbol table. */
name = (char *) alloca (ret_comp->u.s_name.len + 1);
memcpy (name, ret_comp->u.s_name.s, ret_comp->u.s_name.len);
name[ret_comp->u.s_name.len] = '\0';
/* Ignore any typedefs that should not be substituted. */
for (i = 0; i < ARRAY_SIZE (ignore_typedefs); ++i)
{
if (strcmp (name, ignore_typedefs[i]) == 0)
return 0;
}
sym = NULL;
TRY_CATCH (except, RETURN_MASK_ALL)
{
sym = lookup_symbol (name, 0, VAR_DOMAIN, 0);
}
if (except.reason >= 0 && sym != NULL)
{
struct type *otype = SYMBOL_TYPE (sym);
/* If the type is a typedef, replace it. */
if (TYPE_CODE (otype) == TYPE_CODE_TYPEDEF)
{
long len;
int is_anon;
struct type *type;
struct demangle_parse_info *i;
struct ui_file *buf;
/* Get the real type of the typedef. */
type = check_typedef (otype);
is_anon = (TYPE_TAG_NAME (type) == NULL
&& (TYPE_CODE (type) == TYPE_CODE_ENUM
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION));
if (is_anon)
{
struct type *last = otype;
/* Find the last typedef for the type. */
while (TYPE_TARGET_TYPE (last) != NULL
&& (TYPE_CODE (TYPE_TARGET_TYPE (last))
== TYPE_CODE_TYPEDEF))
last = TYPE_TARGET_TYPE (last);
/* If there is only one typedef for this anonymous type,
do not substitute it. */
if (type == otype)
return 0;
else
/* Use the last typedef seen as the type for this
anonymous type. */
type = last;
}
buf = mem_fileopen ();
TRY_CATCH (except, RETURN_MASK_ERROR)
{
type_print (type, "", buf, -1);
}
/* If type_print threw an exception, there is little point
in continuing, so just bow out gracefully. */
if (except.reason < 0)
{
ui_file_delete (buf);
return 0;
}
name = ui_file_obsavestring (buf, &info->obstack, &len);
ui_file_delete (buf);
/* Turn the result into a new tree. Note that this
tree will contain pointers into NAME, so NAME cannot
be free'd until all typedef conversion is done and
the final result is converted into a string. */
i = cp_demangled_name_to_comp (name, NULL);
if (i != NULL)
{
/* Merge the two trees. */
cp_merge_demangle_parse_infos (info, ret_comp, i);
/* Replace any newly introduced typedefs -- but not
if the type is anonymous (that would lead to infinite
looping). */
if (!is_anon)
replace_typedefs (info, ret_comp);
}
else
{
/* This shouldn't happen unless the type printer has
output something that the name parser cannot grok.
Nonetheless, an ounce of prevention...
Canonicalize the name again, and store it in the
current node (RET_COMP). */
char *canon = cp_canonicalize_string_no_typedefs (name);
if (canon != NULL)
{
/* Copy the canonicalization into the obstack and
free CANON. */
name = copy_string_to_obstack (&info->obstack, canon, &len);
xfree (canon);
}
ret_comp->u.s_name.s = name;
ret_comp->u.s_name.len = len;
}
return 1;
}
}
return 0;
}
/* Replace any typedefs appearing in the qualified name
(DEMANGLE_COMPONENT_QUAL_NAME) represented in RET_COMP for the name parse
given in INFO. */
static void
replace_typedefs_qualified_name (struct demangle_parse_info *info,
struct demangle_component *ret_comp)
{
long len;
char *name;
struct ui_file *buf = mem_fileopen ();
struct demangle_component *comp = ret_comp;
/* Walk each node of the qualified name, reconstructing the name of
this element. With every node, check for any typedef substitutions.
If a substitution has occurred, replace the qualified name node
with a DEMANGLE_COMPONENT_NAME node representing the new, typedef-
substituted name. */
while (comp->type == DEMANGLE_COMPONENT_QUAL_NAME)
{
if (d_left (comp)->type == DEMANGLE_COMPONENT_NAME)
{
struct demangle_component new;
ui_file_write (buf, d_left (comp)->u.s_name.s,
d_left (comp)->u.s_name.len);
name = ui_file_obsavestring (buf, &info->obstack, &len);
new.type = DEMANGLE_COMPONENT_NAME;
new.u.s_name.s = name;
new.u.s_name.len = len;
if (inspect_type (info, &new))
{
char *n, *s;
long slen;
/* A typedef was substituted in NEW. Convert it to a
string and replace the top DEMANGLE_COMPONENT_QUAL_NAME
node. */
ui_file_rewind (buf);
n = cp_comp_to_string (&new, 100);
if (n == NULL)
{
/* If something went astray, abort typedef substitutions. */
ui_file_delete (buf);
return;
}
s = copy_string_to_obstack (&info->obstack, n, &slen);
xfree (n);
d_left (ret_comp)->type = DEMANGLE_COMPONENT_NAME;
d_left (ret_comp)->u.s_name.s = s;
d_left (ret_comp)->u.s_name.len = slen;
d_right (ret_comp) = d_right (comp);
comp = ret_comp;
continue;
}
}
else
{
/* The current node is not a name, so simply replace any
typedefs in it. Then print it to the stream to continue
checking for more typedefs in the tree. */
replace_typedefs (info, d_left (comp));
name = cp_comp_to_string (d_left (comp), 100);
if (name == NULL)
{
/* If something went astray, abort typedef substitutions. */
ui_file_delete (buf);
return;
}
fputs_unfiltered (name, buf);
xfree (name);
}
ui_file_write (buf, "::", 2);
comp = d_right (comp);
}
/* If the next component is DEMANGLE_COMPONENT_NAME, save the qualified
name assembled above and append the name given by COMP. Then use this
reassembled name to check for a typedef. */
if (comp->type == DEMANGLE_COMPONENT_NAME)
{
ui_file_write (buf, comp->u.s_name.s, comp->u.s_name.len);
name = ui_file_obsavestring (buf, &info->obstack, &len);
/* Replace the top (DEMANGLE_COMPONENT_QUAL_NAME) node
with a DEMANGLE_COMPONENT_NAME node containing the whole
name. */
ret_comp->type = DEMANGLE_COMPONENT_NAME;
ret_comp->u.s_name.s = name;
ret_comp->u.s_name.len = len;
inspect_type (info, ret_comp);
}
else
replace_typedefs (info, comp);
ui_file_delete (buf);
}
/* A function to check const and volatile qualifiers for argument types.
"Parameter declarations that differ only in the presence
or absence of `const' and/or `volatile' are equivalent."
C++ Standard N3290, clause 13.1.3 #4. */
static void
check_cv_qualifiers (struct demangle_component *ret_comp)
{
while (d_left (ret_comp) != NULL
&& (d_left (ret_comp)->type == DEMANGLE_COMPONENT_CONST
|| d_left (ret_comp)->type == DEMANGLE_COMPONENT_VOLATILE))
{
d_left (ret_comp) = d_left (d_left (ret_comp));
}
}
/* Walk the parse tree given by RET_COMP, replacing any typedefs with
their basic types. */
static void
replace_typedefs (struct demangle_parse_info *info,
struct demangle_component *ret_comp)
{
if (ret_comp)
{
switch (ret_comp->type)
{
case DEMANGLE_COMPONENT_ARGLIST:
check_cv_qualifiers (ret_comp);
/* Fall through */
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
case DEMANGLE_COMPONENT_TEMPLATE:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
case DEMANGLE_COMPONENT_TYPED_NAME:
replace_typedefs (info, d_left (ret_comp));
replace_typedefs (info, d_right (ret_comp));
break;
case DEMANGLE_COMPONENT_NAME:
inspect_type (info, ret_comp);
break;
case DEMANGLE_COMPONENT_QUAL_NAME:
replace_typedefs_qualified_name (info, ret_comp);
break;
case DEMANGLE_COMPONENT_LOCAL_NAME:
case DEMANGLE_COMPONENT_CTOR:
case DEMANGLE_COMPONENT_ARRAY_TYPE:
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
replace_typedefs (info, d_right (ret_comp));
break;
case DEMANGLE_COMPONENT_CONST:
case DEMANGLE_COMPONENT_RESTRICT:
case DEMANGLE_COMPONENT_VOLATILE:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_REFERENCE:
replace_typedefs (info, d_left (ret_comp));
break;
default:
break;
}
}
}
/* Parse STRING and convert it to canonical form, resolving any typedefs.
If parsing fails, or if STRING is already canonical, return NULL.
Otherwise return the canonical form. The return value is allocated via
xmalloc. */
char *
cp_canonicalize_string_no_typedefs (const char *string)
{
char *ret;
unsigned int estimated_len;
struct demangle_parse_info *info;
ret = NULL;
estimated_len = strlen (string) * 2;
info = cp_demangled_name_to_comp (string, NULL);
if (info != NULL)
{
/* Replace all the typedefs in the tree. */
replace_typedefs (info, info->tree);
/* Convert the tree back into a string. */
ret = cp_comp_to_string (info->tree, estimated_len);
gdb_assert (ret != NULL);
/* Free the parse information. */
cp_demangled_name_parse_free (info);
/* Finally, compare the original string with the computed
name, returning NULL if they are the same. */
if (strcmp (string, ret) == 0)
{
xfree (ret);
return NULL;
}
}
return ret;
}
/* Parse STRING and convert it to canonical form. If parsing fails,
or if STRING is already canonical, return NULL. Otherwise return
the canonical form. The return value is allocated via xmalloc. */
@ -124,19 +514,20 @@ cp_already_canonical (const char *string)
char *
cp_canonicalize_string (const char *string)
{
struct demangle_component *ret_comp;
struct demangle_parse_info *info;
unsigned int estimated_len;
char *ret;
if (cp_already_canonical (string))
return NULL;
ret_comp = cp_demangled_name_to_comp (string, NULL);
if (ret_comp == NULL)
info = cp_demangled_name_to_comp (string, NULL);
if (info == NULL)
return NULL;
estimated_len = strlen (string) * 2;
ret = cp_comp_to_string (ret_comp, estimated_len);
ret = cp_comp_to_string (info->tree, estimated_len);
cp_demangled_name_parse_free (info);
if (strcmp (string, ret) == 0)
{
@ -153,23 +544,27 @@ cp_canonicalize_string (const char *string)
freed when finished with the tree, or NULL if none was needed.
OPTIONS will be passed to the demangler. */
static struct demangle_component *
static struct demangle_parse_info *
mangled_name_to_comp (const char *mangled_name, int options,
void **memory, char **demangled_p)
{
struct demangle_component *ret;
char *demangled_name;
struct demangle_parse_info *info;
/* If it looks like a v3 mangled name, then try to go directly
to trees. */
if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
{
struct demangle_component *ret;
ret = cplus_demangle_v3_components (mangled_name,
options, memory);
if (ret)
{
info = cp_new_demangle_parse_info ();
info->tree = ret;
*demangled_p = NULL;
return ret;
return info;
}
}
@ -181,16 +576,16 @@ mangled_name_to_comp (const char *mangled_name, int options,
/* If we could demangle the name, parse it to build the component
tree. */
ret = cp_demangled_name_to_comp (demangled_name, NULL);
info = cp_demangled_name_to_comp (demangled_name, NULL);
if (ret == NULL)
if (info == NULL)
{
xfree (demangled_name);
return NULL;
}
*demangled_p = demangled_name;
return ret;
return info;
}
/* Return the name of the class containing method PHYSNAME. */
@ -201,14 +596,16 @@ cp_class_name_from_physname (const char *physname)
void *storage = NULL;
char *demangled_name = NULL, *ret;
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
struct demangle_parse_info *info;
int done;
ret_comp = mangled_name_to_comp (physname, DMGL_ANSI,
&storage, &demangled_name);
if (ret_comp == NULL)
info = mangled_name_to_comp (physname, DMGL_ANSI,
&storage, &demangled_name);
if (info == NULL)
return NULL;
done = 0;
ret_comp = info->tree;
/* First strip off any qualifiers, if we have a function or
method. */
@ -277,8 +674,8 @@ cp_class_name_from_physname (const char *physname)
}
xfree (storage);
if (demangled_name)
xfree (demangled_name);
xfree (demangled_name);
cp_demangled_name_parse_free (info);
return ret;
}
@ -348,13 +745,14 @@ method_name_from_physname (const char *physname)
void *storage = NULL;
char *demangled_name = NULL, *ret;
struct demangle_component *ret_comp;
struct demangle_parse_info *info;
ret_comp = mangled_name_to_comp (physname, DMGL_ANSI,
&storage, &demangled_name);
if (ret_comp == NULL)
info = mangled_name_to_comp (physname, DMGL_ANSI,
&storage, &demangled_name);
if (info == NULL)
return NULL;
ret_comp = unqualified_name_from_comp (ret_comp);
ret_comp = unqualified_name_from_comp (info->tree);
ret = NULL;
if (ret_comp != NULL)
@ -363,8 +761,8 @@ method_name_from_physname (const char *physname)
ret = cp_comp_to_string (ret_comp, 10);
xfree (storage);
if (demangled_name)
xfree (demangled_name);
xfree (demangled_name);
cp_demangled_name_parse_free (info);
return ret;
}
@ -379,17 +777,19 @@ cp_func_name (const char *full_name)
{
char *ret;
struct demangle_component *ret_comp;
struct demangle_parse_info *info;
ret_comp = cp_demangled_name_to_comp (full_name, NULL);
if (!ret_comp)
info = cp_demangled_name_to_comp (full_name, NULL);
if (!info)
return NULL;
ret_comp = unqualified_name_from_comp (ret_comp);
ret_comp = unqualified_name_from_comp (info->tree);
ret = NULL;
if (ret_comp != NULL)
ret = cp_comp_to_string (ret_comp, 10);
cp_demangled_name_parse_free (info);
return ret;
}
@ -402,16 +802,18 @@ cp_remove_params (const char *demangled_name)
{
int done = 0;
struct demangle_component *ret_comp;
struct demangle_parse_info *info;
char *ret = NULL;
if (demangled_name == NULL)
return NULL;
ret_comp = cp_demangled_name_to_comp (demangled_name, NULL);
if (ret_comp == NULL)
info = cp_demangled_name_to_comp (demangled_name, NULL);
if (info == NULL)
return NULL;
/* First strip off any qualifiers, if we have a function or method. */
ret_comp = info->tree;
while (!done)
switch (ret_comp->type)
{
@ -433,6 +835,7 @@ cp_remove_params (const char *demangled_name)
if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
ret = cp_comp_to_string (d_left (ret_comp), 10);
cp_demangled_name_parse_free (info);
return ret;
}

View File

@ -26,13 +26,12 @@
/* We need this for 'domain_enum', alas... */
#include "symtab.h"
#include "vec.h"
#include "gdb_obstack.h"
/* Opaque declarations. */
struct symbol;
struct obstack;
struct block;
struct objfile;
struct type;
@ -46,6 +45,20 @@ struct demangle_component;
#define CP_ANONYMOUS_NAMESPACE_LEN 21
/* The result of parsing a name. */
struct demangle_parse_info
{
/* The memory used during the parse. */
struct demangle_info *info;
/* The result of the parse. */
struct demangle_component *tree;
/* Any temporary memory used during typedef replacement. */
struct obstack obstack;
};
/* This struct is designed to store data from using directives. It
says that names from namespace IMPORT_SRC should be visible within
namespace IMPORT_DEST. These form a linked list; NEXT is the next
@ -134,6 +147,8 @@ struct using_direct
extern char *cp_canonicalize_string (const char *string);
extern char *cp_canonicalize_string_no_typedefs (const char *string);
extern char *cp_class_name_from_physname (const char *physname);
extern char *method_name_from_physname (const char *physname);
@ -214,12 +229,21 @@ struct type *cp_lookup_transparent_type (const char *name);
/* Functions from cp-name-parser.y. */
extern struct demangle_component *cp_demangled_name_to_comp
(const char *demangled_name, const char **errmsg);
extern struct demangle_parse_info *cp_demangled_name_to_comp
(const char *demangled_name, const char **errmsg);
extern char *cp_comp_to_string (struct demangle_component *result,
int estimated_len);
extern void cp_demangled_name_parse_free (struct demangle_parse_info *);
extern struct cleanup *make_cleanup_cp_demangled_name_parse_free
(struct demangle_parse_info *);
extern void cp_merge_demangle_parse_infos (struct demangle_parse_info *,
struct demangle_component *,
struct demangle_parse_info *);
extern struct demangle_parse_info *cp_new_demangle_parse_info (void);
/* The list of "maint cplus" commands. */
extern struct cmd_list_element *maint_cplus_cmd_list;

View File

@ -245,7 +245,7 @@ find_methods (struct type *t, char *name, enum language language,
/* NAME is typed by the user: it needs to be canonicalized before
passing to lookup_symbol. */
canon = cp_canonicalize_string (name);
canon = cp_canonicalize_string_no_typedefs (name);
if (canon != NULL)
{
name = canon;
@ -1365,7 +1365,7 @@ decode_compound (char **argptr, int funfirstline,
char *the_real_saved_arg, char *p)
{
struct symtabs_and_lines values;
char *p2;
char *p2, *name, *canon;
char *saved_arg2 = *argptr;
char *temp_end;
struct symbol *sym;
@ -1373,6 +1373,7 @@ decode_compound (char **argptr, int funfirstline,
struct symbol *sym_class;
struct type *t;
char *saved_arg;
struct cleanup *cleanup;
/* If the user specified any completer quote characters in the input,
strip them. They are superfluous. */
@ -1597,7 +1598,18 @@ decode_compound (char **argptr, int funfirstline,
*argptr = (*p == '\'') ? p + 1 : p;
/* Look up entire name. */
sym = lookup_symbol (copy, get_selected_block (0), VAR_DOMAIN, 0);
name = copy;
cleanup = make_cleanup (null_cleanup, NULL);
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
name = canon;
make_cleanup (xfree, name);
}
sym = lookup_symbol (name, get_selected_block (0), VAR_DOMAIN, 0);
do_cleanups (cleanup);
if (sym)
return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
else
@ -1743,7 +1755,7 @@ find_method (int funfirstline, struct linespec_result *canonical,
strcpy (name, SYMBOL_NATURAL_NAME (sym_class));
strcat (name, "::");
strcat (name, copy);
canon = cp_canonicalize_string (name);
canon = cp_canonicalize_string_no_typedefs (name);
if (canon != NULL)
{
xfree (name);
@ -2085,16 +2097,31 @@ decode_variable (char *copy, int funfirstline,
struct linespec_result *canonical,
struct symtab *file_symtab)
{
char *name, *canon;
struct symbol *sym;
struct cleanup *cleanup;
struct minimal_symbol *msymbol;
sym = lookup_symbol (copy, get_search_block (file_symtab),
VAR_DOMAIN, 0);
name = copy;
cleanup = make_cleanup (null_cleanup, NULL);
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
name = canon;
make_cleanup (xfree, name);
}
sym = lookup_symbol (name, get_search_block (file_symtab), VAR_DOMAIN, 0);
if (sym != NULL)
return symbol_found (funfirstline, canonical, copy, sym, file_symtab, NULL);
{
do_cleanups (cleanup);
return symbol_found (funfirstline, canonical, copy, sym,
file_symtab, NULL);
}
msymbol = lookup_minimal_symbol (copy, NULL, NULL);
msymbol = lookup_minimal_symbol (name, NULL, NULL);
do_cleanups (cleanup);
if (msymbol != NULL)
return minsym_found (funfirstline, msymbol);

View File

@ -577,8 +577,10 @@ typy_legacy_template_argument (struct type *type, struct block *block,
{
int i;
struct demangle_component *demangled;
struct demangle_parse_info *info;
const char *err;
struct type *argtype;
struct cleanup *cleanup;
if (TYPE_NAME (type) == NULL)
{
@ -587,12 +589,14 @@ typy_legacy_template_argument (struct type *type, struct block *block,
}
/* Note -- this is not thread-safe. */
demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
if (! demangled)
info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
if (! info)
{
PyErr_SetString (PyExc_RuntimeError, err);
return NULL;
}
demangled = info->tree;
cleanup = make_cleanup_cp_demangled_name_parse_free (info);
/* Strip off component names. */
while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
@ -601,6 +605,7 @@ typy_legacy_template_argument (struct type *type, struct block *block,
if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
{
do_cleanups (cleanup);
PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
return NULL;
}
@ -613,12 +618,14 @@ typy_legacy_template_argument (struct type *type, struct block *block,
if (! demangled)
{
do_cleanups (cleanup);
PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
argno);
return NULL;
}
argtype = typy_lookup_type (demangled->u.s_binary.left, block);
do_cleanups (cleanup);
if (! argtype)
return NULL;