[rtems-tools commit] linkers/exe-info Support ARM static constructors.

Chris Johns chrisj at rtems.org
Wed Aug 16 08:18:43 UTC 2017


Module:    rtems-tools
Branch:    master
Commit:    78bbe4c1a31dc62c3a9bee919645c0aa8781709b
Changeset: http://git.rtems.org/rtems-tools/commit/?id=78bbe4c1a31dc62c3a9bee919645c0aa8781709b

Author:    Chris Johns <chrisj at rtems.org>
Date:      Wed Aug 16 18:09:59 2017 +1000

linkers/exe-info Support ARM static constructors.

Note, ARM destructors are registered at runtime and currently not
easly found.

Update libiberty to get a newer demangler.

Closes #3102.

---

 linkers/rtems-exeinfo.cpp               |   97 +-
 rtemstoolkit/libiberty/ansidecl.h       |  226 +--
 rtemstoolkit/libiberty/concat.c         |   61 +-
 rtemstoolkit/libiberty/cp-demangle.c    | 2574 +++++++++++++++++++++++++------
 rtemstoolkit/libiberty/cp-demangle.h    |   42 +-
 rtemstoolkit/libiberty/cplus-dem.c      |  578 +++++--
 rtemstoolkit/libiberty/d-demangle.c     | 1646 ++++++++++++++++++++
 rtemstoolkit/libiberty/demangle.h       |  133 +-
 rtemstoolkit/libiberty/environ.h        |   35 +
 rtemstoolkit/libiberty/libiberty.h      |  526 ++++++-
 rtemstoolkit/libiberty/make-temp-file.c |   15 +-
 rtemstoolkit/libiberty/mkstemps.c       |    4 +-
 rtemstoolkit/libiberty/pex-common.c     |   10 +-
 rtemstoolkit/libiberty/pex-common.h     |    5 +-
 rtemstoolkit/libiberty/pex-djgpp.c      |    9 +-
 rtemstoolkit/libiberty/pex-msdos.c      |    3 +-
 rtemstoolkit/libiberty/pex-one.c        |    2 +-
 rtemstoolkit/libiberty/pex-unix.c       |   23 +-
 rtemstoolkit/libiberty/pex-win32.c      |   85 +-
 rtemstoolkit/libiberty/rust-demangle.c  |  348 +++++
 rtemstoolkit/libiberty/safe-ctype.c     |    3 +-
 rtemstoolkit/libiberty/safe-ctype.h     |    2 +-
 rtemstoolkit/libiberty/stpcpy.c         |    2 +-
 rtemstoolkit/libiberty/xmalloc.c        |  185 +++
 rtemstoolkit/libiberty/xmemdup.c        |   41 +
 rtemstoolkit/libiberty/xstrdup.c        |   36 +
 rtemstoolkit/libiberty/xstrerror.c      |   79 +
 rtemstoolkit/rld-buffer.h               |   49 +-
 rtemstoolkit/rld-files.cpp              |   13 +
 rtemstoolkit/rld-files.h                |   14 +
 rtemstoolkit/rld-symbols.cpp            |   45 +-
 rtemstoolkit/rld-symbols.h              |    2 +-
 rtemstoolkit/wscript                    |    6 +
 33 files changed, 5940 insertions(+), 959 deletions(-)

diff --git a/linkers/rtems-exeinfo.cpp b/linkers/rtems-exeinfo.cpp
index dc3e1ec..c79ea94 100644
--- a/linkers/rtems-exeinfo.cpp
+++ b/linkers/rtems-exeinfo.cpp
@@ -56,18 +56,36 @@ namespace rld
   namespace exeinfo
   {
     /**
-     * Sections we decode.
+     * Default section list.
      */
-    const char* init_sections[] =
+    const char* default_init[] =
     {
       ".rtemsroset",
       ".ctors",
+      ".init",
       0
     };
 
-    const char* fini_sections[] =
+    const char* default_fini[] =
     {
       ".dtors",
+      ".fini",
+      0
+    };
+
+    /**
+     * ARM section list.
+     */
+    const char* arm_init[] =
+    {
+      ".rtemsroset",
+      ".init_array",
+      0
+    };
+
+    const char* arm_fini[] =
+    {
+      ".fini_array",
       0
     };
 
@@ -76,13 +94,14 @@ namespace rld
      */
     struct section
     {
-      const files::section& sec;      //< The executable's section.
-      buffer::buffer        data;     //< The section's data.
+      const files::section& sec;        //< The executable's section.
+      buffer::buffer        data;       //< The section's data.
+      files::byteorder      byteorder;  //< The image's byteorder.
 
       /**
        * Construct the section.
        */
-      section (const files::section& sec);
+      section (const files::section& sec, files::byteorder byteorder);
 
       /**
        * Copy construct.
@@ -111,10 +130,13 @@ namespace rld
      */
     struct image
     {
-      files::object    exe;       //< The object file that is the executable.
-      symbols::table   symbols;   //< The synbols for a map.
-      symbols::addrtab addresses; //< The symbols keyed by address.
-      files::sections  secs;      //< The sections in the executable.
+      files::object    exe;         //< The object file that is the executable.
+      symbols::table   symbols;     //< The synbols for a map.
+      symbols::addrtab addresses;   //< The symbols keyed by address.
+      files::sections  secs;        //< The sections in the executable.
+      const char**     init;        //< The init section's list for the machinetype.
+      const char**     fini;        //< The fini section's list for the machinetype.
+
 
       /**
        * Load the executable file.
@@ -147,9 +169,10 @@ namespace rld
       void output_init_fini (const char* label, const char** names);
     };
 
-    section::section (const files::section& sec)
+    section::section (const files::section& sec, files::byteorder byteorder)
       : sec (sec),
-        data (sec.size)
+        data (sec.size),
+        byteorder (byteorder)
     {
     }
 
@@ -218,7 +241,7 @@ namespace rld
             std::cout << "init:section-loader: " << fsec.name
                       << " added" << std::endl;
 
-          section sec (fsec);
+          section sec (fsec, img.exe.get_byteorder ());
           img.exe.seek (fsec.offset);
           sec.data.read (img.exe, fsec.size);
           secs.push_back (sec);
@@ -228,7 +251,9 @@ namespace rld
     }
 
     image::image (const std::string exe_name)
-      : exe (exe_name)
+      : exe (exe_name),
+        init (0),
+        fini (0)
     {
       /*
        * Open the executable file and begin the session on it.
@@ -241,6 +266,21 @@ namespace rld
                           "init::image");
 
       /*
+       * Set up the section lists for the machiner type.
+       */
+      switch (exe.elf ().machinetype ())
+      {
+        case EM_ARM:
+          init = arm_init;
+          fini = arm_fini;
+          break;
+        default:
+          init  = default_init;
+          fini  = default_fini;
+          break;
+      }
+
+      /*
        * Load the symbols and sections.
        */
       exe.load_symbols (symbols, true);
@@ -260,6 +300,17 @@ namespace rld
     {
       std::cout << "Sections: " << secs.size () << std::endl;
 
+      size_t max_section_name = 0;
+
+      for (files::sections::const_iterator si = secs.begin ();
+           si != secs.end ();
+           ++si)
+      {
+        const files::section& sec = *si;
+        if (sec.name.length() > max_section_name)
+          max_section_name = sec.name.length();
+      }
+
       for (files::sections::const_iterator si = secs.begin ();
            si != secs.end ();
            ++si)
@@ -286,15 +337,15 @@ namespace rld
         SF (SHF_ORDERED,         13, 'O');
 
         std::cout << "  " << std::left
-                  << std::setw (15) << sec.name
+                  << std::setw (max_section_name) << sec.name
                   << " " << flags
                   << std::right << std::hex << std::setfill ('0')
-                  << " address: 0x" << std::setw (8) << sec.address
+                  << " addr: 0x" << std::setw (8) << sec.address
                   << " 0x" << std::setw (8) << sec.address + sec.size
                   << std::dec << std::setfill (' ')
-                  << " size: " << std::setw (7) << sec.size
+                  << " size: " << std::setw (10) << sec.size
                   << " align: " << std::setw (3) << sec.alignment
-                  << " relocs: " << std::setw (4) << sec.relocs.size ()
+                  << " relocs: " << std::setw (6) << sec.relocs.size ()
                   << std::endl;
       }
 
@@ -304,13 +355,13 @@ namespace rld
     void
     image::output_init ()
     {
-      output_init_fini ("Init", init_sections);
+      output_init_fini ("Init", init);
     }
 
     void
     image::output_fini ()
     {
-      output_init_fini ("Fini", fini_sections);
+      output_init_fini ("Fini", fini);
     }
 
     void
@@ -347,13 +398,7 @@ namespace rld
                     << std::dec << std::setfill ('0');
           if (sym)
           {
-            /*
-             * C++ is adding '_GLOBAL__sub_I_' to the label. If present, strip
-             * and check the label.
-             */
             std::string label = sym->name ();
-            if (rld::starts_with (label, "_GLOBAL__sub_I_"))
-              label = rld::find_replace (label, "_GLOBAL__sub_I_", "");
             if (rld::symbols::is_cplusplus (label))
               rld::symbols::demangle_name (label, label);
             std::cout << " " << label;
diff --git a/rtemstoolkit/libiberty/ansidecl.h b/rtemstoolkit/libiberty/ansidecl.h
index 86b0944..f6e1761 100644
--- a/rtemstoolkit/libiberty/ansidecl.h
+++ b/rtemstoolkit/libiberty/ansidecl.h
@@ -1,7 +1,5 @@
 /* ANSI and traditional C compatability macros
-   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2009
-   Free Software Foundation, Inc.
+   Copyright (C) 1991-2017 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
 This program is free software; you can redistribute it and/or modify
@@ -24,93 +22,16 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
 
    Macro		ANSI C definition	Traditional C definition
    -----		---- - ----------	----------- - ----------
-   ANSI_PROTOTYPES	1			not defined
    PTR			`void *'		`char *'
-   PTRCONST		`void *const'		`char *'
-   LONG_DOUBLE		`long double'		`double'
    const		not defined		`'
    volatile		not defined		`'
    signed		not defined		`'
-   VA_START(ap, var)	va_start(ap, var)	va_start(ap)
-
-   Note that it is safe to write "void foo();" indicating a function
-   with no return value, in all K+R compilers we have been able to test.
-
-   For declaring functions with prototypes, we also provide these:
-
-   PARAMS ((prototype))
-   -- for functions which take a fixed number of arguments.  Use this
-   when declaring the function.  When defining the function, write a
-   K+R style argument list.  For example:
-
-	char *strcpy PARAMS ((char *dest, char *source));
-	...
-	char *
-	strcpy (dest, source)
-	     char *dest;
-	     char *source;
-	{ ... }
-
-
-   VPARAMS ((prototype, ...))
-   -- for functions which take a variable number of arguments.  Use
-   PARAMS to declare the function, VPARAMS to define it.  For example:
-
-	int printf PARAMS ((const char *format, ...));
-	...
-	int
-	printf VPARAMS ((const char *format, ...))
-	{
-	   ...
-	}
-
-   For writing functions which take variable numbers of arguments, we
-   also provide the VA_OPEN, VA_CLOSE, and VA_FIXEDARG macros.  These
-   hide the differences between K+R <varargs.h> and C89 <stdarg.h> more
-   thoroughly than the simple VA_START() macro mentioned above.
-
-   VA_OPEN and VA_CLOSE are used *instead of* va_start and va_end.
-   Immediately after VA_OPEN, put a sequence of VA_FIXEDARG calls
-   corresponding to the list of fixed arguments.  Then use va_arg
-   normally to get the variable arguments, or pass your va_list object
-   around.  You do not declare the va_list yourself; VA_OPEN does it
-   for you.
-
-   Here is a complete example:
-
-	int
-	printf VPARAMS ((const char *format, ...))
-	{
-	   int result;
-
-	   VA_OPEN (ap, format);
-	   VA_FIXEDARG (ap, const char *, format);
-
-	   result = vfprintf (stdout, format, ap);
-	   VA_CLOSE (ap);
-
-	   return result;
-	}
-
-
-   You can declare variables either before or after the VA_OPEN,
-   VA_FIXEDARG sequence.  Also, VA_OPEN and VA_CLOSE are the beginning
-   and end of a block.  They must appear at the same nesting level,
-   and any variables declared after VA_OPEN go out of scope at
-   VA_CLOSE.  Unfortunately, with a K+R compiler, that includes the
-   argument list.  You can have multiple instances of VA_OPEN/VA_CLOSE
-   pairs in a single function in case you need to traverse the
-   argument list more than once.
 
    For ease of writing code which uses GCC extensions but needs to be
    portable to other compilers, we provide the GCC_VERSION macro that
    simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
    wrappers around __attribute__.  Also, __extension__ will be #defined
-   to nothing if it doesn't work.  See below.
-
-   This header also defines a lot of obsolete macros:
-   CONST, VOLATILE, SIGNED, PROTO, EXFUN, DEFUN, DEFUN_VOID,
-   AND, DOTS, NOARGS.  Don't use them.  */
+   to nothing if it doesn't work.  See below.  */
 
 #ifndef	_ANSIDECL_H
 #define _ANSIDECL_H	1
@@ -149,28 +70,8 @@ So instead we use the macro below and test it against specific values.  */
    C++ compilers, does not define __STDC__, though it acts as if this
    was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
 
-#define ANSI_PROTOTYPES	1
 #define PTR		void *
-#define PTRCONST	void *const
-#define LONG_DOUBLE	long double
-
-/* PARAMS is often defined elsewhere (e.g. by libintl.h), so wrap it in
-   a #ifndef.  */
-#ifndef PARAMS
-#define PARAMS(ARGS)		ARGS
-#endif
 
-#define VPARAMS(ARGS)		ARGS
-#define VA_START(VA_LIST, VAR)	va_start(VA_LIST, VAR)
-
-/* variadic function helper macros */
-/* "struct Qdmy" swallows the semicolon after VA_OPEN/VA_FIXEDARG's
-   use without inhibiting further decls and without declaring an
-   actual variable.  */
-#define VA_OPEN(AP, VAR)	{ va_list AP; va_start(AP, VAR); { struct Qdmy
-#define VA_CLOSE(AP)		} va_end(AP); }
-#define VA_FIXEDARG(AP, T, N)	struct Qdmy
- 
 #undef const
 #undef volatile
 #undef signed
@@ -178,7 +79,7 @@ So instead we use the macro below and test it against specific values.  */
 /* inline requires special treatment; it's in C99, and GCC >=2.7 supports
    it too, but it's not in C89.  */
 #undef inline
-#if __STDC_VERSION__ > 199901L || defined(__cplusplus)
+#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__))
 /* it's a keyword */
 #else
 # if GCC_VERSION >= 2007
@@ -188,35 +89,9 @@ So instead we use the macro below and test it against specific values.  */
 # endif
 #endif
 
-/* These are obsolete.  Do not use.  */
-#ifndef IN_GCC
-#define CONST		const
-#define VOLATILE	volatile
-#define SIGNED		signed
-
-#define PROTO(type, name, arglist)	type name arglist
-#define EXFUN(name, proto)		name proto
-#define DEFUN(name, arglist, args)	name(args)
-#define DEFUN_VOID(name)		name(void)
-#define AND		,
-#define DOTS		, ...
-#define NOARGS		void
-#endif /* ! IN_GCC */
-
 #else	/* Not ANSI C.  */
 
-#undef  ANSI_PROTOTYPES
 #define PTR		char *
-#define PTRCONST	PTR
-#define LONG_DOUBLE	double
-
-#define PARAMS(args)		()
-#define VPARAMS(args)		(va_alist) va_dcl
-#define VA_START(va_list, var)	va_start(va_list)
-
-#define VA_OPEN(AP, VAR)		{ va_list AP; va_start(AP); { struct Qdmy
-#define VA_CLOSE(AP)			} va_end(AP); }
-#define VA_FIXEDARG(AP, TYPE, NAME)	TYPE NAME = va_arg(AP, TYPE)
 
 /* some systems define these in header files for non-ansi mode */
 #undef const
@@ -228,20 +103,6 @@ So instead we use the macro below and test it against specific values.  */
 #define signed
 #define inline
 
-#ifndef IN_GCC
-#define CONST
-#define VOLATILE
-#define SIGNED
-
-#define PROTO(type, name, arglist)	type name ()
-#define EXFUN(name, proto)		name()
-#define DEFUN(name, arglist, args)	name arglist args;
-#define DEFUN_VOID(name)		name()
-#define AND		;
-#define DOTS
-#define NOARGS
-#endif /* ! IN_GCC */
-
 #endif	/* ANSI C.  */
 
 /* Define macros for some gcc attributes.  This permits us to use the
@@ -279,8 +140,15 @@ So instead we use the macro below and test it against specific values.  */
 # endif
 #endif
 
+/* Similarly to ARG_UNUSED below.  Prior to GCC 3.4, the C++ frontend
+   couldn't parse attributes placed after the identifier name, and now
+   the entire compiler is built with C++.  */
 #ifndef ATTRIBUTE_UNUSED
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#if GCC_VERSION >= 3004
+#  define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#else
+#define ATTRIBUTE_UNUSED
+#endif
 #endif /* ATTRIBUTE_UNUSED */
 
 /* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
@@ -304,6 +172,15 @@ So instead we use the macro below and test it against specific values.  */
 # endif /* GNUC >= 3.3 */
 #endif /* ATTRIBUTE_NONNULL */
 
+/* Attribute `returns_nonnull' was valid as of gcc 4.9.  */
+#ifndef ATTRIBUTE_RETURNS_NONNULL
+# if (GCC_VERSION >= 4009)
+#  define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
+# else
+#  define ATTRIBUTE_RETURNS_NONNULL
+# endif /* GNUC >= 4.9 */
+#endif /* ATTRIBUTE_RETURNS_NONNULL */
+
 /* Attribute `pure' was valid as of gcc 3.0.  */
 #ifndef ATTRIBUTE_PURE
 # if (GCC_VERSION >= 3000)
@@ -375,7 +252,7 @@ So instead we use the macro below and test it against specific values.  */
 # endif /* GNUC >= 3.0 */
 #endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
 
-/* Useful for structures whose layout must much some binary specification
+/* Useful for structures whose layout must match some binary specification
    regardless of the alignment and padding qualities of the compiler.  */
 #ifndef ATTRIBUTE_PACKED
 # define ATTRIBUTE_PACKED __attribute__ ((packed))
@@ -397,6 +274,15 @@ So instead we use the macro below and test it against specific values.  */
 # endif /* GNUC >= 4.3 */
 #endif /* ATTRIBUTE_HOT */
 
+/* Attribute 'no_sanitize_undefined' was valid as of gcc 4.9.  */
+#ifndef ATTRIBUTE_NO_SANITIZE_UNDEFINED
+# if (GCC_VERSION >= 4009)
+#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__ ((no_sanitize_undefined))
+# else
+#  define ATTRIBUTE_NO_SANITIZE_UNDEFINED
+# endif /* GNUC >= 4.9 */
+#endif /* ATTRIBUTE_NO_SANITIZE_UNDEFINED */
+
 /* We use __extension__ in some places to suppress -pedantic warnings
    about GCC extensions.  This feature didn't work properly before
    gcc 2.8.  */
@@ -416,6 +302,58 @@ So instead we use the macro below and test it against specific values.  */
 #define EXPORTED_CONST const
 #endif
 
+/* Be conservative and only use enum bitfields with C++ or GCC.
+   FIXME: provide a complete autoconf test for buggy enum bitfields.  */
+
+#ifdef __cplusplus
+#define ENUM_BITFIELD(TYPE) enum TYPE
+#elif (GCC_VERSION > 2000)
+#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
+#else
+#define ENUM_BITFIELD(TYPE) unsigned int
+#endif
+
+#if __cpp_constexpr >= 200704
+#define CONSTEXPR constexpr
+#else
+#define CONSTEXPR
+#endif
+
+/* C++11 adds the ability to add "override" after an implementation of a
+   virtual function in a subclass, to:
+     (A) document that this is an override of a virtual function
+     (B) allow the compiler to issue a warning if it isn't (e.g. a mismatch
+         of the type signature).
+
+   Similarly, it allows us to add a "final" to indicate that no subclass
+   may subsequently override the vfunc.
+
+   Provide OVERRIDE and FINAL as macros, allowing us to get these benefits
+   when compiling with C++11 support, but without requiring C++11.
+
+   For gcc, use "-std=c++11" to enable C++11 support; gcc 6 onwards enables
+   this by default (actually GNU++14).  */
+
+#if __cplusplus >= 201103
+/* C++11 claims to be available: use it.  final/override were only
+   implemented in 4.7, though.  */
+# if GCC_VERSION < 4007
+#  define OVERRIDE
+#  define FINAL
+# else
+#  define OVERRIDE override
+#  define FINAL final
+# endif
+#elif GCC_VERSION >= 4007
+/* G++ 4.7 supports __final in C++98.  */
+# define OVERRIDE
+# define FINAL __final
+#else
+/* No C++11 support; leave the macros empty: */
+# define OVERRIDE
+# define FINAL
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/rtemstoolkit/libiberty/concat.c b/rtemstoolkit/libiberty/concat.c
index 9779d56..e9671bb 100644
--- a/rtemstoolkit/libiberty/concat.c
+++ b/rtemstoolkit/libiberty/concat.c
@@ -1,5 +1,5 @@
 /* Concatenate variable number of strings.
-   Copyright (C) 1991, 1994, 2001, 2011 Free Software Foundation, Inc.
+   Copyright (C) 1991-2017 Free Software Foundation, Inc.
    Written by Fred Fish @ Cygnus Support
 
 This file is part of the libiberty library.
@@ -25,23 +25,11 @@ Boston, MA 02110-1301, USA.  */
   @dots{}, @code{NULL})
 
 Concatenate zero or more of strings and return the result in freshly
- at code{xmalloc}ed memory.  Returns @code{NULL} if insufficient memory is
-available.  The argument list is terminated by the first @code{NULL}
-pointer encountered.  Pointers to empty strings are ignored.
+ at code{xmalloc}ed memory.  The argument list is terminated by the first
+ at code{NULL} pointer encountered.  Pointers to empty strings are ignored.
 
 @end deftypefn
 
-NOTES
-
-	This function uses xmalloc() which is expected to be a front end
-	function to malloc() that deals with low memory situations.  In
-	typical use, if malloc() returns NULL then xmalloc() diverts to an
-	error handler routine which never returns, and thus xmalloc will
-	never return a NULL pointer.  If the client application wishes to
-	deal with low memory situations itself, it should supply an xmalloc
-	that just directly invokes malloc and blindly returns whatever
-	malloc returns.
-
 */
 
 
@@ -102,11 +90,11 @@ unsigned long
 concat_length (const char *first, ...)
 {
   unsigned long length;
+  va_list args;
 
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   length = vconcat_length (first, args);
-  VA_CLOSE (args);
+  va_end (args);
 
   return length;
 }
@@ -117,13 +105,12 @@ char *
 concat_copy (char *dst, const char *first, ...)
 {
   char *save_dst;
+  va_list args;
 
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, char *, dst);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   vconcat_copy (dst, first, args);
   save_dst = dst; /* With K&R C, dst goes out of scope here.  */
-  VA_CLOSE (args);
+  va_end (args);
 
   return save_dst;
 }
@@ -141,10 +128,10 @@ char *libiberty_concat_ptr;
 char *
 concat_copy2 (const char *first, ...)
 {
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, const char *, first);
+  va_list args;
+  va_start (args, first);
   vconcat_copy (libiberty_concat_ptr, first, args);
-  VA_CLOSE (args);
+  va_end (args);
 
   return libiberty_concat_ptr;
 }
@@ -153,18 +140,17 @@ char *
 concat (const char *first, ...)
 {
   char *newstr;
+  va_list args;
 
   /* First compute the size of the result and get sufficient memory.  */
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
-  VA_CLOSE (args);
+  va_end (args);
 
   /* Now copy the individual pieces to the result string. */
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   vconcat_copy (newstr, first, args);
-  VA_CLOSE (args);
+  va_end (args);
 
   return newstr;
 }
@@ -191,22 +177,19 @@ char *
 reconcat (char *optr, const char *first, ...)
 {
   char *newstr;
+  va_list args;
 
   /* First compute the size of the result and get sufficient memory.  */
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, char *, optr);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   newstr = XNEWVEC (char, vconcat_length (first, args) + 1);
-  VA_CLOSE (args);
+  va_end (args);
 
   /* Now copy the individual pieces to the result string. */
-  VA_OPEN (args, first);
-  VA_FIXEDARG (args, char *, optr);
-  VA_FIXEDARG (args, const char *, first);
+  va_start (args, first);
   vconcat_copy (newstr, first, args);
   if (optr) /* Done before VA_CLOSE so optr stays in scope for K&R C.  */
     free (optr);
-  VA_CLOSE (args);
+  va_end (args);
 
   return newstr;
 }
diff --git a/rtemstoolkit/libiberty/cp-demangle.c b/rtemstoolkit/libiberty/cp-demangle.c
index c590561..7b8d0b4 100644
--- a/rtemstoolkit/libiberty/cp-demangle.c
+++ b/rtemstoolkit/libiberty/cp-demangle.c
@@ -1,6 +1,5 @@
 /* Demangler for g++ V3 ABI.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian at wasabisystems.com>.
 
    This file is part of the libiberty library, which is part of GCC.
@@ -93,7 +92,11 @@
    CP_DEMANGLE_DEBUG
       If defined, turns on debugging mode, which prints information on
       stdout about the mangled string.  This is not generally useful.
-*/
+
+   CHECK_DEMANGLER
+      If defined, additional sanity checks will be performed.  It will
+      cause some slowdown, but will allow to catch out-of-bound access
+      errors earlier.  This macro is intended for testing and debugging.  */
 
 #if defined (_AIX) && !defined (__GNUC__)
  #pragma alloca
@@ -124,6 +127,13 @@ extern char *alloca ();
 # endif /* alloca */
 #endif /* HAVE_ALLOCA_H */
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef INT_MAX
+# define INT_MAX       (int)(((unsigned int) ~0) >> 1)          /* 0x7FFFFFFF */ 
+#endif
+
 #include "ansidecl.h"
 #include "libiberty.h"
 #include "demangle.h"
@@ -162,10 +172,10 @@ static struct demangle_component *d_mangled_name (struct d_info *, int);
 static struct demangle_component *d_type (struct d_info *);
 
 #define cplus_demangle_print d_print
-static char *d_print (int, const struct demangle_component *, int, size_t *);
+static char *d_print (int, struct demangle_component *, int, size_t *);
 
 #define cplus_demangle_print_callback d_print_callback
-static int d_print_callback (int, const struct demangle_component *,
+static int d_print_callback (int, struct demangle_component *,
                              demangle_callbackref, void *);
 
 #define cplus_demangle_init_info d_init_info
@@ -254,7 +264,7 @@ struct d_print_mod
      in which they appeared in the mangled string.  */
   struct d_print_mod *next;
   /* The modifier.  */
-  const struct demangle_component *mod;
+  struct demangle_component *mod;
   /* Whether this modifier was printed.  */
   int printed;
   /* The list of templates which applies to this modifier.  */
@@ -275,11 +285,46 @@ struct d_growable_string
   int allocation_failure;
 };
 
+/* Stack of components, innermost first, used to avoid loops.  */
+
+struct d_component_stack
+{
+  /* This component.  */
+  const struct demangle_component *dc;
+  /* This component's parent.  */
+  const struct d_component_stack *parent;
+};
+
+/* A demangle component and some scope captured when it was first
+   traversed.  */
+
+struct d_saved_scope
+{
+  /* The component whose scope this is.  */
+  const struct demangle_component *container;
+  /* The list of templates, if any, that was current when this
+     scope was captured.  */
+  struct d_print_template *templates;
+};
+
+/* Checkpoint structure to allow backtracking.  This holds copies
+   of the fields of struct d_info that need to be restored
+   if a trial parse needs to be backtracked over.  */
+
+struct d_info_checkpoint
+{
+  const char *n;
+  int next_comp;
+  int next_sub;
+  int expansion;
+};
+
+/* Maximum number of times d_print_comp may be called recursively.  */
+#define MAX_RECURSION_COUNT 1024
+
 enum { D_PRINT_BUFFER_LENGTH = 256 };
 struct d_print_info
 {
-  /* The options passed to the demangler.  */
-  int options;
   /* Fixed-length allocated buffer for demangled data, flushed to the
      callback with a NUL termination once full.  */
   char buf[D_PRINT_BUFFER_LENGTH];
@@ -299,9 +344,33 @@ struct d_print_info
   struct d_print_mod *modifiers;
   /* Set to 1 if we saw a demangling error.  */
   int demangle_failure;
+  /* Number of times d_print_comp was recursively called.  Should not
+     be bigger than MAX_RECURSION_COUNT.  */
+  int recursion;
+  /* Non-zero if we're printing a lambda argument.  A template
+     parameter reference actually means 'auto'.  */
+  int is_lambda_arg;
   /* The current index into any template argument packs we are using
-     for printing.  */
+     for printing, or -1 to print the whole pack.  */
   int pack_index;
+  /* Number of d_print_flush calls so far.  */
+  unsigned long int flush_count;
+  /* Stack of components, innermost first, used to avoid loops.  */
+  const struct d_component_stack *component_stack;
+  /* Array of saved scopes for evaluating substitutions.  */
+  struct d_saved_scope *saved_scopes;
+  /* Index of the next unused saved scope in the above array.  */
+  int next_saved_scope;
+  /* Number of saved scopes in the above array.  */
+  int num_saved_scopes;
+  /* Array of templates for saving into scopes.  */
+  struct d_print_template *copy_templates;
+  /* Index of the next unused copy template in the above array.  */
+  int next_copy_template;
+  /* Number of copy templates in the above array.  */
+  int num_copy_templates;
+  /* The nearest enclosing template, if any.  */
+  const struct demangle_component *current_template;
 };
 
 #ifdef CP_DEMANGLE_DEBUG
@@ -320,6 +389,9 @@ static struct demangle_component *
 d_make_name (struct d_info *, const char *, int);
 
 static struct demangle_component *
+d_make_demangle_mangled_name (struct d_info *, const char *);
+
+static struct demangle_component *
 d_make_builtin_type (struct d_info *,
                      const struct demangle_builtin_type_info *);
 
@@ -340,7 +412,7 @@ d_make_dtor (struct d_info *, enum gnu_v3_dtor_kinds,
              struct demangle_component *);
 
 static struct demangle_component *
-d_make_template_param (struct d_info *, long);
+d_make_template_param (struct d_info *, int);
 
 static struct demangle_component *
 d_make_sub (struct d_info *, const char *, int);
@@ -363,7 +435,7 @@ static struct demangle_component *d_unqualified_name (struct d_info *);
 
 static struct demangle_component *d_source_name (struct d_info *);
 
-static long d_number (struct d_info *);
+static int d_number (struct d_info *);
 
 static struct demangle_component *d_identifier (struct d_info *, int);
 
@@ -371,6 +443,8 @@ static struct demangle_component *d_operator_name (struct d_info *);
 
 static struct demangle_component *d_special_name (struct d_info *);
 
+static struct demangle_component *d_parmlist (struct d_info *);
+
 static int d_call_offset (struct d_info *, int);
 
 static struct demangle_component *d_ctor_dtor_name (struct d_info *);
@@ -379,6 +453,9 @@ static struct demangle_component **
 d_cv_qualifiers (struct d_info *, struct demangle_component **, int);
 
 static struct demangle_component *
+d_ref_qualifier (struct d_info *, struct demangle_component *);
+
+static struct demangle_component *
 d_function_type (struct d_info *);
 
 static struct demangle_component *
@@ -389,6 +466,8 @@ d_class_enum_type (struct d_info *);
 
 static struct demangle_component *d_array_type (struct d_info *);
 
+static struct demangle_component *d_vector_type (struct d_info *);
+
 static struct demangle_component *
 d_pointer_to_member_type (struct d_info *);
 
@@ -396,6 +475,7 @@ static struct demangle_component *
 d_template_param (struct d_info *);
 
 static struct demangle_component *d_template_args (struct d_info *);
+static struct demangle_component *d_template_args_1 (struct d_info *);
 
 static struct demangle_component *
 d_template_arg (struct d_info *);
@@ -408,11 +488,22 @@ static struct demangle_component *d_local_name (struct d_info *);
 
 static int d_discriminator (struct d_info *);
 
+static struct demangle_component *d_lambda (struct d_info *);
+
+static struct demangle_component *d_unnamed_type (struct d_info *);
+
+static struct demangle_component *
+d_clone_suffix (struct d_info *, struct demangle_component *);
+
 static int
 d_add_substitution (struct d_info *, struct demangle_component *);
 
 static struct demangle_component *d_substitution (struct d_info *, int);
 
+static void d_checkpoint (struct d_info *, struct d_info_checkpoint *);
+
+static void d_backtrack (struct d_info *, struct d_info_checkpoint *);
+
 static void d_growable_string_init (struct d_growable_string *, size_t);
 
 static inline void
@@ -425,7 +516,8 @@ static void
 d_growable_string_callback_adapter (const char *, size_t, void *);
 
 static void
-d_print_init (struct d_print_info *, int, demangle_callbackref, void *);
+d_print_init (struct d_print_info *, demangle_callbackref, void *,
+	      const struct demangle_component *);
 
 static inline void d_print_error (struct d_print_info *);
 
@@ -443,37 +535,65 @@ static inline void d_append_string (struct d_print_info *, const char *);
 static inline char d_last_char (struct d_print_info *);
 
 static void
-d_print_comp (struct d_print_info *, const struct demangle_component *);
+d_print_comp (struct d_print_info *, int, struct demangle_component *);
 
 static void
 d_print_java_identifier (struct d_print_info *, const char *, int);
 
 static void
-d_print_mod_list (struct d_print_info *, struct d_print_mod *, int);
+d_print_mod_list (struct d_print_info *, int, struct d_print_mod *, int);
 
 static void
-d_print_mod (struct d_print_info *, const struct demangle_component *);
+d_print_mod (struct d_print_info *, int, struct demangle_component *);
 
 static void
