From: Phil Blundell Date: Mon, 23 Oct 2000 09:43:14 +0000 (+0000) Subject: Merge from mainline. X-Git-Tag: binutils-2_10_1~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9350a5a9862e400446da0c9605a33867f6bc36c6;p=thirdparty%2Fbinutils-gdb.git Merge from mainline. --- diff --git a/include/ChangeLog b/include/ChangeLog index 4408899df90..a41d5b1793c 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2000-10-23 Philip Blundell + + * demangle.h, dyn-string.h: Update from trunk version. + 2000-05-26 Eli Zaretskii * filenames.h: New file. diff --git a/include/demangle.h b/include/demangle.h index 63fe5e2adf4..61dd23071a4 100644 --- a/include/demangle.h +++ b/include/demangle.h @@ -24,21 +24,23 @@ /* Options passed to cplus_demangle (in 2nd parameter). */ -#define DMGL_NO_OPTS 0 /* For readability... */ -#define DMGL_PARAMS (1 << 0) /* Include function args */ -#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ -#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ - -#define DMGL_AUTO (1 << 8) -#define DMGL_GNU (1 << 9) -#define DMGL_LUCID (1 << 10) -#define DMGL_ARM (1 << 11) -#define DMGL_HP (1 << 12) /* For the HP aCC compiler; same as ARM - except for template arguments, etc. */ -#define DMGL_EDG (1 << 13) +#define DMGL_NO_OPTS 0 /* For readability... */ +#define DMGL_PARAMS (1 << 0) /* Include function args */ +#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ +#define DMGL_JAVA (1 << 2) /* Demangle as Java rather than C++. */ + +#define DMGL_AUTO (1 << 8) +#define DMGL_GNU (1 << 9) +#define DMGL_LUCID (1 << 10) +#define DMGL_ARM (1 << 11) +#define DMGL_HP (1 << 12) /* For the HP aCC compiler; + same as ARM except for + template arguments, etc. */ +#define DMGL_EDG (1 << 13) +#define DMGL_GNU_NEW_ABI (1 << 14) /* 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) +#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_NEW_ABI) /* Enumeration of possible demangling styles. @@ -56,17 +58,19 @@ extern enum demangling_styles lucid_demangling = DMGL_LUCID, arm_demangling = DMGL_ARM, hp_demangling = DMGL_HP, - edg_demangling = DMGL_EDG + edg_demangling = DMGL_EDG, + gnu_new_abi_demangling = DMGL_GNU_NEW_ABI } current_demangling_style; /* Define string names for the various demangling styles. */ -#define AUTO_DEMANGLING_STYLE_STRING "auto" -#define GNU_DEMANGLING_STYLE_STRING "gnu" -#define LUCID_DEMANGLING_STYLE_STRING "lucid" -#define ARM_DEMANGLING_STYLE_STRING "arm" -#define HP_DEMANGLING_STYLE_STRING "hp" -#define EDG_DEMANGLING_STYLE_STRING "edg" +#define AUTO_DEMANGLING_STYLE_STRING "auto" +#define GNU_DEMANGLING_STYLE_STRING "gnu" +#define LUCID_DEMANGLING_STYLE_STRING "lucid" +#define ARM_DEMANGLING_STYLE_STRING "arm" +#define HP_DEMANGLING_STYLE_STRING "hp" +#define EDG_DEMANGLING_STYLE_STRING "edg" +#define GNU_NEW_ABI_DEMANGLING_STYLE_STRING "gnu-new-abi" /* Some macros to test what demangling style is active. */ @@ -77,6 +81,17 @@ extern enum demangling_styles #define ARM_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_ARM) #define HP_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_HP) #define EDG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_EDG) +#define GNU_NEW_ABI_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_NEW_ABI) + +/* Provide information about the available demangle styles. This code is + pulled from gdb into libiberty because it is useful to binutils also. */ + +extern struct demangler_engine +{ + const char *demangling_style_name; + enum demangling_styles demangling_style; + const char *demangling_style_doc; +} libiberty_demanglers[]; extern char * cplus_demangle PARAMS ((const char *mangled, int options)); @@ -92,4 +107,14 @@ cplus_mangle_opname PARAMS ((const char *opname, int options)); extern void set_cplus_marker_for_demangling PARAMS ((int ch)); +extern enum demangling_styles +cplus_demangle_set_style PARAMS ((enum demangling_styles style)); + +extern enum demangling_styles +cplus_demangle_name_to_style PARAMS ((const char *name)); + +/* New-ABI demangling entry point, defined in cp-demangle.c. */ +extern char* +cplus_demangle_new_abi PARAMS ((const char* mangled)); + #endif /* DEMANGLE_H */ diff --git a/libiberty/ChangeLog b/libiberty/ChangeLog index c858409d301..dbd616b1a20 100644 --- a/libiberty/ChangeLog +++ b/libiberty/ChangeLog @@ -1,3 +1,16 @@ +2000-10-17 Philip Blundell + + * cp-demangle.c, dyn-string.c, cplus-dem.c: Update from trunk + version. + * testsuite/demangle-expected, testsuite/regress-demangle: + Likewise. + + From 2000-06-04 Alex Samuel + * Makefile.in (CFILES): Add cp-demangle.c and dyn-string.c. + (REQUIRED_OFILES): Add cp-demangle.o and dyn-string.o. + (cp-demangle.o): New dependency. + (dyn-string.o): Likewise. + Thu Mar 16 01:33:58 2000 Jeffrey A Law (law@cygnus.com) * Makefile.in (partition.o): Depend on config.h diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in index 9aa57f06d4b..5858a5072c0 100644 --- a/libiberty/Makefile.in +++ b/libiberty/Makefile.in @@ -1,6 +1,6 @@ # # Makefile -# Copyright (C) 1990, 91 - 99, 2000 +# Copyright (C) 1990, 91, 00 - 99, 2000 # Free Software Foundation # # This file is part of the libiberty library. @@ -124,7 +124,8 @@ HFILES = alloca-conf.h # (alphabetical), and add them to REQUIRED_OFILES or funcs in # configure.in. CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \ - bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c fdmatch.c \ + bzero.c calloc.c choose-temp.c clock.c concat.c cplus-dem.c \ + cp-demangle.c dyn-string.c fdmatch.c \ fnmatch.c getcwd.c getpwd.c getopt.c getopt1.c getpagesize.c \ getruntime.c floatformat.c hashtab.c hex.c index.c insque.c memchr.c \ memcmp.c memcpy.c memmove.c memset.c mkstemps.c objalloc.c obstack.c \ @@ -136,10 +137,10 @@ CFILES = asprintf.c alloca.c argv.c atexit.c basename.c bcmp.c bcopy.c \ xatexit.c xexit.c xmalloc.c xmemdup.c xstrdup.c xstrerror.c # These are always included in the library. -REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o \ - fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o hashtab.o \ - hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o spaces.o \ - splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \ +REQUIRED_OFILES = argv.o choose-temp.o concat.o cplus-dem.o cp-demangle.o \ + dyn-string.o fdmatch.o fnmatch.o getopt.o getopt1.o getpwd.o getruntime.o \ + hashtab.o hex.o floatformat.o objalloc.o obstack.o partition.o pexecute.o \ + spaces.o splay-tree.o strerror.o strsignal.o xatexit.o xexit.o xmalloc.o \ xmemdup.o xstrdup.o xstrerror.o $(TARGETLIB): $(REQUIRED_OFILES) $(EXTRA_OFILES) $(LIBOBJS) $(ALLOCA) @@ -259,6 +260,8 @@ choose-temp.o: config.h clock.o: config.h concat.o: $(INCDIR)/libiberty.h cplus-dem.o: config.h $(INCDIR)/demangle.h +cp-demangle.o: config.h $(INCDIR)/dyn-string.h $(INCDIR)/demangle.h +dyn-string.o: config.h $(INCDIR)/dyn-string.h fdmatch.o: $(INCDIR)/libiberty.h fnmatch.o: config.h $(INCDIR)/fnmatch.h getcwd.o: config.h diff --git a/libiberty/cp-demangle.c b/libiberty/cp-demangle.c index e543edfd766..1eb24027e51 100644 --- a/libiberty/cp-demangle.c +++ b/libiberty/cp-demangle.c @@ -1,9 +1,7 @@ /* Demangler for IA64 / g++ standard C++ ABI. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000 CodeSourcery LLC. Written by Alex Samuel . - This file is part of GNU CC. - This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -23,8 +21,7 @@ the IA64 / g++ standard C++ ABI. Use the cp_demangle function to demangle a mangled name, or compile with the preprocessor macro STANDALONE_DEMANGLER defined to create a demangling filter - executable (functionally similar to c++filt, but includes this - demangler only). */ + executable. */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -64,10 +61,6 @@ (((CHAR) >= 'a' && (CHAR) <= 'z') \ || ((CHAR) >= 'A' && (CHAR) <= 'Z')) -/* The prefix prepended by GCC to an identifier represnting the - anonymous namespace. */ -#define ANONYMOUS_NAMESPACE_PREFIX "_GLOBAL_" - /* If flag_verbose is zero, some simplifications will be made to the output to make it easier to read and supress details that are generally not of interest to the average C++ programmer. @@ -98,10 +91,17 @@ struct substitution_def /* The demangled text of the substitution. */ dyn_string_t text; + /* The template parameter that this represents, indexed from zero. + If this is not a template paramter number, the value is + NOT_TEMPLATE_PARM. */ + int template_parm_number; + /* Whether this substitution represents a template item. */ int template_p : 1; }; +#define NOT_TEMPLATE_PARM (-1) + /* Data structure representing a template argument list. */ struct template_arg_list_def @@ -172,7 +172,7 @@ typedef const char *status_t; #define STATUS_INTERNAL_ERROR "Internal error." /* This status code indicates a failure in malloc or realloc. */ -static const char *const status_allocation_failed = "Allocation failed."; +static const char* const status_allocation_failed = "Allocation failed."; #define STATUS_ALLOCATION_FAILED status_allocation_failed /* Non-zero if STATUS indicates that no error has occurred. */ @@ -196,8 +196,8 @@ static string_list_t string_list_new PARAMS ((int)); static void string_list_delete PARAMS ((string_list_t)); -static status_t result_add_separated_char - PARAMS ((demangling_t, int)); +static status_t result_close_template_list + PARAMS ((demangling_t)); static status_t result_push PARAMS ((demangling_t)); static string_list_t result_pop @@ -205,7 +205,7 @@ static string_list_t result_pop static int substitution_start PARAMS ((demangling_t)); static status_t substitution_add - PARAMS ((demangling_t, int, int)); + PARAMS ((demangling_t, int, int, int)); static dyn_string_t substitution_get PARAMS ((demangling_t, int, int *)); #ifdef CP_DEMANGLE_DEBUG @@ -287,22 +287,6 @@ static void demangling_delete (dyn_string_append_char (&(DM)->result->string, (CHAR)) \ ? STATUS_OK : STATUS_ALLOCATION_FAILED) -/* Inserts a dyn_string_t to the demangled result at position POS. */ -#define result_insert_string(DM, POS, STRING) \ - (dyn_string_insert (&(DM)->result->string, (POS), (STRING)) \ - ? STATUS_OK : STATUS_ALLOCATION_FAILED) - -/* Inserts NUL-terminated string CSTR to the demangled result at - position POS. */ -#define result_insert(DM, POS, CSTR) \ - (dyn_string_insert_cstr (&(DM)->result->string, (POS), (CSTR)) \ - ? STATUS_OK : STATUS_ALLOCATION_FAILED) - -/* Inserts character CHAR to the demangled result at position POS. */ -#define result_insert_char(DM, POS, CHAR) \ - (dyn_string_insert_char (&(DM)->result->string, (POS), (CHAR)) \ - ? STATUS_OK : STATUS_ALLOCATION_FAILED) - /* The length of the current demangled result. */ #define result_length(DM) \ dyn_string_length (&(DM)->result->string) @@ -313,13 +297,6 @@ static void demangling_delete (dyn_string_append_space (&(DM)->result->string) \ ? STATUS_OK : STATUS_ALLOCATION_FAILED) -/* Appends a (less-than, greater-than) character to the result in DM - to (open, close) a template argument or parameter list. Appends a - space first if necessary to prevent spurious elision of angle - brackets with the previous character. */ -#define result_open_template_list(DM) result_add_separated_char(DM, '<') -#define result_close_template_list(DM) result_add_separated_char(DM, '>') - /* Appends a base 10 representation of VALUE to DS. STATUS_OK on success. On failure, deletes DS and returns an error code. */ @@ -401,27 +378,28 @@ string_list_delete (node) } } -/* Appends CHARACTER to the demangled result. If the current trailing - character of the result is CHARACTER, a space is inserted first. */ +/* Appends a greater-than character to the demangled result. If the + last character is a greater-than character, a space is inserted + first, so that the two greater-than characters don't look like a + right shift token. */ static status_t -result_add_separated_char (dm, character) +result_close_template_list (dm) demangling_t dm; - int character; { dyn_string_t s = &dm->result->string; /* Add a space if the last character is already a closing angle bracket, so that a nested template arg list doesn't look like it's closed with a right-shift operator. */ - if (dyn_string_last_char (s) == character) + if (dyn_string_last_char (s) == '>') { if (!dyn_string_append_char (s, ' ')) return STATUS_ALLOCATION_FAILED; } /* Add closing angle brackets. */ - if (!dyn_string_append_char (s, character)) + if (!dyn_string_append_char (s, '>')) return STATUS_ALLOCATION_FAILED; return STATUS_OK; @@ -473,13 +451,19 @@ substitution_start (dm) /* Adds the suffix of the current demangled result of DM starting at START_POSITION as a potential substitution. If TEMPLATE_P is - non-zero, this potential substitution is a template-id. */ + non-zero, this potential substitution is a template-id. + + If TEMPLATE_PARM_NUMBER is not NOT_TEMPLATE_PARM, the substitution + is for that particular , and is distinct from other + otherwise-identical types and other s with + different indices. */ static status_t -substitution_add (dm, start_position, template_p) +substitution_add (dm, start_position, template_p, template_parm_number) demangling_t dm; int start_position; int template_p; + int template_parm_number; { dyn_string_t result = result_string (dm); dyn_string_t substitution = dyn_string_new (0); @@ -497,14 +481,23 @@ substitution_add (dm, start_position, template_p) return STATUS_ALLOCATION_FAILED; } + /* Check whether SUBSTITUTION already occurs. */ + for (i = 0; i < dm->num_substitutions; ++i) + if (dyn_string_eq (dm->substitutions[i].text, substitution) + && dm->substitutions[i].template_parm_number == template_parm_number) + /* Found SUBSTITUTION already present. */ + { + /* Callers expect this function to take ownership of + SUBSTITUTION, so delete it. */ + dyn_string_delete (substitution); + return STATUS_OK; + } + /* If there's no room for the new entry, grow the array. */ if (dm->substitutions_allocated == dm->num_substitutions) { size_t new_array_size; - if (dm->substitutions_allocated > 0) - dm->substitutions_allocated *= 2; - else - dm->substitutions_allocated = 2; + dm->substitutions_allocated *= 2; new_array_size = sizeof (struct substitution_def) * dm->substitutions_allocated; @@ -519,9 +512,10 @@ substitution_add (dm, start_position, template_p) } /* Add the substitution to the array. */ - i = dm->num_substitutions++; dm->substitutions[i].text = substitution; dm->substitutions[i].template_p = template_p; + dm->substitutions[i].template_parm_number = template_parm_number; + ++dm->num_substitutions; #ifdef CP_DEMANGLE_DEBUG substitutions_print (dm, stderr); @@ -807,7 +801,7 @@ static status_t demangle_nested_name static status_t demangle_prefix PARAMS ((demangling_t, int *)); static status_t demangle_unqualified_name - PARAMS ((demangling_t, int *)); + PARAMS ((demangling_t)); static status_t demangle_source_name PARAMS ((demangling_t)); static status_t demangle_number @@ -818,18 +812,12 @@ static status_t demangle_identifier PARAMS ((demangling_t, int, dyn_string_t)); static status_t demangle_operator_name PARAMS ((demangling_t, int, int *)); -static status_t demangle_nv_offset - PARAMS ((demangling_t)); -static status_t demangle_v_offset - PARAMS ((demangling_t)); -static status_t demangle_call_offset - PARAMS ((demangling_t)); static status_t demangle_special_name PARAMS ((demangling_t)); static status_t demangle_ctor_dtor_name PARAMS ((demangling_t)); static status_t demangle_type_ptr - PARAMS ((demangling_t, int *, int)); + PARAMS ((demangling_t)); static status_t demangle_type PARAMS ((demangling_t)); static status_t demangle_CV_qualifiers @@ -837,15 +825,15 @@ static status_t demangle_CV_qualifiers static status_t demangle_builtin_type PARAMS ((demangling_t)); static status_t demangle_function_type - PARAMS ((demangling_t, int *)); + PARAMS ((demangling_t, int)); static status_t demangle_bare_function_type - PARAMS ((demangling_t, int *)); + PARAMS ((demangling_t, int)); static status_t demangle_class_enum_type PARAMS ((demangling_t, int *)); static status_t demangle_array_type PARAMS ((demangling_t)); static status_t demangle_template_param - PARAMS ((demangling_t)); + PARAMS ((demangling_t, int *)); static status_t demangle_template_args PARAMS ((demangling_t)); static status_t demangle_literal @@ -859,21 +847,19 @@ static status_t demangle_scope_expression static status_t demangle_expr_primary PARAMS ((demangling_t)); static status_t demangle_substitution - PARAMS ((demangling_t, int *)); + PARAMS ((demangling_t, int *, int *)); static status_t demangle_local_name PARAMS ((demangling_t)); static status_t demangle_discriminator PARAMS ((demangling_t, int)); static status_t cp_demangle PARAMS ((const char *, dyn_string_t)); -#ifdef IN_LIBGCC2 static status_t cp_demangle_type PARAMS ((const char*, dyn_string_t)); -#endif /* When passed to demangle_bare_function_type, indicates that the function's return type is not encoded before its parameter types. */ -#define BFT_NO_RETURN_TYPE NULL +#define BFT_NO_RETURN_TYPE -1 /* Check that the next character is C. If so, consume it. If not, return an error. */ @@ -924,7 +910,7 @@ static status_t demangle_encoding (dm) demangling_t dm; { - int encode_return_type; + int template_p; int start_position; template_arg_list_t old_arg_list = current_template_arg_list (dm); char peek = peek_char (dm); @@ -940,18 +926,18 @@ demangle_encoding (dm) else { /* Now demangle the name. */ - RETURN_IF_ERROR (demangle_name (dm, &encode_return_type)); + RETURN_IF_ERROR (demangle_name (dm, &template_p)); /* If there's anything left, the name was a function name, with maybe its return type, and its parameters types, following. */ if (!end_of_name_p (dm) && peek_char (dm) != 'E') { - if (encode_return_type) + if (template_p) /* Template functions have their return type encoded. The return type should be inserted at start_position. */ RETURN_IF_ERROR - (demangle_bare_function_type (dm, &start_position)); + (demangle_bare_function_type (dm, start_position)); else /* Non-template functions don't have their return type encoded. */ @@ -982,32 +968,24 @@ demangle_encoding (dm) ::= */ static status_t -demangle_name (dm, encode_return_type) +demangle_name (dm, template_p) demangling_t dm; - int *encode_return_type; + int *template_p; { + int special_std_substitution; int start = substitution_start (dm); - char peek = peek_char (dm); - int is_std_substitution = 0; - - /* Generally, the return type is encoded if the function is a - template-id, and suppressed otherwise. There are a few cases, - though, in which the return type is not encoded even for a - templated function. In these cases, this flag is set. */ - int suppress_return_type = 0; DEMANGLE_TRACE ("name", dm); - switch (peek) + switch (peek_char (dm)) { case 'N': /* This is a . */ - RETURN_IF_ERROR (demangle_nested_name (dm, encode_return_type)); + RETURN_IF_ERROR (demangle_nested_name (dm, template_p)); break; case 'Z': RETURN_IF_ERROR (demangle_local_name (dm)); - *encode_return_type = 0; break; case 'S': @@ -1018,45 +996,48 @@ demangle_name (dm, encode_return_type) (void) next_char (dm); (void) next_char (dm); RETURN_IF_ERROR (result_append (dm, "std::")); - RETURN_IF_ERROR - (demangle_unqualified_name (dm, &suppress_return_type)); - is_std_substitution = 1; + RETURN_IF_ERROR (demangle_unqualified_name (dm)); } else - RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type)); + { + RETURN_IF_ERROR (demangle_substitution (dm, template_p, + &special_std_substitution)); + if (special_std_substitution) + { + /* This was the magic `std::' substitution. We can have + a or one of the unscoped names + following. */ + RETURN_IF_ERROR (result_append (dm, "::")); + RETURN_IF_ERROR (demangle_name (dm, template_p)); + } + } /* Check if a template argument list immediately follows. If so, then we just demangled an . */ if (peek_char (dm) == 'I') { - /* A template name of the form std:: is a - substitution candidate. */ - if (is_std_substitution) - RETURN_IF_ERROR (substitution_add (dm, start, 0)); - /* Demangle the here. */ + RETURN_IF_ERROR (substitution_add (dm, start, 0, + NOT_TEMPLATE_PARM)); RETURN_IF_ERROR (demangle_template_args (dm)); - *encode_return_type = !suppress_return_type; } - else - *encode_return_type = 0; - break; default: /* This is an or . */ - RETURN_IF_ERROR (demangle_unqualified_name (dm, &suppress_return_type)); + RETURN_IF_ERROR (demangle_unqualified_name (dm)); /* If the is followed by template args, this is an . */ if (peek_char (dm) == 'I') { /* Add a substitution for the unqualified template name. */ - RETURN_IF_ERROR (substitution_add (dm, start, 0)); + RETURN_IF_ERROR (substitution_add (dm, start, 0, + NOT_TEMPLATE_PARM)); RETURN_IF_ERROR (demangle_template_args (dm)); - *encode_return_type = !suppress_return_type; + *template_p = 1; } else - *encode_return_type = 0; + *template_p = 0; break; } @@ -1066,12 +1047,12 @@ demangle_name (dm, encode_return_type) /* Demangles and emits a . - ::= N [] E */ + ::= N [] E */ static status_t -demangle_nested_name (dm, encode_return_type) +demangle_nested_name (dm, template_p) demangling_t dm; - int *encode_return_type; + int *template_p; { char peek; @@ -1096,9 +1077,9 @@ demangle_nested_name (dm, encode_return_type) RETURN_IF_ERROR (result_append_space (dm)); } - RETURN_IF_ERROR (demangle_prefix (dm, encode_return_type)); - /* No need to demangle the final ; demangle_prefix - will handle it. */ + RETURN_IF_ERROR (demangle_prefix (dm, template_p)); + /* No need to demangle the final ; demangle_prefix will + handle it. */ RETURN_IF_ERROR (demangle_char (dm, 'E')); return STATUS_OK; @@ -1106,52 +1087,41 @@ demangle_nested_name (dm, encode_return_type) /* Demangles and emits a . - ::= + ::= ::= ::= # empty ::= ::= - ::= */ + ::= + + ::= + ::= */ static status_t -demangle_prefix (dm, encode_return_type) +demangle_prefix (dm, template_p) demangling_t dm; - int *encode_return_type; + int *template_p; { int start = substitution_start (dm); int nested = 0; - /* ENCODE_RETURN_TYPE is updated as we decend the nesting chain. - After , it is set to non-zero; after everything - else it is set to zero. */ - - /* Generally, the return type is encoded if the function is a - template-id, and suppressed otherwise. There are a few cases, - though, in which the return type is not encoded even for a - templated function. In these cases, this flag is set. */ - int suppress_return_type = 0; + /* TEMPLATE_P is updated as we decend the nesting chain. After + , it is set to non-zero; after everything else it + is set to zero. */ DEMANGLE_TRACE ("prefix", dm); while (1) { char peek; + int unused; if (end_of_name_p (dm)) return "Unexpected end of name in ."; peek = peek_char (dm); - /* We'll initialize suppress_return_type to false, and set it to true - if we end up demangling a constructor name. However, make - sure we're not actually about to demangle template arguments - -- if so, this is the following a - , so we'll want the previous flag value - around. */ - if (peek != 'I') - suppress_return_type = 0; - if (IS_DIGIT ((unsigned char) peek) || (peek >= 'a' && peek <= 'z') || peek == 'C' || peek == 'D' @@ -1165,30 +1135,25 @@ demangle_prefix (dm, encode_return_type) if (peek == 'S') /* The substitution determines whether this is a - template-id. */ - RETURN_IF_ERROR (demangle_substitution (dm, encode_return_type)); + template-id. */ + RETURN_IF_ERROR (demangle_substitution (dm, template_p, + &unused)); else { - /* It's just a name. */ - RETURN_IF_ERROR - (demangle_unqualified_name (dm, &suppress_return_type)); - *encode_return_type = 0; + RETURN_IF_ERROR (demangle_unqualified_name (dm)); + *template_p = 0; } } else if (peek == 'Z') RETURN_IF_ERROR (demangle_local_name (dm)); else if (peek == 'I') { + if (*template_p) + return STATUS_INTERNAL_ERROR; + /* The template name is a substitution candidate. */ + RETURN_IF_ERROR (substitution_add (dm, start, 0, NOT_TEMPLATE_PARM)); RETURN_IF_ERROR (demangle_template_args (dm)); - - /* Now we want to indicate to the caller that we've - demangled template arguments, thus the prefix was a - . That's so that the caller knows to - demangle the function's return type, if this turns out to - be a function name. But, if it's a member template - constructor or a templated conversion operator, report it - as untemplated. Those never get encoded return types. */ - *encode_return_type = !suppress_return_type; + *template_p = 1; } else if (peek == 'E') /* All done. */ @@ -1196,56 +1161,38 @@ demangle_prefix (dm, encode_return_type) else return "Unexpected character in ."; - if (peek != 'S' - && peek_char (dm) != 'E') - /* Add a new substitution for the prefix thus far. */ - RETURN_IF_ERROR (substitution_add (dm, start, *encode_return_type)); + /* Add a new substitution for the prefix thus far. */ + RETURN_IF_ERROR (substitution_add (dm, start, *template_p, + NOT_TEMPLATE_PARM)); } } -/* Demangles and emits an . If this - is for a special function type that should never - have its return type encoded (particularly, a constructor or - conversion operator), *SUPPRESS_RETURN_TYPE is set to 1; otherwise, - it is set to zero. +/* Demangles and emits an . If the + is a function and the first element in the + argument list should be taken to be its return type, + ENCODE_RETURN_TYPE is non-zero. ::= ::= ::= */ static status_t -demangle_unqualified_name (dm, suppress_return_type) +demangle_unqualified_name (dm) demangling_t dm; - int *suppress_return_type; { char peek = peek_char (dm); DEMANGLE_TRACE ("unqualified-name", dm); - /* By default, don't force suppression of the return type (though - non-template functions still don't get a return type encoded). */ - *suppress_return_type = 0; - if (IS_DIGIT ((unsigned char) peek)) RETURN_IF_ERROR (demangle_source_name (dm)); else if (peek >= 'a' && peek <= 'z') { int num_args; - - /* Conversion operators never have a return type encoded. */ - if (peek == 'c' && peek_char_next (dm) == 'v') - *suppress_return_type = 1; - RETURN_IF_ERROR (demangle_operator_name (dm, 0, &num_args)); } else if (peek == 'C' || peek == 'D') - { - /* Constructors never have a return type encoded. */ - if (peek == 'C') - *suppress_return_type = 1; - - RETURN_IF_ERROR (demangle_ctor_dtor_name (dm)); - } + RETURN_IF_ERROR (demangle_ctor_dtor_name (dm)); else return "Unexpected character in ."; @@ -1383,29 +1330,6 @@ demangle_identifier (dm, length, identifier) return STATUS_ALLOCATION_FAILED; } - /* GCC encodes anonymous namespaces using a `_GLOBAL_[_.$]N.' - followed by the source file name and some random characters. - Unless we're in strict mode, decipher these names appropriately. */ - if (!flag_strict) - { - char *name = dyn_string_buf (identifier); - int prefix_length = strlen (ANONYMOUS_NAMESPACE_PREFIX); - - /* Compare the first, fixed part. */ - if (strncmp (name, ANONYMOUS_NAMESPACE_PREFIX, prefix_length) == 0) - { - name += prefix_length; - /* The next character might be a period, an underscore, or - dollar sign, depending on the target architecture's - assembler's capabilities. After that comes an `N'. */ - if ((*name == '.' || *name == '_' || *name == '$') - && *(name + 1) == 'N') - /* This looks like the anonymous namespace identifier. - Replace it with something comprehensible. */ - dyn_string_copy_cstr (identifier, "(anonymous namespace)"); - } - } - return STATUS_OK; } @@ -1464,7 +1388,7 @@ demangle_identifier (dm, length, identifier) ::= qu # ? ::= sz # sizeof ::= cv # cast - ::= v [0-9] # vendor extended operator */ + ::= vx # vendor extended operator */ static status_t demangle_operator_name (dm, short_name, num_args) @@ -1525,7 +1449,6 @@ demangle_operator_name (dm, short_name, num_args) { "pm", "->*" , 2 }, { "pp", "++" , 1 }, { "ps", "+" , 1 }, - { "pt", "->" , 2 }, { "qu", "?" , 3 }, { "rM", "%=" , 2 }, { "rS", ">>=" , 2 }, @@ -1544,10 +1467,10 @@ demangle_operator_name (dm, short_name, num_args) DEMANGLE_TRACE ("operator-name", dm); - /* Is this a vendor-extended operator? */ - if (c0 == 'v' && IS_DIGIT (c1)) + /* Is this a vendor extended operator? */ + if (c0 == 'v' && c1 == 'x') { - RETURN_IF_ERROR (result_append (dm, "operator ")); + RETURN_IF_ERROR (result_append (dm, "operator")); RETURN_IF_ERROR (demangle_source_name (dm)); *num_args = 0; return STATUS_OK; @@ -1593,157 +1516,22 @@ demangle_operator_name (dm, short_name, num_args) } } -/* Demangles and omits an . - - ::= # non-virtual base override */ - -static status_t -demangle_nv_offset (dm) - demangling_t dm; -{ - dyn_string_t number; - status_t status = STATUS_OK; - - DEMANGLE_TRACE ("h-offset", dm); - - /* Demangle the offset. */ - number = dyn_string_new (4); - if (number == NULL) - return STATUS_ALLOCATION_FAILED; - demangle_number_literally (dm, number, 10, 1); - - /* Don't display the offset unless in verbose mode. */ - if (flag_verbose) - { - status = result_append (dm, " [nv:"); - if (STATUS_NO_ERROR (status)) - status = result_append_string (dm, number); - if (STATUS_NO_ERROR (status)) - status = result_append_char (dm, ']'); - } - - /* Clean up. */ - dyn_string_delete (number); - RETURN_IF_ERROR (status); - return STATUS_OK; -} - -/* Demangles and emits a . - - ::= _ - # virtual base override, with vcall offset */ - -static status_t -demangle_v_offset (dm) - demangling_t dm; -{ - dyn_string_t number; - status_t status = STATUS_OK; - - DEMANGLE_TRACE ("v-offset", dm); - - /* Demangle the offset. */ - number = dyn_string_new (4); - if (number == NULL) - return STATUS_ALLOCATION_FAILED; - demangle_number_literally (dm, number, 10, 1); - - /* Don't display the offset unless in verbose mode. */ - if (flag_verbose) - { - status = result_append (dm, " [v:"); - if (STATUS_NO_ERROR (status)) - status = result_append_string (dm, number); - if (STATUS_NO_ERROR (status)) - result_append_char (dm, ','); - } - dyn_string_delete (number); - RETURN_IF_ERROR (status); - - /* Demangle the separator. */ - RETURN_IF_ERROR (demangle_char (dm, '_')); - - /* Demangle the vcall offset. */ - number = dyn_string_new (4); - if (number == NULL) - return STATUS_ALLOCATION_FAILED; - demangle_number_literally (dm, number, 10, 1); - - /* Don't display the vcall offset unless in verbose mode. */ - if (flag_verbose) - { - status = result_append_string (dm, number); - if (STATUS_NO_ERROR (status)) - status = result_append_char (dm, ']'); - } - dyn_string_delete (number); - RETURN_IF_ERROR (status); - - return STATUS_OK; -} - -/* Demangles and emits a . - - ::= h _ - ::= v _ */ - -static status_t -demangle_call_offset (dm) - demangling_t dm; -{ - DEMANGLE_TRACE ("call-offset", dm); - - switch (peek_char (dm)) - { - case 'h': - advance_char (dm); - /* Demangle the offset. */ - RETURN_IF_ERROR (demangle_nv_offset (dm)); - /* Demangle the separator. */ - RETURN_IF_ERROR (demangle_char (dm, '_')); - break; - - case 'v': - advance_char (dm); - /* Demangle the offset. */ - RETURN_IF_ERROR (demangle_v_offset (dm)); - /* Demangle the separator. */ - RETURN_IF_ERROR (demangle_char (dm, '_')); - break; - - default: - return "Unrecognized ."; - } - - return STATUS_OK; -} - /* Demangles and emits a . ::= GV # Guard variable + ::= Th[n] _ + # non-virtual base override thunk + ::= Tv[n] _ + _ + # virtual base override thunk ::= TV # virtual table ::= TT # VTT ::= TI # typeinfo structure ::= TS # typeinfo name - Other relevant productions include thunks: - - ::= T - # base is the nominal target function of thunk - - ::= Tc - # base is the nominal target function of thunk - # first call-offset is 'this' adjustment - # second call-offset is result adjustment - - where - - ::= h _ - ::= v _ - Also demangles the special g++ manglings, - ::= TC _ + ::= CT _ # construction vtable ::= TF # typeinfo function (old ABI only) ::= TJ # java Class structure */ @@ -1821,7 +1609,20 @@ demangle_special_name (dm) /* Non-virtual thunk. */ advance_char (dm); RETURN_IF_ERROR (result_append (dm, "non-virtual thunk")); - RETURN_IF_ERROR (demangle_nv_offset (dm)); + /* Demangle and emit the offset. */ + number = dyn_string_new (4); + if (number == NULL) + return STATUS_ALLOCATION_FAILED; + demangle_number_literally (dm, number, 10, 1); + /* Don't display the offset unless in verbose mode. */ + if (flag_verbose) + { + status = result_append_char (dm, ' '); + if (STATUS_NO_ERROR (status)) + status = result_append_string (dm, number); + } + dyn_string_delete (number); + RETURN_IF_ERROR (status); /* Demangle the separator. */ RETURN_IF_ERROR (demangle_char (dm, '_')); /* Demangle and emit the target name and function type. */ @@ -1832,23 +1633,41 @@ demangle_special_name (dm) case 'v': /* Virtual thunk. */ advance_char (dm); - RETURN_IF_ERROR (result_append (dm, "virtual thunk")); - RETURN_IF_ERROR (demangle_v_offset (dm)); + RETURN_IF_ERROR (result_append (dm, "virtual thunk ")); + /* Demangle and emit the offset. */ + number = dyn_string_new (4); + if (number == NULL) + return STATUS_ALLOCATION_FAILED; + demangle_number_literally (dm, number, 10, 1); + /* Don't display the offset unless in verbose mode. */ + if (flag_verbose) + { + status = result_append_string (dm, number); + if (STATUS_NO_ERROR (status)) + result_append_char (dm, ' '); + } + dyn_string_delete (number); + RETURN_IF_ERROR (status); + /* Demangle the separator. */ + RETURN_IF_ERROR (demangle_char (dm, '_')); + /* Demangle and emit the vcall offset. */ + number = dyn_string_new (4); + if (number == NULL) + return STATUS_ALLOCATION_FAILED; + demangle_number_literally (dm, number, 10, 1); + /* Don't display the vcall offset unless in verbose mode. */ + if (flag_verbose) + { + status = result_append_string (dm, number); + if (STATUS_NO_ERROR (status)) + status = result_append_char (dm, ' '); + } + dyn_string_delete (number); + RETURN_IF_ERROR (status); /* Demangle the separator. */ RETURN_IF_ERROR (demangle_char (dm, '_')); /* Demangle and emit the target function. */ - RETURN_IF_ERROR (result_append (dm, " to ")); - RETURN_IF_ERROR (demangle_encoding (dm)); - break; - - case 'c': - /* Covariant return thunk. */ - advance_char (dm); - RETURN_IF_ERROR (result_append (dm, "covariant return thunk")); - RETURN_IF_ERROR (demangle_call_offset (dm)); - RETURN_IF_ERROR (demangle_call_offset (dm)); - /* Demangle and emit the target function. */ - RETURN_IF_ERROR (result_append (dm, " to ")); + RETURN_IF_ERROR (result_append (dm, "to ")); RETURN_IF_ERROR (demangle_encoding (dm)); break; @@ -1917,6 +1736,7 @@ demangle_special_name (dm) ::= C1 # complete object (in-charge) ctor ::= C2 # base object (not-in-charge) ctor ::= C3 # complete object (in-charge) allocating ctor + ::= C4 # base object (not-in-charge) allocating ctor ::= D0 # deleting (in-charge) dtor ::= D1 # complete object (in-charge) dtor ::= D2 # base object (not-in-charge) dtor */ @@ -1929,7 +1749,8 @@ demangle_ctor_dtor_name (dm) { "in-charge", "not-in-charge", - "allocating" + "in-charge allocating", + "not-in-charge allocating" }; static const char *const dtor_flavors[] = { @@ -1947,7 +1768,7 @@ demangle_ctor_dtor_name (dm) { /* A constructor name. Consume the C. */ advance_char (dm); - if (peek_char (dm) < '1' || peek_char (dm) > '3') + if (peek_char (dm) < '1' || peek_char (dm) > '4') return "Unrecognized constructor."; RETURN_IF_ERROR (result_append_string (dm, dm->last_source_name)); /* Print the flavor of the constructor if in verbose mode. */ @@ -1989,19 +1810,6 @@ demangle_ctor_dtor_name (dm) a pointer to data or pointer to function to construct the right output syntax. C++'s pointer syntax is hairy. - This function adds substitution candidates for every nested - pointer/reference type it processes, including the outermost, final - type, assuming the substitution starts at SUBSTITUTION_START in the - demangling result. For example, if this function demangles - `PP3Foo', it will add a substitution for `Foo', `Foo*', and - `Foo**', in that order. - - *INSERT_POS is a quantity used internally, when this function calls - itself recursively, to figure out where to insert pointer - punctuation on the way up. On entry to this function, INSERT_POS - should point to a temporary value, but that value need not be - initialized. - ::= P ::= R ::= @@ -2009,137 +1817,105 @@ demangle_ctor_dtor_name (dm) ::= M */ static status_t -demangle_type_ptr (dm, insert_pos, substitution_start) +demangle_type_ptr (dm) demangling_t dm; - int *insert_pos; - int substitution_start; { char next; status_t status; - int is_substitution_candidate = 1; + + /* Collect pointer symbols into this string. */ + dyn_string_t symbols = dyn_string_new (10); DEMANGLE_TRACE ("type*", dm); + if (symbols == NULL) + return STATUS_ALLOCATION_FAILED; + /* Scan forward, collecting pointers and references into symbols, until we hit something else. Then emit the type. */ - next = peek_char (dm); - if (next == 'P') - { - /* A pointer. Snarf the `P'. */ - advance_char (dm); - /* Demangle the underlying type. */ - RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, - substitution_start)); - /* Insert an asterisk where we're told to; it doesn't - necessarily go at the end. */ - RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '*')); - /* The next (outermost) pointer or reference character should go - after this one. */ - ++(*insert_pos); - } - else if (next == 'R') - { - /* A reference. Snarf the `R'. */ - advance_char (dm); - /* Demangle the underlying type. */ - RETURN_IF_ERROR (demangle_type_ptr (dm, insert_pos, - substitution_start)); - /* Insert an ampersand where we're told to; it doesn't - necessarily go at the end. */ - RETURN_IF_ERROR (result_insert_char (dm, *insert_pos, '&')); - /* The next (outermost) pointer or reference character should go - after this one. */ - ++(*insert_pos); - } - else if (next == 'M') + while (1) { - /* A pointer-to-member. */ - dyn_string_t class_type; - - /* Eat the 'M'. */ - advance_char (dm); - - /* Capture the type of which this is a pointer-to-member. */ - RETURN_IF_ERROR (result_push (dm)); - RETURN_IF_ERROR (demangle_type (dm)); - class_type = (dyn_string_t) result_pop (dm); - - if (peek_char (dm) == 'F') - /* A pointer-to-member function. We want output along the - lines of `void (C::*) (int, int)'. Demangle the function - type, which would in this case give `void () (int, int)' - and set *insert_pos to the spot between the first - parentheses. */ - status = demangle_type_ptr (dm, insert_pos, substitution_start); - else - { - /* A pointer-to-member variable. Demangle the type of the - pointed-to member. */ + next = peek_char (dm); + if (next == 'P') + { + if (!dyn_string_append_char (symbols, '*')) + return STATUS_ALLOCATION_FAILED; + advance_char (dm); + } + else if (next == 'R') + { + if (!dyn_string_append_char (symbols, '&')) + return STATUS_ALLOCATION_FAILED; + advance_char (dm); + } + else if (next == 'M') + { + /* Pointer-to-member. */ + dyn_string_t class_type; + + /* Eat the 'M'. */ + advance_char (dm); + + /* Capture the type of which this is a pointer-to-member. */ + RETURN_IF_ERROR (result_push (dm)); + RETURN_IF_ERROR (demangle_type (dm)); + class_type = (dyn_string_t) result_pop (dm); + + /* Build the pointer-to-member notation. It comes before + other pointer and reference qualifiers -- */ + if (!dyn_string_prepend_cstr (symbols, "::*")) + return STATUS_ALLOCATION_FAILED; + if (!dyn_string_prepend (symbols, class_type)) + return STATUS_ALLOCATION_FAILED; + dyn_string_delete (class_type); + + if (peek_char (dm) == 'F') + continue; + + /* Demangle the type of the pointed-to member. */ status = demangle_type (dm); /* Make it pretty. */ if (STATUS_NO_ERROR (status)) status = result_append_space (dm); - /* The pointer-to-member notation (e.g. `C::*') follows the - member's type. */ - *insert_pos = result_length (dm); + /* Add the pointer-to-member syntax, and other pointer and + reference symbols. */ + if (STATUS_NO_ERROR (status)) + status = result_append_string (dm, symbols); + /* Clean up. */ + dyn_string_delete (symbols); + + RETURN_IF_ERROR (status); + return STATUS_OK; } + else if (next == 'F') + { + /* Ooh, tricky, a pointer-to-function. */ + int position = result_length (dm); + status = result_append_char (dm, '('); + if (STATUS_NO_ERROR (status)) + status = result_append_string (dm, symbols); + if (STATUS_NO_ERROR (status)) + status = result_append_char (dm, ')'); + dyn_string_delete (symbols); + RETURN_IF_ERROR (status); - /* Build the pointer-to-member notation. */ - if (STATUS_NO_ERROR (status)) - status = result_insert (dm, *insert_pos, "::*"); - if (STATUS_NO_ERROR (status)) - status = result_insert_string (dm, *insert_pos, class_type); - /* There may be additional levels of (pointer or reference) - indirection in this type. If so, the `*' and `&' should be - added after the pointer-to-member notation (e.g. `C::*&' for - a reference to a pointer-to-member of class C). */ - *insert_pos += dyn_string_length (class_type) + 3; + RETURN_IF_ERROR (demangle_function_type (dm, position)); + return STATUS_OK; + } + else + { + /* No more pointe or reference tokens. Finish up. */ + status = demangle_type (dm); - /* Clean up. */ - dyn_string_delete (class_type); + if (STATUS_NO_ERROR (status)) + status = result_append_string (dm, symbols); + dyn_string_delete (symbols); + RETURN_IF_ERROR (status); - RETURN_IF_ERROR (status); - } - else if (next == 'F') - { - /* Ooh, tricky, a pointer-to-function. When we demangle the - function type, the return type should go at the very - beginning. */ - *insert_pos = result_length (dm); - /* The parentheses indicate this is a function pointer or - reference type. */ - RETURN_IF_ERROR (result_append (dm, "()")); - /* Now demangle the function type. The return type will be - inserted before the `()', and the argument list will go after - it. */ - RETURN_IF_ERROR (demangle_function_type (dm, insert_pos)); - /* We should now have something along the lines of - `void () (int, int)'. The pointer or reference characters - have to inside the first set of parentheses. *insert_pos has - already been updated to point past the end of the return - type. Move it one character over so it points inside the - `()'. */ - ++(*insert_pos); - } - else - { - /* No more pointer or reference tokens; this is therefore a - pointer to data. Finish up by demangling the underlying - type. */ - RETURN_IF_ERROR (demangle_type (dm)); - /* The pointer or reference characters follow the underlying - type, as in `int*&'. */ - *insert_pos = result_length (dm); - /* Because of the production ::= , - demangle_type will already have added the underlying type as - a substitution candidate. Don't do it again. */ - is_substitution_candidate = 0; + RETURN_IF_ERROR (status); + return STATUS_OK; + } } - - if (is_substitution_candidate) - RETURN_IF_ERROR (substitution_add (dm, substitution_start, 0)); - - return STATUS_OK; } /* Demangles and emits a . @@ -2150,7 +1926,6 @@ demangle_type_ptr (dm, insert_pos, substitution_start) ::= ::= ::= - ::= ::= ::= P # pointer-to ::= R # reference-to @@ -2166,28 +1941,22 @@ demangle_type (dm) int start = substitution_start (dm); char peek = peek_char (dm); char peek_next; - int encode_return_type = 0; + int template_p = 0; + int special_std_substitution; + int is_builtin_type = 0; template_arg_list_t old_arg_list = current_template_arg_list (dm); - int insert_pos; - - /* A can be a ; therefore, this is a - substitution candidate unless a special condition holds (see - below). */ - int is_substitution_candidate = 1; + int template_parm = NOT_TEMPLATE_PARM; DEMANGLE_TRACE ("type", dm); /* A can start with a digit (a ), an N (a ), or a Z (a ). */ if (IS_DIGIT ((unsigned char) peek) || peek == 'N' || peek == 'Z') - RETURN_IF_ERROR (demangle_class_enum_type (dm, &encode_return_type)); - /* Lower-case letters begin s, except for `r', which - denotes restrict. */ - else if (peek >= 'a' && peek <= 'z' && peek != 'r') + RETURN_IF_ERROR (demangle_class_enum_type (dm, &template_p)); + else if (peek >= 'a' && peek <= 'z') { RETURN_IF_ERROR (demangle_builtin_type (dm)); - /* Built-in types are not substitution candidates. */ - is_substitution_candidate = 0; + is_builtin_type = 1; } else switch (peek) @@ -2195,9 +1964,6 @@ demangle_type (dm) case 'r': case 'V': case 'K': - /* CV-qualifiers (including restrict). We have to demangle - them off to the side, since C++ syntax puts them in a funny - place for qualified pointer and reference types. */ { status_t status; dyn_string_t cv_qualifiers = dyn_string_new (24); @@ -2240,28 +2006,7 @@ demangle_type (dm) break; case 'T': - /* It's either a or a - . In either case, demangle the - `T' token first. */ - RETURN_IF_ERROR (demangle_template_param (dm)); - - /* Check for a template argument list; if one is found, it's a - ::= - ::= */ - if (peek_char (dm) == 'I') - { - /* Add a substitution candidate. The template parameter - `T' token is a substitution candidate by itself, - without the template argument list. */ - RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type)); - - /* Now demangle the template argument list. */ - RETURN_IF_ERROR (demangle_template_args (dm)); - /* The entire type, including the template template - parameter and its argument list, will be added as a - substitution candidate below. */ - } - + RETURN_IF_ERROR (demangle_template_param (dm, &template_parm)); break; case 'S': @@ -2271,56 +2016,16 @@ demangle_type (dm) or underscore. */ peek_next = peek_char_next (dm); if (IS_DIGIT (peek_next) || peek_next == '_') - { - RETURN_IF_ERROR (demangle_substitution (dm, &encode_return_type)); - - /* The substituted name may have been a template name. - Check if template arguments follow, and if so, demangle - them. */ - if (peek_char (dm) == 'I') - RETURN_IF_ERROR (demangle_template_args (dm)); - else - /* A substitution token is not itself a substitution - candidate. (However, if the substituted template is - instantiated, the resulting type is.) */ - is_substitution_candidate = 0; - } + RETURN_IF_ERROR (demangle_substitution (dm, &template_p, + &special_std_substitution)); else - { - /* Now some trickiness. We have a special substitution - here. Often, the special substitution provides the - name of a template that's subsequently instantiated, - for instance `SaIcE' => std::allocator. In these - cases we need to add a substitution candidate for the - entire and thus don't want to clear - the is_substitution_candidate flag. - - However, it's possible that what we have here is a - substitution token representing an entire type, such as - `Ss' => std::string. In this case, we mustn't add a - new substitution candidate for this substitution token. - To detect this case, remember where the start of the - substitution token is. */ - const char *next = dm->next; - /* Now demangle the . */ - RETURN_IF_ERROR - (demangle_class_enum_type (dm, &encode_return_type)); - /* If all that was just demangled is the two-character - special substitution token, supress the addition of a - new candidate for it. */ - if (dm->next == next + 2) - is_substitution_candidate = 0; - } - + demangle_class_enum_type (dm, &template_p); break; case 'P': case 'R': case 'M': - RETURN_IF_ERROR (demangle_type_ptr (dm, &insert_pos, start)); - /* demangle_type_ptr adds all applicable substitution - candidates. */ - is_substitution_candidate = 0; + RETURN_IF_ERROR (demangle_type_ptr (dm)); break; case 'C': @@ -2338,7 +2043,7 @@ demangle_type (dm) break; case 'U': - /* Vendor-extended type qualifier. */ + /* Vendor extended type qualifier. */ advance_char (dm); RETURN_IF_ERROR (demangle_source_name (dm)); RETURN_IF_ERROR (result_append_char (dm, ' ')); @@ -2349,12 +2054,13 @@ demangle_type (dm) return "Unexpected character in ."; } - if (is_substitution_candidate) + /* Unqualified builin types are not substitution candidates. */ + if (!is_builtin_type) /* Add a new substitution for the type. If this type was a , pass its index since from the point of - substitutions; a token is a substitution + substitutions, a token is a substitution candidate distinct from the type that is substituted for it. */ - RETURN_IF_ERROR (substitution_add (dm, start, encode_return_type)); + RETURN_IF_ERROR (substitution_add (dm, start, template_p, template_parm)); /* Pop off template argument lists added during mangling of this type. */ @@ -2493,18 +2199,16 @@ demangle_CV_qualifiers (dm, qualifiers) } } -/* Demangles and emits a . *FUNCTION_NAME_POS is the +/* Demangles and emits a FUNCTION_NAME_POS is the position in the result string of the start of the function - identifier, at which the function's return type will be inserted; - *FUNCTION_NAME_POS is updated to position past the end of the - function's return type. + identifier, at which the function's return type will be inserted. ::= F [Y] E */ static status_t demangle_function_type (dm, function_name_pos) demangling_t dm; - int *function_name_pos; + int function_name_pos; { DEMANGLE_TRACE ("function-type", dm); RETURN_IF_ERROR (demangle_char (dm, 'F')); @@ -2530,7 +2234,7 @@ demangle_function_type (dm, function_name_pos) static status_t demangle_bare_function_type (dm, return_type_pos) demangling_t dm; - int *return_type_pos; + int return_type_pos; { /* Sequence is the index of the current function parameter, counting from zero. The value -1 denotes the return type. */ @@ -2555,16 +2259,10 @@ demangle_bare_function_type (dm, return_type_pos) /* Add a space to the end of the type. Insert the return type where we've been asked to. */ - if (!dyn_string_append_space (return_type)) + if (!dyn_string_append_space (return_type) + || !dyn_string_insert (result_string (dm), return_type_pos, + return_type)) status = STATUS_ALLOCATION_FAILED; - if (STATUS_NO_ERROR (status)) - { - if (!dyn_string_insert (result_string (dm), *return_type_pos, - return_type)) - status = STATUS_ALLOCATION_FAILED; - else - *return_type_pos += dyn_string_length (return_type); - } dyn_string_delete (return_type); RETURN_IF_ERROR (status); @@ -2575,88 +2273,60 @@ demangle_bare_function_type (dm, return_type_pos) the only type in a parameter list; in that case, we want to print `foo ()' instead of `foo (void)'. */ if (peek_char (dm) == 'v') - /* Consume the v. */ - advance_char (dm); - else { - /* Separate parameter types by commas. */ - if (sequence > 0) - RETURN_IF_ERROR (result_append (dm, ", ")); - /* Demangle the type. */ - RETURN_IF_ERROR (demangle_type (dm)); + /* Consume the v. */ + advance_char (dm); + continue; } + /* Separate parameter types by commas. */ + if (sequence > 0) + RETURN_IF_ERROR (result_append (dm, ", ")); + /* Demangle the type. */ + RETURN_IF_ERROR (demangle_type (dm)); } ++sequence; } RETURN_IF_ERROR (result_append_char (dm, ')')); - /* We should have demangled at least one parameter type (which would - be void, for a function that takes no parameters), plus the - return type, if we were supposed to demangle that. */ - if (sequence == -1) - return "Missing function return type."; - else if (sequence == 0) - return "Missing function parameter."; - return STATUS_OK; } -/* Demangles and emits a . *ENCODE_RETURN_TYPE is set to +/* Demangles and emits a . *TEMPLATE_P is set to non-zero if the type is a template-id, zero otherwise. ::= */ static status_t -demangle_class_enum_type (dm, encode_return_type) +demangle_class_enum_type (dm, template_p) demangling_t dm; - int *encode_return_type; + int *template_p; { DEMANGLE_TRACE ("class-enum-type", dm); - RETURN_IF_ERROR (demangle_name (dm, encode_return_type)); + RETURN_IF_ERROR (demangle_name (dm, template_p)); return STATUS_OK; } /* Demangles and emits an . - ::= A [] _ - ::= A _ */ + ::= A [] _ */ static status_t demangle_array_type (dm) demangling_t dm; { - status_t status = STATUS_OK; - dyn_string_t array_size = NULL; - char peek; + status_t status; + dyn_string_t array_size = dyn_string_new (10); + + if (array_size == NULL) + return STATUS_ALLOCATION_FAILED; - RETURN_IF_ERROR (demangle_char (dm, 'A')); + status = demangle_char (dm, 'A'); /* Demangle the array size into array_size. */ - peek = peek_char (dm); - if (peek == '_') - /* Array bound is omitted. This is a C99-style VLA. */ - ; - else if (IS_DIGIT (peek_char (dm))) - { - /* It looks like a constant array bound. */ - array_size = dyn_string_new (10); - if (array_size == NULL) - return STATUS_ALLOCATION_FAILED; - status = demangle_number_literally (dm, array_size, 10, 0); - } - else - { - /* Anything is must be an expression for a nont-constant array - bound. This happens if the array type occurs in a template - and the array bound references a template parameter. */ - RETURN_IF_ERROR (result_push (dm)); - RETURN_IF_ERROR (demangle_expression (dm)); - array_size = (dyn_string_t) result_pop (dm); - } - /* array_size may have been allocated by now, so we can't use - RETURN_IF_ERROR until it's been deallocated. */ + if (STATUS_NO_ERROR (status)) + status = demangle_number_literally (dm, array_size, 10, 0); /* Demangle the base type of the array. */ if (STATUS_NO_ERROR (status)) @@ -2667,26 +2337,27 @@ demangle_array_type (dm) /* Emit the array dimension syntax. */ if (STATUS_NO_ERROR (status)) status = result_append_char (dm, '['); - if (STATUS_NO_ERROR (status) && array_size != NULL) + if (STATUS_NO_ERROR (status)) status = result_append_string (dm, array_size); if (STATUS_NO_ERROR (status)) status = result_append_char (dm, ']'); - if (array_size != NULL) - dyn_string_delete (array_size); + dyn_string_delete (array_size); RETURN_IF_ERROR (status); return STATUS_OK; } -/* Demangles and emits a . +/* Demangles and emits a . The zero-indexed position + in the parameter list is placed in *TEMPLATE_PARM_NUMBER. ::= T_ # first template parameter ::= T _ */ static status_t -demangle_template_param (dm) +demangle_template_param (dm, template_parm_number) demangling_t dm; + int *template_parm_number; { int parm_number; template_arg_list_t current_arg_list = current_template_arg_list (dm); @@ -2716,6 +2387,10 @@ demangle_template_param (dm) return "Template parameter number out of bounds."; RETURN_IF_ERROR (result_append_string (dm, (dyn_string_t) arg)); + if (peek_char (dm) == 'I') + RETURN_IF_ERROR (demangle_template_args (dm)); + + *template_parm_number = parm_number; return STATUS_OK; } @@ -2744,7 +2419,7 @@ demangle_template_args (dm) return STATUS_ALLOCATION_FAILED; RETURN_IF_ERROR (demangle_char (dm, 'I')); - RETURN_IF_ERROR (result_open_template_list (dm)); + RETURN_IF_ERROR (result_append_char (dm, '<')); do { string_list_t arg; @@ -2920,7 +2595,6 @@ demangle_template_arg (dm) /* Expression. */ advance_char (dm); RETURN_IF_ERROR (demangle_expression (dm)); - RETURN_IF_ERROR (demangle_char (dm, 'E')); break; default: @@ -3025,11 +2699,12 @@ demangle_expr_primary (dm) demangling_t dm; { char peek = peek_char (dm); + int unused; DEMANGLE_TRACE ("expr-primary", dm); if (peek == 'T') - RETURN_IF_ERROR (demangle_template_param (dm)); + RETURN_IF_ERROR (demangle_template_param (dm, &unused)); else if (peek == 'L') { /* Consume the `L'. */ @@ -3050,7 +2725,10 @@ demangle_expr_primary (dm) } /* Demangles and emits a . Sets *TEMPLATE_P to non-zero - if the substitution is the name of a template, zero otherwise. + if the substitution is the name of a template, zero otherwise. If + the substitution token is St, which corresponds to the `::std::' + namespace and can appear in a non-nested name, sets + *SPECIAL_STD_SUBSTITUTION to non-zero; zero otherwise. ::= S _ ::= S_ @@ -3066,13 +2744,14 @@ demangle_expr_primary (dm) ::= So # ::std::basic_ostream > ::= Sd # ::std::basic_iostream > + std::char_traits > */ static status_t -demangle_substitution (dm, template_p) +demangle_substitution (dm, template_p, special_std_substitution) demangling_t dm; int *template_p; + int *special_std_substitution; { int seq_id; int peek; @@ -3081,6 +2760,7 @@ demangle_substitution (dm, template_p) DEMANGLE_TRACE ("substitution", dm); RETURN_IF_ERROR (demangle_char (dm, 'S')); + *special_std_substitution = 0; /* Scan the substitution sequence index. A missing number denotes the first index. */ @@ -3101,6 +2781,7 @@ demangle_substitution (dm, template_p) { case 't': RETURN_IF_ERROR (result_append (dm, "std")); + *special_std_substitution = 1; break; case 'a': @@ -3216,7 +2897,7 @@ demangle_local_name (dm) RETURN_IF_ERROR (demangle_char (dm, 'Z')); RETURN_IF_ERROR (demangle_encoding (dm)); RETURN_IF_ERROR (demangle_char (dm, 'E')); - RETURN_IF_ERROR (result_append (dm, "::")); + RETURN_IF_ERROR (result_append (dm, "'s ")); if (peek_char (dm) == 's') { @@ -3229,6 +2910,7 @@ demangle_local_name (dm) else { int unused; + RETURN_IF_ERROR (result_append (dm, "local ")); /* Local name for some other entity. Demangle its name. */ RETURN_IF_ERROR (demangle_name (dm, &unused)); RETURN_IF_ERROR (demangle_discriminator (dm, 1)); @@ -3251,7 +2933,7 @@ demangle_discriminator (dm, suppress_first) int suppress_first; { /* Output for s to the demangled name is completely - suppressed if not in verbose mode. */ + supressed if not in verbose mode. */ if (peek_char (dm) == '_') { @@ -3343,7 +3025,6 @@ cp_demangle (name, result) dyn_string_t. On success, returns STATUS_OK. On failiure, returns an error message, and the contents of RESULT are unchanged. */ -#ifdef IN_LIBGCC2 static status_t cp_demangle_type (type_name, result) const char* type_name; @@ -3381,6 +3062,9 @@ cp_demangle_type (type_name, result) return status; } + +#ifdef IN_LIBGCC2 + extern char *__cxa_demangle PARAMS ((const char *, char *, size_t *, int *)); /* ABI-mandated entry point in the C++ runtime library for performing @@ -3537,8 +3221,7 @@ static void print_usage /* Non-zero if CHAR is a character than can occur in a mangled name. */ #define is_mangled_char(CHAR) \ - (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) \ - || (CHAR) == '_' || (CHAR) == '.' || (CHAR) == '$') + (IS_ALPHA (CHAR) || IS_DIGIT (CHAR) || (CHAR) == '_') /* The name of this program, as invoked. */ const char* program_name; @@ -3551,7 +3234,7 @@ print_usage (fp, exit_value) int exit_value; { fprintf (fp, "Usage: %s [options] [names ...]\n", program_name); - fprintf (fp, "Options:\n"); + fprintf (fp, "Options:\n", program_name); fprintf (fp, " -h,--help Display this message.\n"); fprintf (fp, " -s,--strict Demangle standard names only.\n"); fprintf (fp, " -v,--verbose Produce verbose demanglings.\n"); diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c index 52249d2b580..8a672c684b1 100644 --- a/libiberty/cplus-dem.c +++ b/libiberty/cplus-dem.c @@ -252,6 +252,55 @@ typedef enum type_kind_t tk_real } type_kind_t; +struct demangler_engine libiberty_demanglers[] = +{ + { + AUTO_DEMANGLING_STYLE_STRING, + auto_demangling, + "Automatic selection based on executable" + } + , + { + GNU_DEMANGLING_STYLE_STRING, + gnu_demangling, + "GNU (g++) style demangling" + } + , + { + LUCID_DEMANGLING_STYLE_STRING, + lucid_demangling, + "Lucid (lcc) style demangling" + } + , + { + ARM_DEMANGLING_STYLE_STRING, + arm_demangling, + "ARM style demangling" + } + , + { + HP_DEMANGLING_STYLE_STRING, + hp_demangling, + "HP (aCC) style demangling" + } + , + { + EDG_DEMANGLING_STYLE_STRING, + edg_demangling, + "EDG style demangling" + } + , + { + GNU_NEW_ABI_DEMANGLING_STYLE_STRING, + gnu_new_abi_demangling, + "GNU (g++) new-ABI-style demangling" + } + , + { + NULL, unknown_demangling, NULL + } +}; + #define STRING_EMPTY(str) ((str) -> b == (str) -> p) #define PREPEND_BLANK(str) {if (!STRING_EMPTY(str)) \ string_prepend(str, " ");} @@ -268,12 +317,21 @@ typedef enum type_kind_t /* Prototypes for local functions */ +static void +delete_work_stuff PARAMS ((struct work_stuff *)); + +static void +delete_non_B_K_work_stuff PARAMS ((struct work_stuff *)); + static char * mop_up PARAMS ((struct work_stuff *, string *, int)); static void squangle_mop_up PARAMS ((struct work_stuff *)); +static void +work_stuff_copy_to_from PARAMS ((struct work_stuff *, struct work_stuff *)); + #if 0 static int demangle_method_args PARAMS ((struct work_stuff *, const char **, string *)); @@ -379,6 +437,10 @@ static void demangle_function_name PARAMS ((struct work_stuff *, const char **, string *, const char *)); +static int +iterate_demangle_function PARAMS ((struct work_stuff *, + const char **, string *, const char *)); + static void remember_type PARAMS ((struct work_stuff *, const char *, int)); @@ -636,8 +698,8 @@ cplus_demangle_opname (opname, result, options) } } else if (opname[0] == '_' && opname[1] == '_' - && opname[2] >= 'a' && opname[2] <= 'z' - && opname[3] >= 'a' && opname[3] <= 'z') + && islower((unsigned char)opname[2]) + && islower((unsigned char)opname[3])) { if (opname[4] == '\0') { @@ -733,6 +795,7 @@ cplus_demangle_opname (opname, result, options) return ret; } + /* Takes operator name as e.g. "++" and returns mangled operator name (e.g. "postincrement_expr"), or NULL if not found. @@ -758,6 +821,40 @@ cplus_mangle_opname (opname, options) return (0); } +/* Add a routine to set the demangling style to be sure it is valid and + allow for any demangler initialization that maybe necessary. */ + +enum demangling_styles +cplus_demangle_set_style (style) + enum demangling_styles style; +{ + struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (style == demangler->demangling_style) + { + current_demangling_style = style; + return current_demangling_style; + } + + return unknown_demangling; +} + +/* Do string name to style translation */ + +enum demangling_styles +cplus_demangle_name_to_style (name) + const char *name; +{ + struct demangler_engine *demangler = libiberty_demanglers; + + for (; demangler->demangling_style != unknown_demangling; ++demangler) + if (strcmp (name, demangler->demangling_style_name) == 0) + return demangler->demangling_style; + + return unknown_demangling; +} + /* char *cplus_demangle (const char *mangled, int options) If MANGLED is a mangled function name produced by GNU C++, then @@ -798,6 +895,10 @@ cplus_demangle (mangled, options) if ((work -> options & DMGL_STYLE_MASK) == 0) work -> options |= (int) current_demangling_style & DMGL_STYLE_MASK; + /* The new-ABI demangling is implemented elsewhere. */ + if (GNU_NEW_ABI_DEMANGLING) + return cplus_demangle_new_abi (mangled); + ret = internal_cplus_demangle (work, mangled); squangle_mop_up (work); return (ret); @@ -893,16 +994,85 @@ squangle_mop_up (work) } } -/* Clear out any mangled storage */ -static char * -mop_up (work, declp, success) - struct work_stuff *work; - string *declp; - int success; +/* Copy the work state and storage. */ + +static void +work_stuff_copy_to_from (to, from) + struct work_stuff *to; + struct work_stuff *from; { - char *demangled = NULL; + int i; + + delete_work_stuff (to); + + /* Shallow-copy scalars. */ + memcpy (to, from, sizeof (*to)); + + /* Deep-copy dynamic storage. */ + if (from->typevec_size) + to->typevec + = (char **) xmalloc (from->typevec_size * sizeof (to->typevec[0])); + + for (i = 0; i < from->ntypes; i++) + { + int len = strlen (from->typevec[i]) + 1; + + to->typevec[i] = xmalloc (len); + memcpy (to->typevec[i], from->typevec[i], len); + } + + if (from->ksize) + to->ktypevec + = (char **) xmalloc (from->ksize * sizeof (to->ktypevec[0])); + + for (i = 0; i < from->numk; i++) + { + int len = strlen (from->ktypevec[i]) + 1; + + to->ktypevec[i] = xmalloc (len); + memcpy (to->ktypevec[i], from->ktypevec[i], len); + } + + if (from->bsize) + to->btypevec + = (char **) xmalloc (from->bsize * sizeof (to->btypevec[0])); + + for (i = 0; i < from->numb; i++) + { + int len = strlen (from->btypevec[i]) + 1; + + to->btypevec[i] = xmalloc (len); + memcpy (to->btypevec[i], from->btypevec[i], len); + } + + if (from->ntmpl_args) + to->tmpl_argvec + = xmalloc (from->ntmpl_args * sizeof (to->tmpl_argvec[0])); + for (i = 0; i < from->ntmpl_args; i++) + { + int len = strlen (from->tmpl_argvec[i]) + 1; + + to->tmpl_argvec[i] = xmalloc (len); + memcpy (to->tmpl_argvec[i], from->tmpl_argvec[i], len); + } + + if (from->previous_argument) + { + to->previous_argument = (string*) xmalloc (sizeof (string)); + string_init (to->previous_argument); + string_appends (to->previous_argument, from->previous_argument); + } +} + + +/* Delete dynamic stuff in work_stuff that is not to be re-used. */ + +static void +delete_non_B_K_work_stuff (work) + struct work_stuff *work; +{ /* Discard the remembered types, if any. */ forget_types (work); @@ -929,6 +1099,30 @@ mop_up (work, declp, success) free ((char*) work->previous_argument); work->previous_argument = NULL; } +} + + +/* Delete all dynamic storage in work_stuff. */ +static void +delete_work_stuff (work) + struct work_stuff *work; +{ + delete_non_B_K_work_stuff (work); + squangle_mop_up (work); +} + + +/* Clear out any mangled storage */ + +static char * +mop_up (work, declp, success) + struct work_stuff *work; + string *declp; + int success; +{ + char *demangled = NULL; + + delete_non_B_K_work_stuff (work); /* If demangling was successful, ensure that the demangled string is null terminated and return it. Otherwise, free the demangling decl. */ @@ -1154,7 +1348,7 @@ demangle_signature (work, mangled, declp) break; case '_': - if (GNU_DEMANGLING && expect_return_type) + if ((AUTO_DEMANGLING || GNU_DEMANGLING) && expect_return_type) { /* Read the return type. */ string return_type; @@ -1188,7 +1382,7 @@ demangle_signature (work, mangled, declp) break; case 'H': - if (GNU_DEMANGLING) + if (AUTO_DEMANGLING || GNU_DEMANGLING) { /* A G++ template function. Read the template arguments. */ success = demangle_template (work, mangled, declp, 0, 0, @@ -1433,6 +1627,11 @@ demangle_integral_value (work, mangled, s) { int value; + /* By default, we let the number decide whether we shall consume an + underscore. */ + int consume_following_underscore = 0; + int leave_following_underscore = 0; + success = 0; /* Negative numbers are indicated with a leading `m'. */ @@ -1441,17 +1640,49 @@ demangle_integral_value (work, mangled, s) string_appendn (s, "-", 1); (*mangled)++; } + else if (mangled[0][0] == '_' && mangled[0][1] == 'm') + { + /* Since consume_count_with_underscores does not handle the + `m'-prefix we must do it here, using consume_count and + adjusting underscores: we have to consume the underscore + matching the prepended one. */ + consume_following_underscore = 1; + string_appendn (s, "-", 1); + (*mangled) += 2; + } + else if (**mangled == '_') + { + /* Do not consume a following underscore; + consume_following_underscore will consume what should be + consumed. */ + leave_following_underscore = 1; + } + + /* We must call consume_count if we expect to remove a trailing + underscore, since consume_count_with_underscores expects + the leading underscore (that we consumed) if it is to handle + multi-digit numbers. */ + if (consume_following_underscore) + value = consume_count (mangled); + else + value = consume_count_with_underscores (mangled); - /* Read the rest of the number. */ - value = consume_count_with_underscores (mangled); if (value != -1) { char buf[INTBUF_SIZE]; sprintf (buf, "%d", value); string_append (s, buf); - /* If the next character is an underscore, skip it. */ - if (**mangled == '_') + /* Numbers not otherwise delimited, might have an underscore + appended as a delimeter, which we should skip. + + ??? This used to always remove a following underscore, which + is wrong. If other (arbitrary) cases are followed by an + underscore, we need to do something more radical. */ + + if ((value > 9 || consume_following_underscore) + && ! leave_following_underscore + && **mangled == '_') (*mangled)++; /* All is well. */ @@ -1616,7 +1847,7 @@ demangle_template_value_parm (work, mangled, s, tk) template parameters (e.g. S) is placed in TRAWNAME if TRAWNAME is non-NULL. If IS_TYPE is nonzero, this template is a type template, not a function template. If both IS_TYPE and REMEMBER are nonzero, - the tmeplate is remembered in the list of back-referenceable + the template is remembered in the list of back-referenceable types. */ static int @@ -2148,6 +2379,86 @@ demangle_class (work, mangled, declp) return (success); } + +/* Called when there's a "__" in the mangled name, with `scan' pointing to + the rightmost guess. + + Find the correct "__"-sequence where the function name ends and the + signature starts, which is ambiguous with GNU mangling. + Call demangle_signature here, so we can make sure we found the right + one; *mangled will be consumed so caller will not make further calls to + demangle_signature. */ + +static int +iterate_demangle_function (work, mangled, declp, scan) + struct work_stuff *work; + const char **mangled; + string *declp; + const char *scan; +{ + const char *mangle_init = *mangled; + int success = 0; + string decl_init; + struct work_stuff work_init; + + if (*(scan + 2) == '\0') + return 0; + + /* Do not iterate for some demangling modes, or if there's only one + "__"-sequence. This is the normal case. */ + if (ARM_DEMANGLING || LUCID_DEMANGLING || HP_DEMANGLING || EDG_DEMANGLING + || mystrstr (scan + 2, "__") == NULL) + { + demangle_function_name (work, mangled, declp, scan); + return 1; + } + + /* Save state so we can restart if the guess at the correct "__" was + wrong. */ + string_init (&decl_init); + string_appends (&decl_init, declp); + memset (&work_init, 0, sizeof work_init); + work_stuff_copy_to_from (&work_init, work); + + /* Iterate over occurrences of __, allowing names and types to have a + "__" sequence in them. We must start with the first (not the last) + occurrence, since "__" most often occur between independent mangled + parts, hence starting at the last occurence inside a signature + might get us a "successful" demangling of the signature. */ + + while (scan[2]) + { + demangle_function_name (work, mangled, declp, scan); + success = demangle_signature (work, mangled, declp); + if (success) + break; + + /* Reset demangle state for the next round. */ + *mangled = mangle_init; + string_clear (declp); + string_appends (declp, &decl_init); + work_stuff_copy_to_from (work, &work_init); + + /* Leave this underscore-sequence. */ + scan += 2; + + /* Scan for the next "__" sequence. */ + while (*scan && (scan[0] != '_' || scan[1] != '_')) + scan++; + + /* Move to last "__" in this sequence. */ + while (*scan && *scan == '_') + scan++; + scan -= 2; + } + + /* Delete saved state. */ + delete_work_stuff (&work_init); + string_delete (&decl_init); + + return success; +} + /* LOCAL FUNCTION @@ -2163,6 +2474,8 @@ SYNOPSIS DESCRIPTION Consume and demangle the prefix of the mangled name. + While processing the function name root, arrange to call + demangle_signature if the root is ambiguous. DECLP points to the string buffer into which demangled output is placed. On entry, the buffer is empty. On exit it contains @@ -2336,29 +2649,16 @@ demangle_prefix (work, mangled, declp) success = 0; } else - { - const char *tmp; - - /* Look for the LAST occurrence of __, allowing names to - have the '__' sequence embedded in them. */ - if (!(ARM_DEMANGLING || HP_DEMANGLING)) - { - while ((tmp = mystrstr (scan + 2, "__")) != NULL) - scan = tmp; - } - if (*(scan + 2) == '\0') - success = 0; - else - demangle_function_name (work, mangled, declp, scan); - } + return iterate_demangle_function (work, mangled, declp, scan); } } else if (*(scan + 2) != '\0') { /* Mangled name does not start with "__" but does have one somewhere in there with non empty stuff after it. Looks like a global - function name. */ - demangle_function_name (work, mangled, declp, scan); + function name. Iterate over all "__":s until the right + one is found. */ + return iterate_demangle_function (work, mangled, declp, scan); } else { @@ -2512,6 +2812,25 @@ gnu_special (work, mangled, declp) success = 0; break; } + + if (n > 10 && strncmp (*mangled, "_GLOBAL_", 8) == 0 + && (*mangled)[9] == 'N' + && (*mangled)[8] == (*mangled)[10] + && strchr (cplus_markers, (*mangled)[8])) + { + /* A member of the anonymous namespace. There's information + about what identifier or filename it was keyed to, but + it's just there to make the mangled name unique; we just + step over it. */ + string_append (declp, "{anonymous}"); + (*mangled) += n; + + /* Now p points to the marker before the N, so we need to + update it to the first marker after what we consumed. */ + p = strpbrk (*mangled, cplus_markers); + break; + } + string_appendn (declp, *mangled, n); (*mangled) += n; } @@ -2573,7 +2892,7 @@ gnu_special (work, mangled, declp) success = demangle_template (work, mangled, declp, 0, 1, 1); break; default: - success = demangle_fund_type (work, mangled, declp); + success = do_type (work, mangled, declp); break; } if (success && **mangled != '\0') @@ -3311,7 +3630,7 @@ demangle_fund_type (work, mangled, result) int done = 0; int success = 1; char buf[10]; - int dec = 0; + unsigned int dec = 0; string btype; type_kind_t tk = tk_integral; @@ -3455,7 +3774,7 @@ demangle_fund_type (work, mangled, result) *mangled += min (strlen (*mangled), 2); } sscanf (buf, "%x", &dec); - sprintf (buf, "int%i_t", dec); + sprintf (buf, "int%u_t", dec); APPEND_BLANK (result); string_append (result, buf); break; @@ -4188,8 +4507,8 @@ demangle_function_name (work, mangled, declp, scan) } } else if (declp->b[0] == '_' && declp->b[1] == '_' - && declp->b[2] >= 'a' && declp->b[2] <= 'z' - && declp->b[3] >= 'a' && declp->b[3] <= 'z') + && islower((unsigned char)declp->b[2]) + && islower((unsigned char)declp->b[3])) { if (declp->b[4] == '\0') { @@ -4402,6 +4721,7 @@ static int flags = DMGL_PARAMS | DMGL_ANSI; static void demangle_it PARAMS ((char *)); static void usage PARAMS ((FILE *, int)) ATTRIBUTE_NORETURN; static void fatal PARAMS ((const char *)) ATTRIBUTE_NORETURN; +static void print_demangler_list PARAMS ((FILE *)); static void demangle_it (mangled_name) @@ -4421,16 +4741,43 @@ demangle_it (mangled_name) } } +static void +print_demangler_list (stream) + FILE *stream; +{ + struct demangler_engine *demangler; + + fprintf (stream, "{%s", libiberty_demanglers->demangling_style_name); + + for (demangler = libiberty_demanglers + 1; + demangler->demangling_style != unknown_demangling; + ++demangler) + fprintf (stream, ",%s", demangler->demangling_style_name); + + fprintf (stream, "}"); +} + static void usage (stream, status) FILE *stream; int status; { fprintf (stream, "\ -Usage: %s [-_] [-n] [-s {gnu,lucid,arm,hp,edg}] [--strip-underscores]\n\ - [--no-strip-underscores] [--format={gnu,lucid,arm,hp,edg}]\n\ - [--help] [--version] [arg...]\n", +Usage: %s [-_] [-n] [--strip-underscores] [--no-strip-underscores] \n", program_name); + + fprintf (stream, "\ + [-s "); + print_demangler_list (stream); + fprintf (stream, "]\n"); + + fprintf (stream, "\ + [--format "); + print_demangler_list (stream); + fprintf (stream, "]\n"); + + fprintf (stream, "\ + [--help] [--version] [arg...]\n"); exit (status); } @@ -4468,6 +4815,9 @@ standard_symbol_characters PARAMS ((void)); static const char * hp_symbol_characters PARAMS ((void)); +static const char * +gnu_new_abi_symbol_characters PARAMS ((void)); + /* Return the string of non-alnum characters that may occur as a valid symbol component, in the standard assembler symbol syntax. */ @@ -4516,6 +4866,17 @@ hp_symbol_characters () } +/* Return the string of non-alnum characters that may occur + as a valid symbol component in the GNU standard C++ ABI mangling + scheme. */ + +static const char * +gnu_new_abi_symbol_characters () +{ + return "_"; +} + + extern int main PARAMS ((int, char **)); int @@ -4553,32 +4914,19 @@ main (argc, argv) flags |= DMGL_JAVA; break; case 's': - if (strcmp (optarg, "gnu") == 0) - { - current_demangling_style = gnu_demangling; - } - else if (strcmp (optarg, "lucid") == 0) - { - current_demangling_style = lucid_demangling; - } - else if (strcmp (optarg, "arm") == 0) - { - current_demangling_style = arm_demangling; - } - else if (strcmp (optarg, "hp") == 0) - { - current_demangling_style = hp_demangling; - } - else if (strcmp (optarg, "edg") == 0) - { - current_demangling_style = edg_demangling; - } - else - { - fprintf (stderr, "%s: unknown demangling style `%s'\n", - program_name, optarg); - return (1); - } + { + enum demangling_styles style; + + style = cplus_demangle_name_to_style (optarg); + if (style == unknown_demangling) + { + fprintf (stderr, "%s: unknown demangling style `%s'\n", + program_name, optarg); + return (1); + } + else + cplus_demangle_set_style (style); + } break; } } @@ -4603,6 +4951,9 @@ main (argc, argv) case hp_demangling: valid_symbols = hp_symbol_characters (); break; + case gnu_new_abi_demangling: + valid_symbols = gnu_new_abi_symbol_characters (); + break; default: /* Folks should explicitly indicate the appropriate alphabet for each demangling. Providing a default would allow the @@ -4652,6 +5003,7 @@ main (argc, argv) if (c == EOF) break; putchar (c); + fflush (stdout); } } diff --git a/libiberty/dyn-string.c b/libiberty/dyn-string.c index 34f88ade96d..69897f84c5e 100644 --- a/libiberty/dyn-string.c +++ b/libiberty/dyn-string.c @@ -305,30 +305,6 @@ dyn_string_insert_cstr (dest, pos, src) return 1; } -/* Inserts character C into DEST starting at position POS. DEST is - expanded as necessary. Returns 1 on success. On failure, - RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */ - -int -dyn_string_insert_char (dest, pos, c) - dyn_string_t dest; - int pos; - int c; -{ - int i; - - if (dyn_string_resize (dest, dest->length + 1) == NULL) - return 0; - /* Make room for the insertion. Be sure to copy the NUL. */ - for (i = dest->length; i >= pos; --i) - dest->s[i + 1] = dest->s[i]; - /* Add the new character. */ - dest->s[pos] = c; - /* Compute the new length. */ - ++dest->length; - return 1; -} - /* Append S to DS, resizing DS if necessary. Returns 1 on success. On failure, if RETURN_ON_ALLOCATION_FAILURE, deletes DEST and returns 0. */ diff --git a/libiberty/testsuite/demangle-expected b/libiberty/testsuite/demangle-expected index d3a1fe43890..a5d72fab0fe 100644 --- a/libiberty/testsuite/demangle-expected +++ b/libiberty/testsuite/demangle-expected @@ -2486,3 +2486,83 @@ f(Bar<21>, int) --format=gnu f__FGt3Bar1i24XY_t f(Bar<2>, XY_t) +# +--format=gnu +foo__H1Zt2TA2ZRCiZt2NA1Ui9_X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZcZt2NA1Ui_20__X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZiZt8N___A___1Ui_99__X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZRCiZt2NA1im1_X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZRCiZt2NA1im9_X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZcZt2NA1i_m20__X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZcZt2NA1im1_X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZiZt4N__A1im9_X01_i +int foo > >(TA >) +# +--format=gnu +foo__H1Zt2TA2ZiZt4N__A1i_m99__X01_i +int foo > >(TA >) +# +--format=gnu +__opi__t2TA2ZiZt4N__A1i9 +TA >::operator int(void) +# +--format=gnu +__opi__t2TA2ZiZt8N___A___1i_m99_ +TA >::operator int(void) +# +--format=gnu +foo___bar__baz_____H1Zt2TA2ZiZt8N___A___1i_99__X01_i +int foo___bar__baz___ > >(TA >) +# +--format=gnu +foo__bar___foobar_____t2TA2ZiZt8N___A___1i_m99_ +TA >::foo__bar___foobar___(void) +# +--format=gnu +foo__bar___foobar_____t2TA2ZiZt4N__A1i9 +TA >::foo__bar___foobar___(void) +# +--format=gnu +__tfP8sockaddr +sockaddr * type_info function +# +--format=gnu +__tfPQ25libcwt16option_event_tct1Z12burst_app_ct +libcw::option_event_tct * type_info function +# +--format=gnu +__tiP8sockaddr +sockaddr * type_info node +# +--format=gnu +__tiPQ25libcwt16option_event_tct1Z12burst_app_ct +libcw::option_event_tct * type_info node +# +--format=gnu +_27_GLOBAL_.N.__12burst_app_ct.app_instance +{anonymous}::app_instance +# +--format=gnu +_26_GLOBAL_\$N\$_tmp_n.iilg4Gya\$app_instance +{anonymous}::app_instance diff --git a/libiberty/testsuite/regress-demangle b/libiberty/testsuite/regress-demangle index bd48ce9013e..1086762dbb2 100755 --- a/libiberty/testsuite/regress-demangle +++ b/libiberty/testsuite/regress-demangle @@ -15,6 +15,8 @@ sed -e '/^#/ d' "$1" | ( if test "x$x" != "x$demangled"; then failures=`expr $failures + 1` echo "FAIL: $type $mangled" + echo " result: $x" + echo " expected: $demangled" fi done