/* Demangler for g++ V3 ABI.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@wasabisystems.com>.
This file is part of the libiberty library, which is part of GCC.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
*/
/* This code implements a demangler for the g++ V3 ABI. The ABI is
/* Next template on the list. */
struct d_print_template *next;
/* This template. */
- const struct demangle_component *template;
+ const struct demangle_component *template_decl;
};
/* A list of type modifiers. This is used while printing. */
case DEMANGLE_COMPONENT_REFTEMP:
printf ("reference temporary\n");
break;
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+ printf ("hidden alias\n");
+ break;
case DEMANGLE_COMPONENT_RESTRICT:
printf ("restrict\n");
break;
case DEMANGLE_COMPONENT_JAVA_CLASS:
case DEMANGLE_COMPONENT_GUARD:
case DEMANGLE_COMPONENT_REFTEMP:
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
case DEMANGLE_COMPONENT_POINTER:
case DEMANGLE_COMPONENT_REFERENCE:
case DEMANGLE_COMPONENT_COMPLEX:
struct demangle_component *
cplus_demangle_mangled_name (struct d_info *di, int top_level)
{
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return NULL;
- if (d_next_char (di) != 'Z')
+ if (! d_check_char (di, 'Z'))
return NULL;
return d_encoding (di, top_level);
}
struct demangle_component *ret;
struct demangle_component **pret;
- if (d_next_char (di) != 'N')
+ if (! d_check_char (di, 'N'))
return NULL;
pret = d_cv_qualifiers (di, &ret, 1);
if (*pret == NULL)
return NULL;
- if (d_next_char (di) != 'E')
+ if (! d_check_char (di, 'E'))
return NULL;
return ret;
::= TF <type>
::= TJ <type>
::= GR <name>
+ ::= GA <encoding>
*/
static struct demangle_component *
d_special_name (struct d_info *di)
{
- char c;
-
di->expansion += 20;
- c = d_next_char (di);
- if (c == 'T')
+ if (d_check_char (di, 'T'))
{
switch (d_next_char (di))
{
offset = d_number (di);
if (offset < 0)
return NULL;
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return NULL;
base_type = cplus_demangle_type (di);
/* We don't display the offset. FIXME: We should display
return NULL;
}
}
- else if (c == 'G')
+ else if (d_check_char (di, 'G'))
{
switch (d_next_char (di))
{
return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
NULL);
+ case 'A':
+ return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
+ d_encoding (di, 0), NULL);
+
default:
return NULL;
}
else if (c == 'v')
{
d_number (di);
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return 0;
d_number (di);
}
else
return 0;
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return 0;
return 1;
else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD)
di->expansion += di->last_name->u.s_string.len;
}
- switch (d_next_char (di))
+ switch (d_peek_char (di))
{
case 'C':
{
enum gnu_v3_ctor_kinds kind;
- switch (d_next_char (di))
+ switch (d_peek_next_char (di))
{
case '1':
kind = gnu_v3_complete_object_ctor;
default:
return NULL;
}
+ d_advance (di, 2);
return d_make_ctor (di, kind, di->last_name);
}
{
enum gnu_v3_dtor_kinds kind;
- switch (d_next_char (di))
+ switch (d_peek_next_char (di))
{
case '0':
kind = gnu_v3_deleting_dtor;
default:
return NULL;
}
+ d_advance (di, 2);
return d_make_dtor (di, kind, di->last_name);
}
{
struct demangle_component *ret;
- if (d_next_char (di) != 'F')
+ if (! d_check_char (di, 'F'))
return NULL;
if (d_peek_char (di) == 'Y')
{
d_advance (di, 1);
}
ret = d_bare_function_type (di, 1);
- if (d_next_char (di) != 'E')
+ if (! d_check_char (di, 'E'))
return NULL;
return ret;
}
-/* <bare-function-type> ::= <type>+ */
+/* <bare-function-type> ::= [J]<type>+ */
static struct demangle_component *
d_bare_function_type (struct d_info *di, int has_return_type)
struct demangle_component *return_type;
struct demangle_component *tl;
struct demangle_component **ptl;
+ char peek;
+
+ /* Detect special qualifier indicating that the first argument
+ is the return type. */
+ peek = d_peek_char (di);
+ if (peek == 'J')
+ {
+ d_advance (di, 1);
+ has_return_type = 1;
+ }
return_type = NULL;
tl = NULL;
ptl = &tl;
while (1)
{
- char peek;
struct demangle_component *type;
peek = d_peek_char (di);
char peek;
struct demangle_component *dim;
- if (d_next_char (di) != 'A')
+ if (! d_check_char (di, 'A'))
return NULL;
peek = d_peek_char (di);
return NULL;
}
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim,
struct demangle_component *mem;
struct demangle_component **pmem;
- if (d_next_char (di) != 'M')
+ if (! d_check_char (di, 'M'))
return NULL;
cl = cplus_demangle_type (di);
g++ does not work that way. g++ treats only the CV-qualified
member function as a substitution source. FIXME. So to work
with g++, we need to pull off the CV-qualifiers here, in order to
- avoid calling add_substitution() in cplus_demangle_type(). */
+ avoid calling add_substitution() in cplus_demangle_type(). But
+ for a CV-qualified member which is not a function, g++ does
+ follow the ABI, so we need to handle that case here by calling
+ d_add_substitution ourselves. */
pmem = d_cv_qualifiers (di, &mem, 1);
if (pmem == NULL)
return NULL;
*pmem = cplus_demangle_type (di);
+ if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ if (! d_add_substitution (di, mem))
+ return NULL;
+ }
+
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
}
{
long param;
- if (d_next_char (di) != 'T')
+ if (! d_check_char (di, 'T'))
return NULL;
if (d_peek_char (di) == '_')
param += 1;
}
- if (d_next_char (di) != '_')
+ if (! d_check_char (di, '_'))
return NULL;
++di->did_subs;
constructor or destructor. */
hold_last_name = di->last_name;
- if (d_next_char (di) != 'I')
+ if (! d_check_char (di, 'I'))
return NULL;
al = NULL;
case 'X':
d_advance (di, 1);
ret = d_expression (di);
- if (d_next_char (di) != 'E')
+ if (! d_check_char (di, 'E'))
return NULL;
return ret;
{
struct demangle_component *ret;
- if (d_next_char (di) != 'L')
+ if (! d_check_char (di, 'L'))
return NULL;
if (d_peek_char (di) == '_')
ret = cplus_demangle_mangled_name (di, 0);
}
s = d_str (di);
while (d_peek_char (di) != 'E')
- d_advance (di, 1);
+ {
+ if (d_peek_char (di) == '\0')
+ return NULL;
+ d_advance (di, 1);
+ }
ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s));
}
- if (d_next_char (di) != 'E')
+ if (! d_check_char (di, 'E'))
return NULL;
return ret;
}
{
struct demangle_component *function;
- if (d_next_char (di) != 'Z')
+ if (! d_check_char (di, 'Z'))
return NULL;
function = d_encoding (di, 0);
- if (d_next_char (di) != 'E')
+ if (! d_check_char (di, 'E'))
return NULL;
if (d_peek_char (di) == 's')
{
char c;
- if (d_next_char (di) != 'S')
+ if (! d_check_char (di, 'S'))
return NULL;
c = d_next_char (di);
id = id * 36 + c - 'A' + 10;
else
return NULL;
+ if (id < 0)
+ return NULL;
c = d_next_char (di);
}
while (c != '_');
char *newbuf;
newalc = dpi->alc * 2;
- newbuf = realloc (dpi->buf, newalc);
+ newbuf = (char *) realloc (dpi->buf, newalc);
if (newbuf == NULL)
{
free (dpi->buf);
dpi.options = options;
dpi.alc = estimate + 1;
- dpi.buf = malloc (dpi.alc);
+ dpi.buf = (char *) malloc (dpi.alc);
if (dpi.buf == NULL)
{
*palc = 1;
{
dpt.next = dpi->templates;
dpi->templates = &dpt;
- dpt.template = typed_name;
+ dpt.template_decl = typed_name;
}
/* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then
return;
}
i = dc->u.s_number.number;
- for (a = d_right (dpi->templates->template);
+ for (a = d_right (dpi->templates->template_decl);
a != NULL;
a = d_right (a))
{
d_print_comp (dpi, d_left (dc));
return;
+ case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+ d_append_string_constant (dpi, "hidden alias for ");
+ d_print_comp (dpi, d_left (dc));
+ return;
+
case DEMANGLE_COMPONENT_SUB_STD:
d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len);
return;
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
{
+ if ((dpi->options & DMGL_RET_POSTFIX) != 0)
+ d_print_function_type (dpi, dc, dpi->modifiers);
+
+ /* Print return type if present */
if (d_left (dc) != NULL)
{
struct d_print_mod dpm;
/* We must pass this type down as a modifier in order to
print it in the right location. */
-
dpm.next = dpi->modifiers;
dpi->modifiers = &dpm;
dpm.mod = dc;
if (dpm.printed)
return;
- d_append_char (dpi, ' ');
+ /* In standard prefix notation, there is a space between the
+ return type and the function signature. */
+ if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+ d_append_char (dpi, ' ');
}
- d_print_function_type (dpi, dc, dpi->modifiers);
+ if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+ d_print_function_type (dpi, dc, dpi->modifiers);
return;
}
dpt.next = dpi->templates;
dpi->templates = &dpt;
- dpt.template = d_left (dc);
+ dpt.template_decl = d_left (dc);
d_print_comp (dpi, d_left (d_left (dc)));
{
char *r;
- r = malloc (40 + len - 11);
+ r = (char *) malloc (40 + len - 11);
if (r == NULL)
*palc = 1;
else
char *from;
char *to;
- demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS, &alc);
+ demangled = d_demangle (mangled, DMGL_JAVA | DMGL_PARAMS | DMGL_RET_POSTFIX,
+ &alc);
if (demangled == NULL)
return NULL;
#include "getopt.h"
#include "dyn-string.h"
-static void print_usage PARAMS ((FILE* fp, int exit_value));
+static void print_usage (FILE* fp, int exit_value);
#define IS_ALPHA(CHAR) \
(((CHAR) >= 'a' && (CHAR) <= 'z') \