summaryrefslogtreecommitdiff
path: root/debian/patches/libiberty-updates.diff
diff options
context:
space:
mode:
Diffstat (limited to 'debian/patches/libiberty-updates.diff')
-rw-r--r--debian/patches/libiberty-updates.diff2647
1 files changed, 2647 insertions, 0 deletions
diff --git a/debian/patches/libiberty-updates.diff b/debian/patches/libiberty-updates.diff
new file mode 100644
index 0000000..caae314
--- /dev/null
+++ b/debian/patches/libiberty-updates.diff
@@ -0,0 +1,2647 @@
+# DP: libiberty updates, taken from the trunk 20161108
+
+2016-11-30 David Malcolm <dmalcolm@redhat.com>
+
+ PR c/78498
+ * strndup.c (strlen): Delete decl.
+ (strnlen): Add decl.
+ (strndup): Call strnlen rather than strlen.
+ * xstrndup.c (xstrndup): Likewise.
+
+2016-11-29 Nathan Sidwell <nathan@acm.org>
+
+ * cp-demangle.c (d_print_comp_inner): Fix parameter indentation.
+
+2016-11-03 David Tolnay <dtolnay@gmail.com>
+ Mark Wielaard <mark@klomp.org>
+
+ * Makefile.in (CFILES): Add rust-demangle.c.
+ (REQUIRED_OFILES): Add rust-demangle.o.
+ * cplus-dem.c (libiberty_demanglers): Add rust_demangling case.
+ (cplus_demangle): Handle RUST_DEMANGLING.
+ (rust_demangle): New function.
+ * rust-demangle.c: New file.
+ * testsuite/Makefile.in (really-check): Add check-rust-demangle.
+ (check-rust-demangle): New rule.
+ * testsuite/rust-demangle-expected: New file.
+
+2016-11-15 Mark Wielaard <mark@klomp.org>
+
+ * cp-demangle.c (d_expression_1): Make sure third expression
+ exists for ?: and fold expressions.
+ * testsuite/demangle-expected: Add examples of strings that could
+ crash the demangler because of missing expression.
+
+2016-11-14 Mark Wielaard <mark@klomp.org>
+
+ * cplus-dem.c (demangle_signature): After 'H', template function,
+ no success and don't advance position if end of string reached.
+ (demangle_template): After 'z', template name, return zero on
+ premature end of string.
+ (gnu_special): Guard strchr against searching for zero characters.
+ (do_type): If member, only advance mangled string when 'F' found.
+ * testsuite/demangle-expected: Add examples of strings that could
+ crash the demangler by reading past end of input.
+
+2016-11-06 Mark Wielaard <mark@klomp.org>
+
+ * configure.ac (ac_libiberty_warn_cflags): Add -Wshadow=local.
+ * configure: Regenerated.
+
+2016-11-07 Jason Merrill <jason@redhat.com>
+
+ * cp-demangle.c (is_fnqual_component_type): New.
+ (d_encoding, d_print_comp_inner, d_print_mod_list): Use it.
+ (FNQUAL_COMPONENT_CASE): New.
+ (d_make_comp, has_return_type, d_print_comp_inner)
+ (d_print_function_type): Use it.
+ (next_is_type_qual): New.
+ (d_cv_qualifiers, d_print_mod): Handle noexcept and throw-spec.
+
+2016-11-02 Mark Wielaard <mjw@redhat.com>
+
+ * cplus-dem.c (demangle_signature): Move fall through comment.
+ (demangle_fund_type): Add fall through comment between 'G' and 'I'.
+ * hashtab.c (iterative_hash): Add fall through comments.
+ * regex.c (regex_compile): Add Fall through comment after '+'/'?'.
+ (byte_re_match_2_internal): Add Fall through comment after jump_n.
+ Change "Note fall through" to "Fall through".
+ (common_op_match_null_string_p): Return false after set_number_at
+ instead of fall through.
+
+2016-11-01 Jason Merrill <jason@redhat.com>
+
+ * cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.
+
+2016-10-31 Mark Wielaard <mjw@redhat.com>
+
+ * cplus-dem.c (ada_demangle): Initialize demangled to NULL and
+ XDELETEVEC demangled when unknown.
+
+2016-09-19 Andrew Stubbs <ams@codesourcery.com>
+
+ * pex-win32.c (argv_to_cmdline): Quote zero-length parameters.
+ * testsuite/test-pexecute.c (main): Insert check for zero-length parameters.
+
+2016-09-10 Mark Wielaard <mjw@redhat.com>
+
+ * cp-demangle.c (d_substitution): Change struct demangle_component
+ variable name from c to dc.
+
+2016-08-12 Marek Polacek <polacek@redhat.com>
+
+ PR c/7652
+ * cp-demangle.c (d_print_mod): Add FALLTHRU.
+
+2016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
+
+ PR c++/71696
+ * cplus-dem.c: Prevent infinite recursion when there is a cycle
+ in the referencing of remembered mangled types.
+ (work_stuff): New stack to keep track of the remembered mangled
+ types that are currently being processed.
+ (push_processed_type): New method to push currently processed
+ remembered type onto the stack.
+ (pop_processed_type): New method to pop currently processed
+ remembered type from the stack.
+ (work_stuff_copy_to_from): Copy values of new variables.
+ (delete_non_B_K_work_stuff): Free stack memory.
+ (demangle_args): Push/Pop currently processed remembered type.
+ (do_type): Do not demangle a cyclic reference and push/pop
+ referenced remembered type.
+
+2016-07-29 Aldy Hernandez <aldyh@redhat.com>
+
+ * make-relative-prefix.c (make_relative_prefix_1): Fall back to
+ malloc if alloca argument is greater than MAX_ALLOCA_SIZE.
+
+2016-07-15 Jason Merrill <jason@redhat.com>
+
+ * cp-demangle.c (cplus_demangle_operators): Add f[lrLR].
+ (d_expression_1): Handle them.
+ (d_maybe_print_fold_expression): New.
+ (d_print_comp_inner): Use it.
+ (d_index_template_argument): Handle negative index.
+
+ * cp-demangle.c (cplus_demangle_operators): Add sP and sZ.
+ (d_print_comp_inner): Handle them.
+ (d_template_args_1): Split out from d_template_args.
+ (d_args_length): New.
+
+2016-07-13 Marcel Böhme <boehme.marcel@gmail.com>
+
+ PR c++/70926
+ * cplus-dem.c: Handle large values and overflow when demangling
+ length variables.
+ (demangle_template_value_parm): Read only until end of mangled string.
+ (do_hpacc_template_literal): Likewise.
+ (do_type): Handle overflow when demangling array indices.
+
+2016-06-12 Brooks Moses <bmoses@google.com>
+
+ * cp-demangle.c (cplus_demangle_print_callback): Avoid zero-length
+ VLAs.
+
+2016-05-31 Alan Modra <amodra@gmail.com>
+
+ * xmemdup.c (xmemdup): Use xmalloc rather than xcalloc.
+
+2016-05-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70498
+ * cp-demangle.c (d_expression_1): Formatting fix.
+
+2016-05-18 Artemiy Volkov <artemiyv@acm.org>
+
+ * cplus-dem.c (enum type_kind_t): Add tk_rvalue_reference
+ constant.
+ (demangle_template_value_parm): Handle tk_rvalue_reference
+ type kind.
+ (do_type): Support 'O' type id (rvalue references).
+
+ * testsuite/demangle-expected: Add tests.
+
+Index: b/src/libiberty/argv.c
+===================================================================
+--- a/src/libiberty/argv.c
++++ b/src/libiberty/argv.c
+@@ -35,6 +35,13 @@ Boston, MA 02110-1301, USA. */
+ #include <string.h>
+ #include <stdlib.h>
+ #include <stdio.h>
++#include <sys/types.h>
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#if HAVE_SYS_STAT_H
++#include <sys/stat.h>
++#endif
+
+ #ifndef NULL
+ #define NULL 0
+@@ -387,6 +394,9 @@ expandargv (int *argcp, char ***argvp)
+ char **file_argv;
+ /* The number of options read from the response file, if any. */
+ size_t file_argc;
++#ifdef S_ISDIR
++ struct stat sb;
++#endif
+ /* We are only interested in options of the form "@file". */
+ filename = (*argvp)[i];
+ if (filename[0] != '@')
+@@ -397,6 +407,15 @@ expandargv (int *argcp, char ***argvp)
+ fprintf (stderr, "%s: error: too many @-files encountered\n", (*argvp)[0]);
+ xexit (1);
+ }
++#ifdef S_ISDIR
++ if (stat (filename+1, &sb) < 0)
++ continue;
++ if (S_ISDIR(sb.st_mode))
++ {
++ fprintf (stderr, "%s: error: @-file refers to a directory\n", (*argvp)[0]);
++ xexit (1);
++ }
++#endif
+ /* Read the contents of the file. */
+ f = fopen (++filename, "r");
+ if (!f)
+Index: b/src/libiberty/ChangeLog
+===================================================================
+--- a/src/libiberty/ChangeLog
++++ b/src/libiberty/ChangeLog
+@@ -22,11 +22,126 @@
+ printing.
+ * testsuite/demangle-expected: Add lambda auto mangling cases.
+
+-2016-08-22 Release Manager
++2016-12-06 DJ Delorie <dj@redhat.com>
+
+- * GCC 6.2.0 released.
++ * argv.c (expandargv): Check for directories passed as @-files.
+
+-2016-07-21 Jason Merrill <jason@redhat.com>
++2016-11-30 David Malcolm <dmalcolm@redhat.com>
++
++ PR c/78498
++ * strndup.c (strlen): Delete decl.
++ (strnlen): Add decl.
++ (strndup): Call strnlen rather than strlen.
++ * xstrndup.c (xstrndup): Likewise.
++
++2016-11-29 Nathan Sidwell <nathan@acm.org>
++
++ * cp-demangle.c (d_print_comp_inner): Fix parameter indentation.
++
++2016-11-03 David Tolnay <dtolnay@gmail.com>
++ Mark Wielaard <mark@klomp.org>
++
++ * Makefile.in (CFILES): Add rust-demangle.c.
++ (REQUIRED_OFILES): Add rust-demangle.o.
++ * cplus-dem.c (libiberty_demanglers): Add rust_demangling case.
++ (cplus_demangle): Handle RUST_DEMANGLING.
++ (rust_demangle): New function.
++ * rust-demangle.c: New file.
++ * testsuite/Makefile.in (really-check): Add check-rust-demangle.
++ (check-rust-demangle): New rule.
++ * testsuite/rust-demangle-expected: New file.
++
++2016-11-15 Mark Wielaard <mark@klomp.org>
++
++ * cp-demangle.c (d_expression_1): Make sure third expression
++ exists for ?: and fold expressions.
++ * testsuite/demangle-expected: Add examples of strings that could
++ crash the demangler because of missing expression.
++
++2016-11-14 Mark Wielaard <mark@klomp.org>
++
++ * cplus-dem.c (demangle_signature): After 'H', template function,
++ no success and don't advance position if end of string reached.
++ (demangle_template): After 'z', template name, return zero on
++ premature end of string.
++ (gnu_special): Guard strchr against searching for zero characters.
++ (do_type): If member, only advance mangled string when 'F' found.
++ * testsuite/demangle-expected: Add examples of strings that could
++ crash the demangler by reading past end of input.
++
++2016-11-06 Mark Wielaard <mark@klomp.org>
++
++ * configure.ac (ac_libiberty_warn_cflags): Add -Wshadow=local.
++ * configure: Regenerated.
++
++2016-11-07 Jason Merrill <jason@redhat.com>
++
++ * cp-demangle.c (is_fnqual_component_type): New.
++ (d_encoding, d_print_comp_inner, d_print_mod_list): Use it.
++ (FNQUAL_COMPONENT_CASE): New.
++ (d_make_comp, has_return_type, d_print_comp_inner)
++ (d_print_function_type): Use it.
++ (next_is_type_qual): New.
++ (d_cv_qualifiers, d_print_mod): Handle noexcept and throw-spec.
++
++2016-11-02 Mark Wielaard <mjw@redhat.com>
++
++ * cplus-dem.c (demangle_signature): Move fall through comment.
++ (demangle_fund_type): Add fall through comment between 'G' and 'I'.
++ * hashtab.c (iterative_hash): Add fall through comments.
++ * regex.c (regex_compile): Add Fall through comment after '+'/'?'.
++ (byte_re_match_2_internal): Add Fall through comment after jump_n.
++ Change "Note fall through" to "Fall through".
++ (common_op_match_null_string_p): Return false after set_number_at
++ instead of fall through.
++
++2016-11-01 Jason Merrill <jason@redhat.com>
++
++ * cp-demangle.c (d_ctor_dtor_name): Handle inheriting constructor.
++
++2016-10-31 Mark Wielaard <mjw@redhat.com>
++
++ * cplus-dem.c (ada_demangle): Initialize demangled to NULL and
++ XDELETEVEC demangled when unknown.
++
++2016-09-19 Andrew Stubbs <ams@codesourcery.com>
++
++ * pex-win32.c (argv_to_cmdline): Quote zero-length parameters.
++ * testsuite/test-pexecute.c (main): Insert check for zero-length parameters.
++
++2016-09-10 Mark Wielaard <mjw@redhat.com>
++
++ * cp-demangle.c (d_substitution): Change struct demangle_component
++ variable name from c to dc.
++
++2016-08-12 Marek Polacek <polacek@redhat.com>
++
++ PR c/7652
++ * cp-demangle.c (d_print_mod): Add FALLTHRU.
++
++2016-08-04 Marcel Böhme <boehme.marcel@gmail.com>
++
++ PR c++/71696
++ * cplus-dem.c: Prevent infinite recursion when there is a cycle
++ in the referencing of remembered mangled types.
++ (work_stuff): New stack to keep track of the remembered mangled
++ types that are currently being processed.
++ (push_processed_type): New method to push currently processed
++ remembered type onto the stack.
++ (pop_processed_type): New method to pop currently processed
++ remembered type from the stack.
++ (work_stuff_copy_to_from): Copy values of new variables.
++ (delete_non_B_K_work_stuff): Free stack memory.
++ (demangle_args): Push/Pop currently processed remembered type.
++ (do_type): Do not demangle a cyclic reference and push/pop
++ referenced remembered type.
++
++2016-07-29 Aldy Hernandez <aldyh@redhat.com>
++
++ * make-relative-prefix.c (make_relative_prefix_1): Fall back to
++ malloc if alloca argument is greater than MAX_ALLOCA_SIZE.
++
++2016-07-15 Jason Merrill <jason@redhat.com>
+
+ * cp-demangle.c (cplus_demangle_operators): Add f[lrLR].
+ (d_expression_1): Handle them.
+@@ -39,15 +154,40 @@
+ (d_template_args_1): Split out from d_template_args.
+ (d_args_length): New.
+
+-2016-05-19 Jakub Jelinek <jakub@redhat.com>
++2016-07-13 Marcel Böhme <boehme.marcel@gmail.com>
++
++ PR c++/70926
++ * cplus-dem.c: Handle large values and overflow when demangling
++ length variables.
++ (demangle_template_value_parm): Read only until end of mangled string.
++ (do_hpacc_template_literal): Likewise.
++ (do_type): Handle overflow when demangling array indices.
++
++2016-06-12 Brooks Moses <bmoses@google.com>
++
++ * cp-demangle.c (cplus_demangle_print_callback): Avoid zero-length
++ VLAs.
+
+- Backported from mainline
+- 2016-05-19 Jakub Jelinek <jakub@redhat.com>
++2016-05-31 Alan Modra <amodra@gmail.com>
++
++ * xmemdup.c (xmemdup): Use xmalloc rather than xcalloc.
++
++2016-05-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70498
+ * cp-demangle.c (d_expression_1): Formatting fix.
+
+- 2016-05-02 Marcel Böhme <boehme.marcel@gmail.com>
++2016-05-18 Artemiy Volkov <artemiyv@acm.org>
++
++ * cplus-dem.c (enum type_kind_t): Add tk_rvalue_reference
++ constant.
++ (demangle_template_value_parm): Handle tk_rvalue_reference
++ type kind.
++ (do_type): Support 'O' type id (rvalue references).
++
++ * testsuite/demangle-expected: Add tests.
++
++2016-05-02 Marcel Böhme <boehme.marcel@gmail.com>
+
+ PR c++/70498
+ * cp-demangle.c: Parse numbers as integer instead of long to avoid
+@@ -66,9 +206,9 @@
+ (d_unnamed_type): Likewise.
+ * testsuite/demangle-expected: Add regression test cases.
+
+-2016-04-27 Release Manager
++2016-04-30 Oleg Endo <olegendo@gcc.gnu.org>
+
+- * GCC 6.1.0 released.
++ * configure: Remove SH5 support.
+
+ 2016-04-08 Marcel Böhme <boehme.marcel@gmail.com>
+
+@@ -141,8 +281,6 @@
+
+ PR other/61321
+ PR other/61233
+- * demangle.h (enum demangle_component_type)
+- <DEMANGLE_COMPONENT_CONVERSION>: New value.
+ * cp-demangle.c (d_demangle_callback, d_make_comp): Handle
+ DEMANGLE_COMPONENT_CONVERSION.
+ (is_ctor_dtor_or_conversion): Handle DEMANGLE_COMPONENT_CONVERSION
+@@ -729,11 +867,11 @@
+ 2013-05-31 Matt Burgess <matthew@linuxfromscratch.org>
+
+ PR other/56780
+- * libiberty/configure.ac: Move test for --enable-install-libiberty
++ * configure.ac: Move test for --enable-install-libiberty
+ outside of the 'with_target_subdir' test so that it actually gets
+ run. Add output messages to show the test result.
+- * libiberty/configure: Regenerate.
+- * libiberty/Makefile.in (install_to_libdir): Place the
++ * configure: Regenerate.
++ * Makefile.in (install_to_libdir): Place the
+ installation of the libiberty library in the same guard as that
+ used for the headers to prevent it being installed unless
+ requested via --enable-install-libiberty.
+@@ -1533,7 +1671,6 @@
+ Daniel Jacobowitz <dan@codesourcery.com>
+ Pedro Alves <pedro@codesourcery.com>
+
+- libiberty/
+ * argv.c (consume_whitespace): New function.
+ (only_whitespace): New function.
+ (buildargv): Always use ISSPACE by calling consume_whitespace.
+@@ -1734,8 +1871,8 @@
+
+ 2009-04-07 Arnaud Patard <apatard@mandriva.com>
+
+- * libiberty/configure.ac: Fix Linux/MIPS matching rule.
+- * libiberty/configure: Regenerate.
++ * configure.ac: Fix Linux/MIPS matching rule.
++ * configure: Regenerate.
+
+ 2009-03-27 Ian Lance Taylor <iant@google.com>
+
+@@ -1898,8 +2035,8 @@
+
+ 2008-04-21 Aurelien Jarno <aurelien@aurel32.net>
+
+- * libiberty/configure.ac: use -fPIC on Linux/MIPS hosts.
+- * libiberty/configure: Regenerate.
++ * configure.ac: use -fPIC on Linux/MIPS hosts.
++ * configure: Regenerate.
+
+ 2008-04-18 Kris Van Hees <kris.van.hees@oracle.com>
+
+@@ -3677,7 +3814,7 @@
+
+ 2003-12-15 Brendan Kehoe <brendan@zen.org>
+
+- * libiberty/Makefile.in (floatformat.o): Add dependency on
++ * Makefile.in (floatformat.o): Add dependency on
+ config.h to accompany change of 2003-12-03.
+
+ 2003-12-15 Ian Lance Taylor <ian@wasabisystems.com>
+@@ -4373,7 +4510,7 @@
+
+ 2002-10-06 Andreas Jaeger <aj@suse.de>
+
+- * libiberty/cplus-dem.c (ada_demangle): Get rid of unneeded
++ * cplus-dem.c (ada_demangle): Get rid of unneeded
+ variable and of strict-aliasing warning.
+ (grow_vect): Use char as first parameter.
+
+@@ -4641,7 +4778,7 @@
+
+ 2002-01-31 Adam Megacz <adam@xwt.org>
+
+- * gcc/libiberty/configure.in: Treat mingw the same as cywin
++ * configure.in: Treat mingw the same as cywin
+ wrt HAVE_SYS_ERRLIST.
+
+ 2002-01-30 Phil Edwards <pme@gcc.gnu.org>
+@@ -5149,8 +5286,8 @@ Tue Aug 21 12:35:04 2001 Christopher Fa
+ 2001-03-10 Neil Booth <neil@daikokuya.demon.co.uk>
+ John David Anglin <dave@hiauly1.hia.nrc.ca>
+
+- * libiberty/lbasename.c: New file.
+- * libiberty/Makefile.in: Update for lbasename.
++ * lbasename.c: New file.
++ * Makefile.in: Update for lbasename.
+
+ 2001-03-06 Zack Weinberg <zackw@stanford.edu>
+
+@@ -5523,13 +5660,13 @@ Tue Aug 21 12:35:04 2001 Christopher Fa
+
+ 2000-08-24 Greg McGary <greg@mcgary.org>
+
+- * libiberty/random.c (end_ptr): Revert previous change.
++ * random.c (end_ptr): Revert previous change.
+
+ 2000-08-24 Greg McGary <greg@mcgary.org>
+
+- * libiberty/cplus-dem.c (cplus_demangle_opname, cplus_mangle_opname,
++ * cplus-dem.c (cplus_demangle_opname, cplus_mangle_opname,
+ demangle_expression, demangle_function_name): Use ARRAY_SIZE.
+- * libiberty/random.c (end_ptr): Likewise.
++ * random.c (end_ptr): Likewise.
+
+ 2000-08-23 Alex Samuel <samuel@codesourcery.com>
+
+Index: b/src/libiberty/configure
+===================================================================
+--- a/src/libiberty/configure
++++ b/src/libiberty/configure
+@@ -4398,7 +4398,8 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
+ ac_libiberty_warn_cflags=
+ save_CFLAGS="$CFLAGS"
+ for real_option in -W -Wall -Wwrite-strings -Wc++-compat \
+- -Wstrict-prototypes; do
++ -Wstrict-prototypes \
++ -Wshadow=local; do
+ # Do the check with the no- prefix removed since gcc silently
+ # accepts any -Wno-* option on purpose
+ case $real_option in
+@@ -5145,8 +5146,7 @@ case "${host}" in
+ PICFLAG=-fpic
+ ;;
+ # FIXME: Simplify to sh*-*-netbsd*?
+- sh-*-netbsdelf* | shl*-*-netbsdelf* | sh5-*-netbsd* | sh5l*-*-netbsd* | \
+- sh64-*-netbsd* | sh64l*-*-netbsd*)
++ sh-*-netbsdelf* | shl*-*-netbsdelf*)
+ PICFLAG=-fpic
+ ;;
+ # Default to -fPIC unless specified otherwise.
+Index: b/src/libiberty/configure.ac
+===================================================================
+--- a/src/libiberty/configure.ac
++++ b/src/libiberty/configure.ac
+@@ -160,7 +160,8 @@ AC_SYS_LARGEFILE
+ AC_PROG_CPP_WERROR
+
+ ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wc++-compat \
+- -Wstrict-prototypes], [ac_libiberty_warn_cflags])
++ -Wstrict-prototypes \
++ -Wshadow=local], [ac_libiberty_warn_cflags])
+ ACX_PROG_CC_WARNING_ALMOST_PEDANTIC([], [ac_libiberty_warn_cflags])
+
+ AC_PROG_CC_C_O
+Index: b/src/libiberty/cp-demangle.c
+===================================================================
+--- a/src/libiberty/cp-demangle.c
++++ b/src/libiberty/cp-demangle.c
+@@ -439,6 +439,8 @@ static struct demangle_component *d_oper
+
+ static struct demangle_component *d_special_name (struct d_info *);
+
++static struct demangle_component *d_parmlist (struct d_info *);
++
+ static int d_call_offset (struct d_info *, int);
+
+ static struct demangle_component *d_ctor_dtor_name (struct d_info *);
+@@ -562,6 +564,32 @@ static int d_demangle_callback (const ch
+ demangle_callbackref, void *);
+ static char *d_demangle (const char *, int, size_t *);
+
++/* True iff TYPE is a demangling component representing a
++ function-type-qualifier. */
++
++static int
++is_fnqual_component_type (enum demangle_component_type type)
++{
++ return (type == DEMANGLE_COMPONENT_RESTRICT_THIS
++ || type == DEMANGLE_COMPONENT_VOLATILE_THIS
++ || type == DEMANGLE_COMPONENT_CONST_THIS
++ || type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
++ || type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
++ || type == DEMANGLE_COMPONENT_NOEXCEPT
++ || type == DEMANGLE_COMPONENT_THROW_SPEC
++ || type == DEMANGLE_COMPONENT_REFERENCE_THIS);
++}
++
++#define FNQUAL_COMPONENT_CASE \
++ case DEMANGLE_COMPONENT_RESTRICT_THIS: \
++ case DEMANGLE_COMPONENT_VOLATILE_THIS: \
++ case DEMANGLE_COMPONENT_CONST_THIS: \
++ case DEMANGLE_COMPONENT_REFERENCE_THIS: \
++ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS: \
++ case DEMANGLE_COMPONENT_TRANSACTION_SAFE: \
++ case DEMANGLE_COMPONENT_NOEXCEPT: \
++ case DEMANGLE_COMPONENT_THROW_SPEC
++
+ #ifdef CP_DEMANGLE_DEBUG
+
+ static void
+@@ -987,14 +1015,9 @@ d_make_comp (struct d_info *di, enum dem
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_CONST:
+- case DEMANGLE_COMPONENT_RESTRICT_THIS:
+- case DEMANGLE_COMPONENT_VOLATILE_THIS:
+- case DEMANGLE_COMPONENT_CONST_THIS:
+- case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+- case DEMANGLE_COMPONENT_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_ARGLIST:
+ case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
++ FNQUAL_COMPONENT_CASE:
+ break;
+
+ /* Other types should not be seen here. */
+@@ -1228,12 +1251,7 @@ has_return_type (struct demangle_compone
+ return 0;
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ return ! is_ctor_dtor_or_conversion (d_left (dc));
+- case DEMANGLE_COMPONENT_RESTRICT_THIS:
+- case DEMANGLE_COMPONENT_VOLATILE_THIS:
+- case DEMANGLE_COMPONENT_CONST_THIS:
+- case DEMANGLE_COMPONENT_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
++ FNQUAL_COMPONENT_CASE:
+ return has_return_type (d_left (dc));
+ }
+ }
+@@ -1290,13 +1308,12 @@ d_encoding (struct d_info *di, int top_l
+ while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+ || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+ || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+- || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
+ || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+ || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
+ dc = d_left (dc);
+
+ /* If the top level is a DEMANGLE_COMPONENT_LOCAL_NAME, then
+- there may be CV-qualifiers on its right argument which
++ there may be function-qualifiers on its right argument which
+ really apply here; this happens when parsing a class
+ which is local to a function. */
+ if (dc->type == DEMANGLE_COMPONENT_LOCAL_NAME)
+@@ -1304,12 +1321,7 @@ d_encoding (struct d_info *di, int top_l
+ struct demangle_component *dcr;
+
+ dcr = d_right (dc);
+- while (dcr->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+- || dcr->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+- || dcr->type == DEMANGLE_COMPONENT_CONST_THIS
+- || dcr->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
+- || dcr->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+- || dcr->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
++ while (is_fnqual_component_type (dcr->type))
+ dcr = d_left (dcr);
+ dc->u.s_binary.right = dcr;
+ }
+@@ -2171,6 +2183,13 @@ d_ctor_dtor_name (struct d_info *di)
+ case 'C':
+ {
+ enum gnu_v3_ctor_kinds kind;
++ int inheriting = 0;
++
++ if (d_peek_next_char (di) == 'I')
++ {
++ inheriting = 1;
++ d_advance (di, 1);
++ }
+
+ switch (d_peek_next_char (di))
+ {
+@@ -2192,7 +2211,12 @@ d_ctor_dtor_name (struct d_info *di)
+ default:
+ return NULL;
+ }
++
+ d_advance (di, 2);
++
++ if (inheriting)
++ cplus_demangle_type (di);
++
+ return d_make_ctor (di, kind, di->last_name);
+ }
+
+@@ -2230,6 +2254,24 @@ d_ctor_dtor_name (struct d_info *di)
+ }
+ }
+
++/* True iff we're looking at an order-insensitive type-qualifier, including
++ function-type-qualifiers. */
++
++static int
++next_is_type_qual (struct d_info *di)
++{
++ char peek = d_peek_char (di);
++ if (peek == 'r' || peek == 'V' || peek == 'K')
++ return 1;
++ if (peek == 'D')
++ {
++ peek = d_peek_next_char (di);
++ if (peek == 'x' || peek == 'o' || peek == 'O' || peek == 'w')
++ return 1;
++ }
++ return 0;
++}
++
+ /* <type> ::= <builtin-type>
+ ::= <function-type>
+ ::= <class-enum-type>
+@@ -2315,9 +2357,7 @@ cplus_demangle_type (struct d_info *di)
+ __vector, and it treats it as order-sensitive when mangling
+ names. */
+
+- peek = d_peek_char (di);
+- if (peek == 'r' || peek == 'V' || peek == 'K'
+- || (peek == 'D' && d_peek_next_char (di) == 'x'))
++ if (next_is_type_qual (di))
+ {
+ struct demangle_component **pret;
+
+@@ -2352,6 +2392,7 @@ cplus_demangle_type (struct d_info *di)
+
+ can_subst = 1;
+
++ peek = d_peek_char (di);
+ switch (peek)
+ {
+ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
+@@ -2643,10 +2684,10 @@ d_cv_qualifiers (struct d_info *di,
+
+ pstart = pret;
+ peek = d_peek_char (di);
+- while (peek == 'r' || peek == 'V' || peek == 'K'
+- || (peek == 'D' && d_peek_next_char (di) == 'x'))
++ while (next_is_type_qual (di))
+ {
+ enum demangle_component_type t;
++ struct demangle_component *right = NULL;
+
+ d_advance (di, 1);
+ if (peek == 'r')
+@@ -2672,12 +2713,41 @@ d_cv_qualifiers (struct d_info *di,
+ }
+ else
+ {
+- t = DEMANGLE_COMPONENT_TRANSACTION_SAFE;
+- di->expansion += sizeof "transaction_safe";
+- d_advance (di, 1);
++ peek = d_next_char (di);
++ if (peek == 'x')
++ {
++ t = DEMANGLE_COMPONENT_TRANSACTION_SAFE;
++ di->expansion += sizeof "transaction_safe";
++ }
++ else if (peek == 'o'
++ || peek == 'O')
++ {
++ t = DEMANGLE_COMPONENT_NOEXCEPT;
++ di->expansion += sizeof "noexcept";
++ if (peek == 'O')
++ {
++ right = d_expression (di);
++ if (right == NULL)
++ return NULL;
++ if (! d_check_char (di, 'E'))
++ return NULL;
++ }
++ }
++ else if (peek == 'w')
++ {
++ t = DEMANGLE_COMPONENT_THROW_SPEC;
++ di->expansion += sizeof "throw";
++ right = d_parmlist (di);
++ if (right == NULL)
++ return NULL;
++ if (! d_check_char (di, 'E'))
++ return NULL;
++ }
++ else
++ return NULL;
+ }
+
+- *pret = d_make_comp (di, t, NULL, NULL);
++ *pret = d_make_comp (di, t, NULL, right);
+ if (*pret == NULL)
+ return NULL;
+ pret = &d_left (*pret);
+@@ -3352,6 +3422,8 @@ d_expression_1 (struct d_info *di)
+ first = d_expression_1 (di);
+ second = d_expression_1 (di);
+ third = d_expression_1 (di);
++ if (third == NULL)
++ return NULL;
+ }
+ else if (code[0] == 'f')
+ {
+@@ -3359,6 +3431,8 @@ d_expression_1 (struct d_info *di)
+ first = d_operator_name (di);
+ second = d_expression_1 (di);
+ third = d_expression_1 (di);
++ if (third == NULL)
++ return NULL;
+ }
+ else if (code[0] == 'n')
+ {
+@@ -3776,7 +3850,7 @@ d_substitution (struct d_info *di, int p
+ {
+ const char *s;
+ int len;
+- struct demangle_component *c;
++ struct demangle_component *dc;
+
+ if (p->set_last_name != NULL)
+ di->last_name = d_make_sub (di, p->set_last_name,
+@@ -3792,15 +3866,15 @@ d_substitution (struct d_info *di, int p
+ len = p->simple_len;
+ }
+ di->expansion += len;
+- c = d_make_sub (di, s, len);
++ dc = d_make_sub (di, s, len);
+ if (d_peek_char (di) == 'B')
+ {
+ /* If there are ABI tags on the abbreviation, it becomes
+ a substitution candidate. */
+- c = d_abi_tags (di, c);
+- d_add_substitution (di, c);
++ dc = d_abi_tags (di, dc);
++ d_add_substitution (di, dc);
+ }
+- return c;
++ return dc;
+ }
+ }
+
+@@ -3968,6 +4042,8 @@ d_count_templates_scopes (int *num_templ
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
++ case DEMANGLE_COMPONENT_NOEXCEPT:
++ case DEMANGLE_COMPONENT_THROW_SPEC:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_COMPLEX:
+@@ -4163,8 +4239,12 @@ cplus_demangle_print_callback (int optio
+
+ {
+ #ifdef CP_DYNAMIC_ARRAYS
+- __extension__ struct d_saved_scope scopes[dpi.num_saved_scopes];
+- __extension__ struct d_print_template temps[dpi.num_copy_templates];
++ /* Avoid zero-length VLAs, which are prohibited by the C99 standard
++ and flagged as errors by Address Sanitizer. */
++ __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0)
++ ? dpi.num_saved_scopes : 1];
++ __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0)
++ ? dpi.num_copy_templates : 1];
+
+ dpi.saved_scopes = scopes;
+ dpi.copy_templates = temps;
+@@ -4492,7 +4572,7 @@ d_maybe_print_fold_expression (struct d_
+
+ static void
+ d_print_comp_inner (struct d_print_info *dpi, int options,
+- const struct demangle_component *dc)
++ const struct demangle_component *dc)
+ {
+ /* Magic variable to let reference smashing skip over the next modifier
+ without needing to modify *dc. */
+@@ -4579,12 +4659,7 @@ d_print_comp_inner (struct d_print_info
+ adpm[i].templates = dpi->templates;
+ ++i;
+
+- if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
+- && typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
+- && typed_name->type != DEMANGLE_COMPONENT_CONST_THIS
+- && typed_name->type != DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+- && typed_name->type != DEMANGLE_COMPONENT_TRANSACTION_SAFE
+- && typed_name->type != DEMANGLE_COMPONENT_REFERENCE_THIS)
++ if (!is_fnqual_component_type (typed_name->type))
+ break;
+
+ typed_name = d_left (typed_name);
+@@ -4621,13 +4696,7 @@ d_print_comp_inner (struct d_print_info
+ d_print_error (dpi);
+ return;
+ }
+- while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+- || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+- || local_name->type == DEMANGLE_COMPONENT_CONST_THIS
+- || local_name->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+- || local_name->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
+- || (local_name->type
+- == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))
++ while (is_fnqual_component_type (local_name->type))
+ {
+ if (i >= sizeof adpm / sizeof adpm[0])
+ {
+@@ -4961,16 +5030,11 @@ d_print_comp_inner (struct d_print_info
+ }
+ /* Fall through. */
+
+- case DEMANGLE_COMPONENT_RESTRICT_THIS:
+- case DEMANGLE_COMPONENT_VOLATILE_THIS:
+- case DEMANGLE_COMPONENT_CONST_THIS:
+- case DEMANGLE_COMPONENT_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_COMPLEX:
+ case DEMANGLE_COMPONENT_IMAGINARY:
+- case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
++ FNQUAL_COMPONENT_CASE:
+ modifier:
+ {
+ /* We keep a list of modifiers on the stack. */
+@@ -5679,13 +5743,7 @@ d_print_mod_list (struct d_print_info *d
+
+ if (mods->printed
+ || (! suffix
+- && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+- || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+- || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS
+- || mods->mod->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+- || mods->mod->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
+- || (mods->mod->type
+- == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS))))
++ && (is_fnqual_component_type (mods->mod->type))))
+ {
+ d_print_mod_list (dpi, options, mods->next, suffix);
+ return;
+@@ -5738,12 +5796,7 @@ d_print_mod_list (struct d_print_info *d
+ dc = dc->u.s_unary_num.sub;
+ }
+
+- while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
+- || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
+- || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+- || dc->type == DEMANGLE_COMPONENT_REFERENCE_THIS
+- || dc->type == DEMANGLE_COMPONENT_TRANSACTION_SAFE
+- || dc->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS)
++ while (is_fnqual_component_type (dc->type))
+ dc = d_left (dc);
+
+ d_print_comp (dpi, options, dc);
+@@ -5782,6 +5835,24 @@ d_print_mod (struct d_print_info *dpi, i
+ case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+ d_append_string (dpi, " transaction_safe");
+ return;
++ case DEMANGLE_COMPONENT_NOEXCEPT:
++ d_append_string (dpi, " noexcept");
++ if (d_right (mod))
++ {
++ d_append_char (dpi, '(');
++ d_print_comp (dpi, options, d_right (mod));
++ d_append_char (dpi, ')');
++ }
++ return;
++ case DEMANGLE_COMPONENT_THROW_SPEC:
++ d_append_string (dpi, " throw");
++ if (d_right (mod))
++ {
++ d_append_char (dpi, '(');
++ d_print_comp (dpi, options, d_right (mod));
++ d_append_char (dpi, ')');
++ }
++ return;
+ case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+ d_append_char (dpi, ' ');
+ d_print_comp (dpi, options, d_right (mod));
+@@ -5794,11 +5865,13 @@ d_print_mod (struct d_print_info *dpi, i
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ /* For the ref-qualifier, put a space before the &. */
+ d_append_char (dpi, ' ');
++ /* FALLTHRU */
+ case DEMANGLE_COMPONENT_REFERENCE:
+ d_append_char (dpi, '&');
+ return;
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+ d_append_char (dpi, ' ');
++ /* FALLTHRU */
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ d_append_string (dpi, "&&");
+ return;
+@@ -5867,12 +5940,7 @@ d_print_function_type (struct d_print_in
+ need_space = 1;
+ need_paren = 1;
+ break;
+- case DEMANGLE_COMPONENT_RESTRICT_THIS:
+- case DEMANGLE_COMPONENT_VOLATILE_THIS:
+- case DEMANGLE_COMPONENT_CONST_THIS:
+- case DEMANGLE_COMPONENT_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
++ FNQUAL_COMPONENT_CASE:
+ break;
+ default:
+ break;
+@@ -6414,7 +6482,6 @@ is_ctor_or_dtor (const char *mangled,
+ case DEMANGLE_COMPONENT_CONST_THIS:
+ case DEMANGLE_COMPONENT_REFERENCE_THIS:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+- case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+ default:
+ dc = NULL;
+ break;
+Index: b/src/libiberty/cplus-dem.c
+===================================================================
+--- a/src/libiberty/cplus-dem.c
++++ b/src/libiberty/cplus-dem.c
+@@ -144,6 +144,9 @@ struct work_stuff
+ string* previous_argument; /* The last function argument demangled. */
+ int nrepeats; /* The number of times to repeat the previous
+ argument. */
++ int *proctypevec; /* Indices of currently processed remembered typevecs. */
++ int proctypevec_size;
++ int nproctypes;
+ };
+
+ #define PRINT_ANSI_QUALIFIERS (work -> options & DMGL_ANSI)
+@@ -244,6 +247,7 @@ typedef enum type_kind_t
+ tk_none,
+ tk_pointer,
+ tk_reference,
++ tk_rvalue_reference,
+ tk_integral,
+ tk_bool,
+ tk_char,
+@@ -319,6 +323,12 @@ const struct demangler_engine libiberty_
+ }
+ ,
+ {
++ RUST_DEMANGLING_STYLE_STRING,
++ rust_demangling,
++ "Rust style demangling"
++ }
++ ,
++ {
+ NULL, unknown_demangling, NULL
+ }
+ };
+@@ -435,6 +445,10 @@ iterate_demangle_function (struct work_s
+
+ static void remember_type (struct work_stuff *, const char *, int);
+
++static void push_processed_type (struct work_stuff *, int);
++
++static void pop_processed_type (struct work_stuff *);
++
+ static void remember_Btype (struct work_stuff *, const char *, int, int);
+
+ static int register_Btype (struct work_stuff *);
+@@ -866,10 +880,26 @@ cplus_demangle (const char *mangled, int
+ work->options |= (int) current_demangling_style & DMGL_STYLE_MASK;
+
+ /* The V3 ABI demangling is implemented elsewhere. */
+- if (GNU_V3_DEMANGLING || AUTO_DEMANGLING)
++ if (GNU_V3_DEMANGLING || RUST_DEMANGLING || AUTO_DEMANGLING)
+ {
+ ret = cplus_demangle_v3 (mangled, work->options);
+- if (ret || GNU_V3_DEMANGLING)
++ if (GNU_V3_DEMANGLING)
++ return ret;
++
++ if (ret)
++ {
++ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions.
++ The subtitutions are always smaller, so do in place changes. */
++ if (rust_is_mangled (ret))
++ rust_demangle_sym (ret);
++ else if (RUST_DEMANGLING)
++ {
++ free (ret);
++ ret = NULL;
++ }
++ }
++
++ if (ret || RUST_DEMANGLING)
+ return ret;
+ }
+
+@@ -895,6 +925,27 @@ cplus_demangle (const char *mangled, int
+ return (ret);
+ }
+
++char *
++rust_demangle (const char *mangled, int options)
++{
++ /* Rust symbols are GNU_V3 mangled plus some extra subtitutions. */
++ char *ret = cplus_demangle_v3 (mangled, options);
++
++ /* The Rust subtitutions are always smaller, so do in place changes. */
++ if (ret != NULL)
++ {
++ if (rust_is_mangled (ret))
++ rust_demangle_sym (ret);
++ else
++ {
++ free (ret);
++ ret = NULL;
++ }
++ }
++
++ return ret;
++}
++
+ /* Demangle ada names. The encoding is documented in gcc/ada/exp_dbug.ads. */
+
+ char *
+@@ -903,7 +954,7 @@ ada_demangle (const char *mangled, int o
+ int len0;
+ const char* p;
+ char *d;
+- char *demangled;
++ char *demangled = NULL;
+
+ /* Discard leading _ada_, which is used for library level subprograms. */
+ if (strncmp (mangled, "_ada_", 5) == 0)
+@@ -1148,6 +1199,7 @@ ada_demangle (const char *mangled, int o
+ return demangled;
+
+ unknown:
++ XDELETEVEC (demangled);
+ len0 = strlen (mangled);
+ demangled = XNEWVEC (char, len0 + 3);
+
+@@ -1301,6 +1353,10 @@ work_stuff_copy_to_from (struct work_stu
+ memcpy (to->btypevec[i], from->btypevec[i], len);
+ }
+
++ if (from->proctypevec)
++ to->proctypevec =
++ XDUPVEC (int, from->proctypevec, from->proctypevec_size);
++
+ if (from->ntmpl_args)
+ to->tmpl_argvec = XNEWVEC (char *, from->ntmpl_args);
+
+@@ -1329,11 +1385,17 @@ delete_non_B_K_work_stuff (struct work_s
+ /* Discard the remembered types, if any. */
+
+ forget_types (work);
+- if (work -> typevec != NULL)
++ if (work->typevec != NULL)
++ {
++ free ((char *) work->typevec);
++ work->typevec = NULL;
++ work->typevec_size = 0;
++ }
++ if (work->proctypevec != NULL)
+ {
+- free ((char *) work -> typevec);
+- work -> typevec = NULL;
+- work -> typevec_size = 0;
++ free (work->proctypevec);
++ work->proctypevec = NULL;
++ work->proctypevec_size = 0;
+ }
+ if (work->tmpl_argvec)
+ {
+@@ -1635,12 +1697,13 @@ demangle_signature (struct work_stuff *w
+ 0);
+ if (!(work->constructor & 1))
+ expect_return_type = 1;
+- (*mangled)++;
++ if (!**mangled)
++ success = 0;
++ else
++ (*mangled)++;
+ break;
+ }
+- else
+- /* fall through */
+- {;}
++ /* fall through */
+
+ default:
+ if (AUTO_DEMANGLING || GNU_DEMANGLING)
+@@ -2042,7 +2105,8 @@ demangle_template_value_parm (struct wor
+ }
+ else if (tk == tk_real)
+ success = demangle_real_value (work, mangled, s);
+- else if (tk == tk_pointer || tk == tk_reference)
++ else if (tk == tk_pointer || tk == tk_reference
++ || tk == tk_rvalue_reference)
+ {
+ if (**mangled == 'Q')
+ success = demangle_qualified (work, mangled, s,
+@@ -2051,7 +2115,8 @@ demangle_template_value_parm (struct wor
+ else
+ {
+ int symbol_len = consume_count (mangled);
+- if (symbol_len == -1)
++ if (symbol_len == -1
++ || symbol_len > (long) strlen (*mangled))
+ return -1;
+ if (symbol_len == 0)
+ string_appendn (s, "0", 1);
+@@ -2114,6 +2179,8 @@ demangle_template (struct work_stuff *wo
+ {
+ int idx;
+ (*mangled)++;
++ if (**mangled == '\0')
++ return (0);
+ (*mangled)++;
+
+ idx = consume_count_with_underscores (mangled);
+@@ -2958,7 +3025,7 @@ gnu_special (struct work_stuff *work, co
+ int success = 1;
+ const char *p;
+
+- if ((*mangled)[0] == '_'
++ if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
+ && strchr (cplus_markers, (*mangled)[1]) != NULL
+ && (*mangled)[2] == '_')
+ {
+@@ -2972,7 +3039,7 @@ gnu_special (struct work_stuff *work, co
+ && (*mangled)[3] == 't'
+ && (*mangled)[4] == '_')
+ || ((*mangled)[1] == 'v'
+- && (*mangled)[2] == 't'
++ && (*mangled)[2] == 't' && (*mangled)[3] != '\0'
+ && strchr (cplus_markers, (*mangled)[3]) != NULL)))
+ {
+ /* Found a GNU style virtual table, get past "_vt<CPLUS_MARKER>"
+@@ -3552,6 +3619,8 @@ static int
+ do_type (struct work_stuff *work, const char **mangled, string *result)
+ {
+ int n;
++ int i;
++ int is_proctypevec;
+ int done;
+ int success;
+ string decl;
+@@ -3564,6 +3633,7 @@ do_type (struct work_stuff *work, const
+
+ done = 0;
+ success = 1;
++ is_proctypevec = 0;
+ while (success && !done)
+ {
+ int member;
+@@ -3588,6 +3658,14 @@ do_type (struct work_stuff *work, const
+ tk = tk_reference;
+ break;
+
++ /* An rvalue reference type */
++ case 'O':
++ (*mangled)++;
++ string_prepend (&decl, "&&");
++ if (tk == tk_none)
++ tk = tk_rvalue_reference;
++ break;
++
+ /* An array */
+ case 'A':
+ {
+@@ -3611,13 +3689,20 @@ do_type (struct work_stuff *work, const
+ /* A back reference to a previously seen type */
+ case 'T':
+ (*mangled)++;
+- if (!get_count (mangled, &n) || n >= work -> ntypes)
++ if (!get_count (mangled, &n) || n < 0 || n >= work -> ntypes)
+ {
+ success = 0;
+ }
+ else
+- {
+- remembered_type = work -> typevec[n];
++ for (i = 0; i < work->nproctypes; i++)
++ if (work -> proctypevec [i] == n)
++ success = 0;
++
++ if (success)
++ {
++ is_proctypevec = 1;
++ push_processed_type (work, n);
++ remembered_type = work->typevec[n];
+ mangled = &remembered_type;
+ }
+ break;
+@@ -3645,7 +3730,6 @@ do_type (struct work_stuff *work, const
+ break;
+
+ case 'M':
+- case 'O':
+ {
+ type_quals = TYPE_UNQUALIFIED;
+
+@@ -3725,11 +3809,12 @@ do_type (struct work_stuff *work, const
+ break;
+ }
+
+- if (*(*mangled)++ != 'F')
++ if (*(*mangled) != 'F')
+ {
+ success = 0;
+ break;
+ }
++ (*mangled)++;
+ }
+ if ((member && !demangle_nested_args (work, mangled, &decl))
+ || **mangled != '_')
+@@ -3789,7 +3874,7 @@ do_type (struct work_stuff *work, const
+ /* A back reference to a previously seen squangled type */
+ case 'B':
+ (*mangled)++;
+- if (!get_count (mangled, &n) || n >= work -> numb)
++ if (!get_count (mangled, &n) || n < 0 || n >= work -> numb)
+ success = 0;
+ else
+ string_append (result, work->btypevec[n]);
+@@ -3840,6 +3925,9 @@ do_type (struct work_stuff *work, const
+ string_delete (result);
+ string_delete (&decl);
+
++ if (is_proctypevec)
++ pop_processed_type (work);
++
+ if (success)
+ /* Assume an integral type, if we're not sure. */
+ return (int) ((tk == tk_none) ? tk_integral : tk);
+@@ -3983,6 +4071,7 @@ demangle_fund_type (struct work_stuff *w
+ success = 0;
+ break;
+ }
++ /* fall through */
+ case 'I':
+ (*mangled)++;
+ if (**mangled == '_')
+@@ -4130,7 +4219,8 @@ do_hpacc_template_literal (struct work_s
+
+ literal_len = consume_count (mangled);
+
+- if (literal_len <= 0)
++ if (literal_len <= 0
++ || literal_len > (long) strlen (*mangled))
+ return 0;
+
+ /* Literal parameters are names of arrays, functions, etc. and the
+@@ -4252,6 +4342,41 @@ do_arg (struct work_stuff *work, const c
+ }
+
+ static void
++push_processed_type (struct work_stuff *work, int typevec_index)
++{
++ if (work->nproctypes >= work->proctypevec_size)
++ {
++ if (!work->proctypevec_size)
++ {
++ work->proctypevec_size = 4;
++ work->proctypevec = XNEWVEC (int, work->proctypevec_size);
++ }
++ else
++ {
++ if (work->proctypevec_size < 16)
++ /* Double when small. */
++ work->proctypevec_size *= 2;
++ else
++ {
++ /* Grow slower when large. */
++ if (work->proctypevec_size > (INT_MAX / 3) * 2)
++ xmalloc_failed (INT_MAX);
++ work->proctypevec_size = (work->proctypevec_size * 3 / 2);
++ }
++ work->proctypevec
++ = XRESIZEVEC (int, work->proctypevec, work->proctypevec_size);
++ }
++ }
++ work->proctypevec [work->nproctypes++] = typevec_index;
++}
++
++static void
++pop_processed_type (struct work_stuff *work)
++{
++ work->nproctypes--;
++}
++
++static void
+ remember_type (struct work_stuff *work, const char *start, int len)
+ {
+ char *tem;
+@@ -4515,10 +4640,13 @@ demangle_args (struct work_stuff *work,
+ {
+ string_append (declp, ", ");
+ }
++ push_processed_type (work, t);
+ if (!do_arg (work, &tem, &arg))
+ {
++ pop_processed_type (work);
+ return (0);
+ }
++ pop_processed_type (work);
+ if (PRINT_ARG_TYPES)
+ {
+ string_appends (declp, &arg);
+Index: b/src/libiberty/hashtab.c
+===================================================================
+--- a/src/libiberty/hashtab.c
++++ b/src/libiberty/hashtab.c
+@@ -962,17 +962,17 @@ iterative_hash (const PTR k_in /* the ke
+ c += length;
+ switch(len) /* all the case statements fall through */
+ {
+- case 11: c+=((hashval_t)k[10]<<24);
+- case 10: c+=((hashval_t)k[9]<<16);
+- case 9 : c+=((hashval_t)k[8]<<8);
++ case 11: c+=((hashval_t)k[10]<<24); /* fall through */
++ case 10: c+=((hashval_t)k[9]<<16); /* fall through */
++ case 9 : c+=((hashval_t)k[8]<<8); /* fall through */
+ /* the first byte of c is reserved for the length */
+- case 8 : b+=((hashval_t)k[7]<<24);
+- case 7 : b+=((hashval_t)k[6]<<16);
+- case 6 : b+=((hashval_t)k[5]<<8);
+- case 5 : b+=k[4];
+- case 4 : a+=((hashval_t)k[3]<<24);
+- case 3 : a+=((hashval_t)k[2]<<16);
+- case 2 : a+=((hashval_t)k[1]<<8);
++ case 8 : b+=((hashval_t)k[7]<<24); /* fall through */
++ case 7 : b+=((hashval_t)k[6]<<16); /* fall through */
++ case 6 : b+=((hashval_t)k[5]<<8); /* fall through */
++ case 5 : b+=k[4]; /* fall through */
++ case 4 : a+=((hashval_t)k[3]<<24); /* fall through */
++ case 3 : a+=((hashval_t)k[2]<<16); /* fall through */
++ case 2 : a+=((hashval_t)k[1]<<8); /* fall through */
+ case 1 : a+=k[0];
+ /* case 0: nothing left to add */
+ }
+Index: b/src/libiberty/Makefile.in
+===================================================================
+--- a/src/libiberty/Makefile.in
++++ b/src/libiberty/Makefile.in
+@@ -146,6 +146,7 @@ CFILES = alloca.c argv.c asprintf.c atex
+ pex-unix.c pex-win32.c \
+ physmem.c putenv.c \
+ random.c regex.c rename.c rindex.c \
++ rust-demangle.c \
+ safe-ctype.c setenv.c setproctitle.c sha1.c sigsetmask.c \
+ simple-object.c simple-object-coff.c simple-object-elf.c \
+ simple-object-mach-o.c simple-object-xcoff.c \
+@@ -183,6 +184,7 @@ REQUIRED_OFILES = \
+ ./partition.$(objext) ./pexecute.$(objext) ./physmem.$(objext) \
+ ./pex-common.$(objext) ./pex-one.$(objext) \
+ ./@pexecute@.$(objext) ./vprintf-support.$(objext) \
++ ./rust-demangle.$(objext) \
+ ./safe-ctype.$(objext) \
+ ./simple-object.$(objext) ./simple-object-coff.$(objext) \
+ ./simple-object-elf.$(objext) ./simple-object-mach-o.$(objext) \
+@@ -1188,6 +1190,17 @@ $(CONFIGURED_OFILES): stamp-picdir stamp
+ else true; fi
+ $(COMPILE.c) $(srcdir)/rindex.c $(OUTPUT_OPTION)
+
++./rust-demangle.$(objext): $(srcdir)/rust-demangle.c config.h \
++ $(INCDIR)/ansidecl.h $(INCDIR)/demangle.h $(INCDIR)/libiberty.h \
++ $(INCDIR)/safe-ctype.h
++ if [ x"$(PICFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(srcdir)/rust-demangle.c -o pic/$@; \
++ else true; fi
++ if [ x"$(NOASANFLAG)" != x ]; then \
++ $(COMPILE.c) $(PICFLAG) $(NOASANFLAG) $(srcdir)/rust-demangle.c -o noasan/$@; \
++ else true; fi
++ $(COMPILE.c) $(srcdir)/rust-demangle.c $(OUTPUT_OPTION)
++
+ ./safe-ctype.$(objext): $(srcdir)/safe-ctype.c $(INCDIR)/ansidecl.h \
+ $(INCDIR)/safe-ctype.h
+ if [ x"$(PICFLAG)" != x ]; then \
+Index: b/src/libiberty/make-relative-prefix.c
+===================================================================
+--- a/src/libiberty/make-relative-prefix.c
++++ b/src/libiberty/make-relative-prefix.c
+@@ -233,6 +233,7 @@ make_relative_prefix_1 (const char *prog
+ int i, n, common;
+ int needed_len;
+ char *ret = NULL, *ptr, *full_progname;
++ char *alloc_ptr = NULL;
+
+ if (progname == NULL || bin_prefix == NULL || prefix == NULL)
+ return NULL;
+@@ -256,7 +257,10 @@ make_relative_prefix_1 (const char *prog
+ #ifdef HAVE_HOST_EXECUTABLE_SUFFIX
+ len += strlen (HOST_EXECUTABLE_SUFFIX);
+ #endif
+- nstore = (char *) alloca (len);
++ if (len < MAX_ALLOCA_SIZE)
++ nstore = (char *) alloca (len);
++ else
++ alloc_ptr = nstore = (char *) malloc (len);
+
+ startp = endp = temp;
+ while (1)
+@@ -312,12 +316,12 @@ make_relative_prefix_1 (const char *prog
+ else
+ full_progname = strdup (progname);
+ if (full_progname == NULL)
+- return NULL;
++ goto bailout;
+
+ prog_dirs = split_directories (full_progname, &prog_num);
+ free (full_progname);
+ if (prog_dirs == NULL)
+- return NULL;
++ goto bailout;
+
+ bin_dirs = split_directories (bin_prefix, &bin_num);
+ if (bin_dirs == NULL)
+@@ -395,6 +399,7 @@ make_relative_prefix_1 (const char *prog
+ free_split_directories (prog_dirs);
+ free_split_directories (bin_dirs);
+ free_split_directories (prefix_dirs);
++ free (alloc_ptr);
+
+ return ret;
+ }
+Index: b/src/libiberty/pex-win32.c
+===================================================================
+--- a/src/libiberty/pex-win32.c
++++ b/src/libiberty/pex-win32.c
+@@ -370,6 +370,8 @@ argv_to_cmdline (char *const *argv)
+ cmdline_len++;
+ }
+ }
++ if (j == 0)
++ needs_quotes = 1;
+ /* Trailing backslashes also need to be escaped because they will be
+ followed by the terminating quote. */
+ if (needs_quotes)
+@@ -394,6 +396,8 @@ argv_to_cmdline (char *const *argv)
+ break;
+ }
+ }
++ if (j == 0)
++ needs_quotes = 1;
+
+ if (needs_quotes)
+ {
+Index: b/src/libiberty/regex.c
+===================================================================
+--- a/src/libiberty/regex.c
++++ b/src/libiberty/regex.c
+@@ -2493,6 +2493,7 @@ PREFIX(regex_compile) (const char *ARG_P
+ if ((syntax & RE_BK_PLUS_QM)
+ || (syntax & RE_LIMITED_OPS))
+ goto normal_char;
++ /* Fall through. */
+ handle_plus:
+ case '*':
+ /* If there is no previous pattern... */
+@@ -6697,6 +6698,7 @@ byte_re_match_2_internal (struct re_patt
+ {
+ case jump_n:
+ is_a_jump_n = true;
++ /* Fall through. */
+ case pop_failure_jump:
+ case maybe_pop_jump:
+ case jump:
+@@ -7125,7 +7127,7 @@ byte_re_match_2_internal (struct re_patt
+ DEBUG_PRINT1 (" Match => jump.\n");
+ goto unconditional_jump;
+ }
+- /* Note fall through. */
++ /* Fall through. */
+
+
+ /* The end of a simple repeat has a pop_failure_jump back to
+@@ -7150,7 +7152,7 @@ byte_re_match_2_internal (struct re_patt
+ dummy_low_reg, dummy_high_reg,
+ reg_dummy, reg_dummy, reg_info_dummy);
+ }
+- /* Note fall through. */
++ /* Fall through. */
+
+ unconditional_jump:
+ #ifdef _LIBC
+@@ -7453,6 +7455,7 @@ byte_re_match_2_internal (struct re_patt
+ {
+ case jump_n:
+ is_a_jump_n = true;
++ /* Fall through. */
+ case maybe_pop_jump:
+ case pop_failure_jump:
+ case jump:
+@@ -7718,6 +7721,7 @@ PREFIX(common_op_match_null_string_p) (U
+
+ case set_number_at:
+ p1 += 2 * OFFSET_ADDRESS_SIZE;
++ return false;
+
+ default:
+ /* All other opcodes mean we cannot match the empty string. */
+Index: b/src/libiberty/rust-demangle.c
+===================================================================
+--- /dev/null
++++ b/src/libiberty/rust-demangle.c
+@@ -0,0 +1,348 @@
++/* Demangler for the Rust programming language
++ Copyright 2016 Free Software Foundation, Inc.
++ Written by David Tolnay (dtolnay@gmail.com).
++
++This file is part of the libiberty library.
++Libiberty is free software; you can redistribute it and/or
++modify it under the terms of the GNU Library General Public
++License as published by the Free Software Foundation; either
++version 2 of the License, or (at your option) any later version.
++
++In addition to the permissions in the GNU Library General Public
++License, the Free Software Foundation gives you unlimited permission
++to link the compiled version of this file into combinations with other
++programs, and to distribute those combinations without any restriction
++coming from the use of this file. (The Library Public License
++restrictions do apply in other respects; for example, they cover
++modification of the file, and distribution when not linked into a
++combined executable.)
++
++Libiberty is distributed in the hope that it will be useful,
++but WITHOUT ANY WARRANTY; without even the implied warranty of
++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++Library General Public License for more details.
++
++You should have received a copy of the GNU Library General Public
++License along with libiberty; see the file COPYING.LIB.
++If not, see <http://www.gnu.org/licenses/>. */
++
++
++#ifdef HAVE_CONFIG_H
++#include "config.h"
++#endif
++
++#include "safe-ctype.h"
++
++#include <sys/types.h>
++#include <string.h>
++#include <stdio.h>
++
++#ifdef HAVE_STRING_H
++#include <string.h>
++#else
++extern size_t strlen(const char *s);
++extern int strncmp(const char *s1, const char *s2, size_t n);
++extern void *memset(void *s, int c, size_t n);
++#endif
++
++#include <demangle.h>
++#include "libiberty.h"
++
++
++/* Mangled Rust symbols look like this:
++ _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a
++
++ The original symbol is:
++ <std::sys::fd::FileDesc as core::ops::Drop>::drop
++
++ The last component of the path is a 64-bit hash in lowercase hex,
++ prefixed with "h". Rust does not have a global namespace between
++ crates, an illusion which Rust maintains by using the hash to
++ distinguish things that would otherwise have the same symbol.
++
++ Any path component not starting with a XID_Start character is
++ prefixed with "_".
++
++ The following escape sequences are used:
++
++ "," => $C$
++ "@" => $SP$
++ "*" => $BP$
++ "&" => $RF$
++ "<" => $LT$
++ ">" => $GT$
++ "(" => $LP$
++ ")" => $RP$
++ " " => $u20$
++ "\"" => $u22$
++ "'" => $u27$
++ "+" => $u2b$
++ ";" => $u3b$
++ "[" => $u5b$
++ "]" => $u5d$
++ "{" => $u7b$
++ "}" => $u7d$
++ "~" => $u7e$
++
++ A double ".." means "::" and a single "." means "-".
++
++ The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$ */
++
++static const char *hash_prefix = "::h";
++static const size_t hash_prefix_len = 3;
++static const size_t hash_len = 16;
++
++static int is_prefixed_hash (const char *start);
++static int looks_like_rust (const char *sym, size_t len);
++static int unescape (const char **in, char **out, const char *seq, char value);
++
++/* INPUT: sym: symbol that has been through C++ (gnu v3) demangling
++
++ This function looks for the following indicators:
++
++ 1. The hash must consist of "h" followed by 16 lowercase hex digits.
++
++ 2. As a sanity check, the hash must use between 5 and 15 of the 16
++ possible hex digits. This is true of 99.9998% of hashes so once
++ in your life you may see a false negative. The point is to
++ notice path components that could be Rust hashes but are
++ probably not, like "haaaaaaaaaaaaaaaa". In this case a false
++ positive (non-Rust symbol has an important path component
++ removed because it looks like a Rust hash) is worse than a false
++ negative (the rare Rust symbol is not demangled) so this sets
++ the balance in favor of false negatives.
++
++ 3. There must be no characters other than a-zA-Z0-9 and _.:$
++
++ 4. There must be no unrecognized $-sign sequences.
++
++ 5. There must be no sequence of three or more dots in a row ("..."). */
++
++int
++rust_is_mangled (const char *sym)
++{
++ size_t len, len_without_hash;
++
++ if (!sym)
++ return 0;
++
++ len = strlen (sym);
++ if (len <= hash_prefix_len + hash_len)
++ /* Not long enough to contain "::h" + hash + something else */
++ return 0;
++
++ len_without_hash = len - (hash_prefix_len + hash_len);
++ if (!is_prefixed_hash (sym + len_without_hash))
++ return 0;
++
++ return looks_like_rust (sym, len_without_hash);
++}
++
++/* A hash is the prefix "::h" followed by 16 lowercase hex digits. The
++ hex digits must comprise between 5 and 15 (inclusive) distinct
++ digits. */
++
++static int
++is_prefixed_hash (const char *str)
++{
++ const char *end;
++ char seen[16];
++ size_t i;
++ int count;
++
++ if (strncmp (str, hash_prefix, hash_prefix_len))
++ return 0;
++ str += hash_prefix_len;
++
++ memset (seen, 0, sizeof(seen));
++ for (end = str + hash_len; str < end; str++)
++ if (*str >= '0' && *str <= '9')
++ seen[*str - '0'] = 1;
++ else if (*str >= 'a' && *str <= 'f')
++ seen[*str - 'a' + 10] = 1;
++ else
++ return 0;
++
++ /* Count how many distinct digits seen */
++ count = 0;
++ for (i = 0; i < 16; i++)
++ if (seen[i])
++ count++;
++
++ return count >= 5 && count <= 15;
++}
++
++static int
++looks_like_rust (const char *str, size_t len)
++{
++ const char *end = str + len;
++
++ while (str < end)
++ switch (*str)
++ {
++ case '$':
++ if (!strncmp (str, "$C$", 3))
++ str += 3;
++ else if (!strncmp (str, "$SP$", 4)
++ || !strncmp (str, "$BP$", 4)
++ || !strncmp (str, "$RF$", 4)
++ || !strncmp (str, "$LT$", 4)
++ || !strncmp (str, "$GT$", 4)
++ || !strncmp (str, "$LP$", 4)
++ || !strncmp (str, "$RP$", 4))
++ str += 4;
++ else if (!strncmp (str, "$u20$", 5)
++ || !strncmp (str, "$u22$", 5)
++ || !strncmp (str, "$u27$", 5)
++ || !strncmp (str, "$u2b$", 5)
++ || !strncmp (str, "$u3b$", 5)
++ || !strncmp (str, "$u5b$", 5)
++ || !strncmp (str, "$u5d$", 5)
++ || !strncmp (str, "$u7b$", 5)
++ || !strncmp (str, "$u7d$", 5)
++ || !strncmp (str, "$u7e$", 5))
++ str += 5;
++ else
++ return 0;
++ break;
++ case '.':
++ /* Do not allow three or more consecutive dots */
++ if (!strncmp (str, "...", 3))
++ return 0;
++ /* Fall through */
++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
++ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
++ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
++ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
++ case 'y': case 'z':
++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
++ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
++ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
++ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
++ case 'Y': case 'Z':
++ case '0': case '1': case '2': case '3': case '4': case '5':
++ case '6': case '7': case '8': case '9':
++ case '_':
++ case ':':
++ str++;
++ break;
++ default:
++ return 0;
++ }
++
++ return 1;
++}
++
++/*
++ INPUT: sym: symbol for which rust_is_mangled(sym) returned 1.
++
++ The input is demangled in-place because the mangled name is always
++ longer than the demangled one. */
++
++void
++rust_demangle_sym (char *sym)
++{
++ const char *in;
++ char *out;
++ const char *end;
++
++ if (!sym)
++ return;
++
++ in = sym;
++ out = sym;
++ end = sym + strlen (sym) - (hash_prefix_len + hash_len);
++
++ while (in < end)
++ switch (*in)
++ {
++ case '$':
++ if (!(unescape (&in, &out, "$C$", ',')
++ || unescape (&in, &out, "$SP$", '@')
++ || unescape (&in, &out, "$BP$", '*')
++ || unescape (&in, &out, "$RF$", '&')
++ || unescape (&in, &out, "$LT$", '<')
++ || unescape (&in, &out, "$GT$", '>')
++ || unescape (&in, &out, "$LP$", '(')
++ || unescape (&in, &out, "$RP$", ')')
++ || unescape (&in, &out, "$u20$", ' ')
++ || unescape (&in, &out, "$u22$", '\"')
++ || unescape (&in, &out, "$u27$", '\'')
++ || unescape (&in, &out, "$u2b$", '+')
++ || unescape (&in, &out, "$u3b$", ';')
++ || unescape (&in, &out, "$u5b$", '[')
++ || unescape (&in, &out, "$u5d$", ']')
++ || unescape (&in, &out, "$u7b$", '{')
++ || unescape (&in, &out, "$u7d$", '}')
++ || unescape (&in, &out, "$u7e$", '~'))) {
++ /* unexpected escape sequence, not looks_like_rust. */
++ goto fail;
++ }
++ break;
++ case '_':
++ /* If this is the start of a path component and the next
++ character is an escape sequence, ignore the underscore. The
++ mangler inserts an underscore to make sure the path
++ component begins with a XID_Start character. */
++ if ((in == sym || in[-1] == ':') && in[1] == '$')
++ in++;
++ else
++ *out++ = *in++;
++ break;
++ case '.':
++ if (in[1] == '.')
++ {
++ /* ".." becomes "::" */
++ *out++ = ':';
++ *out++ = ':';
++ in += 2;
++ }
++ else
++ {
++ /* "." becomes "-" */
++ *out++ = '-';
++ in++;
++ }
++ break;
++ case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
++ case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
++ case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
++ case 's': case 't': case 'u': case 'v': case 'w': case 'x':
++ case 'y': case 'z':
++ case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
++ case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
++ case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
++ case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
++ case 'Y': case 'Z':
++ case '0': case '1': case '2': case '3': case '4': case '5':
++ case '6': case '7': case '8': case '9':
++ case ':':
++ *out++ = *in++;
++ break;
++ default:
++ /* unexpected character in symbol, not looks_like_rust. */
++ goto fail;
++ }
++ goto done;
++
++fail:
++ *out++ = '?'; /* This is pretty lame, but it's hard to do better. */
++done:
++ *out = '\0';
++}
++
++static int
++unescape (const char **in, char **out, const char *seq, char value)
++{
++ size_t len = strlen (seq);
++
++ if (strncmp (*in, seq, len))
++ return 0;
++
++ **out = value;
++
++ *in += len;
++ *out += 1;
++
++ return 1;
++}
+Index: b/src/libiberty/strndup.c
+===================================================================
+--- a/src/libiberty/strndup.c
++++ b/src/libiberty/strndup.c
+@@ -33,7 +33,7 @@ memory was available. The result is alw
+ #include "ansidecl.h"
+ #include <stddef.h>
+
+-extern size_t strlen (const char*);
++extern size_t strnlen (const char *s, size_t maxlen);
+ extern PTR malloc (size_t);
+ extern PTR memcpy (PTR, const PTR, size_t);
+
+@@ -41,10 +41,7 @@ char *
+ strndup (const char *s, size_t n)
+ {
+ char *result;
+- size_t len = strlen (s);
+-
+- if (n < len)
+- len = n;
++ size_t len = strnlen (s, n);
+
+ result = (char *) malloc (len + 1);
+ if (!result)
+Index: b/src/libiberty/testsuite/demangle-expected
+===================================================================
+--- a/src/libiberty/testsuite/demangle-expected
++++ b/src/libiberty/testsuite/demangle-expected
+@@ -31,6 +31,11 @@ ArrowLine::ArrowheadIntersects(Arrowhead
+ ArrowLine::ArrowheadIntersects
+ #
+ --format=gnu --no-params
++ArrowheadIntersects__9ArrowLineP9ArrowheadO6BoxObjP7Graphic
++ArrowLine::ArrowheadIntersects(Arrowhead *, BoxObj &&, Graphic *)
++ArrowLine::ArrowheadIntersects
++#
++--format=gnu --no-params
+ AtEnd__13ivRubberGroup
+ ivRubberGroup::AtEnd(void)
+ ivRubberGroup::AtEnd
+@@ -51,6 +56,11 @@ TextCode::CoreConstDecls(ostream &)
+ TextCode::CoreConstDecls
+ #
+ --format=gnu --no-params
++CoreConstDecls__8TextCodeO7ostream
++TextCode::CoreConstDecls(ostream &&)
++TextCode::CoreConstDecls
++#
++--format=gnu --no-params
+ Detach__8StateVarP12StateVarView
+ StateVar::Detach(StateVarView *)
+ StateVar::Detach
+@@ -66,21 +76,41 @@ RelateManip::Effect(ivEvent &)
+ RelateManip::Effect
+ #
+ --format=gnu --no-params
++Effect__11RelateManipO7ivEvent
++RelateManip::Effect(ivEvent &&)
++RelateManip::Effect
++#
++--format=gnu --no-params
+ FindFixed__FRP4CNetP4CNet
+ FindFixed(CNet *&, CNet *)
+ FindFixed
+ #
+ --format=gnu --no-params
++FindFixed__FOP4CNetP4CNet
++FindFixed(CNet *&&, CNet *)
++FindFixed
++#
++--format=gnu --no-params
+ Fix48_abort__FR8twolongs
+ Fix48_abort(twolongs &)
+ Fix48_abort
+ #
+ --format=gnu --no-params
++Fix48_abort__FO8twolongs
++Fix48_abort(twolongs &&)
++Fix48_abort
++#
++--format=gnu --no-params
+ GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveRiT2
+ iv2_6_VScroller::GetBarInfo(ivPerspective *, int &, int &)
+ iv2_6_VScroller::GetBarInfo
+ #
+ --format=gnu --no-params
++GetBarInfo__15iv2_6_VScrollerP13ivPerspectiveOiT2
++iv2_6_VScroller::GetBarInfo(ivPerspective *, int &&, int &&)
++iv2_6_VScroller::GetBarInfo
++#
++--format=gnu --no-params
+ GetBgColor__C9ivPainter
+ ivPainter::GetBgColor(void) const
+ ivPainter::GetBgColor
+@@ -986,11 +1016,21 @@ List<VHDLEntity>::Pix::Pix(List<VHDLEnti
+ List<VHDLEntity>::Pix::Pix
+ #
+ --format=gnu --no-params
++__Q2t4List1Z10VHDLEntity3PixOCQ2t4List1Z10VHDLEntity3Pix
++List<VHDLEntity>::Pix::Pix(List<VHDLEntity>::Pix const &&)
++List<VHDLEntity>::Pix::Pix
++#
++--format=gnu --no-params
+ __Q2t4List1Z10VHDLEntity7elementRC10VHDLEntityPT0
+ List<VHDLEntity>::element::element(VHDLEntity const &, List<VHDLEntity>::element *)
+ List<VHDLEntity>::element::element
+ #
+ --format=gnu --no-params
++__Q2t4List1Z10VHDLEntity7elementOC10VHDLEntityPT0
++List<VHDLEntity>::element::element(VHDLEntity const &&, List<VHDLEntity>::element *)
++List<VHDLEntity>::element::element
++#
++--format=gnu --no-params
+ __Q2t4List1Z10VHDLEntity7elementRCQ2t4List1Z10VHDLEntity7element
+ List<VHDLEntity>::element::element(List<VHDLEntity>::element const &)
+ List<VHDLEntity>::element::element
+@@ -1036,6 +1076,11 @@ PixX<VHDLLibrary, VHDLLibraryRep, List<V
+ PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
+ #
+ --format=gnu --no-params
++__t4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntityOCt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
++PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > const &&)
++PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> >::PixX
++#
++--format=gnu --no-params
+ nextE__C11VHDLLibraryRt4PixX3Z11VHDLLibraryZ14VHDLLibraryRepZt4List1Z10VHDLEntity
+ VHDLLibrary::nextE(PixX<VHDLLibrary, VHDLLibraryRep, List<VHDLEntity> > &) const
+ VHDLLibrary::nextE
+@@ -1261,6 +1306,11 @@ smanip_int::smanip_int(ios &(*)(ios &, i
+ smanip_int::smanip_int
+ #
+ --format=lucid --no-params
++__ct__10smanip_intFPFO3iosi_O3iosi
++smanip_int::smanip_int(ios &&(*)(ios &&, int), int)
++smanip_int::smanip_int
++#
++--format=lucid --no-params
+ __ct__11fstreambaseFi
+ fstreambase::fstreambase(int)
+ fstreambase::fstreambase
+@@ -1281,6 +1331,11 @@ smanip_long::smanip_long(ios &(*)(ios &,
+ smanip_long::smanip_long
+ #
+ --format=lucid --no-params
++__ct__11smanip_longFPFO3iosl_O3iosl
++smanip_long::smanip_long(ios &&(*)(ios &&, long), long)
++smanip_long::smanip_long
++#
++--format=lucid --no-params
+ __ct__11stdiostreamFP4FILE
+ stdiostream::stdiostream(FILE *)
+ stdiostream::stdiostream
+@@ -1321,6 +1376,11 @@ foo::foo(foo &)
+ foo::foo
+ #
+ --format=lucid --no-params
++__ct__3fooFO3foo
++foo::foo(foo &&)
++foo::foo
++#
++--format=lucid --no-params
+ __ct__3fooFi
+ foo::foo(int)
+ foo::foo
+@@ -1336,6 +1396,11 @@ foo::foo(int, foo &, int, foo &, int, fo
+ foo::foo
+ #
+ --format=lucid --no-params
++__ct__3fooFiO3fooT1T2T1T2
++foo::foo(int, foo &&, int, foo &&, int, foo &&)
++foo::foo
++#
++--format=lucid --no-params
+ __ct__3iosFP9streambuf
+ ios::ios(streambuf *)
+ ios::ios
+@@ -1811,6 +1876,11 @@ foo(int, foo &, int, foo &, int, foo &)
+ foo
+ #
+ --format=lucid --no-params
++foo__FiO3fooT1T2T1T2
++foo(int, foo &&, int, foo &&, int, foo &&)
++foo
++#
++--format=lucid --no-params
+ foo___3barFl
+ bar::foo_(long)
+ bar::foo_
+@@ -2561,6 +2631,11 @@ DListNode<RLabel &>::DListNode(RLabel &,
+ DListNode<RLabel &>::DListNode
+ #
+ --format=arm --no-params
++__ct__25DListNode__pt__9_O6RLabelFO6RLabelP25DListNode__pt__9_O6RLabelT2
++DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *)
++DListNode<RLabel &&>::DListNode
++#
++--format=arm --no-params
+ bar__3fooFiT16FooBar
+ foo::bar(int, int, FooBar)
+ foo::bar
+@@ -2991,6 +3066,11 @@ DListNode<RLabel &>::DListNode(RLabel &,
+ DListNode<RLabel &>::DListNode
+ #
+ --format=hp --no-params
++__ct__9DListNodeXTO6RLabel__FO6RLabelP9DListNodeXTO6RLabel_T2
++DListNode<RLabel &&>::DListNode(RLabel &&, DListNode<RLabel &&> *, DListNode<RLabel &&> *)
++DListNode<RLabel &&>::DListNode
++#
++--format=hp --no-params
+ elem__6vectorXTiUP34__Fi
+ vector<int,34U>::elem(int)
+ vector<int,34U>::elem
+@@ -3021,16 +3101,31 @@ vector<int,-67,4000U,short &>::elem(int)
+ vector<int,-67,4000U,short &>::elem
+ #
+ --format=hp --no-params
++elem__6vectorXTiSN67UP4000TOs__Fi
++vector<int,-67,4000U,short &&>::elem(int)
++vector<int,-67,4000U,short &&>::elem
++#
++--format=hp --no-params
+ elem__6vectorXTiSN67TRdTFPv_i__Fi
+ vector<int,-67,double &,int (void *)>::elem(int)
+ vector<int,-67,double &,int (void *)>::elem
+ #
+ --format=hp --no-params
++elem__6vectorXTiSN67TOdTFPv_i__Fi
++vector<int,-67,double &&,int (void *)>::elem(int)
++vector<int,-67,double &&,int (void *)>::elem
++#
++--format=hp --no-params
+ X__6vectorXTiSN67TdTPvUP5TRs
+ vector<int,-67,double,void *,5U,short &>::X
+ vector<int,-67,double,void *,5U,short &>::X
+ #
+ --format=hp --no-params
++X__6vectorXTiSN67TdTPvUP5TOs
++vector<int,-67,double,void *,5U,short &&>::X
++vector<int,-67,double,void *,5U,short &&>::X
++#
++--format=hp --no-params
+ elem__6vectorXTiA3foo__Fi
+ vector<int,&foo>::elem(int)
+ vector<int,&foo>::elem
+@@ -3071,6 +3166,11 @@ Spec<int,int &,int>::spec(int *)
+ Spec<int,int &,int>::spec
+ #
+ --format=hp --no-params
++spec__17Spec<#1,#1.&&,#1>XTiTOiTi_FPi
++Spec<int,int &&,int>::spec(int *)
++Spec<int,int &&,int>::spec
++#
++--format=hp --no-params
+ add__XTc_FcT1
+ add<char>(char, char)
+ add<char>
+@@ -3101,6 +3201,11 @@ C<Test, Test::output> call<Test>(Test &)
+ C<Test, Test::output> call<Test>
+ #
+ --format=gnu --no-params
++call__H1Z4Test_OX01_t1C2ZX01PMX01FPX01i_vQ2X016output
++C<Test, Test::output> call<Test>(Test &&)
++C<Test, Test::output> call<Test>
++#
++--format=gnu --no-params
+ fn__FPQ21n1cPMQ21n1cFPQ21n1c_i
+ fn(n::c *, int (n::c::*)(n::c *))
+ fn
+@@ -3126,6 +3231,11 @@ int foo<TA<int const &, NA<9> > >(TA<int
+ int foo<TA<int const &, NA<9> > >
+ #
+ --format=gnu --no-params
++foo__H1Zt2TA2ZOCiZt2NA1Ui9_X01_i
++int foo<TA<int const &&, NA<9> > >(TA<int const &&, NA<9> >)
++int foo<TA<int const &&, NA<9> > >
++#
++--format=gnu --no-params
+ foo__H1Zt2TA2ZcZt2NA1Ui20_X01_i
+ int foo<TA<char, NA<20> > >(TA<char, NA<20> >)
+ int foo<TA<char, NA<20> > >
+@@ -3402,6 +3512,11 @@ int* const volatile restrict _far
+ _Z3fooILi2EEvRAplT_Li1E_i
+ void foo<2>(int (&) [(2)+(1)])
+ foo<2>
++#
++--format=gnu-v3 --no-params
++_Z3fooILi2EEvOAplT_Li1E_i
++void foo<2>(int (&&) [(2)+(1)])
++foo<2>
+ #
+ --format=gnu-v3 --no-params
+ _Z1fM1AKFvvE
+@@ -4462,6 +4577,66 @@ __vt_90000000000cafebabe
+
+ _Z80800000000000000000000
+ _Z80800000000000000000000
++#
++# Tests write access violation PR70926
++
++0__Ot2m02R5T0000500000
++0__Ot2m02R5T0000500000
++#
++
++0__GT50000000000_
++0__GT50000000000_
++#
++
++__t2m05B500000000000000000_
++__t2m05B500000000000000000_
++#
++# Tests stack overflow PR71696
++
++__10%0__S4_0T0T0
++%0<>::%0(%0<>)
++
++# Inheriting constructor
++_ZN1DCI11BEi
++D::B(int)
++
++# exception-specification (C++17)
++_Z1fIvJiELb0EEvPDOT1_EFT_DpT0_E
++void f<void, int, false>(void (*)(int) noexcept(false))
++
++_Z1fIvJiELb0EEvPDoFT_DpT0_E
++void f<void, int, false>(void (*)(int) noexcept)
++
++_Z1fIvJiELb0EEvPDwiEFT_DpT0_E
++void f<void, int, false>(void (*)(int) throw(int))
++
++# Could crash
++_
++_
++
++# Could crash
++_vt
++_vt
++
++# Could crash
++_$_1Acitz
++_$_1Acitz
++
++# Could crash
++_$_H1R
++_$_H1R
++
++# Could crash
++_Q8ccQ4M2e.
++_Q8ccQ4M2e.
++
++# fold-expression with missing third component could crash.
++_Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE
++_Z12binary_rightIJLi1ELi2ELi3EEEv1AIXfRplT_LiEEE
++
++# ?: expression with missing third component could crash.
++AquT_quT_4mxautouT_4mxxx
++AquT_quT_4mxautouT_4mxxx
+
+ # pr c++/78252 generic lambda mangling uses template parms, and leads
+ # to unbounded recursion if not dealt with properly
+Index: b/src/libiberty/testsuite/Makefile.in
+===================================================================
+--- a/src/libiberty/testsuite/Makefile.in
++++ b/src/libiberty/testsuite/Makefile.in
+@@ -45,8 +45,8 @@ all:
+ # CHECK is set to "really_check" or the empty string by configure.
+ check: @CHECK@
+
+-really-check: check-cplus-dem check-d-demangle check-pexecute check-expandargv \
+- check-strtol
++really-check: check-cplus-dem check-d-demangle check-rust-demangle \
++ check-pexecute check-expandargv check-strtol
+
+ # Run some tests of the demangler.
+ check-cplus-dem: test-demangle $(srcdir)/demangle-expected
+@@ -55,6 +55,9 @@ check-cplus-dem: test-demangle $(srcdir)
+ check-d-demangle: test-demangle $(srcdir)/d-demangle-expected
+ ./test-demangle < $(srcdir)/d-demangle-expected
+
++check-rust-demangle: test-demangle $(srcdir)/rust-demangle-expected
++ ./test-demangle < $(srcdir)/rust-demangle-expected
++
+ # Check the pexecute code.
+ check-pexecute: test-pexecute
+ ./test-pexecute
+Index: b/src/libiberty/testsuite/rust-demangle-expected
+===================================================================
+--- /dev/null
++++ b/src/libiberty/testsuite/rust-demangle-expected
+@@ -0,0 +1,161 @@
++# This file holds test cases for the Rust demangler.
++# Each test case looks like this:
++# options
++# input to be demangled
++# expected output
++#
++# See demangle-expected for documentation of supported options.
++#
++# A line starting with `#' is ignored.
++# However, blank lines in this file are NOT ignored.
++#
++############
++#
++# Coverage Tests
++#
++#
++# Demangles as rust symbol.
++--format=rust
++_ZN4main4main17he714a2e23ed7db23E
++main::main
++# Also demangles as c++ gnu v3 mangled symbol. But with extra Rust hash.
++--format=gnu-v3
++_ZN4main4main17he714a2e23ed7db23E
++main::main::he714a2e23ed7db23
++# But auto should demangle fully gnu-v3 -> rust -> demangled, not partially.
++--format=auto
++_ZN4main4main17he714a2e23ed7db23E
++main::main
++# Hash is exactly 16 hex chars. Not more.
++--format=auto
++_ZN4main4main18h1e714a2e23ed7db23E
++main::main::h1e714a2e23ed7db23
++# Not less.
++--format=auto
++_ZN4main4main16h714a2e23ed7db23E
++main::main::h714a2e23ed7db23
++# And not non-hex.
++--format=auto
++_ZN4main4main17he714a2e23ed7db2gE
++main::main::he714a2e23ed7db2g
++# $XX$ substitutions should not contain just numbers.
++--format=auto
++_ZN4main4$99$17he714a2e23ed7db23E
++main::$99$::he714a2e23ed7db23
++# _ at start of path should be removed.
++# ".." translates to "::" "$GT$" to ">" and "$LT$" to "<".
++--format=rust
++_ZN71_$LT$Test$u20$$u2b$$u20$$u27$static$u20$as$u20$foo..Bar$LT$Test$GT$$GT$3bar17h930b740aa94f1d3aE
++<Test + 'static as foo::Bar<Test>>::bar
++#
++--format=rust
++_ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17h8581507801fb8615E
++<I as core::iter::traits::IntoIterator>::into_iter
++#
++--format=rust
++_ZN10parse_tsan4main17hdbbfdf1c6a7e27d9E
++parse_tsan::main
++#
++--format=rust
++_ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E
++<std::env::Args as core::iter::iterator::Iterator>::next
++#
++--format=rust
++_ZN4core3str9from_utf817hdcea28871313776dE
++core::str::from_utf8
++#
++--format=rust
++_ZN4core3mem7size_of17h18bde9bb8c22e2cfE
++core::mem::size_of
++#
++--format=rust
++_ZN5alloc4heap8allocate17hd55c03e6cb81d924E
++alloc::heap::allocate
++#
++--format=rust
++_ZN4core3ptr8null_mut17h736cce09ca0ac11aE
++core::ptr::null_mut
++#
++--format=rust
++_ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h7f9de798bc3f0879E
++core::ptr::<impl *mut T>::is_null
++#
++--format=rust
++_ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$6double17h4166e2b47539e1ffE
++<alloc::raw_vec::RawVec<T>>::double
++#
++--format=rust
++_ZN39_$LT$collections..vec..Vec$LT$T$GT$$GT$4push17hd4b6b23c1b88141aE
++<collections::vec::Vec<T>>::push
++#
++--format=rust
++_ZN70_$LT$collections..vec..Vec$LT$T$GT$$u20$as$u20$core..ops..DerefMut$GT$9deref_mut17hf299b860dc5a831cE
++<collections::vec::Vec<T> as core::ops::DerefMut>::deref_mut
++#
++--format=rust
++_ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc784b4a166cb5e5cE
++<core::ptr::Unique<T> as core::ops::Deref>::deref
++#
++--format=rust
++_ZN40_$LT$alloc..raw_vec..RawVec$LT$T$GT$$GT$3ptr17h7570b6e9070b693bE
++<alloc::raw_vec::RawVec<T>>::ptr
++#
++--format=rust
++_ZN4core3ptr31_$LT$impl$u20$$BP$mut$u20$T$GT$7is_null17h0f3228f343444ac8E
++core::ptr::<impl *mut T>::is_null
++#
++--format=rust
++_ZN53_$LT$$u5b$T$u5d$$u20$as$u20$core..slice..SliceExt$GT$10as_mut_ptr17h153241df1c7d1666E
++<[T] as core::slice::SliceExt>::as_mut_ptr
++#
++--format=rust
++_ZN11collections5slice29_$LT$impl$u20$$u5b$T$u5d$$GT$10as_mut_ptr17hf12a6d0409938c96E
++collections::slice::<impl [T]>::as_mut_ptr
++#
++--format=rust
++_ZN4core3ptr5write17h651fe53ec860e780E
++core::ptr::write
++#
++--format=rust
++_ZN65_$LT$std..env..Args$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h420a7c8d0c7eef40E
++<std::env::Args as core::iter::iterator::Iterator>::next
++#
++--format=rust
++_ZN54_$LT$I$u20$as$u20$core..iter..traits..IntoIterator$GT$9into_iter17he06cb713aae5b465E
++<I as core::iter::traits::IntoIterator>::into_iter
++#
++--format=rust
++_ZN71_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17hf7f23304ebe62eedE
++<collections::vec::IntoIter<T> as core::ops::Drop>::drop
++#
++--format=rust
++_ZN86_$LT$collections..vec..IntoIter$LT$T$GT$$u20$as$u20$core..iter..iterator..Iterator$GT$4next17h04b3fbf148c39713E
++<collections::vec::IntoIter<T> as core::iter::iterator::Iterator>::next
++#
++--format=rust
++_ZN75_$LT$$RF$$u27$a$u20$mut$u20$I$u20$as$u20$core..iter..iterator..Iterator$GT$4next17ha050492063e0fd20E
++<&'a mut I as core::iter::iterator::Iterator>::next
++# Different hashes are OK, they are just stripped.
++--format=rust
++_ZN13drop_contents17hfe3c0a68c8ad1c74E
++drop_contents
++#
++--format=rust
++_ZN13drop_contents17h48cb59bef15bb555E
++drop_contents
++#
++--format=rust
++_ZN4core3mem7size_of17h900b33157bf58f26E
++core::mem::size_of
++#
++--format=rust
++_ZN67_$LT$alloc..raw_vec..RawVec$LT$T$GT$$u20$as$u20$core..ops..Drop$GT$4drop17h96a5cf6e94807905E
++<alloc::raw_vec::RawVec<T> as core::ops::Drop>::drop
++#
++--format=rust
++_ZN68_$LT$core..nonzero..NonZero$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17hc49056f882aa46dbE
++<core::nonzero::NonZero<T> as core::ops::Deref>::deref
++#
++--format=rust
++_ZN63_$LT$core..ptr..Unique$LT$T$GT$$u20$as$u20$core..ops..Deref$GT$5deref17h19f2ad4920655e85E
++<core::ptr::Unique<T> as core::ops::Deref>::deref
+Index: b/src/libiberty/testsuite/test-pexecute.c
+===================================================================
+--- a/src/libiberty/testsuite/test-pexecute.c
++++ b/src/libiberty/testsuite/test-pexecute.c
+@@ -285,6 +285,20 @@ main (int argc, char **argv)
+ ERROR ("echo exit status failed");
+ pex_free (pex1);
+
++ /* Check empty parameters don't get lost. */
++ pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp");
++ subargv[1] = "echo";
++ subargv[2] = "foo";
++ subargv[3] = "";
++ subargv[4] = "bar";
++ subargv[5] = NULL;
++ TEST_PEX_RUN (pex1, 0, "./test-pexecute", subargv, NULL, NULL);
++ e = TEST_PEX_READ_OUTPUT (pex1);
++ CHECK_LINE (e, "foo bar"); /* Two spaces! */
++ if (TEST_PEX_GET_STATUS_1 (pex1) != 0)
++ ERROR ("echo exit status failed");
++ pex_free (pex1);
++
+ pex1 = TEST_PEX_INIT (PEX_USE_PIPES, "temp");
+ subargv[1] = "echo";
+ subargv[2] = "bar";
+Index: b/src/libiberty/xmemdup.c
+===================================================================
+--- a/src/libiberty/xmemdup.c
++++ b/src/libiberty/xmemdup.c
+@@ -1,4 +1,4 @@
+-/* xmemdup.c -- Duplicate a memory buffer, using xcalloc.
++/* xmemdup.c -- Duplicate a memory buffer, using xmalloc.
+ This trivial function is in the public domain.
+ Jeff Garzik, September 1999. */
+
+@@ -34,6 +34,8 @@ allocated, the remaining memory is zeroe
+ PTR
+ xmemdup (const PTR input, size_t copy_size, size_t alloc_size)
+ {
+- PTR output = xcalloc (1, alloc_size);
++ PTR output = xmalloc (alloc_size);
++ if (alloc_size > copy_size)
++ memset ((char *) output + copy_size, 0, alloc_size - copy_size);
+ return (PTR) memcpy (output, input, copy_size);
+ }
+Index: b/src/libiberty/xstrndup.c
+===================================================================
+--- a/src/libiberty/xstrndup.c
++++ b/src/libiberty/xstrndup.c
+@@ -48,10 +48,7 @@ char *
+ xstrndup (const char *s, size_t n)
+ {
+ char *result;
+- size_t len = strlen (s);
+-
+- if (n < len)
+- len = n;
++ size_t len = strnlen (s, n);
+
+ result = XNEWVEC (char, len + 1);
+
+Index: b/src/include/libiberty.h
+===================================================================
+--- a/src/include/libiberty.h
++++ b/src/include/libiberty.h
+@@ -397,6 +397,17 @@ extern void hex_init (void);
+ /* Save files used for communication between processes. */
+ #define PEX_SAVE_TEMPS 0x4
+
++/* Max number of alloca bytes per call before we must switch to malloc.
++
++ ?? Swiped from gnulib's regex_internal.h header. Is this actually
++ the case? This number seems arbitrary, though sane.
++
++ The OS usually guarantees only one guard page at the bottom of the stack,
++ and a page size can be as small as 4096 bytes. So we cannot safely
++ allocate anything larger than 4096 bytes. Also care for the possibility
++ of a few compiler-allocated temporary stack slots. */
++#define MAX_ALLOCA_SIZE 4032
++
+ /* Prepare to execute one or more programs, with standard output of
+ each program fed to standard input of the next.
+ FLAGS As above.
+Index: b/src/include/demangle.h
+===================================================================
+--- a/src/include/demangle.h
++++ b/src/include/demangle.h
+@@ -63,9 +63,10 @@ extern "C" {
+ #define DMGL_GNU_V3 (1 << 14)
+ #define DMGL_GNAT (1 << 15)
+ #define DMGL_DLANG (1 << 16)
++#define DMGL_RUST (1 << 17) /* Rust wraps GNU_V3 style mangling. */
+
+ /* If none of these are set, use 'current_demangling_style' as the default. */
+-#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG)
++#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
+
+ /* Enumeration of possible demangling styles.
+
+@@ -88,7 +89,8 @@ extern enum demangling_styles
+ gnu_v3_demangling = DMGL_GNU_V3,
+ java_demangling = DMGL_JAVA,
+ gnat_demangling = DMGL_GNAT,
+- dlang_demangling = DMGL_DLANG
++ dlang_demangling = DMGL_DLANG,
++ rust_demangling = DMGL_RUST
+ } current_demangling_style;
+
+ /* Define string names for the various demangling styles. */
+@@ -104,6 +106,7 @@ extern enum demangling_styles
+ #define JAVA_DEMANGLING_STYLE_STRING "java"
+ #define GNAT_DEMANGLING_STYLE_STRING "gnat"
+ #define DLANG_DEMANGLING_STYLE_STRING "dlang"
++#define RUST_DEMANGLING_STYLE_STRING "rust"
+
+ /* Some macros to test what demangling style is active. */
+
+@@ -118,6 +121,7 @@ extern enum demangling_styles
+ #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA)
+ #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
+ #define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG)
++#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST)
+
+ /* Provide information about the available demangle styles. This code is
+ pulled from gdb into libiberty because it is useful to binutils also. */
+@@ -175,6 +179,27 @@ ada_demangle (const char *mangled, int o
+ extern char *
+ dlang_demangle (const char *mangled, int options);
+
++/* Returns non-zero iff MANGLED is a rust mangled symbol. MANGLED must
++ already have been demangled through cplus_demangle_v3. If this function
++ returns non-zero then MANGLED can be demangled (in-place) using
++ RUST_DEMANGLE_SYM. */
++extern int
++rust_is_mangled (const char *mangled);
++
++/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM.
++ If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might
++ replace characters that cannot be demangled with '?' and might truncate
++ SYM. After calling RUST_DEMANGLE_SYM SYM might be shorter, but never
++ larger. */
++extern void
++rust_demangle_sym (char *sym);
++
++/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise
++ returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and
++ RUST_DEMANGLE_SYM. Returns a new string that is owned by the caller. */
++extern char *
++rust_demangle (const char *mangled, int options);
++
+ enum gnu_v3_ctor_kinds {
+ gnu_v3_complete_object_ctor = 1,
+ gnu_v3_base_object_ctor,
+@@ -449,7 +474,9 @@ enum demangle_component_type
+ /* A transaction-safe function type. */
+ DEMANGLE_COMPONENT_TRANSACTION_SAFE,
+ /* A cloned function. */
+- DEMANGLE_COMPONENT_CLONE
++ DEMANGLE_COMPONENT_CLONE,
++ DEMANGLE_COMPONENT_NOEXCEPT,
++ DEMANGLE_COMPONENT_THROW_SPEC
+ };
+
+ /* Types which are only used internally. */