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:
parent
7230378dfd
commit
3a93a0c2ef
|
@ -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>
|
2011-08-17 Phil Muldoon <pmuldoon@redhat.com>
|
||||||
Tom Tromey <tromey@redhat.com>
|
Tom Tromey <tromey@redhat.com>
|
||||||
Matt Rice <ratmice@gmail.com>
|
Matt Rice <ratmice@gmail.com>
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include "libiberty.h"
|
#include "libiberty.h"
|
||||||
#include "demangle.h"
|
#include "demangle.h"
|
||||||
#include "cp-support.h"
|
#include "cp-support.h"
|
||||||
|
#include "gdb_assert.h"
|
||||||
|
|
||||||
/* Bison does not make it easy to create a parser without global
|
/* Bison does not make it easy to create a parser without global
|
||||||
state, unfortunately. Here are all the global variables used
|
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 {
|
struct demangle_info {
|
||||||
int used;
|
int used;
|
||||||
struct demangle_info *prev, *next;
|
struct demangle_info *next;
|
||||||
struct demangle_component comps[ALLOC_CHUNK];
|
struct demangle_component comps[ALLOC_CHUNK];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,7 +77,6 @@ d_grab (void)
|
||||||
if (demangle_info->next == NULL)
|
if (demangle_info->next == NULL)
|
||||||
{
|
{
|
||||||
more = malloc (sizeof (struct demangle_info));
|
more = malloc (sizeof (struct demangle_info));
|
||||||
more->prev = demangle_info;
|
|
||||||
more->next = NULL;
|
more->next = NULL;
|
||||||
demangle_info->next = more;
|
demangle_info->next = more;
|
||||||
}
|
}
|
||||||
|
@ -1935,20 +1935,14 @@ yyerror (char *msg)
|
||||||
generally allocate too many components, but the extra memory usage
|
generally allocate too many components, but the extra memory usage
|
||||||
doesn't hurt because the trees are temporary and the storage is
|
doesn't hurt because the trees are temporary and the storage is
|
||||||
reused. More may be allocated later, by d_grab. */
|
reused. More may be allocated later, by d_grab. */
|
||||||
static void
|
static struct demangle_info *
|
||||||
allocate_info (void)
|
allocate_info (void)
|
||||||
{
|
{
|
||||||
if (demangle_info == NULL)
|
struct demangle_info *info = malloc (sizeof (struct demangle_info));
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
demangle_info->used = 0;
|
info->next = NULL;
|
||||||
|
info->used = 0;
|
||||||
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert RESULT to a string. The return value is allocated
|
/* 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);
|
&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,
|
/* 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
|
a structure containing the root of the new tree is returned; it must
|
||||||
call to this function and should not be freed. On error, NULL is
|
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
|
returned, and an error message will be set in *ERRMSG (which does
|
||||||
not need to be freed). */
|
not need to be freed). */
|
||||||
|
|
||||||
struct demangle_component *
|
struct demangle_parse_info *
|
||||||
cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
|
cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
|
||||||
{
|
{
|
||||||
static char errbuf[60];
|
static char errbuf[60];
|
||||||
struct demangle_component *result;
|
struct demangle_parse_info *result;
|
||||||
|
|
||||||
prev_lexptr = lexptr = demangled_name;
|
prev_lexptr = lexptr = demangled_name;
|
||||||
error_lexptr = NULL;
|
error_lexptr = NULL;
|
||||||
global_errmsg = NULL;
|
global_errmsg = NULL;
|
||||||
|
|
||||||
allocate_info ();
|
demangle_info = allocate_info ();
|
||||||
|
|
||||||
|
result = cp_new_demangle_parse_info ();
|
||||||
|
result->info = demangle_info;
|
||||||
|
|
||||||
if (yyparse ())
|
if (yyparse ())
|
||||||
{
|
{
|
||||||
|
@ -1993,10 +2066,11 @@ cp_demangled_name_to_comp (const char *demangled_name, const char **errmsg)
|
||||||
strcat (errbuf, "'");
|
strcat (errbuf, "'");
|
||||||
*errmsg = errbuf;
|
*errmsg = errbuf;
|
||||||
}
|
}
|
||||||
|
cp_demangled_name_parse_free (result);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = global_result;
|
result->tree = global_result;
|
||||||
global_result = NULL;
|
global_result = NULL;
|
||||||
|
|
||||||
return result;
|
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
|
int
|
||||||
main (int argc, char **argv)
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -2055,7 +2143,7 @@ main (int argc, char **argv)
|
||||||
char buf[65536];
|
char buf[65536];
|
||||||
int arg;
|
int arg;
|
||||||
const char *errmsg;
|
const char *errmsg;
|
||||||
struct demangle_component *result;
|
struct demangle_parse_info *result;
|
||||||
|
|
||||||
arg = 1;
|
arg = 1;
|
||||||
if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
|
if (argv[arg] && strcmp (argv[arg], "--debug") == 0)
|
||||||
|
@ -2089,7 +2177,8 @@ main (int argc, char **argv)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
cp_print (result);
|
cp_print (result->tree);
|
||||||
|
cp_demangled_name_parse_free (result);
|
||||||
|
|
||||||
free (str2);
|
free (str2);
|
||||||
if (c)
|
if (c)
|
||||||
|
@ -2108,7 +2197,8 @@ main (int argc, char **argv)
|
||||||
fputc ('\n', stderr);
|
fputc ('\n', stderr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
cp_print (result);
|
cp_print (result->tree);
|
||||||
|
cp_demangled_name_parse_free (result);
|
||||||
putchar ('\n');
|
putchar ('\n');
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
455
gdb/cp-support.c
455
gdb/cp-support.c
|
@ -86,6 +86,47 @@ static const char *operator_tokens[] =
|
||||||
/* new[] and delete[] require special whitespace handling */
|
/* 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
|
/* Return 1 if STRING is clearly already in canonical form. This
|
||||||
function is conservative; things which it does not recognize are
|
function is conservative; things which it does not recognize are
|
||||||
assumed to be non-canonical, and the parser will sort them out
|
assumed to be non-canonical, and the parser will sort them out
|
||||||
|
@ -117,6 +158,355 @@ cp_already_canonical (const char *string)
|
||||||
return 0;
|
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,
|
/* Parse STRING and convert it to canonical form. If parsing fails,
|
||||||
or if STRING is already canonical, return NULL. Otherwise return
|
or if STRING is already canonical, return NULL. Otherwise return
|
||||||
the canonical form. The return value is allocated via xmalloc. */
|
the canonical form. The return value is allocated via xmalloc. */
|
||||||
|
@ -124,19 +514,20 @@ cp_already_canonical (const char *string)
|
||||||
char *
|
char *
|
||||||
cp_canonicalize_string (const char *string)
|
cp_canonicalize_string (const char *string)
|
||||||
{
|
{
|
||||||
struct demangle_component *ret_comp;
|
struct demangle_parse_info *info;
|
||||||
unsigned int estimated_len;
|
unsigned int estimated_len;
|
||||||
char *ret;
|
char *ret;
|
||||||
|
|
||||||
if (cp_already_canonical (string))
|
if (cp_already_canonical (string))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret_comp = cp_demangled_name_to_comp (string, NULL);
|
info = cp_demangled_name_to_comp (string, NULL);
|
||||||
if (ret_comp == NULL)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
estimated_len = strlen (string) * 2;
|
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)
|
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.
|
freed when finished with the tree, or NULL if none was needed.
|
||||||
OPTIONS will be passed to the demangler. */
|
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,
|
mangled_name_to_comp (const char *mangled_name, int options,
|
||||||
void **memory, char **demangled_p)
|
void **memory, char **demangled_p)
|
||||||
{
|
{
|
||||||
struct demangle_component *ret;
|
|
||||||
char *demangled_name;
|
char *demangled_name;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
|
|
||||||
/* If it looks like a v3 mangled name, then try to go directly
|
/* If it looks like a v3 mangled name, then try to go directly
|
||||||
to trees. */
|
to trees. */
|
||||||
if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
|
if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
|
||||||
{
|
{
|
||||||
|
struct demangle_component *ret;
|
||||||
|
|
||||||
ret = cplus_demangle_v3_components (mangled_name,
|
ret = cplus_demangle_v3_components (mangled_name,
|
||||||
options, memory);
|
options, memory);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
info = cp_new_demangle_parse_info ();
|
||||||
|
info->tree = ret;
|
||||||
*demangled_p = NULL;
|
*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
|
/* If we could demangle the name, parse it to build the component
|
||||||
tree. */
|
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);
|
xfree (demangled_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*demangled_p = demangled_name;
|
*demangled_p = demangled_name;
|
||||||
return ret;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the name of the class containing method PHYSNAME. */
|
/* Return the name of the class containing method PHYSNAME. */
|
||||||
|
@ -201,14 +596,16 @@ cp_class_name_from_physname (const char *physname)
|
||||||
void *storage = NULL;
|
void *storage = NULL;
|
||||||
char *demangled_name = NULL, *ret;
|
char *demangled_name = NULL, *ret;
|
||||||
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
|
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
int done;
|
int done;
|
||||||
|
|
||||||
ret_comp = mangled_name_to_comp (physname, DMGL_ANSI,
|
info = mangled_name_to_comp (physname, DMGL_ANSI,
|
||||||
&storage, &demangled_name);
|
&storage, &demangled_name);
|
||||||
if (ret_comp == NULL)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
done = 0;
|
done = 0;
|
||||||
|
ret_comp = info->tree;
|
||||||
|
|
||||||
/* First strip off any qualifiers, if we have a function or
|
/* First strip off any qualifiers, if we have a function or
|
||||||
method. */
|
method. */
|
||||||
|
@ -277,8 +674,8 @@ cp_class_name_from_physname (const char *physname)
|
||||||
}
|
}
|
||||||
|
|
||||||
xfree (storage);
|
xfree (storage);
|
||||||
if (demangled_name)
|
xfree (demangled_name);
|
||||||
xfree (demangled_name);
|
cp_demangled_name_parse_free (info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,13 +745,14 @@ method_name_from_physname (const char *physname)
|
||||||
void *storage = NULL;
|
void *storage = NULL;
|
||||||
char *demangled_name = NULL, *ret;
|
char *demangled_name = NULL, *ret;
|
||||||
struct demangle_component *ret_comp;
|
struct demangle_component *ret_comp;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
|
|
||||||
ret_comp = mangled_name_to_comp (physname, DMGL_ANSI,
|
info = mangled_name_to_comp (physname, DMGL_ANSI,
|
||||||
&storage, &demangled_name);
|
&storage, &demangled_name);
|
||||||
if (ret_comp == NULL)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret_comp = unqualified_name_from_comp (ret_comp);
|
ret_comp = unqualified_name_from_comp (info->tree);
|
||||||
|
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
if (ret_comp != NULL)
|
if (ret_comp != NULL)
|
||||||
|
@ -363,8 +761,8 @@ method_name_from_physname (const char *physname)
|
||||||
ret = cp_comp_to_string (ret_comp, 10);
|
ret = cp_comp_to_string (ret_comp, 10);
|
||||||
|
|
||||||
xfree (storage);
|
xfree (storage);
|
||||||
if (demangled_name)
|
xfree (demangled_name);
|
||||||
xfree (demangled_name);
|
cp_demangled_name_parse_free (info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,17 +777,19 @@ cp_func_name (const char *full_name)
|
||||||
{
|
{
|
||||||
char *ret;
|
char *ret;
|
||||||
struct demangle_component *ret_comp;
|
struct demangle_component *ret_comp;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
|
|
||||||
ret_comp = cp_demangled_name_to_comp (full_name, NULL);
|
info = cp_demangled_name_to_comp (full_name, NULL);
|
||||||
if (!ret_comp)
|
if (!info)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret_comp = unqualified_name_from_comp (ret_comp);
|
ret_comp = unqualified_name_from_comp (info->tree);
|
||||||
|
|
||||||
ret = NULL;
|
ret = NULL;
|
||||||
if (ret_comp != NULL)
|
if (ret_comp != NULL)
|
||||||
ret = cp_comp_to_string (ret_comp, 10);
|
ret = cp_comp_to_string (ret_comp, 10);
|
||||||
|
|
||||||
|
cp_demangled_name_parse_free (info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,16 +802,18 @@ cp_remove_params (const char *demangled_name)
|
||||||
{
|
{
|
||||||
int done = 0;
|
int done = 0;
|
||||||
struct demangle_component *ret_comp;
|
struct demangle_component *ret_comp;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
char *ret = NULL;
|
char *ret = NULL;
|
||||||
|
|
||||||
if (demangled_name == NULL)
|
if (demangled_name == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ret_comp = cp_demangled_name_to_comp (demangled_name, NULL);
|
info = cp_demangled_name_to_comp (demangled_name, NULL);
|
||||||
if (ret_comp == NULL)
|
if (info == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* First strip off any qualifiers, if we have a function or method. */
|
/* First strip off any qualifiers, if we have a function or method. */
|
||||||
|
ret_comp = info->tree;
|
||||||
while (!done)
|
while (!done)
|
||||||
switch (ret_comp->type)
|
switch (ret_comp->type)
|
||||||
{
|
{
|
||||||
|
@ -433,6 +835,7 @@ cp_remove_params (const char *demangled_name)
|
||||||
if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
|
if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
|
||||||
ret = cp_comp_to_string (d_left (ret_comp), 10);
|
ret = cp_comp_to_string (d_left (ret_comp), 10);
|
||||||
|
|
||||||
|
cp_demangled_name_parse_free (info);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,12 @@
|
||||||
/* We need this for 'domain_enum', alas... */
|
/* We need this for 'domain_enum', alas... */
|
||||||
|
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
|
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
#include "gdb_obstack.h"
|
||||||
|
|
||||||
/* Opaque declarations. */
|
/* Opaque declarations. */
|
||||||
|
|
||||||
struct symbol;
|
struct symbol;
|
||||||
struct obstack;
|
|
||||||
struct block;
|
struct block;
|
||||||
struct objfile;
|
struct objfile;
|
||||||
struct type;
|
struct type;
|
||||||
|
@ -46,6 +45,20 @@ struct demangle_component;
|
||||||
|
|
||||||
#define CP_ANONYMOUS_NAMESPACE_LEN 21
|
#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
|
/* This struct is designed to store data from using directives. It
|
||||||
says that names from namespace IMPORT_SRC should be visible within
|
says that names from namespace IMPORT_SRC should be visible within
|
||||||
namespace IMPORT_DEST. These form a linked list; NEXT is the next
|
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 (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 *cp_class_name_from_physname (const char *physname);
|
||||||
|
|
||||||
extern char *method_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. */
|
/* Functions from cp-name-parser.y. */
|
||||||
|
|
||||||
extern struct demangle_component *cp_demangled_name_to_comp
|
extern struct demangle_parse_info *cp_demangled_name_to_comp
|
||||||
(const char *demangled_name, const char **errmsg);
|
(const char *demangled_name, const char **errmsg);
|
||||||
|
|
||||||
extern char *cp_comp_to_string (struct demangle_component *result,
|
extern char *cp_comp_to_string (struct demangle_component *result,
|
||||||
int estimated_len);
|
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. */
|
/* The list of "maint cplus" commands. */
|
||||||
|
|
||||||
extern struct cmd_list_element *maint_cplus_cmd_list;
|
extern struct cmd_list_element *maint_cplus_cmd_list;
|
||||||
|
|
|
@ -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
|
/* NAME is typed by the user: it needs to be canonicalized before
|
||||||
passing to lookup_symbol. */
|
passing to lookup_symbol. */
|
||||||
canon = cp_canonicalize_string (name);
|
canon = cp_canonicalize_string_no_typedefs (name);
|
||||||
if (canon != NULL)
|
if (canon != NULL)
|
||||||
{
|
{
|
||||||
name = canon;
|
name = canon;
|
||||||
|
@ -1365,7 +1365,7 @@ decode_compound (char **argptr, int funfirstline,
|
||||||
char *the_real_saved_arg, char *p)
|
char *the_real_saved_arg, char *p)
|
||||||
{
|
{
|
||||||
struct symtabs_and_lines values;
|
struct symtabs_and_lines values;
|
||||||
char *p2;
|
char *p2, *name, *canon;
|
||||||
char *saved_arg2 = *argptr;
|
char *saved_arg2 = *argptr;
|
||||||
char *temp_end;
|
char *temp_end;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
@ -1373,6 +1373,7 @@ decode_compound (char **argptr, int funfirstline,
|
||||||
struct symbol *sym_class;
|
struct symbol *sym_class;
|
||||||
struct type *t;
|
struct type *t;
|
||||||
char *saved_arg;
|
char *saved_arg;
|
||||||
|
struct cleanup *cleanup;
|
||||||
|
|
||||||
/* If the user specified any completer quote characters in the input,
|
/* If the user specified any completer quote characters in the input,
|
||||||
strip them. They are superfluous. */
|
strip them. They are superfluous. */
|
||||||
|
@ -1597,7 +1598,18 @@ decode_compound (char **argptr, int funfirstline,
|
||||||
*argptr = (*p == '\'') ? p + 1 : p;
|
*argptr = (*p == '\'') ? p + 1 : p;
|
||||||
|
|
||||||
/* Look up entire name. */
|
/* 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)
|
if (sym)
|
||||||
return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
|
return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
|
||||||
else
|
else
|
||||||
|
@ -1743,7 +1755,7 @@ find_method (int funfirstline, struct linespec_result *canonical,
|
||||||
strcpy (name, SYMBOL_NATURAL_NAME (sym_class));
|
strcpy (name, SYMBOL_NATURAL_NAME (sym_class));
|
||||||
strcat (name, "::");
|
strcat (name, "::");
|
||||||
strcat (name, copy);
|
strcat (name, copy);
|
||||||
canon = cp_canonicalize_string (name);
|
canon = cp_canonicalize_string_no_typedefs (name);
|
||||||
if (canon != NULL)
|
if (canon != NULL)
|
||||||
{
|
{
|
||||||
xfree (name);
|
xfree (name);
|
||||||
|
@ -2085,16 +2097,31 @@ decode_variable (char *copy, int funfirstline,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
struct symtab *file_symtab)
|
struct symtab *file_symtab)
|
||||||
{
|
{
|
||||||
|
char *name, *canon;
|
||||||
struct symbol *sym;
|
struct symbol *sym;
|
||||||
|
struct cleanup *cleanup;
|
||||||
struct minimal_symbol *msymbol;
|
struct minimal_symbol *msymbol;
|
||||||
|
|
||||||
sym = lookup_symbol (copy, get_search_block (file_symtab),
|
name = copy;
|
||||||
VAR_DOMAIN, 0);
|
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)
|
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)
|
if (msymbol != NULL)
|
||||||
return minsym_found (funfirstline, msymbol);
|
return minsym_found (funfirstline, msymbol);
|
||||||
|
|
|
@ -577,8 +577,10 @@ typy_legacy_template_argument (struct type *type, struct block *block,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct demangle_component *demangled;
|
struct demangle_component *demangled;
|
||||||
|
struct demangle_parse_info *info;
|
||||||
const char *err;
|
const char *err;
|
||||||
struct type *argtype;
|
struct type *argtype;
|
||||||
|
struct cleanup *cleanup;
|
||||||
|
|
||||||
if (TYPE_NAME (type) == NULL)
|
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. */
|
/* Note -- this is not thread-safe. */
|
||||||
demangled = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
|
info = cp_demangled_name_to_comp (TYPE_NAME (type), &err);
|
||||||
if (! demangled)
|
if (! info)
|
||||||
{
|
{
|
||||||
PyErr_SetString (PyExc_RuntimeError, err);
|
PyErr_SetString (PyExc_RuntimeError, err);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
demangled = info->tree;
|
||||||
|
cleanup = make_cleanup_cp_demangled_name_parse_free (info);
|
||||||
|
|
||||||
/* Strip off component names. */
|
/* Strip off component names. */
|
||||||
while (demangled->type == DEMANGLE_COMPONENT_QUAL_NAME
|
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)
|
if (demangled->type != DEMANGLE_COMPONENT_TEMPLATE)
|
||||||
{
|
{
|
||||||
|
do_cleanups (cleanup);
|
||||||
PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
|
PyErr_SetString (PyExc_RuntimeError, _("Type is not a template."));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -613,12 +618,14 @@ typy_legacy_template_argument (struct type *type, struct block *block,
|
||||||
|
|
||||||
if (! demangled)
|
if (! demangled)
|
||||||
{
|
{
|
||||||
|
do_cleanups (cleanup);
|
||||||
PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
|
PyErr_Format (PyExc_RuntimeError, _("No argument %d in template."),
|
||||||
argno);
|
argno);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
argtype = typy_lookup_type (demangled->u.s_binary.left, block);
|
argtype = typy_lookup_type (demangled->u.s_binary.left, block);
|
||||||
|
do_cleanups (cleanup);
|
||||||
if (! argtype)
|
if (! argtype)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue