X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=libiberty%2Fcp-demangle.c;h=cbfb2f937ca970bb57bf7983a466ac7fcf1cb478;hb=refs%2Fheads%2Fconcurrent-displaced-stepping-2020-04-01;hp=d0f57b7fcce5a667b76f220025bf374cfa716822;hpb=abc6552b2679eddc1a6b2d0e50b1bcb05350d1e9;p=deliverable%2Fbinutils-gdb.git diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index d0f57b7fcc..cbfb2f937c 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 - Free Software Foundation, Inc. + Copyright (C) 2003-2020 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 . @@ -93,7 +92,11 @@ CP_DEMANGLE_DEBUG If defined, turns on debugging mode, which prints information on stdout about the mangled string. This is not generally useful. -*/ + + CHECK_DEMANGLER + If defined, additional sanity checks will be performed. It will + cause some slowdown, but will allow to catch out-of-bound access + errors earlier. This macro is intended for testing and debugging. */ #if defined (_AIX) && !defined (__GNUC__) #pragma alloca @@ -124,6 +127,13 @@ extern char *alloca (); # endif /* alloca */ #endif /* HAVE_ALLOCA_H */ +#ifdef HAVE_LIMITS_H +#include +#endif +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + #include "ansidecl.h" #include "libiberty.h" #include "demangle.h" @@ -162,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 @@ -182,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__) */ @@ -254,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. */ @@ -275,6 +285,43 @@ struct d_growable_string int allocation_failure; }; +/* Stack of components, innermost first, used to avoid loops. */ + +struct d_component_stack +{ + /* This component. */ + const struct demangle_component *dc; + /* This component's parent. */ + const struct d_component_stack *parent; +}; + +/* A demangle component and some scope captured when it was first + traversed. */ + +struct d_saved_scope +{ + /* The component whose scope this is. */ + const struct demangle_component *container; + /* The list of templates, if any, that was current when this + scope was captured. */ + struct d_print_template *templates; +}; + +/* Checkpoint structure to allow backtracking. This holds copies + of the fields of struct d_info that need to be restored + if a trial parse needs to be backtracked over. */ + +struct d_info_checkpoint +{ + const char *n; + int next_comp; + int next_sub; + int 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 { @@ -297,11 +344,33 @@ 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. */ + for printing, or -1 to print the whole pack. */ int pack_index; /* Number of d_print_flush calls so far. */ unsigned long int flush_count; + /* Stack of components, innermost first, used to avoid loops. */ + const struct d_component_stack *component_stack; + /* Array of saved scopes for evaluating substitutions. */ + struct d_saved_scope *saved_scopes; + /* Index of the next unused saved scope in the above array. */ + int next_saved_scope; + /* Number of saved scopes in the above array. */ + int num_saved_scopes; + /* Array of templates for saving into scopes. */ + struct d_print_template *copy_templates; + /* Index of the next unused copy template in the above array. */ + int next_copy_template; + /* Number of copy templates in the above array. */ + int num_copy_templates; + /* The nearest enclosing template, if any. */ + const struct demangle_component *current_template; }; #ifdef CP_DEMANGLE_DEBUG @@ -343,7 +412,7 @@ d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds, struct demangle_component *); static struct demangle_component * -d_make_template_param (struct d_info *, long); +d_make_template_param (struct d_info *, int); static struct demangle_component * d_make_sub (struct d_info *, const char *, int); @@ -366,7 +435,7 @@ static struct demangle_component *d_unqualified_name (struct d_info *); static struct demangle_component *d_source_name (struct d_info *); -static long d_number (struct d_info *); +static int d_number (struct d_info *); static struct demangle_component *d_identifier (struct d_info *, int); @@ -374,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 *); @@ -381,6 +452,9 @@ static struct demangle_component *d_ctor_dtor_name (struct d_info *); static struct demangle_component ** d_cv_qualifiers (struct d_info *, struct demangle_component **, int); +static struct demangle_component * +d_ref_qualifier (struct d_info *, struct demangle_component *); + static struct demangle_component * d_function_type (struct d_info *); @@ -401,6 +475,7 @@ static struct demangle_component * d_template_param (struct d_info *); static struct demangle_component *d_template_args (struct d_info *); +static struct demangle_component *d_template_args_1 (struct d_info *); static struct demangle_component * d_template_arg (struct d_info *); @@ -425,6 +500,10 @@ d_add_substitution (struct d_info *, struct demangle_component *); static struct demangle_component *d_substitution (struct d_info *, int); +static void d_checkpoint (struct d_info *, struct d_info_checkpoint *); + +static void d_backtrack (struct d_info *, struct d_info_checkpoint *); + static void d_growable_string_init (struct d_growable_string *, size_t); static inline void @@ -437,7 +516,8 @@ static void d_growable_string_callback_adapter (const char *, size_t, void *); static void -d_print_init (struct d_print_info *, demangle_callbackref, void *); +d_print_init (struct d_print_info *, demangle_callbackref, void *, + struct demangle_component *); static inline void d_print_error (struct d_print_info *); @@ -455,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); @@ -464,28 +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 *); +static void d_print_cast (struct d_print_info *, int, + struct demangle_component *); +static void d_print_conversion (struct d_print_info *, int, + 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 @@ -508,9 +617,20 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_NAME: printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s); return; + case DEMANGLE_COMPONENT_TAGGED_NAME: + printf ("tagged name\n"); + d_dump (dc->u.s_binary.left, indent + 2); + d_dump (dc->u.s_binary.right, indent + 2); + return; case DEMANGLE_COMPONENT_TEMPLATE_PARAM: printf ("template parameter %ld\n", dc->u.s_number.number); return; + 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; case DEMANGLE_COMPONENT_CTOR: printf ("constructor %d\n", (int) dc->u.s_ctor.kind); d_dump (dc->u.s_ctor.name, indent + 2); @@ -585,6 +705,12 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_HIDDEN_ALIAS: printf ("hidden alias\n"); break; + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + printf ("transaction clone\n"); + break; + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + printf ("non-transaction clone\n"); + break; case DEMANGLE_COMPONENT_RESTRICT: printf ("restrict\n"); break; @@ -603,6 +729,15 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_CONST_THIS: printf ("const this\n"); break; + case DEMANGLE_COMPONENT_REFERENCE_THIS: + printf ("reference this\n"); + break; + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: + printf ("rvalue reference this\n"); + break; + case DEMANGLE_COMPONENT_TRANSACTION_SAFE: + printf ("transaction_safe this\n"); + break; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: printf ("vendor type qualifier\n"); break; @@ -634,7 +769,9 @@ d_dump (struct demangle_component *dc, int indent) printf ("pointer to member type\n"); break; case DEMANGLE_COMPONENT_FIXED_TYPE: - printf ("fixed-point type\n"); + 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"); @@ -642,9 +779,18 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: printf ("template argument list\n"); break; + case DEMANGLE_COMPONENT_INITIALIZER_LIST: + printf ("initializer list\n"); + break; case DEMANGLE_COMPONENT_CAST: printf ("cast\n"); break; + case DEMANGLE_COMPONENT_CONVERSION: + printf ("conversion operator\n"); + break; + case DEMANGLE_COMPONENT_NULLARY: + printf ("nullary operator\n"); + break; case DEMANGLE_COMPONENT_UNARY: printf ("unary operator\n"); break; @@ -678,12 +824,29 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_CHARACTER: printf ("character '%c'\n", dc->u.s_character.character); return; + case DEMANGLE_COMPONENT_NUMBER: + printf ("number %ld\n", dc->u.s_number.number); + return; case DEMANGLE_COMPONENT_DECLTYPE: printf ("decltype\n"); break; case DEMANGLE_COMPONENT_PACK_EXPANSION: printf ("pack expansion\n"); break; + case DEMANGLE_COMPONENT_TLS_INIT: + printf ("tls init function\n"); + break; + case DEMANGLE_COMPONENT_TLS_WRAPPER: + printf ("tls wrapper function\n"); + break; + case DEMANGLE_COMPONENT_DEFAULT_ARG: + printf ("default argument %d\n", dc->u.s_unary_num.num); + d_dump (dc->u.s_unary_num.sub, indent+2); + return; + case DEMANGLE_COMPONENT_LAMBDA: + printf ("lambda %d\n", dc->u.s_unary_num.num); + d_dump (dc->u.s_unary_num.sub, indent+2); + return; } d_dump (d_left (dc), indent + 2); @@ -698,8 +861,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; @@ -715,6 +880,8 @@ 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; @@ -732,8 +899,10 @@ cplus_demangle_fill_ctor (struct demangle_component *p, if (p == NULL || name == NULL || (int) kind < gnu_v3_complete_object_ctor - || (int) kind > gnu_v3_complete_object_allocating_ctor) + || (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; @@ -751,8 +920,10 @@ cplus_demangle_fill_dtor (struct demangle_component *p, if (p == NULL || name == NULL || (int) kind < gnu_v3_deleting_dtor - || (int) kind > gnu_v3_base_object_dtor) + || (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; @@ -769,6 +940,8 @@ 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; + p->d_counting = 0; ++di->next_comp; return p; } @@ -791,6 +964,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: case DEMANGLE_COMPONENT_TYPED_NAME: + case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_TEMPLATE: case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: @@ -800,7 +974,6 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_BINARY_ARGS: case DEMANGLE_COMPONENT_TRINARY: case DEMANGLE_COMPONENT_TRINARY_ARG1: - case DEMANGLE_COMPONENT_TRINARY_ARG2: case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: case DEMANGLE_COMPONENT_COMPOUND_NAME: @@ -821,8 +994,12 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_COVARIANT_THUNK: case DEMANGLE_COMPONENT_JAVA_CLASS: case DEMANGLE_COMPONENT_GUARD: + case DEMANGLE_COMPONENT_TLS_INIT: + case DEMANGLE_COMPONENT_TLS_WRAPPER: case DEMANGLE_COMPONENT_REFTEMP: case DEMANGLE_COMPONENT_HIDDEN_ALIAS: + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_RVALUE_REFERENCE: @@ -830,11 +1007,15 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_IMAGINARY: case DEMANGLE_COMPONENT_VENDOR_TYPE: case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_DECLTYPE: case DEMANGLE_COMPONENT_PACK_EXPANSION: case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: 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; @@ -842,6 +1023,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, /* This needs a right parameter, but the left parameter can be empty. */ case DEMANGLE_COMPONENT_ARRAY_TYPE: + case DEMANGLE_COMPONENT_INITIALIZER_LIST: if (right == NULL) return NULL; break; @@ -852,11 +1034,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_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + FNQUAL_COMPONENT_CASE: break; /* Other types should not be seen here. */ @@ -992,7 +1172,7 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, /* Add a new template parameter. */ static struct demangle_component * -d_make_template_param (struct d_info *di, long i) +d_make_template_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1008,7 +1188,7 @@ d_make_template_param (struct d_info *di, long i) /* Add a new function parameter. */ static struct demangle_component * -d_make_function_param (struct d_info *di, long i) +d_make_function_param (struct d_info *di, int i) { struct demangle_component *p; @@ -1088,11 +1268,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: + FNQUAL_COMPONENT_CASE: return has_return_type (d_left (dc)); } } @@ -1114,7 +1294,7 @@ is_ctor_dtor_or_conversion (struct demangle_component *dc) return is_ctor_dtor_or_conversion (d_right (dc)); case DEMANGLE_COMPONENT_CTOR: case DEMANGLE_COMPONENT_DTOR: - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: return 1; } } @@ -1132,50 +1312,91 @@ 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) + 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 = 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)); + + if (d_right (dc) == NULL) + dc = NULL; } + } + else + { + peek = d_peek_char (di); + if (peek != '\0' && peek != 'E') + { + struct demangle_component *ftype; - return 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; + } } + } - 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))); + return dc; +} + +/* ::= B */ + +static struct demangle_component * +d_abi_tags (struct d_info *di, struct demangle_component *dc) +{ + struct demangle_component *hold_last_name; + char peek; + + /* Preserve the last name, so the ABI tag doesn't clobber it. */ + hold_last_name = di->last_name; + + while (peek = d_peek_char (di), + peek == 'B') + { + struct demangle_component *tag; + d_advance (di, 1); + tag = d_source_name (di); + dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag); } + + di->last_name = hold_last_name; + + return dc; } /* ::= @@ -1204,7 +1425,6 @@ d_name (struct d_info *di) case 'Z': return d_local_name (di); - case 'L': case 'U': return d_unqualified_name (di); @@ -1251,6 +1471,7 @@ d_name (struct d_info *di) return dc; } + case 'L': default: dc = d_unqualified_name (di); if (d_peek_char (di) == 'I') @@ -1267,8 +1488,8 @@ d_name (struct d_info *di) } } -/* ::= N [] E - ::= N [] E +/* ::= N [] [] E + ::= N [] [] E */ static struct demangle_component * @@ -1276,6 +1497,7 @@ d_nested_name (struct d_info *di) { struct demangle_component *ret; struct demangle_component **pret; + struct demangle_component *rqual; if (! d_check_char (di, 'N')) return NULL; @@ -1284,10 +1506,20 @@ d_nested_name (struct d_info *di) if (pret == NULL) return NULL; + /* Parse the ref-qualifier now and then attach it + once we have something to attach it to. */ + rqual = d_ref_qualifier (di, NULL); + *pret = d_prefix (di); if (*pret == NULL) return NULL; + if (rqual) + { + d_left (rqual) = ret; + ret = rqual; + } + if (! d_check_char (di, 'E')) return NULL; @@ -1392,26 +1624,29 @@ d_prefix (struct d_info *di) static struct demangle_component * d_unqualified_name (struct d_info *di) { + struct demangle_component *ret; char peek; peek = d_peek_char (di); if (IS_DIGIT (peek)) - return d_source_name (di); + ret = d_source_name (di); else if (IS_LOWER (peek)) { - struct demangle_component *ret; - + 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) - di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; - return ret; + { + di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2; + if (!strcmp (ret->u.s_operator.op->code, "li")) + ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret, + d_source_name (di)); + } } else if (peek == 'C' || peek == 'D') - return d_ctor_dtor_name (di); + ret = d_ctor_dtor_name (di); else if (peek == 'L') { - struct demangle_component * ret; - d_advance (di, 1); ret = d_source_name (di); @@ -1419,22 +1654,27 @@ d_unqualified_name (struct d_info *di) return NULL; if (! d_discriminator (di)) return NULL; - return ret; } else if (peek == 'U') { switch (d_peek_next_char (di)) { case 'l': - return d_lambda (di); + ret = d_lambda (di); + break; case 't': - return d_unnamed_type (di); + ret = d_unnamed_type (di); + break; default: return NULL; } } else return NULL; + + if (d_peek_char (di) == 'B') + ret = d_abi_tags (di, ret); + return ret; } /* ::= <(positive length) number> */ @@ -1442,7 +1682,7 @@ d_unqualified_name (struct d_info *di) static struct demangle_component * d_source_name (struct d_info *di) { - long len; + int len; struct demangle_component *ret; len = d_number (di); @@ -1455,12 +1695,12 @@ d_source_name (struct d_info *di) /* number ::= [n] <(non-negative decimal integer)> */ -static long +static int d_number (struct d_info *di) { int negative; char peek; - long ret; + int ret; negative = 0; peek = d_peek_char (di); @@ -1480,7 +1720,9 @@ d_number (struct d_info *di) ret = - ret; return ret; } - ret = ret * 10 + peek - '0'; + if (ret > ((INT_MAX - (peek - '0')) / 10)) + return -1; + ret = ret * 10 + (peek - '0'); d_advance (di, 1); peek = d_peek_char (di); } @@ -1546,7 +1788,8 @@ d_identifier (struct d_info *di, int len) /* operator_name ::= many different two character encodings. ::= cv ::= v -*/ + + This list is sorted for binary search. */ #define NL(s) s, (sizeof s) - 1 @@ -1558,23 +1801,35 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "aa", NL ("&&"), 2 }, { "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 }, - { "da", NL ("delete[]"), 1 }, + { "da", NL ("delete[] "), 1 }, + { "dc", NL ("dynamic_cast"), 2 }, { "de", NL ("*"), 1 }, - { "dl", NL ("delete"), 1 }, + { "dl", NL ("delete "), 1 }, + { "ds", NL (".*"), 2 }, { "dt", NL ("."), 2 }, { "dv", NL ("/"), 2 }, { "eO", NL ("^="), 2 }, { "eo", NL ("^"), 2 }, { "eq", NL ("=="), 2 }, + { "fL", NL ("..."), 3 }, + { "fR", NL ("..."), 3 }, + { "fl", NL ("..."), 2 }, + { "fr", NL ("..."), 2 }, { "ge", NL (">="), 2 }, + { "gs", NL ("::"), 1 }, { "gt", NL (">"), 2 }, { "ix", NL ("[]"), 2 }, { "lS", NL ("<<="), 2 }, { "le", NL ("<="), 2 }, + { "li", NL ("operator\"\" "), 1 }, { "ls", NL ("<<"), 2 }, { "lt", NL ("<"), 2 }, { "mI", NL ("-="), 2 }, @@ -1582,11 +1837,11 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "mi", NL ("-"), 2 }, { "ml", NL ("*"), 2 }, { "mm", NL ("--"), 1 }, - { "na", NL ("new[]"), 1 }, + { "na", NL ("new[]"), 3 }, { "ne", NL ("!="), 2 }, { "ng", NL ("-"), 1 }, { "nt", NL ("!"), 1 }, - { "nw", NL ("new"), 1 }, + { "nw", NL ("new"), 3 }, { "oR", NL ("|="), 2 }, { "oo", NL ("||"), 2 }, { "or", NL ("|"), 2 }, @@ -1599,12 +1854,17 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "qu", NL ("?"), 3 }, { "rM", NL ("%="), 2 }, { "rS", NL (">>="), 2 }, + { "rc", NL ("reinterpret_cast"), 2 }, { "rm", NL ("%"), 2 }, { "rs", NL (">>"), 2 }, + { "sP", NL ("sizeof..."), 1 }, + { "sZ", NL ("sizeof..."), 1 }, + { "sc", NL ("static_cast"), 2 }, + { "ss", NL ("<=>"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, - { "at", NL ("alignof "), 1 }, - { "az", NL ("alignof "), 1 }, + { "tr", NL ("throw"), 0 }, + { "tw", NL ("throw "), 1 }, { NULL, NULL, 0, 0 } }; @@ -1619,8 +1879,20 @@ d_operator_name (struct d_info *di) if (c1 == 'v' && IS_DIGIT (c2)) return d_make_extended_operator (di, c2 - '0', d_source_name (di)); else if (c1 == 'c' && c2 == 'v') - return d_make_comp (di, DEMANGLE_COMPONENT_CAST, - cplus_demangle_type (di), NULL); + { + struct demangle_component *type; + int was_conversion = di->is_conversion; + struct demangle_component *res; + + di->is_conversion = ! di->is_expression; + type = cplus_demangle_type (di); + if (di->is_conversion) + res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL); + else + res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL); + di->is_conversion = was_conversion; + return res; + } else { /* LOW is the inclusive lower bound. */ @@ -1670,7 +1942,7 @@ d_java_resource (struct d_info *di) { struct demangle_component *p = NULL; struct demangle_component *next = NULL; - long len, i; + int len, i; char c; const char *str; @@ -1752,6 +2024,7 @@ d_java_resource (struct d_info *di) ::= TT ::= TI ::= TS + ::= TA ::= GV <(object) name> ::= T <(base) encoding> ::= Tc <(base) encoding> @@ -1762,6 +2035,8 @@ d_java_resource (struct d_info *di) ::= GR ::= GA ::= Gr + ::= GTt + ::= GTn */ static struct demangle_component * @@ -1810,7 +2085,7 @@ d_special_name (struct d_info *di) case 'C': { struct demangle_component *derived_type; - long offset; + int offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); @@ -1834,6 +2109,18 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS, cplus_demangle_type (di), NULL); + case 'H': + return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT, + d_name (di), NULL); + + case 'W': + return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, + d_name (di), NULL); + + case 'A': + return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ, + d_template_arg (di), NULL); + default: return NULL; } @@ -1843,7 +2130,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': { @@ -1856,6 +2144,23 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, d_encoding (di, 0), NULL); + case 'T': + switch (d_next_char (di)) + { + case 'n': + return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, + d_encoding (di, 0), NULL); + default: + /* ??? The proposal is that other letters (such as 'h') stand + for different variants of transaction cloning, such as + compiling directly for hardware transaction support. But + they still should all be transactional clones of some sort + so go ahead and call them that. */ + case 't': + return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE, + d_encoding (di, 0), NULL); + } + case 'r': return d_java_resource (di); @@ -1927,6 +2232,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)) { @@ -1939,10 +2251,21 @@ d_ctor_dtor_name (struct d_info *di) case '3': kind = gnu_v3_complete_object_allocating_ctor; break; + case '4': + kind = gnu_v3_unified_ctor; + break; + case '5': + kind = gnu_v3_object_ctor_group; + break; default: return NULL; } + d_advance (di, 2); + + if (inheriting) + cplus_demangle_type (di); + return d_make_ctor (di, kind, di->last_name); } @@ -1961,6 +2284,13 @@ d_ctor_dtor_name (struct d_info *di) case '2': kind = gnu_v3_base_object_dtor; break; + /* digit '3' is not used */ + case '4': + kind = gnu_v3_unified_dtor; + break; + case '5': + kind = gnu_v3_object_dtor_group; + break; default: return NULL; } @@ -1973,6 +2303,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; +} + /* ::= ::= ::= @@ -2029,9 +2377,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 }, }; @@ -2058,22 +2407,42 @@ 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') + if (next_is_type_qual (di)) { struct demangle_component **pret; pret = d_cv_qualifiers (di, &ret, 0); if (pret == NULL) return NULL; - *pret = cplus_demangle_type (di); - if (! *pret || ! d_add_substitution (di, ret)) + if (d_peek_char (di) == 'F') + { + /* cv-qualifiers before a function type apply to 'this', + so avoid adding the unqualified function type to + the substitution list. */ + *pret = d_function_type (di); + } + else + *pret = cplus_demangle_type (di); + if (!*pret) + return NULL; + if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS + || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS) + { + /* Move the ref-qualifier outside the cv-qualifiers so that + they are printed in the right order. */ + struct demangle_component *fn = d_left (*pret); + d_left (*pret) = ret; + ret = *pret; + *pret = fn; + } + if (! d_add_substitution (di, ret)) return NULL; return ret; } can_subst = 1; + peek = d_peek_char (di); switch (peek) { case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': @@ -2116,13 +2485,61 @@ cplus_demangle_type (struct d_info *di) ret = d_template_param (di); if (d_peek_char (di) == 'I') { - /* This is . The - part is a substitution + /* This may be . + If this is the type for a conversion operator, we can + have a here only by following + a derivation like this: + + + -> + -> + -> + -> + -> + -> cv + -> cv + + where the is followed by another. + Otherwise, we must have a derivation like this: + + + -> + -> + -> + -> + -> + -> cv + -> cv + + where we need to leave the to be processed + by d_prefix (following the ). + + The part is a substitution candidate. */ - if (! d_add_substitution (di, ret)) - return NULL; - ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, - d_template_args (di)); + if (! di->is_conversion) + { + if (! d_add_substitution (di, ret)) + return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); + } + else + { + struct demangle_component *args; + struct d_info_checkpoint checkpoint; + + d_checkpoint (di, &checkpoint); + args = d_template_args (di); + if (d_peek_char (di) == 'I') + { + if (! d_add_substitution (di, ret)) + return NULL; + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + args); + } + else + d_backtrack (di, &checkpoint); + } } break; @@ -2192,6 +2609,9 @@ cplus_demangle_type (struct d_info *di) case 'U': d_advance (di, 1); ret = d_source_name (di); + if (d_peek_char (di) == 'I') + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL, cplus_demangle_type (di), ret); break; @@ -2209,14 +2629,25 @@ cplus_demangle_type (struct d_info *di) d_expression (di), NULL); if (ret && d_next_char (di) != 'E') ret = NULL; + can_subst = 1; break; case 'p': /* Pack expansion. */ ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, cplus_demangle_type (di), NULL); + can_subst = 1; break; - + + case 'a': + /* auto */ + ret = d_make_name (di, "auto", 4); + break; + case '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]); @@ -2237,14 +2668,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; @@ -2265,11 +2701,12 @@ cplus_demangle_type (struct d_info *di) case 'v': ret = d_vector_type (di); + can_subst = 1; break; 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; @@ -2291,7 +2728,7 @@ cplus_demangle_type (struct d_info *di) return ret; } -/* ::= [r] [V] [K] */ +/* ::= [r] [V] [K] [Dx] */ static struct demangle_component ** d_cv_qualifiers (struct d_info *di, @@ -2302,9 +2739,10 @@ d_cv_qualifiers (struct d_info *di, pstart = pret; peek = d_peek_char (di); - while (peek == 'r' || peek == 'V' || peek == 'K') + while (next_is_type_qual (di)) { enum demangle_component_type t; + struct demangle_component *right = NULL; d_advance (di, 1); if (peek == 'r') @@ -2321,15 +2759,50 @@ d_cv_qualifiers (struct d_info *di, : DEMANGLE_COMPONENT_VOLATILE); di->expansion += sizeof "volatile"; } - else + else if (peek == 'K') { t = (member_fn ? DEMANGLE_COMPONENT_CONST_THIS : DEMANGLE_COMPONENT_CONST); di->expansion += sizeof "const"; } + else + { + 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); @@ -2362,24 +2835,71 @@ d_cv_qualifiers (struct d_info *di, return pret; } -/* ::= F [Y] E */ +/* ::= R + ::= O */ static struct demangle_component * -d_function_type (struct d_info *di) +d_ref_qualifier (struct d_info *di, struct demangle_component *sub) { - struct demangle_component *ret; + struct demangle_component *ret = sub; + char peek; - if (! d_check_char (di, 'F')) - return NULL; - if (d_peek_char (di) == 'Y') + peek = d_peek_char (di); + if (peek == 'R' || peek == 'O') { - /* Function has C linkage. We don't print this information. - FIXME: We should print it in verbose mode. */ + enum demangle_component_type t; + if (peek == 'R') + { + t = DEMANGLE_COMPONENT_REFERENCE_THIS; + di->expansion += sizeof "&"; + } + else + { + t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS; + di->expansion += sizeof "&&"; + } d_advance (di, 1); + + ret = d_make_comp (di, t, ret, NULL); } - ret = d_bare_function_type (di, 1); - if (! d_check_char (di, 'E')) - return NULL; + + return ret; +} + +/* ::= F [Y] [] [T] E */ + +static struct demangle_component * +d_function_type (struct d_info *di) +{ + struct demangle_component *ret = NULL; + + if ((di->options & DMGL_NO_RECURSE_LIMIT) == 0) + { + 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 ++; + } + + 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; } @@ -2400,6 +2920,10 @@ d_parmlist (struct d_info *di) char peek = d_peek_char (di); if (peek == '\0' || peek == 'E' || peek == '.') break; + if ((peek == 'R' || peek == 'O') + && d_peek_next_char (di) == 'E') + /* Function ref-qualifier, not a ref prefix for a parameter type. */ + break; type = cplus_demangle_type (di); if (type == NULL) return NULL; @@ -2550,51 +3074,42 @@ d_pointer_to_member_type (struct d_info *di) { struct demangle_component *cl; struct demangle_component *mem; - struct demangle_component **pmem; if (! d_check_char (di, 'M')) return NULL; cl = cplus_demangle_type (di); + if (cl == NULL) + return NULL; - /* The ABI specifies that any type can be a substitution source, and - that M is followed by two types, and that when a CV-qualified - type is seen both the base type and the CV-qualified types are - substitution sources. The ABI also specifies that for a pointer - to a CV-qualified member function, the qualifiers are attached to - the second type. Given the grammar, a plain reading of the ABI - suggests that both the CV-qualified member function and the - non-qualified member function are substitution sources. However, - g++ does not work that way. g++ treats only the CV-qualified - member function as a substitution source. FIXME. So to work - with g++, we need to pull off the CV-qualifiers here, in order to - avoid calling add_substitution() in cplus_demangle_type(). But - for a CV-qualified member which is not a function, g++ does - follow the ABI, so we need to handle that case here by calling - d_add_substitution ourselves. */ - - pmem = d_cv_qualifiers (di, &mem, 1); - if (pmem == NULL) + /* The ABI says, "The type of a non-static member function is considered + to be different, for the purposes of substitution, from the type of a + namespace-scope or static member function whose type appears + similar. The types of two non-static member functions are considered + to be different, for the purposes of substitution, if the functions + are members of different classes. In other words, for the purposes of + substitution, the class of which the function is a member is + considered part of the type of function." + + For a pointer to member function, this call to cplus_demangle_type + will end up adding a (possibly qualified) non-member function type to + the substitution table, which is not correct; however, the member + function type will never be used in a substitution, so putting the + wrong type in the substitution table is harmless. */ + + mem = cplus_demangle_type (di); + if (mem == NULL) return NULL; - *pmem = cplus_demangle_type (di); - if (*pmem == NULL) - return NULL; - - if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) - { - if (! d_add_substitution (di, mem)) - return NULL; - } return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); } /* _ */ -static long +static int d_compact_number (struct d_info *di) { - long num; + int num; if (d_peek_char (di) == '_') num = 0; else if (d_peek_char (di) == 'n') @@ -2602,7 +3117,7 @@ d_compact_number (struct d_info *di) else num = d_number (di) + 1; - if (! d_check_char (di, '_')) + if (num < 0 || ! d_check_char (di, '_')) return -1; return num; } @@ -2614,7 +3129,7 @@ d_compact_number (struct d_info *di) static struct demangle_component * d_template_param (struct d_info *di) { - long param; + int param; if (! d_check_char (di, 'T')) return NULL; @@ -2623,8 +3138,6 @@ d_template_param (struct d_info *di) if (param < 0) return NULL; - ++di->did_subs; - return d_make_template_param (di, param); } @@ -2632,6 +3145,19 @@ d_template_param (struct d_info *di) static struct demangle_component * d_template_args (struct d_info *di) +{ + if (d_peek_char (di) != 'I' + && d_peek_char (di) != 'J') + return NULL; + d_advance (di, 1); + + return d_template_args_1 (di); +} + +/* * E */ + +static struct demangle_component * +d_template_args_1 (struct d_info *di) { struct demangle_component *hold_last_name; struct demangle_component *al; @@ -2642,9 +3168,6 @@ d_template_args (struct d_info *di) constructor or destructor. */ hold_last_name = di->last_name; - if (! d_check_char (di, 'I')) - return NULL; - if (d_peek_char (di) == 'E') { /* An argument pack can be empty. */ @@ -2702,6 +3225,7 @@ d_template_arg (struct d_info *di) return d_expr_primary (di); case 'I': + case 'J': /* An argument pack. */ return d_template_args (di); @@ -2710,15 +3234,16 @@ d_template_arg (struct d_info *di) } } -/* Subroutine of ::= cl + E */ +/* Parse a sequence of expressions until we hit the terminator + character. */ static struct demangle_component * -d_exprlist (struct d_info *di) +d_exprlist (struct d_info *di, char terminator) { struct demangle_component *list = NULL; struct demangle_component **p = &list; - if (d_peek_char (di) == 'E') + if (d_peek_char (di) == terminator) { d_advance (di, 1); return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL); @@ -2735,7 +3260,7 @@ d_exprlist (struct d_info *di) return NULL; p = &d_right (*p); - if (d_peek_char (di) == 'E') + if (d_peek_char (di) == terminator) { d_advance (di, 1); break; @@ -2745,6 +3270,18 @@ d_exprlist (struct d_info *di) return list; } +/* Returns nonzero iff OP is an operator for a C++ cast: const_cast, + dynamic_cast, static_cast or reinterpret_cast. */ + +static int +op_is_new_cast (struct demangle_component *op) +{ + const char *code = op->u.s_operator.op->code; + return (code[1] == 'c' + && (code[0] == 's' || code[0] == 'd' + || code[0] == 'c' || code[0] == 'r')); +} + /* ::= <(unary) operator-name> ::= <(binary) operator-name> ::= <(trinary) operator-name> @@ -2756,8 +3293,8 @@ d_exprlist (struct d_info *di) ::= */ -static struct demangle_component * -d_expression (struct d_info *di) +static inline struct demangle_component * +d_expression_1 (struct d_info *di) { char peek; @@ -2785,7 +3322,7 @@ d_expression (struct d_info *di) { d_advance (di, 2); return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, - d_expression (di), NULL); + d_expression_1 (di), NULL); } else if (peek == 'f' && d_peek_next_char (di) == 'p') { @@ -2800,9 +3337,10 @@ d_expression (struct d_info *di) } else { - index = d_compact_number (di) + 1; - if (index == 0) + index = d_compact_number (di); + if (index == INT_MAX || index == -1) return NULL; + index++; } return d_make_function_param (di, index); } @@ -2826,9 +3364,23 @@ d_expression (struct d_info *di) else return name; } + else if ((peek == 'i' || peek == 't') + && d_peek_next_char (di) == 'l') + { + /* Brace-enclosed initializer list, untyped or typed. */ + struct demangle_component *type = NULL; + d_advance (di, 2); + if (peek == 't') + type = cplus_demangle_type (di); + if (!d_peek_char (di) || !d_peek_next_char (di)) + return NULL; + return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST, + type, d_exprlist (di, 'E')); + } else { struct demangle_component *op; + const char *code = NULL; int args; op = d_operator_name (di); @@ -2836,12 +3388,13 @@ d_expression (struct d_info *di) return NULL; if (op->type == DEMANGLE_COMPONENT_OPERATOR) - di->expansion += op->u.s_operator.op->len - 2; - - if (op->type == DEMANGLE_COMPONENT_OPERATOR - && strcmp (op->u.s_operator.op->code, "st") == 0) - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - cplus_demangle_type (di)); + { + code = op->u.s_operator.op->code; + di->expansion += op->u.s_operator.op->len - 2; + if (strcmp (code, "st") == 0) + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, + cplus_demangle_type (di)); + } switch (op->type) { @@ -2860,26 +3413,50 @@ d_expression (struct d_info *di) switch (args) { + case 0: + return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL); + case 1: { struct demangle_component *operand; + int suffix = 0; + + if (code && (code[0] == 'p' || code[0] == 'm') + && code[1] == code[0]) + /* pp_ and mm_ are the prefix variants. */ + suffix = !d_check_char (di, '_'); + if (op->type == DEMANGLE_COMPONENT_CAST && d_check_char (di, '_')) - operand = d_exprlist (di); + operand = d_exprlist (di, 'E'); + else if (code && !strcmp (code, "sP")) + operand = d_template_args_1 (di); else - operand = d_expression (di); - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - operand); + operand = d_expression_1 (di); + + if (suffix) + /* Indicate the suffix variant for d_print_comp. */ + operand = d_make_comp (di, DEMANGLE_COMPONENT_BINARY_ARGS, + operand, operand); + + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, operand); } case 2: { struct demangle_component *left; struct demangle_component *right; - const char *code = op->u.s_operator.op->code; - left = d_expression (di); + if (code == NULL) + return NULL; + if (op_is_new_cast (op)) + left = cplus_demangle_type (di); + else if (code[0] == 'f') + /* fold-expression. */ + left = d_operator_name (di); + else + left = d_expression_1 (di); if (!strcmp (code, "cl")) - right = d_exprlist (di); + right = d_exprlist (di, 'E'); else if (!strcmp (code, "dt") || !strcmp (code, "pt")) { right = d_unqualified_name (di); @@ -2888,7 +3465,7 @@ d_expression (struct d_info *di) right, d_template_args (di)); } else - right = d_expression (di); + right = d_expression_1 (di); return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, d_make_comp (di, @@ -2899,17 +3476,63 @@ d_expression (struct d_info *di) { struct demangle_component *first; struct demangle_component *second; + struct demangle_component *third; - first = d_expression (di); - second = d_expression (di); + if (code == NULL) + return NULL; + else if (!strcmp (code, "qu")) + { + /* ?: expression. */ + 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') + { + /* fold-expression. */ + 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') + { + /* new-expression. */ + if (code[1] != 'w' && code[1] != 'a') + return NULL; + first = d_exprlist (di, '_'); + second = cplus_demangle_type (di); + if (d_peek_char (di) == 'E') + { + d_advance (di, 1); + third = NULL; + } + else if (d_peek_char (di) == 'p' + && d_peek_next_char (di) == 'i') + { + /* Parenthesized initializer. */ + d_advance (di, 2); + third = d_exprlist (di, 'E'); + } + else if (d_peek_char (di) == 'i' + && d_peek_next_char (di) == 'l') + /* initializer-list. */ + third = d_expression_1 (di); + else + return NULL; + } + else + return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op, d_make_comp (di, DEMANGLE_COMPONENT_TRINARY_ARG1, first, d_make_comp (di, DEMANGLE_COMPONENT_TRINARY_ARG2, - second, - d_expression (di)))); + second, third))); } default: return NULL; @@ -2917,6 +3540,18 @@ d_expression (struct d_info *di) } } +static struct demangle_component * +d_expression (struct d_info *di) +{ + struct demangle_component *ret; + int was_expression = di->is_expression; + + di->is_expression = 1; + ret = d_expression_1 (di); + di->is_expression = was_expression; + return ret; +} + /* ::= L <(value) number> E ::= L <(value) float> E ::= L E @@ -2949,6 +3584,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 @@ -2982,17 +3628,21 @@ d_expr_primary (struct d_info *di) /* ::= Z <(function) encoding> E <(entity) name> [] ::= Z <(function) encoding> E s [] + ::= Z <(function) encoding> E d [ number>] _ */ 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; @@ -3002,13 +3652,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') @@ -3021,24 +3668,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. */ @@ -3046,14 +3706,28 @@ d_local_name (struct d_info *di) static int d_discriminator (struct d_info *di) { - long 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; } @@ -3102,7 +3776,7 @@ static struct demangle_component * d_unnamed_type (struct d_info *di) { struct demangle_component *ret; - long num; + int num; if (! d_check_char (di, 'U')) return NULL; @@ -3250,8 +3924,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 @@ -3278,6 +3950,7 @@ d_substitution (struct d_info *di, int prefix) { const char *s; int len; + struct demangle_component *dc; if (p->set_last_name != NULL) di->last_name = d_make_sub (di, p->set_last_name, @@ -3293,7 +3966,16 @@ d_substitution (struct d_info *di, int prefix) len = p->simple_len; } di->expansion += len; - return 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. */ + dc = d_abi_tags (di, dc); + if (! d_add_substitution (di, dc)) + return NULL; + } + return dc; } } @@ -3301,6 +3983,24 @@ d_substitution (struct d_info *di, int prefix) } } +static void +d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint) +{ + checkpoint->n = di->n; + checkpoint->next_comp = di->next_comp; + checkpoint->next_sub = di->next_sub; + checkpoint->expansion = di->expansion; +} + +static void +d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint) +{ + di->n = checkpoint->n; + di->next_comp = checkpoint->next_comp; + di->next_sub = checkpoint->next_sub; + di->expansion = checkpoint->expansion; +} + /* Initialize a growable string. */ static void @@ -3377,11 +4077,152 @@ d_growable_string_callback_adapter (const char *s, size_t l, void *opaque) d_growable_string_append_buffer (dgs, s, l); } +/* Walk the tree, counting the number of templates encountered, and + the number of times a scope might be saved. These counts will be + used to allocate data structures for d_print_comp, so the logic + here must mirror the logic d_print_comp will use. It is not + important that the resulting numbers are exact, so long as they + are larger than the actual numbers encountered. */ + +static void +d_count_templates_scopes (struct d_print_info *dpi, + struct demangle_component *dc) +{ + if (dc == NULL || dc->d_counting > 1 || dpi->recursion > MAX_RECURSION_COUNT) + return; + + ++ dc->d_counting; + + switch (dc->type) + { + case DEMANGLE_COMPONENT_NAME: + case DEMANGLE_COMPONENT_TEMPLATE_PARAM: + case DEMANGLE_COMPONENT_FUNCTION_PARAM: + case DEMANGLE_COMPONENT_SUB_STD: + case DEMANGLE_COMPONENT_BUILTIN_TYPE: + case DEMANGLE_COMPONENT_OPERATOR: + case DEMANGLE_COMPONENT_CHARACTER: + case DEMANGLE_COMPONENT_NUMBER: + case DEMANGLE_COMPONENT_UNNAMED_TYPE: + break; + + case DEMANGLE_COMPONENT_TEMPLATE: + 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) + dpi->num_saved_scopes++; + goto recurse_left_right; + + case DEMANGLE_COMPONENT_QUAL_NAME: + case DEMANGLE_COMPONENT_LOCAL_NAME: + case DEMANGLE_COMPONENT_TYPED_NAME: + case DEMANGLE_COMPONENT_VTABLE: + case DEMANGLE_COMPONENT_VTT: + case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: + case DEMANGLE_COMPONENT_TYPEINFO: + case DEMANGLE_COMPONENT_TYPEINFO_NAME: + case DEMANGLE_COMPONENT_TYPEINFO_FN: + case DEMANGLE_COMPONENT_THUNK: + case DEMANGLE_COMPONENT_VIRTUAL_THUNK: + case DEMANGLE_COMPONENT_COVARIANT_THUNK: + case DEMANGLE_COMPONENT_JAVA_CLASS: + case DEMANGLE_COMPONENT_GUARD: + case DEMANGLE_COMPONENT_TLS_INIT: + case DEMANGLE_COMPONENT_TLS_WRAPPER: + case DEMANGLE_COMPONENT_REFTEMP: + case DEMANGLE_COMPONENT_HIDDEN_ALIAS: + case DEMANGLE_COMPONENT_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_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: + case DEMANGLE_COMPONENT_IMAGINARY: + case DEMANGLE_COMPONENT_VENDOR_TYPE: + case DEMANGLE_COMPONENT_FUNCTION_TYPE: + case DEMANGLE_COMPONENT_ARRAY_TYPE: + case DEMANGLE_COMPONENT_PTRMEM_TYPE: + 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: + case DEMANGLE_COMPONENT_NULLARY: + case DEMANGLE_COMPONENT_UNARY: + case DEMANGLE_COMPONENT_BINARY: + case DEMANGLE_COMPONENT_BINARY_ARGS: + case DEMANGLE_COMPONENT_TRINARY: + case DEMANGLE_COMPONENT_TRINARY_ARG1: + case DEMANGLE_COMPONENT_TRINARY_ARG2: + case DEMANGLE_COMPONENT_LITERAL: + case DEMANGLE_COMPONENT_LITERAL_NEG: + case DEMANGLE_COMPONENT_JAVA_RESOURCE: + case DEMANGLE_COMPONENT_COMPOUND_NAME: + case DEMANGLE_COMPONENT_DECLTYPE: + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + case DEMANGLE_COMPONENT_PACK_EXPANSION: + case DEMANGLE_COMPONENT_TAGGED_NAME: + case DEMANGLE_COMPONENT_CLONE: + recurse_left_right: + /* 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 (dpi, dc->u.s_ctor.name); + break; + + case DEMANGLE_COMPONENT_DTOR: + d_count_templates_scopes (dpi, dc->u.s_dtor.name); + break; + + case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: + d_count_templates_scopes (dpi, dc->u.s_extended_operator.name); + break; + + case DEMANGLE_COMPONENT_FIXED_TYPE: + 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 (dpi, d_left (dc)); + break; + + case DEMANGLE_COMPONENT_LAMBDA: + case DEMANGLE_COMPONENT_DEFAULT_ARG: + d_count_templates_scopes (dpi, dc->u.s_unary_num.sub); + break; + } +} + /* Initialize a print information structure. */ static void d_print_init (struct d_print_info *dpi, demangle_callbackref callback, - void *opaque) + void *opaque, struct demangle_component *dc) { dpi->len = 0; dpi->last_char = '\0'; @@ -3394,6 +4235,28 @@ 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; + + dpi->saved_scopes = NULL; + dpi->next_saved_scope = 0; + dpi->num_saved_scopes = 0; + + dpi->copy_templates = NULL; + dpi->next_copy_template = 0; + dpi->num_copy_templates = 0; + + 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; } /* Indicate that an error occurred during printing, and test for error. */ @@ -3449,10 +4312,10 @@ d_append_string (struct d_print_info *dpi, const char *s) } static inline void -d_append_num (struct d_print_info *dpi, long l) +d_append_num (struct d_print_info *dpi, int l) { char buf[25]; - sprintf (buf,"%ld", l); + sprintf (buf,"%d", l); d_append_string (dpi, buf); } @@ -3474,14 +4337,33 @@ 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; - d_print_init (&dpi, callback, opaque); + d_print_init (&dpi, callback, opaque, dc); - d_print_comp (&dpi, options, dc); + { +#ifdef CP_DYNAMIC_ARRAYS + /* Avoid zero-length VLAs, which are prohibited by the C99 standard + and flagged as errors by Address Sanitizer. */ + __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0) + ? dpi.num_saved_scopes : 1]; + __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0) + ? dpi.num_copy_templates : 1]; + + dpi.saved_scopes = scopes; + dpi.copy_templates = temps; +#else + dpi.saved_scopes = alloca (dpi.num_saved_scopes + * sizeof (*dpi.saved_scopes)); + dpi.copy_templates = alloca (dpi.num_copy_templates + * sizeof (*dpi.copy_templates)); +#endif + + d_print_comp (&dpi, options, dc); + } d_print_flush (&dpi); @@ -3498,7 +4380,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; @@ -3519,13 +4401,17 @@ cplus_demangle_print (int options, const struct demangle_component *dc, } /* Returns the I'th element of the template arglist ARGS, or NULL on - failure. */ + failure. If I is negative, return the entire arglist. */ static struct demangle_component * d_index_template_argument (struct demangle_component *args, int i) { struct demangle_component *a; + if (i < 0) + /* Print the whole argument pack. */ + return args; + for (a = args; a != NULL; a = d_right (a)) @@ -3583,11 +4469,16 @@ d_find_pack (struct d_print_info *dpi, case DEMANGLE_COMPONENT_LAMBDA: case DEMANGLE_COMPONENT_NAME: + case DEMANGLE_COMPONENT_TAGGED_NAME: case DEMANGLE_COMPONENT_OPERATOR: case DEMANGLE_COMPONENT_BUILTIN_TYPE: case DEMANGLE_COMPONENT_SUB_STD: 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; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: @@ -3620,15 +4511,41 @@ d_pack_length (const struct demangle_component *dc) return count; } +/* Returns the number of template args in DC, expanding any pack expansions + found there. */ + +static int +d_args_length (struct d_print_info *dpi, const struct demangle_component *dc) +{ + int count = 0; + for (; dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST; + dc = d_right (dc)) + { + struct demangle_component *elt = d_left (dc); + if (elt == NULL) + break; + if (elt->type == DEMANGLE_COMPONENT_PACK_EXPANSION) + { + struct demangle_component *a = d_find_pack (dpi, d_left (elt)); + count += d_pack_length (a); + } + else + ++count; + } + return count; +} + /* DC is a component of a mangled expression. Print it, wrapped in parens if needed. */ 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 + || dc->type == DEMANGLE_COMPONENT_QUAL_NAME + || dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM) simple = 1; if (!simple) @@ -3638,15 +4555,142 @@ d_print_subexpr (struct d_print_info *dpi, int options, d_append_char (dpi, ')'); } +/* Save the current scope. */ + +static void +d_save_scope (struct d_print_info *dpi, + const struct demangle_component *container) +{ + struct d_saved_scope *scope; + struct d_print_template *src, **link; + + if (dpi->next_saved_scope >= dpi->num_saved_scopes) + { + d_print_error (dpi); + return; + } + scope = &dpi->saved_scopes[dpi->next_saved_scope]; + dpi->next_saved_scope++; + + scope->container = container; + link = &scope->templates; + + for (src = dpi->templates; src != NULL; src = src->next) + { + struct d_print_template *dst; + + if (dpi->next_copy_template >= dpi->num_copy_templates) + { + d_print_error (dpi); + return; + } + dst = &dpi->copy_templates[dpi->next_copy_template]; + dpi->next_copy_template++; + + dst->template_decl = src->template_decl; + *link = dst; + link = &dst->next; + } + + *link = NULL; +} + +/* Attempt to locate a previously saved scope. Returns NULL if no + corresponding saved scope was found. */ + +static struct d_saved_scope * +d_get_saved_scope (struct d_print_info *dpi, + const struct demangle_component *container) +{ + int i; + + for (i = 0; i < dpi->next_saved_scope; i++) + if (dpi->saved_scopes[i].container == container) + return &dpi->saved_scopes[i]; + + return NULL; +} + +/* If DC is a C++17 fold-expression, print it and return true; otherwise + return false. */ + +static int +d_maybe_print_fold_expression (struct d_print_info *dpi, int options, + struct demangle_component *dc) +{ + struct demangle_component *ops, *operator_, *op1, *op2; + int save_idx; + + const char *fold_code = d_left (dc)->u.s_operator.op->code; + if (fold_code[0] != 'f') + return 0; + + ops = d_right (dc); + operator_ = d_left (ops); + op1 = d_right (ops); + op2 = 0; + if (op1->type == DEMANGLE_COMPONENT_TRINARY_ARG2) + { + op2 = d_right (op1); + op1 = d_left (op1); + } + + /* Print the whole pack. */ + save_idx = dpi->pack_index; + dpi->pack_index = -1; + + switch (fold_code[1]) + { + /* Unary left fold, (... + X). */ + case 'l': + d_append_string (dpi, "(..."); + d_print_expr_op (dpi, options, operator_); + d_print_subexpr (dpi, options, op1); + d_append_char (dpi, ')'); + break; + + /* Unary right fold, (X + ...). */ + case 'r': + d_append_char (dpi, '('); + d_print_subexpr (dpi, options, op1); + d_print_expr_op (dpi, options, operator_); + d_append_string (dpi, "...)"); + break; + + /* Binary left fold, (42 + ... + X). */ + case 'L': + /* Binary right fold, (X + ... + 42). */ + case 'R': + d_append_char (dpi, '('); + d_print_subexpr (dpi, options, op1); + d_print_expr_op (dpi, options, operator_); + d_append_string (dpi, "..."); + d_print_expr_op (dpi, options, operator_); + d_print_subexpr (dpi, options, op2); + d_append_char (dpi, ')'); + break; + } + + dpi->pack_index = save_idx; + return 1; +} + /* Subroutine to handle components. */ static void -d_print_comp (struct d_print_info *dpi, int options, - const struct demangle_component *dc) +d_print_comp_inner (struct d_print_info *dpi, int options, + 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. */ + struct d_print_template *saved_templates; + + /* Nonzero if templates have been stored in the above variable. */ + int need_template_restore = 0; if (dc == NULL) { @@ -3665,6 +4709,13 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); return; + case DEMANGLE_COMPONENT_TAGGED_NAME: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, "[abi:"); + d_print_comp (dpi, options, d_right (dc)); + d_append_char (dpi, ']'); + return; + case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: d_print_comp (dpi, options, d_left (dc)); @@ -3672,7 +4723,17 @@ d_print_comp (struct d_print_info *dpi, int options, d_append_string (dpi, "::"); else d_append_char (dpi, '.'); - d_print_comp (dpi, options, d_right (dc)); + { + struct demangle_component *local_name = d_right (dc); + if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) + { + d_append_string (dpi, "{default arg#"); + d_append_num (dpi, local_name->u.s_unary_num.num + 1); + d_append_string (dpi, "}::"); + local_name = local_name->u.s_unary_num.sub; + } + d_print_comp (dpi, options, local_name); + } return; case DEMANGLE_COMPONENT_TYPED_NAME: @@ -3705,9 +4766,7 @@ d_print_comp (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) + if (!is_fnqual_component_type (typed_name->type)) break; typed_name = d_left (typed_name); @@ -3719,29 +4778,17 @@ d_print_comp (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; - while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || local_name->type == DEMANGLE_COMPONENT_CONST_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]) { @@ -3753,13 +4800,27 @@ d_print_comp (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)); @@ -3788,6 +4849,12 @@ d_print_comp (struct d_print_info *dpi, int options, { struct d_print_mod *hold_dpm; struct demangle_component *dcl; + const struct demangle_component *hold_current; + + /* This template may need to be referenced by a cast operator + contained in its subtree. */ + hold_current = dpi->current_template; + dpi->current_template = dc; /* Don't push modifiers into a template definition. Doing so could give the wrong definition for a template argument. @@ -3824,38 +4891,52 @@ d_print_comp (struct d_print_info *dpi, int options, } dpi->modifiers = hold_dpm; + dpi->current_template = hold_current; return; } 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); @@ -3923,6 +5004,16 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp (dpi, options, d_left (dc)); return; + case DEMANGLE_COMPONENT_TLS_INIT: + d_append_string (dpi, "TLS init function for "); + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_TLS_WRAPPER: + d_append_string (dpi, "TLS wrapper function for "); + d_print_comp (dpi, options, d_left (dc)); + return; + case DEMANGLE_COMPONENT_REFTEMP: d_append_string (dpi, "reference temporary #"); d_print_comp (dpi, options, d_right (dc)); @@ -3935,6 +5026,16 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp (dpi, options, d_left (dc)); return; + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + d_append_string (dpi, "transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + d_append_string (dpi, "non-transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); + return; + case DEMANGLE_COMPONENT_SUB_STD: d_append_buffer (dpi, dc->u.s_string.string, dc->u.s_string.len); return; @@ -3971,15 +5072,60 @@ d_print_comp (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 demangle_component *a = d_lookup_template_argument (dpi, sub); + struct d_saved_scope *scope = d_get_saved_scope (dpi, sub); + struct demangle_component *a; + + if (scope == NULL) + { + /* This is the first time SUB has been traversed. + We need to capture the current templates so + they can be restored if SUB is reentered as a + substitution. */ + d_save_scope (dpi, sub); + if (d_print_saw_error (dpi)) + return; + } + else + { + const struct d_component_stack *dcse; + int found_self_or_parent = 0; + + /* This traversal is reentering SUB as a substition. + If we are not beneath SUB or DC in the tree then we + need to restore SUB's template stack temporarily. */ + for (dcse = dpi->component_stack; dcse != NULL; + dcse = dcse->parent) + { + if (dcse->dc == sub + || (dcse->dc == dc + && dcse != dpi->component_stack)) + { + found_self_or_parent = 1; + break; + } + } + + if (!found_self_or_parent) + { + saved_templates = dpi->templates; + dpi->templates = scope->templates; + need_template_restore = 1; + } + } + + a = d_lookup_template_argument (dpi, sub); if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) a = d_index_template_argument (a, dpi->pack_index); if (a == NULL) { + if (need_template_restore) + dpi->templates = saved_templates; + d_print_error (dpi); return; } @@ -3995,13 +5141,11 @@ d_print_comp (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_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: + FNQUAL_COMPONENT_CASE: modifier: { /* We keep a list of modifiers on the stack. */ @@ -4025,6 +5169,9 @@ d_print_comp (struct d_print_info *dpi, int options, dpi->modifiers = dpm.next; + if (need_template_restore) + dpi->templates = saved_templates; + return; } @@ -4214,16 +5361,32 @@ d_print_comp (struct d_print_info *dpi, int options, } return; + case DEMANGLE_COMPONENT_INITIALIZER_LIST: + { + struct demangle_component *type = d_left (dc); + struct demangle_component *list = d_right (dc); + + if (type) + d_print_comp (dpi, options, type); + d_append_char (dpi, '{'); + d_print_comp (dpi, options, list); + d_append_char (dpi, '}'); + } + return; + case DEMANGLE_COMPONENT_OPERATOR: { - char c; + const struct demangle_operator_info *op = dc->u.s_operator.op; + int len = op->len; d_append_string (dpi, "operator"); - c = dc->u.s_operator.op->name[0]; - if (IS_LOWER (c)) + /* Add a space before new/delete. */ + if (IS_LOWER (op->name[0])) d_append_char (dpi, ' '); - d_append_buffer (dpi, dc->u.s_operator.op->name, - dc->u.s_operator.op->len); + /* Omit a trailing space. */ + if (op->name[len-1] == ' ') + --len; + d_append_buffer (dpi, op->name, len); return; } @@ -4232,60 +5395,79 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_comp (dpi, options, dc->u.s_extended_operator.name); return; - case DEMANGLE_COMPONENT_CAST: + case DEMANGLE_COMPONENT_CONVERSION: d_append_string (dpi, "operator "); - d_print_cast (dpi, options, dc); + d_print_conversion (dpi, options, dc); + return; + + case DEMANGLE_COMPONENT_NULLARY: + d_print_expr_op (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_UNARY: - if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR - && d_left (dc)->u.s_operator.op->len == 1 - && d_left (dc)->u.s_operator.op->name[0] == '&' - && d_right (dc)->type == DEMANGLE_COMPONENT_TYPED_NAME - && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_QUAL_NAME - && d_right (d_right (dc))->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) - { - /* Address of a function (therefore in an expression context) must - have its argument list suppressed. - - unary operator ... dc - operator & ... d_left (dc) - typed name ... d_right (dc) - qualified name ... d_left (d_right (dc)) - - function type ... d_right (d_right (dc)) - argument list - */ + { + struct demangle_component *op = d_left (dc); + struct demangle_component *operand = d_right (dc); + const char *code = NULL; - d_print_expr_op (dpi, options, d_left (dc)); - d_print_comp (dpi, options, d_left (d_right (dc))); - return; - } - else if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR - && d_left (dc)->u.s_operator.op->len == 1 - && d_left (dc)->u.s_operator.op->name[0] == '&' - && d_right (dc)->type == DEMANGLE_COMPONENT_QUAL_NAME) - { - /* Keep also already processed variant without the argument list. + if (op->type == DEMANGLE_COMPONENT_OPERATOR) + { + code = op->u.s_operator.op->code; + if (!strcmp (code, "ad")) + { + /* Don't print the argument list for the address of a + function. */ + if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME + && d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME + && d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) + operand = d_left (operand); + } + if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS) + { + /* This indicates a suffix operator. */ + operand = d_left (operand); + d_print_subexpr (dpi, options, operand); + d_print_expr_op (dpi, options, op); + return; + } + } - unary operator ... dc - operator & ... d_left (dc) - qualified name ... d_right (dc) - */ + /* For sizeof..., just print the pack length. */ + if (code && !strcmp (code, "sZ")) + { + struct demangle_component *a = d_find_pack (dpi, operand); + int len = d_pack_length (a); + d_append_num (dpi, len); + return; + } + else if (code && !strcmp (code, "sP")) + { + int len = d_args_length (dpi, operand); + d_append_num (dpi, len); + return; + } - d_print_expr_op (dpi, options, d_left (dc)); - d_print_comp (dpi, options, d_right (dc)); - return; - } - else if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST) - d_print_expr_op (dpi, options, d_left (dc)); - else - { - d_append_char (dpi, '('); - d_print_cast (dpi, options, d_left (dc)); - d_append_char (dpi, ')'); - } - d_print_subexpr (dpi, options, d_right (dc)); + if (op->type != DEMANGLE_COMPONENT_CAST) + d_print_expr_op (dpi, options, op); + else + { + d_append_char (dpi, '('); + d_print_cast (dpi, options, op); + d_append_char (dpi, ')'); + } + if (code && !strcmp (code, "gs")) + /* Avoid parens after '::'. */ + d_print_comp (dpi, options, operand); + else if (code && !strcmp (code, "st")) + /* Always print parens for sizeof (type). */ + { + d_append_char (dpi, '('); + d_print_comp (dpi, options, operand); + d_append_char (dpi, ')'); + } + else + d_print_subexpr (dpi, options, operand); + } return; case DEMANGLE_COMPONENT_BINARY: @@ -4295,6 +5477,20 @@ d_print_comp (struct d_print_info *dpi, int options, return; } + if (op_is_new_cast (d_left (dc))) + { + d_print_expr_op (dpi, options, d_left (dc)); + d_append_char (dpi, '<'); + d_print_comp (dpi, options, d_left (d_right (dc))); + d_append_string (dpi, ">("); + d_print_comp (dpi, options, d_right (d_right (dc))); + d_append_char (dpi, ')'); + return; + } + + if (d_maybe_print_fold_expression (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. */ @@ -4350,11 +5546,35 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_error (dpi); return; } - d_print_subexpr (dpi, options, d_left (d_right (dc))); - d_print_expr_op (dpi, options, d_left (dc)); - d_print_subexpr (dpi, options, d_left (d_right (d_right (dc)))); - d_append_string (dpi, " : "); - d_print_subexpr (dpi, options, d_right (d_right (d_right (dc)))); + if (d_maybe_print_fold_expression (dpi, options, dc)) + return; + { + struct demangle_component *op = d_left (dc); + struct demangle_component *first = d_left (d_right (dc)); + struct demangle_component *second = d_left (d_right (d_right (dc))); + struct demangle_component *third = d_right (d_right (d_right (dc))); + + if (!strcmp (op->u.s_operator.op->code, "qu")) + { + d_print_subexpr (dpi, options, first); + d_print_expr_op (dpi, options, op); + d_print_subexpr (dpi, options, second); + d_append_string (dpi, " : "); + d_print_subexpr (dpi, options, third); + } + else + { + d_append_string (dpi, "new "); + if (d_left (first) != NULL) + { + d_print_subexpr (dpi, options, first); + d_append_char (dpi, ' '); + } + d_print_comp (dpi, options, second); + if (third) + d_print_subexpr (dpi, options, third); + } + } return; case DEMANGLE_COMPONENT_TRINARY_ARG1: @@ -4524,7 +5744,11 @@ d_print_comp (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, '}'); @@ -4549,6 +5773,31 @@ d_print_comp (struct d_print_info *dpi, int options, } } +static void +d_print_comp (struct d_print_info *dpi, int options, + 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; + dpi->component_stack = &self; + + 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 Unicode characters. The C++ ABI doesn't mention Unicode encoding, so we don't it for C++. Characters are encoded as @@ -4615,9 +5864,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))) + && (is_fnqual_component_type (mods->mod->type)))) { d_print_mod_list (dpi, options, mods->next, suffix); return; @@ -4670,9 +5917,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) + while (is_fnqual_component_type (dc->type)) dc = d_left (dc); d_print_comp (dpi, options, dc); @@ -4692,7 +5937,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) { @@ -4708,6 +5953,27 @@ d_print_mod (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_CONST_THIS: d_append_string (dpi, " const"); return; + 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)); @@ -4717,17 +5983,24 @@ d_print_mod (struct d_print_info *dpi, int options, if ((options & DMGL_JAVA) == 0) d_append_char (dpi, '*'); return; + case DEMANGLE_COMPONENT_REFERENCE_THIS: + /* For the ref-qualifier, put a space before the &. */ + d_append_char (dpi, ' '); + /* 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; 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) != '(') @@ -4756,7 +6029,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; @@ -4788,9 +6061,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: + FNQUAL_COMPONENT_CASE: break; default: break; @@ -4836,7 +6107,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; @@ -4890,7 +6161,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, @@ -4903,30 +6174,43 @@ 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) { - if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) - d_print_comp (dpi, options, d_left (dc)); - else - { - struct d_print_mod *hold_dpm; - struct d_print_template dpt; + d_print_comp (dpi, options, d_left (dc)); +} - /* It appears that for a templated cast operator, we need to put - the template parameters in scope for the operator name, but - not for the parameters. The effect is that we need to handle - the template printing here. */ +/* Print a conversion operator. */ - hold_dpm = dpi->modifiers; - dpi->modifiers = NULL; +static void +d_print_conversion (struct d_print_info *dpi, int options, + struct demangle_component *dc) +{ + struct d_print_template dpt; + /* For a conversion operator, we need the template parameters from + the enclosing template in scope for processing the type. */ + if (dpi->current_template != NULL) + { dpt.next = dpi->templates; dpi->templates = &dpt; - dpt.template_decl = d_left (dc); + dpt.template_decl = dpi->current_template; + } + if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) + { + d_print_comp (dpi, options, d_left (dc)); + if (dpi->current_template != NULL) + dpi->templates = dpt.next; + } + else + { d_print_comp (dpi, options, d_left (d_left (dc))); - dpi->templates = dpt.next; + /* For a templated cast operator, we need to remove the template + parameters from scope after printing the operator name, + so we need to handle the template printing here. */ + if (dpi->current_template != NULL) + dpi->templates = dpt.next; if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); @@ -4937,8 +6221,6 @@ d_print_cast (struct d_print_info *dpi, int options, if (d_last_char (dpi) == '>') d_append_char (dpi, ' '); d_append_char (dpi, '>'); - - dpi->modifiers = hold_dpm; } } @@ -4956,21 +6238,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 @@ -5010,6 +6294,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]; @@ -5041,6 +6339,8 @@ d_demangle_callback (const char *mangled, int options, NULL); d_advance (&di, strlen (d_str (&di))); break; + default: + abort (); /* We have listed all the cases. */ } /* If DMGL_PARAMS is set, then if we didn't consume the entire @@ -5311,14 +6611,17 @@ is_ctor_or_dtor (const char *mangled, { switch (dc->type) { + /* These cannot appear on a constructor or destructor. */ + case DEMANGLE_COMPONENT_RESTRICT_THIS: + case DEMANGLE_COMPONENT_VOLATILE_THIS: + case DEMANGLE_COMPONENT_CONST_THIS: + case DEMANGLE_COMPONENT_REFERENCE_THIS: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: default: dc = NULL; break; case DEMANGLE_COMPONENT_TYPED_NAME: case DEMANGLE_COMPONENT_TEMPLATE: - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: dc = d_left (dc); break; case DEMANGLE_COMPONENT_QUAL_NAME: