diff options
Diffstat (limited to 'rtemstoolkit/libiberty/cp-demangle.c')
-rw-r--r-- | rtemstoolkit/libiberty/cp-demangle.c | 1384 |
1 files changed, 976 insertions, 408 deletions
diff --git a/rtemstoolkit/libiberty/cp-demangle.c b/rtemstoolkit/libiberty/cp-demangle.c index 7b8d0b4..2ce984f 100644 --- a/rtemstoolkit/libiberty/cp-demangle.c +++ b/rtemstoolkit/libiberty/cp-demangle.c @@ -1,5 +1,5 @@ /* Demangler for g++ V3 ABI. - Copyright (C) 2003-2017 Free Software Foundation, Inc. + Copyright (C) 2003-2023 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@wasabisystems.com>. This file is part of the libiberty library, which is part of GCC. @@ -30,7 +30,7 @@ /* This code implements a demangler for the g++ V3 ABI. The ABI is described on this web page: - http://www.codesourcery.com/cxx-abi/abi.html#mangling + https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling This code was written while looking at the demangler written by Alex Samuel <samuel@codesourcery.com>. @@ -192,9 +192,9 @@ static void d_init_info (const char *, int, size_t, struct d_info *); #else #ifdef __STDC__ #ifdef __STDC_VERSION__ -#if __STDC_VERSION__ >= 199901L +#if __STDC_VERSION__ >= 199901L && !__STDC_NO_VLA__ #define CP_DYNAMIC_ARRAYS -#endif /* __STDC__VERSION >= 199901L */ +#endif /* __STDC_VERSION__ >= 199901L && !__STDC_NO_VLA__ */ #endif /* defined (__STDC_VERSION__) */ #endif /* defined (__STDC__) */ #endif /* ! defined (__GNUC__) */ @@ -347,9 +347,9 @@ struct d_print_info /* Number of times d_print_comp was recursively called. Should not be bigger than MAX_RECURSION_COUNT. */ int recursion; - /* Non-zero if we're printing a lambda argument. A template - parameter reference actually means 'auto'. */ - int is_lambda_arg; + /* 1 more than the number of explicit template parms of a lambda. Template + parm references >= are actually 'auto'. */ + int lambda_tpl_parms; /* The current index into any template argument packs we are using for printing, or -1 to print the whole pack. */ int pack_index; @@ -425,13 +425,16 @@ is_ctor_dtor_or_conversion (struct demangle_component *); static struct demangle_component *d_encoding (struct d_info *, int); -static struct demangle_component *d_name (struct d_info *); +static struct demangle_component *d_name (struct d_info *, int substable); static struct demangle_component *d_nested_name (struct d_info *); -static struct demangle_component *d_prefix (struct d_info *); +static int d_maybe_module_name (struct d_info *, struct demangle_component **); -static struct demangle_component *d_unqualified_name (struct d_info *); +static struct demangle_component *d_prefix (struct d_info *, int); + +static struct demangle_component *d_unqualified_name (struct d_info *, + struct demangle_component *scope, struct demangle_component *module); static struct demangle_component *d_source_name (struct d_info *); @@ -462,7 +465,7 @@ static struct demangle_component * d_bare_function_type (struct d_info *, int); static struct demangle_component * -d_class_enum_type (struct d_info *); +d_class_enum_type (struct d_info *, int); static struct demangle_component *d_array_type (struct d_info *); @@ -488,6 +491,10 @@ static struct demangle_component *d_local_name (struct d_info *); static int d_discriminator (struct d_info *); +static struct demangle_component *d_template_parm (struct d_info *, int *bad); + +static struct demangle_component *d_template_head (struct d_info *, int *bad); + static struct demangle_component *d_lambda (struct d_info *); static struct demangle_component *d_unnamed_type (struct d_info *); @@ -517,7 +524,7 @@ d_growable_string_callback_adapter (const char *, size_t, void *); static void d_print_init (struct d_print_info *, demangle_callbackref, void *, - const struct demangle_component *); + struct demangle_component *); static inline void d_print_error (struct d_print_info *); @@ -568,22 +575,6 @@ static int d_demangle_callback (const char *, int, demangle_callbackref, void *); static char *d_demangle (const char *, int, size_t *); -/* True iff TYPE is a demangling component representing a - function-type-qualifier. */ - -static int -is_fnqual_component_type (enum demangle_component_type type) -{ - return (type == DEMANGLE_COMPONENT_RESTRICT_THIS - || type == DEMANGLE_COMPONENT_VOLATILE_THIS - || type == DEMANGLE_COMPONENT_CONST_THIS - || type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS - || type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || type == DEMANGLE_COMPONENT_NOEXCEPT - || type == DEMANGLE_COMPONENT_THROW_SPEC - || type == DEMANGLE_COMPONENT_REFERENCE_THIS); -} - #define FNQUAL_COMPONENT_CASE \ case DEMANGLE_COMPONENT_RESTRICT_THIS: \ case DEMANGLE_COMPONENT_VOLATILE_THIS: \ @@ -594,6 +585,23 @@ is_fnqual_component_type (enum demangle_component_type type) case DEMANGLE_COMPONENT_NOEXCEPT: \ case DEMANGLE_COMPONENT_THROW_SPEC +/* True iff TYPE is a demangling component representing a + function-type-qualifier. */ + +static int +is_fnqual_component_type (enum demangle_component_type type) +{ + switch (type) + { + FNQUAL_COMPONENT_CASE: + return 1; + default: + break; + } + return 0; +} + + #ifdef CP_DEMANGLE_DEBUG static void @@ -624,6 +632,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_TEMPLATE_PARAM: printf ("template parameter %ld\n", dc->u.s_number.number); return; + case DEMANGLE_COMPONENT_TPARM_OBJ: + printf ("template parameter object\n"); + break; case DEMANGLE_COMPONENT_FUNCTION_PARAM: printf ("function parameter %ld\n", dc->u.s_number.number); return; @@ -641,6 +652,13 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_BUILTIN_TYPE: printf ("builtin type %s\n", dc->u.s_builtin.type->name); return; + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: + { + char suffix[2] = { dc->u.s_extended_builtin.type->suffix, 0 }; + printf ("builtin type %s%d%s\n", dc->u.s_extended_builtin.type->name, + dc->u.s_extended_builtin.type->arg, suffix); + } + return; case DEMANGLE_COMPONENT_OPERATOR: printf ("operator %s\n", dc->u.s_operator.op->name); return; @@ -764,11 +782,6 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_PTRMEM_TYPE: printf ("pointer to member type\n"); break; - case DEMANGLE_COMPONENT_FIXED_TYPE: - printf ("fixed-point type, accum? %d, sat? %d\n", - dc->u.s_fixed.accum, dc->u.s_fixed.sat); - d_dump (dc->u.s_fixed.length, indent + 2); - break; case DEMANGLE_COMPONENT_ARGLIST: printf ("argument list\n"); break; @@ -811,6 +824,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_LITERAL_NEG: printf ("negative literal\n"); break; + case DEMANGLE_COMPONENT_VENDOR_EXPR: + printf ("vendor expression\n"); + break; case DEMANGLE_COMPONENT_JAVA_RESOURCE: printf ("java resource\n"); break; @@ -857,9 +873,10 @@ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) { - if (p == NULL || s == NULL || len == 0) + if (p == NULL || s == NULL || len <= 0) return 0; p->d_printing = 0; + p->d_counting = 0; p->type = DEMANGLE_COMPONENT_NAME; p->u.s_name.s = s; p->u.s_name.len = len; @@ -876,6 +893,7 @@ cplus_demangle_fill_extended_operator (struct demangle_component *p, int args, if (p == NULL || args < 0 || name == NULL) return 0; p->d_printing = 0; + p->d_counting = 0; p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; p->u.s_extended_operator.args = args; p->u.s_extended_operator.name = name; @@ -896,6 +914,7 @@ cplus_demangle_fill_ctor (struct demangle_component *p, || (int) kind > gnu_v3_object_ctor_group) return 0; p->d_printing = 0; + p->d_counting = 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; p->u.s_ctor.name = name; @@ -916,6 +935,7 @@ cplus_demangle_fill_dtor (struct demangle_component *p, || (int) kind > gnu_v3_object_dtor_group) return 0; p->d_printing = 0; + p->d_counting = 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; p->u.s_dtor.name = name; @@ -933,6 +953,7 @@ d_make_empty (struct d_info *di) return NULL; p = &di->comps[di->next_comp]; p->d_printing = 0; + p->d_counting = 0; ++di->next_comp; return p; } @@ -967,9 +988,11 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_TRINARY_ARG1: case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: + case DEMANGLE_COMPONENT_VENDOR_EXPR: case DEMANGLE_COMPONENT_COMPOUND_NAME: case DEMANGLE_COMPONENT_VECTOR_TYPE: case DEMANGLE_COMPONENT_CLONE: + case DEMANGLE_COMPONENT_MODULE_ENTITY: if (left == NULL || right == NULL) return NULL; break; @@ -1006,6 +1029,14 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: case DEMANGLE_COMPONENT_NULLARY: case DEMANGLE_COMPONENT_TRINARY_ARG2: + case DEMANGLE_COMPONENT_TPARM_OBJ: + case DEMANGLE_COMPONENT_STRUCTURED_BINDING: + case DEMANGLE_COMPONENT_MODULE_INIT: + case DEMANGLE_COMPONENT_TEMPLATE_HEAD: + case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM: + case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM: + case DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM: + case DEMANGLE_COMPONENT_FRIEND: if (left == NULL) return NULL; break; @@ -1014,6 +1045,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, empty. */ case DEMANGLE_COMPONENT_ARRAY_TYPE: case DEMANGLE_COMPONENT_INITIALIZER_LIST: + case DEMANGLE_COMPONENT_MODULE_NAME: + case DEMANGLE_COMPONENT_MODULE_PARTITION: if (right == NULL) return NULL; break; @@ -1026,6 +1059,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_CONST: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + case DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM: FNQUAL_COMPONENT_CASE: break; @@ -1087,6 +1121,28 @@ d_make_builtin_type (struct d_info *di, return p; } +/* Add a new extended builtin type component. */ + +static struct demangle_component * +d_make_extended_builtin_type (struct d_info *di, + const struct demangle_builtin_type_info *type, + short arg, char suffix) +{ + struct demangle_component *p; + + if (type == NULL) + return NULL; + p = d_make_empty (di); + if (p != NULL) + { + p->type = DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE; + p->u.s_extended_builtin.type = type; + p->u.s_extended_builtin.arg = arg; + p->u.s_extended_builtin.suffix = suffix; + } + return p; +} + /* Add a new operator component. */ static struct demangle_component * @@ -1258,6 +1314,8 @@ has_return_type (struct demangle_component *dc) { default: return 0; + case DEMANGLE_COMPONENT_LOCAL_NAME: + return has_return_type (d_right (dc)); case DEMANGLE_COMPONENT_TEMPLATE: return ! is_ctor_dtor_or_conversion (d_left (dc)); FNQUAL_COMPONENT_CASE: @@ -1300,25 +1358,22 @@ static struct demangle_component * d_encoding (struct d_info *di, int top_level) { char peek = d_peek_char (di); + struct demangle_component *dc; if (peek == 'G' || peek == 'T') - return d_special_name (di); + dc = d_special_name (di); else { - struct demangle_component *dc; + dc = d_name (di, 0); - dc = d_name (di); - - if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) + if (!dc) + /* Failed already. */; + else if (top_level && (di->options & DMGL_PARAMS) == 0) { /* Strip off any initial CV-qualifiers, as they really apply to the `this' parameter, and they were not output by the 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_REFERENCE_THIS - || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + while (is_fnqual_component_type (dc->type)) dc = d_left (dc); /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then @@ -1327,23 +1382,42 @@ d_encoding (struct d_info *di, int top_level) which is local to a function. */ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) { - struct demangle_component *dcr; + while (d_right (dc) != NULL + && is_fnqual_component_type (d_right (dc)->type)) + d_right (dc) = d_left (d_right (dc)); - dcr = d_right (dc); - while (is_fnqual_component_type (dcr->type)) - dcr = d_left (dcr); - dc->u.s_binary.right = dcr; + if (d_right (dc) == NULL) + dc = NULL; } - - return dc; } + else + { + peek = d_peek_char (di); + if (peek != '\0' && peek != 'E') + { + struct demangle_component *ftype; - peek = d_peek_char (di); - if (dc == NULL || peek == '\0' || peek == 'E') - return dc; - return d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, dc, - d_bare_function_type (di, has_return_type (dc))); + ftype = d_bare_function_type (di, has_return_type (dc)); + if (ftype) + { + /* If this is a non-top-level local-name, clear the + return type, so it doesn't confuse the user by + being confused with the return type of whaever + this is nested within. */ + if (!top_level && dc->type == DEMANGLE_COMPONENT_LOCAL_NAME + && ftype->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) + d_left (ftype) = NULL; + + dc = d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, + dc, ftype); + } + else + dc = NULL; + } + } } + + return dc; } /* <tagged-name> ::= <name> B <source-name> */ @@ -1384,80 +1458,74 @@ d_abi_tags (struct d_info *di, struct demangle_component *dc) */ static struct demangle_component * -d_name (struct d_info *di) +d_name (struct d_info *di, int substable) { char peek = d_peek_char (di); - struct demangle_component *dc; + struct demangle_component *dc = NULL; + struct demangle_component *module = NULL; + int subst = 0; switch (peek) { case 'N': - return d_nested_name (di); + dc = d_nested_name (di); + break; case 'Z': - return d_local_name (di); + dc = d_local_name (di); + break; case 'U': - return d_unqualified_name (di); + dc = d_unqualified_name (di, NULL, NULL); + break; case 'S': { - int subst; - - if (d_peek_next_char (di) != 't') - { - dc = d_substitution (di, 0); - subst = 1; - } - else + if (d_peek_next_char (di) == 't') { d_advance (di, 2); - dc = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, - d_make_name (di, "std", 3), - d_unqualified_name (di)); + dc = d_make_name (di, "std", 3); di->expansion += 3; - subst = 0; } - if (d_peek_char (di) != 'I') + if (d_peek_char (di) == 'S') { - /* The grammar does not permit this case to occur if we - called d_substitution() above (i.e., subst == 1). We - don't bother to check. */ - } - else - { - /* This is <template-args>, which means that we just saw - <unscoped-template-name>, which is a substitution - candidate if we didn't just get it from a - substitution. */ - if (! subst) + module = d_substitution (di, 0); + if (!module) + return NULL; + if (!(module->type == DEMANGLE_COMPONENT_MODULE_NAME + || module->type == DEMANGLE_COMPONENT_MODULE_PARTITION)) { - if (! d_add_substitution (di, dc)) + if (dc) return NULL; + subst = 1; + dc = module; + module = NULL; } - dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, - d_template_args (di)); } - - return dc; } + /* FALLTHROUGH */ case 'L': default: - dc = d_unqualified_name (di); + if (!subst) + dc = d_unqualified_name (di, dc, module); if (d_peek_char (di) == 'I') { /* This is <template-args>, which means that we just saw <unscoped-template-name>, which is a substitution candidate. */ - if (! d_add_substitution (di, dc)) + if (!subst && !d_add_substitution (di, dc)) return NULL; dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); + subst = 0; } - return dc; + break; } + if (substable && !subst && !d_add_substitution (di, dc)) + return NULL; + return dc; } /* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E @@ -1482,7 +1550,7 @@ d_nested_name (struct d_info *di) once we have something to attach it to. */ rqual = d_ref_qualifier (di, NULL); - *pret = d_prefix (di); + *pret = d_prefix (di, 1); if (*pret == NULL) return NULL; @@ -1508,105 +1576,149 @@ d_nested_name (struct d_info *di) <template-prefix> ::= <prefix> <(template) unqualified-name> ::= <template-param> ::= <substitution> -*/ + + SUBST is true if we should add substitutions (as normal), false + if not (in an unresolved-name). */ static struct demangle_component * -d_prefix (struct d_info *di) +d_prefix (struct d_info *di, int substable) { struct demangle_component *ret = NULL; - while (1) + for (;;) { - char peek; - enum demangle_component_type comb_type; - struct demangle_component *dc; - - peek = d_peek_char (di); - if (peek == '\0') - return NULL; + char peek = d_peek_char (di); /* The older code accepts a <local-name> here, but I don't see that in the grammar. The older code does not accept a <template-param> here. */ - comb_type = DEMANGLE_COMPONENT_QUAL_NAME; - if (peek == 'D') + if (peek == 'D' + && (d_peek_next_char (di) == 'T' + || d_peek_next_char (di) == 't')) { - char peek2 = d_peek_next_char (di); - if (peek2 == 'T' || peek2 == 't') - /* Decltype. */ - dc = cplus_demangle_type (di); - else - /* Destructor name. */ - dc = d_unqualified_name (di); + /* Decltype. */ + if (ret) + return NULL; + ret = cplus_demangle_type (di); } - else if (IS_DIGIT (peek) - || IS_LOWER (peek) - || peek == 'C' - || peek == 'U' - || peek == 'L') - dc = d_unqualified_name (di); - else if (peek == 'S') - dc = d_substitution (di, 1); else if (peek == 'I') { if (ret == NULL) return NULL; - comb_type = DEMANGLE_COMPONENT_TEMPLATE; - dc = d_template_args (di); + struct demangle_component *dc = d_template_args (di); + if (!dc) + return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, dc); } else if (peek == 'T') - 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) + if (ret) return NULL; + ret = d_template_param (di); + } + else if (peek == 'M') + { + /* Initializer scope for a lambda. We already added it as a + substitution candidate, don't do that again. */ d_advance (di, 1); continue; } else + { + struct demangle_component *module = NULL; + if (peek == 'S') + { + module = d_substitution (di, 1); + if (!module) + return NULL; + if (!(module->type == DEMANGLE_COMPONENT_MODULE_NAME + || module->type == DEMANGLE_COMPONENT_MODULE_PARTITION)) + { + if (ret) + return NULL; + ret = module; + continue; + } + } + ret = d_unqualified_name (di, ret, module); + } + + if (!ret) + break; + + if (d_peek_char (di) == 'E') + break; + + if (substable && !d_add_substitution (di, ret)) return NULL; + } - if (ret == NULL) - ret = dc; - else - ret = d_make_comp (di, comb_type, ret, dc); + return ret; +} - if (peek != 'S' && d_peek_char (di) != 'E') +static int +d_maybe_module_name (struct d_info *di, struct demangle_component **name) +{ + while (d_peek_char (di) == 'W') + { + d_advance (di, 1); + enum demangle_component_type code = DEMANGLE_COMPONENT_MODULE_NAME; + if (d_peek_char (di) == 'P') { - if (! d_add_substitution (di, ret)) - return NULL; + code = DEMANGLE_COMPONENT_MODULE_PARTITION; + d_advance (di, 1); } + + *name = d_make_comp (di, code, *name, d_source_name (di)); + if (!*name) + return 0; + if (!d_add_substitution (di, *name)) + return 0; } + return 1; } -/* <unqualified-name> ::= <operator-name> - ::= <ctor-dtor-name> - ::= <source-name> - ::= <local-source-name> - - <local-source-name> ::= L <source-name> <discriminator> +/* <unqualified-name> ::= [<module-name>] <operator-name> [<abi-tags>] + ::= [<module-name>] <ctor-dtor-name> [<abi-tags>] + ::= [<module-name>] <source-name> [<abi-tags>] + ::= [<module-name>] F <source-name> [<abi-tags>] + ::= [<module-name>] <local-source-name> [<abi-tags>] + ::= [<module-name>] DC <source-name>+ E [<abi-tags>] + <local-source-name> ::= L <source-name> <discriminator> [<abi-tags>] */ static struct demangle_component * -d_unqualified_name (struct d_info *di) +d_unqualified_name (struct d_info *di, struct demangle_component *scope, + struct demangle_component *module) { struct demangle_component *ret; char peek; + int member_like_friend = 0; + + if (!d_maybe_module_name (di, &module)) + return NULL; peek = d_peek_char (di); + if (peek == 'F') + { + member_like_friend = 1; + d_advance (di, 1); + peek = d_peek_char (di); + } if (IS_DIGIT (peek)) ret = d_source_name (di); else if (IS_LOWER (peek)) { + int was_expr = di->is_expression; if (peek == 'o' && d_peek_next_char (di) == 'n') - d_advance (di, 2); + { + d_advance (di, 2); + /* Treat cv as naming a conversion operator. */ + di->is_expression = 0; + } ret = d_operator_name (di); + di->is_expression = was_expr; if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) { di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; @@ -1615,6 +1727,28 @@ d_unqualified_name (struct d_info *di) d_source_name (di)); } } + else if (peek == 'D' && d_peek_next_char (di) == 'C') + { + // structured binding + d_advance (di, 2); + struct demangle_component *prev = NULL; + do + { + struct demangle_component *next = + d_make_comp (di, DEMANGLE_COMPONENT_STRUCTURED_BINDING, + d_source_name (di), NULL); + if (prev) + d_right (prev) = next; + else + ret = next; + prev = next; + } + while (prev && d_peek_char (di) != 'E'); + if (prev) + d_advance (di, 1); + else + ret = NULL; + } else if (peek == 'C' || peek == 'D') ret = d_ctor_dtor_name (di); else if (peek == 'L') @@ -1644,8 +1778,15 @@ d_unqualified_name (struct d_info *di) else return NULL; + if (module) + ret = d_make_comp (di, DEMANGLE_COMPONENT_MODULE_ENTITY, ret, module); if (d_peek_char (di) == 'B') ret = d_abi_tags (di, ret); + if (member_like_friend) + ret = d_make_comp (di, DEMANGLE_COMPONENT_FRIEND, ret, NULL); + if (scope) + ret = d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, scope, ret); + return ret; } @@ -1694,7 +1835,7 @@ d_number (struct d_info *di) } if (ret > ((INT_MAX - (peek - '0')) / 10)) return -1; - ret = ret * 10 + peek - '0'; + ret = ret * 10 + (peek - '0'); d_advance (di, 1); peek = d_peek_char (di); } @@ -1774,19 +1915,23 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "ad", NL ("&"), 1 }, { "an", NL ("&"), 2 }, { "at", NL ("alignof "), 1 }, + { "aw", NL ("co_await "), 1 }, { "az", NL ("alignof "), 1 }, { "cc", NL ("const_cast"), 2 }, { "cl", NL ("()"), 2 }, { "cm", NL (","), 2 }, { "co", NL ("~"), 1 }, { "dV", NL ("/="), 2 }, + { "dX", NL ("[...]="), 3 }, /* [expr...expr] = expr */ { "da", NL ("delete[] "), 1 }, { "dc", NL ("dynamic_cast"), 2 }, { "de", NL ("*"), 1 }, + { "di", NL ("="), 2 }, /* .name = expr */ { "dl", NL ("delete "), 1 }, { "ds", NL (".*"), 2 }, { "dt", NL ("."), 2 }, { "dv", NL ("/"), 2 }, + { "dx", NL ("]="), 2 }, /* [expr] = expr */ { "eO", NL ("^="), 2 }, { "eo", NL ("^"), 2 }, { "eq", NL ("=="), 2 }, @@ -1813,6 +1958,7 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "ng", NL ("-"), 1 }, { "nt", NL ("!"), 1 }, { "nw", NL ("new"), 3 }, + { "nx", NL ("noexcept"), 1 }, { "oR", NL ("|="), 2 }, { "oo", NL ("||"), 2 }, { "or", NL ("|"), 2 }, @@ -1831,6 +1977,7 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "sP", NL ("sizeof..."), 1 }, { "sZ", NL ("sizeof..."), 1 }, { "sc", NL ("static_cast"), 2 }, + { "ss", NL ("<=>"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, { "tr", NL ("throw"), 0 }, @@ -1994,6 +2141,7 @@ d_java_resource (struct d_info *di) ::= TT <type> ::= TI <type> ::= TS <type> + ::= TA <template-arg> ::= GV <(object) name> ::= T <call-offset> <(base) encoding> ::= Tc <call-offset> <call-offset> <(base) encoding> @@ -2080,11 +2228,15 @@ d_special_name (struct d_info *di) case 'H': return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT, - d_name (di), NULL); + d_name (di, 0), NULL); case 'W': return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, - d_name (di), NULL); + d_name (di, 0), NULL); + + case 'A': + return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ, + d_template_arg (di), NULL); default: return NULL; @@ -2095,11 +2247,12 @@ d_special_name (struct d_info *di) switch (d_next_char (di)) { case 'V': - return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL); + return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, + d_name (di, 0), NULL); case 'R': { - struct demangle_component *name = d_name (di); + struct demangle_component *name = d_name (di, 0); return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name, d_number_component (di)); } @@ -2108,6 +2261,14 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, d_encoding (di, 0), NULL); + case 'I': + { + struct demangle_component *module = NULL; + if (!d_maybe_module_name (di, &module) || !module) + return NULL; + return d_make_comp (di, DEMANGLE_COMPONENT_MODULE_INIT, + module, NULL); + } case 'T': switch (d_next_char (di)) { @@ -2341,10 +2502,13 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = /* 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)"), + /* 30 */ { NL ("char8_t"), NL ("char8_t"), D_PRINT_DEFAULT }, + /* 31 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT }, + /* 32 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT }, + /* 33 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"), D_PRINT_DEFAULT }, + /* 34 */ { NL ("_Float"), NL ("_Float"), D_PRINT_FLOAT }, + /* 35 */ { NL ("std::bfloat16_t"), NL ("std::bfloat16_t"), D_PRINT_FLOAT }, }; CP_STATIC_IF_GLIBCPP_V3 @@ -2429,13 +2593,6 @@ cplus_demangle_type (struct d_info *di) ret = d_function_type (di); break; - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - case 'N': - case 'Z': - ret = d_class_enum_type (di); - break; - case 'A': ret = d_array_type (di); break; @@ -2506,39 +2663,6 @@ cplus_demangle_type (struct d_info *di) } break; - case 'S': - /* If this is a special substitution, then it is the start of - <class-enum-type>. */ - { - char peek_next; - - peek_next = d_peek_next_char (di); - if (IS_DIGIT (peek_next) - || peek_next == '_' - || IS_UPPER (peek_next)) - { - ret = d_substitution (di, 0); - /* The substituted name may have been a template name and - may be followed by tepmlate args. */ - if (d_peek_char (di) == 'I') - ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, - d_template_args (di)); - else - can_subst = 0; - } - else - { - ret = d_class_enum_type (di); - /* If the substitution was a complete type, then it is not - a new substitution candidate. However, if the - substitution was followed by template arguments, then - the whole thing is a substitution candidate. */ - if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) - can_subst = 0; - } - } - break; - case 'O': d_advance (di, 1); ret = d_make_comp (di, DEMANGLE_COMPONENT_RVALUE_REFERENCE, @@ -2631,31 +2755,54 @@ cplus_demangle_type (struct d_info *di) ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[29]); di->expansion += ret->u.s_builtin.type->len; break; + case 'u': + /* char8_t */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]); + di->expansion += ret->u.s_builtin.type->len; + break; case 's': /* char16_t */ - ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[30]); + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]); di->expansion += ret->u.s_builtin.type->len; break; case 'i': /* char32_t */ - ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]); + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]); 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; + /* DF<number>_ - _Float<number>. + DF<number>x - _Float<number>x + DF16b - std::bfloat16_t. */ + { + int arg = d_number (di); + char buf[12]; + char suffix = 0; + if (d_peek_char (di) == 'b') + { + if (arg != 16) + return NULL; + d_advance (di, 1); + ret = d_make_builtin_type (di, + &cplus_demangle_builtin_types[35]); + di->expansion += ret->u.s_builtin.type->len; + break; + } + if (d_peek_char (di) == 'x') + suffix = 'x'; + if (!suffix && d_peek_char (di) != '_') + return NULL; + ret + = d_make_extended_builtin_type (di, + &cplus_demangle_builtin_types[34], + arg, suffix); + d_advance (di, 1); + sprintf (buf, "%d", arg); + di->expansion += ret->u.s_extended_builtin.type->len + + strlen (buf) + (suffix != 0); + break; + } case 'v': ret = d_vector_type (di); @@ -2664,7 +2811,7 @@ cplus_demangle_type (struct d_info *di) case 'n': /* decltype(nullptr) */ - ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]); + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[33]); di->expansion += ret->u.s_builtin.type->len; break; @@ -2674,7 +2821,7 @@ cplus_demangle_type (struct d_info *di) break; default: - return NULL; + return d_class_enum_type (di, 1); } if (can_subst) @@ -2829,21 +2976,35 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub) static struct demangle_component * d_function_type (struct d_info *di) { - struct demangle_component *ret; + struct demangle_component *ret = NULL; - if (! d_check_char (di, 'F')) - return NULL; - if (d_peek_char (di) == 'Y') + if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0) { - /* Function has C linkage. We don't print this information. - FIXME: We should print it in verbose mode. */ - d_advance (di, 1); + if (di->recursion_level > DEMANGLE_RECURSION_LIMIT) + /* FIXME: There ought to be a way to report + that the recursion limit has been reached. */ + return NULL; + + di->recursion_level ++; } - ret = d_bare_function_type (di, 1); - ret = d_ref_qualifier (di, ret); - if (! d_check_char (di, 'E')) - return NULL; + if (d_check_char (di, 'F')) + { + if (d_peek_char (di) == 'Y') + { + /* Function has C linkage. We don't print this information. + FIXME: We should print it in verbose mode. */ + d_advance (di, 1); + } + ret = d_bare_function_type (di, 1); + ret = d_ref_qualifier (di, ret); + + if (! d_check_char (di, 'E')) + ret = NULL; + } + + if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0) + di->recursion_level --; return ret; } @@ -2933,9 +3094,9 @@ d_bare_function_type (struct d_info *di, int has_return_type) /* <class-enum-type> ::= <name> */ static struct demangle_component * -d_class_enum_type (struct d_info *di) +d_class_enum_type (struct d_info *di, int substable) { - return d_name (di); + return d_name (di, substable); } /* <array-type> ::= A <(positive dimension) number> _ <(element) type> @@ -3226,18 +3387,69 @@ op_is_new_cast (struct demangle_component *op) || code[0] == 'c' || code[0] == 'r')); } +/* <unresolved-name> ::= [gs] <base-unresolved-name> # x or (with "gs") ::x + ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x + # T::N::x /decltype(p)::N::x + ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name> + # A::x, N::y, A<T>::z; "gs" means leading "::" + ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name> + + "gs" is handled elsewhere, as a unary operator. */ + +static struct demangle_component * +d_unresolved_name (struct d_info *di) +{ + struct demangle_component *type; + struct demangle_component *name; + char peek; + + /* Consume the "sr". */ + d_advance (di, 2); + + peek = d_peek_char (di); + if (di->unresolved_name_state + && (IS_DIGIT (peek) + || IS_LOWER (peek) + || peek == 'C' + || peek == 'U' + || peek == 'L')) + { + /* The third production is ambiguous with the old unresolved-name syntax + of <type> <base-unresolved-name>; in the old mangling, A::x was mangled + as sr1A1x, now sr1AE1x. So we first try to demangle using the new + mangling, then with the old if that fails. */ + di->unresolved_name_state = -1; + type = d_prefix (di, 0); + if (d_peek_char (di) == 'E') + d_advance (di, 1); + } + else + type = cplus_demangle_type (di); + name = d_unqualified_name (di, type, NULL); + if (d_peek_char (di) == 'I') + name = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, + d_template_args (di)); + return name; +} + /* <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> - ::= sr <type> <unqualified-name> <template-args> + ::= u <source-name> <template-arg>* E # vendor extended expression + ::= <unresolved-name> ::= <expr-primary> + + <braced-expression> ::= <expression> + ::= di <field source-name> <braced-expression> # .name = expr + ::= dx <index expression> <braced-expression> # [expr] = expr + ::= dX <range begin expression> <range end expression> <braced-expression> + # [expr ... expr] = expr */ -static inline struct demangle_component * +static struct demangle_component * d_expression_1 (struct d_info *di) { char peek; @@ -3248,20 +3460,7 @@ d_expression_1 (struct d_info *di) else if (peek == 'T') return d_template_param (di); else if (peek == 's' && d_peek_next_char (di) == 'r') - { - struct demangle_component *type; - struct demangle_component *name; - - d_advance (di, 2); - type = cplus_demangle_type (di); - name = d_unqualified_name (di); - if (d_peek_char (di) != 'I') - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); - else - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, - d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, - d_template_args (di))); - } + return d_unresolved_name (di); else if (peek == 's' && d_peek_next_char (di) == 'p') { d_advance (di, 2); @@ -3299,7 +3498,7 @@ d_expression_1 (struct d_info *di) /* operator-function-id, i.e. operator+(t). */ d_advance (di, 2); - name = d_unqualified_name (di); + name = d_unqualified_name (di, NULL, NULL); if (name == NULL) return NULL; if (d_peek_char (di) == 'I') @@ -3313,14 +3512,23 @@ d_expression_1 (struct d_info *di) { /* Brace-enclosed initializer list, untyped or typed. */ struct demangle_component *type = NULL; + d_advance (di, 2); if (peek == 't') type = cplus_demangle_type (di); - if (!d_peek_next_char (di)) + if (!d_peek_char (di) || !d_peek_next_char (di)) return NULL; - d_advance (di, 2); return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST, type, d_exprlist (di, 'E')); } + else if (peek == 'u') + { + /* A vendor extended expression. */ + struct demangle_component *name, *args; + d_advance (di, 1); + name = d_source_name (di); + args = d_template_args_1 (di); + return d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_EXPR, name, args); + } else { struct demangle_component *op; @@ -3380,13 +3588,10 @@ d_expression_1 (struct d_info *di) 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); + operand = d_make_comp (di, DEMANGLE_COMPONENT_BINARY_ARGS, + operand, operand); + + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, operand); } case 2: { @@ -3400,16 +3605,30 @@ d_expression_1 (struct d_info *di) else if (code[0] == 'f') /* fold-expression. */ left = d_operator_name (di); + else if (!strcmp (code, "di")) + left = d_unqualified_name (di, NULL, NULL); else left = d_expression_1 (di); if (!strcmp (code, "cl")) right = d_exprlist (di, 'E'); 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)); + peek = d_peek_char (di); + /* These codes start a qualified name. */ + if ((peek == 'g' && d_peek_next_char (di) == 's') + || (peek == 's' && d_peek_next_char (di) == 'r')) + right = d_expression_1 (di); + else + { + /* Otherwise it's an unqualified name. We use + d_unqualified_name rather than d_expression_1 here for + old mangled names that didn't add 'on' before operator + names. */ + right = d_unqualified_name (di, NULL, NULL); + if (d_peek_char (di) == 'I') + right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, + right, d_template_args (di)); + } } else right = d_expression_1 (di); @@ -3427,7 +3646,8 @@ d_expression_1 (struct d_info *di) if (code == NULL) return NULL; - else if (!strcmp (code, "qu")) + else if (!strcmp (code, "qu") + || !strcmp (code, "dX")) { /* ?: expression. */ first = d_expression_1 (di); @@ -3531,6 +3751,17 @@ d_expr_primary (struct d_info *di) && type->u.s_builtin.type->print != D_PRINT_DEFAULT) di->expansion -= type->u.s_builtin.type->len; + if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE + && strcmp (type->u.s_builtin.type->name, + cplus_demangle_builtin_types[33].name) == 0) + { + if (d_peek_char (di) == 'E') + { + d_advance (di, 1); + return type; + } + } + /* Rather than try to interpret the literal value, we just collect it as a string. Note that it's possible to have a floating point literal here. The ABI specifies that the @@ -3571,11 +3802,14 @@ static struct demangle_component * d_local_name (struct d_info *di) { struct demangle_component *function; + struct demangle_component *name; if (! d_check_char (di, 'Z')) return NULL; function = d_encoding (di, 0); + if (!function) + return NULL; if (! d_check_char (di, 'E')) return NULL; @@ -3585,13 +3819,10 @@ d_local_name (struct d_info *di) d_advance (di, 1); if (! d_discriminator (di)) return NULL; - return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, - d_make_name (di, "string literal", - sizeof "string literal" - 1)); + name = d_make_name (di, "string literal", sizeof "string literal" - 1); } else { - struct demangle_component *name; int num = -1; if (d_peek_char (di) == 'd') @@ -3603,22 +3834,31 @@ d_local_name (struct d_info *di) return NULL; } - name = d_name (di); - 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; - } + name = d_name (di, 0); + + if (name + /* Lambdas and unnamed types have internal discriminators + and are not functions. */ + && name->type != DEMANGLE_COMPONENT_LAMBDA + && name->type != DEMANGLE_COMPONENT_UNNAMED_TYPE) + { + /* Read and ignore an optional discriminator. */ + 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); } + + /* Elide the return type of the containing function so as to not + confuse the user thinking it is the return type of whatever local + function we might be containing. */ + if (function->type == DEMANGLE_COMPONENT_TYPED_NAME + && d_right (function)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) + d_left (d_right (function)) = NULL; + + return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name); } /* <discriminator> ::= _ <number> # when number < 10 @@ -3658,32 +3898,120 @@ d_discriminator (struct d_info *di) return 1; } -/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ */ +/* <template-parm> ::= Ty + ::= Tn <type> + ::= Tt <template-head> E + ::= Tp <template-parm> */ static struct demangle_component * -d_lambda (struct d_info *di) +d_template_parm (struct d_info *di, int *bad) { - struct demangle_component *tl; - struct demangle_component *ret; - int num; + if (d_peek_char (di) != 'T') + return NULL; + + struct demangle_component *op; + enum demangle_component_type kind; + switch (d_peek_next_char (di)) + { + default: + return NULL; + + case 'p': /* Pack */ + d_advance (di, 2); + op = d_template_parm (di, bad); + kind = DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM; + if (!op) + { + *bad = 1; + return NULL; + } + break; + + case 'y': /* Typename */ + d_advance (di, 2); + op = NULL; + kind = DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM; + break; + + case 'n': /* Non-Type */ + d_advance (di, 2); + op = cplus_demangle_type (di); + kind = DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM; + if (!op) + { + *bad = 1; + return NULL; + } + break; + case 't': /* Template */ + d_advance (di, 2); + op = d_template_head (di, bad); + kind = DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM; + if (!op || !d_check_char (di, 'E')) + { + *bad = 1; + return NULL; + } + } + + return d_make_comp (di, kind, op, NULL); +} + +/* <template-head> ::= <template-head>? <template-parm> */ + +static struct demangle_component * +d_template_head (struct d_info *di, int *bad) +{ + struct demangle_component *res = NULL, **slot = &res; + struct demangle_component *op; + + while ((op = d_template_parm (di, bad))) + { + *slot = op; + slot = &d_right (op); + } + + /* Wrap it in a template head, to make concatenating with any parm list, and + printing simpler. */ + if (res) + res = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_HEAD, res, NULL); + + return res; +} + +/* <closure-type-name> ::= Ul <template-head>? <lambda-sig> E [ <nonnegative number> ] _ */ + +static struct demangle_component * +d_lambda (struct d_info *di) +{ if (! d_check_char (di, 'U')) return NULL; if (! d_check_char (di, 'l')) return NULL; - tl = d_parmlist (di); + int bad = 0; + struct demangle_component *head = d_template_head (di, &bad); + if (bad) + return NULL; + + struct demangle_component *tl = d_parmlist (di); if (tl == NULL) return NULL; + if (head) + { + d_right (head) = tl; + tl = head; + } if (! d_check_char (di, 'E')) return NULL; - num = d_compact_number (di); + int num = d_compact_number (di); if (num < 0) return NULL; - ret = d_make_empty (di); + struct demangle_component *ret = d_make_empty (di); if (ret) { ret->type = DEMANGLE_COMPONENT_LAMBDA; @@ -3691,9 +4019,6 @@ d_lambda (struct d_info *di) ret->u.s_unary_num.num = num; } - if (! d_add_substitution (di, ret)) - return NULL; - return ret; } @@ -3737,10 +4062,11 @@ d_clone_suffix (struct d_info *di, struct demangle_component *encoding) const char *pend = suffix; struct demangle_component *n; - if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_')) + if (*pend == '.' && (IS_LOWER (pend[1]) || IS_DIGIT (pend[1]) + || pend[1] == '_')) { pend += 2; - while (IS_LOWER (*pend) || *pend == '_') + while (IS_LOWER (*pend) || IS_DIGIT (*pend) || *pend == '_') ++pend; } while (*pend == '.' && IS_DIGIT (pend[1])) @@ -4012,12 +4338,14 @@ d_growable_string_callback_adapter (const char *s, size_t l, void *opaque) are larger than the actual numbers encountered. */ static void -d_count_templates_scopes (int *num_templates, int *num_scopes, - const struct demangle_component *dc) +d_count_templates_scopes (struct d_print_info *dpi, + struct demangle_component *dc) { - if (dc == NULL) + if (dc == NULL || dc->d_counting > 1 || dpi->recursion > MAX_RECURSION_COUNT) return; + ++ dc->d_counting; + switch (dc->type) { case DEMANGLE_COMPONENT_NAME: @@ -4025,20 +4353,31 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_FUNCTION_PARAM: case DEMANGLE_COMPONENT_SUB_STD: case DEMANGLE_COMPONENT_BUILTIN_TYPE: + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: case DEMANGLE_COMPONENT_OPERATOR: case DEMANGLE_COMPONENT_CHARACTER: case DEMANGLE_COMPONENT_NUMBER: case DEMANGLE_COMPONENT_UNNAMED_TYPE: + case DEMANGLE_COMPONENT_STRUCTURED_BINDING: + case DEMANGLE_COMPONENT_MODULE_NAME: + case DEMANGLE_COMPONENT_MODULE_PARTITION: + case DEMANGLE_COMPONENT_MODULE_INIT: + case DEMANGLE_COMPONENT_FIXED_TYPE: + case DEMANGLE_COMPONENT_TEMPLATE_HEAD: + case DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM: + case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM: + case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM: + case DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM: break; case DEMANGLE_COMPONENT_TEMPLATE: - (*num_templates)++; + dpi->num_copy_templates++; goto recurse_left_right; case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_RVALUE_REFERENCE: if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) - (*num_scopes)++; + dpi->num_saved_scopes++; goto recurse_left_right; case DEMANGLE_COMPONENT_QUAL_NAME: @@ -4081,6 +4420,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_VECTOR_TYPE: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + case DEMANGLE_COMPONENT_TPARM_OBJ: case DEMANGLE_COMPONENT_INITIALIZER_LIST: case DEMANGLE_COMPONENT_CAST: case DEMANGLE_COMPONENT_CONVERSION: @@ -4093,6 +4433,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_TRINARY_ARG2: case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: + case DEMANGLE_COMPONENT_VENDOR_EXPR: case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_COMPOUND_NAME: case DEMANGLE_COMPONENT_DECLTYPE: @@ -4102,42 +4443,40 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_CLONE: recurse_left_right: - d_count_templates_scopes (num_templates, num_scopes, - d_left (dc)); - d_count_templates_scopes (num_templates, num_scopes, - d_right (dc)); + /* PR 89394 - Check for too much recursion. */ + if (dpi->recursion > DEMANGLE_RECURSION_LIMIT) + /* FIXME: There ought to be a way to report to the + user that the recursion limit has been reached. */ + return; + + ++ dpi->recursion; + d_count_templates_scopes (dpi, d_left (dc)); + d_count_templates_scopes (dpi, d_right (dc)); + -- dpi->recursion; break; case DEMANGLE_COMPONENT_CTOR: - d_count_templates_scopes (num_templates, num_scopes, - dc->u.s_ctor.name); + d_count_templates_scopes (dpi, dc->u.s_ctor.name); break; case DEMANGLE_COMPONENT_DTOR: - d_count_templates_scopes (num_templates, num_scopes, - dc->u.s_dtor.name); + d_count_templates_scopes (dpi, dc->u.s_dtor.name); break; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: - d_count_templates_scopes (num_templates, num_scopes, - dc->u.s_extended_operator.name); - break; - - case DEMANGLE_COMPONENT_FIXED_TYPE: - d_count_templates_scopes (num_templates, num_scopes, - dc->u.s_fixed.length); + d_count_templates_scopes (dpi, dc->u.s_extended_operator.name); break; case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: - d_count_templates_scopes (num_templates, num_scopes, - d_left (dc)); + case DEMANGLE_COMPONENT_MODULE_ENTITY: + case DEMANGLE_COMPONENT_FRIEND: + d_count_templates_scopes (dpi, d_left (dc)); break; case DEMANGLE_COMPONENT_LAMBDA: case DEMANGLE_COMPONENT_DEFAULT_ARG: - d_count_templates_scopes (num_templates, num_scopes, - dc->u.s_unary_num.sub); + d_count_templates_scopes (dpi, dc->u.s_unary_num.sub); break; } } @@ -4146,7 +4485,7 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, static void d_print_init (struct d_print_info *dpi, demangle_callbackref callback, - void *opaque, const struct demangle_component *dc) + void *opaque, struct demangle_component *dc) { dpi->len = 0; dpi->last_char = '\0'; @@ -4160,7 +4499,7 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->demangle_failure = 0; dpi->recursion = 0; - dpi->is_lambda_arg = 0; + dpi->lambda_tpl_parms = 0; dpi->component_stack = NULL; @@ -4172,8 +4511,12 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->next_copy_template = 0; dpi->num_copy_templates = 0; - d_count_templates_scopes (&dpi->num_copy_templates, - &dpi->num_saved_scopes, dc); + d_count_templates_scopes (dpi, dc); + /* If we did not reach the recursion limit, then reset the + current recursion value back to 0, so that we can print + the templates. */ + if (dpi->recursion < DEMANGLE_RECURSION_LIMIT) + dpi->recursion = 0; dpi->num_copy_templates *= dpi->num_saved_scopes; dpi->current_template = NULL; @@ -4392,11 +4735,11 @@ d_find_pack (struct d_print_info *dpi, case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_OPERATOR: case DEMANGLE_COMPONENT_BUILTIN_TYPE: + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: case DEMANGLE_COMPONENT_SUB_STD: case DEMANGLE_COMPONENT_CHARACTER: case DEMANGLE_COMPONENT_FUNCTION_PARAM: case DEMANGLE_COMPONENT_UNNAMED_TYPE: - case DEMANGLE_COMPONENT_FIXED_TYPE: case DEMANGLE_COMPONENT_DEFAULT_ARG: case DEMANGLE_COMPONENT_NUMBER: return NULL; @@ -4595,6 +4938,91 @@ d_maybe_print_fold_expression (struct d_print_info *dpi, int options, return 1; } +/* True iff DC represents a C99-style designated initializer. */ + +static int +is_designated_init (struct demangle_component *dc) +{ + if (dc->type != DEMANGLE_COMPONENT_BINARY + && dc->type != DEMANGLE_COMPONENT_TRINARY) + return 0; + + struct demangle_component *op = d_left (dc); + const char *code = op->u.s_operator.op->code; + return (code[0] == 'd' + && (code[1] == 'i' || code[1] == 'x' || code[1] == 'X')); +} + +/* If DC represents a C99-style designated initializer, print it and return + true; otherwise, return false. */ + +static int +d_maybe_print_designated_init (struct d_print_info *dpi, int options, + struct demangle_component *dc) +{ + if (!is_designated_init (dc)) + return 0; + + const char *code = d_left (dc)->u.s_operator.op->code; + + struct demangle_component *operands = d_right (dc); + struct demangle_component *op1 = d_left (operands); + struct demangle_component *op2 = d_right (operands); + + if (code[1] == 'i') + d_append_char (dpi, '.'); + else + d_append_char (dpi, '['); + + d_print_comp (dpi, options, op1); + if (code[1] == 'X') + { + d_append_string (dpi, " ... "); + d_print_comp (dpi, options, d_left (op2)); + op2 = d_right (op2); + } + if (code[1] != 'i') + d_append_char (dpi, ']'); + if (is_designated_init (op2)) + { + /* Don't put '=' or '(' between chained designators. */ + d_print_comp (dpi, options, op2); + } + else + { + d_append_char (dpi, '='); + d_print_subexpr (dpi, options, op2); + } + return 1; +} + +static void +d_print_lambda_parm_name (struct d_print_info *dpi, int type, unsigned index) +{ + const char *str; + switch (type) + { + default: + dpi->demangle_failure = 1; + str = ""; + break; + + case DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM: + str = "$T"; + break; + + case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM: + str = "$N"; + break; + + case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM: + str = "$TT"; + break; + } + d_append_string (dpi, str); + d_append_num (dpi, index); +} + /* Subroutine to handle components. */ static void @@ -4636,6 +5064,38 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_append_char (dpi, ']'); return; + case DEMANGLE_COMPONENT_STRUCTURED_BINDING: + d_append_char (dpi, '['); + for (;;) + { + d_print_comp (dpi, options, d_left (dc)); + dc = d_right (dc); + if (!dc) + break; + d_append_string (dpi, ", "); + } + d_append_char (dpi, ']'); + return; + + case DEMANGLE_COMPONENT_MODULE_ENTITY: + d_print_comp (dpi, options, d_left (dc)); + d_append_char (dpi, '@'); + d_print_comp (dpi, options, d_right (dc)); + return; + + case DEMANGLE_COMPONENT_MODULE_NAME: + case DEMANGLE_COMPONENT_MODULE_PARTITION: + { + if (d_left (dc)) + d_print_comp (dpi, options, d_left (dc)); + char c = dc->type == DEMANGLE_COMPONENT_MODULE_PARTITION + ? ':' : d_left (dc) ? '.' : 0; + if (c) + d_append_char (dpi, c); + d_print_comp (dpi, options, d_right (dc)); + } + return; + case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: d_print_comp (dpi, options, d_left (dc)); @@ -4698,32 +5158,17 @@ d_print_comp_inner (struct d_print_info *dpi, int options, return; } - /* If typed_name is a template, then it applies to the - function type as well. */ - if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) - { - dpt.next = dpi->templates; - dpi->templates = &dpt; - dpt.template_decl = typed_name; - } - /* If typed_name is a DEMANGLE_COMPONENT_LOCAL_NAME, then there may be CV-qualifiers on its right argument which - really apply here; this happens when parsing a class which + really apply here; this happens when parsing a class that is local to a function. */ if (typed_name->type == DEMANGLE_COMPONENT_LOCAL_NAME) { - 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; - if (local_name == NULL) - { - d_print_error (dpi); - return; - } - while (is_fnqual_component_type (local_name->type)) + typed_name = d_right (typed_name); + if (typed_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) + typed_name = typed_name->u.s_unary_num.sub; + while (typed_name != NULL + && is_fnqual_component_type (typed_name->type)) { if (i >= sizeof adpm / sizeof adpm[0]) { @@ -4735,15 +5180,29 @@ d_print_comp_inner (struct d_print_info *dpi, int options, adpm[i].next = &adpm[i - 1]; dpi->modifiers = &adpm[i]; - adpm[i - 1].mod = local_name; + adpm[i - 1].mod = typed_name; adpm[i - 1].printed = 0; adpm[i - 1].templates = dpi->templates; ++i; - local_name = d_left (local_name); + typed_name = d_left (typed_name); + } + if (typed_name == NULL) + { + d_print_error (dpi); + return; } } + /* If typed_name is a template, then it applies to the + function type as well. */ + if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) + { + dpt.next = dpi->templates; + dpi->templates = &dpt; + dpt.template_decl = typed_name; + } + d_print_comp (dpi, options, d_right (dc)); if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) @@ -4818,7 +5277,21 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } case DEMANGLE_COMPONENT_TEMPLATE_PARAM: - if (dpi->is_lambda_arg) + if (dpi->lambda_tpl_parms > dc->u.s_number.number + 1) + { + const struct demangle_component *a + = d_left (dpi->templates->template_decl); + unsigned c; + for (c = dc->u.s_number.number; a && c; c--) + a = d_right (a); + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM) + a = d_left (a); + if (!a) + dpi->demangle_failure = 1; + else + d_print_lambda_parm_name (dpi, a->type, dc->u.s_number.number); + } + else if (dpi->lambda_tpl_parms) { /* Show the template parm index, as that's how g++ displays these, and future proofs us against potential @@ -4854,6 +5327,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } return; + case DEMANGLE_COMPONENT_TPARM_OBJ: + d_append_string (dpi, "template parameter object for "); + d_print_comp (dpi, options, d_left (dc)); + return; + case DEMANGLE_COMPONENT_CTOR: d_print_comp (dpi, options, dc->u.s_ctor.name); return; @@ -4863,6 +5341,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_print_comp (dpi, options, dc->u.s_dtor.name); return; + case DEMANGLE_COMPONENT_MODULE_INIT: + d_append_string (dpi, "initializer for module "); + d_print_comp (dpi, options, d_left (dc)); + return; + case DEMANGLE_COMPONENT_VTABLE: d_append_string (dpi, "vtable for "); d_print_comp (dpi, options, d_left (dc)); @@ -4989,7 +5472,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, { /* Handle reference smashing: & + && = &. */ struct demangle_component *sub = d_left (dc); - if (!dpi->is_lambda_arg + if (!dpi->lambda_tpl_parms && sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) { struct d_saved_scope *scope = d_get_saved_scope (dpi, sub); @@ -5100,6 +5583,14 @@ d_print_comp_inner (struct d_print_info *dpi, int options, dc->u.s_builtin.type->java_len); return; + case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE: + d_append_buffer (dpi, dc->u.s_extended_builtin.type->name, + dc->u.s_extended_builtin.type->len); + d_append_num (dpi, dc->u.s_extended_builtin.arg); + if (dc->u.s_extended_builtin.suffix) + d_append_buffer (dpi, &dc->u.s_extended_builtin.suffix, 1); + return; + case DEMANGLE_COMPONENT_VENDOR_TYPE: d_print_comp (dpi, options, d_left (dc)); return; @@ -5238,22 +5729,6 @@ d_print_comp_inner (struct d_print_info *dpi, int options, 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: if (d_left (dc) != NULL) @@ -5374,8 +5849,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options, 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). */ + else if (code && (!strcmp (code, "st") || !strcmp (code, "nx"))) + /* Always print parens for sizeof (type) and noexcept(expr). */ { d_append_char (dpi, '('); d_print_comp (dpi, options, operand); @@ -5407,6 +5882,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, if (d_maybe_print_fold_expression (dpi, options, dc)) return; + if (d_maybe_print_designated_init (dpi, options, dc)) + 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. */ @@ -5464,6 +5942,8 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } if (d_maybe_print_fold_expression (dpi, options, dc)) return; + if (d_maybe_print_designated_init (dpi, options, dc)) + return; { struct demangle_component *op = d_left (dc); struct demangle_component *first = d_left (d_right (dc)); @@ -5583,6 +6063,13 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } return; + case DEMANGLE_COMPONENT_VENDOR_EXPR: + d_print_comp (dpi, options, d_left (dc)); + d_append_char (dpi, '('); + d_print_comp (dpi, options, d_right (dc)); + d_append_char (dpi, ')'); + return; + case DEMANGLE_COMPONENT_NUMBER: d_append_num (dpi, dc->u.s_number.number); return; @@ -5609,9 +6096,10 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_PACK_EXPANSION: { - int len; - int i; - struct demangle_component *a = d_find_pack (dpi, d_left (dc)); + struct demangle_component *a = NULL; + + if (!dpi->lambda_tpl_parms) + a = d_find_pack (dpi, d_left (dc)); if (a == NULL) { /* d_find_pack won't find anything if the only packs involved @@ -5619,17 +6107,20 @@ d_print_comp_inner (struct d_print_info *dpi, int options, 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) + else { - dpi->pack_index = i; - d_print_comp (dpi, options, dc); - if (i < len-1) - d_append_string (dpi, ", "); + int len = d_pack_length (a); + int i; + + dc = d_left (dc); + for (i = 0; i < len; ++i) + { + if (i) + d_append_string (dpi, ", "); + dpi->pack_index = i; + d_print_comp (dpi, options, dc); + } } } return; @@ -5659,15 +6150,50 @@ d_print_comp_inner (struct d_print_info *dpi, int options, return; case DEMANGLE_COMPONENT_LAMBDA: - d_append_string (dpi, "{lambda("); - /* Generic lambda auto parms are mangled as the template type - parm they are. */ - dpi->is_lambda_arg++; - d_print_comp (dpi, options, dc->u.s_unary_num.sub); - dpi->is_lambda_arg--; - d_append_string (dpi, ")#"); - d_append_num (dpi, dc->u.s_unary_num.num + 1); - d_append_char (dpi, '}'); + { + d_append_string (dpi, "{lambda"); + struct demangle_component *parms = dc->u.s_unary_num.sub; + struct d_print_template dpt; + /* Generic lambda auto parms are mangled as the (synthedic) template + type parm they are. We need to tell the printer that (a) we're in + a lambda, and (b) the number of synthetic parms. */ + int saved_tpl_parms = dpi->lambda_tpl_parms; + dpi->lambda_tpl_parms = 0; + /* Hang any lambda head as-if template args. */ + dpt.template_decl = NULL; + dpt.next = dpi->templates; + dpi->templates = &dpt; + if (parms && parms->type == DEMANGLE_COMPONENT_TEMPLATE_HEAD) + { + dpt.template_decl = parms; + + d_append_char (dpi, '<'); + struct demangle_component *parm; + for (parm = d_left (parms); parm; parm = d_right (parm)) + { + if (dpi->lambda_tpl_parms++) + d_append_string (dpi, ", "); + d_print_comp (dpi, options, parm); + d_append_char (dpi, ' '); + if (parm->type == DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM) + parm = d_left (parm); + d_print_lambda_parm_name (dpi, parm->type, + dpi->lambda_tpl_parms - 1); + } + d_append_char (dpi, '>'); + + parms = d_right (parms); + } + dpi->lambda_tpl_parms++; + + d_append_char (dpi, '('); + d_print_comp (dpi, options, parms); + dpi->lambda_tpl_parms = saved_tpl_parms; + dpi->templates = dpt.next; + 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: @@ -5683,6 +6209,45 @@ d_print_comp_inner (struct d_print_info *dpi, int options, d_append_char (dpi, ']'); return; + case DEMANGLE_COMPONENT_FRIEND: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, "[friend]"); + return; + + case DEMANGLE_COMPONENT_TEMPLATE_HEAD: + { + d_append_char (dpi, '<'); + int count = 0; + struct demangle_component *parm; + for (parm = d_left (dc); parm; parm = d_right (parm)) + { + if (count++) + d_append_string (dpi, ", "); + d_print_comp (dpi, options, parm); + } + d_append_char (dpi, '>'); + } + return; + + case DEMANGLE_COMPONENT_TEMPLATE_TYPE_PARM: + d_append_string (dpi, "typename"); + return; + + case DEMANGLE_COMPONENT_TEMPLATE_NON_TYPE_PARM: + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_TEMPLATE_TEMPLATE_PARM: + d_append_string (dpi, "template"); + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, " class"); + return; + + case DEMANGLE_COMPONENT_TEMPLATE_PACK_PARM: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, "..."); + return; + default: d_print_error (dpi); return; @@ -5913,10 +6478,10 @@ d_print_mod (struct d_print_info *dpi, int options, d_append_string (dpi, "&&"); return; case DEMANGLE_COMPONENT_COMPLEX: - d_append_string (dpi, "complex "); + d_append_string (dpi, " _Complex"); return; case DEMANGLE_COMPONENT_IMAGINARY: - d_append_string (dpi, "imaginary "); + d_append_string (dpi, " _Imaginary"); return; case DEMANGLE_COMPONENT_PTRMEM_TYPE: if (d_last_char (dpi) != '(') @@ -6112,32 +6677,10 @@ d_print_conversion (struct d_print_info *dpi, int options, 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))); - - /* 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; + d_print_comp (dpi, options, d_left (dc)); - if (d_last_char (dpi) == '<') - d_append_char (dpi, ' '); - d_append_char (dpi, '<'); - 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_append_char (dpi, ' '); - d_append_char (dpi, '>'); - } + if (dpi->current_template != NULL) + dpi->templates = dpt.next; } /* Initialize the information structure we use to pass around @@ -6154,13 +6697,13 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len, di->n = mangled; - /* We can not need more components than twice the number of chars in + /* We cannot need more components than twice the number of chars in the mangled string. Most components correspond directly to chars, but the ARGLIST types are exceptions. */ di->num_comps = 2 * len; di->next_comp = 0; - /* Similarly, we can not need more substitutions than there are + /* Similarly, we cannot need more substitutions than there are chars in the mangled string. */ di->num_subs = len; di->next_sub = 0; @@ -6170,6 +6713,7 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len, di->expansion = 0; di->is_expression = 0; di->is_conversion = 0; + di->recursion_level = 0; } /* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI @@ -6207,8 +6751,25 @@ d_demangle_callback (const char *mangled, int options, type = DCT_TYPE; } + di.unresolved_name_state = 1; + + again: cplus_demangle_init_info (mangled, options, strlen (mangled), &di); + /* PR 87675 - Check for a mangled string that is so long + that we do not have enough stack space to demangle it. */ + if (((options & DMGL_NO_RECURSE_LIMIT) == 0) + /* This check is a bit arbitrary, since what we really want to do is to + compare the sizes of the di.comps and di.subs arrays against the + amount of stack space remaining. But there is no portable way to do + this, so instead we use the recursion limit as a guide to the maximum + size of the arrays. */ + && (unsigned long) di.num_comps > DEMANGLE_RECURSION_LIMIT) + { + /* FIXME: We need a way to indicate that a stack limit has been reached. */ + return 0; + } + { #ifdef CP_DYNAMIC_ARRAYS __extension__ struct demangle_component comps[di.num_comps]; @@ -6251,6 +6812,13 @@ d_demangle_callback (const char *mangled, int options, if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') dc = NULL; + /* See discussion in d_unresolved_name. */ + if (dc == NULL && di.unresolved_name_state == -1) + { + di.unresolved_name_state = 0; + goto again; + } + #ifdef CP_DEMANGLE_DEBUG d_dump (dc, 0); #endif |