-d_print_function_type (struct d_print_info *,
-                       const struct demangle_component *,
+d_print_function_type (struct d_print_info *, int,
+                       struct demangle_component *,
                        struct d_print_mod *);
 
 static void
-d_print_array_type (struct d_print_info *,
-                    const struct demangle_component *,
+d_print_array_type (struct d_print_info *, int,
+                    struct demangle_component *,
                     struct d_print_mod *);
 
 static void
-d_print_expr_op (struct d_print_info *, const struct demangle_component *);
+d_print_expr_op (struct d_print_info *, int, struct demangle_component *);
 
-static void
-d_print_cast (struct d_print_info *, const struct demangle_component *);
+static void d_print_cast (struct d_print_info *, int,
+			  struct demangle_component *);
+static void d_print_conversion (struct d_print_info *, int,
+				struct demangle_component *);
 
 static int d_demangle_callback (const char *, int,
                                 demangle_callbackref, void *);
 static char *d_demangle (const char *, int, size_t *);
 
+/* 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
@@ -496,9 +616,17 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_NAME:
       printf ("name '%.*s'\n", dc->u.s_name.len, dc->u.s_name.s);
       return;
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+      printf ("tagged name\n");
+      d_dump (dc->u.s_binary.left, indent + 2);
+      d_dump (dc->u.s_binary.right, indent + 2);
+      return;
     case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
       printf ("template parameter %ld\n", dc->u.s_number.number);
       return;
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+      printf ("function parameter %ld\n", dc->u.s_number.number);
+      return;
     case DEMANGLE_COMPONENT_CTOR:
       printf ("constructor %d\n", (int) dc->u.s_ctor.kind);
       d_dump (dc->u.s_ctor.name, indent + 2);
@@ -573,6 +701,12 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
       printf ("hidden alias\n");
       break;
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+      printf ("transaction clone\n");
+      break;
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+      printf ("non-transaction clone\n");
+      break;
     case DEMANGLE_COMPONENT_RESTRICT:
       printf ("restrict\n");
       break;
@@ -591,6 +725,15 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_CONST_THIS:
       printf ("const this\n");
       break;
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+      printf ("reference this\n");
+      break;
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+      printf ("rvalue reference this\n");
+      break;
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+      printf ("transaction_safe this\n");
+      break;
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
       printf ("vendor type qualifier\n");
       break;
@@ -622,7 +765,9 @@ d_dump (struct demangle_component *dc, int indent)
       printf ("pointer to member type\n");
       break;
     case DEMANGLE_COMPONENT_FIXED_TYPE:
-      printf ("fixed-point type\n");
+      printf ("fixed-point type, accum? %d, sat? %d\n",
+              dc->u.s_fixed.accum, dc->u.s_fixed.sat);
+      d_dump (dc->u.s_fixed.length, indent + 2);
       break;
     case DEMANGLE_COMPONENT_ARGLIST:
       printf ("argument list\n");
@@ -630,9 +775,18 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
       printf ("template argument list\n");
       break;
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+      printf ("initializer list\n");
+      break;
     case DEMANGLE_COMPONENT_CAST:
       printf ("cast\n");
       break;
+    case DEMANGLE_COMPONENT_CONVERSION:
+      printf ("conversion operator\n");
+      break;
+    case DEMANGLE_COMPONENT_NULLARY:
+      printf ("nullary operator\n");
+      break;
     case DEMANGLE_COMPONENT_UNARY:
       printf ("unary operator\n");
       break;
@@ -666,12 +820,29 @@ d_dump (struct demangle_component *dc, int indent)
     case DEMANGLE_COMPONENT_CHARACTER:
       printf ("character '%c'\n",  dc->u.s_character.character);
       return;
+    case DEMANGLE_COMPONENT_NUMBER:
+      printf ("number %ld\n", dc->u.s_number.number);
+      return;
     case DEMANGLE_COMPONENT_DECLTYPE:
       printf ("decltype\n");
       break;
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
       printf ("pack expansion\n");
       break;
+    case DEMANGLE_COMPONENT_TLS_INIT:
+      printf ("tls init function\n");
+      break;
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
+      printf ("tls wrapper function\n");
+      break;
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+      printf ("default argument %d\n", dc->u.s_unary_num.num);
+      d_dump (dc->u.s_unary_num.sub, indent+2);
+      return;
+    case DEMANGLE_COMPONENT_LAMBDA:
+      printf ("lambda %d\n", dc->u.s_unary_num.num);
+      d_dump (dc->u.s_unary_num.sub, indent+2);
+      return;
     }
 
   d_dump (d_left (dc), indent + 2);
@@ -688,6 +859,7 @@ cplus_demangle_fill_name (struct demangle_component *p, const char *s, int len)
 {
   if (p == NULL || s == NULL || len == 0)
     return 0;
+  p->d_printing = 0;
   p->type = DEMANGLE_COMPONENT_NAME;
   p->u.s_name.s = s;
   p->u.s_name.len = len;
@@ -703,6 +875,7 @@ cplus_demangle_fill_extended_operator (struct demangle_component *p, int args,
 {
   if (p == NULL || args < 0 || name == NULL)
     return 0;
+  p->d_printing = 0;
   p->type = DEMANGLE_COMPONENT_EXTENDED_OPERATOR;
   p->u.s_extended_operator.args = args;
   p->u.s_extended_operator.name = name;
@@ -720,8 +893,9 @@ cplus_demangle_fill_ctor (struct demangle_component *p,
   if (p == NULL
       || name == NULL
       || (int) kind < gnu_v3_complete_object_ctor
-      || (int) kind > gnu_v3_complete_object_allocating_ctor)
+      || (int) kind > gnu_v3_object_ctor_group)
     return 0;
+  p->d_printing = 0;
   p->type = DEMANGLE_COMPONENT_CTOR;
   p->u.s_ctor.kind = kind;
   p->u.s_ctor.name = name;
@@ -739,8 +913,9 @@ cplus_demangle_fill_dtor (struct demangle_component *p,
   if (p == NULL
       || name == NULL
       || (int) kind < gnu_v3_deleting_dtor
-      || (int) kind > gnu_v3_base_object_dtor)
+      || (int) kind > gnu_v3_object_dtor_group)
     return 0;
+  p->d_printing = 0;
   p->type = DEMANGLE_COMPONENT_DTOR;
   p->u.s_dtor.kind = kind;
   p->u.s_dtor.name = name;
@@ -757,6 +932,7 @@ d_make_empty (struct d_info *di)
   if (di->next_comp >= di->num_comps)
     return NULL;
   p = &di->comps[di->next_comp];
+  p->d_printing = 0;
   ++di->next_comp;
   return p;
 }
@@ -779,6 +955,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_QUAL_NAME:
     case DEMANGLE_COMPONENT_LOCAL_NAME:
     case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
     case DEMANGLE_COMPONENT_TEMPLATE:
     case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
@@ -788,10 +965,11 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_BINARY_ARGS:
     case DEMANGLE_COMPONENT_TRINARY:
     case DEMANGLE_COMPONENT_TRINARY_ARG1:
-    case DEMANGLE_COMPONENT_TRINARY_ARG2:
     case DEMANGLE_COMPONENT_LITERAL:
     case DEMANGLE_COMPONENT_LITERAL_NEG:
     case DEMANGLE_COMPONENT_COMPOUND_NAME:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+    case DEMANGLE_COMPONENT_CLONE:
       if (left == NULL || right == NULL)
 	return NULL;
       break;
@@ -807,8 +985,12 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_COVARIANT_THUNK:
     case DEMANGLE_COMPONENT_JAVA_CLASS:
     case DEMANGLE_COMPONENT_GUARD:
+    case DEMANGLE_COMPONENT_TLS_INIT:
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
     case DEMANGLE_COMPONENT_REFTEMP:
     case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
     case DEMANGLE_COMPONENT_POINTER:
     case DEMANGLE_COMPONENT_REFERENCE:
     case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
@@ -816,11 +998,14 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_IMAGINARY:
     case DEMANGLE_COMPONENT_VENDOR_TYPE:
     case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
     case DEMANGLE_COMPONENT_JAVA_RESOURCE:
     case DEMANGLE_COMPONENT_DECLTYPE:
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
     case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
     case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+    case DEMANGLE_COMPONENT_NULLARY:
+    case DEMANGLE_COMPONENT_TRINARY_ARG2:
       if (left == NULL)
 	return NULL;
       break;
@@ -828,6 +1013,7 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
       /* This needs a right parameter, but the left parameter can be
 	 empty.  */
     case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
       if (right == NULL)
 	return NULL;
       break;
@@ -838,11 +1024,9 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
     case DEMANGLE_COMPONENT_RESTRICT:
     case DEMANGLE_COMPONENT_VOLATILE:
     case DEMANGLE_COMPONENT_CONST:
-    case DEMANGLE_COMPONENT_RESTRICT_THIS:
-    case DEMANGLE_COMPONENT_VOLATILE_THIS:
-    case DEMANGLE_COMPONENT_CONST_THIS:
     case DEMANGLE_COMPONENT_ARGLIST:
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+    FNQUAL_COMPONENT_CASE:
       break;
 
       /* Other types should not be seen here.  */
@@ -860,6 +1044,17 @@ d_make_comp (struct d_info *di, enum demangle_component_type type,
   return p;
 }
 
+/* Add a new demangle mangled name component.  */
+
+static struct demangle_component *
+d_make_demangle_mangled_name (struct d_info *di, const char *s)
+{
+  if (d_peek_char (di) != '_' || d_peek_next_char (di) != 'Z')
+    return d_make_name (di, s, strlen (s));
+  d_advance (di, 2);
+  return d_encoding (di, 0);
+}
+
 /* Add a new name component.  */
 
 static struct demangle_component *
@@ -922,6 +1117,20 @@ d_make_extended_operator (struct d_info *di, int args,
   return p;
 }
 
+static struct demangle_component *
+d_make_default_arg (struct d_info *di, int num,
+		    struct demangle_component *sub)
+{
+  struct demangle_component *p = d_make_empty (di);
+  if (p)
+    {
+      p->type = DEMANGLE_COMPONENT_DEFAULT_ARG;
+      p->u.s_unary_num.num = num;
+      p->u.s_unary_num.sub = sub;
+    }
+  return p;
+}
+
 /* Add a new constructor component.  */
 
 static struct demangle_component *
@@ -953,7 +1162,7 @@ d_make_dtor (struct d_info *di, enum gnu_v3_dtor_kinds kind,
 /* Add a new template parameter.  */
 
 static struct demangle_component *
-d_make_template_param (struct d_info *di, long i)
+d_make_template_param (struct d_info *di, int i)
 {
   struct demangle_component *p;
 
@@ -969,7 +1178,7 @@ d_make_template_param (struct d_info *di, long i)
 /* Add a new function parameter.  */
 
 static struct demangle_component *
-d_make_function_param (struct d_info *di, long i)
+d_make_function_param (struct d_info *di, int i)
 {
   struct demangle_component *p;
 
@@ -999,7 +1208,7 @@ d_make_sub (struct d_info *di, const char *name, int len)
   return p;
 }
 
-/* <mangled-name> ::= _Z <encoding>
+/* <mangled-name> ::= _Z <encoding> [<clone-suffix>]*
 
    TOP_LEVEL is non-zero when called at the top level.  */
 
@@ -1007,6 +1216,8 @@ CP_STATIC_IF_GLIBCPP_V3
 struct demangle_component *
 cplus_demangle_mangled_name (struct d_info *di, int top_level)
 {
+  struct demangle_component *p;
+
   if (! d_check_char (di, '_')
       /* Allow missing _ if not at toplevel to work around a
 	 bug in G++ abi-version=2 mangling; see the comment in
@@ -1015,7 +1226,18 @@ cplus_demangle_mangled_name (struct d_info *di, int top_level)
     return NULL;
   if (! d_check_char (di, 'Z'))
     return NULL;
-  return d_encoding (di, top_level);
+  p = d_encoding (di, top_level);
+
+  /* If at top level and parsing parameters, check for a clone
+     suffix.  */
+  if (top_level && (di->options & DMGL_PARAMS) != 0)
+    while (d_peek_char (di) == '.'
+	   && (IS_LOWER (d_peek_next_char (di))
+	       || d_peek_next_char (di) == '_'
+	       || IS_DIGIT (d_peek_next_char (di))))
+      p = d_clone_suffix (di, p);
+
+  return p;
 }
 
 /* Return whether a function should have a return type.  The argument
@@ -1038,9 +1260,7 @@ has_return_type (struct demangle_component *dc)
       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:
+    FNQUAL_COMPONENT_CASE:
       return has_return_type (d_left (dc));
     }
 }
@@ -1062,7 +1282,7 @@ is_ctor_dtor_or_conversion (struct demangle_component *dc)
       return is_ctor_dtor_or_conversion (d_right (dc));
     case DEMANGLE_COMPONENT_CTOR:
     case DEMANGLE_COMPONENT_DTOR:
-    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
       return 1;
     }
 }
@@ -1096,11 +1316,13 @@ d_encoding (struct d_info *di, int top_level)
 	     v2 demangler without DMGL_PARAMS.  */
 	  while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
 		 || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-		 || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+		 || dc->type == DEMANGLE_COMPONENT_CONST_THIS
+		 || 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)
@@ -1108,9 +1330,7 @@ d_encoding (struct d_info *di, int top_level)
 	      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)
+	      while (is_fnqual_component_type (dcr->type))
 		dcr = d_left (dcr);
 	      dc->u.s_binary.right = dcr;
 	    }
@@ -1126,6 +1346,31 @@ d_encoding (struct d_info *di, int top_level)
     }
 }
 
+/* <tagged-name> ::= <name> B <source-name> */
+
+static struct demangle_component *
+d_abi_tags (struct d_info *di, struct demangle_component *dc)
+{
+  struct demangle_component *hold_last_name;
+  char peek;
+
+  /* Preserve the last name, so the ABI tag doesn't clobber it.  */
+  hold_last_name = di->last_name;
+
+  while (peek = d_peek_char (di),
+	 peek == 'B')
+    {
+      struct demangle_component *tag;
+      d_advance (di, 1);
+      tag = d_source_name (di);
+      dc = d_make_comp (di, DEMANGLE_COMPONENT_TAGGED_NAME, dc, tag);
+    }
+
+  di->last_name = hold_last_name;
+
+  return dc;
+}
+
 /* <name> ::= <nested-name>
           ::= <unscoped-name>
           ::= <unscoped-template-name> <template-args>
@@ -1152,9 +1397,9 @@ d_name (struct d_info *di)
     case 'Z':
       return d_local_name (di);
 
-    case 'L':
+    case 'U':
       return d_unqualified_name (di);
-	
+
     case 'S':
       {
 	int subst;
@@ -1198,6 +1443,7 @@ d_name (struct d_info *di)
 	return dc;
       }
 
+    case 'L':
     default:
       dc = d_unqualified_name (di);
       if (d_peek_char (di) == 'I')
@@ -1214,8 +1460,8 @@ d_name (struct d_info *di)
     }
 }
 
-/* <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
-                 ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
+/* <nested-name> ::= N [<CV-qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E
+                 ::= N [<CV-qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E
 */
 
 static struct demangle_component *
@@ -1223,6 +1469,7 @@ d_nested_name (struct d_info *di)
 {
   struct demangle_component *ret;
   struct demangle_component **pret;
+  struct demangle_component *rqual;
 
   if (! d_check_char (di, 'N'))
     return NULL;
@@ -1231,10 +1478,20 @@ d_nested_name (struct d_info *di)
   if (pret == NULL)
     return NULL;
 
+  /* Parse the ref-qualifier now and then attach it
+     once we have something to attach it to.  */
+  rqual = d_ref_qualifier (di, NULL);
+
   *pret = d_prefix (di);
   if (*pret == NULL)
     return NULL;
 
+  if (rqual)
+    {
+      d_left (rqual) = ret;
+      ret = rqual;
+    }
+
   if (! d_check_char (di, 'E'))
     return NULL;
 
@@ -1244,6 +1501,7 @@ d_nested_name (struct d_info *di)
 /* <prefix> ::= <prefix> <unqualified-name>
             ::= <template-prefix> <template-args>
             ::= <template-param>
+            ::= <decltype>
             ::=
             ::= <substitution>
 
@@ -1272,10 +1530,20 @@ d_prefix (struct d_info *di)
 	 <template-param> here.  */
 
       comb_type = DEMANGLE_COMPONENT_QUAL_NAME;
-      if (IS_DIGIT (peek)
+      if (peek == 'D')
+	{
+	  char peek2 = d_peek_next_char (di);
+	  if (peek2 == 'T' || peek2 == 't')
+	    /* Decltype.  */
+	    dc = cplus_demangle_type (di);
+	  else
+	    /* Destructor name.  */
+	    dc = d_unqualified_name (di);
+	}
+      else if (IS_DIGIT (peek)
 	  || IS_LOWER (peek)
 	  || peek == 'C'
-	  || peek == 'D'
+	  || peek == 'U'
 	  || peek == 'L')
 	dc = d_unqualified_name (di);
       else if (peek == 'S')
@@ -1291,6 +1559,16 @@ d_prefix (struct d_info *di)
 	dc = d_template_param (di);
       else if (peek == 'E')
 	return ret;
+      else if (peek == 'M')
+	{
+	  /* Initializer scope for a lambda.  We don't need to represent
+	     this; the normal code will just treat the variable as a type
+	     scope, which gives appropriate output.  */
+	  if (ret == NULL)
+	    return NULL;
+	  d_advance (di, 1);
+	  continue;
+	}
       else
 	return NULL;
 
@@ -1318,26 +1596,29 @@ d_prefix (struct d_info *di)
 static struct demangle_component *
 d_unqualified_name (struct d_info *di)
 {
+  struct demangle_component *ret;
   char peek;
 
   peek = d_peek_char (di);
   if (IS_DIGIT (peek))
-    return d_source_name (di);
+    ret = d_source_name (di);
   else if (IS_LOWER (peek))
     {
-      struct demangle_component *ret;
-
+      if (peek == 'o' && d_peek_next_char (di) == 'n')
+	d_advance (di, 2);
       ret = d_operator_name (di);
       if (ret != NULL && ret->type == DEMANGLE_COMPONENT_OPERATOR)
-	di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
-      return ret;
+	{
+	  di->expansion += sizeof "operator" + ret->u.s_operator.op->len - 2;
+	  if (!strcmp (ret->u.s_operator.op->code, "li"))
+	    ret = d_make_comp (di, DEMANGLE_COMPONENT_UNARY, ret,
+			       d_source_name (di));
+	}
     }
   else if (peek == 'C' || peek == 'D')
-    return d_ctor_dtor_name (di);
+    ret = d_ctor_dtor_name (di);
   else if (peek == 'L')
     {
-      struct demangle_component * ret;
-
       d_advance (di, 1);
 
       ret = d_source_name (di);
@@ -1345,10 +1626,27 @@ d_unqualified_name (struct d_info *di)
 	return NULL;
       if (! d_discriminator (di))
 	return NULL;
-      return ret;
+    }
+  else if (peek == 'U')
+    {
+      switch (d_peek_next_char (di))
+	{
+	case 'l':
+	  ret = d_lambda (di);
+	  break;
+	case 't':
+	  ret = d_unnamed_type (di);
+	  break;
+	default:
+	  return NULL;
+	}
     }
   else
     return NULL;
+
+  if (d_peek_char (di) == 'B')
+    ret = d_abi_tags (di, ret);
+  return ret;
 }
 
 /* <source-name> ::= <(positive length) number> <identifier>  */
@@ -1356,7 +1654,7 @@ d_unqualified_name (struct d_info *di)
 static struct demangle_component *
 d_source_name (struct d_info *di)
 {
-  long len;
+  int len;
   struct demangle_component *ret;
 
   len = d_number (di);
@@ -1369,12 +1667,12 @@ d_source_name (struct d_info *di)
 
 /* number ::= [n] <(non-negative decimal integer)>  */
 
-static long
+static int
 d_number (struct d_info *di)
 {
   int negative;
   char peek;
-  long ret;
+  int ret;
 
   negative = 0;
   peek = d_peek_char (di);
@@ -1394,12 +1692,28 @@ d_number (struct d_info *di)
 	    ret = - ret;
 	  return ret;
 	}
+      if (ret > ((INT_MAX - (peek - '0')) / 10))
+        return -1;
       ret = ret * 10 + peek - '0';
       d_advance (di, 1);
       peek = d_peek_char (di);
     }
 }
 
+/* Like d_number, but returns a demangle_component.  */
+
+static struct demangle_component *
+d_number_component (struct d_info *di)
+{
+  struct demangle_component *ret = d_make_empty (di);
+  if (ret)
+    {
+      ret->type = DEMANGLE_COMPONENT_NUMBER;
+      ret->u.s_number.number = d_number (di);
+    }
+  return ret;
+}
+
 /* identifier ::= <(unqualified source code identifier)>  */
 
 static struct demangle_component *
@@ -1446,7 +1760,8 @@ d_identifier (struct d_info *di, int len)
 /* operator_name ::= many different two character encodings.
                  ::= cv <type>
                  ::= v <digit> <source-name>
-*/
+
+   This list is sorted for binary search.  */
 
 #define NL(s) s, (sizeof s) - 1
 
@@ -1458,23 +1773,34 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "aa", NL ("&&"),        2 },
   { "ad", NL ("&"),         1 },
   { "an", NL ("&"),         2 },
+  { "at", NL ("alignof "),   1 },
+  { "az", NL ("alignof "),   1 },
+  { "cc", NL ("const_cast"), 2 },
   { "cl", NL ("()"),        2 },
   { "cm", NL (","),         2 },
   { "co", NL ("~"),         1 },
   { "dV", NL ("/="),        2 },
-  { "da", NL ("delete[]"),  1 },
+  { "da", NL ("delete[] "), 1 },
+  { "dc", NL ("dynamic_cast"), 2 },
   { "de", NL ("*"),         1 },
-  { "dl", NL ("delete"),    1 },
+  { "dl", NL ("delete "),   1 },
+  { "ds", NL (".*"),        2 },
   { "dt", NL ("."),         2 },
   { "dv", NL ("/"),         2 },
   { "eO", NL ("^="),        2 },
   { "eo", NL ("^"),         2 },
   { "eq", NL ("=="),        2 },
+  { "fL", NL ("..."),       3 },
+  { "fR", NL ("..."),       3 },
+  { "fl", NL ("..."),       2 },
+  { "fr", NL ("..."),       2 },
   { "ge", NL (">="),        2 },
+  { "gs", NL ("::"),	    1 },
   { "gt", NL (">"),         2 },
   { "ix", NL ("[]"),        2 },
   { "lS", NL ("<<="),       2 },
   { "le", NL ("<="),        2 },
+  { "li", NL ("operator\"\" "), 1 },
   { "ls", NL ("<<"),        2 },
   { "lt", NL ("<"),         2 },
   { "mI", NL ("-="),        2 },
@@ -1482,11 +1808,11 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "mi", NL ("-"),         2 },
   { "ml", NL ("*"),         2 },
   { "mm", NL ("--"),        1 },
-  { "na", NL ("new[]"),     1 },
+  { "na", NL ("new[]"),     3 },
   { "ne", NL ("!="),        2 },
   { "ng", NL ("-"),         1 },
   { "nt", NL ("!"),         1 },
-  { "nw", NL ("new"),       1 },
+  { "nw", NL ("new"),       3 },
   { "oR", NL ("|="),        2 },
   { "oo", NL ("||"),        2 },
   { "or", NL ("|"),         2 },
@@ -1499,12 +1825,16 @@ const struct demangle_operator_info cplus_demangle_operators[] =
   { "qu", NL ("?"),         3 },
   { "rM", NL ("%="),        2 },
   { "rS", NL (">>="),       2 },
+  { "rc", NL ("reinterpret_cast"), 2 },
   { "rm", NL ("%"),         2 },
   { "rs", NL (">>"),        2 },
+  { "sP", NL ("sizeof..."), 1 },
+  { "sZ", NL ("sizeof..."), 1 },
+  { "sc", NL ("static_cast"), 2 },
   { "st", NL ("sizeof "),   1 },
   { "sz", NL ("sizeof "),   1 },
-  { "at", NL ("alignof "),   1 },
-  { "az", NL ("alignof "),   1 },
+  { "tr", NL ("throw"),     0 },
+  { "tw", NL ("throw "),    1 },
   { NULL, NULL, 0,          0 }
 };
 
@@ -1519,8 +1849,20 @@ d_operator_name (struct d_info *di)
   if (c1 == 'v' && IS_DIGIT (c2))
     return d_make_extended_operator (di, c2 - '0', d_source_name (di));
   else if (c1 == 'c' && c2 == 'v')
-    return d_make_comp (di, DEMANGLE_COMPONENT_CAST,
-			cplus_demangle_type (di), NULL);
+    {
+      struct demangle_component *type;
+      int was_conversion = di->is_conversion;
+      struct demangle_component *res;
+
+      di->is_conversion = ! di->is_expression;
+      type = cplus_demangle_type (di);
+      if (di->is_conversion)
+	res = d_make_comp (di, DEMANGLE_COMPONENT_CONVERSION, type, NULL);
+      else
+	res = d_make_comp (di, DEMANGLE_COMPONENT_CAST, type, NULL);
+      di->is_conversion = was_conversion;
+      return res;
+    }
   else
     {
       /* LOW is the inclusive lower bound.  */
@@ -1570,7 +1912,7 @@ d_java_resource (struct d_info *di)
 {
   struct demangle_component *p = NULL;
   struct demangle_component *next = NULL;
-  long len, i;
+  int len, i;
   char c;
   const char *str;
 
@@ -1662,6 +2004,8 @@ d_java_resource (struct d_info *di)
                   ::= GR <name>
 		  ::= GA <encoding>
 		  ::= Gr <resource name>
+		  ::= GTt <encoding>
+		  ::= GTn <encoding>
 */
 
 static struct demangle_component *
@@ -1710,7 +2054,7 @@ d_special_name (struct d_info *di)
 	case 'C':
 	  {
 	    struct demangle_component *derived_type;
-	    long offset;
+	    int offset;
 	    struct demangle_component *base_type;
 
 	    derived_type = cplus_demangle_type (di);
@@ -1734,6 +2078,14 @@ d_special_name (struct d_info *di)
 	  return d_make_comp (di, DEMANGLE_COMPONENT_JAVA_CLASS,
 			      cplus_demangle_type (di), NULL);
 
+	case 'H':
+	  return d_make_comp (di, DEMANGLE_COMPONENT_TLS_INIT,
+			      d_name (di), NULL);
+
+	case 'W':
+	  return d_make_comp (di, DEMANGLE_COMPONENT_TLS_WRAPPER,
+			      d_name (di), NULL);
+
 	default:
 	  return NULL;
 	}
@@ -1746,13 +2098,33 @@ d_special_name (struct d_info *di)
 	  return d_make_comp (di, DEMANGLE_COMPONENT_GUARD, d_name (di), NULL);
 
 	case 'R':
-	  return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, d_name (di),
-			      NULL);
+	  {
+	    struct demangle_component *name = d_name (di);
+	    return d_make_comp (di, DEMANGLE_COMPONENT_REFTEMP, name,
+				d_number_component (di));
+	  }
 
 	case 'A':
 	  return d_make_comp (di, DEMANGLE_COMPONENT_HIDDEN_ALIAS,
 			      d_encoding (di, 0), NULL);
 
+	case 'T':
+	  switch (d_next_char (di))
+	    {
+	    case 'n':
+	      return d_make_comp (di, DEMANGLE_COMPONENT_NONTRANSACTION_CLONE,
+				  d_encoding (di, 0), NULL);
+	    default:
+	      /* ??? The proposal is that other letters (such as 'h') stand
+		 for different variants of transaction cloning, such as
+		 compiling directly for hardware transaction support.  But
+		 they still should all be transactional clones of some sort
+		 so go ahead and call them that.  */
+	    case 't':
+	      return d_make_comp (di, DEMANGLE_COMPONENT_TRANSACTION_CLONE,
+				  d_encoding (di, 0), NULL);
+	    }
+
 	case 'r':
 	  return d_java_resource (di);
 
@@ -1824,6 +2196,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))
 	  {
@@ -1836,10 +2215,21 @@ d_ctor_dtor_name (struct d_info *di)
 	  case '3':
 	    kind = gnu_v3_complete_object_allocating_ctor;
 	    break;
+          case '4':
+	    kind = gnu_v3_unified_ctor;
+	    break;
+	  case '5':
+	    kind = gnu_v3_object_ctor_group;
+	    break;
 	  default:
 	    return NULL;
 	  }
+
 	d_advance (di, 2);
+
+	if (inheriting)
+	  cplus_demangle_type (di);
+
 	return d_make_ctor (di, kind, di->last_name);
       }
 
@@ -1858,6 +2248,13 @@ d_ctor_dtor_name (struct d_info *di)
 	  case '2':
 	    kind = gnu_v3_base_object_dtor;
 	    break;
+          /*  digit '3' is not used */
+	  case '4':
+	    kind = gnu_v3_unified_dtor;
+	    break;
+	  case '5':
+	    kind = gnu_v3_object_dtor_group;
+	    break;
 	  default:
 	    return NULL;
 	  }
@@ -1870,6 +2267,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>
@@ -1928,6 +2343,8 @@ cplus_demangle_builtin_types[D_BUILTIN_TYPE_COUNT] =
   /* 29 */ { NL ("half"),	NL ("half"),		D_PRINT_FLOAT },
   /* 30 */ { NL ("char16_t"),	NL ("char16_t"),	D_PRINT_DEFAULT },
   /* 31 */ { NL ("char32_t"),	NL ("char32_t"),	D_PRINT_DEFAULT },
+  /* 32 */ { NL ("decltype(nullptr)"),	NL ("decltype(nullptr)"),
+	     D_PRINT_DEFAULT },
 };
 
 CP_STATIC_IF_GLIBCPP_V3
@@ -1953,22 +2370,42 @@ cplus_demangle_type (struct d_info *di)
      __vector, and it treats it as order-sensitive when mangling
      names.  */
 
-  peek = d_peek_char (di);
-  if (peek == 'r' || peek == 'V' || peek == 'K')
+  if (next_is_type_qual (di))
     {
       struct demangle_component **pret;
 
       pret = d_cv_qualifiers (di, &ret, 0);
       if (pret == NULL)
 	return NULL;
-      *pret = cplus_demangle_type (di);
-      if (! *pret || ! d_add_substitution (di, ret))
+      if (d_peek_char (di) == 'F')
+	{
+	  /* cv-qualifiers before a function type apply to 'this',
+	     so avoid adding the unqualified function type to
+	     the substitution list.  */
+	  *pret = d_function_type (di);
+	}
+      else
+	*pret = cplus_demangle_type (di);
+      if (!*pret)
+	return NULL;
+      if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
+	  || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
+	{
+	  /* Move the ref-qualifier outside the cv-qualifiers so that
+	     they are printed in the right order.  */
+	  struct demangle_component *fn = d_left (*pret);
+	  d_left (*pret) = ret;
+	  ret = *pret;
+	  *pret = fn;
+	}
+      if (! d_add_substitution (di, ret))
 	return NULL;
       return ret;
     }
 
   can_subst = 1;
 
+  peek = d_peek_char (di);
   switch (peek)
     {
     case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
@@ -2011,13 +2448,61 @@ cplus_demangle_type (struct d_info *di)
       ret = d_template_param (di);
       if (d_peek_char (di) == 'I')
 	{
-	  /* This is <template-template-param> <template-args>.  The
-	     <template-template-param> part is a substitution
+	  /* This may be <template-template-param> <template-args>.
+	     If this is the type for a conversion operator, we can
+	     have a <template-template-param> here only by following
+	     a derivation like this:
+
+	     <nested-name>
+	     -> <template-prefix> <template-args>
+	     -> <prefix> <template-unqualified-name> <template-args>
+	     -> <unqualified-name> <template-unqualified-name> <template-args>
+	     -> <source-name> <template-unqualified-name> <template-args>
+	     -> <source-name> <operator-name> <template-args>
+	     -> <source-name> cv <type> <template-args>
+	     -> <source-name> cv <template-template-param> <template-args> <template-args>
+
+	     where the <template-args> is followed by another.
+	     Otherwise, we must have a derivation like this:
+
+	     <nested-name>
+	     -> <template-prefix> <template-args>
+	     -> <prefix> <template-unqualified-name> <template-args>
+	     -> <unqualified-name> <template-unqualified-name> <template-args>
+	     -> <source-name> <template-unqualified-name> <template-args>
+	     -> <source-name> <operator-name> <template-args>
+	     -> <source-name> cv <type> <template-args>
+	     -> <source-name> cv <template-param> <template-args>
+
+	     where we need to leave the <template-args> to be processed
+	     by d_prefix (following the <template-prefix>).
+
+	     The <template-template-param> part is a substitution
 	     candidate.  */
-	  if (! d_add_substitution (di, ret))
-	    return NULL;
-	  ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
-			     d_template_args (di));
+	  if (! di->is_conversion)
+	    {
+	      if (! d_add_substitution (di, ret))
+		return NULL;
+	      ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+				 d_template_args (di));
+	    }
+	  else
+	    {
+	      struct demangle_component *args;
+	      struct d_info_checkpoint checkpoint;
+
+	      d_checkpoint (di, &checkpoint);
+	      args = d_template_args (di);
+	      if (d_peek_char (di) == 'I')
+		{
+		  if (! d_add_substitution (di, ret))
+		    return NULL;
+		  ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+				     args);
+		}
+	      else
+		d_backtrack (di, &checkpoint);
+	    }
 	}
       break;
 
@@ -2087,6 +2572,9 @@ cplus_demangle_type (struct d_info *di)
     case 'U':
       d_advance (di, 1);
       ret = d_source_name (di);
+      if (d_peek_char (di) == 'I')
+	ret = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE, ret,
+			   d_template_args (di));
       ret = d_make_comp (di, DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL,
 			 cplus_demangle_type (di), ret);
       break;
@@ -2104,14 +2592,25 @@ cplus_demangle_type (struct d_info *di)
 			     d_expression (di), NULL);
 	  if (ret && d_next_char (di) != 'E')
 	    ret = NULL;
+	  can_subst = 1;
 	  break;
 	  
 	case 'p':
 	  /* Pack expansion.  */
 	  ret = d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
 			     cplus_demangle_type (di), NULL);
+	  can_subst = 1;
 	  break;
-	  
+
+	case 'a':
+	  /* auto */
+	  ret = d_make_name (di, "auto", 4);
+	  break;
+	case 'c':
+	  /* decltype(auto) */
+	  ret = d_make_name (di, "decltype(auto)", 14);
+	  break;
+
 	case 'f':
 	  /* 32-bit decimal floating point */
 	  ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[26]);
@@ -2151,11 +2650,24 @@ cplus_demangle_type (struct d_info *di)
 	    /* For demangling we don't care about the bits.  */
 	    d_number (di);
 	  ret->u.s_fixed.length = cplus_demangle_type (di);
+	  if (ret->u.s_fixed.length == NULL)
+	    return NULL;
 	  d_number (di);
 	  peek = d_next_char (di);
 	  ret->u.s_fixed.sat = (peek == 's');
 	  break;
 
+	case 'v':
+	  ret = d_vector_type (di);
+	  can_subst = 1;
+	  break;
+
+        case 'n':
+          /* decltype(nullptr) */
+	  ret = d_make_builtin_type (di, &cplus_demangle_builtin_types[32]);
+	  di->expansion += ret->u.s_builtin.type->len;
+	  break;
+
 	default:
 	  return NULL;
 	}
@@ -2174,18 +2686,21 @@ cplus_demangle_type (struct d_info *di)
   return ret;
 }
 
-/* <CV-qualifiers> ::= [r] [V] [K]  */
+/* <CV-qualifiers> ::= [r] [V] [K] [Dx] */
 
 static struct demangle_component **
 d_cv_qualifiers (struct d_info *di,
                  struct demangle_component **pret, int member_fn)
 {
+  struct demangle_component **pstart;
   char peek;
 
+  pstart = pret;
   peek = d_peek_char (di);
-  while (peek == 'r' || peek == 'V' || peek == 'K')
+  while (next_is_type_qual (di))
     {
       enum demangle_component_type t;
+      struct demangle_component *right = NULL;
 
       d_advance (di, 1);
       if (peek == 'r')
@@ -2202,15 +2717,50 @@ d_cv_qualifiers (struct d_info *di,
 	       : DEMANGLE_COMPONENT_VOLATILE);
 	  di->expansion += sizeof "volatile";
 	}
-      else
+      else if (peek == 'K')
 	{
 	  t = (member_fn
 	       ? DEMANGLE_COMPONENT_CONST_THIS
 	       : DEMANGLE_COMPONENT_CONST);
 	  di->expansion += sizeof "const";
 	}
+      else
+	{
+	  peek = d_next_char (di);
+	  if (peek == 'x')
+	    {
+	      t = DEMANGLE_COMPONENT_TRANSACTION_SAFE;
+	      di->expansion += sizeof "transaction_safe";
+	    }
+	  else if (peek == 'o'
+		   || peek == 'O')
+	    {
+	      t = DEMANGLE_COMPONENT_NOEXCEPT;
+	      di->expansion += sizeof "noexcept";
+	      if (peek == 'O')
+		{
+		  right = d_expression (di);
+		  if (right == NULL)
+		    return NULL;
+		  if (! d_check_char (di, 'E'))
+		    return NULL;
+		}
+	    }
+	  else if (peek == 'w')
+	    {
+	      t = DEMANGLE_COMPONENT_THROW_SPEC;
+	      di->expansion += sizeof "throw";
+	      right = d_parmlist (di);
+	      if (right == NULL)
+		return NULL;
+	      if (! d_check_char (di, 'E'))
+		return NULL;
+	    }
+	  else
+	    return NULL;
+	}
 
-      *pret = d_make_comp (di, t, NULL, NULL);
+      *pret = d_make_comp (di, t, NULL, right);
       if (*pret == NULL)
 	return NULL;
       pret = &d_left (*pret);
@@ -2218,18 +2768,71 @@ d_cv_qualifiers (struct d_info *di,
       peek = d_peek_char (di);
     }
 
+  if (!member_fn && peek == 'F')
+    {
+      while (pstart != pret)
+	{
+	  switch ((*pstart)->type)
+	    {
+	    case DEMANGLE_COMPONENT_RESTRICT:
+	      (*pstart)->type = DEMANGLE_COMPONENT_RESTRICT_THIS;
+	      break;
+	    case DEMANGLE_COMPONENT_VOLATILE:
+	      (*pstart)->type = DEMANGLE_COMPONENT_VOLATILE_THIS;
+	      break;
+	    case DEMANGLE_COMPONENT_CONST:
+	      (*pstart)->type = DEMANGLE_COMPONENT_CONST_THIS;
+	      break;
+	    default:
+	      break;
+	    }
+	  pstart = &d_left (*pstart);
+	}
+    }
+
   return pret;
 }
 
-/* <function-type> ::= F [Y] <bare-function-type> E  */
+/* <ref-qualifier> ::= R
+                   ::= O */
 
 static struct demangle_component *
-d_function_type (struct d_info *di)
+d_ref_qualifier (struct d_info *di, struct demangle_component *sub)
 {
-  struct demangle_component *ret;
+  struct demangle_component *ret = sub;
+  char peek;
 
-  if (! d_check_char (di, 'F'))
-    return NULL;
+  peek = d_peek_char (di);
+  if (peek == 'R' || peek == 'O')
+    {
+      enum demangle_component_type t;
+      if (peek == 'R')
+	{
+	  t = DEMANGLE_COMPONENT_REFERENCE_THIS;
+	  di->expansion += sizeof "&";
+	}
+      else
+	{
+	  t = DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS;
+	  di->expansion += sizeof "&&";
+	}
+      d_advance (di, 1);
+
+      ret = d_make_comp (di, t, ret, NULL);
+    }
+
+  return ret;
+}
+
+/* <function-type> ::= F [Y] <bare-function-type> [<ref-qualifier>] [T] E  */
+
+static struct demangle_component *
+d_function_type (struct d_info *di)
+{
+  struct demangle_component *ret;
+
+  if (! d_check_char (di, 'F'))
+    return NULL;
   if (d_peek_char (di) == 'Y')
     {
       /* Function has C linkage.  We don't print this information.
@@ -2237,55 +2840,41 @@ d_function_type (struct d_info *di)
       d_advance (di, 1);
     }
   ret = d_bare_function_type (di, 1);
+  ret = d_ref_qualifier (di, ret);
+
   if (! d_check_char (di, 'E'))
     return NULL;
   return ret;
 }
 
-/* <bare-function-type> ::= [J]<type>+  */
+/* <type>+ */
 
 static struct demangle_component *
-d_bare_function_type (struct d_info *di, int has_return_type)
+d_parmlist (struct d_info *di)
 {
-  struct demangle_component *return_type;
   struct demangle_component *tl;
   struct demangle_component **ptl;
-  char peek;
-
-  /* Detect special qualifier indicating that the first argument
-     is the return type.  */
-  peek = d_peek_char (di);
-  if (peek == 'J')
-    {
-      d_advance (di, 1);
-      has_return_type = 1;
-    }
 
-  return_type = NULL;
   tl = NULL;
   ptl = &tl;
   while (1)
     {
       struct demangle_component *type;
 
-      peek = d_peek_char (di);
-      if (peek == '\0' || peek == 'E')
+      char peek = d_peek_char (di);
+      if (peek == '\0' || peek == 'E' || peek == '.')
+	break;
+      if ((peek == 'R' || peek == 'O')
+	  && d_peek_next_char (di) == 'E')
+	/* Function ref-qualifier, not a ref prefix for a parameter type.  */
 	break;
       type = cplus_demangle_type (di);
       if (type == NULL)
 	return NULL;
-      if (has_return_type)
-	{
-	  return_type = type;
-	  has_return_type = 0;
-	}
-      else
-	{
-	  *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
-	  if (*ptl == NULL)
-	    return NULL;
-	  ptl = &d_right (*ptl);
-	}
+      *ptl = d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, type, NULL);
+      if (*ptl == NULL)
+	return NULL;
+      ptl = &d_right (*ptl);
     }
 
   /* There should be at least one parameter type besides the optional
@@ -2300,10 +2889,45 @@ d_bare_function_type (struct d_info *di, int has_return_type)
       && d_left (tl)->u.s_builtin.type->print == D_PRINT_VOID)
     {
       di->expansion -= d_left (tl)->u.s_builtin.type->len;
-      tl = NULL;
+      d_left (tl) = NULL;
     }
 
-  return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE, return_type, tl);
+  return tl;
+}
+
+/* <bare-function-type> ::= [J]<type>+  */
+
+static struct demangle_component *
+d_bare_function_type (struct d_info *di, int has_return_type)
+{
+  struct demangle_component *return_type;
+  struct demangle_component *tl;
+  char peek;
+
+  /* Detect special qualifier indicating that the first argument
+     is the return type.  */
+  peek = d_peek_char (di);
+  if (peek == 'J')
+    {
+      d_advance (di, 1);
+      has_return_type = 1;
+    }
+
+  if (has_return_type)
+    {
+      return_type = cplus_demangle_type (di);
+      if (return_type == NULL)
+	return NULL;
+    }
+  else
+    return_type = NULL;
+
+  tl = d_parmlist (di);
+  if (tl == NULL)
+    return NULL;
+
+  return d_make_comp (di, DEMANGLE_COMPONENT_FUNCTION_TYPE,
+		      return_type, tl);
 }
 
 /* <class-enum-type> ::= <name>  */
@@ -2359,6 +2983,34 @@ d_array_type (struct d_info *di)
 		      cplus_demangle_type (di));
 }
 
