X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=libiberty%2Fcp-demangle.c;h=aa78c86dd443c5078c5f440ebeaafd01ae3cd8ec;hb=d043f8c867f85f1c36cc957da8204fe2907b3aea;hp=0c6d71436e3f16b252278230f8732f05b139f2d2;hpb=fa3fcee7b8c73070306ec358e730d1dfcac246bf;p=deliverable%2Fbinutils-gdb.git diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index 0c6d71436e..aa78c86dd4 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1,6 +1,5 @@ /* Demangler for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2014 - Free Software Foundation, Inc. + Copyright (C) 2003-2019 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. @@ -31,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 . @@ -173,10 +172,10 @@ static struct demangle_component *d_mangled_name (struct d_info *, int); static struct demangle_component *d_type (struct d_info *); #define cplus_demangle_print d_print -static char *d_print (int, const struct demangle_component *, int, size_t *); +static char *d_print (int, struct demangle_component *, int, size_t *); #define cplus_demangle_print_callback d_print_callback -static int d_print_callback (int, const struct demangle_component *, +static int d_print_callback (int, struct demangle_component *, demangle_callbackref, void *); #define cplus_demangle_init_info d_init_info @@ -193,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__) */ @@ -265,7 +264,7 @@ struct d_print_mod in which they appeared in the mangled string. */ struct d_print_mod *next; /* The modifier. */ - const struct demangle_component *mod; + struct demangle_component *mod; /* Whether this modifier was printed. */ int printed; /* The list of templates which applies to this modifier. */ @@ -317,10 +316,12 @@ struct d_info_checkpoint const char *n; int next_comp; int next_sub; - int did_subs; int expansion; }; +/* Maximum number of times d_print_comp may be called recursively. */ +#define MAX_RECURSION_COUNT 1024 + enum { D_PRINT_BUFFER_LENGTH = 256 }; struct d_print_info { @@ -343,6 +344,12 @@ struct d_print_info struct d_print_mod *modifiers; /* Set to 1 if we saw a demangling error. */ int demangle_failure; + /* 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; /* The current index into any template argument packs we are using for printing, or -1 to print the whole pack. */ int pack_index; @@ -436,6 +443,8 @@ static struct demangle_component *d_operator_name (struct d_info *); static struct demangle_component *d_special_name (struct d_info *); +static struct demangle_component *d_parmlist (struct d_info *); + static int d_call_offset (struct d_info *, int); static struct demangle_component *d_ctor_dtor_name (struct d_info *); @@ -526,7 +535,7 @@ static inline void d_append_string (struct d_print_info *, const char *); static inline char d_last_char (struct d_print_info *); static void -d_print_comp (struct d_print_info *, int, const struct demangle_component *); +d_print_comp (struct d_print_info *, int, struct demangle_component *); static void d_print_java_identifier (struct d_print_info *, const char *, int); @@ -535,30 +544,57 @@ static void d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int); static void -d_print_mod (struct d_print_info *, int, const struct demangle_component *); +d_print_mod (struct d_print_info *, int, struct demangle_component *); static void d_print_function_type (struct d_print_info *, int, - const struct demangle_component *, + struct demangle_component *, struct d_print_mod *); static void d_print_array_type (struct d_print_info *, int, - const struct demangle_component *, + struct demangle_component *, struct d_print_mod *); static void -d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); +d_print_expr_op (struct d_print_info *, int, struct demangle_component *); static void d_print_cast (struct d_print_info *, int, - const struct demangle_component *); + struct demangle_component *); static void d_print_conversion (struct d_print_info *, int, - const struct demangle_component *); + struct demangle_component *); static int d_demangle_callback (const char *, int, demangle_callbackref, void *); static char *d_demangle (const char *, int, size_t *); +#define FNQUAL_COMPONENT_CASE \ + 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_TRANSACTION_SAFE: \ + 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 @@ -589,6 +625,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; @@ -822,8 +861,9 @@ 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->type = DEMANGLE_COMPONENT_NAME; p->u.s_name.s = s; p->u.s_name.len = len; @@ -839,6 +879,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->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; p->u.s_extended_operator.args = args; p->u.s_extended_operator.name = name; @@ -858,6 +899,7 @@ cplus_demangle_fill_ctor (struct demangle_component *p, || (int) kind < gnu_v3_complete_object_ctor || (int) kind > gnu_v3_object_ctor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_CTOR; p->u.s_ctor.kind = kind; p->u.s_ctor.name = name; @@ -877,6 +919,7 @@ cplus_demangle_fill_dtor (struct demangle_component *p, || (int) kind < gnu_v3_deleting_dtor || (int) kind > gnu_v3_object_dtor_group) return 0; + p->d_printing = 0; p->type = DEMANGLE_COMPONENT_DTOR; p->u.s_dtor.kind = kind; p->u.s_dtor.name = name; @@ -893,6 +936,7 @@ d_make_empty (struct d_info *di) if (di->next_comp >= di->num_comps) return NULL; p = &di->comps[di->next_comp]; + p->d_printing = 0; ++di->next_comp; return p; } @@ -966,6 +1010,7 @@ 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: if (left == NULL) return NULL; break; @@ -984,14 +1029,9 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_RESTRICT: case DEMANGLE_COMPONENT_VOLATILE: case DEMANGLE_COMPONENT_CONST: - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + FNQUAL_COMPONENT_CASE: break; /* Other types should not be seen here. */ @@ -1223,14 +1263,11 @@ 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)); - 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_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: return has_return_type (d_left (dc)); } } @@ -1270,56 +1307,66 @@ 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); - 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_TRANSACTION_SAFE - || 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 - there may be CV-qualifiers on its right argument which + there may be function-qualifiers on its right argument which really apply here; this happens when parsing a class which is local to a function. */ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) { - struct demangle_component *dcr; - - 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_TRANSACTION_SAFE - || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) - dcr = d_left (dcr); - dc->u.s_binary.right = dcr; - } + while (d_right (dc) != NULL + && is_fnqual_component_type (d_right (dc)->type)) + d_right (dc) = d_left (d_right (dc)); - return dc; + if (d_right (dc) == NULL) + dc = NULL; + } } + 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; } /* ::= B */ @@ -1580,6 +1627,8 @@ d_unqualified_name (struct d_info *di) ret = d_source_name (di); else if (IS_LOWER (peek)) { + if (peek == 'o' && d_peek_next_char (di) == 'n') + d_advance (di, 2); ret = d_operator_name (di); if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) { @@ -1666,6 +1715,8 @@ d_number (struct d_info *di) ret = - ret; return ret; } + if (ret > ((INT_MAX - (peek - '0')) / 10)) + return -1; ret = ret * 10 + peek - '0'; d_advance (di, 1); peek = d_peek_char (di); @@ -1966,6 +2017,7 @@ d_java_resource (struct d_info *di) ::= TT ::= TI ::= TS + ::= TA ::= GV <(object) name> ::= T <(base) encoding> ::= Tc <(base) encoding> @@ -2058,6 +2110,10 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, d_name (di), NULL); + case 'A': + return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ, + d_template_arg (di), NULL); + default: return NULL; } @@ -2067,7 +2123,8 @@ 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), NULL); case 'R': { @@ -2168,6 +2225,13 @@ d_ctor_dtor_name (struct d_info *di) case 'C': { enum gnu_v3_ctor_kinds kind; + int inheriting = 0; + + if (d_peek_next_char (di) == 'I') + { + inheriting = 1; + d_advance (di, 1); + } switch (d_peek_next_char (di)) { @@ -2189,7 +2253,12 @@ d_ctor_dtor_name (struct d_info *di) default: return NULL; } + d_advance (di, 2); + + if (inheriting) + cplus_demangle_type (di); + return d_make_ctor (di, kind, di->last_name); } @@ -2227,6 +2296,24 @@ d_ctor_dtor_name (struct d_info *di) } } +/* True iff we're looking at an order-insensitive type-qualifier, including + function-type-qualifiers. */ + +static int +next_is_type_qual (struct d_info *di) +{ + char peek = d_peek_char (di); + if (peek == 'r' || peek == 'V' || peek == 'K') + return 1; + if (peek == 'D') + { + peek = d_peek_next_char (di); + if (peek == 'x' || peek == 'o' || peek == 'O' || peek == 'w') + return 1; + } + return 0; +} + /* ::= ::= ::= @@ -2283,9 +2370,10 @@ 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 }, }; @@ -2312,9 +2400,7 @@ cplus_demangle_type (struct d_info *di) __vector, and it treats it as order-sensitive when mangling names. */ - peek = d_peek_char (di); - if (peek == 'r' || peek == 'V' || peek == 'K' - || (peek == 'D' && d_peek_next_char (di) == 'x')) + if (next_is_type_qual (di)) { struct demangle_component **pret; @@ -2349,6 +2435,7 @@ cplus_demangle_type (struct d_info *di) can_subst = 1; + peek = d_peek_char (di); switch (peek) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': @@ -2549,7 +2636,11 @@ cplus_demangle_type (struct d_info *di) /* auto */ ret = d_make_name (di, "auto", 4); break; - + case 'c': + /* decltype(auto) */ + ret = d_make_name (di, "decltype(auto)", 14); + break; + case 'f': /* 32-bit decimal floating point */ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]); @@ -2570,14 +2661,19 @@ 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; @@ -2603,7 +2699,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; @@ -2636,10 +2732,10 @@ d_cv_qualifiers (struct d_info *di, pstart = pret; peek = d_peek_char (di); - while (peek == 'r' || peek == 'V' || peek == 'K' - || (peek == 'D' && d_peek_next_char (di) == 'x')) + while (next_is_type_qual (di)) { enum demangle_component_type t; + struct demangle_component *right = NULL; d_advance (di, 1); if (peek == 'r') @@ -2665,12 +2761,41 @@ d_cv_qualifiers (struct d_info *di, } else { - t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; - di->expansion += sizeof "transaction_safe"; - d_advance (di, 1); + peek = d_next_char (di); + if (peek == 'x') + { + t = DEMANGLE_COMPONENT_TRANSACTION_SAFE; + di->expansion += sizeof "transaction_safe"; + } + else if (peek == 'o' + || peek == 'O') + { + t = DEMANGLE_COMPONENT_NOEXCEPT; + di->expansion += sizeof "noexcept"; + if (peek == 'O') + { + right = d_expression (di); + if (right == NULL) + return NULL; + if (! d_check_char (di, 'E')) + return NULL; + } + } + else if (peek == 'w') + { + t = DEMANGLE_COMPONENT_THROW_SPEC; + di->expansion += sizeof "throw"; + right = d_parmlist (di); + if (right == NULL) + return NULL; + if (! d_check_char (di, 'E')) + return NULL; + } + else + return NULL; } - *pret = d_make_comp (di, t, NULL, NULL); + *pret = d_make_comp (di, t, NULL, right); if (*pret == NULL) return NULL; pret = &d_left (*pret); @@ -2739,21 +2864,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; } @@ -2992,8 +3131,6 @@ d_template_param (struct d_info *di) if (param < 0) return NULL; - ++di->did_subs; - return d_make_template_param (di, param); } @@ -3225,11 +3362,11 @@ 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')); } @@ -3292,13 +3429,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: { @@ -3345,6 +3479,8 @@ d_expression_1 (struct d_info *di) first = d_expression_1 (di); second = d_expression_1 (di); third = d_expression_1 (di); + if (third == NULL) + return NULL; } else if (code[0] == 'f') { @@ -3352,6 +3488,8 @@ d_expression_1 (struct d_info *di) first = d_operator_name (di); second = d_expression_1 (di); third = d_expression_1 (di); + if (third == NULL) + return NULL; } else if (code[0] == 'n') { @@ -3479,11 +3617,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; @@ -3493,13 +3634,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') @@ -3512,24 +3650,37 @@ d_local_name (struct d_info *di) } 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; - } + + 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); } -/* ::= _ <(non-negative) number> +/* ::= _ # when number < 10 + ::= __ _ # when number >= 10 + + ::= _ # when number >=10 + is also accepted to support gcc versions that wrongly mangled that way. We demangle the discriminator, but we don't print it out. FIXME: We should print it out in verbose mode. */ @@ -3537,14 +3688,28 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - int discrim; + int discrim, num_underscores = 1; if (d_peek_char (di) != '_') return 1; d_advance (di, 1); + if (d_peek_char (di) == '_') + { + ++num_underscores; + d_advance (di, 1); + } + discrim = d_number (di); if (discrim < 0) return 0; + if (num_underscores > 1 && discrim >= 10) + { + if (d_peek_char (di) == '_') + d_advance (di, 1); + else + return 0; + } + return 1; } @@ -3741,8 +3906,6 @@ d_substitution (struct d_info *di, int prefix) if (id >= (unsigned int) di->next_sub) return NULL; - ++di->did_subs; - return di->subs[id]; } else @@ -3769,7 +3932,7 @@ d_substitution (struct d_info *di, int prefix) { const char *s; int len; - struct demangle_component *c; + struct demangle_component *dc; if (p->set_last_name != NULL) di->last_name = d_make_sub (di, p->set_last_name, @@ -3785,15 +3948,16 @@ d_substitution (struct d_info *di, int prefix) len = p->simple_len; } di->expansion += len; - c = d_make_sub (di, s, len); + dc = d_make_sub (di, s, len); if (d_peek_char (di) == 'B') { /* If there are ABI tags on the abbreviation, it becomes a substitution candidate. */ - c = d_abi_tags (di, c); - d_add_substitution (di, c); + dc = d_abi_tags (di, dc); + if (! d_add_substitution (di, dc)) + return NULL; } - return c; + return dc; } } @@ -3807,7 +3971,6 @@ 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; } @@ -3817,7 +3980,6 @@ 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; } @@ -3905,7 +4067,7 @@ 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, +d_count_templates_scopes (struct d_print_info *dpi, const struct demangle_component *dc) { if (dc == NULL) @@ -3925,13 +4087,13 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, 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: @@ -3961,6 +4123,8 @@ d_count_templates_scopes (int *num_templates, int *num_scopes, case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + case DEMANGLE_COMPONENT_NOEXCEPT: + case DEMANGLE_COMPONENT_THROW_SPEC: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: @@ -3972,6 +4136,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: @@ -3993,42 +4158,42 @@ 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); + d_count_templates_scopes (dpi, 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_fixed.length); break; case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: - d_count_templates_scopes (num_templates, num_scopes, - d_left (dc)); + 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; } } @@ -4050,6 +4215,8 @@ d_print_init (struct d_print_info *dpi, demangle_callbackref callback, dpi->opaque = opaque; dpi->demangle_failure = 0; + dpi->recursion = 0; + dpi->is_lambda_arg = 0; dpi->component_stack = NULL; @@ -4061,8 +4228,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; @@ -4146,7 +4317,7 @@ d_last_char (struct d_print_info *dpi) CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_print_callback (int options, - const struct demangle_component *dc, + struct demangle_component *dc, demangle_callbackref callback, void *opaque) { struct d_print_info dpi; @@ -4189,7 +4360,7 @@ cplus_demangle_print_callback (int options, CP_STATIC_IF_GLIBCPP_V3 char * -cplus_demangle_print (int options, const struct demangle_component *dc, +cplus_demangle_print (int options, struct demangle_component *dc, int estimate, size_t *palc) { struct d_growable_string dgs; @@ -4349,7 +4520,7 @@ d_args_length (struct d_print_info *dpi, const struct demangle_component *dc) static void d_print_subexpr (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { int simple = 0; if (dc->type == DEMANGLE_COMPONENT_NAME @@ -4425,9 +4596,9 @@ d_get_saved_scope (struct d_print_info *dpi, static int d_maybe_print_fold_expression (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { - const struct demangle_component *ops, *operator_, *op1, *op2; + struct demangle_component *ops, *operator_, *op1, *op2; int save_idx; const char *fold_code = d_left (dc)->u.s_operator.op->code; @@ -4488,11 +4659,11 @@ d_maybe_print_fold_expression (struct d_print_info *dpi, int options, static void d_print_comp_inner (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { /* Magic variable to let reference smashing skip over the next modifier without needing to modify *dc. */ - const struct demangle_component *mod_inner = NULL; + struct demangle_component *mod_inner = NULL; /* Variable used to store the current templates while a previously captured scope is used. */ @@ -4575,12 +4746,7 @@ d_print_comp_inner (struct d_print_info *dpi, int options, adpm[i].templates = dpi->templates; ++i; - 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_RVALUE_REFERENCE_THIS - && typed_name->type != DEMANGLE_COMPONENT_TRANSACTION_SAFE - && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS) + if (!is_fnqual_component_type (typed_name->type)) break; typed_name = d_left (typed_name); @@ -4592,38 +4758,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 (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_REFERENCE_THIS - || local_name->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || (local_name->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)) + 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]) { @@ -4635,13 +4780,27 @@ 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)); @@ -4718,33 +4877,46 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } case DEMANGLE_COMPONENT_TEMPLATE_PARAM: - { - struct d_print_template *hold_dpt; - struct demangle_component *a = d_lookup_template_argument (dpi, dc); + if (dpi->is_lambda_arg) + { + /* Show the template parm index, as that's how g++ displays + these, and future proofs us against potential + '[] (T *a, T *b) {...}'. */ + d_append_buffer (dpi, "auto:", 5); + d_append_num (dpi, dc->u.s_number.number + 1); + } + else + { + struct d_print_template *hold_dpt; + struct demangle_component *a = d_lookup_template_argument (dpi, dc); - if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) - a = d_index_template_argument (a, dpi->pack_index); + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); - if (a == NULL) - { - d_print_error (dpi); - return; - } + if (a == NULL) + { + d_print_error (dpi); + return; + } - /* While processing this parameter, we need to pop the list of - templates. This is because the template parameter may - itself be a reference to a parameter of an outer - template. */ + /* While processing this parameter, we need to pop the list + of templates. This is because the template parameter may + itself be a reference to a parameter of an outer + template. */ - hold_dpt = dpi->templates; - dpi->templates = hold_dpt->next; + hold_dpt = dpi->templates; + dpi->templates = hold_dpt->next; - d_print_comp (dpi, options, a); + d_print_comp (dpi, options, a); - dpi->templates = hold_dpt; + dpi->templates = hold_dpt; + } + return; - 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); @@ -4880,8 +5052,9 @@ d_print_comp_inner (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_RVALUE_REFERENCE: { /* Handle reference smashing: & + && = &. */ - const struct demangle_component *sub = d_left (dc); - if (sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) + struct demangle_component *sub = d_left (dc); + if (!dpi->is_lambda_arg + && sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) { struct d_saved_scope *scope = d_get_saved_scope (dpi, sub); struct demangle_component *a; @@ -4948,16 +5121,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, } /* Fall through. */ - 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: case DEMANGLE_COMPONENT_IMAGINARY: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: modifier: { /* We keep a list of modifiers on the stack. */ @@ -5556,7 +5724,11 @@ d_print_comp_inner (struct d_print_info *dpi, int options, 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, '}'); @@ -5583,9 +5755,17 @@ d_print_comp_inner (struct d_print_info *dpi, int options, static void d_print_comp (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { struct d_component_stack self; + if (dc == NULL || dc->d_printing > 1 || dpi->recursion > MAX_RECURSION_COUNT) + { + d_print_error (dpi); + return; + } + + dc->d_printing++; + dpi->recursion++; self.dc = dc; self.parent = dpi->component_stack; @@ -5594,6 +5774,8 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp_inner (dpi, options, dc); dpi->component_stack = self.parent; + dc->d_printing--; + dpi->recursion--; } /* Print a Java dentifier. For Java we try to handle encoded extended @@ -5662,13 +5844,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, if (mods->printed || (! 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_REFERENCE_THIS - || mods->mod->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || (mods->mod->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)))) + && (is_fnqual_component_type (mods->mod->type)))) { d_print_mod_list (dpi, options, mods->next, suffix); return; @@ -5721,12 +5897,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, dc = dc->u.s_unary_num.sub; } - while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || dc->type == DEMANGLE_COMPONENT_CONST_THIS - || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE - || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) + while (is_fnqual_component_type (dc->type)) dc = d_left (dc); d_print_comp (dpi, options, dc); @@ -5746,7 +5917,7 @@ d_print_mod_list (struct d_print_info *dpi, int options, static void d_print_mod (struct d_print_info *dpi, int options, - const struct demangle_component *mod) + struct demangle_component *mod) { switch (mod->type) { @@ -5765,6 +5936,24 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_TRANSACTION_SAFE: d_append_string (dpi, " transaction_safe"); return; + case DEMANGLE_COMPONENT_NOEXCEPT: + d_append_string (dpi, " noexcept"); + if (d_right (mod)) + { + d_append_char (dpi, '('); + d_print_comp (dpi, options, d_right (mod)); + d_append_char (dpi, ')'); + } + return; + case DEMANGLE_COMPONENT_THROW_SPEC: + d_append_string (dpi, " throw"); + if (d_right (mod)) + { + d_append_char (dpi, '('); + d_print_comp (dpi, options, d_right (mod)); + d_append_char (dpi, ')'); + } + return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); d_print_comp (dpi, options, d_right (mod)); @@ -5777,11 +5966,13 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_REFERENCE_THIS: /* For the ref-qualifier, put a space before the &. */ d_append_char (dpi, ' '); + /* FALLTHRU */ case DEMANGLE_COMPONENT_REFERENCE: d_append_char (dpi, '&'); return; case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: d_append_char (dpi, ' '); + /* FALLTHRU */ case DEMANGLE_COMPONENT_RVALUE_REFERENCE: d_append_string (dpi, "&&"); return; @@ -5818,7 +6009,7 @@ d_print_mod (struct d_print_info *dpi, int options, static void d_print_function_type (struct d_print_info *dpi, int options, - const struct demangle_component *dc, + struct demangle_component *dc, struct d_print_mod *mods) { int need_paren; @@ -5850,12 +6041,7 @@ d_print_function_type (struct d_print_info *dpi, int options, need_space = 1; need_paren = 1; break; - 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_TRANSACTION_SAFE: + FNQUAL_COMPONENT_CASE: break; default: break; @@ -5901,7 +6087,7 @@ d_print_function_type (struct d_print_info *dpi, int options, static void d_print_array_type (struct d_print_info *dpi, int options, - const struct demangle_component *dc, + struct demangle_component *dc, struct d_print_mod *mods) { int need_space; @@ -5955,7 +6141,7 @@ d_print_array_type (struct d_print_info *dpi, int options, static void d_print_expr_op (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { if (dc->type == DEMANGLE_COMPONENT_OPERATOR) d_append_buffer (dpi, dc->u.s_operator.op->name, @@ -5968,7 +6154,7 @@ d_print_expr_op (struct d_print_info *dpi, int options, static void d_print_cast (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { d_print_comp (dpi, options, d_left (dc)); } @@ -5977,7 +6163,7 @@ d_print_cast (struct d_print_info *dpi, int options, static void d_print_conversion (struct d_print_info *dpi, int options, - const struct demangle_component *dc) + struct demangle_component *dc) { struct d_print_template dpt; @@ -6032,23 +6218,23 @@ 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; - di->did_subs = 0; di->last_name = NULL; 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 @@ -6088,6 +6274,20 @@ d_demangle_callback (const char *mangled, int options, 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]; @@ -6397,7 +6597,6 @@ is_ctor_or_dtor (const char *mangled, case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_REFERENCE_THIS: case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - case DEMANGLE_COMPONENT_TRANSACTION_SAFE: default: dc = NULL; break;