In include:

* dyn-string.h: Adjust formatting.
        (dyn_string_insert_char): New macro.  New declaration.

In libiberty:

        * cp-demangle.c (ANONYMOUS_NAMESPACE_PREFIX): New macro.
        (substitution_def): Remove template_parm_number.
        (NOT_TEMPLATE_PARM): Remove.
        (result_insert_string): New macro.
        (result_insert): Likewise.
        (result_insert_char): Likewise.
        (substitution_add): Remove last parameter.  Don't store template
        parm number.
        (BFT_NO_RETURN_TYPE): Define as NULL.
        (demangle_encoding): Adjust call to demangle_bare_function_type.
        (demangle_name): Adjust substitution.  Adjust call to
        substitution_add.
        (demangle_prefix): Adjust call to substitution_add.
        (demangle_identifier): Handle anonymous namespaces.
        (demangle_operator_name): Change demangling of vendor-extended
        operator to match ABI changes.
        (demangle_type_ptr): Change parameters.  Make recursive.  Handle
        substitutions here.
        (demangle_type): Adjust calls to demangle_template_param,
        substitution_add, and demangle_type_ptr.  Fix substitution of
        templated types.
        (demangle_function_type): Change parameter to a pointer.
        (demangle_bare_function_type): Likewise.  Adjust insertion point.
        (demangle_template_param): Remove last parameter.
        (demangle_expr_primary): Remove unused variable.  Adjust call to
        demangle_template_param.
        (is_mangled_char): Accept `$' and `.'.
        * cplus-dem.c (gnu_new_abi_symbol_characters): Add '$' and '.'.
        * dyn-string.c (dyn_string_insert_char): New function.

From-SVN: r36148
This commit is contained in:
Alex Samuel 2000-09-05 01:01:12 +00:00 committed by Alex Samuel
parent c9672d45dc
commit 31e0ab1f76
6 changed files with 286 additions and 148 deletions

View file

@ -1,3 +1,8 @@
2000-09-04 Alex Samuel <samuel@codesourcery.com>
* dyn-string.h: Adjust formatting.
(dyn_string_insert_char): New macro. New declaration.
2000-08-28 Jason Merrill <jason@redhat.com> 2000-08-28 Jason Merrill <jason@redhat.com>
* md5.h: New file. * md5.h: New file.

View file

@ -59,6 +59,7 @@ typedef struct dyn_string
#define dyn_string_prepend_cstr __cxa_dyn_string_prepend_cstr #define dyn_string_prepend_cstr __cxa_dyn_string_prepend_cstr
#define dyn_string_insert __cxa_dyn_string_insert #define dyn_string_insert __cxa_dyn_string_insert
#define dyn_string_insert_cstr __cxa_dyn_string_insert_cstr #define dyn_string_insert_cstr __cxa_dyn_string_insert_cstr
#define dyn_string_insert_char __cxa_dyn_string_insert_char
#define dyn_string_append __cxa_dyn_string_append #define dyn_string_append __cxa_dyn_string_append
#define dyn_string_append_cstr __cxa_dyn_string_append_cstr #define dyn_string_append_cstr __cxa_dyn_string_append_cstr
#define dyn_string_append_char __cxa_dyn_string_append_char #define dyn_string_append_char __cxa_dyn_string_append_char
@ -82,11 +83,10 @@ extern int dyn_string_insert PARAMS ((dyn_string_t, int,
dyn_string_t)); dyn_string_t));
extern int dyn_string_insert_cstr PARAMS ((dyn_string_t, int, extern int dyn_string_insert_cstr PARAMS ((dyn_string_t, int,
const char *)); const char *));
extern int dyn_string_insert_char PARAMS ((dyn_string_t, int, int));
extern int dyn_string_append PARAMS ((dyn_string_t, dyn_string_t)); extern int dyn_string_append PARAMS ((dyn_string_t, dyn_string_t));
extern int dyn_string_append_cstr extern int dyn_string_append_cstr PARAMS ((dyn_string_t, const char *));
PARAMS ((dyn_string_t, const char *)); extern int dyn_string_append_char PARAMS ((dyn_string_t, int));
extern int dyn_string_append_char
PARAMS ((dyn_string_t, int));
extern int dyn_string_substring PARAMS ((dyn_string_t, extern int dyn_string_substring PARAMS ((dyn_string_t,
dyn_string_t, int, int)); dyn_string_t, int, int));
extern int dyn_string_eq PARAMS ((dyn_string_t, dyn_string_t)); extern int dyn_string_eq PARAMS ((dyn_string_t, dyn_string_t));