+/* <vector-type> ::= Dv <number> _ <type>
+                 ::= Dv _ <expression> _ <type> */
+
+static struct demangle_component *
+d_vector_type (struct d_info *di)
+{
+  char peek;
+  struct demangle_component *dim;
+
+  peek = d_peek_char (di);
+  if (peek == '_')
+    {
+      d_advance (di, 1);
+      dim = d_expression (di);
+    }
+  else
+    dim = d_number_component (di);
+
+  if (dim == NULL)
+    return NULL;
+
+  if (! d_check_char (di, '_'))
+    return NULL;
+
+  return d_make_comp (di, DEMANGLE_COMPONENT_VECTOR_TYPE, dim,
+		      cplus_demangle_type (di));
+}
+
 /* <pointer-to-member-type> ::= M <(class) type> <(member) type>  */
 
 static struct demangle_component *
@@ -2366,45 +3018,54 @@ d_pointer_to_member_type (struct d_info *di)
 {
   struct demangle_component *cl;
   struct demangle_component *mem;
-  struct demangle_component **pmem;
 
   if (! d_check_char (di, 'M'))
     return NULL;
 
   cl = cplus_demangle_type (di);
-
-  /* The ABI specifies that any type can be a substitution source, and
-     that M is followed by two types, and that when a CV-qualified
-     type is seen both the base type and the CV-qualified types are
-     substitution sources.  The ABI also specifies that for a pointer
-     to a CV-qualified member function, the qualifiers are attached to
-     the second type.  Given the grammar, a plain reading of the ABI
-     suggests that both the CV-qualified member function and the
-     non-qualified member function are substitution sources.  However,
-     g++ does not work that way.  g++ treats only the CV-qualified
-     member function as a substitution source.  FIXME.  So to work
-     with g++, we need to pull off the CV-qualifiers here, in order to
-     avoid calling add_substitution() in cplus_demangle_type().  But
-     for a CV-qualified member which is not a function, g++ does
-     follow the ABI, so we need to handle that case here by calling
-     d_add_substitution ourselves.  */
-
-  pmem = d_cv_qualifiers (di, &mem, 1);
-  if (pmem == NULL)
-    return NULL;
-  *pmem = cplus_demangle_type (di);
-  if (*pmem == NULL)
+  if (cl == NULL)
     return NULL;
 
-  if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
-    {
-      if (! d_add_substitution (di, mem))
-	return NULL;
-    }
+  /* The ABI says, "The type of a non-static member function is considered
+     to be different, for the purposes of substitution, from the type of a
+     namespace-scope or static member function whose type appears
+     similar. The types of two non-static member functions are considered
+     to be different, for the purposes of substitution, if the functions
+     are members of different classes. In other words, for the purposes of
+     substitution, the class of which the function is a member is
+     considered part of the type of function."
+
+     For a pointer to member function, this call to cplus_demangle_type
+     will end up adding a (possibly qualified) non-member function type to
+     the substitution table, which is not correct; however, the member
+     function type will never be used in a substitution, so putting the
+     wrong type in the substitution table is harmless.  */
+
+  mem = cplus_demangle_type (di);
+  if (mem == NULL)
+    return NULL;
 
   return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
 }
 
+/* <non-negative number> _ */
+
+static int
+d_compact_number (struct d_info *di)
+{
+  int num;
+  if (d_peek_char (di) == '_')
+    num = 0;
+  else if (d_peek_char (di) == 'n')
+    return -1;
+  else
+    num = d_number (di) + 1;
+
+  if (num < 0 || ! d_check_char (di, '_'))
+    return -1;
+  return num;
+}
+
 /* <template-param> ::= T_
                     ::= T <(parameter-2 non-negative) number> _
 */
@@ -2412,26 +3073,15 @@ d_pointer_to_member_type (struct d_info *di)
 static struct demangle_component *
 d_template_param (struct d_info *di)
 {
-  long param;
+  int param;
 
   if (! d_check_char (di, 'T'))
     return NULL;
 
-  if (d_peek_char (di) == '_')
-    param = 0;
-  else
-    {
-      param = d_number (di);
-      if (param < 0)
-	return NULL;
-      param += 1;
-    }
-
-  if (! d_check_char (di, '_'))
+  param = d_compact_number (di);
+  if (param < 0)
     return NULL;
 
-  ++di->did_subs;
-
   return d_make_template_param (di, param);
 }
 
@@ -2440,6 +3090,19 @@ d_template_param (struct d_info *di)
 static struct demangle_component *
 d_template_args (struct d_info *di)
 {
+  if (d_peek_char (di) != 'I'
+      && d_peek_char (di) != 'J')
+    return NULL;
+  d_advance (di, 1);
+
+  return d_template_args_1 (di);
+}
+
+/* <template-arg>* E  */
+
+static struct demangle_component *
+d_template_args_1 (struct d_info *di)
+{
   struct demangle_component *hold_last_name;
   struct demangle_component *al;
   struct demangle_component **pal;
@@ -2449,9 +3112,6 @@ d_template_args (struct d_info *di)
      constructor or destructor.  */
   hold_last_name = di->last_name;
 
-  if (! d_check_char (di, 'I'))
-    return NULL;
-
   if (d_peek_char (di) == 'E')
     {
       /* An argument pack can be empty.  */
@@ -2509,6 +3169,7 @@ d_template_arg (struct d_info *di)
       return d_expr_primary (di);
 
     case 'I':
+    case 'J':
       /* An argument pack.  */
       return d_template_args (di);
 
@@ -2517,15 +3178,16 @@ d_template_arg (struct d_info *di)
     }
 }
 
-/* Subroutine of <expression> ::= cl <expression>+ E */
+/* Parse a sequence of expressions until we hit the terminator
+   character.  */
 
 static struct demangle_component *
-d_exprlist (struct d_info *di)
+d_exprlist (struct d_info *di, char terminator)
 {
   struct demangle_component *list = NULL;
   struct demangle_component **p = &list;
 
-  if (d_peek_char (di) == 'E')
+  if (d_peek_char (di) == terminator)
     {
       d_advance (di, 1);
       return d_make_comp (di, DEMANGLE_COMPONENT_ARGLIST, NULL, NULL);
@@ -2542,7 +3204,7 @@ d_exprlist (struct d_info *di)
 	return NULL;
       p = &d_right (*p);
 
-      if (d_peek_char (di) == 'E')
+      if (d_peek_char (di) == terminator)
 	{
 	  d_advance (di, 1);
 	  break;
@@ -2552,6 +3214,18 @@ d_exprlist (struct d_info *di)
   return list;
 }
 
+/* Returns nonzero iff OP is an operator for a C++ cast: const_cast,
+   dynamic_cast, static_cast or reinterpret_cast.  */
+
+static int
+op_is_new_cast (struct demangle_component *op)
+{
+  const char *code = op->u.s_operator.op->code;
+  return (code[1] == 'c'
+	  && (code[0] == 's' || code[0] == 'd'
+	      || code[0] == 'c' || code[0] == 'r'));
+}
+
 /* <expression> ::= <(unary) operator-name> <expression>
                 ::= <(binary) operator-name> <expression> <expression>
                 ::= <(trinary) operator-name> <expression> <expression> <expression>
@@ -2563,8 +3237,8 @@ d_exprlist (struct d_info *di)
                 ::= <expr-primary>
 */
 
-static struct demangle_component *
-d_expression (struct d_info *di)
+static inline struct demangle_component *
+d_expression_1 (struct d_info *di)
 {
   char peek;
 
@@ -2592,33 +3266,40 @@ d_expression (struct d_info *di)
     {
       d_advance (di, 2);
       return d_make_comp (di, DEMANGLE_COMPONENT_PACK_EXPANSION,
-			  d_expression (di), NULL);
+			  d_expression_1 (di), NULL);
     }
   else if (peek == 'f' && d_peek_next_char (di) == 'p')
     {
       /* Function parameter used in a late-specified return type.  */
       int index;
       d_advance (di, 2);
-      if (d_peek_char (di) == '_')
-	index = 1;
+      if (d_peek_char (di) == 'T')
+	{
+	  /* 'this' parameter.  */
+	  d_advance (di, 1);
+	  index = 0;
+	}
       else
 	{
-	  index = d_number (di);
-	  if (index < 0)
+	  index = d_compact_number (di);
+	  if (index == INT_MAX || index == -1)
 	    return NULL;
-	  index += 2;
+	  index++;
 	}
-
-      if (! d_check_char (di, '_'))
-	return NULL;
-
       return d_make_function_param (di, index);
     }
-  else if (IS_DIGIT (peek))
+  else if (IS_DIGIT (peek)
+	   || (peek == 'o' && d_peek_next_char (di) == 'n'))
     {
       /* We can get an unqualified name as an expression in the case of
-         a dependent member access, i.e. decltype(T().i).  */
-      struct demangle_component *name = d_unqualified_name (di);
+         a dependent function call, i.e. decltype(f(t)).  */
+      struct demangle_component *name;
+
+      if (peek == 'o')
+	/* operator-function-id, i.e. operator+(t).  */
+	d_advance (di, 2);
+
+      name = d_unqualified_name (di);
       if (name == NULL)
 	return NULL;
       if (d_peek_char (di) == 'I')
@@ -2627,9 +3308,23 @@ d_expression (struct d_info *di)
       else
 	return name;
     }
+  else if ((peek == 'i' || peek == 't')
+	   && d_peek_next_char (di) == 'l')
+    {
+      /* Brace-enclosed initializer list, untyped or typed.  */
+      struct demangle_component *type = NULL;
+      if (peek == 't')
+	type = cplus_demangle_type (di);
+      if (!d_peek_next_char (di))
+	return NULL;
+      d_advance (di, 2);
+      return d_make_comp (di, DEMANGLE_COMPONENT_INITIALIZER_LIST,
+			  type, d_exprlist (di, 'E'));
+    }
   else
     {
       struct demangle_component *op;
+      const char *code = NULL;
       int args;
 
       op = d_operator_name (di);
@@ -2637,12 +3332,13 @@ d_expression (struct d_info *di)
 	return NULL;
 
       if (op->type == DEMANGLE_COMPONENT_OPERATOR)
-	di->expansion += op->u.s_operator.op->len - 2;
-
-      if (op->type == DEMANGLE_COMPONENT_OPERATOR
-	  && strcmp (op->u.s_operator.op->code, "st") == 0)
-	return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
-			    cplus_demangle_type (di));
+	{
+	  code = op->u.s_operator.op->code;
+	  di->expansion += op->u.s_operator.op->len - 2;
+	  if (strcmp (code, "st") == 0)
+	    return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				cplus_demangle_type (di));
+	}
 
       switch (op->type)
 	{
@@ -2661,27 +3357,62 @@ d_expression (struct d_info *di)
 
       switch (args)
 	{
+	case 0:
+	  return d_make_comp (di, DEMANGLE_COMPONENT_NULLARY, op, NULL);
+
 	case 1:
 	  {
 	    struct demangle_component *operand;
+	    int suffix = 0;
+
+	    if (code && (code[0] == 'p' || code[0] == 'm')
+		&& code[1] == code[0])
+	      /* pp_ and mm_ are the prefix variants.  */
+	      suffix = !d_check_char (di, '_');
+
 	    if (op->type == DEMANGLE_COMPONENT_CAST
 		&& d_check_char (di, '_'))
-	      operand = d_exprlist (di);
+	      operand = d_exprlist (di, 'E');
+	    else if (code && !strcmp (code, "sP"))
+	      operand = d_template_args_1 (di);
 	    else
-	      operand = d_expression (di);
-	    return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
-				operand);
+	      operand = d_expression_1 (di);
+
+	    if (suffix)
+	      /* Indicate the suffix variant for d_print_comp.  */
+	      return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				  d_make_comp (di,
+					       DEMANGLE_COMPONENT_BINARY_ARGS,
+					       operand, operand));
+	    else
+	      return d_make_comp (di, DEMANGLE_COMPONENT_UNARY, op,
+				  operand);
 	  }
 	case 2:
 	  {
 	    struct demangle_component *left;
 	    struct demangle_component *right;
 
-	    left = d_expression (di);
-	    if (!strcmp (op->u.s_operator.op->code, "cl"))
-	      right = d_exprlist (di);
+	    if (code == NULL)
+	      return NULL;
+	    if (op_is_new_cast (op))
+	      left = cplus_demangle_type (di);
+	    else if (code[0] == 'f')
+	      /* fold-expression.  */
+	      left = d_operator_name (di);
+	    else
+	      left = d_expression_1 (di);
+	    if (!strcmp (code, "cl"))
+	      right = d_exprlist (di, 'E');
+	    else if (!strcmp (code, "dt") || !strcmp (code, "pt"))
+	      {
+		right = d_unqualified_name (di);
+		if (d_peek_char (di) == 'I')
+		  right = d_make_comp (di, DEMANGLE_COMPONENT_TEMPLATE,
+				       right, d_template_args (di));
+	      }
 	    else
-	      right = d_expression (di);
+	      right = d_expression_1 (di);
 
 	    return d_make_comp (di, DEMANGLE_COMPONENT_BINARY, op,
 				d_make_comp (di,
@@ -2692,17 +3423,63 @@ d_expression (struct d_info *di)
 	  {
 	    struct demangle_component *first;
 	    struct demangle_component *second;
+	    struct demangle_component *third;
 
-	    first = d_expression (di);
-	    second = d_expression (di);
+	    if (code == NULL)
+	      return NULL;
+	    else if (!strcmp (code, "qu"))
+	      {
+		/* ?: expression.  */
+		first = d_expression_1 (di);
+		second = d_expression_1 (di);
+		third = d_expression_1 (di);
+		if (third == NULL)
+		  return NULL;
+	      }
+	    else if (code[0] == 'f')
+	      {
+		/* fold-expression.  */
+		first = d_operator_name (di);
+		second = d_expression_1 (di);
+		third = d_expression_1 (di);
+		if (third == NULL)
+		  return NULL;
+	      }
+	    else if (code[0] == 'n')
+	      {
+		/* new-expression.  */
+		if (code[1] != 'w' && code[1] != 'a')
+		  return NULL;
+		first = d_exprlist (di, '_');
+		second = cplus_demangle_type (di);
+		if (d_peek_char (di) == 'E')
+		  {
+		    d_advance (di, 1);
+		    third = NULL;
+		  }
+		else if (d_peek_char (di) == 'p'
+			 && d_peek_next_char (di) == 'i')
+		  {
+		    /* Parenthesized initializer.  */
+		    d_advance (di, 2);
+		    third = d_exprlist (di, 'E');
+		  }
+		else if (d_peek_char (di) == 'i'
+			 && d_peek_next_char (di) == 'l')
+		  /* initializer-list.  */
+		  third = d_expression_1 (di);
+		else
+		  return NULL;
+	      }
+	    else
+	      return NULL;
 	    return d_make_comp (di, DEMANGLE_COMPONENT_TRINARY, op,
 				d_make_comp (di,
 					     DEMANGLE_COMPONENT_TRINARY_ARG1,
 					     first,
 					     d_make_comp (di,
 							  DEMANGLE_COMPONENT_TRINARY_ARG2,
-							  second,
-							  d_expression (di))));
+							  second, third)));
 	  }
 	default:
 	  return NULL;
@@ -2710,6 +3487,18 @@ d_expression (struct d_info *di)
     }
 }
 
+static struct demangle_component *
+d_expression (struct d_info *di)
+{
+  struct demangle_component *ret;
+  int was_expression = di->is_expression;
+
+  di->is_expression = 1;
+  ret = d_expression_1 (di);
+  di->is_expression = was_expression;
+  return ret;
+}
+
 /* <expr-primary> ::= L <type> <(value) number> E
                   ::= L <type> <(value) float> E
                   ::= L <mangled-name> E
@@ -2775,6 +3564,7 @@ d_expr_primary (struct d_info *di)
 
 /* <local-name> ::= Z <(function) encoding> E <(entity) name> [<discriminator>]
                 ::= Z <(function) encoding> E s [<discriminator>]
+                ::= Z <(function) encoding> E d [<parameter> number>] _ <entity name>
 */
 
 static struct demangle_component *
@@ -2802,15 +3592,40 @@ d_local_name (struct d_info *di)
   else
     {
       struct demangle_component *name;
+      int num = -1;
+
+      if (d_peek_char (di) == 'd')
+	{
+	  /* Default argument scope: d <number> _.  */
+	  d_advance (di, 1);
+	  num = d_compact_number (di);
+	  if (num < 0)
+	    return NULL;
+	}
 
       name = d_name (di);
-      if (! d_discriminator (di))
-	return NULL;
+      if (name)
+	switch (name->type)
+	  {
+	    /* Lambdas and unnamed types have internal discriminators.  */
+	  case DEMANGLE_COMPONENT_LAMBDA:
+	  case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+	    break;
+	  default:
+	    if (! d_discriminator (di))
+	      return NULL;
+	  }
+      if (num >= 0)
+	name = d_make_default_arg (di, num, name);
       return d_make_comp (di, DEMANGLE_COMPONENT_LOCAL_NAME, function, name);
     }
 }
 
-/* <discriminator> ::= _ <(non-negative) number>
+/* <discriminator> ::= _ <number>    # when number < 10
+                   ::= __ <number> _ # when number >= 10
+
+   <discriminator> ::= _ <number>    # when number >=10
+   is also accepted to support gcc versions that wrongly mangled that way.
 
    We demangle the discriminator, but we don't print it out.  FIXME:
    We should print it out in verbose mode.  */
@@ -2818,17 +3633,127 @@ d_local_name (struct d_info *di)
 static int
 d_discriminator (struct d_info *di)
 {
-  long discrim;
+  int discrim, num_underscores = 1;
 
   if (d_peek_char (di) != '_')
     return 1;
   d_advance (di, 1);
+  if (d_peek_char (di) == '_')
+    {
+      ++num_underscores;
+      d_advance (di, 1);
+    }
+
   discrim = d_number (di);
   if (discrim < 0)
     return 0;
+  if (num_underscores > 1 && discrim >= 10)
+    {
+      if (d_peek_char (di) == '_')
+	d_advance (di, 1);
+      else
+	return 0;
+    }
+
   return 1;
 }
 
+/* <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _ */
+
+static struct demangle_component *
+d_lambda (struct d_info *di)
+{
+  struct demangle_component *tl;
+  struct demangle_component *ret;
+  int num;
+
+  if (! d_check_char (di, 'U'))
+    return NULL;
+  if (! d_check_char (di, 'l'))
+    return NULL;
+
+  tl = d_parmlist (di);
+  if (tl == NULL)
+    return NULL;
+
+  if (! d_check_char (di, 'E'))
+    return NULL;
+
+  num = d_compact_number (di);
+  if (num < 0)
+    return NULL;
+
+  ret = d_make_empty (di);
+  if (ret)
+    {
+      ret->type = DEMANGLE_COMPONENT_LAMBDA;
+      ret->u.s_unary_num.sub = tl;
+      ret->u.s_unary_num.num = num;
+    }
+
+  if (! d_add_substitution (di, ret))
+    return NULL;
+
+  return ret;
+}
+
+/* <unnamed-type-name> ::= Ut [ <nonnegative number> ] _ */
+
+static struct demangle_component *
+d_unnamed_type (struct d_info *di)
+{
+  struct demangle_component *ret;
+  int num;
+
+  if (! d_check_char (di, 'U'))
+    return NULL;
+  if (! d_check_char (di, 't'))
+    return NULL;
+
+  num = d_compact_number (di);
+  if (num < 0)
+    return NULL;
+
+  ret = d_make_empty (di);
+  if (ret)
+    {
+      ret->type = DEMANGLE_COMPONENT_UNNAMED_TYPE;
+      ret->u.s_number.number = num;
+    }
+
+  if (! d_add_substitution (di, ret))
+    return NULL;
+
+  return ret;
+}
+
+/* <clone-suffix> ::= [ . <clone-type-identifier> ] [ . <nonnegative number> ]*
+*/
+
+static struct demangle_component *
+d_clone_suffix (struct d_info *di, struct demangle_component *encoding)
+{
+  const char *suffix = d_str (di);
+  const char *pend = suffix;
+  struct demangle_component *n;
+
+  if (*pend == '.' && (IS_LOWER (pend[1]) || pend[1] == '_'))
+    {
+      pend += 2;
+      while (IS_LOWER (*pend) || *pend == '_')
+	++pend;
+    }
+  while (*pend == '.' && IS_DIGIT (pend[1]))
+    {
+      pend += 2;
+      while (IS_DIGIT (*pend))
+	++pend;
+    }
+  d_advance (di, pend - suffix);
+  n = d_make_name (di, suffix, pend - suffix);
+  return d_make_comp (di, DEMANGLE_COMPONENT_CLONE, encoding, n);
+}
+
 /* Add a new substitution.  */
 
 static int
@@ -2926,8 +3851,6 @@ d_substitution (struct d_info *di, int prefix)
       if (id >= (unsigned int) di->next_sub)
 	return NULL;
 
-      ++di->did_subs;
-
       return di->subs[id];
     }
   else
@@ -2954,6 +3877,7 @@ d_substitution (struct d_info *di, int prefix)
 	    {
 	      const char *s;
 	      int len;
+	      struct demangle_component *dc;
 
 	      if (p->set_last_name != NULL)
 		di->last_name = d_make_sub (di, p->set_last_name,
@@ -2969,7 +3893,16 @@ d_substitution (struct d_info *di, int prefix)
 		  len = p->simple_len;
 		}
 	      di->expansion += len;
-	      return d_make_sub (di, s, len);
+	      dc = d_make_sub (di, s, len);
+	      if (d_peek_char (di) == 'B')
+		{
+		  /* If there are ABI tags on the abbreviation, it becomes
+		     a substitution candidate.  */
+		  dc = d_abi_tags (di, dc);
+		  if (! d_add_substitution (di, dc))
+		    return NULL;
+		}
+	      return dc;
 	    }
 	}
 
@@ -2977,6 +3910,24 @@ d_substitution (struct d_info *di, int prefix)
     }
 }
 
+static void
+d_checkpoint (struct d_info *di, struct d_info_checkpoint *checkpoint)
+{
+  checkpoint->n = di->n;
+  checkpoint->next_comp = di->next_comp;
+  checkpoint->next_sub = di->next_sub;
+  checkpoint->expansion = di->expansion;
+}
+
+static void
+d_backtrack (struct d_info *di, struct d_info_checkpoint *checkpoint)
+{
+  di->n = checkpoint->n;
+  di->next_comp = checkpoint->next_comp;
+  di->next_sub = checkpoint->next_sub;
+  di->expansion = checkpoint->expansion;
+}
+
 /* Initialize a growable string.  */
 
 static void
@@ -3053,22 +4004,179 @@ d_growable_string_callback_adapter (const char *s, size_t l, void *opaque)
   d_growable_string_append_buffer (dgs, s, l);
 }
 
+/* Walk the tree, counting the number of templates encountered, and
+   the number of times a scope might be saved.  These counts will be
+   used to allocate data structures for d_print_comp, so the logic
+   here must mirror the logic d_print_comp will use.  It is not
+   important that the resulting numbers are exact, so long as they
+   are larger than the actual numbers encountered.  */
+
+static void
+d_count_templates_scopes (int *num_templates, int *num_scopes,
+			  const struct demangle_component *dc)
+{
+  if (dc == NULL)
+    return;
+
+  switch (dc->type)
+    {
+    case DEMANGLE_COMPONENT_NAME:
+    case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+    case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+    case DEMANGLE_COMPONENT_SUB_STD:
+    case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+    case DEMANGLE_COMPONENT_OPERATOR:
+    case DEMANGLE_COMPONENT_CHARACTER:
+    case DEMANGLE_COMPONENT_NUMBER:
+    case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+      break;
+
+    case DEMANGLE_COMPONENT_TEMPLATE:
+      (*num_templates)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_REFERENCE:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+      if (d_left (dc)->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+	(*num_scopes)++;
+      goto recurse_left_right;
+
+    case DEMANGLE_COMPONENT_QUAL_NAME:
+    case DEMANGLE_COMPONENT_LOCAL_NAME:
+    case DEMANGLE_COMPONENT_TYPED_NAME:
+    case DEMANGLE_COMPONENT_VTABLE:
+    case DEMANGLE_COMPONENT_VTT:
+    case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
+    case DEMANGLE_COMPONENT_TYPEINFO:
+    case DEMANGLE_COMPONENT_TYPEINFO_NAME:
+    case DEMANGLE_COMPONENT_TYPEINFO_FN:
+    case DEMANGLE_COMPONENT_THUNK:
+    case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
+    case DEMANGLE_COMPONENT_COVARIANT_THUNK:
+    case DEMANGLE_COMPONENT_JAVA_CLASS:
+    case DEMANGLE_COMPONENT_GUARD:
+    case DEMANGLE_COMPONENT_TLS_INIT:
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
+    case DEMANGLE_COMPONENT_REFTEMP:
+    case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
+    case DEMANGLE_COMPONENT_RESTRICT:
+    case DEMANGLE_COMPONENT_VOLATILE:
+    case DEMANGLE_COMPONENT_CONST:
+    case DEMANGLE_COMPONENT_RESTRICT_THIS:
+    case DEMANGLE_COMPONENT_VOLATILE_THIS:
+    case DEMANGLE_COMPONENT_CONST_THIS:
+    case DEMANGLE_COMPONENT_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+    case DEMANGLE_COMPONENT_NOEXCEPT:
+    case DEMANGLE_COMPONENT_THROW_SPEC:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
+    case DEMANGLE_COMPONENT_POINTER:
+    case DEMANGLE_COMPONENT_COMPLEX:
+    case DEMANGLE_COMPONENT_IMAGINARY:
+    case DEMANGLE_COMPONENT_VENDOR_TYPE:
+    case DEMANGLE_COMPONENT_FUNCTION_TYPE:
+    case DEMANGLE_COMPONENT_ARRAY_TYPE:
+    case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+    case DEMANGLE_COMPONENT_ARGLIST:
+    case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
+    case DEMANGLE_COMPONENT_NULLARY:
+    case DEMANGLE_COMPONENT_UNARY:
+    case DEMANGLE_COMPONENT_BINARY:
+    case DEMANGLE_COMPONENT_BINARY_ARGS:
+    case DEMANGLE_COMPONENT_TRINARY:
+    case DEMANGLE_COMPONENT_TRINARY_ARG1:
+    case DEMANGLE_COMPONENT_TRINARY_ARG2:
+    case DEMANGLE_COMPONENT_LITERAL:
+    case DEMANGLE_COMPONENT_LITERAL_NEG:
+    case DEMANGLE_COMPONENT_JAVA_RESOURCE:
+    case DEMANGLE_COMPONENT_COMPOUND_NAME:
+    case DEMANGLE_COMPONENT_DECLTYPE:
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+    case DEMANGLE_COMPONENT_PACK_EXPANSION:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+    case DEMANGLE_COMPONENT_CLONE:
+    recurse_left_right:
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_left (dc));
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_right (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_CTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_ctor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_DTOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_dtor.name);
+      break;
+
+    case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_extended_operator.name);
+      break;
+
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
+      d_count_templates_scopes (num_templates, num_scopes,
+                                dc->u.s_fixed.length);
+      break;
+
+    case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
+    case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
+      d_count_templates_scopes (num_templates, num_scopes,
+				d_left (dc));
+      break;
+
+    case DEMANGLE_COMPONENT_LAMBDA:
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+      d_count_templates_scopes (num_templates, num_scopes,
+				dc->u.s_unary_num.sub);
+      break;
+    }
+}
+
 /* Initialize a print information structure.  */
 
 static void
-d_print_init (struct d_print_info *dpi, int options,
-              demangle_callbackref callback, void *opaque)
+d_print_init (struct d_print_info *dpi, demangle_callbackref callback,
+	      void *opaque, const struct demangle_component *dc)
 {
-  dpi->options = options;
   dpi->len = 0;
   dpi->last_char = '\0';
   dpi->templates = NULL;
   dpi->modifiers = NULL;
+  dpi->pack_index = 0;
+  dpi->flush_count = 0;
 
   dpi->callback = callback;
   dpi->opaque = opaque;
 
   dpi->demangle_failure = 0;
+  dpi->recursion = 0;
+  dpi->is_lambda_arg = 0;
+
+  dpi->component_stack = NULL;
+
+  dpi->saved_scopes = NULL;
+  dpi->next_saved_scope = 0;
+  dpi->num_saved_scopes = 0;
+
+  dpi->copy_templates = NULL;
+  dpi->next_copy_template = 0;
+  dpi->num_copy_templates = 0;
+
+  d_count_templates_scopes (&dpi->num_copy_templates,
+			    &dpi->num_saved_scopes, dc);
+  dpi->num_copy_templates *= dpi->num_saved_scopes;
+
+  dpi->current_template = NULL;
 }
 
 /* Indicate that an error occurred during printing, and test for error.  */
@@ -3093,6 +4201,7 @@ d_print_flush (struct d_print_info *dpi)
   dpi->buf[dpi->len] = '\0';
   dpi->callback (dpi->buf, dpi->len, dpi->opaque);
   dpi->len = 0;
+  dpi->flush_count++;
 }
 
 /* Append characters and buffers for printing.  */
@@ -3122,6 +4231,14 @@ d_append_string (struct d_print_info *dpi, const char *s)
   d_append_buffer (dpi, s, strlen (s));
 }
 
