/* Demangler for g++ V3 ABI.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Written by Ian Lance Taylor <ian@wasabisystems.com>.
enum { D_PRINT_BUFFER_LENGTH = 256 };
struct d_print_info
{
- /* The options passed to the demangler. */
- int options;
/* Fixed-length allocated buffer for demangled data, flushed to the
callback with a NUL termination once full. */
char buf[D_PRINT_BUFFER_LENGTH];
struct d_print_mod *modifiers;
/* Set to 1 if we saw a demangling error. */
int demangle_failure;
+ /* The current index into any template argument packs we are using
+ for printing. */
+ int pack_index;
+ /* Number of d_print_flush calls so far. */
+ unsigned long int flush_count;
};
#ifdef CP_DEMANGLE_DEBUG
static struct demangle_component *
d_make_name (struct d_info *, const char *, int);
+static struct demangle_component *
+d_make_demangle_mangled_name (struct d_info *, const char *);
+
static struct demangle_component *
d_make_builtin_type (struct d_info *,
const struct demangle_builtin_type_info *);
static struct demangle_component *d_array_type (struct d_info *);
+static struct demangle_component *d_vector_type (struct d_info *);
+
static struct demangle_component *
d_pointer_to_member_type (struct d_info *);
static int d_discriminator (struct d_info *);
+static struct demangle_component *d_lambda (struct d_info *);
+
+static struct demangle_component *d_unnamed_type (struct d_info *);
+
static int
d_add_substitution (struct d_info *, struct demangle_component *);
d_growable_string_callback_adapter (const char *, size_t, void *);
static void
-d_print_init (struct d_print_info *, int, demangle_callbackref, void *);
+d_print_init (struct d_print_info *, demangle_callbackref, void *);
static inline void d_print_error (struct d_print_info *);
static inline char d_last_char (struct d_print_info *);
static void
-d_print_comp (struct d_print_info *, const struct demangle_component *);
+d_print_comp (struct d_print_info *, int, const struct demangle_component *);
static void
d_print_java_identifier (struct d_print_info *, const char *, int);
static void
-d_print_mod_list (struct d_print_info *, struct d_print_mod *, int);
+d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int);
static void
-d_print_mod (struct d_print_info *, const struct demangle_component *);
+d_print_mod (struct d_print_info *, int, const struct demangle_component *);
static void
-d_print_function_type (struct d_print_info *,
+d_print_function_type (struct d_print_info *, int,
const struct demangle_component *,
struct d_print_mod *);
static void
-d_print_array_type (struct d_print_info *,
+d_print_array_type (struct d_print_info *, int,
const struct demangle_component *,
struct d_print_mod *);
static void
-d_print_expr_op (struct d_print_info *, const struct demangle_component *);
+d_print_expr_op (struct d_print_info *, int, const struct demangle_component *);
static void
-d_print_cast (struct d_print_info *, const struct demangle_component *);
+d_print_cast (struct d_print_info *, int, const struct demangle_component *);
static int d_demangle_callback (const char *, int,
demangle_callbackref, void *);
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
printf ("pointer to member type\n");
break;
+ case DEMANGLE_COMPONENT_FIXED_TYPE:
+ printf ("fixed-point type\n");
+ break;
case DEMANGLE_COMPONENT_ARGLIST:
printf ("argument list\n");
break;
case DEMANGLE_COMPONENT_CHARACTER:
printf ("character '%c'\n", dc->u.s_character.character);
return;
+ case DEMANGLE_COMPONENT_DECLTYPE:
+ printf ("decltype\n");
+ break;
+ case DEMANGLE_COMPONENT_PACK_EXPANSION:
+ printf ("pack expansion\n");
+ break;
}
d_dump (d_left (dc), indent + 2);
{
if (p == NULL
|| name == NULL
- || (kind < gnu_v3_complete_object_ctor
- && kind > gnu_v3_complete_object_allocating_ctor))
+ || (int) kind < gnu_v3_complete_object_ctor
+ || (int) kind > gnu_v3_complete_object_allocating_ctor)
return 0;
p->type = DEMANGLE_COMPONENT_CTOR;
p->u.s_ctor.kind = kind;
{
if (p == NULL
|| name == NULL
- || (kind < gnu_v3_deleting_dtor
- && kind > gnu_v3_base_object_dtor))
+ || (int) kind < gnu_v3_deleting_dtor
+ || (int) kind > gnu_v3_base_object_dtor)
return 0;
p->type = DEMANGLE_COMPONENT_DTOR;
p->u.s_dtor.kind = kind;
case DEMANGLE_COMPONENT_LITERAL:
case DEMANGLE_COMPONENT_LITERAL_NEG:
case DEMANGLE_COMPONENT_COMPOUND_NAME:
+ case DEMANGLE_COMPONENT_VECTOR_TYPE:
if (left == NULL || right == NULL)
return NULL;
break;
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
case DEMANGLE_COMPONENT_VENDOR_TYPE:
- case DEMANGLE_COMPONENT_ARGLIST:
- case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
case DEMANGLE_COMPONENT_CAST:
case DEMANGLE_COMPONENT_JAVA_RESOURCE:
+ case DEMANGLE_COMPONENT_DECLTYPE:
+ case DEMANGLE_COMPONENT_PACK_EXPANSION:
+ case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+ case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
if (left == NULL)
return NULL;
break;
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
break;
/* Other types should not be seen here. */
return p;
}
+/* Add a new demangle mangled name component. */
+
+static struct demangle_component *
+d_make_demangle_mangled_name (struct d_info *di, const char *s)
+{
+ if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z')
+ return d_make_name (di, s, strlen (s));
+ d_advance (di, 2);
+ return d_encoding (di, 0);
+}
+
/* Add a new name component. */
static struct demangle_component *
return p;
}
+static struct demangle_component *
+d_make_default_arg (struct d_info *di, int num,
+ struct demangle_component *sub)
+{
+ struct demangle_component *p = d_make_empty (di);
+ if (p)
+ {
+ p->type = DEMANGLE_COMPONENT_DEFAULT_ARG;
+ p->u.s_unary_num.num = num;
+ p->u.s_unary_num.sub = sub;
+ }
+ return p;
+}
+
/* Add a new constructor component. */
static struct demangle_component *
return p;
}
+/* Add a new function parameter. */
+
+static struct demangle_component *
+d_make_function_param (struct d_info *di, long i)
+{
+ struct demangle_component *p;
+
+ p = d_make_empty (di);
+ if (p != NULL)
+ {
+ p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM;
+ p->u.s_number.number = i;
+ }
+ return p;
+}
+
/* Add a new standard substitution component. */
static struct demangle_component *
struct demangle_component *
cplus_demangle_mangled_name (struct d_info *di, int top_level)
{
- if (! d_check_char (di, '_'))
+ if (! d_check_char (di, '_')
+ /* Allow missing _ if not at toplevel to work around a
+ bug in G++ abi-version=2 mangling; see the comment in
+ write_template_arg. */
+ && top_level)
return NULL;
if (! d_check_char (di, 'Z'))
return NULL;
return d_local_name (di);
case 'L':
+ case 'U':
return d_unqualified_name (di);
-
+
case 'S':
{
int subst;
|| IS_LOWER (peek)
|| peek == 'C'
|| peek == 'D'
+ || peek == 'U'
|| peek == 'L')
dc = d_unqualified_name (di);
else if (peek == 'S')
dc = d_template_param (di);
else if (peek == 'E')
return ret;
+ else if (peek == 'M')
+ {
+ /* Initializer scope for a lambda. We don't need to represent
+ this; the normal code will just treat the variable as a type
+ scope, which gives appropriate output. */
+ if (ret == NULL)
+ return NULL;
+ d_advance (di, 1);
+ continue;
+ }
else
return NULL;
return NULL;
return ret;
}
+ else if (peek == 'U')
+ {
+ switch (d_peek_next_char (di))
+ {
+ case 'l':
+ return d_lambda (di);
+ case 't':
+ return d_unnamed_type (di);
+ default:
+ return NULL;
+ }
+ }
else
return NULL;
}
}
}
+/* Like d_number, but returns a demangle_component. */
+
+static struct demangle_component *
+d_number_component (struct d_info *di)
+{
+ struct demangle_component *ret = d_make_empty (di);
+ if (ret)
+ {
+ ret->type = DEMANGLE_COMPONENT_NUMBER;
+ ret->u.s_number.number = d_number (di);
+ }
+ return ret;
+}
+
/* identifier ::= <(unqualified source code identifier)> */
static struct demangle_component *
{ "aa", NL ("&&"), 2 },
{ "ad", NL ("&"), 1 },
{ "an", NL ("&"), 2 },
- { "cl", NL ("()"), 0 },
+ { "cl", NL ("()"), 2 },
{ "cm", NL (","), 2 },
{ "co", NL ("~"), 1 },
{ "dV", NL ("/="), 2 },
{ "da", NL ("delete[]"), 1 },
{ "de", NL ("*"), 1 },
{ "dl", NL ("delete"), 1 },
+ { "dt", NL ("."), 2 },
{ "dv", NL ("/"), 2 },
{ "eO", NL ("^="), 2 },
{ "eo", NL ("^"), 2 },
{ "rs", NL (">>"), 2 },
{ "st", NL ("sizeof "), 1 },
{ "sz", NL ("sizeof "), 1 },
+ { "at", NL ("alignof "), 1 },
+ { "az", NL ("alignof "), 1 },
{ NULL, NULL, 0, 0 }
};
/* y */ { NL ("unsigned long long"), NL ("unsigned long long"),
D_PRINT_UNSIGNED_LONG_LONG },
/* z */ { NL ("..."), NL ("..."), D_PRINT_DEFAULT },
+ /* 26 */ { NL ("decimal32"), NL ("decimal32"), D_PRINT_DEFAULT },
+ /* 27 */ { NL ("decimal64"), NL ("decimal64"), D_PRINT_DEFAULT },
+ /* 28 */ { NL ("decimal128"), NL ("decimal128"), D_PRINT_DEFAULT },
+ /* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT },
+ /* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT },
+ /* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT },
+ /* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"),
+ D_PRINT_DEFAULT },
};
CP_STATIC_IF_GLIBCPP_V3
cplus_demangle_type (di), ret);
break;
+ case 'D':
+ can_subst = 0;
+ d_advance (di, 1);
+ peek = d_next_char (di);
+ switch (peek)
+ {
+ case 'T':
+ case 't':
+ /* decltype (expression) */
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_DECLTYPE,
+ d_expression (di), NULL);
+ if (ret && d_next_char (di) != 'E')
+ ret = NULL;
+ break;
+
+ case 'p':
+ /* Pack expansion. */
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
+ cplus_demangle_type (di), NULL);
+ break;
+
+ case 'f':
+ /* 32-bit decimal floating point */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ case 'd':
+ /* 64-bit DFP */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[27]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ case 'e':
+ /* 128-bit DFP */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[28]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ case 'h':
+ /* 16-bit half-precision FP */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ case 's':
+ /* char16_t */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+ case 'i':
+ /* char32_t */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+
+ case 'F':
+ /* Fixed point types. DF<int bits><length><fract bits><sat> */
+ ret = d_make_empty (di);
+ ret->type = DEMANGLE_COMPONENT_FIXED_TYPE;
+ if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di))))
+ /* For demangling we don't care about the bits. */
+ d_number (di);
+ ret->u.s_fixed.length = cplus_demangle_type (di);
+ if (ret->u.s_fixed.length == NULL)
+ return NULL;
+ d_number (di);
+ peek = d_next_char (di);
+ ret->u.s_fixed.sat = (peek == 's');
+ break;
+
+ case 'v':
+ ret = d_vector_type (di);
+ break;
+
+ case 'n':
+ /* decltype(nullptr) */
+ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
+ di->expansion += ret->u.s_builtin.type->len;
+ break;
+
+ default:
+ return NULL;
+ }
+ break;
+
default:
return NULL;
}
return ret;
}
-/* <bare-function-type> ::= [J]<type>+ */
+/* <type>+ */
static struct demangle_component *
-d_bare_function_type (struct d_info *di, int has_return_type)
+d_parmlist (struct d_info *di)
{
- 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)
{
struct demangle_component *type;
- peek = d_peek_char (di);
+ char peek = d_peek_char (di);
if (peek == '\0' || peek == 'E')
break;
type = cplus_demangle_type (di);
if (type == NULL)
return NULL;
- if (has_return_type)
- {
- return_type = type;
- has_return_type = 0;
- }
- else
- {
- *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
- if (*ptl == NULL)
- return NULL;
- ptl = &d_right (*ptl);
- }
+ *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
+ if (*ptl == NULL)
+ return NULL;
+ ptl = &d_right (*ptl);
}
/* There should be at least one parameter type besides the optional
&& d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
{
di->expansion -= d_left (tl)->u.s_builtin.type->len;
- tl = NULL;
+ d_left (tl) = NULL;
+ }
+
+ return tl;
+}
+
+/* <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;
+ 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 d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);
+ if (has_return_type)
+ {
+ return_type = cplus_demangle_type (di);
+ if (return_type == NULL)
+ return NULL;
+ }
+ else
+ return_type = NULL;
+
+ tl = d_parmlist (di);
+ if (tl == NULL)
+ return NULL;
+
+ return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE,
+ return_type, tl);
}
/* <class-enum-type> ::= <name> */
cplus_demangle_type (di));
}
+/* <vector-type> ::= Dv <number> _ <type>
+ ::= Dv _ <expression> _ <type> */
+
+static struct demangle_component *
+d_vector_type (struct d_info *di)
+{
+ char peek;
+ struct demangle_component *dim;
+
+ peek = d_peek_char (di);
+ if (peek == '_')
+ {
+ d_advance (di, 1);
+ dim = d_expression (di);
+ }
+ else
+ dim = d_number_component (di);
+
+ if (dim == NULL)
+ return NULL;
+
+ if (! d_check_char (di, '_'))
+ return NULL;
+
+ return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim,
+ cplus_demangle_type (di));
+}
+
/* <pointer-to-member-type> ::= M <(class) type> <(member) type> */
static struct demangle_component *
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
}
+/* <non-negative number> _ */
+
+static long
+d_compact_number (struct d_info *di)
+{
+ long num;
+ if (d_peek_char (di) == '_')
+ num = 0;
+ else if (d_peek_char (di) == 'n')
+ return -1;
+ else
+ num = d_number (di) + 1;
+
+ if (! d_check_char (di, '_'))
+ return -1;
+ return num;
+}
+
/* <template-param> ::= T_
::= T <(parameter-2 non-negative) number> _
*/
if (! d_check_char (di, 'T'))
return NULL;
- if (d_peek_char (di) == '_')
- param = 0;
- else
- {
- param = d_number (di);
- if (param < 0)
- return NULL;
- param += 1;
- }
-
- if (! d_check_char (di, '_'))
+ param = d_compact_number (di);
+ if (param < 0)
return NULL;
++di->did_subs;
if (! d_check_char (di, 'I'))
return NULL;
+ if (d_peek_char (di) == 'E')
+ {
+ /* An argument pack can be empty. */
+ d_advance (di, 1);
+ return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, NULL, NULL);
+ }
+
al = NULL;
pal = &al;
while (1)
case 'L':
return d_expr_primary (di);
+ case 'I':
+ /* An argument pack. */
+ return d_template_args (di);
+
default:
return cplus_demangle_type (di);
}
}
+/* Subroutine of <expression> ::= cl <expression>+ E */
+
+static struct demangle_component *
+d_exprlist (struct d_info *di)
+{
+ struct demangle_component *list = NULL;
+ struct demangle_component **p = &list;
+
+ if (d_peek_char (di) == 'E')
+ {
+ d_advance (di, 1);
+ return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
+ }
+
+ while (1)
+ {
+ struct demangle_component *arg = d_expression (di);
+ if (arg == NULL)
+ return NULL;
+
+ *p = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, arg, NULL);
+ if (*p == NULL)
+ return NULL;
+ p = &d_right (*p);
+
+ if (d_peek_char (di) == 'E')
+ {
+ d_advance (di, 1);
+ break;
+ }
+ }
+
+ return list;
+}
+
/* <expression> ::= <(unary) operator-name> <expression>
::= <(binary) operator-name> <expression> <expression>
::= <(trinary) operator-name> <expression> <expression> <expression>
+ ::= cl <expression>+ E
::= st <type>
::= <template-param>
::= sr <type> <unqualified-name>
d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
d_template_args (di)));
}
+ else if (peek == 's' && d_peek_next_char (di) == 'p')
+ {
+ d_advance (di, 2);
+ return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
+ d_expression (di), NULL);
+ }
+ else if (peek == 'f' && d_peek_next_char (di) == 'p')
+ {
+ /* Function parameter used in a late-specified return type. */
+ int index;
+ d_advance (di, 2);
+ index = d_compact_number (di);
+ if (index < 0)
+ return NULL;
+
+ return d_make_function_param (di, index);
+ }
+ else if (IS_DIGIT (peek)
+ || (peek == 'o' && d_peek_next_char (di) == 'n'))
+ {
+ /* We can get an unqualified name as an expression in the case of
+ a dependent function call, i.e. decltype(f(t)). */
+ struct demangle_component *name;
+
+ if (peek == 'o')
+ /* operator-function-id, i.e. operator+(t). */
+ d_advance (di, 2);
+
+ name = d_unqualified_name (di);
+ if (name == NULL)
+ return NULL;
+ if (d_peek_char (di) == 'I')
+ return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name,
+ d_template_args (di));
+ else
+ return name;
+ }
else
{
struct demangle_component *op;
switch (args)
{
case 1:
- return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
- d_expression (di));
+ {
+ struct demangle_component *operand;
+ if (op->type == DEMANGLE_COMPONENT_CAST
+ && d_check_char (di, '_'))
+ operand = d_exprlist (di);
+ else
+ operand = d_expression (di);
+ return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+ operand);
+ }
case 2:
{
struct demangle_component *left;
+ struct demangle_component *right;
+ const char *code = op->u.s_operator.op->code;
left = d_expression (di);
+ if (!strcmp (code, "cl"))
+ right = d_exprlist (di);
+ else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
+ {
+ right = d_unqualified_name (di);
+ if (d_peek_char (di) == 'I')
+ right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE,
+ right, d_template_args (di));
+ }
+ else
+ right = d_expression (di);
+
return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
d_make_comp (di,
DEMANGLE_COMPONENT_BINARY_ARGS,
- left,
- d_expression (di)));
+ left, right));
}
case 3:
{
if (! d_check_char (di, 'L'))
return NULL;
- if (d_peek_char (di) == '_')
+ if (d_peek_char (di) == '_'
+ /* Workaround for G++ bug; see comment in write_template_arg. */
+ || d_peek_char (di) == 'Z')
ret = cplus_demangle_mangled_name (di, 0);
else
{
else
{
struct demangle_component *name;
+ int num = -1;
+
+ if (d_peek_char (di) == 'd')
+ {
+ /* Default argument scope: d <number> _. */
+ d_advance (di, 1);
+ num = d_compact_number (di);
+ if (num < 0)
+ return NULL;
+ }
name = d_name (di);
- if (! d_discriminator (di))
- return NULL;
+ if (name)
+ switch (name->type)
+ {
+ /* Lambdas and unnamed types have internal discriminators. */
+ case DEMANGLE_COMPONENT_LAMBDA:
+ case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+ break;
+ default:
+ if (! d_discriminator (di))
+ return NULL;
+ }
+ if (num >= 0)
+ name = d_make_default_arg (di, num, name);
return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
}
}
return 1;
}
+/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ */
+
+static struct demangle_component *
+d_lambda (struct d_info *di)
+{
+ struct demangle_component *tl;
+ struct demangle_component *ret;
+ int num;
+
+ if (! d_check_char (di, 'U'))
+ return NULL;
+ if (! d_check_char (di, 'l'))
+ return NULL;
+
+ tl = d_parmlist (di);
+ if (tl == NULL)
+ return NULL;
+
+ if (! d_check_char (di, 'E'))
+ return NULL;
+
+ num = d_compact_number (di);
+ if (num < 0)
+ return NULL;
+
+ ret = d_make_empty (di);
+ if (ret)
+ {
+ ret->type = DEMANGLE_COMPONENT_LAMBDA;
+ ret->u.s_unary_num.sub = tl;
+ ret->u.s_unary_num.num = num;
+ }
+
+ if (! d_add_substitution (di, ret))
+ return NULL;
+
+ return ret;
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
+static struct demangle_component *
+d_unnamed_type (struct d_info *di)
+{
+ struct demangle_component *ret;
+ long num;
+
+ if (! d_check_char (di, 'U'))
+ return NULL;
+ if (! d_check_char (di, 't'))
+ return NULL;
+
+ num = d_compact_number (di);
+ if (num < 0)
+ return NULL;
+
+ ret = d_make_empty (di);
+ if (ret)
+ {
+ ret->type = DEMANGLE_COMPONENT_UNNAMED_TYPE;
+ ret->u.s_number.number = num;
+ }
+
+ if (! d_add_substitution (di, ret))
+ return NULL;
+
+ return ret;
+}
+
/* Add a new substitution. */
static int
/* Initialize a print information structure. */
static void
-d_print_init (struct d_print_info *dpi, int options,
- demangle_callbackref callback, void *opaque)
+d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
+ void *opaque)
{
- dpi->options = options;
dpi->len = 0;
dpi->last_char = '\0';
dpi->templates = NULL;
dpi->modifiers = NULL;
+ dpi->flush_count = 0;
dpi->callback = callback;
dpi->opaque = opaque;
dpi->buf[dpi->len] = '\0';
dpi->callback (dpi->buf, dpi->len, dpi->opaque);
dpi->len = 0;
+ dpi->flush_count++;
}
/* Append characters and buffers for printing. */
d_append_buffer (dpi, s, strlen (s));
}
+static inline void
+d_append_num (struct d_print_info *dpi, long l)
+{
+ char buf[25];
+ sprintf (buf,"%ld", l);
+ d_append_string (dpi, buf);
+}
+
static inline char
d_last_char (struct d_print_info *dpi)
{
{
struct d_print_info dpi;
- d_print_init (&dpi, options, callback, opaque);
+ d_print_init (&dpi, callback, opaque);
- d_print_comp (&dpi, dc);
+ d_print_comp (&dpi, options, dc);
d_print_flush (&dpi);
return dgs.buf;
}
+/* Returns the I'th element of the template arglist ARGS, or NULL on
+ failure. */
+
+static struct demangle_component *
+d_index_template_argument (struct demangle_component *args, int i)
+{
+ struct demangle_component *a;
+
+ for (a = args;
+ a != NULL;
+ a = d_right (a))
+ {
+ if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+ return NULL;
+ if (i <= 0)
+ break;
+ --i;
+ }
+ if (i != 0 || a == NULL)
+ return NULL;
+
+ return d_left (a);
+}
+
+/* Returns the template argument from the current context indicated by DC,
+ which is a DEMANGLE_COMPONENT_TEMPLATE_PARAM, or NULL. */
+
+static struct demangle_component *
+d_lookup_template_argument (struct d_print_info *dpi,
+ const struct demangle_component *dc)
+{
+ if (dpi->templates == NULL)
+ {
+ d_print_error (dpi);
+ return NULL;
+ }
+
+ return d_index_template_argument
+ (d_right (dpi->templates->template_decl),
+ dc->u.s_number.number);
+}
+
+/* Returns a template argument pack used in DC (any will do), or NULL. */
+
+static struct demangle_component *
+d_find_pack (struct d_print_info *dpi,
+ const struct demangle_component *dc)
+{
+ struct demangle_component *a;
+ if (dc == NULL)
+ return NULL;
+
+ switch (dc->type)
+ {
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ a = d_lookup_template_argument (dpi, dc);
+ if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+ return a;
+ return NULL;
+
+ case DEMANGLE_COMPONENT_PACK_EXPANSION:
+ return NULL;
+
+ case DEMANGLE_COMPONENT_LAMBDA:
+ case DEMANGLE_COMPONENT_NAME:
+ case DEMANGLE_COMPONENT_OPERATOR:
+ case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+ case DEMANGLE_COMPONENT_SUB_STD:
+ case DEMANGLE_COMPONENT_CHARACTER:
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+ return NULL;
+
+ case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+ return d_find_pack (dpi, dc->u.s_extended_operator.name);
+ case DEMANGLE_COMPONENT_CTOR:
+ return d_find_pack (dpi, dc->u.s_ctor.name);
+ case DEMANGLE_COMPONENT_DTOR:
+ return d_find_pack (dpi, dc->u.s_dtor.name);
+
+ default:
+ a = d_find_pack (dpi, d_left (dc));
+ if (a)
+ return a;
+ return d_find_pack (dpi, d_right (dc));
+ }
+}
+
+/* Returns the length of the template argument pack DC. */
+
+static int
+d_pack_length (const struct demangle_component *dc)
+{
+ int count = 0;
+ while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST
+ && d_left (dc) != NULL)
+ {
+ ++count;
+ dc = d_right (dc);
+ }
+ return count;
+}
+
+/* DC is a component of a mangled expression. Print it, wrapped in parens
+ if needed. */
+
+static void
+d_print_subexpr (struct d_print_info *dpi, int options,
+ const struct demangle_component *dc)
+{
+ int simple = 0;
+ if (dc->type == DEMANGLE_COMPONENT_NAME
+ || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
+ simple = 1;
+ if (!simple)
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, options, dc);
+ if (!simple)
+ d_append_char (dpi, ')');
+}
+
/* Subroutine to handle components. */
static void
-d_print_comp (struct d_print_info *dpi,
+d_print_comp (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
+ /* Magic variable to let reference smashing skip over the next modifier
+ without needing to modify *dc. */
+ const struct demangle_component *mod_inner = NULL;
+
if (dc == NULL)
{
d_print_error (dpi);
switch (dc->type)
{
case DEMANGLE_COMPONENT_NAME:
- if ((dpi->options & DMGL_JAVA) == 0)
+ if ((options & DMGL_JAVA) == 0)
d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
else
d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
case DEMANGLE_COMPONENT_QUAL_NAME:
case DEMANGLE_COMPONENT_LOCAL_NAME:
- d_print_comp (dpi, d_left (dc));
- if ((dpi->options & DMGL_JAVA) == 0)
+ d_print_comp (dpi, options, d_left (dc));
+ if ((options & DMGL_JAVA) == 0)
d_append_string (dpi, "::");
else
d_append_char (dpi, '.');
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
return;
case DEMANGLE_COMPONENT_TYPED_NAME:
the right place for the type. We also have to pass down
any CV-qualifiers, which apply to the this parameter. */
hold_modifiers = dpi->modifiers;
+ dpi->modifiers = 0;
i = 0;
typed_name = d_left (dc);
while (typed_name != NULL)
struct demangle_component *local_name;
local_name = d_right (typed_name);
+ if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+ local_name = local_name->u.s_unary_num.sub;
while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
}
}
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
dpi->templates = dpt.next;
if (! adpm[i].printed)
{
d_append_char (dpi, ' ');
- d_print_mod (dpi, adpm[i].mod);
+ d_print_mod (dpi, options, adpm[i].mod);
}
}
dcl = d_left (dc);
- if ((dpi->options & DMGL_JAVA) != 0
+ if ((options & DMGL_JAVA) != 0
&& dcl->type == DEMANGLE_COMPONENT_NAME
&& dcl->u.s_name.len == 6
&& strncmp (dcl->u.s_name.s, "JArray", 6) == 0)
/* Special-case Java arrays, so that JArray<TYPE> appears
instead as TYPE[]. */
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
d_append_string (dpi, "[]");
}
else
{
- d_print_comp (dpi, dcl);
+ d_print_comp (dpi, options, dcl);
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<');
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
/* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */
if (d_last_char (dpi) == '>')
case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
{
- long i;
- struct demangle_component *a;
struct d_print_template *hold_dpt;
+ struct demangle_component *a = d_lookup_template_argument (dpi, dc);
- if (dpi->templates == NULL)
- {
- d_print_error (dpi);
- return;
- }
- i = dc->u.s_number.number;
- for (a = d_right (dpi->templates->template_decl);
- a != NULL;
- a = d_right (a))
- {
- if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
- {
- d_print_error (dpi);
- return;
- }
- if (i <= 0)
- break;
- --i;
- }
- if (i != 0 || a == NULL)
+ if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+ a = d_index_template_argument (a, dpi->pack_index);
+
+ if (a == NULL)
{
d_print_error (dpi);
return;
hold_dpt = dpi->templates;
dpi->templates = hold_dpt->next;
- d_print_comp (dpi, d_left (a));
+ d_print_comp (dpi, options, a);
dpi->templates = hold_dpt;
}
case DEMANGLE_COMPONENT_CTOR:
- d_print_comp (dpi, dc->u.s_ctor.name);
+ d_print_comp (dpi, options, dc->u.s_ctor.name);
return;
case DEMANGLE_COMPONENT_DTOR:
d_append_char (dpi, '~');
- d_print_comp (dpi, dc->u.s_dtor.name);
+ d_print_comp (dpi, options, dc->u.s_dtor.name);
return;
case DEMANGLE_COMPONENT_VTABLE:
d_append_string (dpi, "vtable for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_VTT:
d_append_string (dpi, "VTT for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
d_append_string (dpi, "construction vtable for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
d_append_string (dpi, "-in-");
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
return;
case DEMANGLE_COMPONENT_TYPEINFO:
d_append_string (dpi, "typeinfo for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_TYPEINFO_NAME:
d_append_string (dpi, "typeinfo name for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_TYPEINFO_FN:
d_append_string (dpi, "typeinfo fn for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_THUNK:
d_append_string (dpi, "non-virtual thunk to ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
d_append_string (dpi, "virtual thunk to ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_COVARIANT_THUNK:
d_append_string (dpi, "covariant return thunk to ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_JAVA_CLASS:
d_append_string (dpi, "java Class for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_GUARD:
d_append_string (dpi, "guard variable for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_REFTEMP:
d_append_string (dpi, "reference temporary for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
d_append_string (dpi, "hidden alias for ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_SUB_STD:
break;
if (pdpm->mod->type == dc->type)
{
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
}
}
}
}
+ goto modifier;
+
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ {
+ /* Handle reference smashing: & + && = &. */
+ const struct demangle_component *sub = d_left (dc);
+ if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+ {
+ struct demangle_component *a = d_lookup_template_argument (dpi, sub);
+ if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+ a = d_index_template_argument (a, dpi->pack_index);
+ sub = a;
+ }
+
+ if (sub->type == DEMANGLE_COMPONENT_REFERENCE
+ || sub->type == dc->type)
+ dc = sub;
+ else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE)
+ mod_inner = d_left (sub);
+ }
/* Fall through. */
+
case DEMANGLE_COMPONENT_RESTRICT_THIS:
case DEMANGLE_COMPONENT_VOLATILE_THIS:
case DEMANGLE_COMPONENT_CONST_THIS:
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
case DEMANGLE_COMPONENT_POINTER:
- case DEMANGLE_COMPONENT_REFERENCE:
- case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
case DEMANGLE_COMPONENT_COMPLEX:
case DEMANGLE_COMPONENT_IMAGINARY:
+ modifier:
{
/* We keep a list of modifiers on the stack. */
struct d_print_mod dpm;
dpm.printed = 0;
dpm.templates = dpi->templates;
- d_print_comp (dpi, d_left (dc));
+ if (!mod_inner)
+ mod_inner = d_left (dc);
+
+ d_print_comp (dpi, options, mod_inner);
/* If the modifier didn't get printed by the type, print it
now. */
if (! dpm.printed)
- d_print_mod (dpi, dc);
+ d_print_mod (dpi, options, dc);
dpi->modifiers = dpm.next;
}
case DEMANGLE_COMPONENT_BUILTIN_TYPE:
- if ((dpi->options & DMGL_JAVA) == 0)
+ if ((options & DMGL_JAVA) == 0)
d_append_buffer (dpi, dc->u.s_builtin.type->name,
dc->u.s_builtin.type->len);
else
return;
case DEMANGLE_COMPONENT_VENDOR_TYPE:
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_FUNCTION_TYPE:
{
- if ((dpi->options & DMGL_RET_POSTFIX) != 0)
- d_print_function_type (dpi, dc, dpi->modifiers);
+ if ((options & DMGL_RET_POSTFIX) != 0)
+ d_print_function_type (dpi,
+ options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+ dc, dpi->modifiers);
/* Print return type if present */
- if (d_left (dc) != NULL)
+ if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0)
+ d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+ d_left (dc));
+ else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0)
{
struct d_print_mod dpm;
dpm.printed = 0;
dpm.templates = dpi->templates;
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+ d_left (dc));
dpi->modifiers = dpm.next;
/* In standard prefix notation, there is a space between the
return type and the function signature. */
- if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+ if ((options & DMGL_RET_POSTFIX) == 0)
d_append_char (dpi, ' ');
}
- if ((dpi->options & DMGL_RET_POSTFIX) == 0)
- d_print_function_type (dpi, dc, dpi->modifiers);
+ if ((options & DMGL_RET_POSTFIX) == 0)
+ d_print_function_type (dpi,
+ options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+ dc, dpi->modifiers);
return;
}
pdpm = pdpm->next;
}
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
dpi->modifiers = hold_modifiers;
while (i > 1)
{
--i;
- d_print_mod (dpi, adpm[i].mod);
+ d_print_mod (dpi, options, adpm[i].mod);
}
- d_print_array_type (dpi, dc, dpi->modifiers);
+ d_print_array_type (dpi, options, dc, dpi->modifiers);
return;
}
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+ case DEMANGLE_COMPONENT_VECTOR_TYPE:
{
struct d_print_mod dpm;
dpm.printed = 0;
dpm.templates = dpi->templates;
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
/* If the modifier didn't get printed by the type, print it
now. */
if (! dpm.printed)
- {
- d_append_char (dpi, ' ');
- d_print_comp (dpi, d_left (dc));
- d_append_string (dpi, "::*");
- }
+ d_print_mod (dpi, options, dc);
dpi->modifiers = dpm.next;
return;
}
+ case DEMANGLE_COMPONENT_FIXED_TYPE:
+ if (dc->u.s_fixed.sat)
+ d_append_string (dpi, "_Sat ");
+ /* Don't print "int _Accum". */
+ if (dc->u.s_fixed.length->u.s_builtin.type
+ != &cplus_demangle_builtin_types['i'-'a'])
+ {
+ d_print_comp (dpi, options, dc->u.s_fixed.length);
+ d_append_char (dpi, ' ');
+ }
+ if (dc->u.s_fixed.accum)
+ d_append_string (dpi, "_Accum");
+ else
+ d_append_string (dpi, "_Fract");
+ return;
+
case DEMANGLE_COMPONENT_ARGLIST:
case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
- d_print_comp (dpi, d_left (dc));
+ if (d_left (dc) != NULL)
+ d_print_comp (dpi, options, d_left (dc));
if (d_right (dc) != NULL)
{
+ size_t len;
+ unsigned long int flush_count;
+ /* Make sure ", " isn't flushed by d_append_string, otherwise
+ dpi->len -= 2 wouldn't work. */
+ if (dpi->len >= sizeof (dpi->buf) - 2)
+ d_print_flush (dpi);
d_append_string (dpi, ", ");
- d_print_comp (dpi, d_right (dc));
+ len = dpi->len;
+ flush_count = dpi->flush_count;
+ d_print_comp (dpi, options, d_right (dc));
+ /* If that didn't print anything (which can happen with empty
+ template argument packs), remove the comma and space. */
+ if (dpi->flush_count == flush_count && dpi->len == len)
+ dpi->len -= 2;
}
return;
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
d_append_string (dpi, "operator ");
- d_print_comp (dpi, dc->u.s_extended_operator.name);
+ d_print_comp (dpi, options, dc->u.s_extended_operator.name);
return;
case DEMANGLE_COMPONENT_CAST:
d_append_string (dpi, "operator ");
- d_print_cast (dpi, dc);
+ d_print_cast (dpi, options, dc);
return;
case DEMANGLE_COMPONENT_UNARY:
- if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
- d_print_expr_op (dpi, d_left (dc));
+ if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
+ && d_left (dc)->u.s_operator.op->len == 1
+ && d_left (dc)->u.s_operator.op->name[0] == '&'
+ && d_right (dc)->type == DEMANGLE_COMPONENT_TYPED_NAME
+ && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_QUAL_NAME
+ && d_right (d_right (dc))->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ /* Address of a function (therefore in an expression context) must
+ have its argument list suppressed.
+
+ unary operator ... dc
+ operator & ... d_left (dc)
+ typed name ... d_right (dc)
+ qualified name ... d_left (d_right (dc))
+ <names>
+ function type ... d_right (d_right (dc))
+ argument list
+ <arguments> */
+
+ d_print_expr_op (dpi, options, d_left (dc));
+ d_print_comp (dpi, options, d_left (d_right (dc)));
+ return;
+ }
+ else if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
+ && d_left (dc)->u.s_operator.op->len == 1
+ && d_left (dc)->u.s_operator.op->name[0] == '&'
+ && d_right (dc)->type == DEMANGLE_COMPONENT_QUAL_NAME)
+ {
+ /* Keep also already processed variant without the argument list.
+
+ unary operator ... dc
+ operator & ... d_left (dc)
+ qualified name ... d_right (dc)
+ <names> */
+
+ d_print_expr_op (dpi, options, d_left (dc));
+ d_print_comp (dpi, options, d_right (dc));
+ return;
+ }
+ else if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
+ d_print_expr_op (dpi, options, d_left (dc));
else
{
d_append_char (dpi, '(');
- d_print_cast (dpi, d_left (dc));
+ d_print_cast (dpi, options, d_left (dc));
d_append_char (dpi, ')');
}
- d_append_char (dpi, '(');
- d_print_comp (dpi, d_right (dc));
- d_append_char (dpi, ')');
+ d_print_subexpr (dpi, options, d_right (dc));
return;
case DEMANGLE_COMPONENT_BINARY:
&& d_left (dc)->u.s_operator.op->name[0] == '>')
d_append_char (dpi, '(');
- d_append_char (dpi, '(');
- d_print_comp (dpi, d_left (d_right (dc)));
- d_append_string (dpi, ") ");
- d_print_expr_op (dpi, d_left (dc));
- d_append_string (dpi, " (");
- d_print_comp (dpi, d_right (d_right (dc)));
- d_append_char (dpi, ')');
+ if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0
+ && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ {
+ /* Function call used in an expression should not have printed types
+ of the function arguments. Values of the function arguments still
+ get printed below. */
+
+ const struct demangle_component *func = d_left (d_right (dc));
+
+ if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ d_print_error (dpi);
+ d_print_subexpr (dpi, options, d_left (func));
+ }
+ else
+ d_print_subexpr (dpi, options, d_left (d_right (dc)));
+ if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0)
+ {
+ d_append_char (dpi, '[');
+ d_print_comp (dpi, options, d_right (d_right (dc)));
+ d_append_char (dpi, ']');
+ }
+ else
+ {
+ if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0)
+ d_print_expr_op (dpi, options, d_left (dc));
+ d_print_subexpr (dpi, options, d_right (d_right (dc)));
+ }
if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
&& d_left (dc)->u.s_operator.op->len == 1
d_print_error (dpi);
return;
}
- d_append_char (dpi, '(');
- d_print_comp (dpi, d_left (d_right (dc)));
- d_append_string (dpi, ") ");
- d_print_expr_op (dpi, d_left (dc));
- d_append_string (dpi, " (");
- d_print_comp (dpi, d_left (d_right (d_right (dc))));
- d_append_string (dpi, ") : (");
- d_print_comp (dpi, d_right (d_right (d_right (dc))));
- d_append_char (dpi, ')');
+ d_print_subexpr (dpi, options, d_left (d_right (dc)));
+ d_print_expr_op (dpi, options, d_left (dc));
+ d_print_subexpr (dpi, options, d_left (d_right (d_right (dc))));
+ d_append_string (dpi, " : ");
+ d_print_subexpr (dpi, options, d_right (d_right (d_right (dc))));
return;
case DEMANGLE_COMPONENT_TRINARY_ARG1:
{
if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
d_append_char (dpi, '-');
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
switch (tp)
{
default:
}
d_append_char (dpi, '(');
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
d_append_char (dpi, ')');
if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
d_append_char (dpi, '-');
if (tp == D_PRINT_FLOAT)
d_append_char (dpi, '[');
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
if (tp == D_PRINT_FLOAT)
d_append_char (dpi, ']');
}
return;
+ case DEMANGLE_COMPONENT_NUMBER:
+ d_append_num (dpi, dc->u.s_number.number);
+ return;
+
case DEMANGLE_COMPONENT_JAVA_RESOURCE:
d_append_string (dpi, "java resource ");
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
return;
case DEMANGLE_COMPONENT_COMPOUND_NAME:
- d_print_comp (dpi, d_left (dc));
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_left (dc));
+ d_print_comp (dpi, options, d_right (dc));
return;
case DEMANGLE_COMPONENT_CHARACTER:
d_append_char (dpi, dc->u.s_character.character);
return;
+ case DEMANGLE_COMPONENT_DECLTYPE:
+ d_append_string (dpi, "decltype (");
+ d_print_comp (dpi, options, d_left (dc));
+ d_append_char (dpi, ')');
+ return;
+
+ case DEMANGLE_COMPONENT_PACK_EXPANSION:
+ {
+ int len;
+ int i;
+ struct demangle_component *a = d_find_pack (dpi, d_left (dc));
+ if (a == NULL)
+ {
+ /* d_find_pack won't find anything if the only packs involved
+ in this expansion are function parameter packs; in that
+ case, just print the pattern and "...". */
+ d_print_subexpr (dpi, options, d_left (dc));
+ d_append_string (dpi, "...");
+ return;
+ }
+
+ len = d_pack_length (a);
+ dc = d_left (dc);
+ for (i = 0; i < len; ++i)
+ {
+ dpi->pack_index = i;
+ d_print_comp (dpi, options, dc);
+ if (i < len-1)
+ d_append_string (dpi, ", ");
+ }
+ }
+ return;
+
+ case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+ d_append_string (dpi, "{parm#");
+ d_append_num (dpi, dc->u.s_number.number + 1);
+ d_append_char (dpi, '}');
+ return;
+
+ case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+ d_append_string (dpi, "global constructors keyed to ");
+ d_print_comp (dpi, options, dc->u.s_binary.left);
+ return;
+
+ case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+ d_append_string (dpi, "global destructors keyed to ");
+ d_print_comp (dpi, options, dc->u.s_binary.left);
+ return;
+
+ case DEMANGLE_COMPONENT_LAMBDA:
+ d_append_string (dpi, "{lambda(");
+ d_print_comp (dpi, options, dc->u.s_unary_num.sub);
+ d_append_string (dpi, ")#");
+ d_append_num (dpi, dc->u.s_unary_num.num + 1);
+ d_append_char (dpi, '}');
+ return;
+
+ case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+ d_append_string (dpi, "{unnamed type#");
+ d_append_num (dpi, dc->u.s_number.number + 1);
+ d_append_char (dpi, '}');
+ return;
+
default:
d_print_error (dpi);
return;
qualifiers on this after printing a function. */
static void
-d_print_mod_list (struct d_print_info *dpi,
+d_print_mod_list (struct d_print_info *dpi, int options,
struct d_print_mod *mods, int suffix)
{
struct d_print_template *hold_dpt;
|| mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
{
- d_print_mod_list (dpi, mods->next, suffix);
+ d_print_mod_list (dpi, options, mods->next, suffix);
return;
}
if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
{
- d_print_function_type (dpi, mods->mod, mods->next);
+ d_print_function_type (dpi, options, mods->mod, mods->next);
dpi->templates = hold_dpt;
return;
}
else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
{
- d_print_array_type (dpi, mods->mod, mods->next);
+ d_print_array_type (dpi, options, mods->mod, mods->next);
dpi->templates = hold_dpt;
return;
}
hold_modifiers = dpi->modifiers;
dpi->modifiers = NULL;
- d_print_comp (dpi, d_left (mods->mod));
+ d_print_comp (dpi, options, d_left (mods->mod));
dpi->modifiers = hold_modifiers;
- if ((dpi->options & DMGL_JAVA) == 0)
+ if ((options & DMGL_JAVA) == 0)
d_append_string (dpi, "::");
else
d_append_char (dpi, '.');
dc = d_right (mods->mod);
+
+ if (dc->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+ {
+ d_append_string (dpi, "{default arg#");
+ d_append_num (dpi, dc->u.s_unary_num.num + 1);
+ d_append_string (dpi, "}::");
+ dc = dc->u.s_unary_num.sub;
+ }
+
while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|| dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|| dc->type == DEMANGLE_COMPONENT_CONST_THIS)
dc = d_left (dc);
- d_print_comp (dpi, dc);
+ d_print_comp (dpi, options, dc);
dpi->templates = hold_dpt;
return;
}
- d_print_mod (dpi, mods->mod);
+ d_print_mod (dpi, options, mods->mod);
dpi->templates = hold_dpt;
- d_print_mod_list (dpi, mods->next, suffix);
+ d_print_mod_list (dpi, options, mods->next, suffix);
}
/* Print a modifier. */
static void
-d_print_mod (struct d_print_info *dpi,
+d_print_mod (struct d_print_info *dpi, int options,
const struct demangle_component *mod)
{
switch (mod->type)
return;
case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
d_append_char (dpi, ' ');
- d_print_comp (dpi, d_right (mod));
+ d_print_comp (dpi, options, d_right (mod));
return;
case DEMANGLE_COMPONENT_POINTER:
/* There is no pointer symbol in Java. */
- if ((dpi->options & DMGL_JAVA) == 0)
+ if ((options & DMGL_JAVA) == 0)
d_append_char (dpi, '*');
return;
case DEMANGLE_COMPONENT_REFERENCE:
case DEMANGLE_COMPONENT_PTRMEM_TYPE:
if (d_last_char (dpi) != '(')
d_append_char (dpi, ' ');
- d_print_comp (dpi, d_left (mod));
+ d_print_comp (dpi, options, d_left (mod));
d_append_string (dpi, "::*");
return;
case DEMANGLE_COMPONENT_TYPED_NAME:
- d_print_comp (dpi, d_left (mod));
+ d_print_comp (dpi, options, d_left (mod));
return;
+ case DEMANGLE_COMPONENT_VECTOR_TYPE:
+ d_append_string (dpi, " __vector(");
+ d_print_comp (dpi, options, d_left (mod));
+ d_append_char (dpi, ')');
+ return;
+
default:
/* Otherwise, we have something that won't go back on the
modifier stack, so we can just print it. */
- d_print_comp (dpi, mod);
+ d_print_comp (dpi, options, mod);
return;
}
}
/* Print a function type, except for the return type. */
static void
-d_print_function_type (struct d_print_info *dpi,
+d_print_function_type (struct d_print_info *dpi, int options,
const struct demangle_component *dc,
struct d_print_mod *mods)
{
int need_paren;
- int saw_mod;
int need_space;
struct d_print_mod *p;
struct d_print_mod *hold_modifiers;
need_paren = 0;
- saw_mod = 0;
need_space = 0;
for (p = mods; p != NULL; p = p->next)
{
if (p->printed)
break;
- saw_mod = 1;
switch (p->mod->type)
{
case DEMANGLE_COMPONENT_POINTER:
break;
}
- if (d_left (dc) != NULL && ! saw_mod)
- need_paren = 1;
-
if (need_paren)
{
if (! need_space)
hold_modifiers = dpi->modifiers;
dpi->modifiers = NULL;
- d_print_mod_list (dpi, mods, 0);
+ d_print_mod_list (dpi, options, mods, 0);
if (need_paren)
d_append_char (dpi, ')');
d_append_char (dpi, '(');
if (d_right (dc) != NULL)
- d_print_comp (dpi, d_right (dc));
+ d_print_comp (dpi, options, d_right (dc));
d_append_char (dpi, ')');
- d_print_mod_list (dpi, mods, 1);
+ d_print_mod_list (dpi, options, mods, 1);
dpi->modifiers = hold_modifiers;
}
/* Print an array type, except for the element type. */
static void
-d_print_array_type (struct d_print_info *dpi,
+d_print_array_type (struct d_print_info *dpi, int options,
const struct demangle_component *dc,
struct d_print_mod *mods)
{
if (need_paren)
d_append_string (dpi, " (");
- d_print_mod_list (dpi, mods, 0);
+ d_print_mod_list (dpi, options, mods, 0);
if (need_paren)
d_append_char (dpi, ')');
d_append_char (dpi, '[');
if (d_left (dc) != NULL)
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
d_append_char (dpi, ']');
}
/* Print an operator in an expression. */
static void
-d_print_expr_op (struct d_print_info *dpi,
+d_print_expr_op (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
d_append_buffer (dpi, dc->u.s_operator.op->name,
dc->u.s_operator.op->len);
else
- d_print_comp (dpi, dc);
+ d_print_comp (dpi, options, dc);
}
/* Print a cast. */
static void
-d_print_cast (struct d_print_info *dpi,
+d_print_cast (struct d_print_info *dpi, int options,
const struct demangle_component *dc)
{
if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
- d_print_comp (dpi, d_left (dc));
+ d_print_comp (dpi, options, d_left (dc));
else
{
struct d_print_mod *hold_dpm;
dpi->templates = &dpt;
dpt.template_decl = d_left (dc);
- d_print_comp (dpi, d_left (d_left (dc)));
+ d_print_comp (dpi, options, d_left (d_left (dc)));
dpi->templates = dpt.next;
if (d_last_char (dpi) == '<')
d_append_char (dpi, ' ');
d_append_char (dpi, '<');
- d_print_comp (dpi, d_right (d_left (dc)));
+ d_print_comp (dpi, options, d_right (d_left (dc)));
/* Avoid generating two consecutive '>' characters, to avoid
the C++ syntactic ambiguity. */
if (d_last_char (dpi) == '>')
d_demangle_callback (const char *mangled, int options,
demangle_callbackref callback, void *opaque)
{
- int type;
+ enum
+ {
+ DCT_TYPE,
+ DCT_MANGLED,
+ DCT_GLOBAL_CTORS,
+ DCT_GLOBAL_DTORS
+ }
+ type;
struct d_info di;
struct demangle_component *dc;
int status;
if (mangled[0] == '_' && mangled[1] == 'Z')
- type = 0;
+ type = DCT_MANGLED;
else if (strncmp (mangled, "_GLOBAL_", 8) == 0
&& (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$')
&& (mangled[9] == 'D' || mangled[9] == 'I')
&& mangled[10] == '_')
- {
- const char *intro;
-
- intro = (mangled[9] == 'I')
- ? "global constructors keyed to "
- : "global destructors keyed to ";
-
- callback (intro, strlen (intro), opaque);
- callback (mangled + 11, strlen (mangled + 11), opaque);
- return 1;
- }
+ type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS;
else
{
if ((options & DMGL_TYPES) == 0)
return 0;
- type = 1;
+ type = DCT_TYPE;
}
cplus_demangle_init_info (mangled, options, strlen (mangled), &di);
di.subs = alloca (di.num_subs * sizeof (*di.subs));
#endif
- if (type)
- dc = cplus_demangle_type (&di);
- else
- dc = cplus_demangle_mangled_name (&di, 1);
+ switch (type)
+ {
+ case DCT_TYPE:
+ dc = cplus_demangle_type (&di);
+ break;
+ case DCT_MANGLED:
+ dc = cplus_demangle_mangled_name (&di, 1);
+ break;
+ case DCT_GLOBAL_CTORS:
+ case DCT_GLOBAL_DTORS:
+ d_advance (&di, 11);
+ dc = d_make_comp (&di,
+ (type == DCT_GLOBAL_CTORS
+ ? DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS
+ : DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS),
+ d_make_demangle_mangled_name (&di, d_str (&di)),
+ NULL);
+ d_advance (&di, strlen (d_str (&di)));
+ break;
+ }
/* If DMGL_PARAMS is set, then if we didn't consume the entire
mangled string, then we didn't successfully demangle it. If
return NULL;
}
- *palc = dgs.allocation_failure ? 1 : 0;
+ *palc = dgs.allocation_failure ? 1 : dgs.alc;
return dgs.buf;
}