View file

@ -1,3 +1,35 @@
2000-09-03 Alex Samuel <samuel@codesourcery.com>
* cp-demangle.c (ANONYMOUS_NAMESPACE_PREFIX): New macro.
(substitution_def): Remove template_parm_number.
(NOT_TEMPLATE_PARM): Remove.
(result_insert_string): New macro.
(result_insert): Likewise.
(result_insert_char): Likewise.
(substitution_add): Remove last parameter. Don't store template
parm number.
(BFT_NO_RETURN_TYPE): Define as NULL.
(demangle_encoding): Adjust call to demangle_bare_function_type.
(demangle_name): Adjust substitution. Adjust call to
substitution_add.
(demangle_prefix): Adjust call to substitution_add.
(demangle_identifier): Handle anonymous namespaces.
(demangle_operator_name): Change demangling of vendor-extended
operator to match ABI changes.
(demangle_type_ptr): Change parameters. Make recursive. Handle
substitutions here.
(demangle_type): Adjust calls to demangle_template_param,
substitution_add, and demangle_type_ptr. Fix substitution of
templated types.
(demangle_function_type): Change parameter to a pointer.
(demangle_bare_function_type): Likewise. Adjust insertion point.
(demangle_template_param): Remove last parameter.
(demangle_expr_primary): Remove unused variable. Adjust call to
demangle_template_param.
(is_mangled_char): Accept `$' and `.'.
* cplus-dem.c (gnu_new_abi_symbol_characters): Add '$' and '.'.
* dyn-string.c (dyn_string_insert_char): New function.
2000-08-31 Hans-Peter Nilsson <hp@axis.com> 2000-08-31 Hans-Peter Nilsson <hp@axis.com>
* testsuite/demangle-expected: Add nine tests for * testsuite/demangle-expected: Add nine tests for

View file

