case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
printf ("template argument list\n");
break;
+ case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+ printf ("initializer list\n");
+ break;
case DEMANGLE_COMPONENT_CAST:
printf ("cast\n");
break;
+ case DEMANGLE_COMPONENT_NULLARY:
+ printf ("nullary operator\n");
+ break;
case DEMANGLE_COMPONENT_UNARY:
printf ("unary operator\n");
break;
case DEMANGLE_COMPONENT_BINARY_ARGS:
case DEMANGLE_COMPONENT_TRINARY:
case DEMANGLE_COMPONENT_TRINARY_ARG1:
- case DEMANGLE_COMPONENT_TRINARY_ARG2:
case DEMANGLE_COMPONENT_LITERAL:
case DEMANGLE_COMPONENT_LITERAL_NEG:
case DEMANGLE_COMPONENT_COMPOUND_NAME:
case DEMANGLE_COMPONENT_PACK_EXPANSION:
case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+ case DEMANGLE_COMPONENT_NULLARY:
+ case DEMANGLE_COMPONENT_TRINARY_ARG2:
if (left == NULL)
return NULL;
break;
/* This needs a right parameter, but the left parameter can be
empty. */
case DEMANGLE_COMPONENT_ARRAY_TYPE:
+ case DEMANGLE_COMPONENT_INITIALIZER_LIST:
if (right == NULL)
return NULL;
break;
/* operator_name ::= many different two character encodings.
::= cv <type>
::= v <digit> <source-name>
-*/
+
+ This list is sorted for binary search. */
#define NL(s) s, (sizeof s) - 1
{ "aa", NL ("&&"), 2 },
{ "ad", NL ("&"), 1 },
{ "an", NL ("&"), 2 },
+ { "at", NL ("alignof "), 1 },
+ { "az", NL ("alignof "), 1 },
{ "cl", NL ("()"), 2 },
{ "cm", NL (","), 2 },
{ "co", NL ("~"), 1 },
{ "dV", NL ("/="), 2 },
- { "da", NL ("delete[]"), 1 },
+ { "da", NL ("delete[] "), 1 },
{ "de", NL ("*"), 1 },
- { "dl", NL ("delete"), 1 },
+ { "dl", NL ("delete "), 1 },
+ { "ds", NL (".*"), 2 },
{ "dt", NL ("."), 2 },
{ "dv", NL ("/"), 2 },
{ "eO", NL ("^="), 2 },
{ "eo", NL ("^"), 2 },
{ "eq", NL ("=="), 2 },
{ "ge", NL (">="), 2 },
+ { "gs", NL ("::"), 1 },
{ "gt", NL (">"), 2 },
{ "ix", NL ("[]"), 2 },
{ "lS", NL ("<<="), 2 },
{ "mi", NL ("-"), 2 },
{ "ml", NL ("*"), 2 },
{ "mm", NL ("--"), 1 },
- { "na", NL ("new[]"), 1 },
+ { "na", NL ("new[]"), 3 },
{ "ne", NL ("!="), 2 },
{ "ng", NL ("-"), 1 },
{ "nt", NL ("!"), 1 },
- { "nw", NL ("new"), 1 },
+ { "nw", NL ("new"), 3 },
{ "oR", NL ("|="), 2 },
{ "oo", NL ("||"), 2 },
{ "or", NL ("|"), 2 },
{ "rs", NL (">>"), 2 },
{ "st", NL ("sizeof "), 1 },
{ "sz", NL ("sizeof "), 1 },
- { "at", NL ("alignof "), 1 },
- { "az", NL ("alignof "), 1 },
+ { "tr", NL ("throw"), 0 },
+ { "tw", NL ("throw "), 1 },
{ NULL, NULL, 0, 0 }
};
d_expression (di), NULL);
if (ret && d_next_char (di) != 'E')
ret = NULL;
+ can_subst = 1;
break;
case 'p':
/* Pack expansion. */
ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
cplus_demangle_type (di), NULL);
+ can_subst = 1;
break;
case 'f':
case 'v':
ret = d_vector_type (di);
+ can_subst = 1;
break;
case 'n':
constructor or destructor. */
hold_last_name = di->last_name;
- if (! d_check_char (di, 'I'))
+ if (d_peek_char (di) != 'I'
+ && d_peek_char (di) != 'J')
return NULL;
+ d_advance (di, 1);
if (d_peek_char (di) == 'E')
{
return d_expr_primary (di);
case 'I':
+ case 'J':
/* An argument pack. */
return d_template_args (di);
}
}
-/* Subroutine of <expression> ::= cl <expression>+ E */
+/* Parse a sequence of expressions until we hit the terminator
+ character. */
static struct demangle_component *
-d_exprlist (struct d_info *di)
+d_exprlist (struct d_info *di, char terminator)
{
struct demangle_component *list = NULL;
struct demangle_component **p = &list;
- if (d_peek_char (di) == 'E')
+ if (d_peek_char (di) == terminator)
{
d_advance (di, 1);
return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
return NULL;
p = &d_right (*p);
- if (d_peek_char (di) == 'E')
+ if (d_peek_char (di) == terminator)
{
d_advance (di, 1);
break;
else
return name;
}
+ else if ((peek == 'i' || peek == 't')
+ && d_peek_next_char (di) == 'l')
+ {
+ /* Brace-enclosed initializer list, untyped or typed. */
+ struct demangle_component *type = NULL;
+ if (peek == 't')
+ type = cplus_demangle_type (di);
+ d_advance (di, 2);
+ return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
+ type, d_exprlist (di, 'E'));
+ }
else
{
struct demangle_component *op;
+ const char *code = NULL;
int args;
op = d_operator_name (di);
return NULL;
if (op->type == DEMANGLE_COMPONENT_OPERATOR)
- di->expansion += op->u.s_operator.op->len - 2;
-
- if (op->type == DEMANGLE_COMPONENT_OPERATOR
- && strcmp (op->u.s_operator.op->code, "st") == 0)
- return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
- cplus_demangle_type (di));
+ {
+ code = op->u.s_operator.op->code;
+ di->expansion += op->u.s_operator.op->len - 2;
+ if (strcmp (code, "st") == 0)
+ return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+ cplus_demangle_type (di));
+ }
switch (op->type)
{
switch (args)
{
+ case 0:
+ return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL);
+
case 1:
{
struct demangle_component *operand;
+ int suffix = 0;
+
+ if (code && (code[0] == 'p' || code[0] == 'm')
+ && code[1] == code[0])
+ /* pp_ and mm_ are the prefix variants. */
+ suffix = !d_check_char (di, '_');
+
if (op->type == DEMANGLE_COMPONENT_CAST
&& d_check_char (di, '_'))
- operand = d_exprlist (di);
+ operand = d_exprlist (di, 'E');
else
operand = d_expression (di);
- return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
- operand);
+
+ if (suffix)
+ /* Indicate the suffix variant for d_print_comp. */
+ return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+ d_make_comp (di,
+ DEMANGLE_COMPONENT_BINARY_ARGS,
+ operand, operand));
+ else
+ 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);
+ right = d_exprlist (di, 'E');
else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
{
right = d_unqualified_name (di);
{
struct demangle_component *first;
struct demangle_component *second;
+ struct demangle_component *third;
- first = d_expression (di);
- second = d_expression (di);
+ if (!strcmp (code, "qu"))
+ {
+ /* ?: expression. */
+ first = d_expression (di);
+ second = d_expression (di);
+ third = d_expression (di);
+ }
+ else if (code[0] == 'n')
+ {
+ /* new-expression. */
+ if (code[1] != 'w' && code[1] != 'a')
+ return NULL;
+ first = d_exprlist (di, '_');
+ second = cplus_demangle_type (di);
+ if (d_peek_char (di) == 'E')
+ {
+ d_advance (di, 1);
+ third = NULL;
+ }
+ else if (d_peek_char (di) == 'p'
+ && d_peek_next_char (di) == 'i')
+ {
+ /* Parenthesized initializer. */
+ d_advance (di, 2);
+ third = d_exprlist (di, 'E');
+ }
+ else if (d_peek_char (di) == 'i'
+ && d_peek_next_char (di) == 'l')
+ /* initializer-list. */
+ third = d_expression (di);
+ else
+ return NULL;
+ }
+ else
+ return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
d_make_comp (di,
DEMANGLE_COMPONENT_TRINARY_ARG1,
first,
d_make_comp (di,
DEMANGLE_COMPONENT_TRINARY_ARG2,
- second,
- d_expression (di))));
+ second, third)));
}
default:
return NULL;
{
int simple = 0;
if (dc->type == DEMANGLE_COMPONENT_NAME
+ || dc->type == DEMANGLE_COMPONENT_QUAL_NAME
+ || dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST
|| dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
simple = 1;
if (!simple)
}
return;
+ case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+ {
+ struct demangle_component *type = d_left (dc);
+ struct demangle_component *list = d_right (dc);
+
+ if (type)
+ d_print_comp (dpi, options, type);
+ d_append_char (dpi, '{');
+ d_print_comp (dpi, options, list);
+ d_append_char (dpi, '}');
+ }
+ return;
+
case DEMANGLE_COMPONENT_OPERATOR:
{
char c;
d_print_cast (dpi, options, dc);
return;
+ case DEMANGLE_COMPONENT_NULLARY:
+ d_print_expr_op (dpi, options, d_left (dc));
+ return;
+
case DEMANGLE_COMPONENT_UNARY:
- 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.
+ {
+ struct demangle_component *op = d_left (dc);
+ struct demangle_component *operand = d_right (dc);
+ const char *code = NULL;
- unary operator ... dc
- operator & ... d_left (dc)
- qualified name ... d_right (dc)
- <names> */
+ if (op->type == DEMANGLE_COMPONENT_OPERATOR)
+ {
+ code = op->u.s_operator.op->code;
+ if (!strcmp (code, "ad"))
+ {
+ /* Don't print the argument list for the address of a
+ function. */
+ if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME
+ && d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME
+ && d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ operand = d_left (operand);
+ }
+ if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS)
+ {
+ /* This indicates a suffix operator. */
+ operand = d_left (operand);
+ d_print_subexpr (dpi, options, operand);
+ d_print_expr_op (dpi, options, op);
+ return;
+ }
+ }
- 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, options, d_left (dc));
- d_append_char (dpi, ')');
- }
- d_print_subexpr (dpi, options, d_right (dc));
+ if (op->type != DEMANGLE_COMPONENT_CAST)
+ d_print_expr_op (dpi, options, op);
+ else
+ {
+ d_append_char (dpi, '(');
+ d_print_cast (dpi, options, op);
+ d_append_char (dpi, ')');
+ }
+ if (code && !strcmp (code, "gs"))
+ /* Avoid parens after '::'. */
+ d_print_comp (dpi, options, operand);
+ else if (code && !strcmp (code, "st"))
+ /* Always print parens for sizeof (type). */
+ {
+ d_append_char (dpi, '(');
+ d_print_comp (dpi, options, operand);
+ d_append_char (dpi, ')');
+ }
+ else
+ d_print_subexpr (dpi, options, operand);
+ }
return;
case DEMANGLE_COMPONENT_BINARY:
d_print_error (dpi);
return;
}
- 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))));
+ {
+ struct demangle_component *op = d_left (dc);
+ struct demangle_component *first = d_left (d_right (dc));
+ struct demangle_component *second = d_left (d_right (d_right (dc)));
+ struct demangle_component *third = d_right (d_right (d_right (dc)));
+
+ if (!strcmp (op->u.s_operator.op->code, "qu"))
+ {
+ d_print_subexpr (dpi, options, first);
+ d_print_expr_op (dpi, options, op);
+ d_print_subexpr (dpi, options, second);
+ d_append_string (dpi, " : ");
+ d_print_subexpr (dpi, options, third);
+ }
+ else
+ {
+ d_append_string (dpi, "new ");
+ if (d_left (first) != NULL)
+ {
+ d_print_subexpr (dpi, options, first);
+ d_append_char (dpi, ' ');
+ }
+ d_print_comp (dpi, options, second);
+ if (third)
+ d_print_subexpr (dpi, options, third);
+ }
+ }
return;
case DEMANGLE_COMPONENT_TRINARY_ARG1: