From 22a880cbc9cd0ad803bcaca8524309d23fd6607a Mon Sep 17 00:00:00 2001 From: pancake Date: Thu, 29 Nov 2018 11:20:45 +0100 Subject: [PATCH] Fix #12350 - Upgrade the c++ demangler from 2011 to 2018 --- libr/bin/mangling/cxx/Makefile | 6 + libr/bin/mangling/cxx/cp-demangle.c | 3388 ++++++++++++++++----------- libr/bin/mangling/cxx/cp-demangle.h | 41 +- libr/bin/mangling/cxx/demangle.h | 75 +- 4 files changed, 2083 insertions(+), 1427 deletions(-) diff --git a/libr/bin/mangling/cxx/Makefile b/libr/bin/mangling/cxx/Makefile index 2619b95baa..8c4225a4a0 100644 --- a/libr/bin/mangling/cxx/Makefile +++ b/libr/bin/mangling/cxx/Makefile @@ -1,2 +1,8 @@ all: emcc -z -o cxx.js -I. *.c -s EXPORTED_FUNCTIONS='["_cxx","cwrap"]' -DMY_EMSCRIPTEN=1 -s MODULARIZE=1 -s EXPORT_NAME=Demangle -s "EXTRA_EXPORTED_RUNTIME_METHODS=['cwrap']" + +sync: + rm -f demangle.h cp-demangle.c cp-demangle.h + wget https://raw.githubusercontent.com/gcc-mirror/gcc/master/include/demangle.h + wget https://raw.githubusercontent.com/gcc-mirror/gcc/master/libiberty/cp-demangle.c + wget https://raw.githubusercontent.com/gcc-mirror/gcc/master/libiberty/cp-demangle.h diff --git a/libr/bin/mangling/cxx/cp-demangle.c b/libr/bin/mangling/cxx/cp-demangle.c index ec2ad985a4..304fb2cc6d 100644 --- a/libr/bin/mangling/cxx/cp-demangle.c +++ b/libr/bin/mangling/cxx/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-2018 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,15 @@ 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 +#endif #ifdef HAVE_CONFIG_H #include "config.h" @@ -104,6 +111,23 @@ #include #include +#ifdef HAVE_ALLOCA_H +# include +#else +# ifndef alloca +# ifdef __GNUC__ +# define alloca __builtin_alloca +# else +extern char *alloca (); +# endif /* __GNUC__ */ +# endif /* alloca */ +#endif /* HAVE_ALLOCA_H */ + +#include +#ifndef INT_MAX +# define INT_MAX (int)(((unsigned int) ~0) >> 1) /* 0x7FFFFFFF */ +#endif + #include "ansidecl.h" #include "libiberty.h" #include "demangle.h" @@ -142,10 +166,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 @@ -234,7 +258,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. */ @@ -255,6 +279,16 @@ 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. */ @@ -267,6 +301,21 @@ struct d_saved_scope 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 { @@ -289,15 +338,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 @@ -339,7 +406,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); @@ -362,7 +429,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); @@ -370,6 +437,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 *); @@ -400,6 +469,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 *); @@ -424,6 +494,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 @@ -436,7 +510,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 *, + const struct demangle_component *); static inline void d_print_error (struct d_print_info *); @@ -454,7 +529,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); @@ -463,28 +538,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 @@ -492,7 +596,7 @@ d_dump (struct demangle_component *dc, int indent) { int i; - if (!dc) + if (dc == NULL) { if (indent == 0) printf ("failed demangling\n"); @@ -515,6 +619,12 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_TEMPLATE_PARAM: printf ("template parameter %ld\n", dc->u.s_number.number); return; + case DEMANGLE_COMPONENT_TPARM_OBJ: + printf ("template parameter object\n"); + break; + case DEMANGLE_COMPONENT_FUNCTION_PARAM: + printf ("function parameter %ld\n", dc->u.s_number.number); + return; case DEMANGLE_COMPONENT_CTOR: printf ("constructor %d\n", (int) dc->u.s_ctor.kind); d_dump (dc->u.s_ctor.name, indent + 2); @@ -619,6 +729,9 @@ d_dump (struct demangle_component *dc, int indent) 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; @@ -650,7 +763,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"); @@ -664,6 +779,9 @@ d_dump (struct demangle_component *dc, int indent) 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; @@ -700,6 +818,9 @@ 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; @@ -734,13 +855,13 @@ CP_STATIC_IF_GLIBCPP_V3 int cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len) { - if (!p || !s || len == 0) { - return 0; - } - p->type = DEMANGLE_COMPONENT_NAME; - p->u.s_name.s = s; - p->u.s_name.len = len; - return 1; + if (p == NULL || s == NULL || len == 0) + return 0; + p->d_printing = 0; + p->type = DEMANGLE_COMPONENT_NAME; + p->u.s_name.s = s; + p->u.s_name.len = len; + return 1; } /* Fill in a DEMANGLE_COMPONENT_EXTENDED_OPERATOR. */ @@ -750,13 +871,13 @@ int cplus_demangle_fill_extended_operator (struct demangle_component *p, int args, struct demangle_component *name) { - if (!p || args < 0 || !name) { - return 0; - } - p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; - p->u.s_extended_operator.args = args; - p->u.s_extended_operator.name = name; - return 1; + if (p == NULL || args < 0 || name == NULL) + return 0; + p->d_printing = 0; + p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR; + p->u.s_extended_operator.args = args; + p->u.s_extended_operator.name = name; + return 1; } /* Fill in a DEMANGLE_COMPONENT_CTOR. */ @@ -767,13 +888,16 @@ cplus_demangle_fill_ctor (struct demangle_component *p, enum gnu_v3_ctor_kinds kind, struct demangle_component *name) { - if (!p || !name || (int)kind < gnu_v3_complete_object_ctor || (int)kind > gnu_v3_object_ctor_group) { - return 0; - } - p->type = DEMANGLE_COMPONENT_CTOR; - p->u.s_ctor.kind = kind; - p->u.s_ctor.name = name; - return 1; + if (p == NULL + || name == NULL + || (int) kind < gnu_v3_complete_object_ctor + || (int) kind > gnu_v3_object_ctor_group) + return 0; + p->d_printing = 0; + p->type = DEMANGLE_COMPONENT_CTOR; + p->u.s_ctor.kind = kind; + p->u.s_ctor.name = name; + return 1; } /* Fill in a DEMANGLE_COMPONENT_DTOR. */ @@ -784,13 +908,16 @@ cplus_demangle_fill_dtor (struct demangle_component *p, enum gnu_v3_dtor_kinds kind, struct demangle_component *name) { - if (!p || !name || (int)kind < gnu_v3_deleting_dtor || (int)kind > gnu_v3_object_dtor_group) { - return 0; - } - p->type = DEMANGLE_COMPONENT_DTOR; - p->u.s_dtor.kind = kind; - p->u.s_dtor.name = name; - return 1; + if (p == NULL + || name == NULL + || (int) kind < gnu_v3_deleting_dtor + || (int) kind > gnu_v3_object_dtor_group) + return 0; + p->d_printing = 0; + p->type = DEMANGLE_COMPONENT_DTOR; + p->u.s_dtor.kind = kind; + p->u.s_dtor.name = name; + return 1; } /* Add a new component. */ @@ -800,10 +927,10 @@ d_make_empty (struct d_info *di) { struct demangle_component *p; - if (di->next_comp >= di->num_comps) { - return NULL; - } + if (di->next_comp >= di->num_comps) + return NULL; p = &di->comps[di->next_comp]; + p->d_printing = 0; ++di->next_comp; return p; } @@ -841,12 +968,11 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_COMPOUND_NAME: case DEMANGLE_COMPONENT_VECTOR_TYPE: case DEMANGLE_COMPONENT_CLONE: - if (!left || !right) { - return NULL; - } - break; + if (left == NULL || right == NULL) + return NULL; + break; - /* These types only require one parameter. */ + /* These types only require one parameter. */ case DEMANGLE_COMPONENT_VTABLE: case DEMANGLE_COMPONENT_VTT: case DEMANGLE_COMPONENT_TYPEINFO: @@ -870,6 +996,7 @@ 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: @@ -877,33 +1004,28 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: case DEMANGLE_COMPONENT_NULLARY: case DEMANGLE_COMPONENT_TRINARY_ARG2: - if (!left) { - return NULL; - } - break; + case DEMANGLE_COMPONENT_TPARM_OBJ: + if (left == NULL) + return NULL; + break; - /* This needs a right parameter, but the left parameter can be + /* This needs a right parameter, but the left parameter can be empty. */ case DEMANGLE_COMPONENT_ARRAY_TYPE: case DEMANGLE_COMPONENT_INITIALIZER_LIST: - if (!right) { - return NULL; - } - break; + if (right == NULL) + return NULL; + break; - /* These are allowed to have no parameters--in some cases they + /* These are allowed to have no parameters--in some cases they will be filled in later. */ case DEMANGLE_COMPONENT_FUNCTION_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_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: + FNQUAL_COMPONENT_CASE: break; /* Other types should not be seen here. */ @@ -926,11 +1048,10 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, static struct demangle_component * d_make_demangle_mangled_name (struct d_info *di, const char *s) { - if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z') { - return d_make_name (di, s, strlen (s)); - } - d_advance (di, 2); - return d_encoding (di, 0); + if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z') + return d_make_name (di, s, strlen (s)); + d_advance (di, 2); + return d_encoding (di, 0); } /* Add a new name component. */ @@ -941,9 +1062,8 @@ d_make_name (struct d_info *di, const char *s, int len) struct demangle_component *p; p = d_make_empty (di); - if (!cplus_demangle_fill_name (p, s, len)) { - return NULL; - } + if (! cplus_demangle_fill_name (p, s, len)) + return NULL; return p; } @@ -955,9 +1075,8 @@ d_make_builtin_type (struct d_info *di, { struct demangle_component *p; - if (!type) { - return NULL; - } + if (type == NULL) + return NULL; p = d_make_empty (di); if (p != NULL) { @@ -992,9 +1111,8 @@ d_make_extended_operator (struct d_info *di, int args, struct demangle_component *p; p = d_make_empty (di); - if (!cplus_demangle_fill_extended_operator (p, args, name)) { - return NULL; - } + if (! cplus_demangle_fill_extended_operator (p, args, name)) + return NULL; return p; } @@ -1021,9 +1139,8 @@ d_make_ctor (struct d_info *di, enum gnu_v3_ctor_kinds kind, struct demangle_component *p; p = d_make_empty (di); - if (!cplus_demangle_fill_ctor (p, kind, name)) { - return NULL; - } + if (! cplus_demangle_fill_ctor (p, kind, name)) + return NULL; return p; } @@ -1036,16 +1153,15 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind, struct demangle_component *p; p = d_make_empty (di); - if (!cplus_demangle_fill_dtor (p, kind, name)) { - return NULL; - } + if (! cplus_demangle_fill_dtor (p, kind, name)) + return NULL; return p; } /* 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; @@ -1061,7 +1177,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; @@ -1101,25 +1217,24 @@ cplus_demangle_mangled_name (struct d_info *di, int top_level) { struct demangle_component *p; - if (!d_check_char (di, '_') - /* Allow missing _ if not at toplevel to work around a + if (! d_check_char (di, '_') + /* Allow missing _ if not at toplevel to work around a bug in G++ abi-version=2 mangling; see the comment in write_template_arg. */ - && top_level) { - return NULL; - } - if (!d_check_char (di, 'Z')) { - return NULL; - } + && top_level) + return NULL; + if (! d_check_char (di, 'Z')) + return NULL; p = d_encoding (di, top_level); /* If at top level and parsing parameters, check for a clone suffix. */ - if (top_level && (di->options & DMGL_PARAMS) != 0) { - while (d_peek_char (di) == '.' && (IS_LOWER (d_peek_next_char (di)) || d_peek_next_char (di) == '_' || IS_DIGIT (d_peek_next_char (di)))) { - p = d_clone_suffix (di, p); - } - } + if (top_level && (di->options & DMGL_PARAMS) != 0) + while (d_peek_char (di) == '.' + && (IS_LOWER (d_peek_next_char (di)) + || d_peek_next_char (di) == '_' + || IS_DIGIT (d_peek_next_char (di)))) + p = d_clone_suffix (di, p); return p; } @@ -1136,20 +1251,18 @@ cplus_demangle_mangled_name (struct d_info *di, int top_level) static int has_return_type (struct demangle_component *dc) { - if (!dc) { - return 0; - } - switch (dc->type) { - default: - return 0; - case DEMANGLE_COMPONENT_TEMPLATE: - return !is_ctor_dtor_or_conversion (d_left (dc)); - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - return has_return_type (d_left (dc)); + if (dc == NULL) + return 0; + switch (dc->type) + { + default: + return 0; + case DEMANGLE_COMPONENT_LOCAL_NAME: + return has_return_type (d_right (dc)); + case DEMANGLE_COMPONENT_TEMPLATE: + return ! is_ctor_dtor_or_conversion (d_left (dc)); + FNQUAL_COMPONENT_CASE: + return has_return_type (d_left (dc)); } } @@ -1159,19 +1272,19 @@ has_return_type (struct demangle_component *dc) static int is_ctor_dtor_or_conversion (struct demangle_component *dc) { - if (!dc) { - return 0; - } - switch (dc->type) { - default: - return 0; - case DEMANGLE_COMPONENT_QUAL_NAME: - case DEMANGLE_COMPONENT_LOCAL_NAME: - return is_ctor_dtor_or_conversion (d_right (dc)); - case DEMANGLE_COMPONENT_CTOR: - case DEMANGLE_COMPONENT_DTOR: - case DEMANGLE_COMPONENT_CAST: - return 1; + if (dc == NULL) + return 0; + switch (dc->type) + { + default: + return 0; + case DEMANGLE_COMPONENT_QUAL_NAME: + case DEMANGLE_COMPONENT_LOCAL_NAME: + return is_ctor_dtor_or_conversion (d_right (dc)); + case DEMANGLE_COMPONENT_CTOR: + case DEMANGLE_COMPONENT_DTOR: + case DEMANGLE_COMPONENT_CONVERSION: + return 1; } } @@ -1188,46 +1301,60 @@ 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); - } else { - struct demangle_component *dc; + if (peek == 'G' || peek == 'T') + dc = d_special_name (di); + else + { + dc = d_name (di); - dc = d_name (di); - - if (dc != NULL && top_level && (di->options & DMGL_PARAMS) == 0) { - /* Strip off any initial CV-qualifiers, as they really apply + if (!dc) + /* Failed already. */; + else if (top_level && (di->options & DMGL_PARAMS) == 0) + { + /* Strip off any initial CV-qualifiers, as they really apply to the `this' parameter, and they were not output by the v2 demangler without DMGL_PARAMS. */ - while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dc->type == DEMANGLE_COMPONENT_CONST_THIS || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) { - dc = d_left (dc); - } + 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 + /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then + there may be function-qualifiers on its right argument which really apply here; this happens when parsing a class which is local to a function. */ - if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) { - struct demangle_component *dcr; - - dcr = d_right (dc); - while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dcr->type == DEMANGLE_COMPONENT_CONST_THIS || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) { - dcr = d_left (dcr); - } - dc->u.s_binary.right = dcr; - } - - return dc; - } - + if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME) + while (is_fnqual_component_type (d_right (dc)->type)) + d_right (dc) = d_left (d_right (dc)); + } + else + { peek = d_peek_char (di); - if (!dc || 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))); + if (peek != '\0' && peek != 'E') + { + struct demangle_component *ftype; + + ftype = d_bare_function_type (di, has_return_type (dc)); + if (ftype) + { + /* If this is a non-top-level local-name, clear the + return type, so it doesn't confuse the user by + being confused with the return type of whaever + this is nested within. */ + if (!top_level && dc->type == DEMANGLE_COMPONENT_LOCAL_NAME + && ftype->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) + d_left (ftype) = NULL; + + dc = d_make_comp (di, DEMANGLE_COMPONENT_TYPED_NAME, + dc, ftype); + } + else + dc = NULL; + } + } } + + return dc; } /* ::= B */ @@ -1235,7 +1362,12 @@ d_encoding (struct d_info *di, int top_level) 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') { @@ -1244,6 +1376,9 @@ d_abi_tags (struct d_info *di, struct demangle_component *dc) tag = d_source_name (di); dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag); } + + di->last_name = hold_last_name; + return dc; } @@ -1309,9 +1444,8 @@ d_name (struct d_info *di) substitution. */ if (! subst) { - if (!d_add_substitution (di, dc)) { - return NULL; - } + if (! d_add_substitution (di, dc)) + return NULL; } dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); @@ -1328,9 +1462,8 @@ d_name (struct d_info *di) /* This is , which means that we just saw , which is a substitution candidate. */ - if (!d_add_substitution (di, dc)) { - return NULL; - } + if (! d_add_substitution (di, dc)) + return NULL; dc = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, dc, d_template_args (di)); } @@ -1349,23 +1482,20 @@ d_nested_name (struct d_info *di) struct demangle_component **pret; struct demangle_component *rqual; - if (!d_check_char (di, 'N')) { - return NULL; - } + if (! d_check_char (di, 'N')) + return NULL; pret = d_cv_qualifiers (di, &ret, 1); - if (!pret) { - return NULL; - } + 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) { - return NULL; - } + if (*pret == NULL) + return NULL; if (rqual) { @@ -1373,11 +1503,10 @@ d_nested_name (struct d_info *di) ret = rqual; } - if (!d_check_char (di, 'E')) { - return NULL; - } + if (! d_check_char (di, 'E')) + return NULL; - return ret; + return ret; } /* ::= @@ -1404,9 +1533,8 @@ d_prefix (struct d_info *di) struct demangle_component *dc; peek = d_peek_char (di); - if (peek == '\0') { - return NULL; - } + if (peek == '\0') + return NULL; /* The older code accepts a here, but I don't see that in the grammar. The older code does not accept a @@ -1416,51 +1544,54 @@ d_prefix (struct d_info *di) if (peek == 'D') { char peek2 = d_peek_next_char (di); - if (peek2 == 'T' || peek2 == 't') { - /* Decltype. */ - dc = cplus_demangle_type (di); - } else { - /* Destructor name. */ - dc = d_unqualified_name (di); - } - } else if (IS_DIGIT (peek) || IS_LOWER (peek) || peek == 'C' || peek == 'U' || peek == 'L') { - dc = d_unqualified_name (di); - } else if (peek == 'S') { - dc = d_substitution (di, 1); - } else if (peek == 'I') { - if (!ret) { - return NULL; - } - comb_type = DEMANGLE_COMPONENT_TEMPLATE; - dc = d_template_args (di); - } else if (peek == 'T') { - dc = d_template_param (di); - } else if (peek == 'E') { - return ret; - } else if (peek == 'M') { - /* Initializer scope for a lambda. We don't need to represent + if (peek2 == 'T' || peek2 == 't') + /* Decltype. */ + dc = cplus_demangle_type (di); + else + /* Destructor name. */ + dc = d_unqualified_name (di); + } + else if (IS_DIGIT (peek) + || IS_LOWER (peek) + || peek == 'C' + || peek == 'U' + || peek == 'L') + dc = d_unqualified_name (di); + else if (peek == 'S') + dc = d_substitution (di, 1); + else if (peek == 'I') + { + if (ret == NULL) + return NULL; + comb_type = DEMANGLE_COMPONENT_TEMPLATE; + dc = d_template_args (di); + } + else if (peek == 'T') + dc = d_template_param (di); + else if (peek == 'E') + return ret; + else if (peek == 'M') + { + /* Initializer scope for a lambda. We don't need to represent this; the normal code will just treat the variable as a type scope, which gives appropriate output. */ - if (!ret) { - return NULL; - } - d_advance (di, 1); - continue; - } else { - return NULL; - } + if (ret == NULL) + return NULL; + d_advance (di, 1); + continue; + } + else + return NULL; - if (!ret) { - ret = dc; - } else { - ret = d_make_comp (di, comb_type, ret, dc); - } + if (ret == NULL) + ret = dc; + else + ret = d_make_comp (di, comb_type, ret, dc); if (peek != 'S' && d_peek_char (di) != 'E') { - if (!d_add_substitution (di, ret)) { - return NULL; - } + if (! d_add_substitution (di, ret)) + return NULL; } } } @@ -1480,32 +1611,32 @@ d_unqualified_name (struct d_info *di) char peek; peek = d_peek_char (di); - if (!peek) { - return NULL; - } - if (IS_DIGIT (peek)) { - ret = d_source_name (di); - } else if (IS_LOWER (peek)) { - ret = d_operator_name (di); - if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) { - 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') { - ret = d_ctor_dtor_name (di); - } else if (peek == 'L') { - d_advance (di, 1); + if (IS_DIGIT (peek)) + ret = d_source_name (di); + else if (IS_LOWER (peek)) + { + if (peek == 'o' && d_peek_next_char (di) == 'n') + d_advance (di, 2); + ret = d_operator_name (di); + if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR) + { + 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') + ret = d_ctor_dtor_name (di); + else if (peek == 'L') + { + d_advance (di, 1); - ret = d_source_name (di); - if (!ret) { - return NULL; - } - if (!d_discriminator (di)) { - return NULL; - } + ret = d_source_name (di); + if (ret == NULL) + return NULL; + if (! d_discriminator (di)) + return NULL; } else if (peek == 'U') { @@ -1520,14 +1651,12 @@ d_unqualified_name (struct d_info *di) default: return NULL; } - } else { - return NULL; } + else + return NULL; - peek = d_peek_char (di); - if (peek == 'B') { - ret = d_abi_tags (di, ret); - } + if (d_peek_char (di) == 'B') + ret = d_abi_tags (di, ret); return ret; } @@ -1536,13 +1665,12 @@ 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); - if (len <= 0) { - return NULL; - } + if (len <= 0) + return NULL; ret = d_identifier (di, len); di->last_name = ret; return ret; @@ -1550,18 +1678,15 @@ 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); - if (!peek) { - return 0; - } if (peek == 'n') { negative = 1; @@ -1574,11 +1699,12 @@ d_number (struct d_info *di) { if (! IS_DIGIT (peek)) { - if (negative) { - ret = -ret; - } - return ret; + if (negative) + ret = - ret; + return ret; } + if (ret > ((INT_MAX - (peek - '0')) / 10)) + return -1; ret = ret * 10 + peek - '0'; d_advance (di, 1); peek = d_peek_char (di); @@ -1608,19 +1734,17 @@ d_identifier (struct d_info *di, int len) name = d_str (di); - if (di->send - name < len || len < 1) { - return NULL; - } + if (di->send - name < len) + return NULL; d_advance (di, len); /* A Java mangled name may have a trailing '$' if it is a C++ keyword. This '$' is not included in the length count. We just ignore the '$'. */ - char peek = d_peek_char (di); - if ((di->options & DMGL_JAVA) != 0 && peek == '$') { + if ((di->options & DMGL_JAVA) != 0 + && d_peek_char (di) == '$') d_advance (di, 1); - } /* Look for something which looks like a gcc encoding of an anonymous namespace, and replace it with a more user friendly @@ -1650,7 +1774,7 @@ d_identifier (struct d_info *di, int len) This list is sorted for binary search. */ -#define NL(s) s, (sizeof (s)) - 1 +#define NL(s) s, (sizeof s) - 1 CP_STATIC_IF_GLIBCPP_V3 const struct demangle_operator_info cplus_demangle_operators[] = @@ -1677,6 +1801,10 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "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 }, @@ -1711,6 +1839,8 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "rc", NL ("reinterpret_cast"), 2 }, { "rm", NL ("%"), 2 }, { "rs", NL (">>"), 2 }, + { "sP", NL ("sizeof..."), 1 }, + { "sZ", NL ("sizeof..."), 1 }, { "sc", NL ("static_cast"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, @@ -1727,38 +1857,51 @@ d_operator_name (struct d_info *di) c1 = d_next_char (di); c2 = d_next_char (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); - } else { - /* LOW is the inclusive lower bound. */ - int low = 0; - /* HIGH is the exclusive upper bound. We subtract one to ignore + if (c1 == 'v' && IS_DIGIT (c2)) + return d_make_extended_operator (di, c2 - '0', d_source_name (di)); + else if (c1 == 'c' && c2 == 'v') + { + 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. */ + int low = 0; + /* HIGH is the exclusive upper bound. We subtract one to ignore the sentinel at the end of the array. */ - int high = ((sizeof (cplus_demangle_operators) / sizeof (cplus_demangle_operators[0])) - 1); + int high = ((sizeof (cplus_demangle_operators) + / sizeof (cplus_demangle_operators[0])) + - 1); - while (1) { - int i; - const struct demangle_operator_info *p; + while (1) + { + int i; + const struct demangle_operator_info *p; - i = low + (high - low) / 2; - p = cplus_demangle_operators + i; + i = low + (high - low) / 2; + p = cplus_demangle_operators + i; - if (c1 == p->code[0] && c2 == p->code[1]) { - return d_make_operator (di, p); - } + if (c1 == p->code[0] && c2 == p->code[1]) + return d_make_operator (di, p); - if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1])) { - high = i; - } else { - low = i + 1; - } - if (low == high) { - return NULL; - } - } + if (c1 < p->code[0] || (c1 == p->code[0] && c2 < p->code[1])) + high = i; + else + low = i + 1; + if (low == high) + return NULL; + } } } @@ -1780,19 +1923,17 @@ 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; len = d_number (di); - if (len <= 1) { - return NULL; - } + if (len <= 1) + return NULL; /* Eat the leading '_'. */ - if (d_next_char (di) != '_') { - return NULL; - } + if (d_next_char (di) != '_') + return NULL; len--; str = d_str (di); @@ -1801,9 +1942,8 @@ d_java_resource (struct d_info *di) while (len > 0) { c = str[i]; - if (!c) { - return NULL; - } + if (!c) + return NULL; /* Each chunk is either a '$' escape... */ if (c == '$') @@ -1828,34 +1968,31 @@ d_java_resource (struct d_info *di) str = d_str (di); len -= i; i = 0; - if (!next) { - return NULL; - } + if (next == NULL) + return NULL; } /* ... or a sequence of characters. */ else { - while (i < len && str[i] && str[i] != '$') { - i++; - } + while (i < len && str[i] && str[i] != '$') + i++; - next = d_make_name (di, str, i); - d_advance (di, i); - str = d_str (di); - len -= i; - i = 0; - if (!next) { - return NULL; - } + next = d_make_name (di, str, i); + d_advance (di, i); + str = d_str (di); + len -= i; + i = 0; + if (next == NULL) + return NULL; } - if (!p) { - p = next; - } else { - p = d_make_comp (di, DEMANGLE_COMPONENT_COMPOUND_NAME, p, next); - if (!p) { - return NULL; - } + if (p == NULL) + p = next; + else + { + p = d_make_comp (di, DEMANGLE_COMPONENT_COMPOUND_NAME, p, next); + if (p == NULL) + return NULL; } } @@ -1868,6 +2005,7 @@ d_java_resource (struct d_info *di) ::= TT ::= TI ::= TS + ::= TA ::= GV <(object) name> ::= T <(base) encoding> ::= Tc <(base) encoding> @@ -1906,43 +2044,37 @@ d_special_name (struct d_info *di) cplus_demangle_type (di), NULL); case 'h': - if (!d_call_offset (di, 'h')) { - return NULL; - } - return d_make_comp (di, DEMANGLE_COMPONENT_THUNK, - d_encoding (di, 0), NULL); + if (! d_call_offset (di, 'h')) + return NULL; + return d_make_comp (di, DEMANGLE_COMPONENT_THUNK, + d_encoding (di, 0), NULL); case 'v': - if (!d_call_offset (di, 'v')) { - return NULL; - } - return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK, - d_encoding (di, 0), NULL); + if (! d_call_offset (di, 'v')) + return NULL; + return d_make_comp (di, DEMANGLE_COMPONENT_VIRTUAL_THUNK, + d_encoding (di, 0), NULL); case 'c': - if (!d_call_offset (di, '\0')) { - return NULL; - } - if (!d_call_offset (di, '\0')) { - return NULL; - } - return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK, - d_encoding (di, 0), NULL); + if (! d_call_offset (di, '\0')) + return NULL; + if (! d_call_offset (di, '\0')) + return NULL; + return d_make_comp (di, DEMANGLE_COMPONENT_COVARIANT_THUNK, + d_encoding (di, 0), NULL); case 'C': { struct demangle_component *derived_type; - long offset; + int offset; struct demangle_component *base_type; derived_type = cplus_demangle_type (di); offset = d_number (di); - if (offset < 0) { - return NULL; - } - if (!d_check_char (di, '_')) { - return NULL; - } + if (offset < 0) + return NULL; + if (! d_check_char (di, '_')) + return NULL; base_type = cplus_demangle_type (di); /* We don't display the offset. FIXME: We should display it in verbose mode. */ @@ -1966,6 +2098,10 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER, d_name (di), NULL); + case 'A': + return d_make_comp (di, DEMANGLE_COMPONENT_TPARM_OBJ, + d_template_arg (di), NULL); + default: return NULL; } @@ -1975,7 +2111,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': { @@ -2011,9 +2148,9 @@ d_special_name (struct d_info *di) default: return NULL; } - } else { - return NULL; } + else + return NULL; } /* ::= h _ @@ -2032,27 +2169,25 @@ d_special_name (struct d_info *di) static int d_call_offset (struct d_info *di, int c) { - if (c == '\0') { - c = d_next_char (di); - } + if (c == '\0') + c = d_next_char (di); - if (c == 'h') { - d_number (di); - } else if (c == 'v') { - d_number (di); - if (!d_check_char (di, '_')) { - return 0; - } - d_number (di); - } else { - return 0; - } + if (c == 'h') + d_number (di); + else if (c == 'v') + { + d_number (di); + if (! d_check_char (di, '_')) + return 0; + d_number (di); + } + else + return 0; - if (!d_check_char (di, '_')) { - return 0; - } + if (! d_check_char (di, '_')) + return 0; - return 1; + return 1; } /* ::= C1 @@ -2068,17 +2203,23 @@ d_ctor_dtor_name (struct d_info *di) { if (di->last_name != NULL) { - if (di->last_name->type == DEMANGLE_COMPONENT_NAME) { - di->expansion += di->last_name->u.s_name.len; - } else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD) { - di->expansion += di->last_name->u.s_string.len; - } + if (di->last_name->type == DEMANGLE_COMPONENT_NAME) + di->expansion += di->last_name->u.s_name.len; + else if (di->last_name->type == DEMANGLE_COMPONENT_SUB_STD) + di->expansion += di->last_name->u.s_string.len; } switch (d_peek_char (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)) { @@ -2091,13 +2232,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); } @@ -2116,6 +2265,10 @@ 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; @@ -2131,6 +2284,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; +} + /* ::= ::= ::= @@ -2216,27 +2387,24 @@ 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) { - return NULL; - } + if (pret == NULL) + return NULL; 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; - } + } + else + *pret = cplus_demangle_type (di); + if (!*pret) + return NULL; if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS) { @@ -2247,14 +2415,14 @@ cplus_demangle_type (struct d_info *di) ret = *pret; *pret = fn; } - if (!d_add_substitution (di, ret)) { - return NULL; - } - return ret; + 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': @@ -2297,14 +2465,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; @@ -2322,12 +2537,11 @@ cplus_demangle_type (struct d_info *di) ret = d_substitution (di, 0); /* The substituted name may have been a template name and may be followed by tepmlate args. */ - if (d_peek_char (di) == 'I') { - ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, - d_template_args (di)); - } else { - can_subst = 0; - } + if (d_peek_char (di) == 'I') + ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret, + d_template_args (di)); + else + can_subst = 0; } else { @@ -2336,9 +2550,8 @@ cplus_demangle_type (struct d_info *di) a new substitution candidate. However, if the substitution was followed by template arguments, then the whole thing is a substitution candidate. */ - if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) { - can_subst = 0; - } + if (ret != NULL && ret->type == DEMANGLE_COMPONENT_SUB_STD) + can_subst = 0; } } break; @@ -2376,6 +2589,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; @@ -2391,9 +2607,8 @@ cplus_demangle_type (struct d_info *di) /* decltype (expression) */ ret = d_make_comp (di, DEMANGLE_COMPONENT_DECLTYPE, d_expression (di), NULL); - if (ret && d_next_char (di) != 'E') { - ret = NULL; - } + if (ret && d_next_char (di) != 'E') + ret = NULL; can_subst = 1; break; @@ -2408,7 +2623,11 @@ cplus_demangle_type (struct d_info *di) /* auto */ ret = d_make_name (di, "auto", 4); break; - + case 'c': + /* decltype(auto) */ + ret = d_make_name (di, "decltype(auto)", 14); + break; + case 'f': /* 32-bit decimal floating point */ ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]); @@ -2444,14 +2663,12 @@ cplus_demangle_type (struct d_info *di) /* Fixed point types. DF */ ret = d_make_empty (di); ret->type = DEMANGLE_COMPONENT_FIXED_TYPE; - if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di)))) { - /* For demangling we don't care about the bits. */ - d_number (di); - } + if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di)))) + /* For demangling we don't care about the bits. */ + d_number (di); ret->u.s_fixed.length = cplus_demangle_type (di); - if (!ret->u.s_fixed.length) { - return NULL; - } + if (ret->u.s_fixed.length == NULL) + return NULL; d_number (di); peek = d_next_char (di); ret->u.s_fixed.sat = (peek == 's'); @@ -2479,15 +2696,14 @@ cplus_demangle_type (struct d_info *di) if (can_subst) { - if (!d_add_substitution (di, ret)) { - return NULL; - } + if (! d_add_substitution (di, ret)) + return NULL; } return ret; } -/* ::= [r] [V] [K] */ +/* ::= [r] [V] [K] [Dx] */ static struct demangle_component ** d_cv_qualifiers (struct d_info *di, @@ -2498,9 +2714,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') @@ -2517,18 +2734,52 @@ 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); - if (!*pret) { - return NULL; - } + *pret = d_make_comp (di, t, NULL, right); + if (*pret == NULL) + return NULL; pret = &d_left (*pret); peek = d_peek_char (di); @@ -2590,16 +2841,15 @@ d_ref_qualifier (struct d_info *di, struct demangle_component *sub) return ret; } -/* ::= F [Y] [] E */ +/* ::= F [Y] [] [T] E */ static struct demangle_component * d_function_type (struct d_info *di) { struct demangle_component *ret; - if (!d_check_char (di, 'F')) { - return NULL; - } + if (! d_check_char (di, 'F')) + return NULL; if (d_peek_char (di) == 'Y') { /* Function has C linkage. We don't print this information. @@ -2609,9 +2859,8 @@ d_function_type (struct d_info *di) ret = d_bare_function_type (di, 1); ret = d_ref_qualifier (di, ret); - if (!d_check_char (di, 'E')) { - return NULL; - } + if (! d_check_char (di, 'E')) + return NULL; return ret; } @@ -2630,35 +2879,34 @@ d_parmlist (struct d_info *di) struct demangle_component *type; 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; - } + 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) { - return NULL; - } + if (type == NULL) + return NULL; *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); - if (!*ptl) { - return NULL; - } + if (*ptl == NULL) + return NULL; ptl = &d_right (*ptl); } /* There should be at least one parameter type besides the optional return type. A function which takes no arguments will have a single parameter type void. */ - if (!tl) { - return NULL; - } + if (tl == NULL) + return NULL; - /* If we have a single parameter type void, omit it. */ - if (!d_right (tl) && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) { - di->expansion -= d_left (tl)->u.s_builtin.type->len; - d_left (tl) = NULL; + /* If we have a single parameter type void, omit it. */ + if (d_right (tl) == NULL + && d_left (tl)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE + && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) + { + di->expansion -= d_left (tl)->u.s_builtin.type->len; + d_left (tl) = NULL; } return tl; @@ -2685,17 +2933,15 @@ d_bare_function_type (struct d_info *di, int has_return_type) if (has_return_type) { return_type = cplus_demangle_type (di); - if (!return_type) { - return NULL; - } - } else { - return_type = NULL; - } + if (return_type == NULL) + return NULL; + } + else + return_type = NULL; tl = d_parmlist (di); - if (!tl) { - return NULL; - } + if (tl == NULL) + return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl); @@ -2719,40 +2965,39 @@ d_array_type (struct d_info *di) char peek; struct demangle_component *dim; - if (!d_check_char (di, 'A')) { - return NULL; - } + if (! d_check_char (di, 'A')) + return NULL; peek = d_peek_char (di); - if (peek == '_') { - dim = NULL; - } else if (IS_DIGIT (peek)) { - const char *s; + if (peek == '_') + dim = NULL; + else if (IS_DIGIT (peek)) + { + const char *s; - s = d_str (di); - do { - d_advance (di, 1); - peek = d_peek_char (di); - } while (IS_DIGIT (peek)); - dim = d_make_name (di, s, d_str (di) - s); - if (!dim) { - return NULL; - } + s = d_str (di); + do + { + d_advance (di, 1); + peek = d_peek_char (di); + } + while (IS_DIGIT (peek)); + dim = d_make_name (di, s, d_str (di) - s); + if (dim == NULL) + return NULL; } else { dim = d_expression (di); - if (!dim) { - return NULL; - } + if (dim == NULL) + return NULL; } - if (!d_check_char (di, '_')) { - return NULL; - } + if (! d_check_char (di, '_')) + return NULL; - return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, - cplus_demangle_type (di)); + return d_make_comp (di, DEMANGLE_COMPONENT_ARRAY_TYPE, dim, + cplus_demangle_type (di)); } /* ::= Dv _ @@ -2769,17 +3014,15 @@ d_vector_type (struct d_info *di) { d_advance (di, 1); dim = d_expression (di); - } else { - dim = d_number_component (di); - } + } + else + dim = d_number_component (di); - if (!dim) { - return NULL; - } + if (dim == NULL) + return NULL; - if (!d_check_char (di, '_')) { - return NULL; - } + if (! d_check_char (di, '_')) + return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim, cplus_demangle_type (di)); @@ -2793,14 +3036,12 @@ d_pointer_to_member_type (struct d_info *di) struct demangle_component *cl; struct demangle_component *mem; - if (!d_check_char (di, 'M')) { - return NULL; - } + if (! d_check_char (di, 'M')) + return NULL; cl = cplus_demangle_type (di); - if (!cl) { - return NULL; - } + if (cl == NULL) + return NULL; /* The ABI says, "The type of a non-static member function is considered to be different, for the purposes of substitution, from the type of a @@ -2818,30 +3059,27 @@ d_pointer_to_member_type (struct d_info *di) wrong type in the substitution table is harmless. */ mem = cplus_demangle_type (di); - if (!mem) { - return NULL; - } + if (mem == NULL) + 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; - if (d_peek_char (di) == '_') { - num = 0; - } else if (d_peek_char (di) == 'n') { - return -1; - } else { - num = d_number (di) + 1; - } + int num; + if (d_peek_char (di) == '_') + num = 0; + else if (d_peek_char (di) == 'n') + return -1; + else + num = d_number (di) + 1; - if (!d_check_char (di, '_')) { - return -1; - } + if (num < 0 || ! d_check_char (di, '_')) + return -1; return num; } @@ -2852,18 +3090,14 @@ 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; - } + if (! d_check_char (di, 'T')) + return NULL; param = d_compact_number (di); - if (param < 0) { - return NULL; - } - - ++di->did_subs; + if (param < 0) + return NULL; return d_make_template_param (di, param); } @@ -2872,6 +3106,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; @@ -2882,11 +3129,6 @@ d_template_args (struct d_info *di) constructor or destructor. */ hold_last_name = di->last_name; - if (d_peek_char (di) != 'I' && d_peek_char (di) != 'J') { - return NULL; - } - d_advance (di, 1); - if (d_peek_char (di) == 'E') { /* An argument pack can be empty. */ @@ -2901,14 +3143,12 @@ d_template_args (struct d_info *di) struct demangle_component *a; a = d_template_arg (di); - if (!a) { - return NULL; - } + if (a == NULL) + return NULL; *pal = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, a, NULL); - if (!*pal) { - return NULL; - } + if (*pal == NULL) + return NULL; pal = &d_right (*pal); if (d_peek_char (di) == 'E') @@ -2938,9 +3178,8 @@ d_template_arg (struct d_info *di) case 'X': d_advance (di, 1); ret = d_expression (di); - if (!d_check_char (di, 'E')) { - return NULL; - } + if (! d_check_char (di, 'E')) + return NULL; return ret; case 'L': @@ -2974,14 +3213,12 @@ d_exprlist (struct d_info *di, char terminator) while (1) { struct demangle_component *arg = d_expression (di); - if (!arg) { - return NULL; - } + if (arg == NULL) + return NULL; *p = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, arg, NULL); - if (!*p) { - return NULL; - } + if (*p == NULL) + return NULL; p = &d_right (*p); if (d_peek_char (di) == terminator) @@ -3017,36 +3254,36 @@ op_is_new_cast (struct demangle_component *op) ::= */ -static struct demangle_component * -d_expression (struct d_info *di) +static inline struct demangle_component * +d_expression_1 (struct d_info *di) { char peek; peek = d_peek_char (di); - if (peek == 'L') { - return d_expr_primary (di); - } else if (peek == 'T') { - return d_template_param (di); - } else if (peek == 's' && d_peek_next_char (di) == 'r') { - struct demangle_component *type; - struct demangle_component *name; + if (peek == 'L') + return d_expr_primary (di); + else if (peek == 'T') + return d_template_param (di); + else if (peek == 's' && d_peek_next_char (di) == 'r') + { + struct demangle_component *type; + struct demangle_component *name; - d_advance (di, 2); - type = cplus_demangle_type (di); - name = d_unqualified_name (di); - if (d_peek_char (di) != 'I') { - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); - } else { - return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, - d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, - d_template_args (di))); - } + d_advance (di, 2); + type = cplus_demangle_type (di); + name = d_unqualified_name (di); + if (d_peek_char (di) != 'I') + return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, name); + else + return d_make_comp (di, DEMANGLE_COMPONENT_QUAL_NAME, type, + d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, + d_template_args (di))); } else if (peek == 's' && d_peek_next_char (di) == 'p') { 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') { @@ -3061,10 +3298,10 @@ d_expression (struct d_info *di) } else { - index = d_compact_number (di) + 1; - if (index == 0) { - return NULL; - } + index = d_compact_number (di); + if (index == INT_MAX || index == -1) + return NULL; + index++; } return d_make_function_param (di, index); } @@ -3075,31 +3312,29 @@ d_expression (struct d_info *di) a dependent function call, i.e. decltype(f(t)). */ struct demangle_component *name; - if (peek == 'o') { - /* operator-function-id, i.e. operator+(t). */ - d_advance (di, 2); - } + if (peek == 'o') + /* operator-function-id, i.e. operator+(t). */ + d_advance (di, 2); name = d_unqualified_name (di); - if (!name) { - return NULL; - } - if (d_peek_char (di) == 'I') { - return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, - d_template_args (di)); - } else { - return name; - } + if (name == NULL) + return NULL; + if (d_peek_char (di) == 'I') + return d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, + d_template_args (di)); + else + return name; } else if ((peek == 'i' || peek == 't') && d_peek_next_char (di) == 'l') { /* Brace-enclosed initializer list, untyped or typed. */ struct demangle_component *type = NULL; - if (peek == 't') { - type = cplus_demangle_type (di); - } d_advance (di, 2); + if (peek == 't') + type = cplus_demangle_type (di); + if (!d_peek_next_char (di)) + return NULL; return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST, type, d_exprlist (di, 'E')); } @@ -3110,18 +3345,16 @@ d_expression (struct d_info *di) int args; op = d_operator_name (di); - if (!op) { - return NULL; - } + if (op == NULL) + return NULL; if (op->type == DEMANGLE_COMPONENT_OPERATOR) { 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)); - } + if (strcmp (code, "st") == 0) + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, + cplus_demangle_type (di)); } switch (op->type) @@ -3149,49 +3382,51 @@ d_expression (struct d_info *di) 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 (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, 'E'); - } else { - operand = d_expression (di); - } + if (op->type == DEMANGLE_COMPONENT_CAST + && d_check_char (di, '_')) + operand = d_exprlist (di, 'E'); + else if (code && !strcmp (code, "sP")) + operand = d_template_args_1 (di); + else + operand = d_expression_1 (di); - if (suffix) { - /* Indicate the suffix variant for d_print_comp. */ - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - d_make_comp (di, - DEMANGLE_COMPONENT_BINARY_ARGS, - operand, operand)); - } else { - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - operand); - } + 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; - if (op_is_new_cast (op)) { - left = cplus_demangle_type (di); - } else { - left = d_expression (di); - } - if (code && !strcmp (code, "cl")) { - right = d_exprlist (di, 'E'); - } else if (code && (!strcmp (code, "dt") || !strcmp (code, "pt"))) { - right = d_unqualified_name (di); - if (d_peek_char (di) == 'I') { - right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, - right, d_template_args (di)); - } - } else { - right = 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, 'E'); + else if (!strcmp (code, "dt") || !strcmp (code, "pt")) + { + right = d_unqualified_name (di); + if (d_peek_char (di) == 'I') + right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, + right, d_template_args (di)); + } + else + right = d_expression_1 (di); return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op, d_make_comp (di, @@ -3204,19 +3439,31 @@ d_expression (struct d_info *di) struct demangle_component *second; struct demangle_component *third; - if (code && !strcmp (code, "qu")) + if (code == NULL) + return NULL; + else if (!strcmp (code, "qu")) { /* ?: expression. */ - first = d_expression (di); - second = d_expression (di); - third = d_expression (di); + first = d_expression_1 (di); + second = d_expression_1 (di); + third = d_expression_1 (di); + if (third == NULL) + return NULL; } - else if (code && code[0] == 'n') + 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; - } + if (code[1] != 'w' && code[1] != 'a') + return NULL; first = d_exprlist (di, '_'); second = cplus_demangle_type (di); if (d_peek_char (di) == 'E') @@ -3230,22 +3477,23 @@ d_expression (struct d_info *di) /* Parenthesized initializer. */ d_advance (di, 2); third = d_exprlist (di, 'E'); - } else if (d_peek_char (di) == 'i' && d_peek_next_char (di) == 'l') { - /* initializer-list. */ - third = d_expression (di); - } else { - return NULL; } - } else { - return NULL; + else if (d_peek_char (di) == 'i' + && d_peek_next_char (di) == 'l') + /* initializer-list. */ + third = d_expression_1 (di); + 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, third))); + 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, third))); } default: return NULL; @@ -3253,6 +3501,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 @@ -3263,30 +3523,29 @@ d_expr_primary (struct d_info *di) { struct demangle_component *ret; - if (!d_check_char (di, 'L')) { - return NULL; - } + if (! d_check_char (di, 'L')) + return NULL; if (d_peek_char (di) == '_' - /* Workaround for G++ bug; see comment in write_template_arg. */ - || d_peek_char (di) == 'Z') { - ret = cplus_demangle_mangled_name (di, 0); - } else { - struct demangle_component *type; - enum demangle_component_type t; - const char *s; + /* Workaround for G++ bug; see comment in write_template_arg. */ + || d_peek_char (di) == 'Z') + ret = cplus_demangle_mangled_name (di, 0); + else + { + struct demangle_component *type; + enum demangle_component_type t; + const char *s; - type = cplus_demangle_type (di); - if (!type) { - return NULL; - } + type = cplus_demangle_type (di); + if (type == NULL) + return NULL; - /* If we have a type we know how to print, we aren't going to + /* If we have a type we know how to print, we aren't going to print the type name itself. */ - if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE && type->u.s_builtin.type->print != D_PRINT_DEFAULT) { - di->expansion -= type->u.s_builtin.type->len; - } + if (type->type == DEMANGLE_COMPONENT_BUILTIN_TYPE + && type->u.s_builtin.type->print != D_PRINT_DEFAULT) + di->expansion -= type->u.s_builtin.type->len; - /* Rather than try to interpret the literal value, we just + /* 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 format of such literals is machine independent. That's fine, @@ -3297,24 +3556,24 @@ d_expr_primary (struct d_info *di) constant in any readable form anyhow. We don't attempt to handle these cases. */ - t = DEMANGLE_COMPONENT_LITERAL; - if (d_peek_char (di) == 'n') { - t = DEMANGLE_COMPONENT_LITERAL_NEG; - d_advance (di, 1); - } - s = d_str (di); - while (d_peek_char (di) != 'E') { - if (d_peek_char (di) == '\0') { - return NULL; - } - d_advance (di, 1); - } - ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s)); - } - if (!d_check_char (di, 'E')) { + t = DEMANGLE_COMPONENT_LITERAL; + if (d_peek_char (di) == 'n') + { + t = DEMANGLE_COMPONENT_LITERAL_NEG; + d_advance (di, 1); + } + s = d_str (di); + while (d_peek_char (di) != 'E') + { + if (d_peek_char (di) == '\0') return NULL; + d_advance (di, 1); + } + ret = d_make_comp (di, t, type, d_make_name (di, s, d_str (di) - s)); } - return ret; + if (! d_check_char (di, 'E')) + return NULL; + return ret; } /* ::= Z <(function) encoding> E <(entity) name> [] @@ -3326,30 +3585,27 @@ 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; - } + 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; - } + if (! d_check_char (di, 'E')) + return NULL; if (d_peek_char (di) == 's') { 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)); + if (! d_discriminator (di)) + return NULL; + 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') @@ -3357,32 +3613,42 @@ d_local_name (struct d_info *di) /* Default argument scope: d _. */ d_advance (di, 1); num = d_compact_number (di); - if (num < 0) { - return NULL; - } + if (num < 0) + return NULL; } name = d_name (di); - if (name) { - switch (name->type) { - /* Lambdas and unnamed types have internal discriminators. */ - case DEMANGLE_COMPONENT_LAMBDA: - case DEMANGLE_COMPONENT_UNNAMED_TYPE: - break; - default: - if (!d_discriminator (di)) { - return NULL; - } - } - } - if (num >= 0) { - name = d_make_default_arg (di, num, name); - } - return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name); + + 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); } + + /* 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. */ @@ -3390,16 +3656,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; - } + 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 (discrim < 0) + return 0; + if (num_underscores > 1 && discrim >= 10) + { + if (d_peek_char (di) == '_') + d_advance (di, 1); + else + return 0; + } + return 1; } @@ -3412,26 +3690,21 @@ d_lambda (struct d_info *di) struct demangle_component *ret; int num; - if (!d_check_char (di, 'U')) { - return NULL; - } - if (!d_check_char (di, 'l')) { - return NULL; - } + if (! d_check_char (di, 'U')) + return NULL; + if (! d_check_char (di, 'l')) + return NULL; tl = d_parmlist (di); - if (!tl) { - return NULL; - } + if (tl == NULL) + return NULL; - if (!d_check_char (di, 'E')) { - return NULL; - } + if (! d_check_char (di, 'E')) + return NULL; num = d_compact_number (di); - if (num < 0) { - return NULL; - } + if (num < 0) + return NULL; ret = d_make_empty (di); if (ret) @@ -3441,11 +3714,10 @@ d_lambda (struct d_info *di) ret->u.s_unary_num.num = num; } - if (!d_add_substitution (di, ret)) { - return NULL; - } + if (! d_add_substitution (di, ret)) + return NULL; - return ret; + return ret; } /* ::= Ut [ ] _ */ @@ -3454,19 +3726,16 @@ 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; - } - if (!d_check_char (di, 't')) { - return NULL; - } + if (! d_check_char (di, 'U')) + return NULL; + if (! d_check_char (di, 't')) + return NULL; num = d_compact_number (di); - if (num < 0) { - return NULL; - } + if (num < 0) + return NULL; ret = d_make_empty (di); if (ret) @@ -3475,11 +3744,10 @@ d_unnamed_type (struct d_info *di) ret->u.s_number.number = num; } - if (!d_add_substitution (di, ret)) { - return NULL; - } + if (! d_add_substitution (di, ret)) + return NULL; - return ret; + return ret; } /* ::= [ . ] [ . ]* @@ -3495,16 +3763,14 @@ d_clone_suffix (struct d_info *di, struct demangle_component *encoding) if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_')) { pend += 2; - while (IS_LOWER (*pend) || *pend == '_') { - ++pend; - } + while (IS_LOWER (*pend) || *pend == '_') + ++pend; } while (*pend == '.' && IS_DIGIT (pend[1])) { pend += 2; - while (IS_DIGIT (*pend)) { - ++pend; - } + while (IS_DIGIT (*pend)) + ++pend; } d_advance (di, pend - suffix); n = d_make_name (di, suffix, pend - suffix); @@ -3516,15 +3782,13 @@ d_clone_suffix (struct d_info *di, struct demangle_component *encoding) static int d_add_substitution (struct d_info *di, struct demangle_component *dc) { - if (!dc) { - return 0; - } - if (di->next_sub >= di->num_subs) { - return 0; - } - di->subs[di->next_sub] = dc; - ++di->next_sub; - return 1; + if (dc == NULL) + return 0; + if (di->next_sub >= di->num_subs) + return 0; + di->subs[di->next_sub] = dc; + ++di->next_sub; + return 1; } /* ::= S _ @@ -3576,9 +3840,8 @@ d_substitution (struct d_info *di, int prefix) { char c; - if (!d_check_char (di, 'S')) { - return NULL; - } + if (! d_check_char (di, 'S')) + return NULL; c = d_next_char (di); if (c == '_' || IS_DIGIT (c) || IS_UPPER (c)) @@ -3592,16 +3855,14 @@ d_substitution (struct d_info *di, int prefix) { unsigned int new_id; - if (IS_DIGIT (c)) { - new_id = id * 36 + c - '0'; - } else if (IS_UPPER (c)) { - new_id = id * 36 + c - 'A' + 10; - } else { - return NULL; - } - if (new_id < id) { - return NULL; - } + if (IS_DIGIT (c)) + new_id = id * 36 + c - '0'; + else if (IS_UPPER (c)) + new_id = id * 36 + c - 'A' + 10; + else + return NULL; + if (new_id < id) + return NULL; id = new_id; c = d_next_char (di); } @@ -3610,13 +3871,10 @@ d_substitution (struct d_info *di, int prefix) ++id; } - if (id >= (unsigned int)di->next_sub) { - return NULL; - } + if (id >= (unsigned int) di->next_sub) + return NULL; - ++di->did_subs; - - return di->subs[id]; + return di->subs[id]; } else { @@ -3630,9 +3888,8 @@ d_substitution (struct d_info *di, int prefix) char peek; peek = d_peek_char (di); - if (peek == 'C' || peek == 'D') { - verbose = 1; - } + if (peek == 'C' || peek == 'D') + verbose = 1; } pend = (&standard_subs[0] @@ -3643,11 +3900,11 @@ 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, - p->set_last_name_len); - } + if (p->set_last_name != NULL) + di->last_name = d_make_sub (di, p->set_last_name, + p->set_last_name_len); if (verbose) { s = p->full_expansion; @@ -3659,7 +3916,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; } } @@ -3667,6 +3933,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 @@ -3677,9 +3961,8 @@ d_growable_string_init (struct d_growable_string *dgs, size_t estimate) dgs->alc = 0; dgs->allocation_failure = 0; - if (estimate > 0) { - d_growable_string_resize (dgs, estimate); - } + if (estimate > 0) + d_growable_string_resize (dgs, estimate); } /* Grow a growable string to a given size. */ @@ -3690,20 +3973,18 @@ d_growable_string_resize (struct d_growable_string *dgs, size_t need) size_t newalc; char *newbuf; - if (dgs->allocation_failure) { - return; - } + if (dgs->allocation_failure) + return; /* Start allocation at two bytes to avoid any possibility of confusion with the special value of 1 used as a return in *palc to indicate allocation failures. */ newalc = dgs->alc > 0 ? dgs->alc : 2; - while (newalc < need) { - newalc <<= 1; - } + while (newalc < need) + newalc <<= 1; newbuf = (char *) realloc (dgs->buf, newalc); - if (!newbuf) + if (newbuf == NULL) { free (dgs->buf); dgs->buf = NULL; @@ -3725,13 +4006,11 @@ d_growable_string_append_buffer (struct d_growable_string *dgs, size_t need; need = dgs->len + l + 1; - if (need > dgs->alc) { - d_growable_string_resize (dgs, need); - } + if (need > dgs->alc) + d_growable_string_resize (dgs, need); - if (dgs->allocation_failure) { - return; - } + if (dgs->allocation_failure) + return; memcpy (dgs->buf + dgs->len, s, l); dgs->buf[dgs->len + l] = '\0'; @@ -3748,11 +4027,150 @@ 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 (int *num_templates, int *num_scopes, + const struct demangle_component *dc) +{ + if (dc == NULL) + return; + + 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: + (*num_templates)++; + goto recurse_left_right; + + case DEMANGLE_COMPONENT_REFERENCE: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE: + if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM) + (*num_scopes)++; + 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: + d_count_templates_scopes (num_templates, num_scopes, + d_left (dc)); + d_count_templates_scopes (num_templates, num_scopes, + d_right (dc)); + break; + + case DEMANGLE_COMPONENT_CTOR: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_ctor.name); + break; + + case DEMANGLE_COMPONENT_DTOR: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_dtor.name); + break; + + case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_extended_operator.name); + break; + + case DEMANGLE_COMPONENT_FIXED_TYPE: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_fixed.length); + break; + + case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: + case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: + d_count_templates_scopes (num_templates, num_scopes, + d_left (dc)); + break; + + case DEMANGLE_COMPONENT_LAMBDA: + case DEMANGLE_COMPONENT_DEFAULT_ARG: + d_count_templates_scopes (num_templates, num_scopes, + dc->u.s_unary_num.sub); + break; + } +} + /* Initialize a print information structure. */ static void d_print_init (struct d_print_info *dpi, demangle_callbackref callback, - void *opaque) + void *opaque, const struct demangle_component *dc) { dpi->len = 0; dpi->last_char = '\0'; @@ -3765,30 +4183,24 @@ 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; -} -/* Free a print information structure. */ + dpi->copy_templates = NULL; + dpi->next_copy_template = 0; + dpi->num_copy_templates = 0; -static void -d_print_free (struct d_print_info *dpi) -{ - int i; + d_count_templates_scopes (&dpi->num_copy_templates, + &dpi->num_saved_scopes, dc); + dpi->num_copy_templates *= dpi->num_saved_scopes; - for (i = 0; i < dpi->num_saved_scopes; i++) - { - struct d_print_template *ts, *tn; - - for (ts = dpi->saved_scopes[i].templates; ts != NULL; ts = tn) - { - tn = ts->next; - free (ts); - } - } - - free (dpi->saved_scopes); + dpi->current_template = NULL; } /* Indicate that an error occurred during printing, and test for error. */ @@ -3821,12 +4233,11 @@ d_print_flush (struct d_print_info *dpi) static inline void d_append_char (struct d_print_info *dpi, char c) { - if (dpi->len == sizeof (dpi->buf) - 1) { - d_print_flush (dpi); - } + if (dpi->len == sizeof (dpi->buf) - 1) + d_print_flush (dpi); - dpi->buf[dpi->len++] = c; - dpi->last_char = c; + dpi->buf[dpi->len++] = c; + dpi->last_char = c; } static inline void @@ -3834,9 +4245,8 @@ d_append_buffer (struct d_print_info *dpi, const char *s, size_t l) { size_t i; - for (i = 0; i < l; i++) { - d_append_char (dpi, s[i]); - } + for (i = 0; i < l; i++) + d_append_char (dpi, s[i]); } static inline void @@ -3846,10 +4256,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); } @@ -3871,21 +4281,37 @@ 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; - int success; - 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); - success = ! d_print_saw_error (&dpi); - d_print_free (&dpi); - return success; + return ! d_print_saw_error (&dpi); } /* Turn components into a human readable string. OPTIONS is the @@ -3898,7 +4324,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; @@ -3919,30 +4345,31 @@ 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)) { - if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) { - return NULL; - } - if (i <= 0) { - break; - } - --i; - } - if (i != 0 || !a) { - return NULL; + if (a->type != DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + return NULL; + if (i <= 0) + break; + --i; } + if (i != 0 || a == NULL) + return NULL; - return d_left (a); + return d_left (a); } /* Returns the template argument from the current context indicated by DC, @@ -3952,7 +4379,7 @@ static struct demangle_component * d_lookup_template_argument (struct d_print_info *dpi, const struct demangle_component *dc) { - if (!dpi->templates) + if (dpi->templates == NULL) { d_print_error (dpi); return NULL; @@ -3970,17 +4397,15 @@ d_find_pack (struct d_print_info *dpi, const struct demangle_component *dc) { struct demangle_component *a; - if (!dc) { - return NULL; - } + if (dc == NULL) + return NULL; switch (dc->type) { case DEMANGLE_COMPONENT_TEMPLATE_PARAM: a = d_lookup_template_argument (dpi, dc); - if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) { - return a; - } + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + return a; return NULL; case DEMANGLE_COMPONENT_PACK_EXPANSION: @@ -3995,6 +4420,9 @@ d_find_pack (struct d_print_info *dpi, 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: @@ -4006,9 +4434,8 @@ d_find_pack (struct d_print_info *dpi, default: a = d_find_pack (dpi, d_left (dc)); - if (a) { - return a; - } + if (a) + return a; return d_find_pack (dpi, d_right (dc)); } } @@ -4028,45 +4455,81 @@ 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) { - d_append_char (dpi, '('); - } + 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) + d_append_char (dpi, '('); d_print_comp (dpi, options, dc); - if (!simple) { - d_append_char (dpi, ')'); - } + if (!simple) + d_append_char (dpi, ')'); } -/* Return a shallow copy of the current list of templates. - On error d_print_error is called and a partial list may - be returned. Whatever is returned must be freed. */ +/* Save the current scope. */ -static struct d_print_template * -d_copy_templates (struct d_print_info *dpi) +static void +d_save_scope (struct d_print_info *dpi, + const struct demangle_component *container) { - struct d_print_template *src, *result, **link = &result; + 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 = - (struct d_print_template *) malloc (sizeof (struct d_print_template)); + struct d_print_template *dst; - if (!dst) + if (dpi->next_copy_template >= dpi->num_copy_templates) { d_print_error (dpi); - break; + return; } + dst = &dpi->copy_templates[dpi->next_copy_template]; + dpi->next_copy_template++; dst->template_decl = src->template_decl; *link = dst; @@ -4074,19 +4537,97 @@ d_copy_templates (struct d_print_info *dpi) } *link = NULL; +} - return result; +/* 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. */ @@ -4095,23 +4636,22 @@ d_print_comp (struct d_print_info *dpi, int options, /* Nonzero if templates have been stored in the above variable. */ int need_template_restore = 0; - if (!dc) + if (dc == NULL) { d_print_error (dpi); return; } - if (d_print_saw_error (dpi)) { - return; - } + if (d_print_saw_error (dpi)) + return; - switch (dc->type) { + switch (dc->type) + { case DEMANGLE_COMPONENT_NAME: - if ((options & DMGL_JAVA) == 0) { - d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len); - } else { - d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len); - } - return; + if ((options & DMGL_JAVA) == 0) + d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len); + else + 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)); @@ -4123,11 +4663,10 @@ d_print_comp (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: d_print_comp (dpi, options, d_left (dc)); - if ((options & DMGL_JAVA) == 0) { - d_append_string (dpi, "::"); - } else { - d_append_char (dpi, '.'); - } + if ((options & DMGL_JAVA) == 0) + d_append_string (dpi, "::"); + else + d_append_char (dpi, '.'); { struct demangle_component *local_name = d_right (dc); if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) @@ -4171,46 +4710,33 @@ 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 && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS) { - break; - } + if (!is_fnqual_component_type (typed_name->type)) + break; typed_name = d_left (typed_name); } - if (!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; - } - /* 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 - || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || (local_name->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)) + typed_name = d_right (typed_name); + if (typed_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG) + typed_name = typed_name->u.s_unary_num.sub; + if (typed_name == NULL) + { + d_print_error (dpi); + return; + } + while (is_fnqual_component_type (typed_name->type)) { if (i >= sizeof adpm / sizeof adpm[0]) { @@ -4222,20 +4748,28 @@ 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 is a template, then it applies to the + function type as well. */ + if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) + { + dpt.next = dpi->templates; + dpi->templates = &dpt; + dpt.template_decl = typed_name; + } + d_print_comp (dpi, options, d_right (dc)); - if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) { - dpi->templates = dpt.next; - } + if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) + dpi->templates = dpt.next; /* If the modifiers didn't get printed by the type, print them now. */ @@ -4258,6 +4792,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. @@ -4282,53 +4822,64 @@ d_print_comp (struct d_print_info *dpi, int options, else { d_print_comp (dpi, options, dcl); - if (d_last_char (dpi) == '<') { - d_append_char (dpi, ' '); - } + if (d_last_char (dpi) == '<') + d_append_char (dpi, ' '); d_append_char (dpi, '<'); d_print_comp (dpi, options, d_right (dc)); /* Avoid generating two consecutive '>' characters, to avoid the C++ syntactic ambiguity. */ - if (d_last_char (dpi) == '>') { - d_append_char (dpi, ' '); - } + if (d_last_char (dpi) == '>') + d_append_char (dpi, ' '); d_append_char (dpi, '>'); } 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 (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) { - a = d_index_template_argument (a, dpi->pack_index); + 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) - { - d_print_error (dpi); - return; - } + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); - /* 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. */ + if (a == NULL) + { + d_print_error (dpi); + return; + } - hold_dpt = dpi->templates; - dpi->templates = hold_dpt->next; + /* 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. */ - d_print_comp (dpi, options, a); + hold_dpt = dpi->templates; + dpi->templates = hold_dpt->next; - dpi->templates = hold_dpt; + d_print_comp (dpi, options, a); - return; - } + dpi->templates = hold_dpt; + } + 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); @@ -4446,12 +4997,14 @@ d_print_comp (struct d_print_info *dpi, int options, { if (! pdpm->printed) { - if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE && pdpm->mod->type != DEMANGLE_COMPONENT_CONST) { - break; - } - if (pdpm->mod->type == dc->type) { - d_print_comp (dpi, options, d_left (dc)); - return; + if (pdpm->mod->type != DEMANGLE_COMPONENT_RESTRICT + && pdpm->mod->type != DEMANGLE_COMPONENT_VOLATILE + && pdpm->mod->type != DEMANGLE_COMPONENT_CONST) + break; + if (pdpm->mod->type == dc->type) + { + d_print_comp (dpi, options, d_left (dc)); + return; } } } @@ -4462,90 +5015,80 @@ 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 d_saved_scope *scope = d_get_saved_scope (dpi, sub); struct demangle_component *a; - struct d_saved_scope *scope = NULL, *scopes; - int i; - for (i = 0; i < dpi->num_saved_scopes; i++) { - if (dpi->saved_scopes[i].container == sub) { - scope = &dpi->saved_scopes[i]; - } - } - - if (!scope) + if (scope == NULL) { - size_t size; - /* This is the first time SUB has been traversed. We need to capture the current templates so they can be restored if SUB is reentered as a substitution. */ - ++dpi->num_saved_scopes; - size = sizeof (struct d_saved_scope) * dpi->num_saved_scopes; - scopes = (struct d_saved_scope *) realloc (dpi->saved_scopes, - size); - if (!scopes) - { - d_print_error (dpi); - return; - } - - dpi->saved_scopes = scopes; - scope = dpi->saved_scopes + (dpi->num_saved_scopes - 1); - - scope->container = sub; - scope->templates = d_copy_templates (dpi); - if (d_print_saw_error (dpi)) { - return; - } + 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. - Restore the original templates temporarily. */ - saved_templates = dpi->templates; - dpi->templates = scope->templates; - need_template_restore = 1; + 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 && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); - if (!a) + if (a == NULL) { - if (need_template_restore) { - dpi->templates = saved_templates; - } + if (need_template_restore) + dpi->templates = saved_templates; - d_print_error (dpi); - return; + d_print_error (dpi); + return; } sub = a; } - if (sub->type == DEMANGLE_COMPONENT_REFERENCE || sub->type == dc->type) { - dc = sub; - } else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE) { - mod_inner = d_left (sub); - } + if (sub->type == DEMANGLE_COMPONENT_REFERENCE + || sub->type == dc->type) + dc = sub; + else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE) + mod_inner = d_left (sub); } /* Fall through. */ - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: + FNQUAL_COMPONENT_CASE: modifier: { /* We keep a list of modifiers on the stack. */ @@ -4557,36 +5100,32 @@ d_print_comp (struct d_print_info *dpi, int options, dpm.printed = 0; dpm.templates = dpi->templates; - if (!mod_inner) { - mod_inner = d_left (dc); - } + if (!mod_inner) + mod_inner = d_left (dc); d_print_comp (dpi, options, mod_inner); /* If the modifier didn't get printed by the type, print it now. */ - if (!dpm.printed) { - d_print_mod (dpi, options, dc); - } + if (! dpm.printed) + d_print_mod (dpi, options, dc); dpi->modifiers = dpm.next; - if (need_template_restore) { - dpi->templates = saved_templates; - } + if (need_template_restore) + dpi->templates = saved_templates; return; } case DEMANGLE_COMPONENT_BUILTIN_TYPE: - if ((options & DMGL_JAVA) == 0) { - d_append_buffer (dpi, dc->u.s_builtin.type->name, - dc->u.s_builtin.type->len); - } else { - d_append_buffer (dpi, dc->u.s_builtin.type->java_name, - dc->u.s_builtin.type->java_len); - } - return; + if ((options & DMGL_JAVA) == 0) + d_append_buffer (dpi, dc->u.s_builtin.type->name, + dc->u.s_builtin.type->len); + else + d_append_buffer (dpi, dc->u.s_builtin.type->java_name, + dc->u.s_builtin.type->java_len); + return; case DEMANGLE_COMPONENT_VENDOR_TYPE: d_print_comp (dpi, options, d_left (dc)); @@ -4594,50 +5133,47 @@ d_print_comp (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_FUNCTION_TYPE: { - if ((options & DMGL_RET_POSTFIX) != 0) { - d_print_function_type (dpi, - options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), - dc, dpi->modifiers); - } + if ((options & DMGL_RET_POSTFIX) != 0) + d_print_function_type (dpi, + options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), + dc, dpi->modifiers); - /* Print return type if present */ - if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0) { - d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), - d_left (dc)); - } else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0) { - struct d_print_mod dpm; + /* Print return type if present */ + if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0) + d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), + d_left (dc)); + else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0) + { + struct d_print_mod dpm; - /* We must pass this type down as a modifier in order to + /* We must pass this type down as a modifier in order to print it in the right location. */ - dpm.next = dpi->modifiers; - dpi->modifiers = &dpm; - dpm.mod = dc; - dpm.printed = 0; - dpm.templates = dpi->templates; + dpm.next = dpi->modifiers; + dpi->modifiers = &dpm; + dpm.mod = dc; + dpm.printed = 0; + dpm.templates = dpi->templates; - d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), - d_left (dc)); + d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), + d_left (dc)); - dpi->modifiers = dpm.next; + dpi->modifiers = dpm.next; - if (dpm.printed) { - return; - } + if (dpm.printed) + return; - /* In standard prefix notation, there is a space between the + /* In standard prefix notation, there is a space between the return type and the function signature. */ - if ((options & DMGL_RET_POSTFIX) == 0) { - d_append_char (dpi, ' '); - } + if ((options & DMGL_RET_POSTFIX) == 0) + d_append_char (dpi, ' '); } - if ((options & DMGL_RET_POSTFIX) == 0) { - d_print_function_type (dpi, - options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), - dc, dpi->modifiers); - } + if ((options & DMGL_RET_POSTFIX) == 0) + d_print_function_type (dpi, + options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), + dc, dpi->modifiers); - return; + return; } case DEMANGLE_COMPONENT_ARRAY_TYPE: @@ -4692,9 +5228,8 @@ d_print_comp (struct d_print_info *dpi, int options, dpi->modifiers = hold_modifiers; - if (adpm[0].printed) { - return; - } + if (adpm[0].printed) + return; while (i > 1) { @@ -4722,9 +5257,8 @@ d_print_comp (struct d_print_info *dpi, int options, /* If the modifier didn't get printed by the type, print it now. */ - if (!dpm.printed) { - d_print_mod (dpi, options, dc); - } + if (! dpm.printed) + d_print_mod (dpi, options, dc); dpi->modifiers = dpm.next; @@ -4732,43 +5266,41 @@ d_print_comp (struct d_print_info *dpi, int options, } case DEMANGLE_COMPONENT_FIXED_TYPE: - if (dc->u.s_fixed.sat) { - d_append_string (dpi, "_Sat "); - } - /* Don't print "int _Accum". */ - if (dc->u.s_fixed.length->u.s_builtin.type != &cplus_demangle_builtin_types['i' - 'a']) { - d_print_comp (dpi, options, dc->u.s_fixed.length); - d_append_char (dpi, ' '); + if (dc->u.s_fixed.sat) + d_append_string (dpi, "_Sat "); + /* Don't print "int _Accum". */ + if (dc->u.s_fixed.length->u.s_builtin.type + != &cplus_demangle_builtin_types['i'-'a']) + { + d_print_comp (dpi, options, dc->u.s_fixed.length); + d_append_char (dpi, ' '); } - if (dc->u.s_fixed.accum) { - d_append_string (dpi, "_Accum"); - } else { - d_append_string (dpi, "_Fract"); - } - return; + if (dc->u.s_fixed.accum) + d_append_string (dpi, "_Accum"); + else + d_append_string (dpi, "_Fract"); + return; case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: - if (d_left (dc) != NULL) { - d_print_comp (dpi, options, d_left (dc)); - } - if (d_right (dc) != NULL) { - size_t len; - unsigned long int flush_count; - /* Make sure ", " isn't flushed by d_append_string, otherwise + if (d_left (dc) != NULL) + d_print_comp (dpi, options, d_left (dc)); + if (d_right (dc) != NULL) + { + size_t len; + unsigned long int flush_count; + /* Make sure ", " isn't flushed by d_append_string, otherwise dpi->len -= 2 wouldn't work. */ - if (dpi->len >= sizeof (dpi->buf) - 2) { - d_print_flush (dpi); - } - d_append_string (dpi, ", "); - len = dpi->len; - flush_count = dpi->flush_count; - d_print_comp (dpi, options, d_right (dc)); - /* If that didn't print anything (which can happen with empty + if (dpi->len >= sizeof (dpi->buf) - 2) + d_print_flush (dpi); + d_append_string (dpi, ", "); + len = dpi->len; + flush_count = dpi->flush_count; + d_print_comp (dpi, options, d_right (dc)); + /* If that didn't print anything (which can happen with empty template argument packs), remove the comma and space. */ - if (dpi->flush_count == flush_count && dpi->len == len) { - dpi->len -= 2; - } + if (dpi->flush_count == flush_count && dpi->len == len) + dpi->len -= 2; } return; @@ -4777,9 +5309,8 @@ d_print_comp (struct d_print_info *dpi, int options, struct demangle_component *type = d_left (dc); struct demangle_component *list = d_right (dc); - if (type) { - d_print_comp (dpi, options, type); - } + if (type) + d_print_comp (dpi, options, type); d_append_char (dpi, '{'); d_print_comp (dpi, options, list); d_append_char (dpi, '}'); @@ -4793,13 +5324,11 @@ d_print_comp (struct d_print_info *dpi, int options, d_append_string (dpi, "operator"); /* Add a space before new/delete. */ - if (IS_LOWER (op->name[0])) { - d_append_char (dpi, ' '); - } + if (IS_LOWER (op->name[0])) + d_append_char (dpi, ' '); /* Omit a trailing space. */ - if (op->name[len - 1] == ' ') { - --len; - } + if (op->name[len-1] == ' ') + --len; d_append_buffer (dpi, op->name, len); return; } @@ -4809,9 +5338,9 @@ 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: @@ -4831,9 +5360,10 @@ d_print_comp (struct d_print_info *dpi, int options, { /* 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_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) { @@ -4845,25 +5375,41 @@ d_print_comp (struct d_print_info *dpi, int options, } } - 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, ')'); + /* 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; } - if (code && !strcmp (code, "gs")) { - /* Avoid parens after '::'. */ - d_print_comp (dpi, options, operand); - } else if (code && !strcmp (code, "st")) + else if (code && !strcmp (code, "sP")) + { + int len = d_args_length (dpi, operand); + d_append_num (dpi, len); + return; + } + + 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); + d_append_char (dpi, '('); + d_print_comp (dpi, options, operand); + d_append_char (dpi, ')'); } + else + d_print_subexpr (dpi, options, operand); } return; @@ -4885,45 +5431,51 @@ d_print_comp (struct d_print_info *dpi, int options, 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. */ - 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_append_char (dpi, '('); - } + 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_append_char (dpi, '('); - if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0 && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME) { - /* Function call used in an expression should not have printed types + if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0 + && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME) + { + /* Function call used in an expression should not have printed types of the function arguments. Values of the function arguments still get printed below. */ - const struct demangle_component *func = d_left (d_right (dc)); + const struct demangle_component *func = d_left (d_right (dc)); - if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) { - d_print_error (dpi); - } - d_print_subexpr (dpi, options, d_left (func)); - } else { - d_print_subexpr (dpi, options, d_left (d_right (dc))); + if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) + d_print_error (dpi); + d_print_subexpr (dpi, options, d_left (func)); } - if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0) { - d_append_char (dpi, '['); - d_print_comp (dpi, options, d_right (d_right (dc))); - d_append_char (dpi, ']'); + else + d_print_subexpr (dpi, options, d_left (d_right (dc))); + if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0) + { + d_append_char (dpi, '['); + d_print_comp (dpi, options, d_right (d_right (dc))); + d_append_char (dpi, ']'); } else { - if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0) { - d_print_expr_op (dpi, options, d_left (dc)); - } - d_print_subexpr (dpi, options, d_right (d_right (dc))); + if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0) + d_print_expr_op (dpi, options, d_left (dc)); + d_print_subexpr (dpi, options, d_right (d_right (dc))); } - 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_append_char (dpi, ')'); - } + 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_append_char (dpi, ')'); - return; + return; case DEMANGLE_COMPONENT_BINARY_ARGS: /* We should only see this as part of DEMANGLE_COMPONENT_BINARY. */ @@ -4937,6 +5489,8 @@ d_print_comp (struct d_print_info *dpi, int options, d_print_error (dpi); return; } + 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)); @@ -4960,9 +5514,8 @@ d_print_comp (struct d_print_info *dpi, int options, d_append_char (dpi, ' '); } d_print_comp (dpi, options, second); - if (third) { - d_print_subexpr (dpi, options, third); - } + if (third) + d_print_subexpr (dpi, options, third); } } return; @@ -4993,28 +5546,28 @@ d_print_comp (struct d_print_info *dpi, int options, case D_PRINT_UNSIGNED_LONG_LONG: if (d_right (dc)->type == DEMANGLE_COMPONENT_NAME) { - if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) { - d_append_char (dpi, '-'); - } - d_print_comp (dpi, options, d_right (dc)); - switch (tp) { - default: - break; - case D_PRINT_UNSIGNED: - d_append_char (dpi, 'u'); - break; - case D_PRINT_LONG: - d_append_char (dpi, 'l'); - break; - case D_PRINT_UNSIGNED_LONG: - d_append_string (dpi, "ul"); - break; - case D_PRINT_LONG_LONG: - d_append_string (dpi, "ll"); - break; - case D_PRINT_UNSIGNED_LONG_LONG: - d_append_string (dpi, "ull"); - break; + if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) + d_append_char (dpi, '-'); + d_print_comp (dpi, options, d_right (dc)); + switch (tp) + { + default: + break; + case D_PRINT_UNSIGNED: + d_append_char (dpi, 'u'); + break; + case D_PRINT_LONG: + d_append_char (dpi, 'l'); + break; + case D_PRINT_UNSIGNED_LONG: + d_append_string (dpi, "ul"); + break; + case D_PRINT_LONG_LONG: + d_append_string (dpi, "ll"); + break; + case D_PRINT_UNSIGNED_LONG_LONG: + d_append_string (dpi, "ull"); + break; } return; } @@ -5047,16 +5600,13 @@ d_print_comp (struct d_print_info *dpi, int options, d_append_char (dpi, '('); d_print_comp (dpi, options, d_left (dc)); d_append_char (dpi, ')'); - if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) { - d_append_char (dpi, '-'); - } - if (tp == D_PRINT_FLOAT) { - d_append_char (dpi, '['); - } + if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) + d_append_char (dpi, '-'); + if (tp == D_PRINT_FLOAT) + d_append_char (dpi, '['); d_print_comp (dpi, options, d_right (dc)); - if (tp == D_PRINT_FLOAT) { - d_append_char (dpi, ']'); - } + if (tp == D_PRINT_FLOAT) + d_append_char (dpi, ']'); } return; @@ -5089,7 +5639,7 @@ d_print_comp (struct d_print_info *dpi, int options, int len; int i; struct demangle_component *a = d_find_pack (dpi, d_left (dc)); - if (!a) + if (a == NULL) { /* d_find_pack won't find anything if the only packs involved in this expansion are function parameter packs; in that @@ -5105,9 +5655,8 @@ d_print_comp (struct d_print_info *dpi, int options, { dpi->pack_index = i; d_print_comp (dpi, options, dc); - if (i < len - 1) { - d_append_string (dpi, ", "); - } + if (i < len-1) + d_append_string (dpi, ", "); } } return; @@ -5115,12 +5664,13 @@ d_print_comp (struct d_print_info *dpi, int options, case DEMANGLE_COMPONENT_FUNCTION_PARAM: { long num = dc->u.s_number.number; - if (num == 0) { - d_append_string (dpi, "this"); - } else { - d_append_string (dpi, "{parm#"); - d_append_num (dpi, num); - d_append_char (dpi, '}'); + if (num == 0) + d_append_string (dpi, "this"); + else + { + d_append_string (dpi, "{parm#"); + d_append_num (dpi, num); + d_append_char (dpi, '}'); } } return; @@ -5137,7 +5687,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, '}'); @@ -5162,6 +5716,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 @@ -5189,15 +5768,14 @@ d_print_java_identifier (struct d_print_info *dpi, const char *name, int len) { int dig; - if (IS_DIGIT (*q)) { - dig = *q - '0'; - } else if (*q >= 'A' && *q <= 'F') { - dig = *q - 'A' + 10; - } else if (*q >= 'a' && *q <= 'f') { - dig = *q - 'a' + 10; - } else { - break; - } + if (IS_DIGIT (*q)) + dig = *q - '0'; + else if (*q >= 'A' && *q <= 'F') + dig = *q - 'A' + 10; + else if (*q >= 'a' && *q <= 'f') + dig = *q - 'a' + 10; + else + break; c = c * 16 + dig; } @@ -5224,18 +5802,12 @@ d_print_mod_list (struct d_print_info *dpi, int options, { struct d_print_template *hold_dpt; - if (!mods || d_print_saw_error (dpi)) { - return; - } + if (mods == NULL || d_print_saw_error (dpi)) + return; if (mods->printed || (! suffix - && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS - || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS - || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS - || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS - || (mods->mod->type - == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)))) + && (is_fnqual_component_type (mods->mod->type)))) { d_print_mod_list (dpi, options, mods->next, suffix); return; @@ -5273,11 +5845,10 @@ d_print_mod_list (struct d_print_info *dpi, int options, d_print_comp (dpi, options, d_left (mods->mod)); dpi->modifiers = hold_modifiers; - if ((options & DMGL_JAVA) == 0) { - d_append_string (dpi, "::"); - } else { - d_append_char (dpi, '.'); - } + if ((options & DMGL_JAVA) == 0) + d_append_string (dpi, "::"); + else + d_append_char (dpi, '.'); dc = d_right (mods->mod); @@ -5289,14 +5860,13 @@ d_print_mod_list (struct d_print_info *dpi, int options, dc = dc->u.s_unary_num.sub; } - while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS || dc->type == DEMANGLE_COMPONENT_CONST_THIS || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS) { - dc = d_left (dc); - } + while (is_fnqual_component_type (dc->type)) + dc = d_left (dc); - d_print_comp (dpi, options, dc); + d_print_comp (dpi, options, dc); - dpi->templates = hold_dpt; - return; + dpi->templates = hold_dpt; + return; } d_print_mod (dpi, options, mods->mod); @@ -5310,7 +5880,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) { @@ -5326,24 +5896,46 @@ 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)); return; case DEMANGLE_COMPONENT_POINTER: /* There is no pointer symbol in Java. */ - if ((options & DMGL_JAVA) == 0) { - d_append_char (dpi, '*'); - } + 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; @@ -5354,12 +5946,11 @@ d_print_mod (struct d_print_info *dpi, int options, d_append_string (dpi, "imaginary "); return; case DEMANGLE_COMPONENT_PTRMEM_TYPE: - if (d_last_char (dpi) != '(') { - d_append_char (dpi, ' '); - } - d_print_comp (dpi, options, d_left (mod)); - d_append_string (dpi, "::*"); - return; + if (d_last_char (dpi) != '(') + d_append_char (dpi, ' '); + d_print_comp (dpi, options, d_left (mod)); + d_append_string (dpi, "::*"); + return; case DEMANGLE_COMPONENT_TYPED_NAME: d_print_comp (dpi, options, d_left (mod)); return; @@ -5381,7 +5972,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; @@ -5393,52 +5984,46 @@ d_print_function_type (struct d_print_info *dpi, int options, need_space = 0; for (p = mods; p != NULL; p = p->next) { - if (p->printed) { - break; - } + if (p->printed) + break; - switch (p->mod->type) { - case DEMANGLE_COMPONENT_POINTER: - case DEMANGLE_COMPONENT_REFERENCE: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE: - need_paren = 1; - break; - case DEMANGLE_COMPONENT_RESTRICT: - case DEMANGLE_COMPONENT_VOLATILE: - case DEMANGLE_COMPONENT_CONST: - case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: - case DEMANGLE_COMPONENT_COMPLEX: - case DEMANGLE_COMPONENT_IMAGINARY: - case DEMANGLE_COMPONENT_PTRMEM_TYPE: - need_space = 1; - need_paren = 1; - break; - case DEMANGLE_COMPONENT_RESTRICT_THIS: - case DEMANGLE_COMPONENT_VOLATILE_THIS: - case DEMANGLE_COMPONENT_CONST_THIS: - case DEMANGLE_COMPONENT_REFERENCE_THIS: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: - break; - default: - break; - } - if (need_paren) { - break; + switch (p->mod->type) + { + case DEMANGLE_COMPONENT_POINTER: + case DEMANGLE_COMPONENT_REFERENCE: + case DEMANGLE_COMPONENT_RVALUE_REFERENCE: + need_paren = 1; + break; + case DEMANGLE_COMPONENT_RESTRICT: + case DEMANGLE_COMPONENT_VOLATILE: + case DEMANGLE_COMPONENT_CONST: + case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: + case DEMANGLE_COMPONENT_COMPLEX: + case DEMANGLE_COMPONENT_IMAGINARY: + case DEMANGLE_COMPONENT_PTRMEM_TYPE: + need_space = 1; + need_paren = 1; + break; + FNQUAL_COMPONENT_CASE: + break; + default: + break; } + if (need_paren) + break; } if (need_paren) { if (! need_space) { - if (d_last_char (dpi) != '(' && d_last_char (dpi) != '*') { - need_space = 1; - } + if (d_last_char (dpi) != '(' + && d_last_char (dpi) != '*') + need_space = 1; } - if (need_space && d_last_char (dpi) != ' ') { - d_append_char (dpi, ' '); - } - d_append_char (dpi, '('); + if (need_space && d_last_char (dpi) != ' ') + d_append_char (dpi, ' '); + d_append_char (dpi, '('); } hold_modifiers = dpi->modifiers; @@ -5446,15 +6031,13 @@ d_print_function_type (struct d_print_info *dpi, int options, d_print_mod_list (dpi, options, mods, 0); - if (need_paren) { - d_append_char (dpi, ')'); - } + if (need_paren) + d_append_char (dpi, ')'); d_append_char (dpi, '('); - if (d_right (dc) != NULL) { - d_print_comp (dpi, options, d_right (dc)); - } + if (d_right (dc) != NULL) + d_print_comp (dpi, options, d_right (dc)); d_append_char (dpi, ')'); @@ -5467,7 +6050,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; @@ -5497,85 +6080,90 @@ d_print_array_type (struct d_print_info *dpi, int options, } } - if (need_paren) { - d_append_string (dpi, " ("); - } + if (need_paren) + d_append_string (dpi, " ("); - d_print_mod_list (dpi, options, mods, 0); + d_print_mod_list (dpi, options, mods, 0); - if (need_paren) { - d_append_char (dpi, ')'); - } + if (need_paren) + d_append_char (dpi, ')'); } - if (need_space) { - d_append_char (dpi, ' '); - } + if (need_space) + d_append_char (dpi, ' '); - d_append_char (dpi, '['); + d_append_char (dpi, '['); - if (d_left (dc) != NULL) { - d_print_comp (dpi, options, d_left (dc)); - } + if (d_left (dc) != NULL) + d_print_comp (dpi, options, d_left (dc)); - d_append_char (dpi, ']'); + d_append_char (dpi, ']'); } /* Print an operator in an expression. */ 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, - dc->u.s_operator.op->len); - } else { - d_print_comp (dpi, options, dc); - } + if (dc->type == DEMANGLE_COMPONENT_OPERATOR) + d_append_buffer (dpi, dc->u.s_operator.op->name, + dc->u.s_operator.op->len); + else + d_print_comp (dpi, options, dc); } /* Print a cast. */ 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; - dpt.next = dpi->templates; - dpi->templates = &dpt; - dpt.template_decl = d_left (dc); + /* 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 = dpi->current_template; + } - d_print_comp (dpi, options, d_left (d_left (dc))); + 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, ' '); - } - d_append_char (dpi, '<'); - d_print_comp (dpi, options, d_right (d_left (dc))); - /* Avoid generating two consecutive '>' characters, to avoid + if (d_last_char (dpi) == '<') + d_append_char (dpi, ' '); + d_append_char (dpi, '<'); + d_print_comp (dpi, options, d_right (d_left (dc))); + /* Avoid generating two consecutive '>' characters, to avoid the C++ syntactic ambiguity. */ - if (d_last_char (dpi) == '>') { - d_append_char (dpi, ' '); - } - d_append_char (dpi, '>'); - - dpi->modifiers = hold_dpm; + if (d_last_char (dpi) == '>') + d_append_char (dpi, ' '); + d_append_char (dpi, '>'); } } @@ -5603,11 +6191,12 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len, 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; } /* Internal implementation for the demangler. If MANGLED is a g++ v3 ABI @@ -5631,15 +6220,18 @@ d_demangle_callback (const char *mangled, int options, struct demangle_component *dc; int status; - if (mangled[0] == '_' && mangled[1] == 'Z') { - type = DCT_MANGLED; - } else if (strncmp (mangled, "_GLOBAL_", 8) == 0 && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') && (mangled[9] == 'D' || mangled[9] == 'I') && mangled[10] == '_') { - type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS; - } else { - if ((options & DMGL_TYPES) == 0) { - return 0; - } - type = DCT_TYPE; + if (mangled[0] == '_' && mangled[1] == 'Z') + type = DCT_MANGLED; + else if (strncmp (mangled, "_GLOBAL_", 8) == 0 + && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') + && (mangled[9] == 'D' || mangled[9] == 'I') + && mangled[10] == '_') + type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS; + else + { + if ((options & DMGL_TYPES) == 0) + return 0; + type = DCT_TYPE; } cplus_demangle_init_info (mangled, options, strlen (mangled), &di); @@ -5651,14 +6243,9 @@ d_demangle_callback (const char *mangled, int options, di.comps = comps; di.subs = subs; -#else -#ifdef _MSC_VER - di.comps = calloc (di.num_comps * sizeof (*di.comps),1); - di.subs = calloc (di.num_subs * sizeof (*di.subs),1); #else di.comps = alloca (di.num_comps * sizeof (*di.comps)); di.subs = alloca (di.num_subs * sizeof (*di.subs)); -#endif #endif switch (type) @@ -5680,15 +6267,16 @@ 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 mangled string, then we didn't successfully demangle it. If DMGL_PARAMS is not set, we didn't look at the trailing parameters. */ - if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') { - dc = NULL; - } + if (((options & DMGL_PARAMS) != 0) && d_peek_char (&di) != '\0') + dc = NULL; #ifdef CP_DEMANGLE_DEBUG d_dump (dc, 0); @@ -5767,14 +6355,14 @@ __cxa_demangle (const char *mangled_name, char *output_buffer, char *demangled; size_t alc; - if (!mangled_name) + if (mangled_name == NULL) { if (status != NULL) *status = -3; return NULL; } - if (output_buffer != NULL && !length) + if (output_buffer != NULL && length == NULL) { if (status != NULL) *status = -3; @@ -5783,7 +6371,7 @@ __cxa_demangle (const char *mangled_name, char *output_buffer, demangled = d_demangle (mangled_name, DMGL_PARAMS | DMGL_TYPES, &alc); - if (!demangled) + if (demangled == NULL) { if (status != NULL) { @@ -5795,7 +6383,7 @@ __cxa_demangle (const char *mangled_name, char *output_buffer, return NULL; } - if (!output_buffer) + if (output_buffer == NULL) { if (length != NULL) *length = alc; @@ -5852,7 +6440,7 @@ __gcclibcxx_demangle_callback (const char *mangled_name, { int status; - if (!mangled_name || !callback) + if (mangled_name == NULL || callback == NULL) return -3; status = d_demangle_callback (mangled_name, DMGL_PARAMS | DMGL_TYPES, @@ -5937,13 +6525,8 @@ is_ctor_or_dtor (const char *mangled, di.comps = comps; di.subs = subs; #else -#ifdef _MSC_VER - di.comps = calloc (di.num_comps * sizeof (*di.comps), 1); - di.subs = calloc (di.num_subs * sizeof (*di.subs), 1); -#else - di.comps = alloca (di.num_comps * sizeof (*di.comps)); - di.subs = alloca (di.num_subs * sizeof (*di.subs)); -#endif + di.comps = alloca (di.num_comps * sizeof (*di.comps)); + di.subs = alloca (di.num_subs * sizeof (*di.subs)); #endif dc = cplus_demangle_mangled_name (&di, 1); @@ -5999,9 +6582,8 @@ is_gnu_v3_mangled_ctor (const char *name) enum gnu_v3_ctor_kinds ctor_kind; enum gnu_v3_dtor_kinds dtor_kind; - if (!is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) { - return (enum gnu_v3_ctor_kinds)0; - } + if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) + return (enum gnu_v3_ctor_kinds) 0; return ctor_kind; } @@ -6015,9 +6597,8 @@ is_gnu_v3_mangled_dtor (const char *name) enum gnu_v3_ctor_kinds ctor_kind; enum gnu_v3_dtor_kinds dtor_kind; - if (!is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) { - return (enum gnu_v3_dtor_kinds)0; - } + if (! is_ctor_or_dtor (name, &ctor_kind, &dtor_kind)) + return (enum gnu_v3_dtor_kinds) 0; return dtor_kind; } @@ -6198,14 +6779,3 @@ main (int argc, char *argv[]) } #endif /* STANDALONE_DEMANGLER */ - -#if MY_EMSCRIPTEN -#include -EMSCRIPTEN_KEEPALIVE -char *cxx(const char *sym_bol) { - const char *symbol = "_Z29api_internal_launch_ipykernelP7_objectS0_S0_"; - // int options = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES; - int options = DMGL_NO_OPTS | DMGL_PARAMS; - return cplus_demangle_v3 (symbol, options); -} -#endif diff --git a/libr/bin/mangling/cxx/cp-demangle.h b/libr/bin/mangling/cxx/cp-demangle.h index ae635beb4c..51b8a243e0 100644 --- a/libr/bin/mangling/cxx/cp-demangle.h +++ b/libr/bin/mangling/cxx/cp-demangle.h @@ -1,6 +1,5 @@ /* Internal demangler interface for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 - Free Software Foundation, Inc. + Copyright (C) 2003-2018 Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. @@ -112,16 +111,17 @@ struct d_info int next_sub; /* The number of available entries in the subs array. */ int num_subs; - /* The number of substitutions which we actually made from the subs - array, plus the number of template parameter references we - saw. */ - int did_subs; /* The last name we saw, for constructors and destructors. */ struct demangle_component *last_name; /* A running total of the length of large expansions from the mangled name to the demangled name, such as standard substitutions and builtin types. */ int expansion; + /* Non-zero if we are parsing an expression. */ + int is_expression; + /* Non-zero if we are parsing the type operand of a conversion + operator, but not when in an expression. */ + int is_conversion; }; /* To avoid running past the ending '\0', don't: @@ -130,12 +130,37 @@ struct d_info - call d_check_char(di, '\0') Everything else is safe. */ #define d_peek_char(di) (*((di)->n)) -#define d_peek_next_char(di) ((di)->n[1]) -#define d_advance(di, i) ((di)->n += (i)) +#ifndef CHECK_DEMANGLER +# define d_peek_next_char(di) ((di)->n[1]) +# define d_advance(di, i) ((di)->n += (i)) +#endif #define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0) #define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++)) #define d_str(di) ((di)->n) +#ifdef CHECK_DEMANGLER +static inline char +d_peek_next_char (const struct d_info *di) +{ + if (!di->n[0]) + abort (); + return di->n[1]; +} + +static inline void +d_advance (struct d_info *di, int i) +{ + if (i < 0) + abort (); + while (i--) + { + if (!di->n[0]) + abort (); + di->n++; + } +} +#endif + /* Functions and arrays in cp-demangle.c which are referenced by functions in cp-demint.c. */ #ifdef IN_GLIBCPP_V3 diff --git a/libr/bin/mangling/cxx/demangle.h b/libr/bin/mangling/cxx/demangle.h index 58bf547d54..4f920f2b7f 100644 --- a/libr/bin/mangling/cxx/demangle.h +++ b/libr/bin/mangling/cxx/demangle.h @@ -1,7 +1,6 @@ /* Defs for interface to demanglers. - Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, - 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. - + Copyright (C) 1992-2018 Free Software Foundation, Inc. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2, or @@ -63,9 +62,11 @@ extern "C" { #define DMGL_EDG (1 << 13) #define DMGL_GNU_V3 (1 << 14) #define DMGL_GNAT (1 << 15) +#define DMGL_DLANG (1 << 16) +#define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */ /* If none of these are set, use 'current_demangling_style' as the default. */ -#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT) +#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST) /* Enumeration of possible demangling styles. @@ -87,7 +88,9 @@ extern enum demangling_styles edg_demangling = DMGL_EDG, gnu_v3_demangling = DMGL_GNU_V3, java_demangling = DMGL_JAVA, - gnat_demangling = DMGL_GNAT + gnat_demangling = DMGL_GNAT, + dlang_demangling = DMGL_DLANG, + rust_demangling = DMGL_RUST } current_demangling_style; /* Define string names for the various demangling styles. */ @@ -102,6 +105,8 @@ extern enum demangling_styles #define GNU_V3_DEMANGLING_STYLE_STRING "gnu-v3" #define JAVA_DEMANGLING_STYLE_STRING "java" #define GNAT_DEMANGLING_STYLE_STRING "gnat" +#define DLANG_DEMANGLING_STYLE_STRING "dlang" +#define RUST_DEMANGLING_STYLE_STRING "rust" /* Some macros to test what demangling style is active. */ @@ -115,6 +120,8 @@ extern enum demangling_styles #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3) #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA) #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT) +#define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG) +#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST) /* Provide information about the available demangle styles. This code is pulled from gdb into libiberty because it is useful to binutils also. */ @@ -140,10 +147,10 @@ cplus_mangle_opname (const char *opname, int options); extern void set_cplus_marker_for_demangling (int ch); -extern enum demangling_styles +extern enum demangling_styles cplus_demangle_set_style (enum demangling_styles style); -extern enum demangling_styles +extern enum demangling_styles cplus_demangle_name_to_style (const char *name); /* Callback typedef for allocation-less demangler interfaces. */ @@ -169,10 +176,38 @@ java_demangle_v3 (const char *mangled); char * ada_demangle (const char *mangled, int options); +extern char * +dlang_demangle (const char *mangled, int options); + +/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must + already have been demangled through cplus_demangle_v3. If this function + returns non-zero then MANGLED can be demangled (in-place) using + RUST_DEMANGLE_SYM. */ +extern int +rust_is_mangled (const char *mangled); + +/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM. + If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might + replace characters that cannot be demangled with '?' and might truncate + SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never + larger. */ +extern void +rust_demangle_sym (char *sym); + +/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise + returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and + RUST_DEMANGLE_SYM. Returns a new string that is owned by the caller. */ +extern char * +rust_demangle (const char *mangled, int options); + enum gnu_v3_ctor_kinds { gnu_v3_complete_object_ctor = 1, gnu_v3_base_object_ctor, gnu_v3_complete_object_allocating_ctor, + /* These are not part of the V3 ABI. Unified constructors are generated + as a speed-for-space optimization when the -fdeclone-ctor-dtor option + is used, and are always internal symbols. */ + gnu_v3_unified_ctor, gnu_v3_object_ctor_group }; @@ -188,6 +223,10 @@ enum gnu_v3_dtor_kinds { gnu_v3_deleting_dtor = 1, gnu_v3_complete_object_dtor, gnu_v3_base_object_dtor, + /* These are not part of the V3 ABI. Unified destructors are generated + as a speed-for-space optimization when the -fdeclone-ctor-dtor option + is used, and are always internal symbols. */ + gnu_v3_unified_dtor, gnu_v3_object_dtor_group }; @@ -353,6 +392,9 @@ enum demangle_component_type template argument, and the right subtree is either NULL or another TEMPLATE_ARGLIST node. */ DEMANGLE_COMPONENT_TEMPLATE_ARGLIST, + /* A template parameter object (C++20). The left subtree is the + corresponding template argument. */ + DEMANGLE_COMPONENT_TPARM_OBJ, /* An initializer list. The left subtree is either an explicit type or NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST. */ DEMANGLE_COMPONENT_INITIALIZER_LIST, @@ -365,6 +407,10 @@ enum demangle_component_type /* A typecast, represented as a unary operator. The one subtree is the type to which the argument should be cast. */ DEMANGLE_COMPONENT_CAST, + /* A conversion operator, represented as a unary operator. The one + subtree is the type to which the argument should be converted + to. */ + DEMANGLE_COMPONENT_CONVERSION, /* A nullary expression. The left subtree is the operator. */ DEMANGLE_COMPONENT_NULLARY, /* A unary expression. The left subtree is the operator, and the @@ -428,8 +474,12 @@ enum demangle_component_type DEMANGLE_COMPONENT_PACK_EXPANSION, /* A name with an ABI tag. */ DEMANGLE_COMPONENT_TAGGED_NAME, + /* A transaction-safe function type. */ + DEMANGLE_COMPONENT_TRANSACTION_SAFE, /* A cloned function. */ - DEMANGLE_COMPONENT_CLONE + DEMANGLE_COMPONENT_CLONE, + DEMANGLE_COMPONENT_NOEXCEPT, + DEMANGLE_COMPONENT_THROW_SPEC }; /* Types which are only used internally. */ @@ -447,6 +497,11 @@ struct demangle_component /* The type of this component. */ enum demangle_component_type type; + /* Guard against recursive component printing. + Initialize to zero. Private to d_print_comp. + All other fields are final after initialization. */ + int d_printing; + union { /* For DEMANGLE_COMPONENT_NAME. */ @@ -641,7 +696,7 @@ cplus_demangle_v3_components (const char *mangled, int options, void **mem); extern char * cplus_demangle_print (int options, - const struct demangle_component *tree, + struct demangle_component *tree, int estimated_length, size_t *p_allocated_size); @@ -661,7 +716,7 @@ cplus_demangle_print (int options, extern int cplus_demangle_print_callback (int options, - const struct demangle_component *tree, + struct demangle_component *tree, demangle_callbackref callback, void *opaque); #ifdef __cplusplus