Index: libiberty/cp-demangle.c |
diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c |
index 0f1166be48ccee90adce883f7f143415fc1dcb37..27cc323f2a24c03c584e8ec74961d9d92e5e49b0 100644 |
--- a/libiberty/cp-demangle.c |
+++ b/libiberty/cp-demangle.c |
@@ -648,9 +648,15 @@ d_dump (struct demangle_component *dc, int indent) |
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; |
@@ -806,7 +812,6 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, |
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: |
@@ -843,6 +848,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, |
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; |
@@ -850,6 +857,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, |
/* 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; |
@@ -1411,7 +1419,12 @@ d_unqualified_name (struct d_info *di) |
ret = d_operator_name (di); |
if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) |
- di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; |
+ { |
+ di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; |
+ if (!strcmp (ret->u.s_operator.op->code, "li")) |
+ ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret, |
+ d_source_name (di)); |
+ } |
return ret; |
} |
else if (peek == 'C' || peek == 'D') |
@@ -1554,7 +1567,8 @@ d_identifier (struct d_info *di, int len) |
/* 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 |
@@ -1566,23 +1580,28 @@ const struct demangle_operator_info cplus_demangle_operators[] = |
{ "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 }, |
{ "le", NL ("<="), 2 }, |
+ { "li", NL ("operator\"\" "), 1 }, |
{ "ls", NL ("<<"), 2 }, |
{ "lt", NL ("<"), 2 }, |
{ "mI", NL ("-="), 2 }, |
@@ -1590,11 +1609,11 @@ const struct demangle_operator_info cplus_demangle_operators[] = |
{ "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 }, |
@@ -1611,8 +1630,8 @@ const struct demangle_operator_info cplus_demangle_operators[] = |
{ "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 } |
}; |
@@ -2242,12 +2261,19 @@ cplus_demangle_type (struct d_info *di) |
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 'a': |
+ /* auto */ |
+ ret = d_make_name (di, "auto", 4); |
break; |
case 'f': |
@@ -2298,6 +2324,7 @@ cplus_demangle_type (struct d_info *di) |
case 'v': |
ret = d_vector_type (di); |
+ can_subst = 1; |
break; |
case 'n': |
@@ -2675,8 +2702,10 @@ d_template_args (struct d_info *di) |
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') |
{ |
@@ -2735,6 +2764,7 @@ d_template_arg (struct d_info *di) |
return d_expr_primary (di); |
case 'I': |
+ case 'J': |
/* An argument pack. */ |
return d_template_args (di); |
@@ -2743,15 +2773,16 @@ d_template_arg (struct d_info *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); |
@@ -2768,7 +2799,7 @@ d_exprlist (struct d_info *di) |
return NULL; |
p = &d_right (*p); |
- if (d_peek_char (di) == 'E') |
+ if (d_peek_char (di) == terminator) |
{ |
d_advance (di, 1); |
break; |
@@ -2859,9 +2890,21 @@ d_expression (struct d_info *di) |
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); |
@@ -2869,12 +2912,13 @@ d_expression (struct d_info *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) |
{ |
@@ -2893,26 +2937,43 @@ d_expression (struct d_info *di) |
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); |
@@ -2932,17 +2993,50 @@ d_expression (struct d_info *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; |
@@ -3621,6 +3715,7 @@ d_find_pack (struct d_print_info *dpi, |
case DEMANGLE_COMPONENT_SUB_STD: |
case DEMANGLE_COMPONENT_CHARACTER: |
case DEMANGLE_COMPONENT_FUNCTION_PARAM: |
+ case DEMANGLE_COMPONENT_UNNAMED_TYPE: |
return NULL; |
case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: |
@@ -3662,6 +3757,8 @@ d_print_subexpr (struct d_print_info *dpi, int options, |
{ |
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) |
@@ -4257,16 +4354,32 @@ d_print_comp (struct d_print_info *dpi, int options, |
} |
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; |
+ const struct demangle_operator_info *op = dc->u.s_operator.op; |
+ int len = op->len; |
d_append_string (dpi, "operator"); |
- c = dc->u.s_operator.op->name[0]; |
- if (IS_LOWER (c)) |
+ /* Add a space before new/delete. */ |
+ if (IS_LOWER (op->name[0])) |
d_append_char (dpi, ' '); |
- d_append_buffer (dpi, dc->u.s_operator.op->name, |
- dc->u.s_operator.op->len); |
+ /* Omit a trailing space. */ |
+ if (op->name[len-1] == ' ') |
+ --len; |
+ d_append_buffer (dpi, op->name, len); |
return; |
} |
@@ -4280,55 +4393,59 @@ d_print_comp (struct d_print_info *dpi, int options, |
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: |
@@ -4393,11 +4510,33 @@ d_print_comp (struct d_print_info *dpi, int options, |
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: |