| Index: libiberty/cp-demangle.c
|
| diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c
|
| index 27cc323f2a24c03c584e8ec74961d9d92e5e49b0..029151e320aadddd23642470434b5aa90761f9e1 100644
|
| --- a/libiberty/cp-demangle.c
|
| +++ b/libiberty/cp-demangle.c
|
| @@ -275,6 +275,31 @@ struct d_growable_string
|
| int allocation_failure;
|
| };
|
|
|
| +/* A demangle component and some scope captured when it was first
|
| + traversed. */
|
| +
|
| +struct d_saved_scope
|
| +{
|
| + /* The component whose scope this is. */
|
| + const struct demangle_component *container;
|
| + /* The list of templates, if any, that was current when this
|
| + scope was captured. */
|
| + struct d_print_template *templates;
|
| +};
|
| +
|
| +/* Checkpoint structure to allow backtracking. This holds copies
|
| + of the fields of struct d_info that need to be restored
|
| + if a trial parse needs to be backtracked over. */
|
| +
|
| +struct d_info_checkpoint
|
| +{
|
| + const char *n;
|
| + int next_comp;
|
| + int next_sub;
|
| + int did_subs;
|
| + int expansion;
|
| +};
|
| +
|
| enum { D_PRINT_BUFFER_LENGTH = 256 };
|
| struct d_print_info
|
| {
|
| @@ -302,6 +327,12 @@ struct d_print_info
|
| int pack_index;
|
| /* Number of d_print_flush calls so far. */
|
| unsigned long int flush_count;
|
| + /* Array of saved scopes for evaluating substitutions. */
|
| + struct d_saved_scope *saved_scopes;
|
| + /* Number of saved scopes in the above array. */
|
| + int num_saved_scopes;
|
| + /* The nearest enclosing template, if any. */
|
| + const struct demangle_component *current_template;
|
| };
|
|
|
| #ifdef CP_DEMANGLE_DEBUG
|
| @@ -382,6 +413,9 @@ static struct demangle_component **
|
| d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
|
|
|
| static struct demangle_component *
|
| +d_ref_qualifier (struct d_info *, struct demangle_component *);
|
| +
|
| +static struct demangle_component *
|
| d_function_type (struct d_info *);
|
|
|
| static struct demangle_component *
|
| @@ -425,6 +459,10 @@ d_add_substitution (struct d_info *, struct demangle_component *);
|
|
|
| static struct demangle_component *d_substitution (struct d_info *, int);
|
|
|
| +static void d_checkpoint (struct d_info *, struct d_info_checkpoint *);
|
| +
|
| +static void d_backtrack (struct d_info *, struct d_info_checkpoint *);
|
| +
|
| static void d_growable_string_init (struct d_growable_string *, size_t);
|
|
|
| static inline void
|
| @@ -508,6 +546,11 @@ d_dump (struct demangle_component *dc, int indent)
|
| case DEMANGLE_COMPONENT_NAME:
|
| printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
|
| return;
|
| + case DEMANGLE_COMPONENT_TAGGED_NAME:
|
| + printf ("tagged name\n");
|
| + d_dump (dc->u.s_binary.left, indent + 2);
|
| + d_dump (dc->u.s_binary.right, indent + 2);
|
| + return;
|
| case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
|
| printf ("template parameter %ld\n", dc->u.s_number.number);
|
| return;
|
| @@ -609,6 +652,12 @@ d_dump (struct demangle_component *dc, int indent)
|
| case DEMANGLE_COMPONENT_CONST_THIS:
|
| printf ("const this\n");
|
| break;
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + printf ("reference this\n");
|
| + break;
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| + printf ("rvalue reference this\n");
|
| + break;
|
| case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
|
| printf ("vendor type qualifier\n");
|
| break;
|
| @@ -696,6 +745,20 @@ d_dump (struct demangle_component *dc, int indent)
|
| case DEMANGLE_COMPONENT_PACK_EXPANSION:
|
| printf ("pack expansion\n");
|
| break;
|
| + case DEMANGLE_COMPONENT_TLS_INIT:
|
| + printf ("tls init function\n");
|
| + break;
|
| + case DEMANGLE_COMPONENT_TLS_WRAPPER:
|
| + printf ("tls wrapper function\n");
|
| + break;
|
| + case DEMANGLE_COMPONENT_DEFAULT_ARG:
|
| + printf ("default argument %d\n", dc->u.s_unary_num.num);
|
| + d_dump (dc->u.s_unary_num.sub, indent+2);
|
| + return;
|
| + case DEMANGLE_COMPONENT_LAMBDA:
|
| + printf ("lambda %d\n", dc->u.s_unary_num.num);
|
| + d_dump (dc->u.s_unary_num.sub, indent+2);
|
| + return;
|
| }
|
|
|
| d_dump (d_left (dc), indent + 2);
|
| @@ -803,6 +866,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
| case DEMANGLE_COMPONENT_QUAL_NAME:
|
| case DEMANGLE_COMPONENT_LOCAL_NAME:
|
| case DEMANGLE_COMPONENT_TYPED_NAME:
|
| + case DEMANGLE_COMPONENT_TAGGED_NAME:
|
| case DEMANGLE_COMPONENT_TEMPLATE:
|
| case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
|
| case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
|
| @@ -832,6 +896,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
| case DEMANGLE_COMPONENT_COVARIANT_THUNK:
|
| case DEMANGLE_COMPONENT_JAVA_CLASS:
|
| case DEMANGLE_COMPONENT_GUARD:
|
| + case DEMANGLE_COMPONENT_TLS_INIT:
|
| + case DEMANGLE_COMPONENT_TLS_WRAPPER:
|
| case DEMANGLE_COMPONENT_REFTEMP:
|
| case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
|
| case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
|
| @@ -871,6 +937,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
|
| case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| case DEMANGLE_COMPONENT_CONST_THIS:
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| case DEMANGLE_COMPONENT_ARGLIST:
|
| case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
|
| break;
|
| @@ -1109,6 +1177,8 @@ has_return_type (struct demangle_component *dc)
|
| case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| case DEMANGLE_COMPONENT_CONST_THIS:
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| return has_return_type (d_left (dc));
|
| }
|
| }
|
| @@ -1164,7 +1234,9 @@ d_encoding (struct d_info *di, int top_level)
|
| v2 demangler without DMGL_PARAMS. */
|
| while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|
| || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|
| - || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
|
| + || dc->type == DEMANGLE_COMPONENT_CONST_THIS
|
| + || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|
| + || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
|
| dc = d_left (dc);
|
|
|
| /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
|
| @@ -1178,7 +1250,9 @@ d_encoding (struct d_info *di, int top_level)
|
| dcr = d_right (dc);
|
| while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|
| || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|
| - || dcr->type == DEMANGLE_COMPONENT_CONST_THIS)
|
| + || dcr->type == DEMANGLE_COMPONENT_CONST_THIS
|
| + || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|
| + || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
|
| dcr = d_left (dcr);
|
| dc->u.s_binary.right = dcr;
|
| }
|
| @@ -1194,6 +1268,23 @@ d_encoding (struct d_info *di, int top_level)
|
| }
|
| }
|
|
|
| +/* <tagged-name> ::= <name> B <source-name> */
|
| +
|
| +static struct demangle_component *
|
| +d_abi_tags (struct d_info *di, struct demangle_component *dc)
|
| +{
|
| + char peek;
|
| + while (peek = d_peek_char (di),
|
| + peek == 'B')
|
| + {
|
| + struct demangle_component *tag;
|
| + d_advance (di, 1);
|
| + tag = d_source_name (di);
|
| + dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
|
| + }
|
| + return dc;
|
| +}
|
| +
|
| /* <name> ::= <nested-name>
|
| ::= <unscoped-name>
|
| ::= <unscoped-template-name> <template-args>
|
| @@ -1220,7 +1311,6 @@ d_name (struct d_info *di)
|
| case 'Z':
|
| return d_local_name (di);
|
|
|
| - case 'L':
|
| case 'U':
|
| return d_unqualified_name (di);
|
|
|
| @@ -1267,6 +1357,7 @@ d_name (struct d_info *di)
|
| return dc;
|
| }
|
|
|
| + case 'L':
|
| default:
|
| dc = d_unqualified_name (di);
|
| if (d_peek_char (di) == 'I')
|
| @@ -1283,8 +1374,8 @@ d_name (struct d_info *di)
|
| }
|
| }
|
|
|
| -/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
|
| - ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
|
| +/* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
|
| + ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
|
| */
|
|
|
| static struct demangle_component *
|
| @@ -1292,6 +1383,7 @@ d_nested_name (struct d_info *di)
|
| {
|
| struct demangle_component *ret;
|
| struct demangle_component **pret;
|
| + struct demangle_component *rqual;
|
|
|
| if (! d_check_char (di, 'N'))
|
| return NULL;
|
| @@ -1300,10 +1392,20 @@ d_nested_name (struct d_info *di)
|
| if (pret == NULL)
|
| return NULL;
|
|
|
| + /* Parse the ref-qualifier now and then attach it
|
| + once we have something to attach it to. */
|
| + rqual = d_ref_qualifier (di, NULL);
|
| +
|
| *pret = d_prefix (di);
|
| if (*pret == NULL)
|
| return NULL;
|
|
|
| + if (rqual)
|
| + {
|
| + d_left (rqual) = ret;
|
| + ret = rqual;
|
| + }
|
| +
|
| if (! d_check_char (di, 'E'))
|
| return NULL;
|
|
|
| @@ -1408,15 +1510,14 @@ d_prefix (struct d_info *di)
|
| static struct demangle_component *
|
| d_unqualified_name (struct d_info *di)
|
| {
|
| + struct demangle_component *ret;
|
| char peek;
|
|
|
| peek = d_peek_char (di);
|
| if (IS_DIGIT (peek))
|
| - return d_source_name (di);
|
| + ret = d_source_name (di);
|
| else if (IS_LOWER (peek))
|
| {
|
| - struct demangle_component *ret;
|
| -
|
| ret = d_operator_name (di);
|
| if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
|
| {
|
| @@ -1425,14 +1526,11 @@ d_unqualified_name (struct d_info *di)
|
| ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret,
|
| d_source_name (di));
|
| }
|
| - return ret;
|
| }
|
| else if (peek == 'C' || peek == 'D')
|
| - return d_ctor_dtor_name (di);
|
| + ret = d_ctor_dtor_name (di);
|
| else if (peek == 'L')
|
| {
|
| - struct demangle_component * ret;
|
| -
|
| d_advance (di, 1);
|
|
|
| ret = d_source_name (di);
|
| @@ -1440,22 +1538,27 @@ d_unqualified_name (struct d_info *di)
|
| return NULL;
|
| if (! d_discriminator (di))
|
| return NULL;
|
| - return ret;
|
| }
|
| else if (peek == 'U')
|
| {
|
| switch (d_peek_next_char (di))
|
| {
|
| case 'l':
|
| - return d_lambda (di);
|
| + ret = d_lambda (di);
|
| + break;
|
| case 't':
|
| - return d_unnamed_type (di);
|
| + ret = d_unnamed_type (di);
|
| + break;
|
| default:
|
| return NULL;
|
| }
|
| }
|
| else
|
| return NULL;
|
| +
|
| + if (d_peek_char (di) == 'B')
|
| + ret = d_abi_tags (di, ret);
|
| + return ret;
|
| }
|
|
|
| /* <source-name> ::= <(positive length) number> <identifier> */
|
| @@ -1582,11 +1685,13 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
| { "an", NL ("&"), 2 },
|
| { "at", NL ("alignof "), 1 },
|
| { "az", NL ("alignof "), 1 },
|
| + { "cc", NL ("const_cast"), 2 },
|
| { "cl", NL ("()"), 2 },
|
| { "cm", NL (","), 2 },
|
| { "co", NL ("~"), 1 },
|
| { "dV", NL ("/="), 2 },
|
| { "da", NL ("delete[] "), 1 },
|
| + { "dc", NL ("dynamic_cast"), 2 },
|
| { "de", NL ("*"), 1 },
|
| { "dl", NL ("delete "), 1 },
|
| { "ds", NL (".*"), 2 },
|
| @@ -1626,8 +1731,10 @@ const struct demangle_operator_info cplus_demangle_operators[] =
|
| { "qu", NL ("?"), 3 },
|
| { "rM", NL ("%="), 2 },
|
| { "rS", NL (">>="), 2 },
|
| + { "rc", NL ("reinterpret_cast"), 2 },
|
| { "rm", NL ("%"), 2 },
|
| { "rs", NL (">>"), 2 },
|
| + { "sc", NL ("static_cast"), 2 },
|
| { "st", NL ("sizeof "), 1 },
|
| { "sz", NL ("sizeof "), 1 },
|
| { "tr", NL ("throw"), 0 },
|
| @@ -1646,8 +1753,15 @@ d_operator_name (struct d_info *di)
|
| if (c1 == 'v' && IS_DIGIT (c2))
|
| return d_make_extended_operator (di, c2 - '0', d_source_name (di));
|
| else if (c1 == 'c' && c2 == 'v')
|
| - return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
|
| - cplus_demangle_type (di), NULL);
|
| + {
|
| + struct demangle_component *type;
|
| + int was_conversion = di->is_conversion;
|
| +
|
| + di->is_conversion = ! di->is_expression;
|
| + type = cplus_demangle_type (di);
|
| + di->is_conversion = was_conversion;
|
| + return d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL);
|
| + }
|
| else
|
| {
|
| /* LOW is the inclusive lower bound. */
|
| @@ -1863,6 +1977,14 @@ d_special_name (struct d_info *di)
|
| return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
|
| cplus_demangle_type (di), NULL);
|
|
|
| + case 'H':
|
| + return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT,
|
| + d_name (di), NULL);
|
| +
|
| + case 'W':
|
| + return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
|
| + d_name (di), NULL);
|
| +
|
| default:
|
| return NULL;
|
| }
|
| @@ -2118,8 +2240,28 @@ cplus_demangle_type (struct d_info *di)
|
| pret = d_cv_qualifiers (di, &ret, 0);
|
| if (pret == NULL)
|
| return NULL;
|
| - *pret = cplus_demangle_type (di);
|
| - if (! *pret || ! d_add_substitution (di, ret))
|
| + if (d_peek_char (di) == 'F')
|
| + {
|
| + /* cv-qualifiers before a function type apply to 'this',
|
| + so avoid adding the unqualified function type to
|
| + the substitution list. */
|
| + *pret = d_function_type (di);
|
| + }
|
| + else
|
| + *pret = cplus_demangle_type (di);
|
| + if (!*pret)
|
| + return NULL;
|
| + if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|
| + || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
|
| + {
|
| + /* Move the ref-qualifier outside the cv-qualifiers so that
|
| + they are printed in the right order. */
|
| + struct demangle_component *fn = d_left (*pret);
|
| + d_left (*pret) = ret;
|
| + ret = *pret;
|
| + *pret = fn;
|
| + }
|
| + if (! d_add_substitution (di, ret))
|
| return NULL;
|
| return ret;
|
| }
|
| @@ -2168,13 +2310,61 @@ cplus_demangle_type (struct d_info *di)
|
| ret = d_template_param (di);
|
| if (d_peek_char (di) == 'I')
|
| {
|
| - /* This is <template-template-param> <template-args>. The
|
| - <template-template-param> part is a substitution
|
| + /* This may be <template-template-param> <template-args>.
|
| + If this is the type for a conversion operator, we can
|
| + have a <template-template-param> here only by following
|
| + a derivation like this:
|
| +
|
| + <nested-name>
|
| + -> <template-prefix> <template-args>
|
| + -> <prefix> <template-unqualified-name> <template-args>
|
| + -> <unqualified-name> <template-unqualified-name> <template-args>
|
| + -> <source-name> <template-unqualified-name> <template-args>
|
| + -> <source-name> <operator-name> <template-args>
|
| + -> <source-name> cv <type> <template-args>
|
| + -> <source-name> cv <template-template-param> <template-args> <template-args>
|
| +
|
| + where the <template-args> is followed by another.
|
| + Otherwise, we must have a derivation like this:
|
| +
|
| + <nested-name>
|
| + -> <template-prefix> <template-args>
|
| + -> <prefix> <template-unqualified-name> <template-args>
|
| + -> <unqualified-name> <template-unqualified-name> <template-args>
|
| + -> <source-name> <template-unqualified-name> <template-args>
|
| + -> <source-name> <operator-name> <template-args>
|
| + -> <source-name> cv <type> <template-args>
|
| + -> <source-name> cv <template-param> <template-args>
|
| +
|
| + where we need to leave the <template-args> to be processed
|
| + by d_prefix (following the <template-prefix>).
|
| +
|
| + The <template-template-param> part is a substitution
|
| candidate. */
|
| - if (! d_add_substitution (di, ret))
|
| - return NULL;
|
| - ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
|
| - d_template_args (di));
|
| + if (! di->is_conversion)
|
| + {
|
| + if (! d_add_substitution (di, ret))
|
| + return NULL;
|
| + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
|
| + d_template_args (di));
|
| + }
|
| + else
|
| + {
|
| + struct demangle_component *args;
|
| + struct d_info_checkpoint checkpoint;
|
| +
|
| + d_checkpoint (di, &checkpoint);
|
| + args = d_template_args (di);
|
| + if (d_peek_char (di) == 'I')
|
| + {
|
| + if (! d_add_substitution (di, ret))
|
| + return NULL;
|
| + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
|
| + args);
|
| + }
|
| + else
|
| + d_backtrack (di, &checkpoint);
|
| + }
|
| }
|
| break;
|
|
|
| @@ -2422,7 +2612,38 @@ d_cv_qualifiers (struct d_info *di,
|
| return pret;
|
| }
|
|
|
| -/* <function-type> ::= F [Y] <bare-function-type> E */
|
| +/* <ref-qualifier> ::= R
|
| + ::= O */
|
| +
|
| +static struct demangle_component *
|
| +d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
|
| +{
|
| + struct demangle_component *ret = sub;
|
| + char peek;
|
| +
|
| + peek = d_peek_char (di);
|
| + if (peek == 'R' || peek == 'O')
|
| + {
|
| + enum demangle_component_type t;
|
| + if (peek == 'R')
|
| + {
|
| + t = DEMANGLE_COMPONENT_REFERENCE_THIS;
|
| + di->expansion += sizeof "&";
|
| + }
|
| + else
|
| + {
|
| + t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS;
|
| + di->expansion += sizeof "&&";
|
| + }
|
| + d_advance (di, 1);
|
| +
|
| + ret = d_make_comp (di, t, ret, NULL);
|
| + }
|
| +
|
| + return ret;
|
| +}
|
| +
|
| +/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] E */
|
|
|
| static struct demangle_component *
|
| d_function_type (struct d_info *di)
|
| @@ -2438,6 +2659,8 @@ d_function_type (struct d_info *di)
|
| d_advance (di, 1);
|
| }
|
| ret = d_bare_function_type (di, 1);
|
| + ret = d_ref_qualifier (di, ret);
|
| +
|
| if (! d_check_char (di, 'E'))
|
| return NULL;
|
| return ret;
|
| @@ -2460,6 +2683,10 @@ d_parmlist (struct d_info *di)
|
| char peek = d_peek_char (di);
|
| if (peek == '\0' || peek == 'E' || peek == '.')
|
| break;
|
| + if ((peek == 'R' || peek == 'O')
|
| + && d_peek_next_char (di) == 'E')
|
| + /* Function ref-qualifier, not a ref prefix for a parameter type. */
|
| + break;
|
| type = cplus_demangle_type (di);
|
| if (type == NULL)
|
| return NULL;
|
| @@ -2610,41 +2837,32 @@ d_pointer_to_member_type (struct d_info *di)
|
| {
|
| struct demangle_component *cl;
|
| struct demangle_component *mem;
|
| - struct demangle_component **pmem;
|
|
|
| if (! d_check_char (di, 'M'))
|
| return NULL;
|
|
|
| cl = cplus_demangle_type (di);
|
| -
|
| - /* The ABI specifies that any type can be a substitution source, and
|
| - that M is followed by two types, and that when a CV-qualified
|
| - type is seen both the base type and the CV-qualified types are
|
| - substitution sources. The ABI also specifies that for a pointer
|
| - to a CV-qualified member function, the qualifiers are attached to
|
| - the second type. Given the grammar, a plain reading of the ABI
|
| - suggests that both the CV-qualified member function and the
|
| - non-qualified member function are substitution sources. However,
|
| - 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(). 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 == NULL)
|
| + if (cl == NULL)
|
| return NULL;
|
|
|
| - if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
|
| - {
|
| - if (! d_add_substitution (di, mem))
|
| - return NULL;
|
| - }
|
| + /* The ABI says, "The type of a non-static member function is considered
|
| + to be different, for the purposes of substitution, from the type of a
|
| + namespace-scope or static member function whose type appears
|
| + similar. The types of two non-static member functions are considered
|
| + to be different, for the purposes of substitution, if the functions
|
| + are members of different classes. In other words, for the purposes of
|
| + substitution, the class of which the function is a member is
|
| + considered part of the type of function."
|
| +
|
| + For a pointer to member function, this call to cplus_demangle_type
|
| + will end up adding a (possibly qualified) non-member function type to
|
| + the substitution table, which is not correct; however, the member
|
| + function type will never be used in a substitution, so putting the
|
| + wrong type in the substitution table is harmless. */
|
| +
|
| + mem = cplus_demangle_type (di);
|
| + if (mem == NULL)
|
| + return NULL;
|
|
|
| return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
|
| }
|
| @@ -2809,6 +3027,18 @@ d_exprlist (struct d_info *di, char terminator)
|
| return list;
|
| }
|
|
|
| +/* Returns nonzero iff OP is an operator for a C++ cast: const_cast,
|
| + dynamic_cast, static_cast or reinterpret_cast. */
|
| +
|
| +static int
|
| +op_is_new_cast (struct demangle_component *op)
|
| +{
|
| + const char *code = op->u.s_operator.op->code;
|
| + return (code[1] == 'c'
|
| + && (code[0] == 's' || code[0] == 'd'
|
| + || code[0] == 'c' || code[0] == 'r'));
|
| +}
|
| +
|
| /* <expression> ::= <(unary) operator-name> <expression>
|
| ::= <(binary) operator-name> <expression> <expression>
|
| ::= <(trinary) operator-name> <expression> <expression> <expression>
|
| @@ -2820,8 +3050,8 @@ d_exprlist (struct d_info *di, char terminator)
|
| ::= <expr-primary>
|
| */
|
|
|
| -static struct demangle_component *
|
| -d_expression (struct d_info *di)
|
| +static inline struct demangle_component *
|
| +d_expression_1 (struct d_info *di)
|
| {
|
| char peek;
|
|
|
| @@ -2849,7 +3079,7 @@ d_expression (struct d_info *di)
|
| {
|
| d_advance (di, 2);
|
| return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
|
| - d_expression (di), NULL);
|
| + d_expression_1 (di), NULL);
|
| }
|
| else if (peek == 'f' && d_peek_next_char (di) == 'p')
|
| {
|
| @@ -2954,7 +3184,7 @@ d_expression (struct d_info *di)
|
| && d_check_char (di, '_'))
|
| operand = d_exprlist (di, 'E');
|
| else
|
| - operand = d_expression (di);
|
| + operand = d_expression_1 (di);
|
|
|
| if (suffix)
|
| /* Indicate the suffix variant for d_print_comp. */
|
| @@ -2971,7 +3201,10 @@ d_expression (struct d_info *di)
|
| struct demangle_component *left;
|
| struct demangle_component *right;
|
|
|
| - left = d_expression (di);
|
| + if (op_is_new_cast (op))
|
| + left = cplus_demangle_type (di);
|
| + else
|
| + left = d_expression_1 (di);
|
| if (!strcmp (code, "cl"))
|
| right = d_exprlist (di, 'E');
|
| else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
|
| @@ -2982,7 +3215,7 @@ d_expression (struct d_info *di)
|
| right, d_template_args (di));
|
| }
|
| else
|
| - right = d_expression (di);
|
| + right = d_expression_1 (di);
|
|
|
| return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
|
| d_make_comp (di,
|
| @@ -2998,9 +3231,9 @@ d_expression (struct d_info *di)
|
| if (!strcmp (code, "qu"))
|
| {
|
| /* ?: expression. */
|
| - first = d_expression (di);
|
| - second = d_expression (di);
|
| - third = d_expression (di);
|
| + first = d_expression_1 (di);
|
| + second = d_expression_1 (di);
|
| + third = d_expression_1 (di);
|
| }
|
| else if (code[0] == 'n')
|
| {
|
| @@ -3024,7 +3257,7 @@ d_expression (struct d_info *di)
|
| else if (d_peek_char (di) == 'i'
|
| && d_peek_next_char (di) == 'l')
|
| /* initializer-list. */
|
| - third = d_expression (di);
|
| + third = d_expression_1 (di);
|
| else
|
| return NULL;
|
| }
|
| @@ -3044,6 +3277,18 @@ d_expression (struct d_info *di)
|
| }
|
| }
|
|
|
| +static struct demangle_component *
|
| +d_expression (struct d_info *di)
|
| +{
|
| + struct demangle_component *ret;
|
| + int was_expression = di->is_expression;
|
| +
|
| + di->is_expression = 1;
|
| + ret = d_expression_1 (di);
|
| + di->is_expression = was_expression;
|
| + return ret;
|
| +}
|
| +
|
| /* <expr-primary> ::= L <type> <(value) number> E
|
| ::= L <type> <(value) float> E
|
| ::= L <mangled-name> E
|
| @@ -3109,6 +3354,7 @@ d_expr_primary (struct d_info *di)
|
|
|
| /* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
|
| ::= Z <(function) encoding> E s [<discriminator>]
|
| + ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name>
|
| */
|
|
|
| static struct demangle_component *
|
| @@ -3428,6 +3674,26 @@ d_substitution (struct d_info *di, int prefix)
|
| }
|
| }
|
|
|
| +static void
|
| +d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint)
|
| +{
|
| + checkpoint->n = di->n;
|
| + checkpoint->next_comp = di->next_comp;
|
| + checkpoint->next_sub = di->next_sub;
|
| + checkpoint->did_subs = di->did_subs;
|
| + checkpoint->expansion = di->expansion;
|
| +}
|
| +
|
| +static void
|
| +d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint)
|
| +{
|
| + di->n = checkpoint->n;
|
| + di->next_comp = checkpoint->next_comp;
|
| + di->next_sub = checkpoint->next_sub;
|
| + di->did_subs = checkpoint->did_subs;
|
| + di->expansion = checkpoint->expansion;
|
| +}
|
| +
|
| /* Initialize a growable string. */
|
|
|
| static void
|
| @@ -3521,6 +3787,31 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
|
| dpi->opaque = opaque;
|
|
|
| dpi->demangle_failure = 0;
|
| +
|
| + dpi->saved_scopes = NULL;
|
| + dpi->num_saved_scopes = 0;
|
| + dpi->current_template = NULL;
|
| +}
|
| +
|
| +/* Free a print information structure. */
|
| +
|
| +static void
|
| +d_print_free (struct d_print_info *dpi)
|
| +{
|
| + int i;
|
| +
|
| + for (i = 0; i < dpi->num_saved_scopes; i++)
|
| + {
|
| + struct d_print_template *ts, *tn;
|
| +
|
| + for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn)
|
| + {
|
| + tn = ts->next;
|
| + free (ts);
|
| + }
|
| + }
|
| +
|
| + free (dpi->saved_scopes);
|
| }
|
|
|
| /* Indicate that an error occurred during printing, and test for error. */
|
| @@ -3605,6 +3896,7 @@ cplus_demangle_print_callback (int options,
|
| demangle_callbackref callback, void *opaque)
|
| {
|
| struct d_print_info dpi;
|
| + int success;
|
|
|
| d_print_init (&dpi, callback, opaque);
|
|
|
| @@ -3612,7 +3904,9 @@ cplus_demangle_print_callback (int options,
|
|
|
| d_print_flush (&dpi);
|
|
|
| - return ! d_print_saw_error (&dpi);
|
| + success = ! d_print_saw_error (&dpi);
|
| + d_print_free (&dpi);
|
| + return success;
|
| }
|
|
|
| /* Turn components into a human readable string. OPTIONS is the
|
| @@ -3710,6 +4004,7 @@ d_find_pack (struct d_print_info *dpi,
|
|
|
| case DEMANGLE_COMPONENT_LAMBDA:
|
| case DEMANGLE_COMPONENT_NAME:
|
| + case DEMANGLE_COMPONENT_TAGGED_NAME:
|
| case DEMANGLE_COMPONENT_OPERATOR:
|
| case DEMANGLE_COMPONENT_BUILTIN_TYPE:
|
| case DEMANGLE_COMPONENT_SUB_STD:
|
| @@ -3768,6 +4063,36 @@ d_print_subexpr (struct d_print_info *dpi, int options,
|
| d_append_char (dpi, ')');
|
| }
|
|
|
| +/* Return a shallow copy of the current list of templates.
|
| + On error d_print_error is called and a partial list may
|
| + be returned. Whatever is returned must be freed. */
|
| +
|
| +static struct d_print_template *
|
| +d_copy_templates (struct d_print_info *dpi)
|
| +{
|
| + struct d_print_template *src, *result, **link = &result;
|
| +
|
| + for (src = dpi->templates; src != NULL; src = src->next)
|
| + {
|
| + struct d_print_template *dst =
|
| + (struct d_print_template *) malloc (sizeof (struct d_print_template));
|
| +
|
| + if (dst == NULL)
|
| + {
|
| + d_print_error (dpi);
|
| + break;
|
| + }
|
| +
|
| + dst->template_decl = src->template_decl;
|
| + *link = dst;
|
| + link = &dst->next;
|
| + }
|
| +
|
| + *link = NULL;
|
| +
|
| + return result;
|
| +}
|
| +
|
| /* Subroutine to handle components. */
|
|
|
| static void
|
| @@ -3778,6 +4103,13 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| without needing to modify *dc. */
|
| const struct demangle_component *mod_inner = NULL;
|
|
|
| + /* Variable used to store the current templates while a previously
|
| + captured scope is used. */
|
| + struct d_print_template *saved_templates;
|
| +
|
| + /* Nonzero if templates have been stored in the above variable. */
|
| + int need_template_restore = 0;
|
| +
|
| if (dc == NULL)
|
| {
|
| d_print_error (dpi);
|
| @@ -3795,6 +4127,13 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
|
| return;
|
|
|
| + case DEMANGLE_COMPONENT_TAGGED_NAME:
|
| + d_print_comp (dpi, options, d_left (dc));
|
| + d_append_string (dpi, "[abi:");
|
| + d_print_comp (dpi, options, d_right (dc));
|
| + d_append_char (dpi, ']');
|
| + return;
|
| +
|
| case DEMANGLE_COMPONENT_QUAL_NAME:
|
| case DEMANGLE_COMPONENT_LOCAL_NAME:
|
| d_print_comp (dpi, options, d_left (dc));
|
| @@ -3802,7 +4141,17 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| d_append_string (dpi, "::");
|
| else
|
| d_append_char (dpi, '.');
|
| - d_print_comp (dpi, options, d_right (dc));
|
| + {
|
| + struct demangle_component *local_name = d_right (dc);
|
| + if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
|
| + {
|
| + d_append_string (dpi, "{default arg#");
|
| + d_append_num (dpi, local_name->u.s_unary_num.num + 1);
|
| + d_append_string (dpi, "}::");
|
| + local_name = local_name->u.s_unary_num.sub;
|
| + }
|
| + d_print_comp (dpi, options, local_name);
|
| + }
|
| return;
|
|
|
| case DEMANGLE_COMPONENT_TYPED_NAME:
|
| @@ -3837,7 +4186,9 @@ d_print_comp (struct d_print_info *dpi, int options,
|
|
|
| if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
|
| && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
|
| - && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
|
| + && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
|
| + && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|
| + && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
|
| break;
|
|
|
| typed_name = d_left (typed_name);
|
| @@ -3871,7 +4222,10 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| 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)
|
| + || local_name->type == DEMANGLE_COMPONENT_CONST_THIS
|
| + || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|
| + || (local_name->type
|
| + == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
|
| {
|
| if (i >= sizeof adpm / sizeof adpm[0])
|
| {
|
| @@ -3918,6 +4272,12 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| {
|
| struct d_print_mod *hold_dpm;
|
| struct demangle_component *dcl;
|
| + const struct demangle_component *hold_current;
|
| +
|
| + /* This template may need to be referenced by a cast operator
|
| + contained in its subtree. */
|
| + hold_current = dpi->current_template;
|
| + dpi->current_template = dc;
|
|
|
| /* Don't push modifiers into a template definition. Doing so
|
| could give the wrong definition for a template argument.
|
| @@ -3954,6 +4314,7 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| }
|
|
|
| dpi->modifiers = hold_dpm;
|
| + dpi->current_template = hold_current;
|
|
|
| return;
|
| }
|
| @@ -4053,6 +4414,16 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| d_print_comp (dpi, options, d_left (dc));
|
| return;
|
|
|
| + case DEMANGLE_COMPONENT_TLS_INIT:
|
| + d_append_string (dpi, "TLS init function for ");
|
| + d_print_comp (dpi, options, d_left (dc));
|
| + return;
|
| +
|
| + case DEMANGLE_COMPONENT_TLS_WRAPPER:
|
| + d_append_string (dpi, "TLS wrapper function for ");
|
| + d_print_comp (dpi, options, d_left (dc));
|
| + return;
|
| +
|
| case DEMANGLE_COMPONENT_REFTEMP:
|
| d_append_string (dpi, "reference temporary #");
|
| d_print_comp (dpi, options, d_right (dc));
|
| @@ -4114,12 +4485,58 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| 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);
|
| + struct demangle_component *a;
|
| + struct d_saved_scope *scope = NULL, *scopes;
|
| + int i;
|
| +
|
| + for (i = 0; i < dpi->num_saved_scopes; i++)
|
| + if (dpi->saved_scopes[i].container == sub)
|
| + scope = &dpi->saved_scopes[i];
|
| +
|
| + if (scope == NULL)
|
| + {
|
| + size_t size;
|
| +
|
| + /* This is the first time SUB has been traversed.
|
| + We need to capture the current templates so
|
| + they can be restored if SUB is reentered as a
|
| + substitution. */
|
| + ++dpi->num_saved_scopes;
|
| + size = sizeof (struct d_saved_scope) * dpi->num_saved_scopes;
|
| + scopes = (struct d_saved_scope *) realloc (dpi->saved_scopes,
|
| + size);
|
| + if (scopes == NULL)
|
| + {
|
| + d_print_error (dpi);
|
| + return;
|
| + }
|
| +
|
| + dpi->saved_scopes = scopes;
|
| + scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1);
|
| +
|
| + scope->container = sub;
|
| + scope->templates = d_copy_templates (dpi);
|
| + if (d_print_saw_error (dpi))
|
| + return;
|
| + }
|
| + else
|
| + {
|
| + /* This traversal is reentering SUB as a substition.
|
| + Restore the original templates temporarily. */
|
| + saved_templates = dpi->templates;
|
| + dpi->templates = scope->templates;
|
| + need_template_restore = 1;
|
| + }
|
| +
|
| + a = d_lookup_template_argument (dpi, sub);
|
| if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
|
| a = d_index_template_argument (a, dpi->pack_index);
|
|
|
| if (a == NULL)
|
| {
|
| + if (need_template_restore)
|
| + dpi->templates = saved_templates;
|
| +
|
| d_print_error (dpi);
|
| return;
|
| }
|
| @@ -4138,6 +4555,8 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| case DEMANGLE_COMPONENT_CONST_THIS:
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
|
| case DEMANGLE_COMPONENT_POINTER:
|
| case DEMANGLE_COMPONENT_COMPLEX:
|
| @@ -4165,6 +4584,9 @@ d_print_comp (struct d_print_info *dpi, int options,
|
|
|
| dpi->modifiers = dpm.next;
|
|
|
| + if (need_template_restore)
|
| + dpi->templates = saved_templates;
|
| +
|
| return;
|
| }
|
|
|
| @@ -4455,6 +4877,17 @@ d_print_comp (struct d_print_info *dpi, int options,
|
| return;
|
| }
|
|
|
| + if (op_is_new_cast (d_left (dc)))
|
| + {
|
| + d_print_expr_op (dpi, options, d_left (dc));
|
| + d_append_char (dpi, '<');
|
| + d_print_comp (dpi, options, d_left (d_right (dc)));
|
| + d_append_string (dpi, ">(");
|
| + d_print_comp (dpi, options, d_right (d_right (dc)));
|
| + d_append_char (dpi, ')');
|
| + return;
|
| + }
|
| +
|
| /* We wrap an expression which uses the greater-than operator in
|
| an extra layer of parens so that it does not get confused
|
| with the '>' which ends the template parameters. */
|
| @@ -4799,7 +5232,10 @@ d_print_mod_list (struct d_print_info *dpi, int options,
|
| || (! suffix
|
| && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|
| || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|
| - || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
|
| + || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
|
| + || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|
| + || (mods->mod->type
|
| + == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
|
| {
|
| d_print_mod_list (dpi, options, mods->next, suffix);
|
| return;
|
| @@ -4854,7 +5290,9 @@ d_print_mod_list (struct d_print_info *dpi, int options,
|
|
|
| while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
|
| || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
|
| - || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
|
| + || dc->type == DEMANGLE_COMPONENT_CONST_THIS
|
| + || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
|
| + || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
|
| dc = d_left (dc);
|
|
|
| d_print_comp (dpi, options, dc);
|
| @@ -4899,9 +5337,14 @@ d_print_mod (struct d_print_info *dpi, int options,
|
| if ((options & DMGL_JAVA) == 0)
|
| d_append_char (dpi, '*');
|
| return;
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + /* For the ref-qualifier, put a space before the &. */
|
| + d_append_char (dpi, ' ');
|
| case DEMANGLE_COMPONENT_REFERENCE:
|
| d_append_char (dpi, '&');
|
| return;
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| + d_append_char (dpi, ' ');
|
| case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
|
| d_append_string (dpi, "&&");
|
| return;
|
| @@ -4973,6 +5416,8 @@ d_print_function_type (struct d_print_info *dpi, int options,
|
| case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| case DEMANGLE_COMPONENT_CONST_THIS:
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| break;
|
| default:
|
| break;
|
| @@ -5087,28 +5532,32 @@ static void
|
| 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, options, d_left (dc));
|
| - else
|
| - {
|
| - struct d_print_mod *hold_dpm;
|
| - struct d_print_template dpt;
|
| -
|
| - /* It appears that for a templated cast operator, we need to put
|
| - the template parameters in scope for the operator name, but
|
| - not for the parameters. The effect is that we need to handle
|
| - the template printing here. */
|
| -
|
| - hold_dpm = dpi->modifiers;
|
| - dpi->modifiers = NULL;
|
| + struct d_print_template dpt;
|
|
|
| + /* For a cast operator, we need the template parameters from
|
| + the enclosing template in scope for processing the type. */
|
| + if (dpi->current_template != NULL)
|
| + {
|
| dpt.next = dpi->templates;
|
| dpi->templates = &dpt;
|
| - dpt.template_decl = d_left (dc);
|
| + dpt.template_decl = dpi->current_template;
|
| + }
|
|
|
| + if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
|
| + {
|
| + d_print_comp (dpi, options, d_left (dc));
|
| + if (dpi->current_template != NULL)
|
| + dpi->templates = dpt.next;
|
| + }
|
| + else
|
| + {
|
| d_print_comp (dpi, options, d_left (d_left (dc)));
|
|
|
| - dpi->templates = dpt.next;
|
| + /* For a templated cast operator, we need to remove the template
|
| + parameters from scope after printing the operator name,
|
| + so we need to handle the template printing here. */
|
| + if (dpi->current_template != NULL)
|
| + dpi->templates = dpt.next;
|
|
|
| if (d_last_char (dpi) == '<')
|
| d_append_char (dpi, ' ');
|
| @@ -5119,8 +5568,6 @@ d_print_cast (struct d_print_info *dpi, int options,
|
| if (d_last_char (dpi) == '>')
|
| d_append_char (dpi, ' ');
|
| d_append_char (dpi, '>');
|
| -
|
| - dpi->modifiers = hold_dpm;
|
| }
|
| }
|
|
|
| @@ -5153,6 +5600,8 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len,
|
| di->last_name = NULL;
|
|
|
| di->expansion = 0;
|
| + di->is_expression = 0;
|
| + di->is_conversion = 0;
|
| }
|
|
|
| /* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI
|
| @@ -5493,14 +5942,17 @@ is_ctor_or_dtor (const char *mangled,
|
| {
|
| switch (dc->type)
|
| {
|
| + /* These cannot appear on a constructor or destructor. */
|
| + case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| + case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| + case DEMANGLE_COMPONENT_CONST_THIS:
|
| + case DEMANGLE_COMPONENT_REFERENCE_THIS:
|
| + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
|
| default:
|
| dc = NULL;
|
| break;
|
| case DEMANGLE_COMPONENT_TYPED_NAME:
|
| case DEMANGLE_COMPONENT_TEMPLATE:
|
| - case DEMANGLE_COMPONENT_RESTRICT_THIS:
|
| - case DEMANGLE_COMPONENT_VOLATILE_THIS:
|
| - case DEMANGLE_COMPONENT_CONST_THIS:
|
| dc = d_left (dc);
|
| break;
|
| case DEMANGLE_COMPONENT_QUAL_NAME:
|
|
|