@ -62,6 +62,10 @@
(((CHAR) >= 'a' && (CHAR) <= 'z') \ (((CHAR) >= 'a' && (CHAR) <= 'z') \
|| ((CHAR) >= 'A' && (CHAR) <= 'Z')) || ((CHAR) >= 'A' && (CHAR) <= 'Z'))
/* The prefix prepended by GCC to an identifier represnting the
anonymous namespace. */
#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_"
/* If flag_verbose is zero, some simplifications will be made to the /* If flag_verbose is zero, some simplifications will be made to the
output to make it easier to read and supress details that are output to make it easier to read and supress details that are
generally not of interest to the average C++ programmer. generally not of interest to the average C++ programmer.
@ -92,17 +96,10 @@ struct substitution_def
/* The demangled text of the substitution. */ /* The demangled text of the substitution. */
dyn_string_t text; dyn_string_t text;
/* The template parameter that this represents, indexed from zero.
If this is not a template paramter number, the value is
NOT_TEMPLATE_PARM. */
int template_parm_number;
/* Whether this substitution represents a template item. */ /* Whether this substitution represents a template item. */
int template_p : 1; int template_p : 1;
}; };
#define NOT_TEMPLATE_PARM (-1)
/* Data structure representing a template argument list. */ /* Data structure representing a template argument list. */
struct template_arg_list_def struct template_arg_list_def
@ -206,7 +203,7 @@ static string_list_t result_pop
static int substitution_start static int substitution_start
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t substitution_add static status_t substitution_add
PARAMS ((demangling_t, int, int, int)); PARAMS ((demangling_t, int, int));
static dyn_string_t substitution_get static dyn_string_t substitution_get
PARAMS ((demangling_t, int, int *)); PARAMS ((demangling_t, int, int *));
#ifdef CP_DEMANGLE_DEBUG #ifdef CP_DEMANGLE_DEBUG
@ -288,6 +285,22 @@ static void demangling_delete
(dyn_string_append_char (&(DM)->result->string, (CHAR)) \ (dyn_string_append_char (&(DM)->result->string, (CHAR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED) ? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Inserts a dyn_string_t to the demangled result at position POS. */
#define result_insert_string(DM, POS, STRING) \
(dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Inserts NUL-terminated string CSTR to the demangled result at
position POS. */
#define result_insert(DM, POS, CSTR) \
(dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* Inserts character CHAR to the demangled result at position POS. */
#define result_insert_char(DM, POS, CHAR) \
(dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
/* The length of the current demangled result. */ /* The length of the current demangled result. */
#define result_length(DM) \ #define result_length(DM) \
dyn_string_length (&(DM)->result->string) dyn_string_length (&(DM)->result->string)
@ -458,19 +471,13 @@ substitution_start (dm)
/* Adds the suffix of the current demangled result of DM starting at /* Adds the suffix of the current demangled result of DM starting at
START_POSITION as a potential substitution. If TEMPLATE_P is START_POSITION as a potential substitution. If TEMPLATE_P is
non-zero, this potential substitution is a template-id. non-zero, this potential substitution is a template-id. */
If TEMPLATE_PARM_NUMBER is not NOT_TEMPLATE_PARM, the substitution
is for that particular <template-param>, and is distinct from other
otherwise-identical types and other <template-param>s with
different indices. */
static status_t static status_t
substitution_add (dm, start_position, template_p, template_parm_number) substitution_add (dm, start_position, template_p)
demangling_t dm; demangling_t dm;
int start_position; int start_position;
int template_p; int template_p;
int template_parm_number;
{ {
dyn_string_t result = result_string (dm); dyn_string_t result = result_string (dm);
dyn_string_t substitution = dyn_string_new (0); dyn_string_t substitution = dyn_string_new (0);
@ -513,7 +520,6 @@ substitution_add (dm, start_position, template_p, template_parm_number)
i = dm->num_substitutions++; i = dm->num_substitutions++;
dm->substitutions[i].text = substitution; dm->substitutions[i].text = substitution;
dm->substitutions[i].template_p = template_p; dm->substitutions[i].template_p = template_p;
dm->substitutions[i].template_parm_number = template_parm_number;
#ifdef CP_DEMANGLE_DEBUG #ifdef CP_DEMANGLE_DEBUG
substitutions_print (dm, stderr); substitutions_print (dm, stderr);
@ -815,7 +821,7 @@ static status_t demangle_special_name
static status_t demangle_ctor_dtor_name static status_t demangle_ctor_dtor_name
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t demangle_type_ptr static status_t demangle_type_ptr
PARAMS ((demangling_t)); PARAMS ((demangling_t, int *, int));
static status_t demangle_type static status_t demangle_type
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t demangle_CV_qualifiers static status_t demangle_CV_qualifiers
@ -823,15 +829,15 @@ static status_t demangle_CV_qualifiers
static status_t demangle_builtin_type static status_t demangle_builtin_type
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t demangle_function_type static status_t demangle_function_type
PARAMS ((demangling_t, int)); PARAMS ((demangling_t, int *));
static status_t demangle_bare_function_type static status_t demangle_bare_function_type
PARAMS ((demangling_t, int)); PARAMS ((demangling_t, int *));
static status_t demangle_class_enum_type static status_t demangle_class_enum_type
PARAMS ((demangling_t, int *)); PARAMS ((demangling_t, int *));
static status_t demangle_array_type static status_t demangle_array_type
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t demangle_template_param static status_t demangle_template_param
PARAMS ((demangling_t, int *)); PARAMS ((demangling_t));
static status_t demangle_template_args static status_t demangle_template_args
PARAMS ((demangling_t)); PARAMS ((demangling_t));
static status_t demangle_literal static status_t demangle_literal
@ -859,7 +865,7 @@ static status_t cp_demangle_type
/* When passed to demangle_bare_function_type, indicates that the /* When passed to demangle_bare_function_type, indicates that the
function's return type is not encoded before its parameter types. */ function's return type is not encoded before its parameter types. */
#define BFT_NO_RETURN_TYPE -1 #define BFT_NO_RETURN_TYPE NULL
/* Check that the next character is C. If so, consume it. If not, /* Check that the next character is C. If so, consume it. If not,
return an error. */ return an error. */
@ -937,7 +943,7 @@ demangle_encoding (dm)
/* Template functions have their return type encoded. The /* Template functions have their return type encoded. The
return type should be inserted at start_position. */ return type should be inserted at start_position. */
RETURN_IF_ERROR RETURN_IF_ERROR
(demangle_bare_function_type (dm, start_position)); (demangle_bare_function_type (dm, &start_position));
else else
/* Non-template functions don't have their return type /* Non-template functions don't have their return type
encoded. */ encoded. */
@ -974,6 +980,7 @@ demangle_name (dm, template_p)
{ {
int start = substitution_start (dm); int start = substitution_start (dm);
char peek = peek_char (dm); char peek = peek_char (dm);
int is_std_substitution = 0;
DEMANGLE_TRACE ("name", dm); DEMANGLE_TRACE ("name", dm);
@ -998,6 +1005,7 @@ demangle_name (dm, template_p)
(void) next_char (dm); (void) next_char (dm);
RETURN_IF_ERROR (result_append (dm, "std::")); RETURN_IF_ERROR (result_append (dm, "std::"));
RETURN_IF_ERROR (demangle_unqualified_name (dm)); RETURN_IF_ERROR (demangle_unqualified_name (dm));
is_std_substitution = 1;
} }
else else
{ {
@ -1007,11 +1015,11 @@ demangle_name (dm, template_p)
If so, then we just demangled an <unqualified-template-name>. */ If so, then we just demangled an <unqualified-template-name>. */
if (peek_char (dm) == 'I') if (peek_char (dm) == 'I')
{ {
/* The template name is a substitution candidate, unless it /* A template name of the form std::<unqualified-name> is a
was already a back-substitution. */ substitution candidate. */
if (peek != 'S') if (is_std_substitution)
RETURN_IF_ERROR (substitution_add (dm, start, 0, RETURN_IF_ERROR (substitution_add (dm, start, 0));
NOT_TEMPLATE_PARM)); /* Demangle the <template-args> here. */
RETURN_IF_ERROR (demangle_template_args (dm)); RETURN_IF_ERROR (demangle_template_args (dm));
*template_p = 1; *template_p = 1;
} }
@ -1029,8 +1037,7 @@ demangle_name (dm, template_p)
if (peek_char (dm) == 'I') if (peek_char (dm) == 'I')
{ {
/* Add a substitution for the unqualified template name. */ /* Add a substitution for the unqualified template name. */
RETURN_IF_ERROR (substitution_add (dm, start, 0, RETURN_IF_ERROR (substitution_add (dm, start, 0));
NOT_TEMPLATE_PARM));
RETURN_IF_ERROR (demangle_template_args (dm)); RETURN_IF_ERROR (demangle_template_args (dm));
*template_p = 1; *template_p = 1;
@ -1185,8 +1192,7 @@ demangle_prefix (dm, template_p)
if (peek != 'S' if (peek != 'S'
&& peek_char (dm) != 'E') && peek_char (dm) != 'E')
/* Add a new substitution for the prefix thus far. */ /* Add a new substitution for the prefix thus far. */
RETURN_IF_ERROR (substitution_add (dm, start, *template_p, RETURN_IF_ERROR (substitution_add (dm, start, *template_p));
NOT_TEMPLATE_PARM));
} }
} }
@ -1353,6 +1359,29 @@ demangle_identifier (dm, length, identifier)
return STATUS_ALLOCATION_FAILED; return STATUS_ALLOCATION_FAILED;
} }
/* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.'
followed by the source file name and some random characters.
Unless we're in strict mode, decipher these names appropriately. */
if (!flag_strict)
{
char *name = dyn_string_buf (identifier);
int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX);
/* Compare the first, fixed part. */
if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0)
{
name += prefix_length;
/* The next character might be a period, an underscore, or
dollar sign, depending on the target architecture's
assembler's capabilities. After that comes an `N'. */
if ((*name == '.' || *name == '_' || *name == '$')
&& *(name + 1) == 'N')
/* This looks like the anonymous namespace identifier.
Replace it with something comprehensible. */
dyn_string_copy_cstr (identifier, "(anonymous namespace)");
}
}
return STATUS_OK; return STATUS_OK;
} }
@ -1411,7 +1440,7 @@ demangle_identifier (dm, length, identifier)
::= qu # ? ::= qu # ?
::= sz # sizeof ::= sz # sizeof
::= cv <type> # cast ::= cv <type> # cast
::= vx <source-name> # vendor extended operator */ ::= v [0-9] <source-name> # vendor extended operator */
static status_t static status_t
demangle_operator_name (dm, short_name, num_args) demangle_operator_name (dm, short_name, num_args)
@ -1491,10 +1520,10 @@ demangle_operator_name (dm, short_name, num_args)
DEMANGLE_TRACE ("operator-name", dm); DEMANGLE_TRACE ("operator-name", dm);
/* Is this a vendor extended operator? */ /* Is this a vendor-extended operator? */
if (c0 == 'v' && c1 == 'x') if (c0 == 'v' && IS_DIGIT (c1))
{ {
RETURN_IF_ERROR (result_append (dm, "operator")); RETURN_IF_ERROR (result_append (dm, "operator "));
RETURN_IF_ERROR (demangle_source_name (dm)); RETURN_IF_ERROR (demangle_source_name (dm));
*num_args = 0; *num_args = 0;
return STATUS_OK; return STATUS_OK;
@ -1832,6 +1861,19 @@ demangle_ctor_dtor_name (dm)
a pointer to data or pointer to function to construct the right a pointer to data or pointer to function to construct the right
output syntax. C++'s pointer syntax is hairy. output syntax. C++'s pointer syntax is hairy.
This function adds substitution candidates for every nested
pointer/reference type it processes, including the outermost, final
type, assuming the substitution starts at SUBSTITUTION_START in the
demangling result. For example, if this function demangles
`PP3Foo', it will add a substitution for `Foo', `Foo*', and
`Foo**', in that order.
*INSERT_POS is a quantity used internally, when this function calls
itself recursively, to figure out where to insert pointer
punctuation on the way up. On entry to this function, INSERT_POS
should point to a temporary value, but that value need not be
initialized.
<type> ::= P <type> <type> ::= P <type>
::= R <type> ::= R <type>
::= <pointer-to-member-type> ::= <pointer-to-member-type>
@ -1839,104 +1881,131 @@ demangle_ctor_dtor_name (dm)
<pointer-to-member-type> ::= M </class/ type> </member/ type> */ <pointer-to-member-type> ::= M </class/ type> </member/ type> */
static status_t static status_t
demangle_type_ptr (dm) demangle_type_ptr (dm, insert_pos, substitution_start)
demangling_t dm; demangling_t dm;
int *insert_pos;
int substitution_start;
{ {
char next; char next;
status_t status; status_t status;
int is_substitution_candidate = 1;
/* Collect pointer symbols into this string. */
dyn_string_t symbols = dyn_string_new (10);
DEMANGLE_TRACE ("type*", dm); DEMANGLE_TRACE ("type*", dm);
if (symbols == NULL)
return STATUS_ALLOCATION_FAILED;
/* Scan forward, collecting pointers and references into symbols, /* Scan forward, collecting pointers and references into symbols,
until we hit something else. Then emit the type. */ until we hit something else. Then emit the type. */
while (1) next = peek_char (dm);
if (next == 'P')
{ {
next = peek_char (dm); /* A pointer. Snarf the `P'. */
if (next == 'P') advance_char (dm);
{ /* Demangle the underlying type. */
if (!dyn_string_append_char (symbols, '*')) RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
return STATUS_ALLOCATION_FAILED; substitution_start));
advance_char (dm); /* Insert an asterisk where we're told to; it doesn't
} necessarily go at the end. */
else if (next == 'R') RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*'));
{ }
if (!dyn_string_append_char (symbols, '&')) else if (next == 'R')
return STATUS_ALLOCATION_FAILED; {
advance_char (dm); /* A reference. Snarf the `R'. */
} advance_char (dm);
else if (next == 'M') /* Demangle the underlying type. */
{ RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos,
/* Pointer-to-member. */ substitution_start));
dyn_string_t class_type; /* Insert an ampersand where we're told to; it doesn't
necessarily go at the end. */
/* Eat the 'M'. */ RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&'));
advance_char (dm); }
else if (next == 'M')
/* Capture the type of which this is a pointer-to-member. */ {
RETURN_IF_ERROR (result_push (dm)); /* A pointer-to-member. */
RETURN_IF_ERROR (demangle_type (dm)); dyn_string_t class_type;
class_type = (dyn_string_t) result_pop (dm);
/* Eat the 'M'. */
/* Build the pointer-to-member notation. It comes before advance_char (dm);
other pointer and reference qualifiers -- */
if (!dyn_string_prepend_cstr (symbols, "::*")) /* Capture the type of which this is a pointer-to-member. */
return STATUS_ALLOCATION_FAILED; RETURN_IF_ERROR (result_push (dm));
if (!dyn_string_prepend (symbols, class_type)) RETURN_IF_ERROR (demangle_type (dm));
return STATUS_ALLOCATION_FAILED; class_type = (dyn_string_t) result_pop (dm);
dyn_string_delete (class_type);
if (peek_char (dm) == 'F')
if (peek_char (dm) == 'F') /* A pointer-to-member function. We want output along the
continue; lines of `void (C::*) (int, int)'. Demangle the function
type, which would in this case give `void () (int, int)'
/* Demangle the type of the pointed-to member. */ and set *insert_pos to the spot between the first
parentheses. */
status = demangle_type_ptr (dm, insert_pos, substitution_start);
else
{
/* A pointer-to-member variable. Demangle the type of the
pointed-to member. */
status = demangle_type (dm); status = demangle_type (dm);
/* Make it pretty. */ /* Make it pretty. */
if (STATUS_NO_ERROR (status)) if (STATUS_NO_ERROR (status))
status = result_append_space (dm); status = result_append_space (dm);
/* Add the pointer-to-member syntax, and other pointer and /* The pointer-to-member notation (e.g. `C::*') follows the
reference symbols. */ member's type. */
if (STATUS_NO_ERROR (status)) *insert_pos = result_length (dm);
status = result_append_string (dm, symbols);
/* Clean up. */
dyn_string_delete (symbols);
RETURN_IF_ERROR (status);
return STATUS_OK;
} }
else if (next == 'F')
{
/* Ooh, tricky, a pointer-to-function. */
int position = result_length (dm);
status = result_append_char (dm, '(');
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, symbols);
if (STATUS_NO_ERROR (status))
status = result_append_char (dm, ')');
dyn_string_delete (symbols);
RETURN_IF_ERROR (status);
RETURN_IF_ERROR (demangle_function_type (dm, position)); /* Build the pointer-to-member notation. */
return STATUS_OK; if (STATUS_NO_ERROR (status))
} status = result_insert (dm, *insert_pos, "::*");
else if (STATUS_NO_ERROR (status))
{ status = result_insert_string (dm, *insert_pos, class_type);
/* No more pointer or reference tokens. Finish up. */ /* There may be additional levels of (pointer or reference)
status = demangle_type (dm); indirection in this type. If so, the `*' and `&' should be
added after the pointer-to-member notation (e.g. `C::*&' for
a reference to a pointer-to-member of class C). */
*insert_pos += dyn_string_length (class_type) + 3;
if (STATUS_NO_ERROR (status)) /* Clean up. */
status = result_append_string (dm, symbols); dyn_string_delete (class_type);
dyn_string_delete (symbols);
RETURN_IF_ERROR (status); RETURN_IF_ERROR (status);
return STATUS_OK;
}
} }
else if (next == 'F')
{
/* Ooh, tricky, a pointer-to-function. When we demangle the
function type, the return type should go at the very
beginning. */
*insert_pos = result_length (dm);
/* The parentheses indicate this is a function pointer or
reference type. */
RETURN_IF_ERROR (result_append (dm, "()"));
/* Now demangle the function type. The return type will be
inserted before the `()', and the argument list will go after
it. */
RETURN_IF_ERROR (demangle_function_type (dm, insert_pos));
/* We should now have something along the lines of
`void () (int, int)'. The pointer or reference characters
have to inside the first set of parentheses. *insert_pos has
already been updated to point past the end of the return
type. Move it one character over so it points inside the
`()'. */
++(*insert_pos);
}
else
{
/* No more pointer or reference tokens; this is therefore a
pointer to data. Finish up by demangling the underlying
type. */
RETURN_IF_ERROR (demangle_type (dm));
/* The pointer or reference characters follow the underlying
type, as in `int*&'. */
*insert_pos = result_length (dm);
/* Because of the production <type> ::= <substitution>,
demangle_type will already have added the underlying type as
a substitution candidate. Don't do it again. */
is_substitution_candidate = 0;
}
if (is_substitution_candidate)
RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0));
return STATUS_OK;
} }
/* Demangles and emits a <type>. /* Demangles and emits a <type>.
@ -1965,7 +2034,7 @@ demangle_type (dm)
char peek_next; char peek_next;
int template_p = 0; int template_p = 0;
template_arg_list_t old_arg_list = current_template_arg_list (dm); template_arg_list_t old_arg_list = current_template_arg_list (dm);
int template_parm = NOT_TEMPLATE_PARM; int insert_pos;
/* A <type> can be a <substitution>; therefore, this <type> is a /* A <type> can be a <substitution>; therefore, this <type> is a
substitution candidate unless a special condition holds (see substitution candidate unless a special condition holds (see
@ -2040,7 +2109,7 @@ demangle_type (dm)
/* It's either a <template-param> or a /* It's either a <template-param> or a
<template-template-param>. In either case, demangle the <template-template-param>. In either case, demangle the
`T' token first. */ `T' token first. */
RETURN_IF_ERROR (demangle_template_param (dm, &template_parm)); RETURN_IF_ERROR (demangle_template_param (dm));
/* Check for a template argument list; if one is found, it's a /* Check for a template argument list; if one is found, it's a
<template-template-param> ::= <template-param> <template-template-param> ::= <template-param>
@ -2050,8 +2119,7 @@ demangle_type (dm)
/* Add a substitution candidate. The template parameter /* Add a substitution candidate. The template parameter
`T' token is a substitution candidate by itself, `T' token is a substitution candidate by itself,
without the template argument list. */ without the template argument list. */
RETURN_IF_ERROR (substitution_add (dm, start, template_p, RETURN_IF_ERROR (substitution_add (dm, start, template_p));
template_parm));
/* Now demangle the template argument list. */ /* Now demangle the template argument list. */
RETURN_IF_ERROR (demangle_template_args (dm)); RETURN_IF_ERROR (demangle_template_args (dm));
@ -2077,23 +2145,27 @@ demangle_type (dm)
them. */ them. */
if (peek_char (dm) == 'I') if (peek_char (dm) == 'I')
RETURN_IF_ERROR (demangle_template_args (dm)); RETURN_IF_ERROR (demangle_template_args (dm));
else
/* A substitution token is not itself a substitution /* A substitution token is not itself a substitution
candidate. */ candidate. (However, if the substituted template is
is_substitution_candidate = 0; instantiated, the resulting type is.) */
is_substitution_candidate = 0;
} }
else else
/* While the special substitution token itself is not a /* While the special substitution token itself is not a
substitution candidate, the <class-enum-type> is, so substitution candidate, the <class-enum-type> is, so
don't clear is_substitution_candidate. */ don't clear is_substitution_candidate. */
demangle_class_enum_type (dm, &template_p); RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p));
break; break;
case 'P': case 'P':
case 'R': case 'R':
case 'M': case 'M':
RETURN_IF_ERROR (demangle_type_ptr (dm)); RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start));
/* demangle_type_ptr adds all applicable substitution
candidates. */
is_substitution_candidate = 0;
break; break;
case 'C': case 'C':
@ -2111,7 +2183,7 @@ demangle_type (dm)
break; break;
case 'U': case 'U':
/* Vendor extended type qualifier. */ /* Vendor-extended type qualifier. */
advance_char (dm); advance_char (dm);
RETURN_IF_ERROR (demangle_source_name (dm)); RETURN_IF_ERROR (demangle_source_name (dm));
RETURN_IF_ERROR (result_append_char (dm, ' ')); RETURN_IF_ERROR (result_append_char (dm, ' '));
@ -2127,7 +2199,7 @@ demangle_type (dm)
<template-param>, pass its index since from the point of <template-param>, pass its index since from the point of
substitutions; a <template-param> token is a substitution substitutions; a <template-param> token is a substitution
candidate distinct from the type that is substituted for it. */ candidate distinct from the type that is substituted for it. */
RETURN_IF_ERROR (substitution_add (dm, start, template_p, template_parm)); RETURN_IF_ERROR (substitution_add (dm, start, template_p));
/* Pop off template argument lists added during mangling of this /* Pop off template argument lists added during mangling of this
type. */ type. */
@ -2266,16 +2338,18 @@ demangle_CV_qualifiers (dm, qualifiers)
} }
} }
/* Demangles and emits a <function-type> FUNCTION_NAME_POS is the /* Demangles and emits a <function-type>. *FUNCTION_NAME_POS is the
position in the result string of the start of the function position in the result string of the start of the function
identifier, at which the function's return type will be inserted. identifier, at which the function's return type will be inserted;
*FUNCTION_NAME_POS is updated to position past the end of the
function's return type.
<function-type> ::= F [Y] <bare-function-type> E */ <function-type> ::= F [Y] <bare-function-type> E */
static status_t static status_t
demangle_function_type (dm, function_name_pos) demangle_function_type (dm, function_name_pos)
demangling_t dm; demangling_t dm;
int function_name_pos; int *function_name_pos;
{ {
DEMANGLE_TRACE ("function-type", dm); DEMANGLE_TRACE ("function-type", dm);
RETURN_IF_ERROR (demangle_char (dm, 'F')); RETURN_IF_ERROR (demangle_char (dm, 'F'));
@ -2301,7 +2375,7 @@ demangle_function_type (dm, function_name_pos)
static status_t static status_t
demangle_bare_function_type (dm, return_type_pos) demangle_bare_function_type (dm, return_type_pos)
demangling_t dm; demangling_t dm;
int return_type_pos; int *return_type_pos;
{ {
/* Sequence is the index of the current function parameter, counting /* Sequence is the index of the current function parameter, counting
from zero. The value -1 denotes the return type. */ from zero. The value -1 denotes the return type. */
@ -2326,10 +2400,16 @@ demangle_bare_function_type (dm, return_type_pos)
/* Add a space to the end of the type. Insert the return /* Add a space to the end of the type. Insert the return
type where we've been asked to. */ type where we've been asked to. */
if (!dyn_string_append_space (return_type) if (!dyn_string_append_space (return_type))
|| !dyn_string_insert (result_string (dm), return_type_pos,
return_type))
status = STATUS_ALLOCATION_FAILED; status = STATUS_ALLOCATION_FAILED;
if (STATUS_NO_ERROR (status))
{
if (!dyn_string_insert (result_string (dm), *return_type_pos,
return_type))
status = STATUS_ALLOCATION_FAILED;
else
*return_type_pos += dyn_string_length (return_type);
}
dyn_string_delete (return_type); dyn_string_delete (return_type);
RETURN_IF_ERROR (status); RETURN_IF_ERROR (status);
@ -2436,16 +2516,14 @@ demangle_array_type (dm)
return STATUS_OK; return STATUS_OK;
} }
/* Demangles and emits a <template-param>. The zero-indexed position /* Demangles and emits a <template-param>.
in the parameter list is placed in *TEMPLATE_PARM_NUMBER.
<template-param> ::= T_ # first template parameter <template-param> ::= T_ # first template parameter
::= T <parameter-2 number> _ */ ::= T <parameter-2 number> _ */
static status_t static status_t
demangle_template_param (dm, template_parm_number) demangle_template_param (dm)
demangling_t dm; demangling_t dm;
int *template_parm_number;
{ {
int parm_number; int parm_number;
template_arg_list_t current_arg_list = current_template_arg_list (dm); template_arg_list_t current_arg_list = current_template_arg_list (dm);
@ -2475,7 +2553,6 @@ demangle_template_param (dm, template_parm_number)
return "Template parameter number out of bounds."; return "Template parameter number out of bounds.";
RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg)); RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg));
*template_parm_number = parm_number;
return STATUS_OK; return STATUS_OK;
} }
@ -2784,12 +2861,11 @@ demangle_expr_primary (dm)
demangling_t dm; demangling_t dm;
{ {
char peek = peek_char (dm); char peek = peek_char (dm);
int unused;
DEMANGLE_TRACE ("expr-primary", dm); DEMANGLE_TRACE ("expr-primary", dm);
if (peek == 'T') if (peek == 'T')
RETURN_IF_ERROR (demangle_template_param (dm, &unused)); RETURN_IF_ERROR (demangle_template_param (dm));
else if (peek == 'L') else if (peek == 'L')
{ {
/* Consume the `L'. */ /* Consume the `L'. */
@ -2826,7 +2902,7 @@ demangle_expr_primary (dm)
::= So # ::std::basic_ostream<char, ::= So # ::std::basic_ostream<char,
std::char_traits<char> > std::char_traits<char> >
::= Sd # ::std::basic_iostream<char, ::= Sd # ::std::basic_iostream<char,
std::char_traits<char> > std::char_traits<char> >
*/ */
static status_t static status_t
@ -3297,7 +3373,8 @@ static void print_usage
/* Non-zero if CHAR is a character than can occur in a mangled name. */ /* Non-zero if CHAR is a character than can occur in a mangled name. */
#define is_mangled_char(CHAR) \ #define is_mangled_char(CHAR) \
(IS_ALPHA (CHAR) || IS_DIGIT (CHAR) || (CHAR) == '_') (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \
|| (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$')
/* The name of this program, as invoked. */ /* The name of this program, as invoked. */
const char* program_name; const char* program_name;

View file

@ -4853,7 +4853,7 @@ hp_symbol_characters ()
static const char * static const char *
gnu_new_abi_symbol_characters () gnu_new_abi_symbol_characters ()
{ {
return "_"; return "_$.";
} }

View file

@ -305,6 +305,30 @@ dyn_string_insert_cstr (dest, pos, src)
return 1; return 1;
} }
/* Inserts character C into DEST starting at position POS. DEST is
expanded as necessary. Returns 1 on success. On failure,
RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */
int
dyn_string_insert_char (dest, pos, c)
dyn_string_t dest;
int pos;
int c;
{
int i;
if (dyn_string_resize (dest, dest->length + 1) == NULL)
return 0;
/* Make room for the insertion. Be sure to copy the NUL. */
for (i = dest->length; i >= pos; --i)
dest->s[i + 1] = dest->s[i];
/* Add the new character. */
dest->s[pos] = c;
/* Compute the new length. */
++dest->length;
return 1;
}
/* Append S to DS, resizing DS if necessary. Returns 1 on success. /* Append S to DS, resizing DS if necessary. Returns 1 on success.
On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and
returns 0. */ returns 0. */