+static inline void
+d_append_num (struct d_print_info *dpi, int l)
+{
+  char buf[25];
+  sprintf (buf,"%d", l);
+  d_append_string (dpi, buf);
+}
+
 static inline char
 d_last_char (struct d_print_info *dpi)
 {
@@ -3140,14 +4257,33 @@ d_last_char (struct d_print_info *dpi)
 CP_STATIC_IF_GLIBCPP_V3
 int
 cplus_demangle_print_callback (int options,
-                               const struct demangle_component *dc,
+                               struct demangle_component *dc,
                                demangle_callbackref callback, void *opaque)
 {
   struct d_print_info dpi;
 
-  d_print_init (&dpi, options, callback, opaque);
+  d_print_init (&dpi, callback, opaque, dc);
 
-  d_print_comp (&dpi, dc);
+  {
+#ifdef CP_DYNAMIC_ARRAYS
+    /* Avoid zero-length VLAs, which are prohibited by the C99 standard
+       and flagged as errors by Address Sanitizer.  */
+    __extension__ struct d_saved_scope scopes[(dpi.num_saved_scopes > 0)
+                                              ? dpi.num_saved_scopes : 1];
+    __extension__ struct d_print_template temps[(dpi.num_copy_templates > 0)
+                                                ? dpi.num_copy_templates : 1];
+
+    dpi.saved_scopes = scopes;
+    dpi.copy_templates = temps;
+#else
+    dpi.saved_scopes = alloca (dpi.num_saved_scopes
+			       * sizeof (*dpi.saved_scopes));
+    dpi.copy_templates = alloca (dpi.num_copy_templates
+				 * sizeof (*dpi.copy_templates));
+#endif
+
+    d_print_comp (&dpi, options, dc);
+  }
 
   d_print_flush (&dpi);
 
@@ -3164,7 +4300,7 @@ cplus_demangle_print_callback (int options,
 
 CP_STATIC_IF_GLIBCPP_V3
 char *
-cplus_demangle_print (int options, const struct demangle_component *dc,
+cplus_demangle_print (int options, struct demangle_component *dc,
                       int estimate, size_t *palc)
 {
   struct d_growable_string dgs;
@@ -3185,13 +4321,17 @@ cplus_demangle_print (int options, const struct demangle_component *dc,
 }
 
 /* Returns the I'th element of the template arglist ARGS, or NULL on
-   failure.  */
+   failure.  If I is negative, return the entire arglist.  */
 
 static struct demangle_component *
 d_index_template_argument (struct demangle_component *args, int i)
 {
   struct demangle_component *a;
 
+  if (i < 0)
+    /* Print the whole argument pack.  */
+    return args;
+
   for (a = args;
        a != NULL;
        a = d_right (a))
@@ -3247,12 +4387,18 @@ d_find_pack (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_PACK_EXPANSION:
       return NULL;
       
+    case DEMANGLE_COMPONENT_LAMBDA:
     case DEMANGLE_COMPONENT_NAME:
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
     case DEMANGLE_COMPONENT_OPERATOR:
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
     case DEMANGLE_COMPONENT_SUB_STD:
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
+    case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
+    case DEMANGLE_COMPONENT_DEFAULT_ARG:
+    case DEMANGLE_COMPONENT_NUMBER:
       return NULL;
 
     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
@@ -3270,45 +4416,202 @@ d_find_pack (struct d_print_info *dpi,
     }
 }
 
-/* Returns the length of the template argument pack DC.  */
+/* Returns the length of the template argument pack DC.  */
+
+static int
+d_pack_length (const struct demangle_component *dc)
+{
+  int count = 0;
+  while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST
+	 && d_left (dc) != NULL)
+    {
+      ++count;
+      dc = d_right (dc);
+    }
+  return count;
+}
+
+/* Returns the number of template args in DC, expanding any pack expansions
+   found there.  */
+
+static int
+d_args_length (struct d_print_info *dpi, const struct demangle_component *dc)
+{
+  int count = 0;
+  for (; dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST;
+       dc = d_right (dc))
+    {
+      struct demangle_component *elt = d_left (dc);
+      if (elt == NULL)
+	break;
+      if (elt->type == DEMANGLE_COMPONENT_PACK_EXPANSION)
+	{
+	  struct demangle_component *a = d_find_pack (dpi, d_left (elt));
+	  count += d_pack_length (a);
+	}
+      else
+	++count;
+    }
+  return count;
+}
+
+/* DC is a component of a mangled expression.  Print it, wrapped in parens
+   if needed.  */
+
+static void
+d_print_subexpr (struct d_print_info *dpi, int options,
+		 struct demangle_component *dc)
+{
+  int simple = 0;
+  if (dc->type == DEMANGLE_COMPONENT_NAME
+      || dc->type == DEMANGLE_COMPONENT_QUAL_NAME
+      || dc->type == DEMANGLE_COMPONENT_INITIALIZER_LIST
+      || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
+    simple = 1;
+  if (!simple)
+    d_append_char (dpi, '(');
+  d_print_comp (dpi, options, dc);
+  if (!simple)
+    d_append_char (dpi, ')');
+}
+
+/* Save the current scope.  */
+
+static void
+d_save_scope (struct d_print_info *dpi,
+	      const struct demangle_component *container)
+{
+  struct d_saved_scope *scope;
+  struct d_print_template *src, **link;
+
+  if (dpi->next_saved_scope >= dpi->num_saved_scopes)
+    {
+      d_print_error (dpi);
+      return;
+    }
+  scope = &dpi->saved_scopes[dpi->next_saved_scope];
+  dpi->next_saved_scope++;
+
+  scope->container = container;
+  link = &scope->templates;
+
+  for (src = dpi->templates; src != NULL; src = src->next)
+    {
+      struct d_print_template *dst;
+
+      if (dpi->next_copy_template >= dpi->num_copy_templates)
+	{
+	  d_print_error (dpi);
+	  return;
+	}
+      dst = &dpi->copy_templates[dpi->next_copy_template];
+      dpi->next_copy_template++;
+
+      dst->template_decl = src->template_decl;
+      *link = dst;
+      link = &dst->next;
+    }
+
+  *link = NULL;
+}
+
+/* Attempt to locate a previously saved scope.  Returns NULL if no
+   corresponding saved scope was found.  */
+
+static struct d_saved_scope *
+d_get_saved_scope (struct d_print_info *dpi,
+		   const struct demangle_component *container)
+{
+  int i;
+
+  for (i = 0; i < dpi->next_saved_scope; i++)
+    if (dpi->saved_scopes[i].container == container)
+      return &dpi->saved_scopes[i];
+
+  return NULL;
+}
+
+/* If DC is a C++17 fold-expression, print it and return true; otherwise
+   return false.  */
 
 static int
-d_pack_length (const struct demangle_component *dc)
+d_maybe_print_fold_expression (struct d_print_info *dpi, int options,
+			       struct demangle_component *dc)
 {
-  int count = 0;
-  while (dc && dc->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST
-	 && d_left (dc) != NULL)
+  struct demangle_component *ops, *operator_, *op1, *op2;
+  int save_idx;
+
+  const char *fold_code = d_left (dc)->u.s_operator.op->code;
+  if (fold_code[0] != 'f')
+    return 0;
+
+  ops = d_right (dc);
+  operator_ = d_left (ops);
+  op1 = d_right (ops);
+  op2 = 0;
+  if (op1->type == DEMANGLE_COMPONENT_TRINARY_ARG2)
     {
-      ++count;
-      dc = d_right (dc);
+      op2 = d_right (op1);
+      op1 = d_left (op1);
     }
-  return count;
-}
 
-/* DC is a component of a mangled expression.  Print it, wrapped in parens
-   if needed.  */
+  /* Print the whole pack.  */
+  save_idx = dpi->pack_index;
+  dpi->pack_index = -1;
 
-static void
-d_print_subexpr (struct d_print_info *dpi,
-		 const struct demangle_component *dc)
-{
-  int simple = 0;
-  if (dc->type == DEMANGLE_COMPONENT_NAME
-      || dc->type == DEMANGLE_COMPONENT_FUNCTION_PARAM)
-    simple = 1;
-  if (!simple)
-    d_append_char (dpi, '(');
-  d_print_comp (dpi, dc);
-  if (!simple)
-    d_append_char (dpi, ')');
+  switch (fold_code[1])
+    {
+      /* Unary left fold, (... + X).  */
+    case 'l':
+      d_append_string (dpi, "(...");
+      d_print_expr_op (dpi, options, operator_);
+      d_print_subexpr (dpi, options, op1);
+      d_append_char (dpi, ')');
+      break;
+
+      /* Unary right fold, (X + ...).  */
+    case 'r':
+      d_append_char (dpi, '(');
+      d_print_subexpr (dpi, options, op1);
+      d_print_expr_op (dpi, options, operator_);
+      d_append_string (dpi, "...)");
+      break;
+
+      /* Binary left fold, (42 + ... + X).  */
+    case 'L':
+      /* Binary right fold, (X + ... + 42).  */
+    case 'R':
+      d_append_char (dpi, '(');
+      d_print_subexpr (dpi, options, op1);
+      d_print_expr_op (dpi, options, operator_);
+      d_append_string (dpi, "...");
+      d_print_expr_op (dpi, options, operator_);
+      d_print_subexpr (dpi, options, op2);
+      d_append_char (dpi, ')');
+      break;
+    }
+
+  dpi->pack_index = save_idx;
+  return 1;
 }
 
 /* Subroutine to handle components.  */
 
 static void
-d_print_comp (struct d_print_info *dpi,
-              const struct demangle_component *dc)
+d_print_comp_inner (struct d_print_info *dpi, int options,
+		    struct demangle_component *dc)
 {
+  /* Magic variable to let reference smashing skip over the next modifier
+     without needing to modify *dc.  */
+  struct demangle_component *mod_inner = NULL;
+
+  /* Variable used to store the current templates while a previously
+     captured scope is used.  */
+  struct d_print_template *saved_templates;
+
+  /* Nonzero if templates have been stored in the above variable.  */
+  int need_template_restore = 0;
+
   if (dc == NULL)
     {
       d_print_error (dpi);
@@ -3320,20 +4623,37 @@ d_print_comp (struct d_print_info *dpi,
   switch (dc->type)
     {
     case DEMANGLE_COMPONENT_NAME:
-      if ((dpi->options & DMGL_JAVA) == 0)
+      if ((options & DMGL_JAVA) == 0)
 	d_append_buffer (dpi, dc->u.s_name.s, dc->u.s_name.len);
       else
 	d_print_java_identifier (dpi, dc->u.s_name.s, dc->u.s_name.len);
       return;
 
+    case DEMANGLE_COMPONENT_TAGGED_NAME:
+      d_print_comp (dpi, options, d_left (dc));
+      d_append_string (dpi, "[abi:");
+      d_print_comp (dpi, options, d_right (dc));
+      d_append_char (dpi, ']');
+      return;
+
     case DEMANGLE_COMPONENT_QUAL_NAME:
     case DEMANGLE_COMPONENT_LOCAL_NAME:
-      d_print_comp (dpi, d_left (dc));
-      if ((dpi->options & DMGL_JAVA) == 0)
+      d_print_comp (dpi, options, d_left (dc));
+      if ((options & DMGL_JAVA) == 0)
 	d_append_string (dpi, "::");
       else
 	d_append_char (dpi, '.');
-      d_print_comp (dpi, d_right (dc));
+      {
+	struct demangle_component *local_name = d_right (dc);
+	if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+	  {
+	    d_append_string (dpi, "{default arg#");
+	    d_append_num (dpi, local_name->u.s_unary_num.num + 1);
+	    d_append_string (dpi, "}::");
+	    local_name = local_name->u.s_unary_num.sub;
+	  }
+	d_print_comp (dpi, options, local_name);
+      }
       return;
 
     case DEMANGLE_COMPONENT_TYPED_NAME:
@@ -3366,9 +4686,7 @@ d_print_comp (struct d_print_info *dpi,
 	    adpm[i].templates = dpi->templates;
 	    ++i;
 
-	    if (typed_name->type != DEMANGLE_COMPONENT_RESTRICT_THIS
-		&& typed_name->type != DEMANGLE_COMPONENT_VOLATILE_THIS
-		&& typed_name->type != DEMANGLE_COMPONENT_CONST_THIS)
+	    if (!is_fnqual_component_type (typed_name->type))
 	      break;
 
 	    typed_name = d_left (typed_name);
@@ -3398,9 +4716,14 @@ d_print_comp (struct d_print_info *dpi,
 	    struct demangle_component *local_name;
 
 	    local_name = d_right (typed_name);
-	    while (local_name->type == DEMANGLE_COMPONENT_RESTRICT_THIS
-		   || local_name->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-		   || local_name->type == DEMANGLE_COMPONENT_CONST_THIS)
+	    if (local_name->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+	      local_name = local_name->u.s_unary_num.sub;
+	    if (local_name == NULL)
+	      {
+		d_print_error (dpi);
+		return;
+	      }
+	    while (is_fnqual_component_type (local_name->type))
 	      {
 		if (i >= sizeof adpm / sizeof adpm[0])
 		  {
@@ -3421,7 +4744,7 @@ d_print_comp (struct d_print_info *dpi,
 	      }
 	  }
 
-	d_print_comp (dpi, d_right (dc));
+	d_print_comp (dpi, options, d_right (dc));
 
 	if (typed_name->type == DEMANGLE_COMPONENT_TEMPLATE)
 	  dpi->templates = dpt.next;
@@ -3434,7 +4757,7 @@ d_print_comp (struct d_print_info *dpi,
 	    if (! adpm[i].printed)
 	      {
 		d_append_char (dpi, ' ');
-		d_print_mod (dpi, adpm[i].mod);
+		d_print_mod (dpi, options, adpm[i].mod);
 	      }
 	  }
 
@@ -3447,6 +4770,12 @@ d_print_comp (struct d_print_info *dpi,
       {
 	struct d_print_mod *hold_dpm;
 	struct demangle_component *dcl;
+	const struct demangle_component *hold_current;
+
+	/* This template may need to be referenced by a cast operator
+	   contained in its subtree.  */
+	hold_current = dpi->current_template;
+	dpi->current_template = dc;
 
 	/* Don't push modifiers into a template definition.  Doing so
 	   could give the wrong definition for a template argument.
@@ -3457,7 +4786,7 @@ d_print_comp (struct d_print_info *dpi,
 
         dcl = d_left (dc);
 
-        if ((dpi->options & DMGL_JAVA) != 0
+        if ((options & DMGL_JAVA) != 0
             && dcl->type == DEMANGLE_COMPONENT_NAME
             && dcl->u.s_name.len == 6
             && strncmp (dcl->u.s_name.s, "JArray", 6) == 0)
@@ -3465,16 +4794,16 @@ d_print_comp (struct d_print_info *dpi,
             /* Special-case Java arrays, so that JArray<TYPE> appears
                instead as TYPE[].  */
 
-            d_print_comp (dpi, d_right (dc));
+            d_print_comp (dpi, options, d_right (dc));
             d_append_string (dpi, "[]");
           }
         else
           {
-	    d_print_comp (dpi, dcl);
+	    d_print_comp (dpi, options, dcl);
 	    if (d_last_char (dpi) == '<')
 	      d_append_char (dpi, ' ');
 	    d_append_char (dpi, '<');
-	    d_print_comp (dpi, d_right (dc));
+	    d_print_comp (dpi, options, d_right (dc));
 	    /* Avoid generating two consecutive '>' characters, to avoid
 	       the C++ syntactic ambiguity.  */
 	    if (d_last_char (dpi) == '>')
@@ -3483,113 +4812,144 @@ d_print_comp (struct d_print_info *dpi,
           }
 
 	dpi->modifiers = hold_dpm;
+	dpi->current_template = hold_current;
 
 	return;
       }
 
     case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
-      {
-	struct d_print_template *hold_dpt;
-	struct demangle_component *a = d_lookup_template_argument (dpi, dc);
-
-	if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
-	  a = d_index_template_argument (a, dpi->pack_index);
+      if (dpi->is_lambda_arg)
+	{
+	  /* Show the template parm index, as that's how g++ displays
+	     these, and future proofs us against potential
+	     '[]<typename T> (T *a, T *b) {...}'.  */
+	  d_append_buffer (dpi, "auto:", 5);
+	  d_append_num (dpi, dc->u.s_number.number + 1);
+	}
+      else
+	{
+	  struct d_print_template *hold_dpt;
+	  struct demangle_component *a = d_lookup_template_argument (dpi, dc);
 
-	if (a == NULL)
-	  {
-	    d_print_error (dpi);
-	    return;
-	  }
+	  if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+	    a = d_index_template_argument (a, dpi->pack_index);
 
-	/* While processing this parameter, we need to pop the list of
-	   templates.  This is because the template parameter may
-	   itself be a reference to a parameter of an outer
-	   template.  */
+	  if (a == NULL)
+	    {
+	      d_print_error (dpi);
+	      return;
+	    }
 
-	hold_dpt = dpi->templates;
-	dpi->templates = hold_dpt->next;
+	  /* While processing this parameter, we need to pop the list
+	     of templates.  This is because the template parameter may
+	     itself be a reference to a parameter of an outer
+	     template.  */
 
-	d_print_comp (dpi, a);
+	  hold_dpt = dpi->templates;
+	  dpi->templates = hold_dpt->next;
 
-	dpi->templates = hold_dpt;
+	  d_print_comp (dpi, options, a);
 
-	return;
-      }
+	  dpi->templates = hold_dpt;
+	}
+      return;
 
     case DEMANGLE_COMPONENT_CTOR:
-      d_print_comp (dpi, dc->u.s_ctor.name);
+      d_print_comp (dpi, options, dc->u.s_ctor.name);
       return;
 
     case DEMANGLE_COMPONENT_DTOR:
       d_append_char (dpi, '~');
-      d_print_comp (dpi, dc->u.s_dtor.name);
+      d_print_comp (dpi, options, dc->u.s_dtor.name);
       return;
 
     case DEMANGLE_COMPONENT_VTABLE:
       d_append_string (dpi, "vtable for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_VTT:
       d_append_string (dpi, "VTT for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_CONSTRUCTION_VTABLE:
       d_append_string (dpi, "construction vtable for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       d_append_string (dpi, "-in-");
-      d_print_comp (dpi, d_right (dc));
+      d_print_comp (dpi, options, d_right (dc));
       return;
 
     case DEMANGLE_COMPONENT_TYPEINFO:
       d_append_string (dpi, "typeinfo for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_TYPEINFO_NAME:
       d_append_string (dpi, "typeinfo name for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_TYPEINFO_FN:
       d_append_string (dpi, "typeinfo fn for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_THUNK:
       d_append_string (dpi, "non-virtual thunk to ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_VIRTUAL_THUNK:
       d_append_string (dpi, "virtual thunk to ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_COVARIANT_THUNK:
       d_append_string (dpi, "covariant return thunk to ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_JAVA_CLASS:
       d_append_string (dpi, "java Class for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_GUARD:
       d_append_string (dpi, "guard variable for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
+      return;
+
+    case DEMANGLE_COMPONENT_TLS_INIT:
+      d_append_string (dpi, "TLS init function for ");
+      d_print_comp (dpi, options, d_left (dc));
+      return;
+
+    case DEMANGLE_COMPONENT_TLS_WRAPPER:
+      d_append_string (dpi, "TLS wrapper function for ");
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_REFTEMP:
-      d_append_string (dpi, "reference temporary for ");
-      d_print_comp (dpi, d_left (dc));
+      d_append_string (dpi, "reference temporary #");
+      d_print_comp (dpi, options, d_right (dc));
+      d_append_string (dpi, " for ");
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
       d_append_string (dpi, "hidden alias for ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
+      return;
+
+    case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
+      d_append_string (dpi, "transaction clone for ");
+      d_print_comp (dpi, options, d_left (dc));
+      return;
+
+    case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
+      d_append_string (dpi, "non-transaction clone for ");
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_SUB_STD:
@@ -3616,22 +4976,93 @@ d_print_comp (struct d_print_info *dpi,
 		  break;
 		if (pdpm->mod->type == dc->type)
 		  {
-		    d_print_comp (dpi, d_left (dc));
+		    d_print_comp (dpi, options, d_left (dc));
 		    return;
 		  }
 	      }
 	  }
       }
+      goto modifier;
+
+    case DEMANGLE_COMPONENT_REFERENCE:
+    case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+      {
+	/* Handle reference smashing: & + && = &.  */
+	struct demangle_component *sub = d_left (dc);
+	if (!dpi->is_lambda_arg
+	    && sub->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+	  {
+	    struct d_saved_scope *scope = d_get_saved_scope (dpi, sub);
+	    struct demangle_component *a;
+
+	    if (scope == NULL)
+	      {
+		/* This is the first time SUB has been traversed.
+		   We need to capture the current templates so
+		   they can be restored if SUB is reentered as a
+		   substitution.  */
+		d_save_scope (dpi, sub);
+		if (d_print_saw_error (dpi))
+		  return;
+	      }
+	    else
+	      {
+		const struct d_component_stack *dcse;
+		int found_self_or_parent = 0;
+
+		/* This traversal is reentering SUB as a substition.
+		   If we are not beneath SUB or DC in the tree then we
+		   need to restore SUB's template stack temporarily.  */
+		for (dcse = dpi->component_stack; dcse != NULL;
+		     dcse = dcse->parent)
+		  {
+		    if (dcse->dc == sub
+			|| (dcse->dc == dc
+			    && dcse != dpi->component_stack))
+		      {
+			found_self_or_parent = 1;
+			break;
+		      }
+		  }
+
+		if (!found_self_or_parent)
+		  {
+		    saved_templates = dpi->templates;
+		    dpi->templates = scope->templates;
+		    need_template_restore = 1;
+		  }
+	      }
+
+	    a = d_lookup_template_argument (dpi, sub);
+	    if (a && a->type == DEMANGLE_COMPONENT_TEMPLATE_ARGLIST)
+	      a = d_index_template_argument (a, dpi->pack_index);
+
+	    if (a == NULL)
+	      {
+		if (need_template_restore)
+		  dpi->templates = saved_templates;
+
+		d_print_error (dpi);
+		return;
+	      }
+
+	    sub = a;
+	  }
+
+	if (sub->type == DEMANGLE_COMPONENT_REFERENCE
+	    || sub->type == dc->type)
+	  dc = sub;
+	else if (sub->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE)
+	  mod_inner = d_left (sub);
+      }
       /* Fall through.  */
-    case DEMANGLE_COMPONENT_RESTRICT_THIS:
-    case DEMANGLE_COMPONENT_VOLATILE_THIS:
-    case DEMANGLE_COMPONENT_CONST_THIS:
+
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
     case DEMANGLE_COMPONENT_POINTER:
-    case DEMANGLE_COMPONENT_REFERENCE:
-    case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
     case DEMANGLE_COMPONENT_COMPLEX:
     case DEMANGLE_COMPONENT_IMAGINARY:
+    FNQUAL_COMPONENT_CASE:
+    modifier:
       {
 	/* We keep a list of modifiers on the stack.  */
 	struct d_print_mod dpm;
@@ -3642,20 +5073,26 @@ d_print_comp (struct d_print_info *dpi,
 	dpm.printed = 0;
 	dpm.templates = dpi->templates;
 
-	d_print_comp (dpi, d_left (dc));
+	if (!mod_inner)
+	  mod_inner = d_left (dc);
+
+	d_print_comp (dpi, options, mod_inner);
 
 	/* If the modifier didn't get printed by the type, print it
 	   now.  */
 	if (! dpm.printed)
-	  d_print_mod (dpi, dc);
+	  d_print_mod (dpi, options, dc);
 
 	dpi->modifiers = dpm.next;
 
+	if (need_template_restore)
+	  dpi->templates = saved_templates;
+
 	return;
       }
 
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
-      if ((dpi->options & DMGL_JAVA) == 0)
+      if ((options & DMGL_JAVA) == 0)
 	d_append_buffer (dpi, dc->u.s_builtin.type->name,
 			 dc->u.s_builtin.type->len);
       else
@@ -3664,16 +5101,21 @@ d_print_comp (struct d_print_info *dpi,
       return;
 
     case DEMANGLE_COMPONENT_VENDOR_TYPE:
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_FUNCTION_TYPE:
       {
-	if ((dpi->options & DMGL_RET_POSTFIX) != 0)
-	  d_print_function_type (dpi, dc, dpi->modifiers);
+	if ((options & DMGL_RET_POSTFIX) != 0)
+	  d_print_function_type (dpi,
+				 options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+				 dc, dpi->modifiers);
 
 	/* Print return type if present */
-	if (d_left (dc) != NULL)
+	if (d_left (dc) != NULL && (options & DMGL_RET_POSTFIX) != 0)
+	  d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+			d_left (dc));
+	else if (d_left (dc) != NULL && (options & DMGL_RET_DROP) == 0)
 	  {
 	    struct d_print_mod dpm;
 
@@ -3685,7 +5127,8 @@ d_print_comp (struct d_print_info *dpi,
 	    dpm.printed = 0;
 	    dpm.templates = dpi->templates;
 
-	    d_print_comp (dpi, d_left (dc));
+	    d_print_comp (dpi, options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+			  d_left (dc));
 
 	    dpi->modifiers = dpm.next;
 
@@ -3694,12 +5137,14 @@ d_print_comp (struct d_print_info *dpi,
 
 	    /* In standard prefix notation, there is a space between the
 	       return type and the function signature.  */
-	    if ((dpi->options & DMGL_RET_POSTFIX) == 0)
+	    if ((options & DMGL_RET_POSTFIX) == 0)
 	      d_append_char (dpi, ' ');
 	  }
 
-	if ((dpi->options & DMGL_RET_POSTFIX) == 0) 
-	  d_print_function_type (dpi, dc, dpi->modifiers);
+	if ((options & DMGL_RET_POSTFIX) == 0)
+	  d_print_function_type (dpi,
+				 options & ~(DMGL_RET_POSTFIX | DMGL_RET_DROP),
+				 dc, dpi->modifiers);
 
 	return;
       }
@@ -3752,7 +5197,7 @@ d_print_comp (struct d_print_info *dpi,
 	    pdpm = pdpm->next;
 	  }
 
-	d_print_comp (dpi, d_right (dc));
+	d_print_comp (dpi, options, d_right (dc));
 
 	dpi->modifiers = hold_modifiers;
 
@@ -3762,15 +5207,16 @@ d_print_comp (struct d_print_info *dpi,
 	while (i > 1)
 	  {
 	    --i;
-	    d_print_mod (dpi, adpm[i].mod);
+	    d_print_mod (dpi, options, adpm[i].mod);
 	  }
 
-	d_print_array_type (dpi, dc, dpi->modifiers);
+	d_print_array_type (dpi, options, dc, dpi->modifiers);
 
 	return;
       }
 
     case DEMANGLE_COMPONENT_PTRMEM_TYPE:
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
       {
 	struct d_print_mod dpm;
 
@@ -3780,16 +5226,12 @@ d_print_comp (struct d_print_info *dpi,
 	dpm.printed = 0;
 	dpm.templates = dpi->templates;
 
-	d_print_comp (dpi, d_right (dc));
+	d_print_comp (dpi, options, d_right (dc));
 
 	/* If the modifier didn't get printed by the type, print it
 	   now.  */
 	if (! dpm.printed)
-	  {
-	    d_append_char (dpi, ' ');
-	    d_print_comp (dpi, d_left (dc));
-	    d_append_string (dpi, "::*");
-	  }
+	  d_print_mod (dpi, options, dc);
 
 	dpi->modifiers = dpm.next;
 
@@ -3803,7 +5245,7 @@ d_print_comp (struct d_print_info *dpi,
       if (dc->u.s_fixed.length->u.s_builtin.type
 	  != &cplus_demangle_builtin_types['i'-'a'])
 	{
-	  d_print_comp (dpi, dc->u.s_fixed.length);
+	  d_print_comp (dpi, options, dc->u.s_fixed.length);
 	  d_append_char (dpi, ' ');
 	}
       if (dc->u.s_fixed.accum)
@@ -3815,53 +5257,133 @@ d_print_comp (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_ARGLIST:
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
       if (d_left (dc) != NULL)
-	d_print_comp (dpi, d_left (dc));
+	d_print_comp (dpi, options, d_left (dc));
       if (d_right (dc) != NULL)
 	{
 	  size_t len;
+	  unsigned long int flush_count;
+	  /* Make sure ", " isn't flushed by d_append_string, otherwise
+	     dpi->len -= 2 wouldn't work.  */
+	  if (dpi->len >= sizeof (dpi->buf) - 2)
+	    d_print_flush (dpi);
 	  d_append_string (dpi, ", ");
 	  len = dpi->len;
-	  d_print_comp (dpi, d_right (dc));
+	  flush_count = dpi->flush_count;
+	  d_print_comp (dpi, options, d_right (dc));
 	  /* If that didn't print anything (which can happen with empty
 	     template argument packs), remove the comma and space.  */
-	  if (dpi->len == len)
+	  if (dpi->flush_count == flush_count && dpi->len == len)
 	    dpi->len -= 2;
 	}
       return;
 
+    case DEMANGLE_COMPONENT_INITIALIZER_LIST:
+      {
+	struct demangle_component *type = d_left (dc);
+	struct demangle_component *list = d_right (dc);
+
+	if (type)
+	  d_print_comp (dpi, options, type);
+	d_append_char (dpi, '{');
+	d_print_comp (dpi, options, list);
+	d_append_char (dpi, '}');
+      }
+      return;
+
     case DEMANGLE_COMPONENT_OPERATOR:
       {
-	char c;
+	const struct demangle_operator_info *op = dc->u.s_operator.op;
+	int len = op->len;
 
 	d_append_string (dpi, "operator");
-	c = dc->u.s_operator.op->name[0];
-	if (IS_LOWER (c))
+	/* Add a space before new/delete.  */
+	if (IS_LOWER (op->name[0]))
 	  d_append_char (dpi, ' ');
-	d_append_buffer (dpi, dc->u.s_operator.op->name,
-			 dc->u.s_operator.op->len);
+	/* Omit a trailing space.  */
+	if (op->name[len-1] == ' ')
+	  --len;
+	d_append_buffer (dpi, op->name, len);
 	return;
       }
 
     case DEMANGLE_COMPONENT_EXTENDED_OPERATOR:
       d_append_string (dpi, "operator ");
-      d_print_comp (dpi, dc->u.s_extended_operator.name);
+      d_print_comp (dpi, options, dc->u.s_extended_operator.name);
       return;
 
-    case DEMANGLE_COMPONENT_CAST:
+    case DEMANGLE_COMPONENT_CONVERSION:
       d_append_string (dpi, "operator ");
-      d_print_cast (dpi, dc);
+      d_print_conversion (dpi, options, dc);
+      return;
+
+    case DEMANGLE_COMPONENT_NULLARY:
+      d_print_expr_op (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_UNARY:
-      if (d_left (dc)->type != DEMANGLE_COMPONENT_CAST)
-	d_print_expr_op (dpi, d_left (dc));
-      else
-	{
-	  d_append_char (dpi, '(');
-	  d_print_cast (dpi, d_left (dc));
-	  d_append_char (dpi, ')');
-	}
-      d_print_subexpr (dpi, d_right (dc));
+      {
+	struct demangle_component *op = d_left (dc);
+	struct demangle_component *operand = d_right (dc);
+	const char *code = NULL;
+
+	if (op->type == DEMANGLE_COMPONENT_OPERATOR)
+	  {
+	    code = op->u.s_operator.op->code;
+	    if (!strcmp (code, "ad"))
+	      {
+		/* Don't print the argument list for the address of a
+		   function.  */
+		if (operand->type == DEMANGLE_COMPONENT_TYPED_NAME
+		    && d_left (operand)->type == DEMANGLE_COMPONENT_QUAL_NAME
+		    && d_right (operand)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+		  operand = d_left (operand);
+	      }
+	    if (operand->type == DEMANGLE_COMPONENT_BINARY_ARGS)
+	      {
+		/* This indicates a suffix operator.  */
+		operand = d_left (operand);
+		d_print_subexpr (dpi, options, operand);
+		d_print_expr_op (dpi, options, op);
+		return;
+	      }
+	  }
+
+	/* For sizeof..., just print the pack length.  */
+	if (code && !strcmp (code, "sZ"))
+	  {
+	    struct demangle_component *a = d_find_pack (dpi, operand);
+	    int len = d_pack_length (a);
+	    d_append_num (dpi, len);
+	    return;
+	  }
+	else if (code && !strcmp (code, "sP"))
+	  {
+	    int len = d_args_length (dpi, operand);
+	    d_append_num (dpi, len);
+	    return;
+	  }
+
+	if (op->type != DEMANGLE_COMPONENT_CAST)
+	  d_print_expr_op (dpi, options, op);
+	else
+	  {
+	    d_append_char (dpi, '(');
+	    d_print_cast (dpi, options, op);
+	    d_append_char (dpi, ')');
+	  }
+	if (code && !strcmp (code, "gs"))
+	  /* Avoid parens after '::'.  */
+	  d_print_comp (dpi, options, operand);
+	else if (code && !strcmp (code, "st"))
+	  /* Always print parens for sizeof (type).  */
+	  {
+	    d_append_char (dpi, '(');
+	    d_print_comp (dpi, options, operand);
+	    d_append_char (dpi, ')');
+	  }
+	else
+	  d_print_subexpr (dpi, options, operand);
+      }
       return;
 
     case DEMANGLE_COMPONENT_BINARY:
@@ -3871,6 +5393,20 @@ d_print_comp (struct d_print_info *dpi,
 	  return;
 	}
 
+      if (op_is_new_cast (d_left (dc)))
+	{
+	  d_print_expr_op (dpi, options, d_left (dc));
+	  d_append_char (dpi, '<');
+	  d_print_comp (dpi, options, d_left (d_right (dc)));
+	  d_append_string (dpi, ">(");
+	  d_print_comp (dpi, options, d_right (d_right (dc)));
+	  d_append_char (dpi, ')');
+	  return;
+	}
+
+      if (d_maybe_print_fold_expression (dpi, options, dc))
+	return;
+
       /* We wrap an expression which uses the greater-than operator in
 	 an extra layer of parens so that it does not get confused
 	 with the '>' which ends the template parameters.  */
@@ -3879,10 +5415,33 @@ d_print_comp (struct d_print_info *dpi,
 	  && d_left (dc)->u.s_operator.op->name[0] == '>')
 	d_append_char (dpi, '(');
 
-      d_print_subexpr (dpi, d_left (d_right (dc)));
-      if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0)
-	d_print_expr_op (dpi, d_left (dc));
-      d_print_subexpr (dpi, d_right (d_right (dc)));
+      if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") == 0
+          && d_left (d_right (dc))->type == DEMANGLE_COMPONENT_TYPED_NAME)
+	{
+	  /* Function call used in an expression should not have printed types
+	     of the function arguments.  Values of the function arguments still
+	     get printed below.  */
+
+	  const struct demangle_component *func = d_left (d_right (dc));
+
+	  if (d_right (func)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
+	    d_print_error (dpi);
+	  d_print_subexpr (dpi, options, d_left (func));
+	}
+      else
+	d_print_subexpr (dpi, options, d_left (d_right (dc)));
+      if (strcmp (d_left (dc)->u.s_operator.op->code, "ix") == 0)
+	{
+	  d_append_char (dpi, '[');
+	  d_print_comp (dpi, options, d_right (d_right (dc)));
+	  d_append_char (dpi, ']');
+	}
+      else
+	{
+	  if (strcmp (d_left (dc)->u.s_operator.op->code, "cl") != 0)
+	    d_print_expr_op (dpi, options, d_left (dc));
+	  d_print_subexpr (dpi, options, d_right (d_right (dc)));
+	}
 
       if (d_left (dc)->type == DEMANGLE_COMPONENT_OPERATOR
 	  && d_left (dc)->u.s_operator.op->len == 1
@@ -3903,11 +5462,35 @@ d_print_comp (struct d_print_info *dpi,
 	  d_print_error (dpi);
 	  return;
 	}
-      d_print_subexpr (dpi, d_left (d_right (dc)));
-      d_print_expr_op (dpi, d_left (dc));
-      d_print_subexpr (dpi, d_left (d_right (d_right (dc))));
-      d_append_string (dpi, " : ");
-      d_print_subexpr (dpi, d_right (d_right (d_right (dc))));
+      if (d_maybe_print_fold_expression (dpi, options, dc))
+	return;
+      {
+	struct demangle_component *op = d_left (dc);
+	struct demangle_component *first = d_left (d_right (dc));
+	struct demangle_component *second = d_left (d_right (d_right (dc)));
+	struct demangle_component *third = d_right (d_right (d_right (dc)));
+
+	if (!strcmp (op->u.s_operator.op->code, "qu"))
+	  {
+	    d_print_subexpr (dpi, options, first);
+	    d_print_expr_op (dpi, options, op);
+	    d_print_subexpr (dpi, options, second);
+	    d_append_string (dpi, " : ");
+	    d_print_subexpr (dpi, options, third);
+	  }
+	else
+	  {
+	    d_append_string (dpi, "new ");
+	    if (d_left (first) != NULL)
+	      {
+		d_print_subexpr (dpi, options, first);
+		d_append_char (dpi, ' ');
+	      }
+	    d_print_comp (dpi, options, second);
+	    if (third)
+	      d_print_subexpr (dpi, options, third);
+	  }
+      }
       return;
 
     case DEMANGLE_COMPONENT_TRINARY_ARG1:
@@ -3938,7 +5521,7 @@ d_print_comp (struct d_print_info *dpi,
 		  {
 		    if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
 		      d_append_char (dpi, '-');
-		    d_print_comp (dpi, d_right (dc));
+		    d_print_comp (dpi, options, d_right (dc));
 		    switch (tp)
 		      {
 		      default:
@@ -3988,26 +5571,30 @@ d_print_comp (struct d_print_info *dpi,
 	  }
 
 	d_append_char (dpi, '(');
-	d_print_comp (dpi, d_left (dc));
+	d_print_comp (dpi, options, d_left (dc));
 	d_append_char (dpi, ')');
 	if (dc->type == DEMANGLE_COMPONENT_LITERAL_NEG)
 	  d_append_char (dpi, '-');
 	if (tp == D_PRINT_FLOAT)
 	  d_append_char (dpi, '[');
-	d_print_comp (dpi, d_right (dc));
+	d_print_comp (dpi, options, d_right (dc));
 	if (tp == D_PRINT_FLOAT)
 	  d_append_char (dpi, ']');
       }
       return;
 
+    case DEMANGLE_COMPONENT_NUMBER:
+      d_append_num (dpi, dc->u.s_number.number);
+      return;
+
     case DEMANGLE_COMPONENT_JAVA_RESOURCE:
       d_append_string (dpi, "java resource ");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       return;
 
     case DEMANGLE_COMPONENT_COMPOUND_NAME:
-      d_print_comp (dpi, d_left (dc));
-      d_print_comp (dpi, d_right (dc));
+      d_print_comp (dpi, options, d_left (dc));
+      d_print_comp (dpi, options, d_right (dc));
       return;
 
     case DEMANGLE_COMPONENT_CHARACTER:
@@ -4016,7 +5603,7 @@ d_print_comp (struct d_print_info *dpi,
 
     case DEMANGLE_COMPONENT_DECLTYPE:
       d_append_string (dpi, "decltype (");
-      d_print_comp (dpi, d_left (dc));
+      d_print_comp (dpi, options, d_left (dc));
       d_append_char (dpi, ')');
       return;
 
@@ -4030,7 +5617,7 @@ d_print_comp (struct d_print_info *dpi,
 	    /* d_find_pack won't find anything if the only packs involved
 	       in this expansion are function parameter packs; in that
 	       case, just print the pattern and "...".  */
-	    d_print_subexpr (dpi, d_left (dc));
+	    d_print_subexpr (dpi, options, d_left (dc));
 	    d_append_string (dpi, "...");
 	    return;
 	  }
@@ -4040,7 +5627,7 @@ d_print_comp (struct d_print_info *dpi,
 	for (i = 0; i < len; ++i)
 	  {
 	    dpi->pack_index = i;
-	    d_print_comp (dpi, dc);
+	    d_print_comp (dpi, options, dc);
 	    if (i < len-1)
 	      d_append_string (dpi, ", ");
 	  }
@@ -4049,21 +5636,51 @@ d_print_comp (struct d_print_info *dpi,
 
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
       {
-	char buf[25];
-	d_append_string (dpi, "parm#");
-	sprintf(buf,"%ld", dc->u.s_number.number);
-	d_append_string (dpi, buf);
-	return;
+	long num = dc->u.s_number.number;
+	if (num == 0)
+	  d_append_string (dpi, "this");
+	else
+	  {
+	    d_append_string (dpi, "{parm#");
+	    d_append_num (dpi, num);
+	    d_append_char (dpi, '}');
+	  }
       }
+      return;
 
     case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
       d_append_string (dpi, "global constructors keyed to ");
-      d_print_comp (dpi, dc->u.s_binary.left);
+      d_print_comp (dpi, options, dc->u.s_binary.left);
       return;
 
     case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
       d_append_string (dpi, "global destructors keyed to ");
-      d_print_comp (dpi, dc->u.s_binary.left);
+      d_print_comp (dpi, options, dc->u.s_binary.left);
+      return;
+
+    case DEMANGLE_COMPONENT_LAMBDA:
+      d_append_string (dpi, "{lambda(");
+      /* Generic lambda auto parms are mangled as the template type
+	 parm they are.  */
+      dpi->is_lambda_arg++;
+      d_print_comp (dpi, options, dc->u.s_unary_num.sub);
+      dpi->is_lambda_arg--;
+      d_append_string (dpi, ")#");
+      d_append_num (dpi, dc->u.s_unary_num.num + 1);
+      d_append_char (dpi, '}');
+      return;
+
+    case DEMANGLE_COMPONENT_UNNAMED_TYPE:
+      d_append_string (dpi, "{unnamed type#");
+      d_append_num (dpi, dc->u.s_number.number + 1);
+      d_append_char (dpi, '}');
+      return;
+
+    case DEMANGLE_COMPONENT_CLONE:
+      d_print_comp (dpi, options, d_left (dc));
+      d_append_string (dpi, " [clone ");
+      d_print_comp (dpi, options, d_right (dc));
+      d_append_char (dpi, ']');
       return;
 
     default:
@@ -4072,6 +5689,31 @@ d_print_comp (struct d_print_info *dpi,
     }
 }
 
+static void
+d_print_comp (struct d_print_info *dpi, int options,
+	      struct demangle_component *dc)
+{
+  struct d_component_stack self;
+  if (dc == NULL || dc->d_printing > 1 || dpi->recursion > MAX_RECURSION_COUNT)
+    {
+      d_print_error (dpi);
+      return;
+    }
+
+  dc->d_printing++;
+  dpi->recursion++;
+
+  self.dc = dc;
+  self.parent = dpi->component_stack;
+  dpi->component_stack = &self;
+
+  d_print_comp_inner (dpi, options, dc);
+
+  dpi->component_stack = self.parent;
+  dc->d_printing--;
+  dpi->recursion--;
+}
+
 /* Print a Java dentifier.  For Java we try to handle encoded extended
    Unicode characters.  The C++ ABI doesn't mention Unicode encoding,
    so we don't it for C++.  Characters are encoded as
@@ -4128,7 +5770,7 @@ d_print_java_identifier (struct d_print_info *dpi, const char *name, int len)
    qualifiers on this after printing a function.  */
 
 static void
-d_print_mod_list (struct d_print_info *dpi,
+d_print_mod_list (struct d_print_info *dpi, int options,
                   struct d_print_mod *mods, int suffix)
 {
   struct d_print_template *hold_dpt;
@@ -4138,11 +5780,9 @@ d_print_mod_list (struct d_print_info *dpi,
 
   if (mods->printed
       || (! suffix
-	  && (mods->mod->type == DEMANGLE_COMPONENT_RESTRICT_THIS
-	      || mods->mod->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-	      || mods->mod->type == DEMANGLE_COMPONENT_CONST_THIS)))
+	  && (is_fnqual_component_type (mods->mod->type))))
     {
-      d_print_mod_list (dpi, mods->next, suffix);
+      d_print_mod_list (dpi, options, mods->next, suffix);
       return;
     }
 
@@ -4153,13 +5793,13 @@ d_print_mod_list (struct d_print_info *dpi,
 
   if (mods->mod->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
     {
-      d_print_function_type (dpi, mods->mod, mods->next);
+      d_print_function_type (dpi, options, mods->mod, mods->next);
       dpi->templates = hold_dpt;
       return;
     }
   else if (mods->mod->type == DEMANGLE_COMPONENT_ARRAY_TYPE)
     {
-      d_print_array_type (dpi, mods->mod, mods->next);
+      d_print_array_type (dpi, options, mods->mod, mods->next);
       dpi->templates = hold_dpt;
       return;
     }
@@ -4175,38 +5815,45 @@ d_print_mod_list (struct d_print_info *dpi,
 
       hold_modifiers = dpi->modifiers;
       dpi->modifiers = NULL;
-      d_print_comp (dpi, d_left (mods->mod));
+      d_print_comp (dpi, options, d_left (mods->mod));
       dpi->modifiers = hold_modifiers;
 
-      if ((dpi->options & DMGL_JAVA) == 0)
+      if ((options & DMGL_JAVA) == 0)
 	d_append_string (dpi, "::");
       else
 	d_append_char (dpi, '.');
 
       dc = d_right (mods->mod);
-      while (dc->type == DEMANGLE_COMPONENT_RESTRICT_THIS
-	     || dc->type == DEMANGLE_COMPONENT_VOLATILE_THIS
-	     || dc->type == DEMANGLE_COMPONENT_CONST_THIS)
+
+      if (dc->type == DEMANGLE_COMPONENT_DEFAULT_ARG)
+	{
+	  d_append_string (dpi, "{default arg#");
+	  d_append_num (dpi, dc->u.s_unary_num.num + 1);
+	  d_append_string (dpi, "}::");
+	  dc = dc->u.s_unary_num.sub;
+	}
+
+      while (is_fnqual_component_type (dc->type))
 	dc = d_left (dc);
 
-      d_print_comp (dpi, dc);
+      d_print_comp (dpi, options, dc);
 
       dpi->templates = hold_dpt;
       return;
     }
 
-  d_print_mod (dpi, mods->mod);
+  d_print_mod (dpi, options, mods->mod);
 
   dpi->templates = hold_dpt;
 
-  d_print_mod_list (dpi, mods->next, suffix);
+  d_print_mod_list (dpi, options, mods->next, suffix);
 }
 
 /* Print a modifier.  */
 
 static void
-d_print_mod (struct d_print_info *dpi,
-             const struct demangle_component *mod)
+d_print_mod (struct d_print_info *dpi, int options,
+             struct demangle_component *mod)
 {
   switch (mod->type)
     {
@@ -4222,18 +5869,46 @@ d_print_mod (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_CONST_THIS:
       d_append_string (dpi, " const");
       return;
+    case DEMANGLE_COMPONENT_TRANSACTION_SAFE:
+      d_append_string (dpi, " transaction_safe");
+      return;
+    case DEMANGLE_COMPONENT_NOEXCEPT:
+      d_append_string (dpi, " noexcept");
+      if (d_right (mod))
+	{
+	  d_append_char (dpi, '(');
+	  d_print_comp (dpi, options, d_right (mod));
+	  d_append_char (dpi, ')');
+	}
+      return;
+    case DEMANGLE_COMPONENT_THROW_SPEC:
+      d_append_string (dpi, " throw");
+      if (d_right (mod))
+	{
+	  d_append_char (dpi, '(');
+	  d_print_comp (dpi, options, d_right (mod));
+	  d_append_char (dpi, ')');
+	}
+      return;
     case DEMANGLE_COMPONENT_VENDOR_TYPE_QUAL:
       d_append_char (dpi, ' ');
-      d_print_comp (dpi, d_right (mod));
+      d_print_comp (dpi, options, d_right (mod));
       return;
     case DEMANGLE_COMPONENT_POINTER:
       /* There is no pointer symbol in Java.  */
-      if ((dpi->options & DMGL_JAVA) == 0)
+      if ((options & DMGL_JAVA) == 0)
 	d_append_char (dpi, '*');
       return;
+    case DEMANGLE_COMPONENT_REFERENCE_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;
@@ -4246,16 +5921,22 @@ d_print_mod (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_PTRMEM_TYPE:
       if (d_last_char (dpi) != '(')
 	d_append_char (dpi, ' ');
-      d_print_comp (dpi, d_left (mod));
+      d_print_comp (dpi, options, d_left (mod));
       d_append_string (dpi, "::*");
       return;
     case DEMANGLE_COMPONENT_TYPED_NAME:
-      d_print_comp (dpi, d_left (mod));
+      d_print_comp (dpi, options, d_left (mod));
+      return;
+    case DEMANGLE_COMPONENT_VECTOR_TYPE:
+      d_append_string (dpi, " __vector(");
+      d_print_comp (dpi, options, d_left (mod));
+      d_append_char (dpi, ')');
       return;
+
     default:
       /* Otherwise, we have something that won't go back on the
 	 modifier stack, so we can just print it.  */
-      d_print_comp (dpi, mod);
+      d_print_comp (dpi, options, mod);
       return;
     }
 }
@@ -4263,25 +5944,22 @@ d_print_mod (struct d_print_info *dpi,
 /* Print a function type, except for the return type.  */
 
 static void
-d_print_function_type (struct d_print_info *dpi,
-                       const struct demangle_component *dc,
+d_print_function_type (struct d_print_info *dpi, int options,
+                       struct demangle_component *dc,
                        struct d_print_mod *mods)
 {
   int need_paren;
-  int saw_mod;
   int need_space;
   struct d_print_mod *p;
   struct d_print_mod *hold_modifiers;
 
   need_paren = 0;
-  saw_mod = 0;
   need_space = 0;
   for (p = mods; p != NULL; p = p->next)
     {
       if (p->printed)
 	break;
 
-      saw_mod = 1;
       switch (p->mod->type)
 	{
 	case DEMANGLE_COMPONENT_POINTER:
@@ -4299,9 +5977,7 @@ d_print_function_type (struct d_print_info *dpi,
 	  need_space = 1;
 	  need_paren = 1;
 	  break;
-	case DEMANGLE_COMPONENT_RESTRICT_THIS:
-	case DEMANGLE_COMPONENT_VOLATILE_THIS:
-	case DEMANGLE_COMPONENT_CONST_THIS:
+	FNQUAL_COMPONENT_CASE:
 	  break;
 	default:
 	  break;
@@ -4310,9 +5986,6 @@ d_print_function_type (struct d_print_info *dpi,
 	break;
     }
 
-  if (d_left (dc) != NULL && ! saw_mod)
-    need_paren = 1;
-
   if (need_paren)
     {
       if (! need_space)
@@ -4329,7 +6002,7 @@ d_print_function_type (struct d_print_info *dpi,
   hold_modifiers = dpi->modifiers;
   dpi->modifiers = NULL;
 
-  d_print_mod_list (dpi, mods, 0);
+  d_print_mod_list (dpi, options, mods, 0);
 
   if (need_paren)
     d_append_char (dpi, ')');
@@ -4337,11 +6010,11 @@ d_print_function_type (struct d_print_info *dpi,
   d_append_char (dpi, '(');
 
   if (d_right (dc) != NULL)
-    d_print_comp (dpi, d_right (dc));
+    d_print_comp (dpi, options, d_right (dc));
 
   d_append_char (dpi, ')');
 
-  d_print_mod_list (dpi, mods, 1);
+  d_print_mod_list (dpi, options, mods, 1);
 
   dpi->modifiers = hold_modifiers;
 }
@@ -4349,8 +6022,8 @@ d_print_function_type (struct d_print_info *dpi,
 /* Print an array type, except for the element type.  */
 
 static void
-d_print_array_type (struct d_print_info *dpi,
-                    const struct demangle_component *dc,
+d_print_array_type (struct d_print_info *dpi, int options,
+                    struct demangle_component *dc,
                     struct d_print_mod *mods)
 {
   int need_space;
@@ -4383,7 +6056,7 @@ d_print_array_type (struct d_print_info *dpi,
       if (need_paren)
 	d_append_string (dpi, " (");
 
-      d_print_mod_list (dpi, mods, 0);
+      d_print_mod_list (dpi, options, mods, 0);
 
       if (need_paren)
 	d_append_char (dpi, ')');
@@ -4395,7 +6068,7 @@ d_print_array_type (struct d_print_info *dpi,
   d_append_char (dpi, '[');
 
   if (d_left (dc) != NULL)
-    d_print_comp (dpi, d_left (dc));
+    d_print_comp (dpi, options, d_left (dc));
 
   d_append_char (dpi, ']');
 }
@@ -4403,56 +6076,67 @@ d_print_array_type (struct d_print_info *dpi,
 /* Print an operator in an expression.  */
 
 static void
-d_print_expr_op (struct d_print_info *dpi,
-                 const struct demangle_component *dc)
+d_print_expr_op (struct d_print_info *dpi, int options,
+                 struct demangle_component *dc)
 {
   if (dc->type == DEMANGLE_COMPONENT_OPERATOR)
     d_append_buffer (dpi, dc->u.s_operator.op->name,
 		     dc->u.s_operator.op->len);
   else
-    d_print_comp (dpi, dc);
+    d_print_comp (dpi, options, dc);
 }
 
 /* Print a cast.  */
 
 static void
-d_print_cast (struct d_print_info *dpi,
-              const struct demangle_component *dc)
+d_print_cast (struct d_print_info *dpi, int options,
+	      struct demangle_component *dc)
 {
-  if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
-    d_print_comp (dpi, d_left (dc));
-  else
-    {
-      struct d_print_mod *hold_dpm;
-      struct d_print_template dpt;
+  d_print_comp (dpi, options, d_left (dc));
+}
 
-      /* It appears that for a templated cast operator, we need to put
-	 the template parameters in scope for the operator name, but
-	 not for the parameters.  The effect is that we need to handle
-	 the template printing here.  */
+/* Print a conversion operator.  */
 
-      hold_dpm = dpi->modifiers;
-      dpi->modifiers = NULL;
+static void
+d_print_conversion (struct d_print_info *dpi, int options,
+		    struct demangle_component *dc)
+{
+  struct d_print_template dpt;
 
+  /* For a conversion operator, we need the template parameters from
+     the enclosing template in scope for processing the type.  */
+  if (dpi->current_template != NULL)
+    {
       dpt.next = dpi->templates;
       dpi->templates = &dpt;
-      dpt.template_decl = d_left (dc);
+      dpt.template_decl = dpi->current_template;
+    }
 
-      d_print_comp (dpi, d_left (d_left (dc)));
+  if (d_left (dc)->type != DEMANGLE_COMPONENT_TEMPLATE)
+    {
+      d_print_comp (dpi, options, d_left (dc));
+      if (dpi->current_template != NULL)
+	dpi->templates = dpt.next;
+    }
+  else
+    {
+      d_print_comp (dpi, options, d_left (d_left (dc)));
 
-      dpi->templates = dpt.next;
+      /* For a templated cast operator, we need to remove the template
+	 parameters from scope after printing the operator name,
+	 so we need to handle the template printing here.  */
+      if (dpi->current_template != NULL)
+	dpi->templates = dpt.next;
 
       if (d_last_char (dpi) == '<')
 	d_append_char (dpi, ' ');
       d_append_char (dpi, '<');
-      d_print_comp (dpi, d_right (d_left (dc)));
+      d_print_comp (dpi, options, d_right (d_left (dc)));
       /* Avoid generating two consecutive '>' characters, to avoid
 	 the C++ syntactic ambiguity.  */
       if (d_last_char (dpi) == '>')
 	d_append_char (dpi, ' ');
       d_append_char (dpi, '>');
-
-      dpi->modifiers = hold_dpm;
     }
 }
 
@@ -4480,11 +6164,12 @@ cplus_demangle_init_info (const char *mangled, int options, size_t len,
      chars in the mangled string.  */
   di->num_subs = len;
   di->next_sub = 0;
-  di->did_subs = 0;
 
   di->last_name = NULL;
 
   di->expansion = 0;
+  di->is_expression = 0;
+  di->is_conversion = 0;
 }
 
 /* Internal implementation for the demangler.  If MANGLED is a g++ v3 ABI
@@ -4505,7 +6190,7 @@ d_demangle_callback (const char *mangled, int options,
     }
   type;
   struct d_info di;
-  struct demangle_component *dc = NULL;
+  struct demangle_component *dc;
   int status;
 
   if (mangled[0] == '_' && mangled[1] == 'Z')
@@ -4551,10 +6236,12 @@ d_demangle_callback (const char *mangled, int options,
 			  (type == DCT_GLOBAL_CTORS
 			   ? DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS
 			   : DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS),
-			  d_make_name (&di, d_str (&di), strlen (d_str (&di))),
+			  d_make_demangle_mangled_name (&di, d_str (&di)),
 			  NULL);
 	d_advance (&di, strlen (d_str (&di)));
 	break;
+      default:
+	abort (); /* We have listed all the cases.  */
       }
 
     /* If DMGL_PARAMS is set, then if we didn't consume the entire
@@ -4600,7 +6287,7 @@ d_demangle (const char *mangled, int options, size_t *palc)
       return NULL;
     }
 
-  *palc = dgs.allocation_failure ? 1 : 0;
+  *palc = dgs.allocation_failure ? 1 : dgs.alc;
   return dgs.buf;
 }
 
@@ -4825,14 +6512,17 @@ is_ctor_or_dtor (const char *mangled,
       {
 	switch (dc->type)
 	  {
+	    /* These cannot appear on a constructor or destructor.  */
+	  case DEMANGLE_COMPONENT_RESTRICT_THIS:
+	  case DEMANGLE_COMPONENT_VOLATILE_THIS:
+	  case DEMANGLE_COMPONENT_CONST_THIS:
+	  case DEMANGLE_COMPONENT_REFERENCE_THIS:
+	  case DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS:
 	  default:
 	    dc = NULL;
 	    break;
 	  case DEMANGLE_COMPONENT_TYPED_NAME:
 	  case DEMANGLE_COMPONENT_TEMPLATE:
-	  case DEMANGLE_COMPONENT_RESTRICT_THIS:
-	  case DEMANGLE_COMPONENT_VOLATILE_THIS:
-	  case DEMANGLE_COMPONENT_CONST_THIS:
 	    dc = d_left (dc);
 	    break;
 	  case DEMANGLE_COMPONENT_QUAL_NAME:
diff --git a/rtemstoolkit/libiberty/cp-demangle.h b/rtemstoolkit/libiberty/cp-demangle.h
index aad3743..d4a4ab6 100644
--- a/rtemstoolkit/libiberty/cp-demangle.h
+++ b/rtemstoolkit/libiberty/cp-demangle.h
@@ -1,5 +1,5 @@
 /* Internal demangler interface for g++ V3 ABI.
-   Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian at wasabisystems.com>.
 
    This file is part of the libiberty library, which is part of GCC.
@@ -111,16 +111,17 @@ struct d_info
   int next_sub;
   /* The number of available entries in the subs array.  */
   int num_subs;
-  /* The number of substitutions which we actually made from the subs
-     array, plus the number of template parameter references we
-     saw.  */
-  int did_subs;
   /* The last name we saw, for constructors and destructors.  */
   struct demangle_component *last_name;
   /* A running total of the length of large expansions from the
      mangled name to the demangled name, such as standard
      substitutions and builtin types.  */
   int expansion;
+  /* Non-zero if we are parsing an expression.  */
+  int is_expression;
+  /* Non-zero if we are parsing the type operand of a conversion
+     operator, but not when in an expression.  */
+  int is_conversion;
 };
 
 /* To avoid running past the ending '\0', don't:
@@ -129,12 +130,37 @@ struct d_info
    - call d_check_char(di, '\0')
    Everything else is safe.  */
 #define d_peek_char(di) (*((di)->n))
-#define d_peek_next_char(di) ((di)->n[1])
-#define d_advance(di, i) ((di)->n += (i))
+#ifndef CHECK_DEMANGLER
+#  define d_peek_next_char(di) ((di)->n[1])
+#  define d_advance(di, i) ((di)->n += (i))
+#endif
 #define d_check_char(di, c) (d_peek_char(di) == c ? ((di)->n++, 1) : 0)
 #define d_next_char(di) (d_peek_char(di) == '\0' ? '\0' : *((di)->n++))
 #define d_str(di) ((di)->n)
 
+#ifdef CHECK_DEMANGLER
+static inline char
+d_peek_next_char (const struct d_info *di)
+{
+  if (!di->n[0])
+    abort ();
+  return di->n[1];
+}
+
+static inline void
+d_advance (struct d_info *di, int i)
+{
+  if (i < 0)
+    abort ();
+  while (i--)
+    {
+      if (!di->n[0])
+	abort ();
+      di->n++;
+    }
+}
+#endif
+
 /* Functions and arrays in cp-demangle.c which are referenced by
    functions in cp-demint.c.  */
 #ifdef IN_GLIBCPP_V3
@@ -147,7 +173,7 @@ struct d_info
 extern const struct demangle_operator_info cplus_demangle_operators[];
 #endif
 
-#define D_BUILTIN_TYPE_COUNT (32)
+#define D_BUILTIN_TYPE_COUNT (33)
 
 CP_STATIC_IF_GLIBCPP_V3
 const struct demangle_builtin_type_info
diff --git a/rtemstoolkit/libiberty/cplus-dem.c b/rtemstoolkit/libiberty/cplus-dem.c
index 6628514..81c17a3 100644
--- a/rtemstoolkit/libiberty/cplus-dem.c
+++ b/rtemstoolkit/libiberty/cplus-dem.c
@@ -1,6 +1,5 @@
 /* Demangler for GNU C++
-   Copyright 1989, 1991, 1994, 1995, 1996, 1997, 1998, 1999,
-   2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
    Written by James Clark (jjc at jclark.uucp)
    Rewritten by Fred Fish (fnf at cygnus.com) for ARM and Lucid demangling
    Modified by Satish Pai (pai at apollo.hp.com) for HP demangling
@@ -56,14 +55,19 @@ void * malloc ();
 void * realloc ();
 #endif
 
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifndef INT_MAX
+# define INT_MAX       (int)(((unsigned int) ~0) >> 1)          /* 0x7FFFFFFF */ 
+#endif
+
 #include <demangle.h>
 #undef CURRENT_DEMANGLING_STYLE
 #define CURRENT_DEMANGLING_STYLE work->options
 
 #include "libiberty.h"
 
-static char *ada_demangle (const char *, int);
-
 #define min(X,Y) (((X) < (Y)) ? (X) : (Y))
 
 /* A value at least one greater than the maximum number of characters
@@ -139,6 +143,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)
@@ -239,6 +246,7 @@ typedef enum type_kind_t
   tk_none,
   tk_pointer,
   tk_reference,
+  tk_rvalue_reference,
   tk_integral,
   tk_bool,
   tk_char,
@@ -308,6 +316,18 @@ const struct demangler_engine libiberty_demanglers[] =
   }
   ,
   {
+    DLANG_DEMANGLING_STYLE_STRING,
+    dlang_demangling,
+    "DLANG style demangling"
+  }
+  ,
+  {
+    RUST_DEMANGLING_STYLE_STRING,
+    rust_demangling,
+    "Rust style demangling"
+  }
+  ,
+  {
     NULL, unknown_demangling, NULL
   }
 };
@@ -424,6 +444,10 @@ iterate_demangle_function (struct work_stuff *,
 
 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 *);
@@ -478,8 +502,6 @@ demangle_arm_hp_template (struct work_stuff *, const char **, int, string *);
 static void
 recursively_demangle (struct work_stuff *, const char **, string *, int);
 
-static void grow_vect (char **, size_t *, size_t, int);
-
 /* Translate count to integer, consuming tokens in the process.
    Conversion terminates on the first non-digit character.
 
@@ -498,21 +520,17 @@ consume_count (const char **type)
 
   while (ISDIGIT ((unsigned char)**type))
     {
-      count *= 10;
-
-      /* Check for overflow.
-	 We assume that count is represented using two's-complement;
-	 no power of two is divisible by ten, so if an overflow occurs
-	 when multiplying by ten, the result will not be a multiple of
-	 ten.  */
-      if ((count % 10) != 0)
+      const int digit = **type - '0';
+      /* Check for overflow.  */
+      if (count > ((INT_MAX - digit) / 10))
 	{
 	  while (ISDIGIT ((unsigned char) **type))
 	    (*type)++;
 	  return -1;
 	}
 
-      count += **type - '0';
+      count *= 10;
+      count += digit;
       (*type)++;
     }
 
@@ -857,10 +875,26 @@ cplus_demangle (const char *mangled, int options)
     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;
     }
 
@@ -872,129 +906,297 @@ cplus_demangle (const char *mangled, int options)
     }
 
   if (GNAT_DEMANGLING)
-    return ada_demangle(mangled,options);
+    return ada_demangle (mangled, options);
+
+  if (DLANG_DEMANGLING)
+    {
+      ret = dlang_demangle (mangled, options);
+      if (ret)
+	return ret;
+    }
 
   ret = internal_cplus_demangle (work, mangled);
   squangle_mop_up (work);
   return (ret);
 }
 
-
-/* Assuming *OLD_VECT points to an array of *SIZE objects of size
-   ELEMENT_SIZE, grow it to contain at least MIN_SIZE objects,
-   updating *OLD_VECT and *SIZE as necessary.  */
-
-static void
-grow_vect (char **old_vect, size_t *size, size_t min_size, int element_size)
+char *
+rust_demangle (const char *mangled, int options)
 {
-  if (*size < min_size)
+  /* 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)
     {
-      *size *= 2;
-      if (*size < min_size)
-	*size = min_size;
-      *old_vect = XRESIZEVAR (char, *old_vect, *size * element_size);
+      if (rust_is_mangled (ret))
+	rust_demangle_sym (ret);
+      else
+	{
+	  free (ret);
+	  ret = NULL;
+	}
     }
+
+  return ret;
 }
 
-/* Demangle ada names:
-   1. Discard final __{DIGIT}+ or ${DIGIT}+
-   2. Convert other instances of embedded "__" to `.'.
-   3. Discard leading _ada_.
-   4. Remove everything after first ___ if it is followed by 'X'.
-   5. Put symbols that should be suppressed in <...> brackets.
-   The resulting string is valid until the next call of ada_demangle.  */
+/* Demangle ada names.  The encoding is documented in gcc/ada/exp_dbug.ads.  */
 
-static char *
+char *
 ada_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
 {
-  int i, j;
   int len0;
   const char* p;
+  char *d;
   char *demangled = NULL;
-  int changed;
-  size_t demangled_size = 0;
   
-  changed = 0;
-
+  /* Discard leading _ada_, which is used for library level subprograms.  */
   if (strncmp (mangled, "_ada_", 5) == 0)
-    {
-      mangled += 5;
-      changed = 1;
-    }
+    mangled += 5;
+
+  /* All ada unit names are lower-case.  */
+  if (!ISLOWER (mangled[0]))
+    goto unknown;
+
+  /* Most of the demangling will trivially remove chars.  Operator names
+     may add one char but because they are always preceeded by '__' which is
+     replaced by '.', they eventually never expand the size.
+     A few special names such as '___elabs' add a few chars (at most 7), but
+     they occur only once.  */
+  len0 = strlen (mangled) + 7 + 1;
+  demangled = XNEWVEC (char, len0);
   
-  if (mangled[0] == '_' || mangled[0] == '<')
-    goto Suppress;
-  
-  p = strstr (mangled, "___");
-  if (p == NULL)
-    len0 = strlen (mangled);
-  else
+  d = demangled;
+  p = mangled;
+  while (1)
     {
-      if (p[3] == 'X')
-	{
-	  len0 = p - mangled;
-	  changed = 1;
-	}
+      /* An entity names is expected.  */
+      if (ISLOWER (*p))
+        {
+          /* An identifier, which is always lower case.  */
+          do
+            *d++ = *p++;
+          while (ISLOWER(*p) || ISDIGIT (*p)
+                 || (p[0] == '_' && (ISLOWER (p[1]) || ISDIGIT (p[1]))));
+        }
+      else if (p[0] == 'O')
+        {
+          /* An operator name.  */
+          static const char * const operators[][2] =
+            {{"Oabs", "abs"},  {"Oand", "and"},    {"Omod", "mod"},
+             {"Onot", "not"},  {"Oor", "or"},      {"Orem", "rem"},
+             {"Oxor", "xor"},  {"Oeq", "="},       {"One", "/="},
+             {"Olt", "<"},     {"Ole", "<="},      {"Ogt", ">"},
+             {"Oge", ">="},    {"Oadd", "+"},      {"Osubtract", "-"},
+             {"Oconcat", "&"}, {"Omultiply", "*"}, {"Odivide", "/"},
+             {"Oexpon", "**"}, {NULL, NULL}};
+          int k;
+
+          for (k = 0; operators[k][0] != NULL; k++)
+            {
+              size_t slen = strlen (operators[k][0]);
+              if (strncmp (p, operators[k][0], slen) == 0)
+                {
+                  p += slen;
+                  slen = strlen (operators[k][1]);
+                  *d++ = '"';
+                  memcpy (d, operators[k][1], slen);
+                  d += slen;
+                  *d++ = '"';
+                  break;
+                }
+            }
+          /* Operator not found.  */
+          if (operators[k][0] == NULL)
+            goto unknown;
+        }
       else
-	goto Suppress;
-    }
-  
-  /* Make demangled big enough for possible expansion by operator name.  */
-  grow_vect (&demangled,
-	     &demangled_size,  2 * len0 + 1,
-	     sizeof (char));
-  
-  if (ISDIGIT ((unsigned char) mangled[len0 - 1])) {
-    for (i = len0 - 2; i >= 0 && ISDIGIT ((unsigned char) mangled[i]); i -= 1)
-      ;
-    if (i > 1 && mangled[i] == '_' && mangled[i - 1] == '_')
-      {
-	len0 = i - 1;
-	changed = 1;
-      }
-    else if (mangled[i] == '$')
-      {
-	len0 = i;
-	changed = 1;
-      }
-  }
-  
-  for (i = 0, j = 0; i < len0 && ! ISALPHA ((unsigned char)mangled[i]);
-       i += 1, j += 1)
-    demangled[j] = mangled[i];
-  
-  while (i < len0)
-    {
-      if (i < len0 - 2 && mangled[i] == '_' && mangled[i + 1] == '_')
-	{
-	  demangled[j] = '.';
-	  changed = 1;
-	  i += 2; j += 1;
-	}
+        {
+          /* Not a GNAT encoding.  */
+          goto unknown;
+        }
+
+      /* The name can be directly followed by some uppercase letters.  */
+      if (p[0] == 'T' && p[1] == 'K')
+        {
+          /* Task stuff.  */
+          if (p[2] == 'B' && p[3] == 0)
+            {
+              /* Subprogram for task body.  */
+              break;
+            }
+          else if (p[2] == '_' && p[3] == '_')
+            {
+              /* Inner declarations in a task.  */
+              p += 4;
+              *d++ = '.';
+              continue;
+            }
+          else
+            goto unknown;
+        }
+      if (p[0] == 'E' && p[1] == 0)
+        {
+          /* Exception name.  */
+          goto unknown;
+        }
+      if ((p[0] == 'P' || p[0] == 'N') && p[1] == 0)
+        {
+          /* Protected type subprogram.  */
+          break;
+        }
+      if ((*p == 'N' || *p == 'S') && p[1] == 0)
+        {
+          /* Enumerated type name table.  */
+          goto unknown;
+        }
+      if (p[0] == 'X')
+        {
+          /* Body nested.  */
+          p++;
+          while (p[0] == 'n' || p[0] == 'b')
+            p++;
+        }
+      if (p[0] == 'S' && p[1] != 0 && (p[2] == '_' || p[2] == 0))
+        {
+          /* Stream operations.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'R':
+              name = "'Read";
+              break;
+            case 'W':
+              name = "'Write";
+              break;
+            case 'I':
+              name = "'Input";
+              break;
+            case 'O':
+              name = "'Output";
+              break;
+            default:
+              goto unknown;
+            }
+          p += 2;
+          strcpy (d, name);
+          d += strlen (name);
+        }
+      else if (p[0] == 'D')
+        {
+          /* Controlled type operation.  */
+          const char *name;
+          switch (p[1])
+            {
+            case 'F':
+              name = ".Finalize";
+              break;
+            case 'A':
+              name = ".Adjust";
+              break;
+            default:
+              goto unknown;
+            }
+          strcpy (d, name);
+          d += strlen (name);
+          break;
+        }
+
+      if (p[0] == '_')
+        {
+          /* Separator.  */
+          if (p[1] == '_')
+            {
+              /* Standard separator.  Handled first.  */
+              p += 2;
+
+              if (ISDIGIT (*p))
+                {
+                  /* Overloading number.  */
+                  do
+                    p++;
+                  while (ISDIGIT (*p) || (p[0] == '_' && ISDIGIT (p[1])));
+                  if (*p == 'X')
+                    {
+                      p++;
+                      while (p[0] == 'n' || p[0] == 'b')
+                        p++;
+                    }
+                }
+              else if (p[0] == '_' && p[1] != '_')
+                {
+                  /* Special names.  */
+                  static const char * const special[][2] = {
+                    { "_elabb", "'Elab_Body" },
+                    { "_elabs", "'Elab_Spec" },
+                    { "_size", "'Size" },
+                    { "_alignment", "'Alignment" },
+                    { "_assign", ".\":=\"" },
+                    { NULL, NULL }
+                  };
+                  int k;
+
+                  for (k = 0; special[k][0] != NULL; k++)
+                    {
+                      size_t slen = strlen (special[k][0]);
+                      if (strncmp (p, special[k][0], slen) == 0)
+                        {
+                          p += slen;
+                          slen = strlen (special[k][1]);
+                          memcpy (d, special[k][1], slen);
+                          d += slen;
+                          break;
+                        }
+                    }
+                  if (special[k][0] != NULL)
+                    break;
+                  else
+                    goto unknown;
+                }
+              else
+                {
+                  *d++ = '.';
+                  continue;
+                }
+            }
+          else if (p[1] == 'B' || p[1] == 'E')
+            {
+              /* Entry Body or barrier Evaluation.  */
+              p += 2;
+              while (ISDIGIT (*p))
+                p++;
+              if (p[0] == 's' && p[1] == 0)
+                break;
+              else
+                goto unknown;
+            }
+          else
+            goto unknown;
+        }
+
+      if (p[0] == '.' && ISDIGIT (p[1]))
+        {
+          /* Nested subprogram.  */
+          p += 2;
+          while (ISDIGIT (*p))
+            p++;
+        }
+      if (*p == 0)
+        {
+          /* End of mangled name.  */
+          break;
+        }
       else
-	{
-	  demangled[j] = mangled[i];
-	  i += 1;  j += 1;
-	}
+        goto unknown;
     }
-  demangled[j] = '\000';
-  
-  for (i = 0; demangled[i] != '\0'; i += 1)
-    if (ISUPPER ((unsigned char)demangled[i]) || demangled[i] == ' ')
-      goto Suppress;
+  *d = 0;
+  return demangled;
 
-  if (! changed)
-    {
-      free (demangled);
-      return NULL;
-    }
-  else
-    return demangled;
-  
- Suppress:
-  grow_vect (&demangled,
-	     &demangled_size,  strlen (mangled) + 3,
-	     sizeof (char));
+ unknown:
+  XDELETEVEC (demangled);
+  len0 = strlen (mangled);
+  demangled = XNEWVEC (char, len0 + 3);
 
   if (mangled[0] == '<')
      strcpy (demangled, mangled);
@@ -1040,6 +1242,11 @@ internal_cplus_demangle (struct work_stuff *work, const char *mangled)
       if ((AUTO_DEMANGLING || GNU_DEMANGLING))
 	{
 	  success = gnu_special (work, &mangled, &decl);
+	  if (!success)
+	    {
+	      delete_work_stuff (work);
+	      string_delete (&decl);
+	    }
 	}
       if (!success)
 	{
@@ -1083,10 +1290,14 @@ squangle_mop_up (struct work_stuff *work)
   if (work -> btypevec != NULL)
     {
       free ((char *) work -> btypevec);
+      work->btypevec = NULL;
+      work->bsize = 0;
     }
   if (work -> ktypevec != NULL)
     {
       free ((char *) work -> ktypevec);
+      work->ktypevec = NULL;
+      work->ksize = 0;
     }
 }
 
@@ -1137,6 +1348,10 @@ work_stuff_copy_to_from (struct work_stuff *to, struct work_stuff *from)
       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);
 
@@ -1165,19 +1380,24 @@ delete_non_B_K_work_stuff (struct work_stuff *work)
   /* 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)
     {
       int i;
 
       for (i = 0; i < work->ntmpl_args; i++)
-	if (work->tmpl_argvec[i])
-	  free ((char*) work->tmpl_argvec[i]);
+	free ((char*) work->tmpl_argvec[i]);
 
       free ((char*) work->tmpl_argvec);
       work->tmpl_argvec = NULL;
@@ -1472,12 +1692,13 @@ demangle_signature (struct work_stuff *work,
 					   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)
@@ -1879,7 +2100,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled,
     }
   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,
@@ -1888,7 +2110,8 @@ demangle_template_value_parm (struct work_stuff *work, const char **mangled,
       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);
@@ -1951,6 +2174,8 @@ demangle_template (struct work_stuff *work, const char **mangled,
 	{
 	  int idx;
 	  (*mangled)++;
+	  if (**mangled == '\0')
+	    return (0);
 	  (*mangled)++;
 
 	  idx = consume_count_with_underscores (mangled);
@@ -2795,7 +3020,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
   int success = 1;
   const char *p;
 
-  if ((*mangled)[0] == '_'
+  if ((*mangled)[0] == '_' && (*mangled)[1] != '\0'
       && strchr (cplus_markers, (*mangled)[1]) != NULL
       && (*mangled)[2] == '_')
     {
@@ -2809,7 +3034,7 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
 		&& (*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>"
@@ -2845,6 +3070,11 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
 		      success = 1;
 		      break;
 		    }
+		  else if (n == -1)
+		    {
+		      success = 0;
+		      break;
+		    }
 		}
 	      else
 		{
@@ -2939,6 +3169,8 @@ gnu_special (struct work_stuff *work, const char **mangled, string *declp)
       delta = consume_count (mangled);
       if (delta == -1)
 	success = 0;
+      else if (**mangled != '_')
+        success = 0;
       else
 	{
 	  char *method = internal_cplus_demangle (work, ++*mangled);
@@ -3384,6 +3616,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;
@@ -3396,6 +3630,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 
   done = 0;
   success = 1;
+  is_proctypevec = 0;
   while (success && !done)
     {
       int member;
@@ -3420,6 +3655,14 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 	    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':
 	  {
@@ -3443,13 +3686,20 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 	/* 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;
@@ -3477,7 +3727,6 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 	  break;
 
 	case 'M':
-	case 'O':
 	  {
 	    type_quals = TYPE_UNQUALIFIED;
 
@@ -3522,7 +3771,10 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 		    string_delete (&temp);
 		  }
 		else
-		  break;
+		  {
+		    string_delete (&temp);
+		    break;
+		  }
 	      }
 	    else if (**mangled == 'Q')
 	      {
@@ -3554,11 +3806,12 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
 		    break;
 		  }
 
-		if (*(*mangled)++ != 'F')
+		if (*(*mangled) != 'F')
 		  {
 		    success = 0;
 		    break;
 		  }
+		(*mangled)++;
 	      }
 	    if ((member && !demangle_nested_args (work, mangled, &decl))
 		|| **mangled != '_')
@@ -3618,7 +3871,7 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
     /* 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]);
@@ -3669,6 +3922,9 @@ do_type (struct work_stuff *work, const char **mangled, string *result)
     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);
@@ -3812,6 +4068,7 @@ demangle_fund_type (struct work_stuff *work,
 	  success = 0;
 	  break;
 	}
+      /* fall through */
     case 'I':
       (*mangled)++;
       if (**mangled == '_')
@@ -3959,7 +4216,8 @@ do_hpacc_template_literal (struct work_stuff *work, const char **mangled,
 
   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
@@ -4081,6 +4339,41 @@ do_arg (struct work_stuff *work, const char **mangled, string *result)
 }
 
 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;
@@ -4097,6 +4390,8 @@ remember_type (struct work_stuff *work, const char *start, int len)
 	}
       else
 	{
+          if (work -> typevec_size > INT_MAX / 2)
+	    xmalloc_failed (INT_MAX);
 	  work -> typevec_size *= 2;
 	  work -> typevec
 	    = XRESIZEVEC (char *, work->typevec, work->typevec_size);
@@ -4124,6 +4419,8 @@ remember_Ktype (struct work_stuff *work, const char *start, int len)
 	}
       else
 	{
+          if (work -> ksize > INT_MAX / 2)
+	    xmalloc_failed (INT_MAX);
 	  work -> ksize *= 2;
 	  work -> ktypevec
 	    = XRESIZEVEC (char *, work->ktypevec, work->ksize);
@@ -4153,6 +4450,8 @@ register_Btype (struct work_stuff *work)
 	}
       else
 	{
+          if (work -> bsize > INT_MAX / 2)
+	    xmalloc_failed (INT_MAX);
 	  work -> bsize *= 2;
 	  work -> btypevec
 	    = XRESIZEVEC (char *, work->btypevec, work->bsize);
@@ -4338,10 +4637,13 @@ demangle_args (struct work_stuff *work, const char **mangled,
 		{
 		  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);
@@ -4607,6 +4909,8 @@ string_need (string *s, int n)
   else if (s->e - s->p < n)
     {
       tem = s->p - s->b;
+      if (n > INT_MAX / 2 - tem)
+        xmalloc_failed (INT_MAX); 
       n += tem;
       n *= 2;
       s->b = XRESIZEVEC (char, s->b, n);
diff --git a/rtemstoolkit/libiberty/d-demangle.c b/rtemstoolkit/libiberty/d-demangle.c
new file mode 100644
index 0000000..08690de
--- /dev/null
+++ b/rtemstoolkit/libiberty/d-demangle.c
@@ -0,0 +1,1646 @@
+/* Demangler for the D programming language
+   Copyright (C) 2014-2017 Free Software Foundation, Inc.
+   Written by Iain Buclaw (ibuclaw at gdcproject.org)
+
+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/>.  */
+
+/* This file exports one function; dlang_demangle.  */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "safe-ctype.h"
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <demangle.h>
+#include "libiberty.h"
+
+/* A mini string-handling package */
+
+typedef struct string		/* Beware: these aren't required to be */
+{				/*  '\0' terminated.  */
+  char *b;			/* pointer to start of string */
+  char *p;			/* pointer after last character */
+  char *e;			/* pointer after end of allocated space */
+} string;
+
+static void
+string_need (string *s, int n)
+{
+  int tem;
+
+  if (s->b == NULL)
+    {
+      if (n < 32)
+	{
+	  n = 32;
+	}
+      s->p = s->b = XNEWVEC (char, n);
+      s->e = s->b + n;
+    }
+  else if (s->e - s->p < n)
+    {
+      tem = s->p - s->b;
+      n += tem;
+      n *= 2;
+      s->b = XRESIZEVEC (char, s->b, n);
+      s->p = s->b + tem;
+      s->e = s->b + n;
+    }
+}
+
+static void
+string_delete (string *s)
+{
+  if (s->b != NULL)
+    {
+      XDELETEVEC (s->b);
+      s->b = s->e = s->p = NULL;
+    }
+}
+
+static void
+string_init (string *s)
+{
+  s->b = s->p = s->e = NULL;
+}
+
+static int
+string_length (string *s)
+{
+  if (s->p == s->b)
+    {
+      return 0;
+    }
+  return s->p - s->b;
+}
+
+static void
+string_setlength (string *s, int n)
+{
+  if (n - string_length (s) < 0)
+    {
+      s->p = s->b + n;
+    }
+}
+
+static void
+string_append (string *p, const char *s)
+{
+  int n = strlen (s);
+  string_need (p, n);
+  memcpy (p->p, s, n);
+  p->p += n;
+}
+
+static void
+string_appendn (string *p, const char *s, int n)
+{
+  if (n != 0)
+    {
+      string_need (p, n);
+      memcpy (p->p, s, n);
+      p->p += n;
+    }
+}
+
+static void
+string_prependn (string *p, const char *s, int n)
+{
+  char *q;
+
+  if (n != 0)
+    {
+      string_need (p, n);
+      for (q = p->p - 1; q >= p->b; q--)
+	{
+	  q[n] = q[0];
+	}
+      memcpy (p->b, s, n);
+      p->p += n;
+    }
+}
+
+static void
+string_prepend (string *p, const char *s)
+{
+  if (s != NULL && *s != '\0')
+    {
+      string_prependn (p, s, strlen (s));
+    }
+}
+
+/* What kinds of symbol we could be parsing.  */
+enum dlang_symbol_kinds
+{
+  /* Top-level symbol, needs it's type checked.  */
+  dlang_top_level,
+  /* Function symbol, needs it's type checked.   */
+  dlang_function,
+  /* Strongly typed name, such as for classes, structs and enums.  */
+  dlang_type_name,
+  /* Template identifier.  */
+  dlang_template_ident,
+  /* Template symbol parameter.  */
+  dlang_template_param
+};
+
+/* Prototypes for forward referenced functions */
+static const char *dlang_function_args (string *, const char *);
+
+static const char *dlang_type (string *, const char *);
+
+static const char *dlang_value (string *, const char *, const char *, char);
+
+static const char *dlang_parse_qualified (string *, const char *,
+					  enum dlang_symbol_kinds);
+
+static const char *dlang_parse_mangle (string *, const char *,
+				       enum dlang_symbol_kinds);
+
+static const char *dlang_parse_tuple (string *, const char *);
+
+static const char *dlang_parse_template (string *, const char *, long);
+
+
+/* Extract the number from MANGLED, and assign the result to RET.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_number (const char *mangled, long *ret)
+{
+  /* Return NULL if trying to extract something that isn't a digit.  */
+  if (mangled == NULL || !ISDIGIT (*mangled))
+    return NULL;
+
+  (*ret) = 0;
+
+  while (ISDIGIT (*mangled))
+    {
+      (*ret) *= 10;
+
+      /* If an overflow occured when multiplying by ten, the result
+	 will not be a multiple of ten.  */
+      if ((*ret % 10) != 0)
+	return NULL;
+
+      (*ret) += mangled[0] - '0';
+      mangled++;
+    }
+
+  if (*mangled == '\0' || *ret < 0)
+    return NULL;
+
+  return mangled;
+}
+
+/* Extract the hex-digit from MANGLED, and assign the result to RET.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_hexdigit (const char *mangled, char *ret)
+{
+  char c;
+
+  /* Return NULL if trying to extract something that isn't a hexdigit.  */
+  if (mangled == NULL || !ISXDIGIT (mangled[0]) || !ISXDIGIT (mangled[1]))
+    return NULL;
+
+  c = mangled[0];
+  if (!ISDIGIT (c))
+    (*ret) = (c - (ISUPPER (c) ? 'A' : 'a') + 10);
+  else
+    (*ret) = (c - '0');
+
+  c = mangled[1];
+  if (!ISDIGIT (c))
+    (*ret) = (*ret << 4) | (c - (ISUPPER (c) ? 'A' : 'a') + 10);
+  else
+    (*ret) = (*ret << 4) | (c - '0');
+
+  mangled += 2;
+
+  return mangled;
+}
+
+/* Extract the function calling convention from MANGLED and
+   return 1 on success or 0 on failure.  */
+static int
+dlang_call_convention_p (const char *mangled)
+{
+  switch (*mangled)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R': case 'Y':
+      return 1;
+
+    default:
+      return 0;
+    }
+}
+
+/* Demangle the calling convention from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_call_convention (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'F': /* (D) */
+      mangled++;
+      break;
+    case 'U': /* (C) */
+      mangled++;
+      string_append (decl, "extern(C) ");
+      break;
+    case 'W': /* (Windows) */
+      mangled++;
+      string_append (decl, "extern(Windows) ");
+      break;
+    case 'V': /* (Pascal) */
+      mangled++;
+      string_append (decl, "extern(Pascal) ");
+      break;
+    case 'R': /* (C++) */
+      mangled++;
+      string_append (decl, "extern(C++) ");
+      break;
+    case 'Y': /* (Objective-C) */
+      mangled++;
+      string_append (decl, "extern(Objective-C) ");
+      break;
+    default:
+      return NULL;
+    }
+
+  return mangled;
+}
+
+/* Extract the type modifiers from MANGLED and append them to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_type_modifiers (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'x': /* const */
+      mangled++;
+      string_append (decl, " const");
+      return mangled;
+    case 'y': /* immutable */
+      mangled++;
+      string_append (decl, " immutable");
+      return mangled;
+    case 'O': /* shared */
+      mangled++;
+      string_append (decl, " shared");
+      return dlang_type_modifiers (decl, mangled);
+    case 'N':
+      mangled++;
+      if (*mangled == 'g') /* wild */
+	{
+	  mangled++;
+	  string_append (decl, " inout");
+	  return dlang_type_modifiers (decl, mangled);
+	}
+      else
+	return NULL;
+
+    default:
+      return mangled;
+    }
+}
+
+/* Demangle the D function attributes from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_attributes (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  while (*mangled == 'N')
+    {
+      mangled++;
+      switch (*mangled)
+	{
+	case 'a': /* pure */
+	  mangled++;
+	  string_append (decl, "pure ");
+	  continue;
+	case 'b': /* nothrow */
+	  mangled++;
+	  string_append (decl, "nothrow ");
+	  continue;
+	case 'c': /* ref */
+	  mangled++;
+	  string_append (decl, "ref ");
+	  continue;
+	case 'd': /* @property */
+	  mangled++;
+	  string_append (decl, "@property ");
+	  continue;
+	case 'e': /* @trusted */
+	  mangled++;
+	  string_append (decl, "@trusted ");
+	  continue;
+	case 'f': /* @safe */
+	  mangled++;
+	  string_append (decl, "@safe ");
+	  continue;
+	case 'g':
+	case 'h':
+	case 'k':
+	  /* inout parameter is represented as 'Ng'.
+	     vector parameter is represented as 'Nh'.
+	     return paramenter is represented as 'Nk'.
+	     If we see this, then we know we're really in the
+	     parameter list.  Rewind and break.  */
+	  mangled--;
+	  break;
+	case 'i': /* @nogc */
+	  mangled++;
+	  string_append (decl, "@nogc ");
+	  continue;
+	case 'j': /* return */
+	  mangled++;
+	  string_append (decl, "return ");
+	  continue;
+	case 'l': /* scope */
+	  mangled++;
+	  string_append (decl, "scope ");
+	  continue;
+
+	default: /* unknown attribute */
+	  return NULL;
+	}
+      break;
+    }
+
+  return mangled;
+}
+
+/* Demangle the function type from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_function_type (string *decl, const char *mangled)
+{
+  string attr, args, type;
+  size_t szattr, szargs, sztype;
+
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  /* The order of the mangled string is:
+	CallConvention FuncAttrs Arguments ArgClose Type
+
+     The demangled string is re-ordered as:
+	CallConvention Type Arguments FuncAttrs
+   */
+  string_init (&attr);
+  string_init (&args);
+  string_init (&type);
+
+  /* Function call convention.  */
+  mangled = dlang_call_convention (decl, mangled);
+
+  /* Function attributes.  */
+  mangled = dlang_attributes (&attr, mangled);
+  szattr = string_length (&attr);
+
+  /* Function arguments.  */
+  mangled = dlang_function_args (&args, mangled);
+  szargs = string_length (&args);
+
+  /* Function return type.  */
+  mangled = dlang_type (&type, mangled);
+  sztype = string_length (&type);
+
+  /* Append to decl in order. */
+  string_appendn (decl, type.b, sztype);
+  string_append (decl, "(");
+  string_appendn (decl, args.b, szargs);
+  string_append (decl, ") ");
+  string_appendn (decl, attr.b, szattr);
+
+  string_delete (&attr);
+  string_delete (&args);
+  string_delete (&type);
+  return mangled;
+}
+
+/* Demangle the argument list from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_function_args (string *decl, const char *mangled)
+{
+  size_t n = 0;
+
+  while (mangled && *mangled != '\0')
+    {
+      switch (*mangled)
+	{
+	case 'X': /* (variadic T t...) style.  */
+	  mangled++;
+	  string_append (decl, "...");
+	  return mangled;
+	case 'Y': /* (variadic T t, ...) style.  */
+	  mangled++;
+	  if (n != 0)
+	    string_append (decl, ", ");
+	  string_append (decl, "...");
+	  return mangled;
+	case 'Z': /* Normal function.  */
+	  mangled++;
+	  return mangled;
+	}
+
+      if (n++)
+	string_append (decl, ", ");
+
+      if (*mangled == 'M') /* scope(T) */
+	{
+	  mangled++;
+	  string_append (decl, "scope ");
+	}
+
+      if (mangled[0] == 'N' && mangled[1] == 'k') /* return(T) */
+	{
+	  mangled += 2;
+	  string_append (decl, "return ");
+	}
+
+      switch (*mangled)
+	{
+	case 'J': /* out(T) */
+	  mangled++;
+	  string_append (decl, "out ");
+	  break;
+	case 'K': /* ref(T) */
+	  mangled++;
+	  string_append (decl, "ref ");
+	  break;
+	case 'L': /* lazy(T) */
+	  mangled++;
+	  string_append (decl, "lazy ");
+	  break;
+	}
+      mangled = dlang_type (decl, mangled);
+    }
+
+  return mangled;
+}
+
+/* Demangle the type from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_type (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+    case 'O': /* shared(T) */
+      mangled++;
+      string_append (decl, "shared(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'x': /* const(T) */
+      mangled++;
+      string_append (decl, "const(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'y': /* immutable(T) */
+      mangled++;
+      string_append (decl, "immutable(");
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, ")");
+      return mangled;
+    case 'N':
+      mangled++;
+      if (*mangled == 'g') /* wild(T) */
+	{
+	  mangled++;
+	  string_append (decl, "inout(");
+	  mangled = dlang_type (decl, mangled);
+	  string_append (decl, ")");
+	  return mangled;
+	}
+      else if (*mangled == 'h') /* vector(T) */
+	{
+	  mangled++;
+	  string_append (decl, "__vector(");
+	  mangled = dlang_type (decl, mangled);
+	  string_append (decl, ")");
+	  return mangled;
+	}
+      else
+	return NULL;
+    case 'A': /* dynamic array (T[]) */
+      mangled++;
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[]");
+      return mangled;
+    case 'G': /* static array (T[N]) */
+    {
+      const char *numptr;
+      size_t num = 0;
+      mangled++;
+
+      numptr = mangled;
+      while (ISDIGIT (*mangled))
+	{
+	  num++;
+	  mangled++;
+	}
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[");
+      string_appendn (decl, numptr, num);
+      string_append (decl, "]");
+      return mangled;
+    }
+    case 'H': /* associative array (T[T]) */
+    {
+      string type;
+      size_t sztype;
+      mangled++;
+
+      string_init (&type);
+      mangled = dlang_type (&type, mangled);
+      sztype = string_length (&type);
+
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "[");
+      string_appendn (decl, type.b, sztype);
+      string_append (decl, "]");
+
+      string_delete (&type);
+      return mangled;
+    }
+    case 'P': /* pointer (T*) */
+      mangled++;
+      if (!dlang_call_convention_p (mangled))
+	{
+	  mangled = dlang_type (decl, mangled);
+	  string_append (decl, "*");
+	  return mangled;
+	}
+      /* Fall through */
+    case 'F': /* function T (D) */
+    case 'U': /* function T (C) */
+    case 'W': /* function T (Windows) */
+    case 'V': /* function T (Pascal) */
+    case 'R': /* function T (C++) */
+    case 'Y': /* function T (Objective-C) */
+      /* Function pointer types don't include the trailing asterisk.  */
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "function");
+      return mangled;
+    case 'I': /* ident T */
+    case 'C': /* class T */
+    case 'S': /* struct T */
+    case 'E': /* enum T */
+    case 'T': /* typedef T */
+      mangled++;
+      return dlang_parse_qualified (decl, mangled, dlang_type_name);
+    case 'D': /* delegate T */
+    {
+      string mods;
+      size_t szmods;
+      mangled++;
+
+      string_init (&mods);
+      mangled = dlang_type_modifiers (&mods, mangled);
+      szmods = string_length (&mods);
+
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "delegate");
+      string_appendn (decl, mods.b, szmods);
+
+      string_delete (&mods);
+      return mangled;
+    }
+    case 'B': /* tuple T */
+      mangled++;
+      return dlang_parse_tuple (decl, mangled);
+
+    /* Basic types */
+    case 'n':
+      mangled++;
+      string_append (decl, "none");
+      return mangled;
+    case 'v':
+      mangled++;
+      string_append (decl, "void");
+      return mangled;
+    case 'g':
+      mangled++;
+      string_append (decl, "byte");
+      return mangled;
+    case 'h':
+      mangled++;
+      string_append (decl, "ubyte");
+      return mangled;
+    case 's':
+      mangled++;
+      string_append (decl, "short");
+      return mangled;
+    case 't':
+      mangled++;
+      string_append (decl, "ushort");
+      return mangled;
+    case 'i':
+      mangled++;
+      string_append (decl, "int");
+      return mangled;
+    case 'k':
+      mangled++;
+      string_append (decl, "uint");
+      return mangled;
+    case 'l':
+      mangled++;
+      string_append (decl, "long");
+      return mangled;
+    case 'm':
+      mangled++;
+      string_append (decl, "ulong");
+      return mangled;
+    case 'f':
+      mangled++;
+      string_append (decl, "float");
+      return mangled;
+    case 'd':
+      mangled++;
+      string_append (decl, "double");
+      return mangled;
+    case 'e':
+      mangled++;
+      string_append (decl, "real");
+      return mangled;
+
+    /* Imaginary and Complex types */
+    case 'o':
+      mangled++;
+      string_append (decl, "ifloat");
+      return mangled;
+    case 'p':
+      mangled++;
+      string_append (decl, "idouble");
+      return mangled;
+    case 'j':
+      mangled++;
+      string_append (decl, "ireal");
+      return mangled;
+    case 'q':
+      mangled++;
+      string_append (decl, "cfloat");
+      return mangled;
+    case 'r':
+      mangled++;
+      string_append (decl, "cdouble");
+      return mangled;
+    case 'c':
+      mangled++;
+      string_append (decl, "creal");
+      return mangled;
+
+    /* Other types */
+    case 'b':
+      mangled++;
+      string_append (decl, "bool");
+      return mangled;
+    case 'a':
+      mangled++;
+      string_append (decl, "char");
+      return mangled;
+    case 'u':
+      mangled++;
+      string_append (decl, "wchar");
+      return mangled;
+    case 'w':
+      mangled++;
+      string_append (decl, "dchar");
+      return mangled;
+    case 'z':
+      mangled++;
+      switch (*mangled)
+	{
+	case 'i':
+	  mangled++;
+	  string_append (decl, "cent");
+	  return mangled;
+	case 'k':
+	  mangled++;
+	  string_append (decl, "ucent");
+	  return mangled;
+	}
+      return NULL;
+
+    default: /* unhandled */
+      return NULL;
+    }
+}
+
+/* Extract the identifier from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_identifier (string *decl, const char *mangled,
+		  enum dlang_symbol_kinds kind)
+{
+  long len;
+  const char *endptr = dlang_number (mangled, &len);
+
+  if (endptr == NULL || len == 0)
+    return NULL;
+
+  /* In template parameter symbols, the first character of the mangled
+     name can be a digit.  This causes ambiguity issues because the
+     digits of the two numbers are adjacent.  */
+  if (kind == dlang_template_param)
+    {
+      long psize = len;
+      const char *pend;
+      int saved = string_length (decl);
+
+      /* Work backwards until a match is found.  */
+      for (pend = endptr; endptr != NULL; pend--)
+	{
+	  mangled = pend;
+
+	  /* Reached the beginning of the pointer to the name length,
+	     try parsing the entire symbol.  */
+	  if (psize == 0)
+	    {
+	      psize = len;
+	      pend = endptr;
+	      endptr = NULL;
+	    }
+
+	  /* Check whether template parameter is a function with a valid
+	     return type or an untyped identifier.  */
+	  if (ISDIGIT (*mangled))
+	    mangled = dlang_parse_qualified (decl, mangled,
+					     dlang_template_ident);
+	  else if (strncmp (mangled, "_D", 2) == 0)
+	    mangled = dlang_parse_mangle (decl, mangled, dlang_function);
+
+	  /* Check for name length mismatch.  */
+	  if (mangled && (mangled - pend) == psize)
+	    return mangled;
+
+	  psize /= 10;
+	  string_setlength (decl, saved);
+	}
+
+      /* No match on any combinations.  */
+      return NULL;
+    }
+  else
+    {
+      if (strlen (endptr) < (size_t) len)
+	return NULL;
+
+      mangled = endptr;
+
+      /* May be a template instance.  */
+      if (len >= 5 && mangled[0] == '_' && mangled[1] == '_'
+	  && (mangled[2] == 'T' || mangled[2] == 'U'))
+	return dlang_parse_template (decl, mangled, len);
+
+      switch (len)
+	{
+	case 6:
+	  if (strncmp (mangled, "__ctor", len) == 0)
+	    {
+	      /* Constructor symbol for a class/struct.  */
+	      string_append (decl, "this");
+	      mangled += len;
+	      return mangled;
+	    }
+	  else if (strncmp (mangled, "__dtor", len) == 0)
+	    {
+	      /* Destructor symbol for a class/struct.  */
+	      string_append (decl, "~this");
+	      mangled += len;
+	      return mangled;
+	    }
+	  else if (strncmp (mangled, "__initZ", len+1) == 0)
+	    {
+	      /* The static initialiser for a given symbol.  */
+	      string_prepend (decl, "initializer for ");
+	      string_setlength (decl, string_length (decl) - 1);
+	      mangled += len;
+	      return mangled;
+	    }
+	  else if (strncmp (mangled, "__vtblZ", len+1) == 0)
+	    {
+	      /* The vtable symbol for a given class.  */
+	      string_prepend (decl, "vtable for ");
+	      string_setlength (decl, string_length (decl) - 1);
+	      mangled += len;
+	      return mangled;
+	    }
+	  break;
+
+	case 7:
+	  if (strncmp (mangled, "__ClassZ", len+1) == 0)
+	    {
+	      /* The classinfo symbol for a given class.  */
+	      string_prepend (decl, "ClassInfo for ");
+	      string_setlength (decl, string_length (decl) - 1);
+	      mangled += len;
+	      return mangled;
+	    }
+	  break;
+
+	case 10:
+	  if (strncmp (mangled, "__postblitMFZ", len+3) == 0)
+	    {
+	      /* Postblit symbol for a struct.  */
+	      string_append (decl, "this(this)");
+	      mangled += len + 3;
+	      return mangled;
+	    }
+	  break;
+
+	case 11:
+	  if (strncmp (mangled, "__InterfaceZ", len+1) == 0)
+	    {
+	      /* The interface symbol for a given class.  */
+	      string_prepend (decl, "Interface for ");
+	      string_setlength (decl, string_length (decl) - 1);
+	      mangled += len;
+	      return mangled;
+	    }
+	  break;
+
+	case 12:
+	  if (strncmp (mangled, "__ModuleInfoZ", len+1) == 0)
+	    {
+	      /* The ModuleInfo symbol for a given module.  */
+	      string_prepend (decl, "ModuleInfo for ");
+	      string_setlength (decl, string_length (decl) - 1);
+	      mangled += len;
+	      return mangled;
+	    }
+	  break;
+	}
+
+      string_appendn (decl, mangled, len);
+      mangled += len;
+    }
+
+  return mangled;
+}
+
+/* Extract the integer value from MANGLED and append it to DECL,
+   where TYPE is the type it should be represented as.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_integer (string *decl, const char *mangled, char type)
+{
+  if (type == 'a' || type == 'u' || type == 'w')
+    {
+      /* Parse character value.  */
+      char value[10];
+      int pos = 10;
+      int width = 0;
+      long val;
+
+      mangled = dlang_number (mangled, &val);
+      if (mangled == NULL)
+	return NULL;
+
+      string_append (decl, "'");
+
+      if (type == 'a' && val >= 0x20 && val < 0x7F)
+	{
+	  /* Represent as a character literal.  */
+	  char c = (char) val;
+	  string_appendn (decl, &c, 1);
+	}
+      else
+	{
+	  /* Represent as a hexadecimal value.  */
+	  switch (type)
+	    {
+	    case 'a': /* char */
+	      string_append (decl, "\\x");
+	      width = 2;
+	      break;
+	    case 'u': /* wchar */
+	      string_append (decl, "\\u");
+	      width = 4;
+	      break;
+	    case 'w': /* dchar */
+	      string_append (decl, "\\U");
+	      width = 8;
+	      break;
+	    }
+
+	  while (val > 0)
+	    {
+	      int digit = val % 16;
+
+	      if (digit < 10)
+		value[--pos] = (char)(digit + '0');
+	      else
+		value[--pos] = (char)((digit - 10) + 'a');
+
+	      val /= 16;
+	      width--;
+	    }
+
+	  for (; width > 0; width--)
+	    value[--pos] = '0';
+
+	  string_appendn (decl, &(value[pos]), 10 - pos);
+	}
+      string_append (decl, "'");
+    }
+  else if (type == 'b')
+    {
+      /* Parse boolean value.  */
+      long val;
+
+      mangled = dlang_number (mangled, &val);
+      if (mangled == NULL)
+	return NULL;
+
+      string_append (decl, val ? "true" : "false");
+    }
+  else
+    {
+      /* Parse integer value.  */
+      const char *numptr = mangled;
+      size_t num = 0;
+
+      if (! ISDIGIT (*mangled))
+	return NULL;
+
+      while (ISDIGIT (*mangled))
+	{
+	  num++;
+	  mangled++;
+	}
+      string_appendn (decl, numptr, num);
+
+      /* Append suffix.  */
+      switch (type)
+	{
+	case 'h': /* ubyte */
+	case 't': /* ushort */
+	case 'k': /* uint */
+	  string_append (decl, "u");
+	  break;
+	case 'l': /* long */
+	  string_append (decl, "L");
+	  break;
+	case 'm': /* ulong */
+	  string_append (decl, "uL");
+	  break;
+	}
+    }
+
+  return mangled;
+}
+
+/* Extract the floating-point value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_real (string *decl, const char *mangled)
+{
+  /* Handle NAN and +-INF.  */
+  if (strncmp (mangled, "NAN", 3) == 0)
+    {
+      string_append (decl, "NaN");
+      mangled += 3;
+      return mangled;
+    }
+  else if (strncmp (mangled, "INF", 3) == 0)
+    {
+      string_append (decl, "Inf");
+      mangled += 3;
+      return mangled;
+    }
+  else if (strncmp (mangled, "NINF", 4) == 0)
+    {
+      string_append (decl, "-Inf");
+      mangled += 4;
+      return mangled;
+    }
+
+  /* Hexadecimal prefix and leading bit.  */
+  if (*mangled == 'N')
+    {
+      string_append (decl, "-");
+      mangled++;
+    }
+
+  if (!ISXDIGIT (*mangled))
+    return NULL;
+
+  string_append (decl, "0x");
+  string_appendn (decl, mangled, 1);
+  string_append (decl, ".");
+  mangled++;
+
+  /* Significand.  */
+  while (ISXDIGIT (*mangled))
+    {
+      string_appendn (decl, mangled, 1);
+      mangled++;
+    }
+
+  /* Exponent.  */
+  if (*mangled != 'P')
+    return NULL;
+
+  string_append (decl, "p");
+  mangled++;
+
+  if (*mangled == 'N')
+    {
+      string_append (decl, "-");
+      mangled++;
+    }
+
+  while (ISDIGIT (*mangled))
+    {
+      string_appendn (decl, mangled, 1);
+      mangled++;
+    }
+
+  return mangled;
+}
+
+/* Extract the string value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_string (string *decl, const char *mangled)
+{
+  char type = *mangled;
+  long len;
+
+  mangled++;
+  mangled = dlang_number (mangled, &len);
+  if (mangled == NULL || *mangled != '_')
+    return NULL;
+
+  mangled++;
+  string_append (decl, "\"");
+  while (len--)
+    {
+      char val;
+      const char *endptr = dlang_hexdigit (mangled, &val);
+
+      if (endptr == NULL)
+	return NULL;
+
+      /* Sanitize white and non-printable characters.  */
+      switch (val)
+	{
+	case ' ':
+	  string_append (decl, " ");
+	  break;
+	case '\t':
+	  string_append (decl, "\\t");
+	  break;
+	case '\n':
+	  string_append (decl, "\\n");
+	  break;
+	case '\r':
+	  string_append (decl, "\\r");
+	  break;
+	case '\f':
+	  string_append (decl, "\\f");
+	  break;
+	case '\v':
+	  string_append (decl, "\\v");
+	  break;
+
+	default:
+	  if (ISPRINT (val))
+	    string_appendn (decl, &val, 1);
+	  else
+	    {
+	      string_append (decl, "\\x");
+	      string_appendn (decl, mangled, 2);
+	    }
+	}
+
+      mangled = endptr;
+    }
+  string_append (decl, "\"");
+
+  if (type != 'a')
+    string_appendn (decl, &type, 1);
+
+  return mangled;
+}
+
+/* Extract the static array value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_arrayliteral (string *decl, const char *mangled)
+{
+  long elements;
+
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
+    return NULL;
+
+  string_append (decl, "[");
+  while (elements--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      if (elements != 0)
+	string_append (decl, ", ");
+    }
+
+  string_append (decl, "]");
+  return mangled;
+}
+
+/* Extract the associative array value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_assocarray (string *decl, const char *mangled)
+{
+  long elements;
+
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
+    return NULL;
+
+  string_append (decl, "[");
+  while (elements--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      string_append (decl, ":");
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+
+      if (elements != 0)
+	string_append (decl, ", ");
+    }
+
+  string_append (decl, "]");
+  return mangled;
+}
+
+/* Extract the struct literal value for NAME from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_structlit (string *decl, const char *mangled, const char *name)
+{
+  long args;
+
+  mangled = dlang_number (mangled, &args);
+  if (mangled == NULL)
+    return NULL;
+
+  if (name != NULL)
+    string_append (decl, name);
+
+  string_append (decl, "(");
+  while (args--)
+    {
+      mangled = dlang_value (decl, mangled, NULL, '\0');
+      if (args != 0)
+	string_append (decl, ", ");
+    }
+
+  string_append (decl, ")");
+  return mangled;
+}
+
+/* Extract the value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_value (string *decl, const char *mangled, const char *name, char type)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  switch (*mangled)
+    {
+      /* Null value.  */
+    case 'n':
+      mangled++;
+      string_append (decl, "null");
+      break;
+
+      /* Integral values.  */
+    case 'N':
+      mangled++;
+      string_append (decl, "-");
+      mangled = dlang_parse_integer (decl, mangled, type);
+      break;
+
+    case 'i':
+      mangled++;
+      /* Fall through */
+
+      /* There really should always be an `i' before encoded numbers, but there
+	 wasn't in early versions of D2, so this case range must remain for
+	 backwards compatibility.  */
+    case '0': case '1': case '2': case '3': case '4':
+    case '5': case '6': case '7': case '8': case '9':
+      mangled = dlang_parse_integer (decl, mangled, type);
+      break;
+
+      /* Real value.  */
+    case 'e':
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      break;
+
+      /* Complex value.  */
+    case 'c':
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      string_append (decl, "+");
+      if (mangled == NULL || *mangled != 'c')
+	return NULL;
+      mangled++;
+      mangled = dlang_parse_real (decl, mangled);
+      string_append (decl, "i");
+      break;
+
+      /* String values.  */
+    case 'a': /* UTF8 */
+    case 'w': /* UTF16 */
+    case 'd': /* UTF32 */
+      mangled = dlang_parse_string (decl, mangled);
+      break;
+
+      /* Array values.  */
+    case 'A':
+      mangled++;
+      if (type == 'H')
+	mangled = dlang_parse_assocarray (decl, mangled);
+      else
+	mangled = dlang_parse_arrayliteral (decl, mangled);
+      break;
+
+      /* Struct values.  */
+    case 'S':
+      mangled++;
+      mangled = dlang_parse_structlit (decl, mangled, name);
+      break;
+
+    default:
+      return NULL;
+    }
+
+  return mangled;
+}
+
+/* Extract and demangle the symbol in MANGLED and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_parse_mangle (string *decl, const char *mangled,
+		    enum dlang_symbol_kinds kind)
+{
+  /* A D mangled symbol is comprised of both scope and type information.
+
+	MangleName:
+	    _D QualifiedName Type
+	    _D QualifiedName M Type
+	    _D QualifiedName Z
+	    ^
+     The caller should have guaranteed that the start pointer is at the
+     above location.
+   */
+  mangled += 2;
+
+  mangled = dlang_parse_qualified (decl, mangled, dlang_top_level);
+
+  if (mangled != NULL)
+    {
+      /* Artificial symbols end with 'Z' and have no type.  */
+      if (*mangled == 'Z')
+	mangled++;
+      else
+	{
+	  string mods;
+	  int saved;
+
+	  /* Skip over 'this' parameter.  */
+	  if (*mangled == 'M')
+	    mangled++;
+
+	  /* Save the type modifiers for appending at the end if needed.  */
+	  string_init (&mods);
+	  mangled = dlang_type_modifiers (&mods, mangled);
+
+	  if (mangled && dlang_call_convention_p (mangled))
+	    {
+	      /* Skip over calling convention and attributes.  */
+	      saved = string_length (decl);
+	      mangled = dlang_call_convention (decl, mangled);
+	      mangled = dlang_attributes (decl, mangled);
+	      string_setlength (decl, saved);
+
+	      string_append (decl, "(");
+	      mangled = dlang_function_args (decl, mangled);
+	      string_append (decl, ")");
+
+	      /* Add any const/immutable/shared modifier. */
+	      string_appendn (decl, mods.b, string_length (&mods));
+	    }
+
+	  /* Consume the decl type of symbol.  */
+	  saved = string_length (decl);
+	  mangled = dlang_type (decl, mangled);
+	  string_setlength (decl, saved);
+
+	  string_delete (&mods);
+	}
+    }
+
+  /* Check that the entire symbol was successfully demangled.  */
+  if (kind == dlang_top_level)
+    {
+      if (mangled == NULL || *mangled != '\0')
+	return NULL;
+    }
+
+  return mangled;
+}
+
+/* Extract and demangle the qualified symbol in MANGLED and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_parse_qualified (string *decl, const char *mangled,
+		       enum dlang_symbol_kinds kind)
+{
+  /* Qualified names are identifiers separated by their encoded length.
+     Nested functions also encode their argument types without specifying
+     what they return.
+
+	QualifiedName:
+	    SymbolName
+	    SymbolName QualifiedName
+	    SymbolName TypeFunctionNoReturn QualifiedName
+	    SymbolName M TypeModifiers TypeFunctionNoReturn QualifiedName
+	    ^
+     The start pointer should be at the above location.
+   */
+  size_t n = 0;
+  do
+    {
+      if (n++)
+	string_append (decl, ".");
+
+      /* Skip over anonymous symbols.  */
+      while (*mangled == '0')
+	mangled++;
+
+      mangled = dlang_identifier (decl, mangled, kind);
+
+      /* Consume the encoded arguments.  However if this is not followed by the
+	 next encoded length, then this is not a continuation of a qualified
+	 name, in which case we backtrack and return the current unconsumed
+	 position of the mangled decl.  */
+      if (mangled && (*mangled == 'M' || dlang_call_convention_p (mangled)))
+	{
+	  const char *start = mangled;
+	  int saved = string_length (decl);
+
+	  /* Skip over 'this' parameter and type modifiers.  */
+	  if (*mangled == 'M')
+	    {
+	      mangled++;
+	      mangled = dlang_type_modifiers (decl, mangled);
+	      string_setlength (decl, saved);
+	    }
+
+	  /* The rule we expect to match in the mangled string is:
+
+		TypeFunctionNoReturn:
+		    CallConvention FuncAttrs Arguments ArgClose
+
+	     The calling convention and function attributes are not included
+	     in the demangled string.  */
+	  mangled = dlang_call_convention (decl, mangled);
+	  mangled = dlang_attributes (decl, mangled);
+	  string_setlength (decl, saved);
+
+	  string_append (decl, "(");
+	  mangled = dlang_function_args (decl, mangled);
+	  string_append (decl, ")");
+
+	  if (mangled == NULL || !ISDIGIT (*mangled))
+	    {
+	      /* Did not match the rule we were looking for.  */
+	      mangled = start;
+	      string_setlength (decl, saved);
+	    }
+	}
+    }
+  while (mangled && ISDIGIT (*mangled));
+
+  return mangled;
+}
+
+/* Demangle the tuple from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_parse_tuple (string *decl, const char *mangled)
+{
+  long elements;
+
+  mangled = dlang_number (mangled, &elements);
+  if (mangled == NULL)
+    return NULL;
+
+  string_append (decl, "Tuple!(");
+
+  while (elements--)
+    {
+      mangled = dlang_type (decl, mangled);
+      if (elements != 0)
+	string_append (decl, ", ");
+    }
+
+  string_append (decl, ")");
+  return mangled;
+}
+
+/* Demangle the argument list from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+dlang_template_args (string *decl, const char *mangled)
+{
+  size_t n = 0;
+
+  while (mangled && *mangled != '\0')
+    {
+      switch (*mangled)
+	{
+	case 'Z': /* End of parameter list.  */
+	  mangled++;
+	  return mangled;
+	}
+
+      if (n++)
+	string_append (decl, ", ");
+
+      /* Skip over specialised template prefix.  */
+      if (*mangled == 'H')
+	mangled++;
+
+      switch (*mangled)
+	{
+	case 'S': /* Symbol parameter.  */
+	  mangled++;
+	  mangled = dlang_identifier (decl, mangled, dlang_template_param);
+	  break;
+	case 'T': /* Type parameter.  */
+	  mangled++;
+	  mangled = dlang_type (decl, mangled);
+	  break;
+	case 'V': /* Value parameter.  */
+	{
+	  string name;
+	  char type;
+
+	  /* Peek at the type.  */
+	  mangled++;
+	  type = *mangled;
+
+	  /* In the few instances where the type is actually desired in
+	     the output, it should precede the value from dlang_value.  */
+	  string_init (&name);
+	  mangled = dlang_type (&name, mangled);
+	  string_need (&name, 1);
+	  *(name.p) = '\0';
+
+	  mangled = dlang_value (decl, mangled, name.b, type);
+	  string_delete (&name);
+	  break;
+	}
+
+	default:
+	  return NULL;
+	}
+    }
+
+  return mangled;
+}
+
+/* Extract and demangle the template symbol in MANGLED, expected to
+   be made up of LEN characters, and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+static const char *
+dlang_parse_template (string *decl, const char *mangled, long len)
+{
+  const char *start = mangled;
+
+  /* Template instance names have the types and values of its parameters
+     encoded into it.
+
+	TemplateInstanceName:
+	    Number __T LName TemplateArgs Z
+	    Number __U LName TemplateArgs Z
+		   ^
+     The start pointer should be at the above location, and LEN should be
+     the value of the decoded number.
+   */
+
+  /* Template symbol.  */
+  if (!ISDIGIT (mangled[3]) || mangled[3] == '0')
+    return NULL;
+
+  mangled += 3;
+
+  /* Template identifier.  */
+  mangled = dlang_identifier (decl, mangled, dlang_template_ident);
+
+  /* Template arguments.  */
+  string_append (decl, "!(");
+  mangled = dlang_template_args (decl, mangled);
+  string_append (decl, ")");
+
+  /* Check for template name length mismatch.  */
+  if (mangled && (mangled - start) != len)
+    return NULL;
+
+  return mangled;
+}
+
+/* Extract and demangle the symbol in MANGLED.  Returns the demangled
+   signature on success or NULL on failure.  */
+
+char *
+dlang_demangle (const char *mangled, int option ATTRIBUTE_UNUSED)
+{
+  string decl;
+  char *demangled = NULL;
+
+  if (mangled == NULL || *mangled == '\0')
+    return NULL;
+
+  if (strncmp (mangled, "_D", 2) != 0)
+    return NULL;
+
+  string_init (&decl);
+
+  if (strcmp (mangled, "_Dmain") == 0)
+    {
+      string_append (&decl, "D main");
+    }
+  else
+    {
+      if (dlang_parse_mangle (&decl, mangled, dlang_top_level) == NULL)
+	string_delete (&decl);
+    }
+
+  if (string_length (&decl) > 0)
+    {
+      string_need (&decl, 1);
+      *(decl.p) = '\0';
+      demangled = decl.b;
+    }
+
+  return demangled;
+}
+
diff --git a/rtemstoolkit/libiberty/demangle.h b/rtemstoolkit/libiberty/demangle.h
index 4b3565b..996203b 100644
--- a/rtemstoolkit/libiberty/demangle.h
+++ b/rtemstoolkit/libiberty/demangle.h
@@ -1,7 +1,6 @@
 /* Defs for interface to demanglers.
-   Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002,
-   2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
-   
+   Copyright (C) 1992-2017 Free Software Foundation, Inc.
+
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public License
    as published by the Free Software Foundation; either version 2, or
@@ -45,7 +44,13 @@ extern "C" {
 #define DMGL_VERBOSE	 (1 << 3)	/* Include implementation details.  */
 #define DMGL_TYPES	 (1 << 4)	/* Also try to demangle type encodings.  */
 #define DMGL_RET_POSTFIX (1 << 5)       /* Print function return types (when
-                                           present) after function signature */
+					   present) after function signature.
+					   It applies only to the toplevel
+					   function type.  */
+#define DMGL_RET_DROP	 (1 << 6)       /* Suppress printing function return
+					   types, even if present.  It applies
+					   only to the toplevel function type.
+					   */
 
 #define DMGL_AUTO	 (1 << 8)
 #define DMGL_GNU	 (1 << 9)
@@ -57,9 +62,11 @@ extern "C" {
 #define DMGL_EDG	 (1 << 13)
 #define DMGL_GNU_V3	 (1 << 14)
 #define DMGL_GNAT	 (1 << 15)
+#define DMGL_DLANG	 (1 << 16)
+#define DMGL_RUST	 (1 << 17)	/* Rust wraps GNU_V3 style mangling.  */
 
 /* If none of these are set, use 'current_demangling_style' as the default. */
-#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT)
+#define DMGL_STYLE_MASK (DMGL_AUTO|DMGL_GNU|DMGL_LUCID|DMGL_ARM|DMGL_HP|DMGL_EDG|DMGL_GNU_V3|DMGL_JAVA|DMGL_GNAT|DMGL_DLANG|DMGL_RUST)
 
 /* Enumeration of possible demangling styles.
 
@@ -81,7 +88,9 @@ extern enum demangling_styles
   edg_demangling = DMGL_EDG,
   gnu_v3_demangling = DMGL_GNU_V3,
   java_demangling = DMGL_JAVA,
-  gnat_demangling = DMGL_GNAT
+  gnat_demangling = DMGL_GNAT,
+  dlang_demangling = DMGL_DLANG,
+  rust_demangling = DMGL_RUST
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
@@ -96,6 +105,8 @@ extern enum demangling_styles
 #define GNU_V3_DEMANGLING_STYLE_STRING        "gnu-v3"
 #define JAVA_DEMANGLING_STYLE_STRING          "java"
 #define GNAT_DEMANGLING_STYLE_STRING          "gnat"
+#define DLANG_DEMANGLING_STYLE_STRING         "dlang"
+#define RUST_DEMANGLING_STYLE_STRING          "rust"
 
 /* Some macros to test what demangling style is active. */
 
@@ -109,6 +120,8 @@ extern enum demangling_styles
 #define GNU_V3_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNU_V3)
 #define JAVA_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_JAVA)
 #define GNAT_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_GNAT)
+#define DLANG_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_DLANG)
+#define RUST_DEMANGLING (((int) CURRENT_DEMANGLING_STYLE) & DMGL_RUST)
 
 /* Provide information about the available demangle styles. This code is
    pulled from gdb into libiberty because it is useful to binutils also.  */
@@ -134,10 +147,10 @@ cplus_mangle_opname (const char *opname, int options);
 extern void
 set_cplus_marker_for_demangling (int ch);
 
-extern enum demangling_styles 
+extern enum demangling_styles
 cplus_demangle_set_style (enum demangling_styles style);
 
-extern enum demangling_styles 
+extern enum demangling_styles
 cplus_demangle_name_to_style (const char *name);
 
 /* Callback typedef for allocation-less demangler interfaces. */
@@ -160,10 +173,42 @@ java_demangle_v3_callback (const char *mangled,
 extern char*
 java_demangle_v3 (const char *mangled);
 
+char *
+ada_demangle (const char *mangled, int options);
+
+extern char *
+dlang_demangle (const char *mangled, int options);
+
+/* Returns non-zero iff MANGLED is a rust mangled symbol.  MANGLED must
+   already have been demangled through cplus_demangle_v3.  If this function
+   returns non-zero then MANGLED can be demangled (in-place) using
+   RUST_DEMANGLE_SYM.  */
+extern int
+rust_is_mangled (const char *mangled);
+
+/* Demangles SYM (in-place) if RUST_IS_MANGLED returned non-zero for SYM.
+   If RUST_IS_MANGLED returned zero for SYM then RUST_DEMANGLE_SYM might
+   replace characters that cannot be demangled with '?' and might truncate
+   SYM.  After calling RUST_DEMANGLE_SYM SYM might be shorter, but never
+   larger.  */
+extern void
+rust_demangle_sym (char *sym);
+
+/* Demangles MANGLED if it was GNU_V3 and then RUST mangled, otherwise
+   returns NULL. Uses CPLUS_DEMANGLE_V3, RUST_IS_MANGLED and
+   RUST_DEMANGLE_SYM.  Returns a new string that is owned by the caller.  */
+extern char *
+rust_demangle (const char *mangled, int options);
+
 enum gnu_v3_ctor_kinds {
   gnu_v3_complete_object_ctor = 1,
   gnu_v3_base_object_ctor,
-  gnu_v3_complete_object_allocating_ctor
+  gnu_v3_complete_object_allocating_ctor,
+  /* These are not part of the V3 ABI.  Unified constructors are generated
+     as a speed-for-space optimization when the -fdeclone-ctor-dtor option
+     is used, and are always internal symbols.  */
+  gnu_v3_unified_ctor,
+  gnu_v3_object_ctor_group
 };
 
 /* Return non-zero iff NAME is the mangled form of a constructor name
@@ -177,7 +222,12 @@ extern enum gnu_v3_ctor_kinds
 enum gnu_v3_dtor_kinds {
   gnu_v3_deleting_dtor = 1,
   gnu_v3_complete_object_dtor,
-  gnu_v3_base_object_dtor
+  gnu_v3_base_object_dtor,
+  /* These are not part of the V3 ABI.  Unified destructors are generated
+     as a speed-for-space optimization when the -fdeclone-ctor-dtor option
+     is used, and are always internal symbols.  */
+  gnu_v3_unified_dtor,
+  gnu_v3_object_dtor_group
 };
 
 /* Return non-zero iff NAME is the mangled form of a destructor name
@@ -261,6 +311,9 @@ enum demangle_component_type
   /* A guard variable.  This has one subtree, the name for which this
      is a guard variable.  */
   DEMANGLE_COMPONENT_GUARD,
+  /* The init and wrapper functions for C++11 thread_local variables.  */
+  DEMANGLE_COMPONENT_TLS_INIT,
+  DEMANGLE_COMPONENT_TLS_WRAPPER,
   /* A reference temporary.  This has one subtree, the name for which
      this is a temporary.  */
   DEMANGLE_COMPONENT_REFTEMP,
@@ -288,6 +341,12 @@ enum demangle_component_type
   /* The const qualifier modifying a member function.  The one subtree
      is the type which is being qualified.  */
   DEMANGLE_COMPONENT_CONST_THIS,
+  /* C++11 A reference modifying a member function.  The one subtree is the
+     type which is being referenced.  */
+  DEMANGLE_COMPONENT_REFERENCE_THIS,
+  /* C++11: An rvalue reference modifying a member function.  The one
+     subtree is the type which is being referenced.  */
+  DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS,
   /* A vendor qualifier.  The left subtree is the type which is being
      qualified, and the right subtree is the name of the
      qualifier.  */
@@ -323,6 +382,9 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_PTRMEM_TYPE,
   /* A fixed-point type.  */
   DEMANGLE_COMPONENT_FIXED_TYPE,
+  /* A vector type.  The left subtree is the number of elements,
+     the right subtree is the element type.  */
+  DEMANGLE_COMPONENT_VECTOR_TYPE,
   /* An argument list.  The left subtree is the current argument, and
      the right subtree is either NULL or another ARGLIST node.  */
   DEMANGLE_COMPONENT_ARGLIST,
@@ -330,6 +392,9 @@ enum demangle_component_type
      template argument, and the right subtree is either NULL or
      another TEMPLATE_ARGLIST node.  */
   DEMANGLE_COMPONENT_TEMPLATE_ARGLIST,
+  /* An initializer list.  The left subtree is either an explicit type or
+     NULL, and the right subtree is a DEMANGLE_COMPONENT_ARGLIST.  */
+  DEMANGLE_COMPONENT_INITIALIZER_LIST,
   /* An operator.  This holds information about a standard
      operator.  */
   DEMANGLE_COMPONENT_OPERATOR,
@@ -339,6 +404,12 @@ enum demangle_component_type
   /* A typecast, represented as a unary operator.  The one subtree is
      the type to which the argument should be cast.  */
   DEMANGLE_COMPONENT_CAST,
+  /* A conversion operator, represented as a unary operator.  The one
+     subtree is the type to which the argument should be converted
+     to.  */
+  DEMANGLE_COMPONENT_CONVERSION,
+  /* A nullary expression.  The left subtree is the operator.  */
+  DEMANGLE_COMPONENT_NULLARY,
   /* A unary expression.  The left subtree is the operator, and the
      right subtree is the single argument.  */
   DEMANGLE_COMPONENT_UNARY,
@@ -375,14 +446,37 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_COMPOUND_NAME,
   /* A name formed by a single character.  */
   DEMANGLE_COMPONENT_CHARACTER,
+  /* A number.  */
+  DEMANGLE_COMPONENT_NUMBER,
   /* A decltype type.  */
   DEMANGLE_COMPONENT_DECLTYPE,
   /* Global constructors keyed to name.  */
   DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS,
   /* Global destructors keyed to name.  */
   DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS,
+  /* A lambda closure type.  */
+  DEMANGLE_COMPONENT_LAMBDA,
+  /* A default argument scope.  */
+  DEMANGLE_COMPONENT_DEFAULT_ARG,
+  /* An unnamed type.  */
+  DEMANGLE_COMPONENT_UNNAMED_TYPE,
+  /* A transactional clone.  This has one subtree, the encoding for
+     which it is providing alternative linkage.  */
+  DEMANGLE_COMPONENT_TRANSACTION_CLONE,
+  /* A non-transactional clone entry point.  In the i386/x86_64 abi,
+     the unmangled symbol of a tm_callable becomes a thunk and the
+     non-transactional function version is mangled thus.  */
+  DEMANGLE_COMPONENT_NONTRANSACTION_CLONE,
   /* A pack expansion.  */
-  DEMANGLE_COMPONENT_PACK_EXPANSION
+  DEMANGLE_COMPONENT_PACK_EXPANSION,
+  /* A name with an ABI tag.  */
+  DEMANGLE_COMPONENT_TAGGED_NAME,
+  /* A transaction-safe function type.  */
+  DEMANGLE_COMPONENT_TRANSACTION_SAFE,
+  /* A cloned function.  */
+  DEMANGLE_COMPONENT_CLONE,
+  DEMANGLE_COMPONENT_NOEXCEPT,
+  DEMANGLE_COMPONENT_THROW_SPEC
 };
 
 /* Types which are only used internally.  */
@@ -400,6 +494,11 @@ struct demangle_component
   /* The type of this component.  */
   enum demangle_component_type type;
 
+  /* Guard against recursive component printing.
+     Initialize to zero.  Private to d_print_comp.
+     All other fields are final after initialization.  */
+  int d_printing;
+
   union
   {
     /* For DEMANGLE_COMPONENT_NAME.  */
@@ -494,6 +593,14 @@ struct demangle_component
       struct demangle_component *right;
     } s_binary;
 
+    struct
+    {
+      /* subtree, same place as d_left.  */
+      struct demangle_component *sub;
+      /* integer.  */
+      int num;
+    } s_unary_num;
+
   } u;
 };
 
@@ -586,7 +693,7 @@ cplus_demangle_v3_components (const char *mangled, int options, void **mem);
 
 extern char *
 cplus_demangle_print (int options,
-                      const struct demangle_component *tree,
+                      struct demangle_component *tree,
                       int estimated_length,
                       size_t *p_allocated_size);
 
@@ -606,7 +713,7 @@ cplus_demangle_print (int options,
 
 extern int
 cplus_demangle_print_callback (int options,
-                               const struct demangle_component *tree,
+                               struct demangle_component *tree,
                                demangle_callbackref callback, void *opaque);
 
 #ifdef __cplusplus
diff --git a/rtemstoolkit/libiberty/environ.h b/rtemstoolkit/libiberty/environ.h
new file mode 100644
index 0000000..32bb0b1
--- /dev/null
+++ b/rtemstoolkit/libiberty/environ.h
@@ -0,0 +1,35 @@
+/* Declare the environ system variable.
+   Copyright (C) 2015-2017 Free Software Foundation, Inc.
+
+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.
+
+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,
+write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/* On OSX, the environ variable can be used directly in the code of an
+   executable, but cannot be used in the code of a shared library (such as
+   GCC's liblto_plugin, which links in libiberty code).  Instead, the
+   function _NSGetEnviron can be called to get the address of environ.  */
+
+#ifndef HAVE_ENVIRON_DECL
+#  ifdef __APPLE__
+#     include <crt_externs.h>
+#     define environ (*_NSGetEnviron ())
+#  else
+#    ifndef environ
+extern char **environ;
+#    endif
+#  endif
+#  define HAVE_ENVIRON_DECL
+#endif
diff --git a/rtemstoolkit/libiberty/libiberty.h b/rtemstoolkit/libiberty/libiberty.h
index d2dfb1b..a0cbbcf 100644
--- a/rtemstoolkit/libiberty/libiberty.h
+++ b/rtemstoolkit/libiberty/libiberty.h
@@ -1,7 +1,6 @@
 /* Function declarations for libiberty.
 
-   Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+   Copyright (C) 1997-2017 Free Software Foundation, Inc.
    
    Note - certain prototypes declared in this header file are for
    functions whoes implementation copyright does not belong to the
@@ -31,63 +30,118 @@
    missing on some operating systems.  We do not declare those here,
    to avoid conflicts with the system header files on operating
    systems that do support those functions.  In this file we only
-   declare those functions which are specific to libiberty. 
+   declare those functions which are specific to libiberty.  */
 
-  Hacked up libiberty.h file from the real one.
-*/
-
-#if !defined (_LIBIERTY_H_)
-#define _LIBIERTY_H_
+#ifndef LIBIBERTY_H
+#define LIBIBERTY_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include <ansidecl.h>
-#include <stdlib.h>
+#include "ansidecl.h"
+
+/* Get a definition for size_t.  */
+#include <stddef.h>
+/* Get a definition for va_list.  */
+#include <stdarg.h>
+
 #include <stdio.h>
 
-#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+/* If the OS supports it, ensure that the supplied stream is setup to
+   avoid any multi-threaded locking.  Otherwise leave the FILE pointer
+   unchanged.  If the stream is NULL do nothing.  */
 
-#define xstrdup   strdup
-#define xstrerror strerror
+extern void unlock_stream (FILE *);
 
-/* These macros provide a K&R/C89/C++-friendly way of allocating structures
-   with nice encapsulation.  The XDELETE*() macros are technically
-   superfluous, but provided here for symmetry.  Using them consistently
-   makes it easier to update client code to use different allocators such
-   as new/delete and new[]/delete[].  */
+/* If the OS supports it, ensure that the standard I/O streams, stdin,
+   stdout and stderr are setup to avoid any multi-threaded locking.
+   Otherwise do nothing.  */
 
-/* Scalar allocators.  */
+extern void unlock_std_streams (void);
 
-#define XALLOCA(T)              ((T *) alloca (sizeof (T)))
-#define XNEW(T)                 ((T *) malloc (sizeof (T)))
-#define XCNEW(T)                ((T *) calloc (1, sizeof (T)))
-#define XDUP(T, P)              ((T *) memdup ((P), sizeof (T), sizeof (T)))
-#define XDELETE(P)              free ((void*) (P))
+/* Open and return a FILE pointer.  If the OS supports it, ensure that
+   the stream is setup to avoid any multi-threaded locking.  Otherwise
+   return the FILE pointer unchanged.  */
 
-/* Array allocators.  */
+extern FILE *fopen_unlocked (const char *, const char *);
+extern FILE *fdopen_unlocked (int, const char *);
+extern FILE *freopen_unlocked (const char *, const char *, FILE *);
 
-#define XALLOCAVEC(T, N)        ((T *) alloca (sizeof (T) * (N)))
-#define XNEWVEC(T, N)           ((T *) malloc (sizeof (T) * (N)))
-#define XCNEWVEC(T, N)          ((T *) calloc ((N), sizeof (T)))
-#define XDUPVEC(T, P, N)        ((T *) memdup ((P), sizeof (T) * (N), sizeof (T) * (N)))
-#define XRESIZEVEC(T, P, N)     ((T *) realloc ((void *) (P), sizeof (T) * (N)))
-#define XDELETEVEC(P)           free ((void*) (P))
+/* Build an argument vector from a string.  Allocates memory using
+   malloc.  Use freeargv to free the vector.  */
 
-/* Allocators for variable-sized structures and raw buffers.  */
+extern char **buildargv (const char *) ATTRIBUTE_MALLOC;
+
+/* Free a vector returned by buildargv.  */
+
+extern void freeargv (char **);
+
+/* Duplicate an argument vector. Allocates memory using malloc.  Use
+   freeargv to free the vector.  */
+
+extern char **dupargv (char * const *) ATTRIBUTE_MALLOC;
+
+/* Expand "@file" arguments in argv.  */
+
+extern void expandargv (int *, char ***);
+
+/* Write argv to an @-file, inserting necessary quoting.  */
+
+extern int writeargv (char * const *, FILE *);
 
-#define XALLOCAVAR(T, S)        ((T *) alloca ((S)))
-#define XNEWVAR(T, S)           ((T *) malloc ((S)))
-#define XCNEWVAR(T, S)          ((T *) calloc (1, (S)))
-#define XDUPVAR(T, P, S1, S2)   ((T *) memdup ((P), (S1), (S2)))
-#define XRESIZEVAR(T, P, S)     ((T *) realloc ((P), (S)))
+/* Return the number of elements in argv.  */
+
+extern int countargv (char * const *);
+
+/* Return the last component of a path name.  Note that we can't use a
+   prototype here because the parameter is declared inconsistently
+   across different systems, sometimes as "char *" and sometimes as
+   "const char *" */
+
+/* HAVE_DECL_* is a three-state macro: undefined, 0 or 1.  If it is
+   undefined, we haven't run the autoconf check so provide the
+   declaration without arguments.  If it is 0, we checked and failed
+   to find the declaration so provide a fully prototyped one.  If it
+   is 1, we found it so don't provide any declaration at all.  */
+#if !HAVE_DECL_BASENAME
+#if defined (__GNU_LIBRARY__ ) || defined (__linux__) \
+ || defined (__FreeBSD__) || defined (__OpenBSD__) || defined (__NetBSD__) \
+ || defined (__CYGWIN__) || defined (__CYGWIN32__) || defined (__MINGW32__) \
+ || defined (__DragonFly__) || defined (HAVE_DECL_BASENAME) 
+extern char *basename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
+#else
+/* Do not allow basename to be used if there is no prototype seen.  We
+   either need to use the above prototype or have one from
+   autoconf which would result in HAVE_DECL_BASENAME being set.  */
+#define basename basename_cannot_be_used_without_a_prototype
+#endif
+#endif
+
+/* A well-defined basename () that is always compiled in.  */
+
+extern const char *lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
+
+/* Same, but assumes DOS semantics (drive name, backslash is also a
+   dir separator) regardless of host.  */
+
+extern const char *dos_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
+
+/* Same, but assumes Unix semantics (absolute paths always start with
+   a slash, only forward slash is accepted as dir separator)
+   regardless of host.  */
+
+extern const char *unix_lbasename (const char *) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1);
+
+/* A well-defined realpath () that is always compiled in.  */
+
+extern char *lrealpath (const char *);
 
 /* Concatenate an arbitrary number of strings.  You must pass NULL as
    the last argument of this function, to terminate the list of
    strings.  Allocates memory using xmalloc.  */
 
-extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
 
 /* Concatenate an arbitrary number of strings.  You must pass NULL as
    the last argument of this function, to terminate the list of
@@ -96,7 +150,7 @@ extern char *concat (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
    pointer to be freed after the new string is created, similar to the
    way xrealloc works.  */
 
-extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_SENTINEL;
+extern char *reconcat (char *, const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
 
 /* Determine the length of concatenating an arbitrary number of
    strings.  You must pass NULL as the last argument of this function,
@@ -109,44 +163,261 @@ extern unsigned long concat_length (const char *, ...) ATTRIBUTE_SENTINEL;
    to terminate the list of strings.  The supplied memory is assumed
    to be large enough.  */
 
-extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_SENTINEL;
+extern char *concat_copy (char *, const char *, ...) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_NONNULL(1) ATTRIBUTE_SENTINEL;
 
 /* Concatenate an arbitrary number of strings into a GLOBAL area of
    memory.  You must pass NULL as the last argument of this function,
    to terminate the list of strings.  The supplied memory is assumed
    to be large enough.  */
 
-extern char *concat_copy2 (const char *, ...) ATTRIBUTE_SENTINEL;
+extern char *concat_copy2 (const char *, ...) ATTRIBUTE_RETURNS_NONNULL ATTRIBUTE_SENTINEL;
 
 /* This is the global area used by concat_copy2.  */
 
 extern char *libiberty_concat_ptr;
 
+/* Concatenate an arbitrary number of strings.  You must pass NULL as
+   the last argument of this function, to terminate the list of
+   strings.  Allocates memory using alloca.  The arguments are
+   evaluated twice!  */
+#define ACONCAT(ACONCAT_PARAMS) \
+  (libiberty_concat_ptr = (char *) alloca (concat_length ACONCAT_PARAMS + 1), \
+   concat_copy2 ACONCAT_PARAMS)
+
+/* Check whether two file descriptors refer to the same file.  */
+
+extern int fdmatch (int fd1, int fd2);
+
+/* Return the position of the first bit set in the argument.  */
+/* Prototypes vary from system to system, so we only provide a
+   prototype on systems where we know that we need it.  */
+#if defined (HAVE_DECL_FFS) && !HAVE_DECL_FFS
+extern int ffs(int);
+#endif
+
+/* Get the working directory.  The result is cached, so don't call
+   chdir() between calls to getpwd().  */
+
+extern char * getpwd (void);
+
+/* Get the current time.  */
+/* Prototypes vary from system to system, so we only provide a
+   prototype on systems where we know that we need it.  */
+#ifdef __MINGW32__
+/* Forward declaration to avoid #include <sys/time.h>.   */
+struct timeval;
+extern int gettimeofday (struct timeval *, void *); 
+#endif
+
+/* Get the amount of time the process has run, in microseconds.  */
+
+extern long get_run_time (void);
+
+/* Generate a relocated path to some installation directory.  Allocates
+   return value using malloc.  */
+
+extern char *make_relative_prefix (const char *, const char *,
+                                   const char *) ATTRIBUTE_MALLOC;
+
+/* Generate a relocated path to some installation directory without
+   attempting to follow any soft links.  Allocates
+   return value using malloc.  */
+
+extern char *make_relative_prefix_ignore_links (const char *, const char *,
+						const char *) ATTRIBUTE_MALLOC;
+
+/* Returns a pointer to a directory path suitable for creating temporary
+   files in.  */
+
+extern const char *choose_tmpdir (void) ATTRIBUTE_RETURNS_NONNULL;
+
+/* Choose a temporary directory to use for scratch files.  */
+
+extern char *choose_temp_base (void) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
 /* Return a temporary file name or NULL if unable to create one.  */
 
 extern char *make_temp_file (const char *) ATTRIBUTE_MALLOC;
 
+/* Remove a link to a file unless it is special. */
+
+extern int unlink_if_ordinary (const char *);
+
+/* Allocate memory filled with spaces.  Allocates using malloc.  */
+
+extern const char *spaces (int count);
+
+/* Return the maximum error number for which strerror will return a
+   string.  */
+
+extern int errno_max (void);
+
+/* Return the name of an errno value (e.g., strerrno (EINVAL) returns
+   "EINVAL").  */
+
+extern const char *strerrno (int);
+
+/* Given the name of an errno value, return the value.  */
+
+extern int strtoerrno (const char *);
+
+/* ANSI's strerror(), but more robust.  */
+
+extern char *xstrerror (int) ATTRIBUTE_RETURNS_NONNULL;
+
+/* Return the maximum signal number for which strsignal will return a
+   string.  */
+
+extern int signo_max (void);
+
+/* Return a signal message string for a signal number
+   (e.g., strsignal (SIGHUP) returns something like "Hangup").  */
+/* This is commented out as it can conflict with one in system headers.
+   We still document its existence though.  */
+
+/*extern const char *strsignal (int);*/
+
+/* Return the name of a signal number (e.g., strsigno (SIGHUP) returns
+   "SIGHUP").  */
+
+extern const char *strsigno (int);
+
+/* Given the name of a signal, return its number.  */
+
+extern int strtosigno (const char *);
+
+/* Register a function to be run by xexit.  Returns 0 on success.  */
+
+extern int xatexit (void (*fn) (void));
+
+/* Exit, calling all the functions registered with xatexit.  */
+
+extern void xexit (int status) ATTRIBUTE_NORETURN;
+
+/* Set the program name used by xmalloc.  */
+
+extern void xmalloc_set_program_name (const char *);
+
+/* Report an allocation failure.  */
+extern void xmalloc_failed (size_t) ATTRIBUTE_NORETURN;
+
+/* Allocate memory without fail.  If malloc fails, this will print a
+   message to stderr (using the name set by xmalloc_set_program_name,
+   if any) and then call xexit.  */
+
+extern void *xmalloc (size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
+/* Reallocate memory without fail.  This works like xmalloc.  Note,
+   realloc type functions are not suitable for attribute malloc since
+   they may return the same address across multiple calls. */
+
+extern void *xrealloc (void *, size_t) ATTRIBUTE_RETURNS_NONNULL;
+
+/* Allocate memory without fail and set it to zero.  This works like
+   xmalloc.  */
+
+extern void *xcalloc (size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
+/* Copy a string into a memory buffer without fail.  */
+
+extern char *xstrdup (const char *) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
+/* Copy at most N characters from string into a buffer without fail.  */
+
+extern char *xstrndup (const char *, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
+/* Copy an existing memory buffer to a new memory buffer without fail.  */
+
+extern void *xmemdup (const void *, size_t, size_t) ATTRIBUTE_MALLOC ATTRIBUTE_RETURNS_NONNULL;
+
+/* Physical memory routines.  Return values are in BYTES.  */
+extern double physmem_total (void);
+extern double physmem_available (void);
+
+/* Compute the 32-bit CRC of a block of memory.  */
+extern unsigned int xcrc32 (const unsigned char *, int, unsigned int);
+
+/* These macros provide a K&R/C89/C++-friendly way of allocating structures
+   with nice encapsulation.  The XDELETE*() macros are technically
+   superfluous, but provided here for symmetry.  Using them consistently
+   makes it easier to update client code to use different allocators such
+   as new/delete and new[]/delete[].  */
+
+/* Scalar allocators.  */
+
+#define XALLOCA(T)		((T *) alloca (sizeof (T)))
+#define XNEW(T)			((T *) xmalloc (sizeof (T)))
+#define XCNEW(T)		((T *) xcalloc (1, sizeof (T)))
+#define XDUP(T, P)		((T *) xmemdup ((P), sizeof (T), sizeof (T)))
+#define XDELETE(P)		free ((void*) (P))
+
+/* Array allocators.  */
+
+#define XALLOCAVEC(T, N)	((T *) alloca (sizeof (T) * (N)))
+#define XNEWVEC(T, N)		((T *) xmalloc (sizeof (T) * (N)))
+#define XCNEWVEC(T, N)		((T *) xcalloc ((N), sizeof (T)))
+#define XDUPVEC(T, P, N)	((T *) xmemdup ((P), sizeof (T) * (N), sizeof (T) * (N)))
+#define XRESIZEVEC(T, P, N)	((T *) xrealloc ((void *) (P), sizeof (T) * (N)))
+#define XDELETEVEC(P)		free ((void*) (P))
+
+/* Allocators for variable-sized structures and raw buffers.  */
+
+#define XALLOCAVAR(T, S)	((T *) alloca ((S)))
+#define XNEWVAR(T, S)		((T *) xmalloc ((S)))
+#define XCNEWVAR(T, S)		((T *) xcalloc (1, (S)))
+#define XDUPVAR(T, P, S1, S2)	((T *) xmemdup ((P), (S1), (S2)))
+#define XRESIZEVAR(T, P, S)	((T *) xrealloc ((P), (S)))
+
+/* Type-safe obstack allocator.  */
+
+#define XOBNEW(O, T)		((T *) obstack_alloc ((O), sizeof (T)))
+#define XOBNEWVEC(O, T, N)	((T *) obstack_alloc ((O), sizeof (T) * (N)))
+#define XOBNEWVAR(O, T, S)	((T *) obstack_alloc ((O), (S)))
+#define XOBFINISH(O, T)         ((T) obstack_finish ((O)))
+
+/* hex character manipulation routines */
+
+#define _hex_array_size 256
+#define _hex_bad	99
+extern const unsigned char _hex_value[_hex_array_size];
+extern void hex_init (void);
+#define hex_p(c)	(hex_value (c) != _hex_bad)
+/* If you change this, note well: Some code relies on side effects in
+   the argument being performed exactly once.  */
+#define hex_value(c)	((unsigned int) _hex_value[(unsigned char) (c)])
+
 /* Flags for pex_init.  These are bits to be or'ed together.  */
 
 /* Record subprocess times, if possible.  */
-#define PEX_RECORD_TIMES        0x1
+#define PEX_RECORD_TIMES	0x1
 
 /* Use pipes for communication between processes, if possible.  */
-#define PEX_USE_PIPES           0x2
+#define PEX_USE_PIPES		0x2
 
 /* Save files used for communication between processes.  */
-#define PEX_SAVE_TEMPS          0x4
+#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.
-   PNAME        The name of the program to report in error messages.
-   TEMPBASE     A base name to use for temporary files; may be NULL to
-                use a random name.
-                Returns NULL on error.  */
+   FLAGS	As above.
+   PNAME	The name of the program to report in error messages.
+   TEMPBASE	A base name to use for temporary files; may be NULL to
+   		use a random name.
+   Returns NULL on error.  */
 
 extern struct pex_obj *pex_init (int flags, const char *pname,
-                                 const char *tempbase);
+				 const char *tempbase) ATTRIBUTE_RETURNS_NONNULL;
 
 /* Flags for pex_run.  These are bits to be or'ed together.  */
 
@@ -155,27 +426,27 @@ extern struct pex_obj *pex_init (int flags, const char *pname,
    not set this if you want to call pex_read_output.  After this is
    set, pex_run may no longer be called with the same struct
    pex_obj.  */
-#define PEX_LAST                0x1
+#define PEX_LAST		0x1
 
 /* Search for program in executable search path.  */
-#define PEX_SEARCH              0x2
+#define PEX_SEARCH		0x2
 
 /* OUTNAME is a suffix.  */
-#define PEX_SUFFIX              0x4
+#define PEX_SUFFIX		0x4
 
 /* Send program's standard error to standard output.  */
-#define PEX_STDERR_TO_STDOUT    0x8
+#define PEX_STDERR_TO_STDOUT	0x8
 
 /* Input file should be opened in binary mode.  This flag is ignored
    on Unix.  */
-#define PEX_BINARY_INPUT        0x10
+#define PEX_BINARY_INPUT	0x10
 
 /* Output file should be opened in binary mode.  This flag is ignored
    on Unix.  For proper behaviour PEX_BINARY_INPUT and
    PEX_BINARY_OUTPUT have to match appropriately--i.e., a call using
    PEX_BINARY_OUTPUT should be followed by a call using
    PEX_BINARY_INPUT.  */
-#define PEX_BINARY_OUTPUT       0x20
+#define PEX_BINARY_OUTPUT	0x20
 
 /* Capture stderr to a pipe.  The output can be read by
    calling pex_read_err and reading from the returned
@@ -183,12 +454,17 @@ extern struct pex_obj *pex_init (int flags, const char *pname,
    the last program in a pipeline.  
 
    This flag is supported only on Unix and Windows.  */
-#define PEX_STDERR_TO_PIPE      0x40
+#define PEX_STDERR_TO_PIPE	0x40
 
 /* Capture stderr in binary mode.  This flag is ignored
    on Unix.  */
-#define PEX_BINARY_ERROR        0x80
+#define PEX_BINARY_ERROR	0x80
+
+/* Append stdout to existing file instead of truncating it.  */
+#define PEX_STDOUT_APPEND	0x100
 
+/* Thes same as PEX_STDOUT_APPEND, but for STDERR.  */
+#define PEX_STDERR_APPEND	0x200
 
 /* Execute one program.  Returns NULL on success.  On error returns an
    error string (typically just the name of a system call); the error
@@ -335,8 +611,140 @@ extern const char *pex_one (int flags, const char *executable,
 			    const char *outname, const char *errname,
 			    int *status, int *err);
 
+/* pexecute and pwait are the old pexecute interface, still here for
+   backward compatibility.  Don't use these for new code.  Instead,
+   use pex_init/pex_run/pex_get_status/pex_free, or pex_one.  */
+
+/* Definitions used by the pexecute routine.  */
+
+#define PEXECUTE_FIRST   1
+#define PEXECUTE_LAST    2
+#define PEXECUTE_ONE     (PEXECUTE_FIRST + PEXECUTE_LAST)
+#define PEXECUTE_SEARCH  4
+#define PEXECUTE_VERBOSE 8
+
+/* Execute a program.  */
+
+extern int pexecute (const char *, char * const *, const char *,
+                     const char *, char **, char **, int);
+
+/* Wait for pexecute to finish.  */
+
+extern int pwait (int, int *, int);
+
+#if defined(HAVE_DECL_ASPRINTF) && !HAVE_DECL_ASPRINTF
+/* Like sprintf but provides a pointer to malloc'd storage, which must
+   be freed by the caller.  */
+
+extern int asprintf (char **, const char *, ...) ATTRIBUTE_PRINTF_2;
+#endif
+
+/* Like asprintf but allocates memory without fail. This works like
+   xmalloc.  */
+
+extern char *xasprintf (const char *, ...) ATTRIBUTE_MALLOC ATTRIBUTE_PRINTF_1;
+
+#if !HAVE_DECL_VASPRINTF
+/* Like vsprintf but provides a pointer to malloc'd storage, which
+   must be freed by the caller.  */
+
+extern int vasprintf (char **, const char *, va_list) ATTRIBUTE_PRINTF(2,0);
+#endif
+
+/* Like vasprintf but allocates memory without fail. This works like
+   xmalloc.  */
+
+extern char *xvasprintf (const char *, va_list) ATTRIBUTE_MALLOC ATTRIBUTE_PRINTF(1,0);
+
+#if defined(HAVE_DECL_SNPRINTF) && !HAVE_DECL_SNPRINTF
+/* Like sprintf but prints at most N characters.  */
+extern int snprintf (char *, size_t, const char *, ...) ATTRIBUTE_PRINTF_3;
+#endif
+
+#if defined(HAVE_DECL_VSNPRINTF) && !HAVE_DECL_VSNPRINTF
+/* Like vsprintf but prints at most N characters.  */
+extern int vsnprintf (char *, size_t, const char *, va_list) ATTRIBUTE_PRINTF(3,0);
+#endif
+
+#if defined (HAVE_DECL_STRNLEN) && !HAVE_DECL_STRNLEN
+extern size_t strnlen (const char *, size_t);
+#endif
+
+#if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP
+/* Compare version strings.  */
+extern int strverscmp (const char *, const char *);
+#endif
+
+#if defined(HAVE_DECL_STRTOL) && !HAVE_DECL_STRTOL
+extern long int strtol (const char *nptr,
+                        char **endptr, int base);
+#endif
+
+#if defined(HAVE_DECL_STRTOUL) && !HAVE_DECL_STRTOUL
+extern unsigned long int strtoul (const char *nptr,
+                                  char **endptr, int base);
+#endif
+
+#if defined(HAVE_LONG_LONG) && defined(HAVE_DECL_STRTOLL) && !HAVE_DECL_STRTOLL
+__extension__
+extern long long int strtoll (const char *nptr,
+                              char **endptr, int base);
+#endif
+
+#if defined(HAVE_LONG_LONG) && defined(HAVE_DECL_STRTOULL) && !HAVE_DECL_STRTOULL
+__extension__
+extern unsigned long long int strtoull (const char *nptr,
+                                        char **endptr, int base);
+#endif
+
+#if defined(HAVE_DECL_STRVERSCMP) && !HAVE_DECL_STRVERSCMP
+/* Compare version strings.  */
+extern int strverscmp (const char *, const char *);
+#endif
+
+/* Set the title of a process */
+extern void setproctitle (const char *name, ...);
+
+/* Increase stack limit if possible.  */
+extern void stack_limit_increase (unsigned long);
+
+#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
+
+/* Drastically simplified alloca configurator.  If we're using GCC,
+   we use __builtin_alloca; otherwise we use the C alloca.  The C
+   alloca is always available.  You can override GCC by defining
+   USE_C_ALLOCA yourself.  The canonical autoconf macro C_ALLOCA is
+   also set/unset as it is often used to indicate whether code needs
+   to call alloca(0).  */
+extern void *C_alloca (size_t) ATTRIBUTE_MALLOC;
+#undef alloca
+#if GCC_VERSION >= 2000 && !defined USE_C_ALLOCA
+# define alloca(x) __builtin_alloca(x)
+# undef C_ALLOCA
+# define ASTRDUP(X) \
+  (__extension__ ({ const char *const libiberty_optr = (X); \
+   const unsigned long libiberty_len = strlen (libiberty_optr) + 1; \
+   char *const libiberty_nptr = (char *) alloca (libiberty_len); \
+   (char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len); }))
+#else
+# define alloca(x) C_alloca(x)
+# undef USE_C_ALLOCA
+# define USE_C_ALLOCA 1
+# undef C_ALLOCA
+# define C_ALLOCA 1
+extern const char *libiberty_optr;
+extern char *libiberty_nptr;
+extern unsigned long libiberty_len;
+# define ASTRDUP(X) \
+  (libiberty_optr = (X), \
+   libiberty_len = strlen (libiberty_optr) + 1, \
+   libiberty_nptr = (char *) alloca (libiberty_len), \
+   (char *) memcpy (libiberty_nptr, libiberty_optr, libiberty_len))
+#endif
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif
+
+#endif /* ! defined (LIBIBERTY_H) */
diff --git a/rtemstoolkit/libiberty/make-temp-file.c b/rtemstoolkit/libiberty/make-temp-file.c
index dc2fc1d..98e215d 100644
--- a/rtemstoolkit/libiberty/make-temp-file.c
+++ b/rtemstoolkit/libiberty/make-temp-file.c
@@ -1,6 +1,5 @@
 /* Utility to pick a temporary filename prefix.
-   Copyright (C) 1996, 1997, 1998, 2001, 2009, 2010
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
@@ -57,7 +56,7 @@ extern int mkstemps (char *, int);
 
 /* Name of temporary file.
    mktemp requires 6 trailing X's.  */
-#define TEMP_FILE "rld--XXXXXX"
+#define TEMP_FILE "ccXXXXXX"
 #define TEMP_FILE_LEN (sizeof(TEMP_FILE) - 1)
 
 #if !defined(_WIN32) || defined(__CYGWIN__)
@@ -93,7 +92,7 @@ static char *memoized_tmpdir;
 
 /*
 
- at deftypefn Replacement char* choose_tmpdir ()
+ at deftypefn Replacement const char* choose_tmpdir ()
 
 Returns a pointer to a directory path suitable for creating temporary
 files in.
@@ -102,7 +101,7 @@ files in.
 
 */
 
-char *
+const char *
 choose_tmpdir (void)
 {
   if (!memoized_tmpdir)
@@ -111,7 +110,7 @@ choose_tmpdir (void)
       const char *base = 0;
       char *tmpdir;
       unsigned int len;
-
+      
 #ifdef VMS
       /* Try VMS standard temp logical.  */
       base = try_dir ("/sys$scratch", base);
@@ -120,7 +119,7 @@ choose_tmpdir (void)
       base = try_dir (getenv ("TMP"), base);
       base = try_dir (getenv ("TEMP"), base);
 #endif
-
+      
 #ifdef P_tmpdir
       /* We really want a directory name here as if concatenated with say \dir
 	 we do not end up with a double \\ which defines an UNC path.  */
@@ -134,7 +133,7 @@ choose_tmpdir (void)
       base = try_dir (vartmp, base);
       base = try_dir (usrtmp, base);
       base = try_dir (tmp, base);
-
+      
       /* If all else fails, use the current directory!  */
       if (base == 0)
 	base = ".";
diff --git a/rtemstoolkit/libiberty/mkstemps.c b/rtemstoolkit/libiberty/mkstemps.c
index a0e68a7..8a0effd 100644
--- a/rtemstoolkit/libiberty/mkstemps.c
+++ b/rtemstoolkit/libiberty/mkstemps.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991, 1992, 1996, 1998, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991-2017 Free Software Foundation, Inc.
    This file is derived from mkstemp.c from the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -35,6 +35,8 @@
 #endif
 #ifdef HAVE_SYS_TIME_H
 #include <sys/time.h>
+#elif HAVE_TIME_H
+#include <time.h>
 #endif
 #include "ansidecl.h"
 
diff --git a/rtemstoolkit/libiberty/pex-common.c b/rtemstoolkit/libiberty/pex-common.c
index 6fd3fde..3a6c7d4 100644
--- a/rtemstoolkit/libiberty/pex-common.c
+++ b/rtemstoolkit/libiberty/pex-common.c
@@ -1,5 +1,5 @@
 /* Common code for executing a program in a sub-process.
-   Copyright (C) 2005, 2010 Free Software Foundation, Inc.
+   Copyright (C) 2005-2017 Free Software Foundation, Inc.
    Written by Ian Lance Taylor <ian at airs.com>.
 
 This file is part of the libiberty library.
@@ -267,7 +267,8 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
   if (out < 0)
     {
       out = obj->funcs->open_write (obj, outname,
-				    (flags & PEX_BINARY_OUTPUT) != 0);
+				    (flags & PEX_BINARY_OUTPUT) != 0,
+				    (flags & PEX_STDOUT_APPEND) != 0);
       if (out < 0)
 	{
 	  *err = errno;
@@ -319,8 +320,9 @@ pex_run_in_environment (struct pex_obj *obj, int flags, const char *executable,
     }
   else
     {
-      errdes = obj->funcs->open_write (obj, errname, 
-				       (flags & PEX_BINARY_ERROR) != 0);
+      errdes = obj->funcs->open_write (obj, errname,
+				       (flags & PEX_BINARY_ERROR) != 0,
+				       (flags & PEX_STDERR_APPEND) != 0);
       if (errdes < 0)
 	{
 	  *err = errno;
diff --git a/rtemstoolkit/libiberty/pex-common.h b/rtemstoolkit/libiberty/pex-common.h
index af338e6..cddcf6b 100644
--- a/rtemstoolkit/libiberty/pex-common.h
+++ b/rtemstoolkit/libiberty/pex-common.h
@@ -1,7 +1,6 @@
 /* Utilities to execute a program in a subprocess (possibly linked by pipes
    with other subprocesses), and wait for it.  Shared logic.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
@@ -104,7 +103,7 @@ struct pex_funcs
   /* Open file NAME for writing.  If BINARY is non-zero, open in
      binary mode.  Return >= 0 on success, -1 on error.  */
   int (*open_write) (struct pex_obj *, const char */* name */,
-                     int /* binary */);
+                     int /* binary */, int /* append */);
   /* Execute a child process.  FLAGS, EXECUTABLE, ARGV, ERR are from
      pex_run.  IN, OUT, ERRDES, TOCLOSE are all descriptors, from
      open_read, open_write, or pipe, or they are one of STDIN_FILE_NO,
diff --git a/rtemstoolkit/libiberty/pex-djgpp.c b/rtemstoolkit/libiberty/pex-djgpp.c
index 0721139..ecb418a 100644
--- a/rtemstoolkit/libiberty/pex-djgpp.c
+++ b/rtemstoolkit/libiberty/pex-djgpp.c
@@ -1,7 +1,6 @@
 /* Utilities to execute a program in a subprocess (possibly linked by pipes
    with other subprocesses), and wait for it.  DJGPP specialization.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
@@ -43,7 +42,7 @@ extern int errno;
 #endif
 
 static int pex_djgpp_open_read (struct pex_obj *, const char *, int);
-static int pex_djgpp_open_write (struct pex_obj *, const char *, int);
+static int pex_djgpp_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_djgpp_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
 				  int, int, int, int,
@@ -90,10 +89,12 @@ pex_djgpp_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED,
 
 static int
 pex_djgpp_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED,
-		      const char *name, int binary)
+		      const char *name, int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return open (name,
 	       (O_WRONLY | O_CREAT | O_TRUNC
 		| (binary ? O_BINARY : O_TEXT)),
diff --git a/rtemstoolkit/libiberty/pex-msdos.c b/rtemstoolkit/libiberty/pex-msdos.c
index fa0f40a..c9e837d 100644
--- a/rtemstoolkit/libiberty/pex-msdos.c
+++ b/rtemstoolkit/libiberty/pex-msdos.c
@@ -1,7 +1,6 @@
 /* Utilities to execute a program in a subprocess (possibly linked by pipes
    with other subprocesses), and wait for it.  Generic MSDOS specialization.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2005
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
diff --git a/rtemstoolkit/libiberty/pex-one.c b/rtemstoolkit/libiberty/pex-one.c
index 696b8bc..6b38860 100644
--- a/rtemstoolkit/libiberty/pex-one.c
+++ b/rtemstoolkit/libiberty/pex-one.c
@@ -1,5 +1,5 @@
 /* Execute a program and wait for a result.
-   Copyright (C) 2005 Free Software Foundation, Inc.
+   Copyright (C) 2005-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
diff --git a/rtemstoolkit/libiberty/pex-unix.c b/rtemstoolkit/libiberty/pex-unix.c
index 80a4770..0b96370 100644
--- a/rtemstoolkit/libiberty/pex-unix.c
+++ b/rtemstoolkit/libiberty/pex-unix.c
@@ -1,8 +1,7 @@
 /* Utilities to execute a program in a subprocess (possibly linked by pipes
    with other subprocesses), and wait for it.  Generic Unix version
    (also used for UWIN and VMS).
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2009,
-   2010 Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
@@ -23,6 +22,7 @@ Boston, MA 02110-1301, USA.  */
 #include "config.h"
 #include "libiberty.h"
 #include "pex-common.h"
+#include "environ.h"
 
 #include <stdio.h>
 #include <signal.h>
@@ -85,13 +85,15 @@ to_ptr32 (char **ptr64)
   int argc;
   __char_ptr_char_ptr32 short_argv;
 
-  for (argc=0; ptr64[argc]; argc++);
+  /* Count number of arguments.  */
+  for (argc = 0; ptr64[argc] != NULL; argc++)
+    ;
 
   /* Reallocate argv with 32 bit pointers.  */
   short_argv = (__char_ptr_char_ptr32) decc$malloc
     (sizeof (__char_ptr32) * (argc + 1));
 
-  for (argc=0; ptr64[argc]; argc++)
+  for (argc = 0; ptr64[argc] != NULL; argc++)
     short_argv[argc] = (__char_ptr32) decc$strdup (ptr64[argc]);
 
   short_argv[argc] = (__char_ptr32) 0;
@@ -260,7 +262,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
 
 	  pt.user_seconds = r2.ru_utime.tv_sec - r1.ru_utime.tv_sec;
 	  pt.user_microseconds = r2.ru_utime.tv_usec - r1.ru_utime.tv_usec;
-	  if ((int) pt.user_microseconds < 0)
+	  if (r2.ru_utime.tv_usec < r1.ru_utime.tv_usec)
 	    {
 	      --pt.user_seconds;
 	      pt.user_microseconds += 1000000;
@@ -268,7 +270,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
 
 	  pt.system_seconds = r2.ru_stime.tv_sec - r1.ru_stime.tv_sec;
 	  pt.system_microseconds = r2.ru_stime.tv_usec - r1.ru_stime.tv_usec;
-	  if ((int) pt.system_microseconds < 0)
+	  if (r2.ru_stime.tv_usec < r1.ru_stime.tv_usec)
 	    {
 	      --pt.system_seconds;
 	      pt.system_microseconds += 1000000;
@@ -299,7 +301,7 @@ pex_wait (struct pex_obj *obj, pid_t pid, int *status, struct pex_time *time)
 static void pex_child_error (struct pex_obj *, const char *, const char *, int)
      ATTRIBUTE_NORETURN;
 static int pex_unix_open_read (struct pex_obj *, const char *, int);
-static int pex_unix_open_write (struct pex_obj *, const char *, int);
+static int pex_unix_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_unix_exec_child (struct pex_obj *, int, const char *,
 				 char * const *, char * const *,
 				 int, int, int, int,
@@ -348,11 +350,12 @@ pex_unix_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_unix_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		     int binary ATTRIBUTE_UNUSED)
+		     int binary ATTRIBUTE_UNUSED, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
-  return open (name, O_WRONLY | O_CREAT | O_TRUNC, PUBLIC_MODE);
+  return open (name, O_WRONLY | O_CREAT
+		     | (append ? O_APPEND : O_TRUNC), PUBLIC_MODE);
 }
 
 /* Close a file.  */
@@ -387,8 +390,6 @@ pex_child_error (struct pex_obj *obj, const char *executable,
 
 /* Execute a child.  */
 
-extern char **environ;
-
 #if defined(HAVE_SPAWNVE) && defined(HAVE_SPAWNVPE)
 /* Implementation of pex->exec_child using the Cygwin spawn operation.  */
 
diff --git a/rtemstoolkit/libiberty/pex-win32.c b/rtemstoolkit/libiberty/pex-win32.c
index f1d47c7..9131158 100644
--- a/rtemstoolkit/libiberty/pex-win32.c
+++ b/rtemstoolkit/libiberty/pex-win32.c
@@ -1,7 +1,6 @@
 /* Utilities to execute a program in a subprocess (possibly linked by pipes
    with other subprocesses), and wait for it.  Generic Win32 specialization.
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
-   Free Software Foundation, Inc.
+   Copyright (C) 1996-2017 Free Software Foundation, Inc.
 
 This file is part of the libiberty library.
 Libiberty is free software; you can redistribute it and/or
@@ -44,7 +43,6 @@ Boston, MA 02110-1301, USA.  */
 #include <sys/stat.h>
 #include <errno.h>
 #include <ctype.h>
-#include <malloc.h>
 
 /* mingw32 headers may not define the following.  */
 
@@ -79,7 +77,7 @@ backslashify (char *s)
 }
 
 static int pex_win32_open_read (struct pex_obj *, const char *, int);
-static int pex_win32_open_write (struct pex_obj *, const char *, int);
+static int pex_win32_open_write (struct pex_obj *, const char *, int, int);
 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *,
 				  char * const *, char * const *,
                                   int, int, int, int,
@@ -127,10 +125,12 @@ pex_win32_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
 
 static int
 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name,
-		      int binary)
+		      int binary, int append)
 {
   /* Note that we can't use O_EXCL here because gcc may have already
      created the temporary file via make_temp_file.  */
+  if (append)
+    return -1;
   return _open (name,
 		(_O_WRONLY | _O_CREAT | _O_TRUNC
 		 | (binary ? _O_BINARY : _O_TEXT)),
@@ -341,17 +341,25 @@ argv_to_cmdline (char *const *argv)
   char *p;
   size_t cmdline_len;
   int i, j, k;
+  int needs_quotes;
 
   cmdline_len = 0;
   for (i = 0; argv[i]; i++)
     {
-      /* We quote every last argument.  This simplifies the problem;
-	 we need only escape embedded double-quotes and immediately
+      /* We only quote arguments that contain spaces, \t or " characters to
+	 prevent wasting 2 chars per argument of the CreateProcess 32k char
+	 limit.  We need only escape embedded double-quotes and immediately
 	 preceeding backslash characters.  A sequence of backslach characters
 	 that is not follwed by a double quote character will not be
 	 escaped.  */
+      needs_quotes = 0;
       for (j = 0; argv[i][j]; j++)
 	{
+	  if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
+	    {
+	      needs_quotes = 1;
+	    }
+
 	  if (argv[i][j] == '"')
 	    {
 	      /* Escape preceeding backslashes.  */
@@ -361,18 +369,39 @@ 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.  */
-      for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
-	cmdline_len++;
+      if (needs_quotes)
+        {
+          for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
+            cmdline_len++;
+        }
       cmdline_len += j;
-      cmdline_len += 3;  /* for leading and trailing quotes and space */
+      /* for leading and trailing quotes and space */
+      cmdline_len += needs_quotes * 2 + 1;
     }
   cmdline = XNEWVEC (char, cmdline_len);
   p = cmdline;
   for (i = 0; argv[i]; i++)
     {
-      *p++ = '"';
+      needs_quotes = 0;
+      for (j = 0; argv[i][j]; j++)
+        {
+          if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"')
+            {
+              needs_quotes = 1;
+              break;
+            }
+        }
+      if (j == 0)
+	needs_quotes = 1;
+
+      if (needs_quotes)
+        {
+          *p++ = '"';
+        }
       for (j = 0; argv[i][j]; j++)
 	{
 	  if (argv[i][j] == '"')
@@ -383,9 +412,12 @@ argv_to_cmdline (char *const *argv)
 	    }
 	  *p++ = argv[i][j];
 	}
-      for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
-	*p++ = '\\';
-      *p++ = '"';
+      if (needs_quotes)
+        {
+          for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--)
+            *p++ = '\\';
+          *p++ = '"';
+        }
       *p++ = ' ';
     }
   p[-1] = '\0';
@@ -742,24 +774,17 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
   int orig_out, orig_in, orig_err;
   BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT);
 
-  /* Ensure we have inheritable descriptors to pass to the child, and close the
-     original descriptors.  */
+  /* Ensure we have inheritable descriptors to pass to the child.  */
   orig_in = in;
   in = _dup (orig_in);
-  if (orig_in != STDIN_FILENO)
-    _close (orig_in);
   
   orig_out = out;
   out = _dup (orig_out);
-  if (orig_out != STDOUT_FILENO)
-    _close (orig_out);
   
   if (separate_stderr)
     {
       orig_err = errdes;
       errdes = _dup (orig_err);
-      if (orig_err != STDERR_FILENO)
-	_close (orig_err);
     }
 
   stdin_handle = INVALID_HANDLE_VALUE;
@@ -837,6 +862,22 @@ pex_win32_exec_child (struct pex_obj *obj ATTRIBUTE_UNUSED, int flags,
       *errmsg = "CreateProcess";
     }
 
+  /* If the child was created successfully, close the original file
+     descriptors.  If the process creation fails, these are closed by
+     pex_run_in_environment instead.  We must not close them twice as
+     that seems to cause a Windows exception.  */
+     
+  if (pid != (pid_t) -1)
+    {
+      if (orig_in != STDIN_FILENO)
+	_close (orig_in);
+      if (orig_out != STDOUT_FILENO)
+	_close (orig_out);
+      if (separate_stderr
+	  && orig_err != STDERR_FILENO)
+	_close (orig_err);
+    }
+
   /* Close the standard input, standard output and standard error handles
      in the parent.  */ 
 
diff --git a/rtemstoolkit/libiberty/rust-demangle.c b/rtemstoolkit/libiberty/rust-demangle.c
new file mode 100644
index 0000000..3d7d090
--- /dev/null
+++ b/rtemstoolkit/libiberty/rust-demangle.c
@@ -0,0 +1,348 @@
+/* Demangler for the Rust programming language
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+   Written by David Tolnay (dtolnay at 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;
+}
diff --git a/rtemstoolkit/libiberty/safe-ctype.c b/rtemstoolkit/libiberty/safe-ctype.c
index 0972b4b..5a13f82 100644
--- a/rtemstoolkit/libiberty/safe-ctype.c
+++ b/rtemstoolkit/libiberty/safe-ctype.c
@@ -1,7 +1,6 @@
 /* <ctype.h> replacement macros.
 
-   Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005 Free Software Foundation, Inc.
+   Copyright (C) 2000-2017 Free Software Foundation, Inc.
    Contributed by Zack Weinberg <zackw at stanford.edu>.
 
 This file is part of the libiberty library.
diff --git a/rtemstoolkit/libiberty/safe-ctype.h b/rtemstoolkit/libiberty/safe-ctype.h
index 0266bf1..16d8ebf 100644
--- a/rtemstoolkit/libiberty/safe-ctype.h
+++ b/rtemstoolkit/libiberty/safe-ctype.h
@@ -1,6 +1,6 @@
 /* <ctype.h> replacement macros.
 
-   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 2000-2017 Free Software Foundation, Inc.
    Contributed by Zack Weinberg <zackw at stanford.edu>.
 
 This file is part of the libiberty library.
diff --git a/rtemstoolkit/libiberty/stpcpy.c b/rtemstoolkit/libiberty/stpcpy.c
index 57b32d1..ddbef28 100644
--- a/rtemstoolkit/libiberty/stpcpy.c
+++ b/rtemstoolkit/libiberty/stpcpy.c
@@ -1,5 +1,5 @@
 /* Implement the stpcpy function.
-   Copyright (C) 2003 Free Software Foundation, Inc.
+   Copyright (C) 2003-2017 Free Software Foundation, Inc.
    Written by Kaveh R. Ghazi <ghazi at caip.rutgers.edu>.
 
 This file is part of the libiberty library.
diff --git a/rtemstoolkit/libiberty/xmalloc.c b/rtemstoolkit/libiberty/xmalloc.c
new file mode 100644
index 0000000..6d0aca4
--- /dev/null
+++ b/rtemstoolkit/libiberty/xmalloc.c
@@ -0,0 +1,185 @@
+/* memory allocation routines with error checking.
+   Copyright (C) 1989-2017 Free Software Foundation, Inc.
+
+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.
+
+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, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
+Boston, MA 02110-1301, USA.  */
+
+/*
+
+ at deftypefn Replacement void* xmalloc (size_t)
+
+Allocate memory without fail.  If @code{malloc} fails, this will print
+a message to @code{stderr} (using the name set by
+ at code{xmalloc_set_program_name},
+if any) and then call @code{xexit}.  Note that it is therefore safe for
+a program to contain @code{#define malloc xmalloc} in its source.
+
+ at end deftypefn
+
+ at deftypefn Replacement void* xrealloc (void *@var{ptr}, size_t @var{size})
+Reallocate memory without fail.  This routine functions like @code{realloc},
+but will behave the same as @code{xmalloc} if memory cannot be found.
+
+ at end deftypefn
+
+ at deftypefn Replacement void* xcalloc (size_t @var{nelem}, size_t @var{elsize})
+
+Allocate memory without fail, and set it to zero.  This routine functions
+like @code{calloc}, but will behave the same as @code{xmalloc} if memory
+cannot be found.
+
+ at end deftypefn
+
+ at deftypefn Replacement void xmalloc_set_program_name (const char *@var{name})
+
+You can use this to set the name of the program used by
+ at code{xmalloc_failed} when printing a failure message.
+
+ at end deftypefn
+
+ at deftypefn Replacement void xmalloc_failed (size_t)
+
+This function is not meant to be called by client code, and is listed
+here for completeness only.  If any of the allocation routines fail, this
+function will be called to print an error message and terminate execution.
+
+ at end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+#include "environ.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <stddef.h>
+
+#if VMS
+#include <stdlib.h>
+#include <unixlib.h>
+#else
+/* For systems with larger pointers than ints, these must be declared.  */
+#  if HAVE_STDLIB_H && HAVE_UNISTD_H && HAVE_DECL_MALLOC \
+      && HAVE_DECL_REALLOC && HAVE_DECL_CALLOC && HAVE_DECL_SBRK
+#    include <stdlib.h>
+#    include <unistd.h>
+#  else
+#    ifdef __cplusplus
+extern "C" {
+#    endif /* __cplusplus */
+void *malloc (size_t);
+void *realloc (void *, size_t);
+void *calloc (size_t, size_t);
+void *sbrk (ptrdiff_t);
+#    ifdef __cplusplus
+}
+#    endif /* __cplusplus */
+#  endif /* HAVE_STDLIB_H ...  */
+#endif /* VMS */
+
+/* The program name if set.  */
+static const char *name = "";
+
+#ifdef HAVE_SBRK
+/* The initial sbrk, set when the program name is set. Not used for win32
+   ports other than cygwin32.  */
+static char *first_break = NULL;
+#endif /* HAVE_SBRK */
+
+void
+xmalloc_set_program_name (const char *s)
+{
+  name = s;
+#ifdef HAVE_SBRK
+  /* Win32 ports other than cygwin32 don't have brk() */
+  if (first_break == NULL)
+    first_break = (char *) sbrk (0);
+#endif /* HAVE_SBRK */
+}
+
+void
+xmalloc_failed (size_t size)
+{
+#ifdef HAVE_SBRK
+  size_t allocated;
+
+  if (first_break != NULL)
+    allocated = (char *) sbrk (0) - first_break;
+  else
+    allocated = (char *) sbrk (0) - (char *) &environ;
+  fprintf (stderr,
+	   "\n%s%sout of memory allocating %lu bytes after a total of %lu bytes\n",
+	   name, *name ? ": " : "",
+	   (unsigned long) size, (unsigned long) allocated);
+#else /* HAVE_SBRK */
+  fprintf (stderr,
+	   "\n%s%sout of memory allocating %lu bytes\n",
+	   name, *name ? ": " : "",
+	   (unsigned long) size);
+#endif /* HAVE_SBRK */
+  exit (1);
+}
+
+PTR
+xmalloc (size_t size)
+{
+  PTR newmem;
+
+  if (size == 0)
+    size = 1;
+  newmem = malloc (size);
+  if (!newmem)
+    xmalloc_failed (size);
+
+  return (newmem);
+}
+
+PTR
+xcalloc (size_t nelem, size_t elsize)
+{
+  PTR newmem;
+
+  if (nelem == 0 || elsize == 0)
+    nelem = elsize = 1;
+
+  newmem = calloc (nelem, elsize);
+  if (!newmem)
+    xmalloc_failed (nelem * elsize);
+
+  return (newmem);
+}
+
+PTR
+xrealloc (PTR oldmem, size_t size)
+{
+  PTR newmem;
+
+  if (size == 0)
+    size = 1;
+  if (!oldmem)
+    newmem = malloc (size);
+  else
+    newmem = realloc (oldmem, size);
+  if (!newmem)
+    xmalloc_failed (size);
+
+  return (newmem);
+}
diff --git a/rtemstoolkit/libiberty/xmemdup.c b/rtemstoolkit/libiberty/xmemdup.c
new file mode 100644
index 0000000..4602afd
--- /dev/null
+++ b/rtemstoolkit/libiberty/xmemdup.c
@@ -0,0 +1,41 @@
+/* xmemdup.c -- Duplicate a memory buffer, using xmalloc.
+   This trivial function is in the public domain.
+   Jeff Garzik, September 1999.  */
+
+/*
+
+ at deftypefn Replacement void* xmemdup (void *@var{input}, @
+  size_t @var{copy_size}, size_t @var{alloc_size})
+
+Duplicates a region of memory without fail.  First, @var{alloc_size} bytes
+are allocated, then @var{copy_size} bytes from @var{input} are copied into
+it, and the new memory is returned.  If fewer bytes are copied than were
+allocated, the remaining memory is zeroed.
+
+ at end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+
+#include <sys/types.h> /* For size_t. */
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+
+PTR
+xmemdup (const PTR input, size_t copy_size, size_t 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);
+}
diff --git a/rtemstoolkit/libiberty/xstrdup.c b/rtemstoolkit/libiberty/xstrdup.c
new file mode 100644
index 0000000..fa12c96
--- /dev/null
+++ b/rtemstoolkit/libiberty/xstrdup.c
@@ -0,0 +1,36 @@
+/* xstrdup.c -- Duplicate a string in memory, using xmalloc.
+   This trivial function is in the public domain.
+   Ian Lance Taylor, Cygnus Support, December 1995.  */
+
+/*
+
+ at deftypefn Replacement char* xstrdup (const char *@var{s})
+
+Duplicates a character string without fail, using @code{xmalloc} to
+obtain memory.
+
+ at end deftypefn
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <sys/types.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+#  include <strings.h>
+# endif
+#endif
+#include "ansidecl.h"
+#include "libiberty.h"
+
+char *
+xstrdup (const char *s)
+{
+  register size_t len = strlen (s) + 1;
+  register char *ret = XNEWVEC (char, len);
+  return (char *) memcpy (ret, s, len);
+}
diff --git a/rtemstoolkit/libiberty/xstrerror.c b/rtemstoolkit/libiberty/xstrerror.c
new file mode 100644
index 0000000..2ea2200
--- /dev/null
+++ b/rtemstoolkit/libiberty/xstrerror.c
@@ -0,0 +1,79 @@
+/* xstrerror.c -- jacket routine for more robust strerror() usage.
+   Fri Jun 16 18:30:00 1995  Pat Rankin  <rankin at eql.caltech.edu>
+   This code is in the public domain.  */
+
+/*
+
+ at deftypefn Replacement char* xstrerror (int @var{errnum})
+
+Behaves exactly like the standard @code{strerror} function, but
+will never return a @code{NULL} pointer.
+
+ at end deftypefn
+
+*/
+
+#include <stdio.h>
+
+#include "config.h"
+#include "libiberty.h"
+
+#ifdef VMS
+#  include <errno.h>
+#  if !defined (__STRICT_ANSI__) && !defined (__HIDE_FORBIDDEN_NAMES)
+#    ifdef __cplusplus
+extern "C" {
+#    endif /* __cplusplus */
+extern char *strerror (int,...);
+#    define DONT_DECLARE_STRERROR
+#    ifdef __cplusplus
+}
+#    endif /* __cplusplus */
+#  endif
+#endif  /* VMS */
+
+
+#ifndef DONT_DECLARE_STRERROR
+#  ifdef __cplusplus
+extern "C" {
+#  endif /* __cplusplus */
+extern char *strerror (int);
+#  ifdef __cplusplus
+}
+#  endif /* __cplusplus */
+#endif
+
+/* If strerror returns NULL, we'll format the number into a static buffer.  */
+
+#define ERRSTR_FMT "undocumented error #%d"
+static char xstrerror_buf[sizeof ERRSTR_FMT + 20];
+
+/* Like strerror, but result is never a null pointer.  */
+
+char *
+xstrerror (int errnum)
+{
+  char *errstr;
+#ifdef VMS
+  char *(*vmslib_strerror) (int,...);
+
+  /* Override any possibly-conflicting declaration from system header.  */
+  vmslib_strerror = (char *(*) (int,...)) strerror;
+  /* Second argument matters iff first is EVMSERR, but it's simpler to
+     pass it unconditionally.  `vaxc$errno' is declared in <errno.h>
+     and maintained by the run-time library in parallel to `errno'.
+     We assume that `errnum' corresponds to the last value assigned to
+     errno by the run-time library, hence vaxc$errno will be relevant.  */
+  errstr = (*vmslib_strerror) (errnum, vaxc$errno);
+#else
+  errstr = strerror (errnum);
+#endif
+
+  /* If `errnum' is out of range, result might be NULL.  We'll fix that.  */
+  if (!errstr)
+    {
+      sprintf (xstrerror_buf, ERRSTR_FMT, errnum);
+      errstr = xstrerror_buf;
+    }
+  return errstr;
+}
diff --git a/rtemstoolkit/rld-buffer.h b/rtemstoolkit/rld-buffer.h
index ea94a9a..08df4ba 100644
--- a/rtemstoolkit/rld-buffer.h
+++ b/rtemstoolkit/rld-buffer.h
@@ -59,6 +59,13 @@ namespace rld
        */
       ~buffer ();
 
+      /*
+       * Return true if the byte order is little-endian.
+       */
+      bool little_endian () const {
+        return le;
+      }
+
       /**
        * Clear the buffer reseting the level to zero.
        */
@@ -148,11 +155,23 @@ namespace rld
     {
       uint8_t bytes[sizeof (T)];
       T       v = value;
-      int     b = sizeof (T) - 1;
-      while (b >= 0)
+      if (buf.little_endian ())
       {
-        bytes[b--] = (uint8_t) v;
-        v >>= 8;
+        size_t b = sizeof (T);
+        while (b != 0)
+        {
+          bytes[--b] = (uint8_t) v;
+          v >>= 8;
+        }
+      }
+      else
+      {
+        size_t b = 0;
+        while (b < sizeof (T))
+        {
+          bytes[b++] = (uint8_t) v;
+          v >>= 8;
+        }
       }
       buf.write (bytes, sizeof (T));
     }
@@ -164,13 +183,25 @@ namespace rld
     void read (buffer& buf, T& value)
     {
       uint8_t bytes[sizeof (T)];
-      int     b = sizeof (T) - 1;
-      buf.read (bytes, sizeof(T));
+      buf.read (bytes, sizeof (T));
       value = 0;
-      while (b >= 0)
+      if (buf.little_endian ())
+      {
+        size_t b = sizeof (T);
+        while (b != 0)
+        {
+          value <<= 8;
+          value |= (T) bytes[--b];
+        }
+      }
+      else
       {
-        value <<= 8;
-        value |= (T) bytes[b--];
+        size_t b = 0;
+        while (b < sizeof (T))
+        {
+          value <<= 8;
+          value |= (T) bytes[b++];
+        }
       }
     }
 
diff --git a/rtemstoolkit/rld-files.cpp b/rtemstoolkit/rld-files.cpp
index 1a236fd..6a276ea 100644
--- a/rtemstoolkit/rld-files.cpp
+++ b/rtemstoolkit/rld-files.cpp
@@ -406,6 +406,19 @@ namespace rld
       return elf_;
     }
 
+    byteorder
+    image::get_byteorder () const
+    {
+      switch (elf_.data_type ())
+      {
+        case ELFDATA2LSB:
+          return little_endian;
+        case ELFDATA2MSB:
+          return big_endian;
+      }
+      throw rld::error ("invalid elf data type", "byteorder: " + name ().path ());
+    }
+
     void
     image::symbol_referenced ()
     {
diff --git a/rtemstoolkit/rld-files.h b/rtemstoolkit/rld-files.h
index b8cc359..09e9aaf 100644
--- a/rtemstoolkit/rld-files.h
+++ b/rtemstoolkit/rld-files.h
@@ -65,6 +65,15 @@ namespace rld
     typedef std::list < object* > object_list;
 
     /**
+     * Byte order of the image.
+     */
+    enum byteorder
+    {
+      big_endian,
+      little_endian
+    };
+
+    /**
      * A file is a single object file that is either in an @ref archive or
      * a separate stand alone @ref object file.
      */
@@ -334,6 +343,11 @@ namespace rld
       elf::file& elf ();
 
       /**
+       * Return the image's byte order.
+       */
+      byteorder get_byteorder () const;
+
+      /**
        * A symbol in the image has been referenced.
        */
       virtual void symbol_referenced ();
diff --git a/rtemstoolkit/rld-symbols.cpp b/rtemstoolkit/rld-symbols.cpp
index 19d5680..642d53f 100644
--- a/rtemstoolkit/rld-symbols.cpp
+++ b/rtemstoolkit/rld-symbols.cpp
@@ -38,29 +38,34 @@ namespace rld
      * Get the demangled name.
      */
     bool
-    is_cplusplus (const std::string& name)
+    demangle_name (const std::string& name, std::string& demangled)
     {
-      char* demangled_name = ::cplus_demangle (name.c_str (),
-                                               DMGL_ANSI | DMGL_PARAMS);
       bool yes = false;
-      if (demangled_name)
+      if (name.length() == 0)
+        demangled = name;
+      else
       {
-        yes = true;
-        ::free (demangled_name);
+        std::string wrapper = "_GLOBAL__sub_I_";
+        size_t      offset = 0;
+        if (name.compare (0, wrapper.length (), wrapper) == 0)
+          offset = wrapper.length ();
+        char* demangled_name = ::cplus_demangle (name.c_str () + offset,
+                                                 DMGL_ANSI | DMGL_PARAMS);
+        if (demangled_name)
+        {
+          demangled = demangled_name;
+          ::free (demangled_name);
+          yes = true;
+        }
       }
       return yes;
     }
 
-    void
-    demangle_name (std::string& name, std::string& demangled)
+    bool
+    is_cplusplus (const std::string& name)
     {
-      char* demangled_name = ::cplus_demangle (name.c_str (),
-                                               DMGL_ANSI | DMGL_PARAMS);
-      if (demangled_name)
-      {
-        demangled = demangled_name;
-        ::free (demangled_name);
-      }
+      std::string demangled;
+      return symbols::demangle_name (name, demangled);
     }
 
     symbol::symbol ()
@@ -83,8 +88,7 @@ namespace rld
     {
       if (!object_)
         throw rld_error_at ("object pointer is 0");
-      if (is_cplusplus ())
-        demangle_name (name_, demangled_);
+      demangle_name (name_, demangled_);
     }
 
     symbol::symbol (int                 index,
@@ -96,8 +100,7 @@ namespace rld
         esym_ (esym),
         references_ (0)
     {
-      if (is_cplusplus ())
-        demangle_name (name_, demangled_);
+      demangle_name (name_, demangled_);
     }
 
     symbol::symbol (const std::string&  name,
@@ -143,7 +146,7 @@ namespace rld
     bool
     symbol::is_cplusplus () const
     {
-      return (name_[0] == '_') && (name_[1] == 'Z');
+      return symbols::is_cplusplus (name_);
     }
 
     bool
@@ -279,7 +282,7 @@ namespace rld
           break;
       }
 
-      out << std::setw (5) << index_
+      out << std::setw (8) << index_
           << ' ' << binding
           << ' ' << type
           << ' ' << std::setw(6) << es.st_shndx
diff --git a/rtemstoolkit/rld-symbols.h b/rtemstoolkit/rld-symbols.h
index 6a71a3d..28d3cab 100644
--- a/rtemstoolkit/rld-symbols.h
+++ b/rtemstoolkit/rld-symbols.h
@@ -48,7 +48,7 @@ namespace rld
      * C++ demangler.
      */
     bool is_cplusplus (const std::string& name);
-    void demangle_name (std::string& name, std::string& demangled);
+    bool demangle_name (const std::string& name, std::string& demangled);
 
     /**
      * Use a local type for the address.
diff --git a/rtemstoolkit/wscript b/rtemstoolkit/wscript
index 3b725e4..81ab647 100644
--- a/rtemstoolkit/wscript
+++ b/rtemstoolkit/wscript
@@ -288,12 +288,18 @@ def bld_libiberty(bld, conf):
               source =['libiberty/concat.c',
                        'libiberty/cplus-dem.c',
                        'libiberty/cp-demangle.c',
+                       'libiberty/d-demangle.c',
+                       'libiberty/rust-demangle.c',
                        'libiberty/make-temp-file.c',
                        'libiberty/mkstemps.c',
                        'libiberty/safe-ctype.c',
                        'libiberty/stpcpy.c',
                        'libiberty/pex-common.c',
                        'libiberty/pex-one.c',
+                       'libiberty/xmalloc.c',
+                       'libiberty/xmemdup.c',
+                       'libiberty/xstrdup.c',
+                       'libiberty/xstrerror.c',
                        pex_host])
 
 #



More information about the vc mailing list