This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: demangler fixes
- To: gcc-patches at gcc dot gnu dot org
- Subject: C++ PATCH: demangler fixes
- From: Alex Samuel <samuel at codesourcery dot com>
- Date: Wed, 23 Aug 2000 00:37:09 -0700 (PDT)
- Organization: CodeSourcery, LLC
This patch fixes three problems in the new-ABI C++ demangler.
1. The demangler now assumes that mangled constructor names do not
encode a return value, even if the constructor is a member
template.
2. A bug is fixed whereby a mangled name containing a substitution
for a type template name followed by a template argument list was
not being demangled.
3. An extra space is inserted before the opening angle bracket in a
template argument list if necessary to prevent it from mushing
into a previous less-than, as in a templated operator< or
operator<< .
Ok to commit?
In libiberty:
* cp-demangle.c (result_close_template_list): Remove function.
(result_add_separated_char): New function.
(result_open_template_list): New macro.
(result_close_template_list): Likewise.
(demangle_prefix): Don't set template_p if the
prefix ends with a ctor name.
(demangle_type_ptr): Remove duplicate RETURN_IF_ERROR.
(demangle_type): Check for template args after substitution.
(demangle_template_args): Use result_open_template_list.
Index: cp-demangle.c
===================================================================
RCS file: /cvs/gcc/egcs/libiberty/cp-demangle.c,v
retrieving revision 1.13
diff -c -p -r1.13 cp-demangle.c
*** cp-demangle.c 2000/07/23 17:55:13 1.13
--- cp-demangle.c 2000/08/23 07:35:31
*************** static string_list_t string_list_new
*** 196,203 ****
PARAMS ((int));
static void string_list_delete
PARAMS ((string_list_t));
! static status_t result_close_template_list
! PARAMS ((demangling_t));
static status_t result_push
PARAMS ((demangling_t));
static string_list_t result_pop
--- 196,203 ----
PARAMS ((int));
static void string_list_delete
PARAMS ((string_list_t));
! static status_t result_add_separated_char
! PARAMS ((demangling_t, char));
static status_t result_push
PARAMS ((demangling_t));
static string_list_t result_pop
*************** static void demangling_delete
*** 297,302 ****
--- 297,309 ----
(dyn_string_append_space (&(DM)->result->string) \
? STATUS_OK : STATUS_ALLOCATION_FAILED)
+ /* Appends a (less-than, greater-than) character to the result in DM
+ to (open, close) a template argument or parameter list. Appends a
+ space first if necessary to prevent spurious elision of angle
+ brackets with the previous character. */
+ #define result_open_template_list(DM) result_add_separated_char(DM, '<')
+ #define result_close_template_list(DM) result_add_separated_char(DM, '>')
+
/* Appends a base 10 representation of VALUE to DS. STATUS_OK on
success. On failure, deletes DS and returns an error code. */
*************** string_list_delete (node)
*** 378,405 ****
}
}
! /* Appends a greater-than character to the demangled result. If the
! last character is a greater-than character, a space is inserted
! first, so that the two greater-than characters don't look like a
! right shift token. */
static status_t
! result_close_template_list (dm)
demangling_t dm;
{
dyn_string_t s = &dm->result->string;
/* Add a space if the last character is already a closing angle
bracket, so that a nested template arg list doesn't look like
it's closed with a right-shift operator. */
! if (dyn_string_last_char (s) == '>')
{
if (!dyn_string_append_char (s, ' '))
return STATUS_ALLOCATION_FAILED;
}
/* Add closing angle brackets. */
! if (!dyn_string_append_char (s, '>'))
return STATUS_ALLOCATION_FAILED;
return STATUS_OK;
--- 385,411 ----
}
}
! /* Appends CHARACTER to the demangled result. If the current trailing
! character of the result is CHARACTER, a space is inserted first. */
static status_t
! result_add_separated_char (dm, character)
demangling_t dm;
+ char character;
{
dyn_string_t s = &dm->result->string;
/* Add a space if the last character is already a closing angle
bracket, so that a nested template arg list doesn't look like
it's closed with a right-shift operator. */
! if (dyn_string_last_char (s) == character)
{
if (!dyn_string_append_char (s, ' '))
return STATUS_ALLOCATION_FAILED;
}
/* Add closing angle brackets. */
! if (!dyn_string_append_char (s, character))
return STATUS_ALLOCATION_FAILED;
return STATUS_OK;
*************** demangle_prefix (dm, template_p)
*** 1108,1113 ****
--- 1114,1123 ----
int start = substitution_start (dm);
int nested = 0;
+ /* This flag is set to non-zero if the most recent (rightmost)
+ element in the prefix was a constructor. */
+ int last_was_ctor = 0;
+
/* TEMPLATE_P is updated as we decend the nesting chain. After
<template-args>, it is set to non-zero; after everything else it
is set to zero. */
*************** demangle_prefix (dm, template_p)
*** 1124,1129 ****
--- 1134,1148 ----
peek = peek_char (dm);
+ /* We'll initialize last_was_ctor to false, and set it to true
+ if we end up demangling a constructor name. However, make
+ sure we're not actually about to demangle template arguments
+ -- if so, this is the <template-args> following a
+ <template-prefix>, so we'll want the previous flag value
+ around. */
+ if (peek != 'I')
+ last_was_ctor = 0;
+
if (IS_DIGIT ((unsigned char) peek)
|| (peek >= 'a' && peek <= 'z')
|| peek == 'C' || peek == 'D'
*************** demangle_prefix (dm, template_p)
*** 1137,1161 ****
if (peek == 'S')
/* The substitution determines whether this is a
! template-id. */
RETURN_IF_ERROR (demangle_substitution (dm, template_p,
&unused));
else
{
RETURN_IF_ERROR (demangle_unqualified_name (dm));
*template_p = 0;
}
}
else if (peek == 'Z')
RETURN_IF_ERROR (demangle_local_name (dm));
else if (peek == 'I')
{
! if (*template_p)
! return STATUS_INTERNAL_ERROR;
/* The template name is a substitution candidate. */
RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
RETURN_IF_ERROR (demangle_template_args (dm));
! *template_p = 1;
}
else if (peek == 'E')
/* All done. */
--- 1156,1202 ----
if (peek == 'S')
/* The substitution determines whether this is a
! template-id. */
RETURN_IF_ERROR (demangle_substitution (dm, template_p,
&unused));
else
{
+ /* It's just a name. Remember whether it's a
+ constructor. */
RETURN_IF_ERROR (demangle_unqualified_name (dm));
*template_p = 0;
}
+
+ /* If this element was a constructor name, make a note of
+ that. */
+ if (peek == 'C')
+ last_was_ctor = 1;
}
else if (peek == 'Z')
RETURN_IF_ERROR (demangle_local_name (dm));
else if (peek == 'I')
{
! /* If the template flag is already set, this is the second
! set of template args in a row. Something is wrong with
! the mangled name. */
! if (*template_p)
! return "Unexpected second consecutive template args in <prefix>.";
/* The template name is a substitution candidate. */
RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM));
RETURN_IF_ERROR (demangle_template_args (dm));
!
! /* Now we want to indicate to the caller that we've
! demangled template arguments, thus the prefix was a
! <template-prefix>. That's so that the caller knows to
! demangle the function's return type, if this turns out to
! be a function name. */
! if (!last_was_ctor)
! *template_p = 1;
! else
! /* But, if it's a member template constructor, report it
! as untemplated. We don't ever want to demangle the
! return type of a constructor. */
! *template_p = 0;
}
else if (peek == 'E')
/* All done. */
*************** demangle_type_ptr (dm)
*** 1904,1916 ****
}
else
{
! /* No more pointe or reference tokens. Finish up. */
status = demangle_type (dm);
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, symbols);
dyn_string_delete (symbols);
- RETURN_IF_ERROR (status);
RETURN_IF_ERROR (status);
return STATUS_OK;
--- 1945,1956 ----
}
else
{
! /* No more pointer or reference tokens. Finish up. */
status = demangle_type (dm);
if (STATUS_NO_ERROR (status))
status = result_append_string (dm, symbols);
dyn_string_delete (symbols);
RETURN_IF_ERROR (status);
return STATUS_OK;
*************** demangle_type (dm)
*** 2016,2023 ****
or underscore. */
peek_next = peek_char_next (dm);
if (IS_DIGIT (peek_next) || peek_next == '_')
! RETURN_IF_ERROR (demangle_substitution (dm, &template_p,
! &special_std_substitution));
else
demangle_class_enum_type (dm, &template_p);
break;
--- 2056,2072 ----
or underscore. */
peek_next = peek_char_next (dm);
if (IS_DIGIT (peek_next) || peek_next == '_')
! {
! RETURN_IF_ERROR (
! demangle_substitution (dm, &template_p,
! &special_std_substitution));
!
! /* The substituted name may have been a template name.
! Check if template arguments follow, and if so, demangle
! them. */
! if (peek_char (dm) == 'I')
! RETURN_IF_ERROR (demangle_template_args (dm));
! }
else
demangle_class_enum_type (dm, &template_p);
break;
*************** demangle_template_args (dm)
*** 2440,2446 ****
return STATUS_ALLOCATION_FAILED;
RETURN_IF_ERROR (demangle_char (dm, 'I'));
! RETURN_IF_ERROR (result_append_char (dm, '<'));
do
{
string_list_t arg;
--- 2489,2495 ----
return STATUS_ALLOCATION_FAILED;
RETURN_IF_ERROR (demangle_char (dm, 'I'));
! RETURN_IF_ERROR (result_open_template_list (dm));
do
{
string_list_t arg;