From: Florian Krohm Date: Sat, 10 Dec 2011 16:00:25 +0000 (+0000) Subject: Update the C++ demangler by importing files from GCC trunk @ r181975. X-Git-Tag: svn/VALGRIND_3_8_0~572 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=34d5fb61d7897cd14d2752a5c51596d98a61508e;p=thirdparty%2Fvalgrind.git Update the C++ demangler by importing files from GCC trunk @ r181975. Also fixes #283413 git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12281 --- diff --git a/NEWS b/NEWS index 9681e93291..5b3ee433a9 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,14 @@ Release 3.7.1 (????) ~~~~~~~~~~~~~~~~~~~~ +* ================== PLATFORM CHANGES ================= + +* ==================== TOOL CHANGES ==================== + +* ==================== OTHER CHANGES ==================== + +* The C++ demangler has been updated so as to work well with C++ + compiled by even the most recent g++'s. * ==================== FIXED BUGS ==================== @@ -16,6 +24,7 @@ https://bugs.kde.org/show_bug.cgi?id=XXXXXX where XXXXXX is the bug number as listed below. 286374 Running cachegrind with --branch-sim=yes on 64-bit PowerPC program fails +283413 Fix wrong sanity check diff --git a/coregrind/m_demangle/ansidecl.h b/coregrind/m_demangle/ansidecl.h index c19955a98a..23d85bf0e1 100644 --- a/coregrind/m_demangle/ansidecl.h +++ b/coregrind/m_demangle/ansidecl.h @@ -1,5 +1,6 @@ /* ANSI and traditional C compatability macros - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, + 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -114,6 +115,10 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. #ifndef _ANSIDECL_H #define _ANSIDECL_H 1 +#ifdef __cplusplus +extern "C" { +#endif + /* Every source file includes this file, so they will all get the switch for lint. */ /* LINTLIBRARY */ @@ -136,7 +141,7 @@ So instead we use the macro below and test it against specific values. */ #define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) #endif /* GCC_VERSION */ -#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) || (defined(__alpha) && defined(__cplusplus)) +#if defined (__STDC__) || defined(__cplusplus) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32) /* All known AIX compilers implement these things (but don't always define __STDC__). The RISC/OS MIPS compiler defines these things in SVR4 mode, but does not define __STDC__. */ @@ -173,7 +178,7 @@ So instead we use the macro below and test it against specific values. */ /* inline requires special treatment; it's in C99, and GCC >=2.7 supports it too, but it's not in C89. */ #undef inline -#if __STDC_VERSION__ > 199901L +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__)) /* it's a keyword */ #else # if GCC_VERSION >= 2007 @@ -256,14 +261,23 @@ So instead we use the macro below and test it against specific values. */ # endif /* GNUC >= 2.96 */ #endif /* ATTRIBUTE_MALLOC */ -/* Attributes on labels were valid as of gcc 2.93. */ +/* Attributes on labels were valid as of gcc 2.93 and g++ 4.5. For + g++ an attribute on a label must be followed by a semicolon. */ #ifndef ATTRIBUTE_UNUSED_LABEL -# if (!defined (__cplusplus) && GCC_VERSION >= 2093) -# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED +# ifndef __cplusplus +# if GCC_VERSION >= 2093 +# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED +# else +# define ATTRIBUTE_UNUSED_LABEL +# endif # else -# define ATTRIBUTE_UNUSED_LABEL -# endif /* !__cplusplus && GNUC >= 2.93 */ -#endif /* ATTRIBUTE_UNUSED_LABEL */ +# if GCC_VERSION >= 4005 +# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED ; +# else +# define ATTRIBUTE_UNUSED_LABEL +# endif +# endif +#endif #ifndef ATTRIBUTE_UNUSED #define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) @@ -390,4 +404,31 @@ So instead we use the macro below and test it against specific values. */ #define __extension__ #endif +/* This is used to declare a const variable which should be visible + outside of the current compilation unit. Use it as + EXPORTED_CONST int i = 1; + This is because the semantics of const are different in C and C++. + "extern const" is permitted in C but it looks strange, and gcc + warns about it when -Wc++-compat is not used. */ +#ifdef __cplusplus +#define EXPORTED_CONST extern const +#else +#define EXPORTED_CONST const +#endif + +/* Be conservative and only use enum bitfields with C++ or GCC. + FIXME: provide a complete autoconf test for buggy enum bitfields. */ + +#ifdef __cplusplus +#define ENUM_BITFIELD(TYPE) enum TYPE +#elif (GCC_VERSION > 2000) +#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE +#else +#define ENUM_BITFIELD(TYPE) unsigned int +#endif + +#ifdef __cplusplus +} +#endif + #endif /* ansidecl.h */ diff --git a/coregrind/m_demangle/cp-demangle.c b/coregrind/m_demangle/cp-demangle.c index 00aba99d6f..98d374609c 100644 --- a/coregrind/m_demangle/cp-demangle.c +++ b/coregrind/m_demangle/cp-demangle.c @@ -1,5 +1,5 @@ /* Demangler for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Written by Ian Lance Taylor . @@ -293,8 +293,6 @@ struct d_growable_string enum { D_PRINT_BUFFER_LENGTH = 256 }; struct d_print_info { - /* The options passed to the demangler. */ - int options; /* Fixed-length allocated buffer for demangled data, flushed to the callback with a NUL termination once full. */ char buf[D_PRINT_BUFFER_LENGTH]; @@ -317,6 +315,8 @@ struct d_print_info /* The current index into any template argument packs we are using for printing. */ int pack_index; + /* Number of d_print_flush calls so far. */ + unsigned long int flush_count; }; #ifdef CP_DEMANGLE_DEBUG @@ -334,6 +334,9 @@ d_make_comp (struct d_info *, enum demangle_component_type, static struct demangle_component * d_make_name (struct d_info *, const char *, int); +static struct demangle_component * +d_make_demangle_mangled_name (struct d_info *, const char *); + static struct demangle_component * d_make_builtin_type (struct d_info *, const struct demangle_builtin_type_info *); @@ -404,6 +407,8 @@ d_class_enum_type (struct d_info *); static struct demangle_component *d_array_type (struct d_info *); +static struct demangle_component *d_vector_type (struct d_info *); + static struct demangle_component * d_pointer_to_member_type (struct d_info *); @@ -423,6 +428,13 @@ static struct demangle_component *d_local_name (struct d_info *); static int d_discriminator (struct d_info *); +static struct demangle_component *d_lambda (struct d_info *); + +static struct demangle_component *d_unnamed_type (struct d_info *); + +static struct demangle_component * +d_clone_suffix (struct d_info *, struct demangle_component *); + static int d_add_substitution (struct d_info *, struct demangle_component *); @@ -440,7 +452,7 @@ static void d_growable_string_callback_adapter (const char *, size_t, void *); static void -d_print_init (struct d_print_info *, int, demangle_callbackref, void *); +d_print_init (struct d_print_info *, demangle_callbackref, void *); static inline void d_print_error (struct d_print_info *); @@ -458,32 +470,32 @@ 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 *, const struct demangle_component *); +d_print_comp (struct d_print_info *, int, const struct demangle_component *); static void d_print_java_identifier (struct d_print_info *, const char *, int); static void -d_print_mod_list (struct d_print_info *, struct d_print_mod *, int); +d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int); static void -d_print_mod (struct d_print_info *, const struct demangle_component *); +d_print_mod (struct d_print_info *, int, const struct demangle_component *); static void -d_print_function_type (struct d_print_info *, +d_print_function_type (struct d_print_info *, int, const struct demangle_component *, struct d_print_mod *); static void -d_print_array_type (struct d_print_info *, +d_print_array_type (struct d_print_info *, int, const struct demangle_component *, struct d_print_mod *); static void -d_print_expr_op (struct d_print_info *, const struct demangle_component *); +d_print_expr_op (struct d_print_info *, int, const struct demangle_component *); static void -d_print_cast (struct d_print_info *, const struct demangle_component *); +d_print_cast (struct d_print_info *, int, const struct demangle_component *); static int d_demangle_callback (const char *, int, demangle_callbackref, void *); @@ -588,6 +600,12 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_HIDDEN_ALIAS: printf ("hidden alias\n"); break; + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + printf ("transaction clone\n"); + break; + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + printf ("non-transaction clone\n"); + break; case DEMANGLE_COMPONENT_RESTRICT: printf ("restrict\n"); break; @@ -636,6 +654,9 @@ d_dump (struct demangle_component *dc, int indent) case DEMANGLE_COMPONENT_PTRMEM_TYPE: printf ("pointer to member type\n"); break; + case DEMANGLE_COMPONENT_FIXED_TYPE: + printf ("fixed-point type\n"); + break; case DEMANGLE_COMPONENT_ARGLIST: printf ("argument list\n"); break; @@ -731,8 +752,8 @@ cplus_demangle_fill_ctor (struct demangle_component *p, { if (p == NULL || name == NULL - || (kind < gnu_v3_complete_object_ctor - && kind > gnu_v3_complete_object_allocating_ctor)) + || (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; @@ -750,8 +771,8 @@ cplus_demangle_fill_dtor (struct demangle_component *p, { if (p == NULL || name == NULL - || (kind < gnu_v3_deleting_dtor - && kind > gnu_v3_base_object_dtor)) + || (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; @@ -804,6 +825,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_LITERAL: case DEMANGLE_COMPONENT_LITERAL_NEG: case DEMANGLE_COMPONENT_COMPOUND_NAME: + case DEMANGLE_COMPONENT_VECTOR_TYPE: + case DEMANGLE_COMPONENT_CLONE: if (left == NULL || right == NULL) return NULL; break; @@ -821,6 +844,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_GUARD: case DEMANGLE_COMPONENT_REFTEMP: case DEMANGLE_COMPONENT_HIDDEN_ALIAS: + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: case DEMANGLE_COMPONENT_POINTER: case DEMANGLE_COMPONENT_REFERENCE: case DEMANGLE_COMPONENT_RVALUE_REFERENCE: @@ -831,6 +856,8 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, case DEMANGLE_COMPONENT_JAVA_RESOURCE: case DEMANGLE_COMPONENT_DECLTYPE: case DEMANGLE_COMPONENT_PACK_EXPANSION: + case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: + case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: if (left == NULL) return NULL; break; @@ -870,6 +897,17 @@ d_make_comp (struct d_info *di, enum demangle_component_type type, return p; } +/* Add a new demangle mangled name component. */ + +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); +} + /* Add a new name component. */ static struct demangle_component * @@ -932,6 +970,20 @@ d_make_extended_operator (struct d_info *di, int args, return p; } +static struct demangle_component * +d_make_default_arg (struct d_info *di, int num, + struct demangle_component *sub) +{ + struct demangle_component *p = d_make_empty (di); + if (p) + { + p->type = DEMANGLE_COMPONENT_DEFAULT_ARG; + p->u.s_unary_num.num = num; + p->u.s_unary_num.sub = sub; + } + return p; +} + /* Add a new constructor component. */ static struct demangle_component * @@ -976,6 +1028,22 @@ d_make_template_param (struct d_info *di, long i) return p; } +/* Add a new function parameter. */ + +static struct demangle_component * +d_make_function_param (struct d_info *di, long i) +{ + struct demangle_component *p; + + p = d_make_empty (di); + if (p != NULL) + { + p->type = DEMANGLE_COMPONENT_FUNCTION_PARAM; + p->u.s_number.number = i; + } + return p; +} + /* Add a new standard substitution component. */ static struct demangle_component * @@ -993,7 +1061,7 @@ d_make_sub (struct d_info *di, const char *name, int len) return p; } -/* ::= _Z +/* ::= _Z []* TOP_LEVEL is non-zero when called at the top level. */ @@ -1001,11 +1069,28 @@ CP_STATIC_IF_GLIBCPP_V3 struct demangle_component * cplus_demangle_mangled_name (struct d_info *di, int top_level) { - if (! d_check_char (di, '_')) + struct demangle_component *p; + + 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; - return d_encoding (di, top_level); + 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); + + return p; } /* Return whether a function should have a return type. The argument @@ -1143,8 +1228,9 @@ d_name (struct d_info *di) return d_local_name (di); case 'L': + case 'U': return d_unqualified_name (di); - + case 'S': { int subst; @@ -1234,6 +1320,7 @@ d_nested_name (struct d_info *di) /* ::= ::= ::= + ::= ::= ::= @@ -1262,10 +1349,20 @@ d_prefix (struct d_info *di) here. */ comb_type = DEMANGLE_COMPONENT_QUAL_NAME; - if (IS_DIGIT (peek) + 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 == 'D' + || peek == 'U' || peek == 'L') dc = d_unqualified_name (di); else if (peek == 'S') @@ -1281,6 +1378,16 @@ d_prefix (struct d_info *di) dc = d_template_param (di); else if (peek == 'E') return ret; + else if (peek == 'M') + { + /* Initializer scope for a lambda. We don't need to represent + this; the normal code will just treat the variable as a type + scope, which gives appropriate output. */ + if (ret == NULL) + return NULL; + d_advance (di, 1); + continue; + } else return NULL; @@ -1337,6 +1444,18 @@ d_unqualified_name (struct d_info *di) return NULL; return ret; } + else if (peek == 'U') + { + switch (d_peek_next_char (di)) + { + case 'l': + return d_lambda (di); + case 't': + return d_unnamed_type (di); + default: + return NULL; + } + } else return NULL; } @@ -1390,6 +1509,20 @@ d_number (struct d_info *di) } } +/* Like d_number, but returns a demangle_component. */ + +static struct demangle_component * +d_number_component (struct d_info *di) +{ + struct demangle_component *ret = d_make_empty (di); + if (ret) + { + ret->type = DEMANGLE_COMPONENT_NUMBER; + ret->u.s_number.number = d_number (di); + } + return ret; +} + /* identifier ::= <(unqualified source code identifier)> */ static struct demangle_component * @@ -1493,6 +1626,8 @@ const struct demangle_operator_info cplus_demangle_operators[] = { "rs", NL (">>"), 2 }, { "st", NL ("sizeof "), 1 }, { "sz", NL ("sizeof "), 1 }, + { "at", NL ("alignof "), 1 }, + { "az", NL ("alignof "), 1 }, { NULL, NULL, 0, 0 } }; @@ -1650,6 +1785,8 @@ d_java_resource (struct d_info *di) ::= GR ::= GA ::= Gr + ::= GTt + ::= GTn */ static struct demangle_component * @@ -1734,13 +1871,33 @@ d_special_name (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL); case 'R': - return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di), - NULL); + { + struct demangle_component *name = d_name (di); + return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name, + d_number_component (di)); + } case 'A': return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS, d_encoding (di, 0), NULL); + case 'T': + switch (d_next_char (di)) + { + case 'n': + return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, + d_encoding (di, 0), NULL); + default: + /* ??? The proposal is that other letters (such as 'h') stand + for different variants of transaction cloning, such as + compiling directly for hardware transaction support. But + they still should all be transactional clones of some sort + so go ahead and call them that. */ + case 't': + return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE, + d_encoding (di, 0), NULL); + } + case 'r': return d_java_resource (di); @@ -1824,6 +1981,9 @@ d_ctor_dtor_name (struct d_info *di) case '3': kind = gnu_v3_complete_object_allocating_ctor; break; + case '5': + kind = gnu_v3_object_ctor_group; + break; default: return NULL; } @@ -1846,6 +2006,9 @@ d_ctor_dtor_name (struct d_info *di) case '2': kind = gnu_v3_base_object_dtor; break; + case '5': + kind = gnu_v3_object_dtor_group; + break; default: return NULL; } @@ -1916,6 +2079,8 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] = /* 29 */ { NL ("half"), NL ("half"), D_PRINT_FLOAT }, /* 30 */ { NL ("char16_t"), NL ("char16_t"), D_PRINT_DEFAULT }, /* 31 */ { NL ("char32_t"), NL ("char32_t"), D_PRINT_DEFAULT }, + /* 32 */ { NL ("decltype(nullptr)"), NL ("decltype(nullptr)"), + D_PRINT_DEFAULT }, }; CP_STATIC_IF_GLIBCPP_V3 @@ -2130,6 +2295,34 @@ cplus_demangle_type (struct d_info *di) ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[31]); di->expansion += ret->u.s_builtin.type->len; break; + + case 'F': + /* 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); + ret->u.s_fixed.length = cplus_demangle_type (di); + if (ret->u.s_fixed.length == NULL) + return NULL; + d_number (di); + peek = d_next_char (di); + ret->u.s_fixed.sat = (peek == 's'); + break; + + case 'v': + ret = d_vector_type (di); + break; + + case 'n': + /* decltype(nullptr) */ + ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]); + di->expansion += ret->u.s_builtin.type->len; + break; + + default: + return NULL; } break; @@ -2152,8 +2345,10 @@ static struct demangle_component ** d_cv_qualifiers (struct d_info *di, struct demangle_component **pret, int member_fn) { + struct demangle_component **pstart; char peek; + pstart = pret; peek = d_peek_char (di); while (peek == 'r' || peek == 'V' || peek == 'K') { @@ -2190,6 +2385,28 @@ d_cv_qualifiers (struct d_info *di, peek = d_peek_char (di); } + if (!member_fn && peek == 'F') + { + while (pstart != pret) + { + switch ((*pstart)->type) + { + case DEMANGLE_COMPONENT_RESTRICT: + (*pstart)->type = DEMANGLE_COMPONENT_RESTRICT_THIS; + break; + case DEMANGLE_COMPONENT_VOLATILE: + (*pstart)->type = DEMANGLE_COMPONENT_VOLATILE_THIS; + break; + case DEMANGLE_COMPONENT_CONST: + (*pstart)->type = DEMANGLE_COMPONENT_CONST_THIS; + break; + default: + break; + } + pstart = &d_left (*pstart); + } + } + return pret; } @@ -2214,50 +2431,30 @@ d_function_type (struct d_info *di) return ret; } -/* ::= [J]+ */ +/* + */ static struct demangle_component * -d_bare_function_type (struct d_info *di, int has_return_tipe) +d_parmlist (struct d_info *di) { - struct demangle_component *return_type; struct demangle_component *tl; struct demangle_component **ptl; - char peek; - - /* Detect special qualifier indicating that the first argument - is the return type. */ - peek = d_peek_char (di); - if (peek == 'J') - { - d_advance (di, 1); - has_return_tipe = 1; - } - return_type = NULL; tl = NULL; ptl = &tl; while (1) { struct demangle_component *type; - peek = d_peek_char (di); - if (peek == '\0' || peek == 'E') + char peek = d_peek_char (di); + if (peek == '\0' || peek == 'E' || peek == '.') break; type = cplus_demangle_type (di); if (type == NULL) return NULL; - if (has_return_tipe) - { - return_type = type; - has_return_tipe = 0; - } - else - { - *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); - if (*ptl == NULL) - return NULL; - ptl = &d_right (*ptl); - } + *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL); + if (*ptl == NULL) + return NULL; + ptl = &d_right (*ptl); } /* There should be at least one parameter type besides the optional @@ -2272,10 +2469,45 @@ d_bare_function_type (struct d_info *di, int has_return_tipe) && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID) { di->expansion -= d_left (tl)->u.s_builtin.type->len; - tl = NULL; + d_left (tl) = NULL; + } + + return tl; +} + +/* ::= [J]+ */ + +static struct demangle_component * +d_bare_function_type (struct d_info *di, int has_return_tipe) +{ + struct demangle_component *return_type; + struct demangle_component *tl; + char peek; + + /* Detect special qualifier indicating that the first argument + is the return type. */ + peek = d_peek_char (di); + if (peek == 'J') + { + d_advance (di, 1); + has_return_tipe = 1; + } + + if (has_return_tipe) + { + return_type = cplus_demangle_type (di); + if (return_type == NULL) + return NULL; } + else + return_type = NULL; + + tl = d_parmlist (di); + if (tl == NULL) + return NULL; - return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl); + return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, + return_type, tl); } /* ::= */ @@ -2331,6 +2563,34 @@ d_array_type (struct d_info *di) cplus_demangle_type (di)); } +/* ::= Dv _ + ::= Dv _ _ */ + +static struct demangle_component * +d_vector_type (struct d_info *di) +{ + char peek; + struct demangle_component *dim; + + peek = d_peek_char (di); + if (peek == '_') + { + d_advance (di, 1); + dim = d_expression (di); + } + else + dim = d_number_component (di); + + if (dim == NULL) + return NULL; + + if (! d_check_char (di, '_')) + return NULL; + + return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim, + cplus_demangle_type (di)); +} + /* ::= M <(class) type> <(member) type> */ static struct demangle_component * @@ -2377,6 +2637,24 @@ d_pointer_to_member_type (struct d_info *di) return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); } +/* _ */ + +static long +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; + + if (! d_check_char (di, '_')) + return -1; + return num; +} + /* ::= T_ ::= T <(parameter-2 non-negative) number> _ */ @@ -2389,17 +2667,8 @@ d_template_param (struct d_info *di) if (! d_check_char (di, 'T')) return NULL; - if (d_peek_char (di) == '_') - param = 0; - else - { - param = d_number (di); - if (param < 0) - return NULL; - param += 1; - } - - if (! d_check_char (di, '_')) + param = d_compact_number (di); + if (param < 0) return NULL; ++di->did_subs; @@ -2560,17 +2829,43 @@ d_expression (struct d_info *di) d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, name, d_template_args (di))); } - else if (peek == 's' && d_peek_next_char (di) == 'T') + else if (peek == 's' && d_peek_next_char (di) == 'p') { - /* Just demangle a parameter placeholder as its type. */ d_advance (di, 2); - return cplus_demangle_type (di); + return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION, + d_expression (di), NULL); } - else if (IS_DIGIT (peek)) + else if (peek == 'f' && d_peek_next_char (di) == 'p') + { + /* Function parameter used in a late-specified return type. */ + int index; + d_advance (di, 2); + if (d_peek_char (di) == 'T') + { + /* 'this' parameter. */ + d_advance (di, 1); + index = 0; + } + else + { + index = d_compact_number (di) + 1; + if (index == 0) + return NULL; + } + return d_make_function_param (di, index); + } + else if (IS_DIGIT (peek) + || (peek == 'o' && d_peek_next_char (di) == 'n')) { /* We can get an unqualified name as an expression in the case of - a dependent member access, i.e. decltype(T().i). */ - struct demangle_component *name = d_unqualified_name (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); + + name = d_unqualified_name (di); if (name == NULL) return NULL; if (d_peek_char (di) == 'I') @@ -2607,28 +2902,39 @@ d_expression (struct d_info *di) args = op->u.s_extended_operator.args; break; case DEMANGLE_COMPONENT_CAST: - if (d_peek_char (di) == 'v') - /* T() encoded as an operand of void. */ - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - cplus_demangle_type (di)); - else - args = 1; + args = 1; break; } switch (args) { case 1: - return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, - d_expression (di)); + { + struct demangle_component *operand; + if (op->type == DEMANGLE_COMPONENT_CAST + && d_check_char (di, '_')) + operand = d_exprlist (di); + else + operand = d_expression (di); + return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op, + operand); + } case 2: { struct demangle_component *left; struct demangle_component *right; + const char *code = op->u.s_operator.op->code; left = d_expression (di); - if (!strcmp (op->u.s_operator.op->code, "cl")) + if (!strcmp (code, "cl")) right = d_exprlist (di); + 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 (di); @@ -2671,7 +2977,9 @@ d_expr_primary (struct d_info *di) if (! d_check_char (di, 'L')) return NULL; - if (d_peek_char (di) == '_') + 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 { @@ -2749,10 +3057,31 @@ d_local_name (struct d_info *di) else { struct demangle_component *name; + int num = -1; + + if (d_peek_char (di) == 'd') + { + /* Default argument scope: d _. */ + d_advance (di, 1); + num = d_compact_number (di); + if (num < 0) + return NULL; + } name = d_name (di); - if (! d_discriminator (di)) - return NULL; + 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); } } @@ -2776,6 +3105,102 @@ d_discriminator (struct d_info *di) return 1; } +/* ::= Ul E [ ] _ */ + +static struct demangle_component * +d_lambda (struct d_info *di) +{ + struct demangle_component *tl; + struct demangle_component *ret; + int num; + + if (! d_check_char (di, 'U')) + return NULL; + if (! d_check_char (di, 'l')) + return NULL; + + tl = d_parmlist (di); + if (tl == NULL) + return NULL; + + if (! d_check_char (di, 'E')) + return NULL; + + num = d_compact_number (di); + if (num < 0) + return NULL; + + ret = d_make_empty (di); + if (ret) + { + ret->type = DEMANGLE_COMPONENT_LAMBDA; + ret->u.s_unary_num.sub = tl; + ret->u.s_unary_num.num = num; + } + + if (! d_add_substitution (di, ret)) + return NULL; + + return ret; +} + +/* ::= Ut [ ] _ */ + +static struct demangle_component * +d_unnamed_type (struct d_info *di) +{ + struct demangle_component *ret; + long num; + + 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; + + ret = d_make_empty (di); + if (ret) + { + ret->type = DEMANGLE_COMPONENT_UNNAMED_TYPE; + ret->u.s_number.number = num; + } + + if (! d_add_substitution (di, ret)) + return NULL; + + return ret; +} + +/* ::= [ . ] [ . ]* +*/ + +static struct demangle_component * +d_clone_suffix (struct d_info *di, struct demangle_component *encoding) +{ + const char *suffix = d_str (di); + const char *pend = suffix; + struct demangle_component *n; + + if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_')) + { + pend += 2; + while (IS_LOWER (*pend) || *pend == '_') + ++pend; + } + while (*pend == '.' && IS_DIGIT (pend[1])) + { + pend += 2; + while (IS_DIGIT (*pend)) + ++pend; + } + d_advance (di, pend - suffix); + n = d_make_name (di, suffix, pend - suffix); + return d_make_comp (di, DEMANGLE_COMPONENT_CLONE, encoding, n); +} + /* Add a new substitution. */ static int @@ -3003,14 +3428,15 @@ d_growable_string_callback_adapter (const char *s, size_t l, void *opaque) /* Initialize a print information structure. */ static void -d_print_init (struct d_print_info *dpi, int options, - demangle_callbackref callback, void *opaque) +d_print_init (struct d_print_info *dpi, demangle_callbackref callback, + void *opaque) { - dpi->options = options; dpi->len = 0; dpi->last_char = '\0'; dpi->templates = NULL; dpi->modifiers = NULL; + dpi->pack_index = 0; + dpi->flush_count = 0; dpi->callback = callback; dpi->opaque = opaque; @@ -3040,6 +3466,7 @@ d_print_flush (struct d_print_info *dpi) dpi->buf[dpi->len] = '\0'; dpi->callback (dpi->buf, dpi->len, dpi->opaque); dpi->len = 0; + dpi->flush_count++; } /* Append characters and buffers for printing. */ @@ -3069,6 +3496,14 @@ d_append_string (struct d_print_info *dpi, const char *s) d_append_buffer (dpi, s, strlen (s)); } +static inline void +d_append_num (struct d_print_info *dpi, long l) +{ + char buf[25]; + sprintf (buf,"%ld", l); + d_append_string (dpi, buf); +} + static inline char d_last_char (struct d_print_info *dpi) { @@ -3092,9 +3527,9 @@ cplus_demangle_print_callback (int options, { struct d_print_info dpi; - d_print_init (&dpi, options, callback, opaque); + d_print_init (&dpi, callback, opaque); - d_print_comp (&dpi, dc); + d_print_comp (&dpi, options, dc); d_print_flush (&dpi); @@ -3194,11 +3629,13 @@ d_find_pack (struct d_print_info *dpi, case DEMANGLE_COMPONENT_PACK_EXPANSION: return NULL; + case DEMANGLE_COMPONENT_LAMBDA: case DEMANGLE_COMPONENT_NAME: case DEMANGLE_COMPONENT_OPERATOR: case DEMANGLE_COMPONENT_BUILTIN_TYPE: case DEMANGLE_COMPONENT_SUB_STD: case DEMANGLE_COMPONENT_CHARACTER: + case DEMANGLE_COMPONENT_FUNCTION_PARAM: return NULL; case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: @@ -3235,15 +3672,16 @@ d_pack_length (const struct demangle_component *dc) if needed. */ static void -d_print_subexpr (struct d_print_info *dpi, +d_print_subexpr (struct d_print_info *dpi, int options, const struct demangle_component *dc) { int simple = 0; - if (dc->type == DEMANGLE_COMPONENT_NAME) + if (dc->type == DEMANGLE_COMPONENT_NAME + || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM) simple = 1; if (!simple) d_append_char (dpi, '('); - d_print_comp (dpi, dc); + d_print_comp (dpi, options, dc); if (!simple) d_append_char (dpi, ')'); } @@ -3251,9 +3689,13 @@ d_print_subexpr (struct d_print_info *dpi, /* Subroutine to handle components. */ static void -d_print_comp (struct d_print_info *dpi, +d_print_comp (struct d_print_info *dpi, int options, const 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; + if (dc == NULL) { d_print_error (dpi); @@ -3265,7 +3707,7 @@ d_print_comp (struct d_print_info *dpi, switch (dc->type) { case DEMANGLE_COMPONENT_NAME: - if ((dpi->options & DMGL_JAVA) == 0) + 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); @@ -3273,12 +3715,12 @@ d_print_comp (struct d_print_info *dpi, case DEMANGLE_COMPONENT_QUAL_NAME: case DEMANGLE_COMPONENT_LOCAL_NAME: - d_print_comp (dpi, d_left (dc)); - if ((dpi->options & DMGL_JAVA) == 0) + d_print_comp (dpi, options, d_left (dc)); + if ((options & DMGL_JAVA) == 0) d_append_string (dpi, "::"); else d_append_char (dpi, '.'); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); return; case DEMANGLE_COMPONENT_TYPED_NAME: @@ -3293,6 +3735,7 @@ d_print_comp (struct d_print_info *dpi, the right place for the type. We also have to pass down any CV-qualifiers, which apply to the this parameter. */ hold_modifiers = dpi->modifiers; + dpi->modifiers = 0; i = 0; typed_name = d_left (dc); while (typed_name != NULL) @@ -3342,6 +3785,8 @@ d_print_comp (struct d_print_info *dpi, 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) @@ -3365,7 +3810,7 @@ d_print_comp (struct d_print_info *dpi, } } - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE) dpi->templates = dpt.next; @@ -3378,7 +3823,7 @@ d_print_comp (struct d_print_info *dpi, if (! adpm[i].printed) { d_append_char (dpi, ' '); - d_print_mod (dpi, adpm[i].mod); + d_print_mod (dpi, options, adpm[i].mod); } } @@ -3401,7 +3846,7 @@ d_print_comp (struct d_print_info *dpi, dcl = d_left (dc); - if ((dpi->options & DMGL_JAVA) != 0 + if ((options & DMGL_JAVA) != 0 && dcl->type == DEMANGLE_COMPONENT_NAME && dcl->u.s_name.len == 6 && strncmp (dcl->u.s_name.s, "JArray", 6) == 0) @@ -3409,16 +3854,16 @@ d_print_comp (struct d_print_info *dpi, /* Special-case Java arrays, so that JArray appears instead as TYPE[]. */ - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); d_append_string (dpi, "[]"); } else { - d_print_comp (dpi, dcl); + d_print_comp (dpi, options, dcl); if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); d_append_char (dpi, '<'); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); /* Avoid generating two consecutive '>' characters, to avoid the C++ syntactic ambiguity. */ if (d_last_char (dpi) == '>') @@ -3453,7 +3898,7 @@ d_print_comp (struct d_print_info *dpi, hold_dpt = dpi->templates; dpi->templates = hold_dpt->next; - d_print_comp (dpi, a); + d_print_comp (dpi, options, a); dpi->templates = hold_dpt; @@ -3461,79 +3906,91 @@ d_print_comp (struct d_print_info *dpi, } case DEMANGLE_COMPONENT_CTOR: - d_print_comp (dpi, dc->u.s_ctor.name); + d_print_comp (dpi, options, dc->u.s_ctor.name); return; case DEMANGLE_COMPONENT_DTOR: d_append_char (dpi, '~'); - d_print_comp (dpi, dc->u.s_dtor.name); + d_print_comp (dpi, options, dc->u.s_dtor.name); return; case DEMANGLE_COMPONENT_VTABLE: d_append_string (dpi, "vtable for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_VTT: d_append_string (dpi, "VTT for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE: d_append_string (dpi, "construction vtable for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); d_append_string (dpi, "-in-"); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO: d_append_string (dpi, "typeinfo for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO_NAME: d_append_string (dpi, "typeinfo name for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_TYPEINFO_FN: d_append_string (dpi, "typeinfo fn for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_THUNK: d_append_string (dpi, "non-virtual thunk to "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_VIRTUAL_THUNK: d_append_string (dpi, "virtual thunk to "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_COVARIANT_THUNK: d_append_string (dpi, "covariant return thunk to "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_JAVA_CLASS: d_append_string (dpi, "java Class for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_GUARD: d_append_string (dpi, "guard variable for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_REFTEMP: - d_append_string (dpi, "reference temporary for "); - d_print_comp (dpi, d_left (dc)); + d_append_string (dpi, "reference temporary #"); + d_print_comp (dpi, options, d_right (dc)); + d_append_string (dpi, " for "); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_HIDDEN_ALIAS: d_append_string (dpi, "hidden alias for "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_TRANSACTION_CLONE: + d_append_string (dpi, "transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); + return; + + case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE: + d_append_string (dpi, "non-transaction clone for "); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_SUB_STD: @@ -3560,22 +4017,50 @@ d_print_comp (struct d_print_info *dpi, break; if (pdpm->mod->type == dc->type) { - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; } } } } + goto modifier; + + case DEMANGLE_COMPONENT_REFERENCE: + 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 *a = d_lookup_template_argument (dpi, sub); + if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST) + a = d_index_template_argument (a, dpi->pack_index); + + if (a == NULL) + { + 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); + } /* Fall through. */ + case DEMANGLE_COMPONENT_RESTRICT_THIS: case DEMANGLE_COMPONENT_VOLATILE_THIS: case DEMANGLE_COMPONENT_CONST_THIS: case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: case DEMANGLE_COMPONENT_POINTER: - case DEMANGLE_COMPONENT_REFERENCE: - case DEMANGLE_COMPONENT_RVALUE_REFERENCE: case DEMANGLE_COMPONENT_COMPLEX: case DEMANGLE_COMPONENT_IMAGINARY: + modifier: { /* We keep a list of modifiers on the stack. */ struct d_print_mod dpm; @@ -3586,12 +4071,15 @@ d_print_comp (struct d_print_info *dpi, dpm.printed = 0; dpm.templates = dpi->templates; - d_print_comp (dpi, 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, dc); + d_print_mod (dpi, options, dc); dpi->modifiers = dpm.next; @@ -3599,7 +4087,7 @@ d_print_comp (struct d_print_info *dpi, } case DEMANGLE_COMPONENT_BUILTIN_TYPE: - if ((dpi->options & DMGL_JAVA) == 0) + if ((options & DMGL_JAVA) == 0) d_append_buffer (dpi, dc->u.s_builtin.type->name, dc->u.s_builtin.type->len); else @@ -3608,16 +4096,21 @@ d_print_comp (struct d_print_info *dpi, return; case DEMANGLE_COMPONENT_VENDOR_TYPE: - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_FUNCTION_TYPE: { - if ((dpi->options & DMGL_RET_POSTFIX) != 0) - d_print_function_type (dpi, 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) + 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; @@ -3629,7 +4122,8 @@ d_print_comp (struct d_print_info *dpi, dpm.printed = 0; dpm.templates = dpi->templates; - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP), + d_left (dc)); dpi->modifiers = dpm.next; @@ -3638,12 +4132,14 @@ d_print_comp (struct d_print_info *dpi, /* In standard prefix notation, there is a space between the return type and the function signature. */ - if ((dpi->options & DMGL_RET_POSTFIX) == 0) + if ((options & DMGL_RET_POSTFIX) == 0) d_append_char (dpi, ' '); } - if ((dpi->options & DMGL_RET_POSTFIX) == 0) - d_print_function_type (dpi, 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; } @@ -3696,7 +4192,7 @@ d_print_comp (struct d_print_info *dpi, pdpm = pdpm->next; } - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); dpi->modifiers = hold_modifiers; @@ -3706,15 +4202,16 @@ d_print_comp (struct d_print_info *dpi, while (i > 1) { --i; - d_print_mod (dpi, adpm[i].mod); + d_print_mod (dpi, options, adpm[i].mod); } - d_print_array_type (dpi, dc, dpi->modifiers); + d_print_array_type (dpi, options, dc, dpi->modifiers); return; } case DEMANGLE_COMPONENT_PTRMEM_TYPE: + case DEMANGLE_COMPONENT_VECTOR_TYPE: { struct d_print_mod dpm; @@ -3724,30 +4221,54 @@ d_print_comp (struct d_print_info *dpi, dpm.printed = 0; dpm.templates = dpi->templates; - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); /* If the modifier didn't get printed by the type, print it now. */ if (! dpm.printed) - { - d_append_char (dpi, ' '); - d_print_comp (dpi, d_left (dc)); - d_append_string (dpi, "::*"); - } + d_print_mod (dpi, options, dc); dpi->modifiers = dpm.next; return; } + case DEMANGLE_COMPONENT_FIXED_TYPE: + if (dc->u.s_fixed.sat) + d_append_string (dpi, "_Sat "); + /* Don't print "int _Accum". */ + if (dc->u.s_fixed.length->u.s_builtin.type + != &cplus_demangle_builtin_types['i'-'a']) + { + d_print_comp (dpi, options, dc->u.s_fixed.length); + d_append_char (dpi, ' '); + } + if (dc->u.s_fixed.accum) + d_append_string (dpi, "_Accum"); + else + d_append_string (dpi, "_Fract"); + return; + case DEMANGLE_COMPONENT_ARGLIST: case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST: if (d_left (dc) != NULL) - d_print_comp (dpi, d_left (dc)); + 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, ", "); - d_print_comp (dpi, d_right (dc)); + 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; } return; @@ -3766,29 +4287,63 @@ d_print_comp (struct d_print_info *dpi, case DEMANGLE_COMPONENT_EXTENDED_OPERATOR: d_append_string (dpi, "operator "); - d_print_comp (dpi, dc->u.s_extended_operator.name); + d_print_comp (dpi, options, dc->u.s_extended_operator.name); return; case DEMANGLE_COMPONENT_CAST: d_append_string (dpi, "operator "); - d_print_cast (dpi, dc); + d_print_cast (dpi, options, dc); return; case DEMANGLE_COMPONENT_UNARY: - if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST) - d_print_expr_op (dpi, d_left (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_right (dc)->type == DEMANGLE_COMPONENT_TYPED_NAME + && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_QUAL_NAME + && d_right (d_right (dc))->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) + { + /* Address of a function (therefore in an expression context) must + have its argument list suppressed. + + unary operator ... dc + operator & ... d_left (dc) + typed name ... d_right (dc) + qualified name ... d_left (d_right (dc)) + + function type ... d_right (d_right (dc)) + argument list + */ + + d_print_expr_op (dpi, options, d_left (dc)); + d_print_comp (dpi, options, d_left (d_right (dc))); + return; + } + else if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR + && d_left (dc)->u.s_operator.op->len == 1 + && d_left (dc)->u.s_operator.op->name[0] == '&' + && d_right (dc)->type == DEMANGLE_COMPONENT_QUAL_NAME) + { + /* Keep also already processed variant without the argument list. + + unary operator ... dc + operator & ... d_left (dc) + qualified name ... d_right (dc) + */ + + d_print_expr_op (dpi, options, d_left (dc)); + d_print_comp (dpi, options, d_right (dc)); + return; + } + else if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST) + d_print_expr_op (dpi, options, d_left (dc)); else { d_append_char (dpi, '('); - d_print_cast (dpi, d_left (dc)); + d_print_cast (dpi, options, d_left (dc)); d_append_char (dpi, ')'); } - if (d_left (dc)->type == DEMANGLE_COMPONENT_CAST - && d_right (dc)->type == DEMANGLE_COMPONENT_BUILTIN_TYPE) - /* type() -- FIXME what about type(multiple,args) */ - d_append_string (dpi, "()"); - else - d_print_subexpr (dpi, d_right (dc)); + d_print_subexpr (dpi, options, d_right (dc)); return; case DEMANGLE_COMPONENT_BINARY: @@ -3806,10 +4361,33 @@ d_print_comp (struct d_print_info *dpi, && d_left (dc)->u.s_operator.op->name[0] == '>') d_append_char (dpi, '('); - d_print_subexpr (dpi, d_left (d_right (dc))); - if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0) - d_print_expr_op (dpi, d_left (dc)); - d_print_subexpr (dpi, d_right (d_right (dc))); + 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)); + + 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 (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 (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR && d_left (dc)->u.s_operator.op->len == 1 @@ -3830,11 +4408,11 @@ d_print_comp (struct d_print_info *dpi, d_print_error (dpi); return; } - d_print_subexpr (dpi, d_left (d_right (dc))); - d_print_expr_op (dpi, d_left (dc)); - d_print_subexpr (dpi, d_left (d_right (d_right (dc)))); + d_print_subexpr (dpi, options, d_left (d_right (dc))); + d_print_expr_op (dpi, options, d_left (dc)); + d_print_subexpr (dpi, options, d_left (d_right (d_right (dc)))); d_append_string (dpi, " : "); - d_print_subexpr (dpi, d_right (d_right (d_right (dc)))); + d_print_subexpr (dpi, options, d_right (d_right (d_right (dc)))); return; case DEMANGLE_COMPONENT_TRINARY_ARG1: @@ -3865,7 +4443,7 @@ d_print_comp (struct d_print_info *dpi, { if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG) d_append_char (dpi, '-'); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); switch (tp) { default: @@ -3915,26 +4493,30 @@ d_print_comp (struct d_print_info *dpi, } d_append_char (dpi, '('); - d_print_comp (dpi, d_left (dc)); + 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, '['); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); if (tp == D_PRINT_FLOAT) d_append_char (dpi, ']'); } return; + case DEMANGLE_COMPONENT_NUMBER: + d_append_num (dpi, dc->u.s_number.number); + return; + case DEMANGLE_COMPONENT_JAVA_RESOURCE: d_append_string (dpi, "java resource "); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); return; case DEMANGLE_COMPONENT_COMPOUND_NAME: - d_print_comp (dpi, d_left (dc)); - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_left (dc)); + d_print_comp (dpi, options, d_right (dc)); return; case DEMANGLE_COMPONENT_CHARACTER: @@ -3943,27 +4525,82 @@ d_print_comp (struct d_print_info *dpi, case DEMANGLE_COMPONENT_DECLTYPE: d_append_string (dpi, "decltype ("); - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); d_append_char (dpi, ')'); return; case DEMANGLE_COMPONENT_PACK_EXPANSION: { - struct demangle_component *a = d_find_pack (dpi, d_left (dc)); - int len = d_pack_length (a); + int len; int i; + struct demangle_component *a = d_find_pack (dpi, d_left (dc)); + if (a == NULL) + { + /* d_find_pack won't find anything if the only packs involved + in this expansion are function parameter packs; in that + case, just print the pattern and "...". */ + d_print_subexpr (dpi, options, d_left (dc)); + d_append_string (dpi, "..."); + return; + } + len = d_pack_length (a); dc = d_left (dc); for (i = 0; i < len; ++i) { dpi->pack_index = i; - d_print_comp (dpi, dc); + d_print_comp (dpi, options, dc); if (i < len-1) d_append_string (dpi, ", "); } } return; + 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, '}'); + } + } + return; + + case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS: + d_append_string (dpi, "global constructors keyed to "); + d_print_comp (dpi, options, dc->u.s_binary.left); + return; + + case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS: + d_append_string (dpi, "global destructors keyed to "); + d_print_comp (dpi, options, dc->u.s_binary.left); + return; + + case DEMANGLE_COMPONENT_LAMBDA: + d_append_string (dpi, "{lambda("); + d_print_comp (dpi, options, dc->u.s_unary_num.sub); + d_append_string (dpi, ")#"); + d_append_num (dpi, dc->u.s_unary_num.num + 1); + d_append_char (dpi, '}'); + return; + + case DEMANGLE_COMPONENT_UNNAMED_TYPE: + d_append_string (dpi, "{unnamed type#"); + d_append_num (dpi, dc->u.s_number.number + 1); + d_append_char (dpi, '}'); + return; + + case DEMANGLE_COMPONENT_CLONE: + d_print_comp (dpi, options, d_left (dc)); + d_append_string (dpi, " [clone "); + d_print_comp (dpi, options, d_right (dc)); + d_append_char (dpi, ']'); + return; + default: d_print_error (dpi); return; @@ -4026,7 +4663,7 @@ d_print_java_identifier (struct d_print_info *dpi, const char *name, int len) qualifiers on this after printing a function. */ static void -d_print_mod_list (struct d_print_info *dpi, +d_print_mod_list (struct d_print_info *dpi, int options, struct d_print_mod *mods, int suffix) { struct d_print_template *hold_dpt; @@ -4040,7 +4677,7 @@ d_print_mod_list (struct d_print_info *dpi, || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS))) { - d_print_mod_list (dpi, mods->next, suffix); + d_print_mod_list (dpi, options, mods->next, suffix); return; } @@ -4051,13 +4688,13 @@ d_print_mod_list (struct d_print_info *dpi, if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE) { - d_print_function_type (dpi, mods->mod, mods->next); + d_print_function_type (dpi, options, mods->mod, mods->next); dpi->templates = hold_dpt; return; } else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE) { - d_print_array_type (dpi, mods->mod, mods->next); + d_print_array_type (dpi, options, mods->mod, mods->next); dpi->templates = hold_dpt; return; } @@ -4073,37 +4710,46 @@ d_print_mod_list (struct d_print_info *dpi, hold_modifiers = dpi->modifiers; dpi->modifiers = NULL; - d_print_comp (dpi, d_left (mods->mod)); + d_print_comp (dpi, options, d_left (mods->mod)); dpi->modifiers = hold_modifiers; - if ((dpi->options & DMGL_JAVA) == 0) + if ((options & DMGL_JAVA) == 0) d_append_string (dpi, "::"); else d_append_char (dpi, '.'); dc = d_right (mods->mod); + + if (dc->type == DEMANGLE_COMPONENT_DEFAULT_ARG) + { + d_append_string (dpi, "{default arg#"); + d_append_num (dpi, dc->u.s_unary_num.num + 1); + d_append_string (dpi, "}::"); + 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 = d_left (dc); - d_print_comp (dpi, dc); + d_print_comp (dpi, options, dc); dpi->templates = hold_dpt; return; } - d_print_mod (dpi, mods->mod); + d_print_mod (dpi, options, mods->mod); dpi->templates = hold_dpt; - d_print_mod_list (dpi, mods->next, suffix); + d_print_mod_list (dpi, options, mods->next, suffix); } /* Print a modifier. */ static void -d_print_mod (struct d_print_info *dpi, +d_print_mod (struct d_print_info *dpi, int options, const struct demangle_component *mod) { switch (mod->type) @@ -4122,11 +4768,11 @@ d_print_mod (struct d_print_info *dpi, return; case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL: d_append_char (dpi, ' '); - d_print_comp (dpi, d_right (mod)); + d_print_comp (dpi, options, d_right (mod)); return; case DEMANGLE_COMPONENT_POINTER: /* There is no pointer symbol in Java. */ - if ((dpi->options & DMGL_JAVA) == 0) + if ((options & DMGL_JAVA) == 0) d_append_char (dpi, '*'); return; case DEMANGLE_COMPONENT_REFERENCE: @@ -4144,16 +4790,22 @@ d_print_mod (struct d_print_info *dpi, case DEMANGLE_COMPONENT_PTRMEM_TYPE: if (d_last_char (dpi) != '(') d_append_char (dpi, ' '); - d_print_comp (dpi, d_left (mod)); + d_print_comp (dpi, options, d_left (mod)); d_append_string (dpi, "::*"); return; case DEMANGLE_COMPONENT_TYPED_NAME: - d_print_comp (dpi, d_left (mod)); + d_print_comp (dpi, options, d_left (mod)); + return; + case DEMANGLE_COMPONENT_VECTOR_TYPE: + d_append_string (dpi, " __vector("); + d_print_comp (dpi, options, d_left (mod)); + d_append_char (dpi, ')'); return; + default: /* Otherwise, we have something that won't go back on the modifier stack, so we can just print it. */ - d_print_comp (dpi, mod); + d_print_comp (dpi, options, mod); return; } } @@ -4161,25 +4813,22 @@ d_print_mod (struct d_print_info *dpi, /* Print a function type, except for the return type. */ static void -d_print_function_type (struct d_print_info *dpi, +d_print_function_type (struct d_print_info *dpi, int options, const struct demangle_component *dc, struct d_print_mod *mods) { int need_paren; - int saw_mod; int need_space; struct d_print_mod *p; struct d_print_mod *hold_modifiers; need_paren = 0; - saw_mod = 0; need_space = 0; for (p = mods; p != NULL; p = p->next) { if (p->printed) break; - saw_mod = 1; switch (p->mod->type) { case DEMANGLE_COMPONENT_POINTER: @@ -4208,9 +4857,6 @@ d_print_function_type (struct d_print_info *dpi, break; } - if (d_left (dc) != NULL && ! saw_mod) - need_paren = 1; - if (need_paren) { if (! need_space) @@ -4227,7 +4873,7 @@ d_print_function_type (struct d_print_info *dpi, hold_modifiers = dpi->modifiers; dpi->modifiers = NULL; - d_print_mod_list (dpi, mods, 0); + d_print_mod_list (dpi, options, mods, 0); if (need_paren) d_append_char (dpi, ')'); @@ -4235,11 +4881,11 @@ d_print_function_type (struct d_print_info *dpi, d_append_char (dpi, '('); if (d_right (dc) != NULL) - d_print_comp (dpi, d_right (dc)); + d_print_comp (dpi, options, d_right (dc)); d_append_char (dpi, ')'); - d_print_mod_list (dpi, mods, 1); + d_print_mod_list (dpi, options, mods, 1); dpi->modifiers = hold_modifiers; } @@ -4247,7 +4893,7 @@ d_print_function_type (struct d_print_info *dpi, /* Print an array type, except for the element type. */ static void -d_print_array_type (struct d_print_info *dpi, +d_print_array_type (struct d_print_info *dpi, int options, const struct demangle_component *dc, struct d_print_mod *mods) { @@ -4281,7 +4927,7 @@ d_print_array_type (struct d_print_info *dpi, if (need_paren) d_append_string (dpi, " ("); - d_print_mod_list (dpi, mods, 0); + d_print_mod_list (dpi, options, mods, 0); if (need_paren) d_append_char (dpi, ')'); @@ -4293,7 +4939,7 @@ d_print_array_type (struct d_print_info *dpi, d_append_char (dpi, '['); if (d_left (dc) != NULL) - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); d_append_char (dpi, ']'); } @@ -4301,24 +4947,24 @@ d_print_array_type (struct d_print_info *dpi, /* Print an operator in an expression. */ static void -d_print_expr_op (struct d_print_info *dpi, +d_print_expr_op (struct d_print_info *dpi, int options, const 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, dc); + d_print_comp (dpi, options, dc); } /* Print a cast. */ static void -d_print_cast (struct d_print_info *dpi, +d_print_cast (struct d_print_info *dpi, int options, const struct demangle_component *dc) { if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE) - d_print_comp (dpi, d_left (dc)); + d_print_comp (dpi, options, d_left (dc)); else { struct d_print_mod *hold_dpm; @@ -4336,14 +4982,14 @@ d_print_cast (struct d_print_info *dpi, dpi->templates = &dpt; dpt.template_decl = d_left (dc); - d_print_comp (dpi, d_left (d_left (dc))); + d_print_comp (dpi, options, d_left (d_left (dc))); dpi->templates = dpt.next; if (d_last_char (dpi) == '<') d_append_char (dpi, ' '); d_append_char (dpi, '<'); - d_print_comp (dpi, d_right (d_left (dc))); + 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) == '>') @@ -4394,33 +5040,30 @@ static int d_demangle_callback (const char *mangled, int options, demangle_callbackref callback, void *opaque) { - int type; + enum + { + DCT_TYPE, + DCT_MANGLED, + DCT_GLOBAL_CTORS, + DCT_GLOBAL_DTORS + } + type; struct d_info di; struct demangle_component *dc; int status; if (mangled[0] == '_' && mangled[1] == 'Z') - type = 0; + type = DCT_MANGLED; else if (strncmp (mangled, "_GLOBAL_", 8) == 0 && (mangled[8] == '.' || mangled[8] == '_' || mangled[8] == '$') && (mangled[9] == 'D' || mangled[9] == 'I') && mangled[10] == '_') - { - const char *intro; - - intro = (mangled[9] == 'I') - ? "global constructors keyed to " - : "global destructors keyed to "; - - callback (intro, strlen (intro), opaque); - callback (mangled + 11, strlen (mangled + 11), opaque); - return 1; - } + type = mangled[9] == 'I' ? DCT_GLOBAL_CTORS : DCT_GLOBAL_DTORS; else { if ((options & DMGL_TYPES) == 0) return 0; - type = 1; + type = DCT_TYPE; } cplus_demangle_init_info (mangled, options, strlen (mangled), &di); @@ -4437,10 +5080,26 @@ d_demangle_callback (const char *mangled, int options, di.subs = alloca (di.num_subs * sizeof (*di.subs)); #endif - if (type) - dc = cplus_demangle_type (&di); - else - dc = cplus_demangle_mangled_name (&di, 1); + switch (type) + { + case DCT_TYPE: + dc = cplus_demangle_type (&di); + break; + case DCT_MANGLED: + dc = cplus_demangle_mangled_name (&di, 1); + break; + case DCT_GLOBAL_CTORS: + case DCT_GLOBAL_DTORS: + d_advance (&di, 11); + dc = d_make_comp (&di, + (type == DCT_GLOBAL_CTORS + ? DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS + : DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS), + d_make_demangle_mangled_name (&di, d_str (&di)), + NULL); + d_advance (&di, strlen (d_str (&di))); + break; + } /* If DMGL_PARAMS is set, then if we didn't consume the entire mangled string, then we didn't successfully demangle it. If @@ -4485,7 +5144,7 @@ d_demangle (const char *mangled, int options, size_t *palc) return NULL; } - *palc = dgs.allocation_failure ? 1 : 0; + *palc = dgs.allocation_failure ? 1 : dgs.alc; return dgs.buf; } diff --git a/coregrind/m_demangle/cp-demangle.h b/coregrind/m_demangle/cp-demangle.h index aad3743740..ae635beb4c 100644 --- a/coregrind/m_demangle/cp-demangle.h +++ b/coregrind/m_demangle/cp-demangle.h @@ -1,5 +1,6 @@ /* Internal demangler interface for g++ V3 ABI. - Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007, 2010 + Free Software Foundation, Inc. Written by Ian Lance Taylor . This file is part of the libiberty library, which is part of GCC. @@ -147,7 +148,7 @@ struct d_info extern const struct demangle_operator_info cplus_demangle_operators[]; #endif -#define D_BUILTIN_TYPE_COUNT (32) +#define D_BUILTIN_TYPE_COUNT (33) CP_STATIC_IF_GLIBCPP_V3 const struct demangle_builtin_type_info diff --git a/coregrind/m_demangle/cplus-dem.c b/coregrind/m_demangle/cplus-dem.c index 6eac15e1b2..4b5600a142 100644 --- a/coregrind/m_demangle/cplus-dem.c +++ b/coregrind/m_demangle/cplus-dem.c @@ -1,6 +1,6 @@ /* Demangler for GNU C++ Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + 2000, 2001, 2002, 2003, 2004, 2010 Free Software Foundation, Inc. Written by James Clark (jjc@jclark.uucp) Rewritten by Fred Fish (fnf@cygnus.com) for ARM and Lucid demangling Modified by Satish Pai (pai@apollo.hp.com) for HP demangling @@ -80,8 +80,6 @@ void * realloc (); #include "demangle.h" #include "safe-ctype.h" -static char *ada_demangle (const char *, int); - #define min(X,Y) (((X) < (Y)) ? (X) : (Y)) /* A value at least one greater than the maximum number of characters @@ -495,8 +493,6 @@ demangle_arm_hp_template (struct work_stuff *, const char **, int, string *); static void recursively_demangle (struct work_stuff *, const char **, string *, int); -static void grow_vect (char **, size_t *, size_t, int); - /* Translate count to integer, consuming tokens in the process. Conversion terminates on the first non-digit character. @@ -889,126 +885,268 @@ ML_(cplus_demangle) (const char *mangled, int options) } if (GNAT_DEMANGLING) - return ada_demangle(mangled,options); + return ada_demangle (mangled, options); ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); } +/* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */ -/* Assuming *OLD_VECT points to an array of *SIZE objects of size - ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects, - updating *OLD_VECT and *SIZE as necessary. */ - -static void -grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size) -{ - if (*size < min_size) - { - *size *= 2; - if (*size < min_size) - *size = min_size; - *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size); - } -} - -/* Demangle ada names: - 1. Discard final __{DIGIT}+ or ${DIGIT}+ - 2. Convert other instances of embedded "__" to `.'. - 3. Discard leading _ada_. - 4. Remove everything after first ___ if it is followed by 'X'. - 5. Put symbols that should be suppressed in <...> brackets. - The resulting string is valid until the next call of ada_demangle. */ - -static char * +char * ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED) { - int i, j; int len0; const char* p; - char *demangled = NULL; - int changed; - size_t demangled_size = 0; + char *d; + char *demangled; - changed = 0; - + /* Discard leading _ada_, which is used for library level subprograms. */ if (strncmp (mangled, "_ada_", 5) == 0) - { - mangled += 5; - changed = 1; - } - - if (mangled[0] == '_' || mangled[0] == '<') - goto Suppress; + mangled += 5; + + /* All ada unit names are lower-case. */ + if (!ISLOWER (mangled[0])) + goto unknown; + + /* Most of the demangling will trivially remove chars. Operator names + may add one char but because they are always preceeded by '__' which is + replaced by '.', they eventually never expand the size. + A few special names such as '___elabs' add a few chars (at most 7), but + they occur only once. */ + len0 = strlen (mangled) + 7 + 1; + demangled = XNEWVEC (char, len0); - p = strstr (mangled, "___"); - if (p == NULL) - len0 = strlen (mangled); - else + d = demangled; + p = mangled; + while (1) { - if (p[3] == 'X') - { - len0 = p - mangled; - changed = 1; - } + /* An entity names is expected. */ + if (ISLOWER (*p)) + { + /* An identifier, which is always lower case. */ + do + *d++ = *p++; + while (ISLOWER(*p) || ISDIGIT (*p) + || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1])))); + } + else if (p[0] == 'O') + { + /* An operator name. */ + static const char * const operators[][2] = + {{"Oabs", "abs"}, {"Oand", "and"}, {"Omod", "mod"}, + {"Onot", "not"}, {"Oor", "or"}, {"Orem", "rem"}, + {"Oxor", "xor"}, {"Oeq", "="}, {"One", "/="}, + {"Olt", "<"}, {"Ole", "<="}, {"Ogt", ">"}, + {"Oge", ">="}, {"Oadd", "+"}, {"Osubtract", "-"}, + {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"}, + {"Oexpon", "**"}, {NULL, NULL}}; + int k; + + for (k = 0; operators[k][0] != NULL; k++) + { + size_t slen = strlen (operators[k][0]); + if (strncmp (p, operators[k][0], slen) == 0) + { + p += slen; + slen = strlen (operators[k][1]); + *d++ = '"'; + memcpy (d, operators[k][1], slen); + d += slen; + *d++ = '"'; + break; + } + } + /* Operator not found. */ + if (operators[k][0] == NULL) + goto unknown; + } else - goto Suppress; - } - - /* Make demangled big enough for possible expansion by operator name. */ - grow_vect (&demangled, - &demangled_size, 2 * len0 + 1, - sizeof (char)); - - if (ISDIGIT ((unsigned char) mangled[len0 - 1])) { - for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1) - ; - if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_') - { - len0 = i - 1; - changed = 1; - } - else if (mangled[i] == '$') - { - len0 = i; - changed = 1; - } - } - - for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]); - i += 1, j += 1) - demangled[j] = mangled[i]; - - while (i < len0) - { - if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_') - { - demangled[j] = '.'; - changed = 1; - i += 2; j += 1; - } + { + /* Not a GNAT encoding. */ + goto unknown; + } + + /* The name can be directly followed by some uppercase letters. */ + if (p[0] == 'T' && p[1] == 'K') + { + /* Task stuff. */ + if (p[2] == 'B' && p[3] == 0) + { + /* Subprogram for task body. */ + break; + } + else if (p[2] == '_' && p[3] == '_') + { + /* Inner declarations in a task. */ + p += 4; + *d++ = '.'; + continue; + } + else + goto unknown; + } + if (p[0] == 'E' && p[1] == 0) + { + /* Exception name. */ + goto unknown; + } + if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0) + { + /* Protected type subprogram. */ + break; + } + if ((*p == 'N' || *p == 'S') && p[1] == 0) + { + /* Enumerated type name table. */ + goto unknown; + } + if (p[0] == 'X') + { + /* Body nested. */ + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0)) + { + /* Stream operations. */ + const char *name; + switch (p[1]) + { + case 'R': + name = "'Read"; + break; + case 'W': + name = "'Write"; + break; + case 'I': + name = "'Input"; + break; + case 'O': + name = "'Output"; + break; + default: + goto unknown; + } + p += 2; + strcpy (d, name); + d += strlen (name); + } + else if (p[0] == 'D') + { + /* Controlled type operation. */ + const char *name; + switch (p[1]) + { + case 'F': + name = ".Finalize"; + break; + case 'A': + name = ".Adjust"; + break; + default: + goto unknown; + } + strcpy (d, name); + d += strlen (name); + break; + } + + if (p[0] == '_') + { + /* Separator. */ + if (p[1] == '_') + { + /* Standard separator. Handled first. */ + p += 2; + + if (ISDIGIT (*p)) + { + /* Overloading number. */ + do + p++; + while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1]))); + if (*p == 'X') + { + p++; + while (p[0] == 'n' || p[0] == 'b') + p++; + } + } + else if (p[0] == '_' && p[1] != '_') + { + /* Special names. */ + static const char * const special[][2] = { + { "_elabb", "'Elab_Body" }, + { "_elabs", "'Elab_Spec" }, + { "_size", "'Size" }, + { "_alignment", "'Alignment" }, + { "_assign", ".\":=\"" }, + { NULL, NULL } + }; + int k; + + for (k = 0; special[k][0] != NULL; k++) + { + size_t slen = strlen (special[k][0]); + if (strncmp (p, special[k][0], slen) == 0) + { + p += slen; + slen = strlen (special[k][1]); + memcpy (d, special[k][1], slen); + d += slen; + break; + } + } + if (special[k][0] != NULL) + break; + else + goto unknown; + } + else + { + *d++ = '.'; + continue; + } + } + else if (p[1] == 'B' || p[1] == 'E') + { + /* Entry Body or barrier Evaluation. */ + p += 2; + while (ISDIGIT (*p)) + p++; + if (p[0] == 's' && p[1] == 0) + break; + else + goto unknown; + } + else + goto unknown; + } + + if (p[0] == '.' && ISDIGIT (p[1])) + { + /* Nested subprogram. */ + p += 2; + while (ISDIGIT (*p)) + p++; + } + if (*p == 0) + { + /* End of mangled name. */ + break; + } else - { - demangled[j] = mangled[i]; - i += 1; j += 1; - } + goto unknown; } - demangled[j] = '\000'; - - for (i = 0; demangled[i] != '\0'; i += 1) - if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ') - goto Suppress; + *d = 0; + return demangled; - if (! changed) - return NULL; - else - return demangled; - - Suppress: - grow_vect (&demangled, - &demangled_size, strlen (mangled) + 3, - sizeof (char)); + unknown: + len0 = strlen (mangled); + demangled = XNEWVEC (char, len0 + 3); if (mangled[0] == '<') strcpy (demangled, mangled); @@ -1190,8 +1328,7 @@ delete_non_B_K_work_stuff (struct work_stuff *work) int i; for (i = 0; i < work->ntmpl_args; i++) - if (work->tmpl_argvec[i]) - free ((char*) work->tmpl_argvec[i]); + free ((char*) work->tmpl_argvec[i]); free ((char*) work->tmpl_argvec); work->tmpl_argvec = NULL; diff --git a/coregrind/m_demangle/demangle.c b/coregrind/m_demangle/demangle.c index 5b5b422f7b..1a57bacaab 100644 --- a/coregrind/m_demangle/demangle.c +++ b/coregrind/m_demangle/demangle.c @@ -75,13 +75,13 @@ impedance-match the libiberty code into our own framework. The current code is from libiberty in the gcc tree, gcc svn - r141363, dated 26 Oct 2008 (when the gcc trunk was in Stage 3 - leading up to a gcc-4.4 release). As of r141363, libiberty is LGPL + r181975, dated 12 Dec 2011 (when the gcc trunk was in Stage 3 + leading up to a gcc-4.7 release). As of r141363, libiberty is LGPL 2.1, which AFAICT is compatible with "GPL 2 or later" and so is OK for inclusion in Valgrind. To update to a newer libiberty, it might be simplest to svn diff - the gcc tree libibery against r141363 and then apply those diffs + the gcc tree libibery against r181975 and then apply those diffs here. */ /* This is the main, standard demangler entry point. */ diff --git a/coregrind/m_demangle/demangle.h b/coregrind/m_demangle/demangle.h index 145d9fdf1f..c0215a1820 100644 --- a/coregrind/m_demangle/demangle.h +++ b/coregrind/m_demangle/demangle.h @@ -1,6 +1,6 @@ /* Defs for interface to demanglers. Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, - 2003, 2004, 2005, 2007 Free Software Foundation, Inc. + 2003, 2004, 2005, 2007, 2008, 2009, 2010 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 @@ -47,7 +47,13 @@ extern "C" { #define DMGL_VERBOSE (1 << 3) /* Include implementation details. */ #define DMGL_TYPES (1 << 4) /* Also try to demangle type encodings. */ #define DMGL_RET_POSTFIX (1 << 5) /* Print function return types (when - present) after function signature */ + present) after function signature. + It applies only to the toplevel + function type. */ +#define DMGL_RET_DROP (1 << 6) /* Suppress printing function return + types, even if present. It applies + only to the toplevel function type. + */ #define DMGL_AUTO (1 << 8) #define DMGL_GNU (1 << 9) @@ -162,10 +168,14 @@ java_demangle_v3_callback (const char *mangled, extern char* java_demangle_v3 (const char *mangled); +char * +ada_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 + gnu_v3_complete_object_allocating_ctor, + gnu_v3_object_ctor_group }; /* Return non-zero iff NAME is the mangled form of a constructor name @@ -179,7 +189,8 @@ extern enum gnu_v3_ctor_kinds enum gnu_v3_dtor_kinds { gnu_v3_deleting_dtor = 1, gnu_v3_complete_object_dtor, - gnu_v3_base_object_dtor + gnu_v3_base_object_dtor, + gnu_v3_object_dtor_group }; /* Return non-zero iff NAME is the mangled form of a destructor name @@ -223,6 +234,8 @@ enum demangle_component_type /* A template parameter. This holds a number, which is the template parameter index. */ DEMANGLE_COMPONENT_TEMPLATE_PARAM, + /* A function parameter. This holds a number, which is the index. */ + DEMANGLE_COMPONENT_FUNCTION_PARAM, /* A constructor. This holds a name and the kind of constructor. */ DEMANGLE_COMPONENT_CTOR, @@ -321,6 +334,11 @@ enum demangle_component_type and the right subtree is the member type. CV-qualifiers appear on the latter. */ DEMANGLE_COMPONENT_PTRMEM_TYPE, + /* A fixed-point type. */ + DEMANGLE_COMPONENT_FIXED_TYPE, + /* A vector type. The left subtree is the number of elements, + the right subtree is the element type. */ + DEMANGLE_COMPONENT_VECTOR_TYPE, /* An argument list. The left subtree is the current argument, and the right subtree is either NULL or another ARGLIST node. */ DEMANGLE_COMPONENT_ARGLIST, @@ -373,10 +391,31 @@ enum demangle_component_type DEMANGLE_COMPONENT_COMPOUND_NAME, /* A name formed by a single character. */ DEMANGLE_COMPONENT_CHARACTER, + /* A number. */ + DEMANGLE_COMPONENT_NUMBER, /* A decltype type. */ DEMANGLE_COMPONENT_DECLTYPE, + /* Global constructors keyed to name. */ + DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS, + /* Global destructors keyed to name. */ + DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS, + /* A lambda closure type. */ + DEMANGLE_COMPONENT_LAMBDA, + /* A default argument scope. */ + DEMANGLE_COMPONENT_DEFAULT_ARG, + /* An unnamed type. */ + DEMANGLE_COMPONENT_UNNAMED_TYPE, + /* A transactional clone. This has one subtree, the encoding for + which it is providing alternative linkage. */ + DEMANGLE_COMPONENT_TRANSACTION_CLONE, + /* A non-transactional clone entry point. In the i386/x86_64 abi, + the unmangled symbol of a tm_callable becomes a thunk and the + non-transactional function version is mangled thus. */ + DEMANGLE_COMPONENT_NONTRANSACTION_CLONE, /* A pack expansion. */ - DEMANGLE_COMPONENT_PACK_EXPANSION + DEMANGLE_COMPONENT_PACK_EXPANSION, + /* A cloned function. */ + DEMANGLE_COMPONENT_CLONE }; /* Types which are only used internally. */ @@ -421,6 +460,17 @@ struct demangle_component struct demangle_component *name; } s_extended_operator; + /* For DEMANGLE_COMPONENT_FIXED_TYPE. */ + struct + { + /* The length, indicated by a C integer type name. */ + struct demangle_component *length; + /* _Accum or _Fract? */ + short accum; + /* Saturating or not? */ + short sat; + } s_fixed; + /* For DEMANGLE_COMPONENT_CTOR. */ struct { @@ -455,10 +505,10 @@ struct demangle_component int len; } s_string; - /* For DEMANGLE_COMPONENT_TEMPLATE_PARAM. */ + /* For DEMANGLE_COMPONENT_*_PARAM. */ struct { - /* Template parameter index. */ + /* Parameter index. */ long number; } s_number; @@ -477,6 +527,14 @@ struct demangle_component struct demangle_component *right; } s_binary; + struct + { + /* subtree, same place as d_left. */ + struct demangle_component *sub; + /* integer. */ + int num; + } s_unary_num; + } u; }; diff --git a/coregrind/m_demangle/dyn-string.c b/coregrind/m_demangle/dyn-string.c index 70449dd03c..0dbb3ac889 100644 --- a/coregrind/m_demangle/dyn-string.c +++ b/coregrind/m_demangle/dyn-string.c @@ -349,7 +349,7 @@ dyn_string_append_cstr (dyn_string_t dest, const char *s) return 1; } -/* Appends C to the end of DEST. Returns 1 on success. On failiure, +/* Appends C to the end of DEST. Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */ int diff --git a/coregrind/m_demangle/dyn-string.h b/coregrind/m_demangle/dyn-string.h index 44e33deba3..2b147271e5 100644 --- a/coregrind/m_demangle/dyn-string.h +++ b/coregrind/m_demangle/dyn-string.h @@ -1,5 +1,6 @@ /* An abstract string datatype. - Copyright (C) 1998, 1999, 2000, 2002, 2004 Free Software Foundation, Inc. + Copyright (C) 1998, 1999, 2000, 2002, 2004, 2005, 2009 + Free Software Foundation, Inc. Contributed by Mark Mitchell (mark@markmitchell.com). This file is part of GCC. @@ -19,6 +20,12 @@ along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#ifndef DYN_STRING_H +#define DYN_STRING_H + +#ifdef __cplusplus +extern "C" { +#endif typedef struct dyn_string { @@ -58,3 +65,9 @@ extern int dyn_string_append_cstr (dyn_string_t, const char *); extern int dyn_string_append_char (dyn_string_t, int); extern int dyn_string_substring (dyn_string_t, dyn_string_t, int, int); extern int dyn_string_eq (dyn_string_t, dyn_string_t); + +#ifdef __cplusplus +} +#endif + +#endif /* !defined (DYN_STRING_H) */