public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Add D demangling support to libiberty
@ 2014-08-03 18:13 Iain Buclaw
  2014-08-04 15:53 ` Ian Lance Taylor
  2014-08-04 16:06 ` Tom Tromey
  0 siblings, 2 replies; 16+ messages in thread
From: Iain Buclaw @ 2014-08-03 18:13 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1702 bytes --]

Hi,

This adds a demangler for the D programming language to libiberty,
intended to be used in GDB and Binutils.  GDB already has a trimmed
down implementation of this, but have been advised that here would be
a better location to house it.

Notes that I think are of interest / questions I have about how I've done this.

- The implementation is some 1200 SLOC (and may grow), so I've put it
in a new file, as opposed included cplus-dem.c.  Is this reasonable?

- This borrows and extends the mini string package in cplus-dem.c,
because it was the simplest to use when writing this.  The GDB
implementation uses obstack, and I'm aware of dyn_string, but I can't
say I'm a fan of using either.

- GDB has a testsuite that provides most of the coverage for what this
code should be doing.

- List of functions in d-demangle.c can be added to the ChangeLog upon request.

- I haven't signed any copyright assignments to GCC.  But I have
papers from Donald ready to send across.

Regards
Iain

---
Add D demangling support for version 2 of the ABI.

include/ChangeLog
2014-08-03  Iain Buclaw  <ibuclaw@gdcproject.org>

        * demangle.h (DMGL_DLANG): New macro.
        (DMGL_STYLE_MASK): Add DMGL_DLANG.
        (demangling_styles): Add dlang_demangling.
        (DLANG_DEMANGLING_STYLE_STRING): New macro.
        (DLANG_DEMANGLING): New macro.
        (dlang_demangle): New prototype.

libibery/ChangeLog
2014-08-03  Iain Buclaw  <ibuclaw@gdcproject.org>

        * Makefile.in (CFILES): Add d-demangle.c.
        (REQUIRED_OFILES): Add d-demangle.o.
        * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case.
        (cplus_demangle): Likewise.
        * d-demangle.c: New file.

---

[-- Attachment #2: d-demangle.patch --]
[-- Type: text/x-patch, Size: 36859 bytes --]

diff --git a/include/demangle.h b/include/demangle.h
index bbad71b..d2a6731 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -63,9 +63,10 @@ extern "C" {
 #define DMGL_EDG	 (1 << 13)
 #define DMGL_GNU_V3	 (1 << 14)
 #define DMGL_GNAT	 (1 << 15)
+#define DMGL_DLANG	 (1 << 16)
 
 /* 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)
 
 /* Enumeration of possible demangling styles.
 
@@ -87,7 +88,8 @@ 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
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
@@ -102,6 +104,7 @@ 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"
 
 /* Some macros to test what demangling style is active. */
 
@@ -115,6 +118,7 @@ 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)
 
 /* Provide information about the available demangle styles. This code is
    pulled from gdb into libiberty because it is useful to binutils also.  */
@@ -169,6 +173,9 @@ java_demangle_v3 (const char *mangled);
 char *
 ada_demangle (const char *mangled, int options);
 
+extern char *
+dlang_demangle (const char *mangled, int options);
+
 enum gnu_v3_ctor_kinds {
   gnu_v3_complete_object_ctor = 1,
   gnu_v3_base_object_ctor,
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index 44e340f..9b87720 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -127,7 +127,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c				\
 	basename.c bcmp.c bcopy.c bsearch.c bzero.c			\
 	calloc.c choose-temp.c clock.c concat.c cp-demangle.c		\
 	 cp-demint.c cplus-dem.c crc32.c				\
-	dwarfnames.c dyn-string.c					\
+	d-demangle.c dwarfnames.c dyn-string.c				\
 	fdmatch.c ffs.c fibheap.c filename_cmp.c floatformat.c		\
 	fnmatch.c fopen_unlocked.c					\
 	getcwd.c getopt.c getopt1.c getpagesize.c getpwd.c getruntime.c	\
@@ -167,7 +167,7 @@ REQUIRED_OFILES =							\
 	./md5.$(objext) ./sha1.$(objext) ./alloca.$(objext)		\
 	./argv.$(objext)						\
 	./choose-temp.$(objext) ./concat.$(objext)			\
-	./cp-demint.$(objext) ./crc32.$(objext)				\
+	./cp-demint.$(objext) ./crc32.$(objext) ./d-demangle.$(objext)	\
 	./dwarfnames.$(objext) ./dyn-string.$(objext)			\
 	./fdmatch.$(objext) ./fibheap.$(objext)				\
 	./filename_cmp.$(objext) ./floatformat.$(objext)		\
@@ -714,6 +714,14 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/dyn-string.c $(OUTPUT_OPTION)
 
+./d-demangle.$(objext): $(srcdir)/d-demangle.c config.h $(INCDIR)/ansidecl.h \
+	$(srcdir)/cp-demangle.h $(INCDIR)/demangle.h \
+	$(INCDIR)/dyn-string.h $(INCDIR)/getopt.h $(INCDIR)/libiberty.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/d-demangle.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/d-demangle.c $(OUTPUT_OPTION)
+
 ./fdmatch.$(objext): $(srcdir)/fdmatch.c config.h $(INCDIR)/ansidecl.h \
 	$(INCDIR)/libiberty.h
 	if [ x"$(PICFLAG)" != x ]; then \
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 52767cc..c68b981 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -306,6 +306,12 @@ const struct demangler_engine libiberty_demanglers[] =
   }
   ,
   {
+    DLANG_DEMANGLING_STYLE_STRING,
+    dlang_demangling,
+    "DLANG style demangling"
+  }
+  ,
+  {
     NULL, unknown_demangling, NULL
   }
 };
@@ -870,6 +876,13 @@ cplus_demangle (const char *mangled, int options)
   if (GNAT_DEMANGLING)
     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);
diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
new file mode 100644
index 0000000..799528e
--- /dev/null
+++ b/libiberty/d-demangle.c
@@ -0,0 +1,1354 @@
+/* Demangler for the D programming language
+   Copyright 2014 Free Software Foundation, Inc.
+   Written by Iain Buclaw (ibuclaw@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.
+
+   This file imports strtol and strtold for decoding mangled literals.  */
+
+#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>
+#else
+long strtol (const char *nptr, char **endptr, int base);
+long double strtold (const char *nptr, char **endptr);
+#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));
+    }
+}
+
+
+/* Prototypes for D demangling functions */
+static const char *dlang_call_convention (string *, const char *);
+
+static const char *dlang_attributes (string *, const char *);
+
+static const char *dlang_function_type (string *, const char *);
+
+static const char *dlang_function_args (string *, const char *);
+
+static const char *dlang_type (string *, const char *);
+
+static const char *dlang_identifier (string *, const char *);
+
+static const char *dlang_parse_integer (string *, const char *, char);
+
+static const char *dlang_parse_real (string *, const char *);
+
+static const char *dlang_parse_string (string *, const char *);
+
+static const char *dlang_parse_arrayliteral (string *, const char *);
+
+static const char *dlang_parse_assocarray (string *, const char *);
+
+static const char *dlang_parse_structlit (string *, const char *, const char *);
+
+static const char *dlang_value (string *, const char *, const char *, char);
+
+static int dlang_call_convention_p (const char *);
+
+static const char *dlang_parse_symbol (string *, const char *);
+
+static const char *dlang_parse_tuple (string *, const char *);
+
+static const char *dlang_template_args (string *, const char *);
+
+static const char *dlang_parse_template (string *, const char *, long);
+
+#define ASCII2HEX(c) \
+  (('a' <= (c) && (c) <= 'f') ? \
+   ((c) - 'a' + 10) \
+   : (('A' <= (c) && (c) <= 'F') ? \
+      ((c) - 'A' + 10) \
+      : (('0' <= (c) && (c) <= '9') ? \
+	 ((c) - '0') \
+	 : 0 \
+        ) \
+     ) \
+  )
+
+/* Demangle the calling convention from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+const char *
+dlang_call_convention (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  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;
+    default:
+      return NULL;
+    }
+
+  return mangled;
+}
+
+/* Demangle the D function attributes from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+const char *
+dlang_attributes (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  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':
+	  /* inout parameter is represented as 'Ng'.
+	     vector parameter is represented as 'Nh'.
+	     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;
+	}
+      break;
+    }
+
+  return mangled;
+}
+
+/* Demangle the function type from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+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 mangled;
+
+  /* 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.  */
+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++;
+	  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 ");
+	}
+
+      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.  */
+const char *
+dlang_type (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  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++;
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "*");
+      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_symbol (decl, mangled);
+    case 'D': /* delegate T */
+      mangled++;
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "delegate");
+      return mangled;
+    case 'B': /* tuple T */
+      mangled++;
+      return dlang_parse_tuple (decl, mangled);
+
+    /* Function types */
+    case 'F': case 'U': case 'W':
+    case 'V': case 'R':
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "function");
+      return 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;
+
+    default: /* unhandled */
+      return NULL;
+    }
+}
+
+/* Extract the identifier from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+const char *
+dlang_identifier (string *decl, const char *mangled)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  if (ISDIGIT (*mangled))
+    {
+      char *endptr;
+      long i = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
+	return NULL;
+
+      mangled = endptr;
+
+      /* May be a template instance.  */
+      if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
+	{
+	  /* Template symbol.  */
+	  if (ISDIGIT (mangled[3]) && mangled[3] != '0')
+	    return dlang_parse_template (decl, mangled, i);
+
+	  return NULL;
+	}
+
+      if (strncmp (mangled, "__ctor", i) == 0)
+	{
+	  /* Constructor symbol for a class/struct.  */
+	  string_append (decl, "this");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__dtor", i) == 0)
+	{
+	  /* Destructor symbol for a class/struct.  */
+	  string_append (decl, "~this");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__postblit", i) == 0)
+	{
+	  /* Postblit symbol for a struct.  */
+	  string_append (decl, "this(this)");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__initZ", i+1) == 0)
+	{
+	  /* The static initialiser for a given symbol.  */
+	  string_prepend (decl, "init for ");
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__ClassZ", i+1) == 0)
+	{
+	  /* The classinfo symbol for a given class.  */
+	  string_prepend (decl, "classinfo for ");
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__vtblZ", i+1) == 0)
+	{
+	  /* The vtable symbol for a given class.  */
+	  string_prepend (decl, "vtable for ");
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
+	{
+	  /* The interface symbol for a given class.  */
+	  string_prepend (decl, "interface for ");
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
+	{
+	  /* The ModuleInfo symbol for a given module.  */
+	  string_prepend (decl, "moduleinfo for ");
+	  mangled += i + 1;
+	  return mangled;
+	}
+
+      string_appendn (decl, mangled, i);
+      mangled += i;
+    }
+  else
+    return NULL;
+
+  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.  */
+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;
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+	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, "'");
+      mangled = endptr;
+    }
+  else if (type == 'b')
+    {
+      /* Parse boolean value.  */
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+	return NULL;
+
+      string_append (decl, val ? "true" : "false");
+      mangled = endptr;
+    }
+  else
+    {
+      /* Parse integer value.  */
+      const char *numptr = mangled;
+      size_t num = 0;
+
+      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.  */
+const char *
+dlang_parse_real (string *decl, const char *mangled)
+{
+  char buffer[64];
+  int len = 0;
+  long double value;
+  char *endptr;
+
+  /* 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')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  if (!ISXDIGIT (*mangled))
+    return NULL;
+
+  buffer[len++] = '0';
+  buffer[len++] = 'x';
+  buffer[len++] = *mangled;
+  buffer[len++] = '.';
+  mangled++;
+
+  /* Significand.  */
+  while (ISXDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Exponent.  */
+  if (*mangled != 'P')
+    return NULL;
+
+  buffer[len++] = 'p';
+  mangled++;
+
+  if (*mangled == 'N')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  while (ISDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Convert buffer from hexadecimal to floating-point.  */
+  buffer[len] = '\0';
+  value = strtold (buffer, &endptr);
+
+  if (endptr == NULL || endptr != (buffer + len))
+    return NULL;
+
+  len = snprintf (buffer, sizeof(buffer), "%#Lg", value);
+  string_appendn (decl, buffer, len);
+  return mangled;
+}
+
+/* Extract the string value from MANGLED and append it to DECL.
+   Return the remaining string on success or NULL on failure.  */
+const char *
+dlang_parse_string (string *decl, const char *mangled)
+{
+  char type = *mangled;
+  char *endptr;
+  long len;
+
+  mangled++;
+  len = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || len < 0)
+    return NULL;
+
+  mangled = endptr;
+  if (*mangled != '_')
+    return NULL;
+
+  mangled++;
+  string_append (decl, "\"");
+  while (len--)
+    {
+      if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
+	{
+	  char a = ASCII2HEX (mangled[0]);
+	  char b = ASCII2HEX (mangled[1]);
+	  char val = (a << 4) | b;
+	  string_appendn (decl, &val, 1);
+	}
+      else
+	return NULL;
+
+      mangled += 2;
+    }
+  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.  */
+const char *
+dlang_parse_arrayliteral (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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.  */
+const char *
+dlang_parse_assocarray (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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.  */
+const char *
+dlang_parse_structlit (string *decl, const char *mangled, const char *name)
+{
+  char *endptr;
+  long args = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || args < 0)
+    return NULL;
+
+  mangled = endptr;
+  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.  */
+const char *
+dlang_value (string *decl, const char *mangled, const char *name, char type)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  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++;
+      if (*mangled < '0' || *mangled > '9')
+	return NULL;
+      /* Fall through */
+    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;
+}
+
+int
+dlang_call_convention_p (const char *mangled)
+{
+  size_t i;
+
+  switch (*mangled)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R':
+      return 1;
+
+    case 'M': /* Prefix for functions needing 'this' */
+      i = 1;
+      if (mangled[i] == 'x')
+	i++;
+
+      switch (mangled[i])
+	{
+	case 'F': case 'U': case 'V':
+	case 'W': case 'R':
+	  return 1;
+	}
+
+    default:
+      return 0;
+    }
+}
+
+/* Extract and demangle the symbol in MANGLED and append it to DECL.
+   Returns the remaining signature on success or NULL on failure.  */
+const char *
+dlang_parse_symbol (string *decl, const char *mangled)
+{
+  size_t n = 0;
+  do
+    {
+      if (n++)
+	string_append (decl, ".");
+
+      mangled = dlang_identifier (decl, mangled);
+
+      if (mangled && dlang_call_convention_p (mangled))
+	{
+	  int saved;
+
+	  /* Skip over 'this' parameter.  */
+	  if (*mangled == 'M')
+	    mangled += (mangled[1] == 'x') ? 2 : 1;
+
+	  /* Skip over calling convention and attributes in qualified name.  */
+	  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, ")");
+
+	  /* Demangle the function return type as a kind of sanity test.  */
+	  if (mangled && !ISDIGIT (*mangled))
+	    {
+	      saved = string_length (decl);
+	      mangled = dlang_type (decl, mangled);
+	      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.  */
+const char *
+dlang_parse_tuple (string *decl, const char *mangled)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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.  */
+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, ", ");
+
+      switch (*mangled)
+	{
+	case 'S': /* Symbol parameter.  */
+	  mangled++;
+	  mangled = dlang_parse_symbol (decl, mangled);
+	  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.  */
+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
+		   ^
+     The start pointer should be at the above location, and LEN should be
+     the value of the decoded number.
+   */
+  if (strncmp (mangled, "__T", 3) != 0)
+    return NULL;
+
+  mangled += 3;
+
+  /* Template identifier.  */
+  mangled = dlang_identifier (decl, mangled);
+
+  /* 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
+    {
+      mangled += 2;
+
+      if (dlang_parse_symbol (&decl, mangled) == NULL)
+	string_delete (&decl);
+    }
+
+  if (string_length (&decl) > 0)
+    {
+      string_need (&decl, 1);
+      *(decl.p) = '\0';
+      demangled = decl.b;
+    }
+
+  return demangled;
+}
+

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-03 18:13 [PATCH] Add D demangling support to libiberty Iain Buclaw
@ 2014-08-04 15:53 ` Ian Lance Taylor
  2014-08-04 16:38   ` Iain Buclaw
  2014-09-19  7:51   ` Iain Buclaw
  2014-08-04 16:06 ` Tom Tromey
  1 sibling, 2 replies; 16+ messages in thread
From: Ian Lance Taylor @ 2014-08-04 15:53 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gcc-patches

On Sun, Aug 3, 2014 at 11:12 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>
> This adds a demangler for the D programming language to libiberty,
> intended to be used in GDB and Binutils.  GDB already has a trimmed
> down implementation of this, but have been advised that here would be
> a better location to house it.
>
> Notes that I think are of interest / questions I have about how I've done this.
>
> - The implementation is some 1200 SLOC (and may grow), so I've put it
> in a new file, as opposed included cplus-dem.c.  Is this reasonable?

Yes.


> - This borrows and extends the mini string package in cplus-dem.c,
> because it was the simplest to use when writing this.  The GDB
> implementation uses obstack, and I'm aware of dyn_string, but I can't
> say I'm a fan of using either.

One thing we discovered for the C++ demangler is that sometimes it's
nice to be able to invoke it from locations where the memory allocator
is not available, such as when the program is crashing.  That is why
the C++ demangler has a cplus_demangle_v3_callback entry point.  For
ordinary demangling the code uses growable_string and
d_growable_string_callback_adapter.  It's not important for now but
you may want to consider doing something like that in the future.

If you do choose to follow that path, because of namespace
considerations I think the right approach would be to move the
growable_string code and the adapter into a .h file in libiberty that
defines the functions as static.  Then both demanglers could #include
that file.  That would let them share the code without adding
unacceptable new symbols to libstdc++.


> - GDB has a testsuite that provides most of the coverage for what this
> code should be doing.

That is nice but we need a small testsuite in libiberty too--see
libiberty/testsuite/test-demangle.c and demangle-expected.  Ideally
you should be able to just add some entries to demangle-expected.


> - List of functions in d-demangle.c can be added to the ChangeLog upon request.

Not necessary.


> - I haven't signed any copyright assignments to GCC.  But I have
> papers from Donald ready to send across.

Definitely necessary before we can consider this.  Please get this
squared away before proceeding with this patch.  Let us know if you
need any help with this.


> +#ifdef HAVE_STDLIB_H
> +#include <stdlib.h>
> +#else
> +long strtol (const char *nptr, char **endptr, int base);
> +long double strtold (const char *nptr, char **endptr);

Use an explicit "extern".

> +#define ASCII2HEX(c) \
> +  (('a' <= (c) && (c) <= 'f') ? \
> +   ((c) - 'a' + 10) \
> +   : (('A' <= (c) && (c) <= 'F') ? \
> +      ((c) - 'A' + 10) \
> +      : (('0' <= (c) && (c) <= '9') ? \
> +	 ((c) - '0') \
> +	 : 0 \
> +        ) \
> +     ) \
> +  )

Use a function, not a macro that multiple-evaluates its argument.


> +/* Prototypes for D demangling functions */

Current style is to only forward declare functions when necessary.


> +const char *
> +dlang_call_convention (string *decl, const char *mangled)

This should be explicitly static.  Same applies to many of the
functions below.

Ian

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-03 18:13 [PATCH] Add D demangling support to libiberty Iain Buclaw
  2014-08-04 15:53 ` Ian Lance Taylor
@ 2014-08-04 16:06 ` Tom Tromey
  2014-08-04 16:38   ` Iain Buclaw
  1 sibling, 1 reply; 16+ messages in thread
From: Tom Tromey @ 2014-08-04 16:06 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gcc-patches

>>>>> "Iain" == Iain Buclaw <ibuclaw@gdcproject.org> writes:

Iain> This adds a demangler for the D programming language to libiberty,
Iain> intended to be used in GDB and Binutils.  GDB already has a trimmed
Iain> down implementation of this, but have been advised that here would be
Iain> a better location to house it.

Iain> - GDB has a testsuite that provides most of the coverage for what this
Iain> code should be doing.

I think it's better to put the tests into libiberty.  That way they are
right next to the code.  This shouldn't be hard, as there's already a
demangler test suite there.

Tom

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-04 16:06 ` Tom Tromey
@ 2014-08-04 16:38   ` Iain Buclaw
  0 siblings, 0 replies; 16+ messages in thread
From: Iain Buclaw @ 2014-08-04 16:38 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gcc-patches

On 4 August 2014 17:06, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Iain" == Iain Buclaw <ibuclaw@gdcproject.org> writes:
>
> Iain> This adds a demangler for the D programming language to libiberty,
> Iain> intended to be used in GDB and Binutils.  GDB already has a trimmed
> Iain> down implementation of this, but have been advised that here would be
> Iain> a better location to house it.
>
> Iain> - GDB has a testsuite that provides most of the coverage for what this
> Iain> code should be doing.
>
> I think it's better to put the tests into libiberty.  That way they are
> right next to the code.  This shouldn't be hard, as there's already a
> demangler test suite there.
>
> Tom

I've found it, thanks.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-04 15:53 ` Ian Lance Taylor
@ 2014-08-04 16:38   ` Iain Buclaw
  2014-08-05 11:58     ` Iain Buclaw
  2014-09-19  7:51   ` Iain Buclaw
  1 sibling, 1 reply; 16+ messages in thread
From: Iain Buclaw @ 2014-08-04 16:38 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 4 August 2014 16:52, Ian Lance Taylor <iant@google.com> wrote:
> On Sun, Aug 3, 2014 at 11:12 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>
>> This adds a demangler for the D programming language to libiberty,
>> intended to be used in GDB and Binutils.  GDB already has a trimmed
>> down implementation of this, but have been advised that here would be
>> a better location to house it.
>>
>> Notes that I think are of interest / questions I have about how I've done this.
>>
>> - The implementation is some 1200 SLOC (and may grow), so I've put it
>> in a new file, as opposed included cplus-dem.c.  Is this reasonable?
>
> Yes.
>
>
>> - This borrows and extends the mini string package in cplus-dem.c,
>> because it was the simplest to use when writing this.  The GDB
>> implementation uses obstack, and I'm aware of dyn_string, but I can't
>> say I'm a fan of using either.
>
> One thing we discovered for the C++ demangler is that sometimes it's
> nice to be able to invoke it from locations where the memory allocator
> is not available, such as when the program is crashing.  That is why
> the C++ demangler has a cplus_demangle_v3_callback entry point.  For
> ordinary demangling the code uses growable_string and
> d_growable_string_callback_adapter.  It's not important for now but
> you may want to consider doing something like that in the future.
>
> If you do choose to follow that path, because of namespace
> considerations I think the right approach would be to move the
> growable_string code and the adapter into a .h file in libiberty that
> defines the functions as static.  Then both demanglers could #include
> that file.  That would let them share the code without adding
> unacceptable new symbols to libstdc++.
>
>
>> - GDB has a testsuite that provides most of the coverage for what this
>> code should be doing.
>
> That is nice but we need a small testsuite in libiberty too--see
> libiberty/testsuite/test-demangle.c and demangle-expected.  Ideally
> you should be able to just add some entries to demangle-expected.
>
>

OK, I'll examine this.



>> - List of functions in d-demangle.c can be added to the ChangeLog upon request.
>
> Not necessary.
>
>
>> - I haven't signed any copyright assignments to GCC.  But I have
>> papers from Donald ready to send across.
>
> Definitely necessary before we can consider this.  Please get this
> squared away before proceeding with this patch.  Let us know if you
> need any help with this.
>
>

I'll let you know when it's been processed.  Last time they had a fast
turnaround.


>> +#ifdef HAVE_STDLIB_H
>> +#include <stdlib.h>
>> +#else
>> +long strtol (const char *nptr, char **endptr, int base);
>> +long double strtold (const char *nptr, char **endptr);
>
> Use an explicit "extern".
>
>> +#define ASCII2HEX(c) \
>> +  (('a' <= (c) && (c) <= 'f') ? \
>> +   ((c) - 'a' + 10) \
>> +   : (('A' <= (c) && (c) <= 'F') ? \
>> +      ((c) - 'A' + 10) \
>> +      : (('0' <= (c) && (c) <= '9') ? \
>> +      ((c) - '0') \
>> +      : 0 \
>> +        ) \
>> +     ) \
>> +  )
>
> Use a function, not a macro that multiple-evaluates its argument.
>
>
>> +/* Prototypes for D demangling functions */
>
> Current style is to only forward declare functions when necessary.
>
>
>> +const char *
>> +dlang_call_convention (string *decl, const char *mangled)
>
> This should be explicitly static.  Same applies to many of the
> functions below.
>

I've dealt with the above, but I'll re-submit the patch when I've
added in the testsuite items.

Regards
Iain

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-04 16:38   ` Iain Buclaw
@ 2014-08-05 11:58     ` Iain Buclaw
  2014-10-14 14:17       ` Joel Brobecker
  0 siblings, 1 reply; 16+ messages in thread
From: Iain Buclaw @ 2014-08-05 11:58 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 816 bytes --]

Attached revision #2 of the patch.

---
Add D demangling support for version 2 of the ABI.

include/ChangeLog
2014-08-05  Iain Buclaw  <ibuclaw@gdcproject.org>

    * demangle.h (DMGL_DLANG): New macro.
    (DMGL_STYLE_MASK): Add DMGL_DLANG.
    (demangling_styles): Add dlang_demangling.
    (DLANG_DEMANGLING_STYLE_STRING): New macro.
    (DLANG_DEMANGLING): New macro.
    (dlang_demangle): New prototype.

libiberty/ChangeLog
2014-08-05  Iain Buclaw  <ibuclaw@gdcproject.org>

    * Makefile.in (CFILES): Add d-demangle.c.
    (REQUIRED_OFILES): Add d-demangle.o.
    * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case.
    (cplus_demangle): Likewise.
    * d-demangle.c: New file.
    * testsuite/Makefile.in (really-check): Add check-d-demangle.
    * testsuite/d-demangle-expected: New file.
---

[-- Attachment #2: d-demangle-2.patch --]
[-- Type: text/x-patch, Size: 56473 bytes --]

diff --git a/include/demangle.h b/include/demangle.h
index bbad71b..d2a6731 100644
--- a/include/demangle.h
+++ b/include/demangle.h
@@ -63,9 +63,10 @@ extern "C" {
 #define DMGL_EDG	 (1 << 13)
 #define DMGL_GNU_V3	 (1 << 14)
 #define DMGL_GNAT	 (1 << 15)
+#define DMGL_DLANG	 (1 << 16)
 
 /* 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)
 
 /* Enumeration of possible demangling styles.
 
@@ -87,7 +88,8 @@ 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
 } current_demangling_style;
 
 /* Define string names for the various demangling styles. */
@@ -102,6 +104,7 @@ 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"
 
 /* Some macros to test what demangling style is active. */
 
@@ -115,6 +118,7 @@ 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)
 
 /* Provide information about the available demangle styles. This code is
    pulled from gdb into libiberty because it is useful to binutils also.  */
@@ -169,6 +173,9 @@ java_demangle_v3 (const char *mangled);
 char *
 ada_demangle (const char *mangled, int options);
 
+extern char *
+dlang_demangle (const char *mangled, int options);
+
 enum gnu_v3_ctor_kinds {
   gnu_v3_complete_object_ctor = 1,
   gnu_v3_base_object_ctor,
diff --git a/libiberty/Makefile.in b/libiberty/Makefile.in
index 44e340f..9b87720 100644
--- a/libiberty/Makefile.in
+++ b/libiberty/Makefile.in
@@ -127,7 +127,7 @@ CFILES = alloca.c argv.c asprintf.c atexit.c				\
 	basename.c bcmp.c bcopy.c bsearch.c bzero.c			\
 	calloc.c choose-temp.c clock.c concat.c cp-demangle.c		\
 	 cp-demint.c cplus-dem.c crc32.c				\
-	dwarfnames.c dyn-string.c					\
+	d-demangle.c dwarfnames.c dyn-string.c				\
 	fdmatch.c ffs.c fibheap.c filename_cmp.c floatformat.c		\
 	fnmatch.c fopen_unlocked.c					\
 	getcwd.c getopt.c getopt1.c getpagesize.c getpwd.c getruntime.c	\
@@ -167,7 +167,7 @@ REQUIRED_OFILES =							\
 	./md5.$(objext) ./sha1.$(objext) ./alloca.$(objext)		\
 	./argv.$(objext)						\
 	./choose-temp.$(objext) ./concat.$(objext)			\
-	./cp-demint.$(objext) ./crc32.$(objext)				\
+	./cp-demint.$(objext) ./crc32.$(objext) ./d-demangle.$(objext)	\
 	./dwarfnames.$(objext) ./dyn-string.$(objext)			\
 	./fdmatch.$(objext) ./fibheap.$(objext)				\
 	./filename_cmp.$(objext) ./floatformat.$(objext)		\
@@ -714,6 +714,14 @@ $(CONFIGURED_OFILES): stamp-picdir stamp-noasandir
 	else true; fi
 	$(COMPILE.c) $(srcdir)/dyn-string.c $(OUTPUT_OPTION)
 
+./d-demangle.$(objext): $(srcdir)/d-demangle.c config.h $(INCDIR)/ansidecl.h \
+	$(srcdir)/cp-demangle.h $(INCDIR)/demangle.h \
+	$(INCDIR)/dyn-string.h $(INCDIR)/getopt.h $(INCDIR)/libiberty.h
+	if [ x"$(PICFLAG)" != x ]; then \
+	  $(COMPILE.c) $(PICFLAG) $(srcdir)/d-demangle.c -o pic/$@; \
+	else true; fi
+	$(COMPILE.c) $(srcdir)/d-demangle.c $(OUTPUT_OPTION)
+
 ./fdmatch.$(objext): $(srcdir)/fdmatch.c config.h $(INCDIR)/ansidecl.h \
 	$(INCDIR)/libiberty.h
 	if [ x"$(PICFLAG)" != x ]; then \
diff --git a/libiberty/cplus-dem.c b/libiberty/cplus-dem.c
index 52767cc..c68b981 100644
--- a/libiberty/cplus-dem.c
+++ b/libiberty/cplus-dem.c
@@ -306,6 +306,12 @@ const struct demangler_engine libiberty_demanglers[] =
   }
   ,
   {
+    DLANG_DEMANGLING_STYLE_STRING,
+    dlang_demangling,
+    "DLANG style demangling"
+  }
+  ,
+  {
     NULL, unknown_demangling, NULL
   }
 };
@@ -870,6 +876,13 @@ cplus_demangle (const char *mangled, int options)
   if (GNAT_DEMANGLING)
     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);
diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
new file mode 100644
index 0000000..d31bf94
--- /dev/null
+++ b/libiberty/d-demangle.c
@@ -0,0 +1,1338 @@
+/* Demangler for the D programming language
+   Copyright 2014 Free Software Foundation, Inc.
+   Written by Iain Buclaw (ibuclaw@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.
+
+   This file imports strtol and strtold for decoding mangled literals.  */
+
+#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>
+#else
+extern long strtol (const char *nptr, char **endptr, int base);
+extern long double strtold (const char *nptr, char **endptr);
+#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));
+    }
+}
+
+/* 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_symbol (string *, const char *);
+
+static const char *dlang_parse_tuple (string *, const char *);
+
+static const char *dlang_parse_template (string *, const char *, long);
+
+
+/* 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 mangled;
+
+  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;
+    default:
+      return NULL;
+    }
+
+  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 mangled;
+
+  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':
+	  /* inout parameter is represented as 'Ng'.
+	     vector parameter is represented as 'Nh'.
+	     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;
+	}
+      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 mangled;
+
+  /* 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++;
+	  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 ");
+	}
+
+      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 mangled;
+
+  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++;
+      mangled = dlang_type (decl, mangled);
+      string_append (decl, "*");
+      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_symbol (decl, mangled);
+    case 'D': /* delegate T */
+      mangled++;
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "delegate");
+      return mangled;
+    case 'B': /* tuple T */
+      mangled++;
+      return dlang_parse_tuple (decl, mangled);
+
+    /* Function types */
+    case 'F': case 'U': case 'W':
+    case 'V': case 'R':
+      mangled = dlang_function_type (decl, mangled);
+      string_append (decl, "function");
+      return 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;
+
+    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)
+{
+  if (mangled == NULL || *mangled == '\0')
+    return mangled;
+
+  if (ISDIGIT (*mangled))
+    {
+      char *endptr;
+      long i = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || i <= 0 || strlen (endptr) < (size_t) i)
+	return NULL;
+
+      mangled = endptr;
+
+      /* May be a template instance.  */
+      if (i >= 5 && strncmp (mangled, "__T", 3) == 0)
+	{
+	  /* Template symbol.  */
+	  if (ISDIGIT (mangled[3]) && mangled[3] != '0')
+	    return dlang_parse_template (decl, mangled, i);
+
+	  return NULL;
+	}
+
+      if (strncmp (mangled, "__ctor", i) == 0)
+	{
+	  /* Constructor symbol for a class/struct.  */
+	  string_append (decl, "this");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__dtor", i) == 0)
+	{
+	  /* Destructor symbol for a class/struct.  */
+	  string_append (decl, "~this");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__postblit", i) == 0)
+	{
+	  /* Postblit symbol for a struct.  */
+	  string_append (decl, "this(this)");
+	  mangled += i;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__initZ", i+1) == 0)
+	{
+	  /* The static initialiser for a given symbol.  */
+	  string_append (decl, "init$");
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__ClassZ", i+1) == 0)
+	{
+	  /* The classinfo symbol for a given class.  */
+	  string_prepend (decl, "ClassInfo for ");
+	  string_setlength (decl, string_length (decl) - 1);
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__vtblZ", i+1) == 0)
+	{
+	  /* The vtable symbol for a given class.  */
+	  string_prepend (decl, "vtable for ");
+	  string_setlength (decl, string_length (decl) - 1);
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__InterfaceZ", i+1) == 0)
+	{
+	  /* The interface symbol for a given class.  */
+	  string_prepend (decl, "Interface for ");
+	  string_setlength (decl, string_length (decl) - 1);
+	  mangled += i + 1;
+	  return mangled;
+	}
+      else if (strncmp (mangled, "__ModuleInfoZ", i+1) == 0)
+	{
+	  /* The ModuleInfo symbol for a given module.  */
+	  string_prepend (decl, "ModuleInfo for ");
+	  string_setlength (decl, string_length (decl) - 1);
+	  mangled += i + 1;
+	  return mangled;
+	}
+
+      string_appendn (decl, mangled, i);
+      mangled += i;
+    }
+  else
+    return NULL;
+
+  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;
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+	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, "'");
+      mangled = endptr;
+    }
+  else if (type == 'b')
+    {
+      /* Parse boolean value.  */
+      char *endptr;
+      long val = strtol (mangled, &endptr, 10);
+
+      if (endptr == NULL || val < 0)
+	return NULL;
+
+      string_append (decl, val ? "true" : "false");
+      mangled = endptr;
+    }
+  else
+    {
+      /* Parse integer value.  */
+      const char *numptr = mangled;
+      size_t num = 0;
+
+      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)
+{
+  char buffer[64];
+  int len = 0;
+  long double value;
+  char *endptr;
+
+  /* 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')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  if (!ISXDIGIT (*mangled))
+    return NULL;
+
+  buffer[len++] = '0';
+  buffer[len++] = 'x';
+  buffer[len++] = *mangled;
+  buffer[len++] = '.';
+  mangled++;
+
+  /* Significand.  */
+  while (ISXDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Exponent.  */
+  if (*mangled != 'P')
+    return NULL;
+
+  buffer[len++] = 'p';
+  mangled++;
+
+  if (*mangled == 'N')
+    {
+      buffer[len++] = '-';
+      mangled++;
+    }
+
+  while (ISDIGIT (*mangled))
+    {
+      buffer[len++] = *mangled;
+      mangled++;
+    }
+
+  /* Convert buffer from hexadecimal to floating-point.  */
+  buffer[len] = '\0';
+  value = strtold (buffer, &endptr);
+
+  if (endptr == NULL || endptr != (buffer + len))
+    return NULL;
+
+  len = snprintf (buffer, sizeof(buffer), "%#Lg", value);
+  string_appendn (decl, buffer, len);
+  return mangled;
+}
+
+/* Convert VAL from an ascii hexdigit to value.  */
+static char
+ascii2hex (char val)
+{
+  if (val >= 'a' && val <= 'f')
+    return (val - 'a' + 10);
+
+  if (val >= 'A' && val <= 'F')
+    return (val - 'A' + 10);
+
+  if (val >= '0' && val <= '9')
+    return (val - '0');
+
+  return 0;
+}
+
+/* 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;
+  char *endptr;
+  long len;
+
+  mangled++;
+  len = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || len < 0)
+    return NULL;
+
+  mangled = endptr;
+  if (*mangled != '_')
+    return NULL;
+
+  mangled++;
+  string_append (decl, "\"");
+  while (len--)
+    {
+      if (ISXDIGIT (mangled[0]) && ISXDIGIT (mangled[1]))
+	{
+	  char a = ascii2hex (mangled[0]);
+	  char b = ascii2hex (mangled[1]);
+	  char val = (a << 4) | b;
+	  string_appendn (decl, &val, 1);
+	}
+      else
+	return NULL;
+
+      mangled += 2;
+    }
+  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)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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)
+{
+  char *endptr;
+  long args = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || args < 0)
+    return NULL;
+
+  mangled = endptr;
+  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 mangled;
+
+  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++;
+      if (*mangled < '0' || *mangled > '9')
+	return NULL;
+      /* Fall through */
+    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;
+}
+
+static int
+dlang_call_convention_p (const char *mangled)
+{
+  size_t i;
+
+  switch (*mangled)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R':
+      return 1;
+
+    case 'M': /* Prefix for functions needing 'this' */
+      i = 1;
+      if (mangled[i] == 'x')
+	i++;
+
+      switch (mangled[i])
+	{
+	case 'F': case 'U': case 'V':
+	case 'W': case 'R':
+	  return 1;
+	}
+
+    default:
+      return 0;
+    }
+}
+
+/* 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_symbol (string *decl, const char *mangled)
+{
+  size_t n = 0;
+  do
+    {
+      if (n++)
+	string_append (decl, ".");
+
+      mangled = dlang_identifier (decl, mangled);
+
+      if (mangled && dlang_call_convention_p (mangled))
+	{
+	  int saved;
+
+	  /* Skip over 'this' parameter.  */
+	  if (*mangled == 'M')
+	    mangled += (mangled[1] == 'x') ? 2 : 1;
+
+	  /* Skip over calling convention and attributes in qualified name.  */
+	  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, ")");
+
+	  /* Demangle the function return type as a kind of sanity test.  */
+	  if (mangled && !ISDIGIT (*mangled))
+	    {
+	      saved = string_length (decl);
+	      mangled = dlang_type (decl, mangled);
+	      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)
+{
+  char *endptr;
+  long elements = strtol (mangled, &endptr, 10);
+
+  if (endptr == NULL || elements < 0)
+    return NULL;
+
+  mangled = endptr;
+  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, ", ");
+
+      switch (*mangled)
+	{
+	case 'S': /* Symbol parameter.  */
+	  mangled++;
+	  mangled = dlang_parse_symbol (decl, mangled);
+	  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
+		   ^
+     The start pointer should be at the above location, and LEN should be
+     the value of the decoded number.
+   */
+  if (strncmp (mangled, "__T", 3) != 0)
+    return NULL;
+
+  mangled += 3;
+
+  /* Template identifier.  */
+  mangled = dlang_identifier (decl, mangled);
+
+  /* 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
+    {
+      mangled += 2;
+
+      if (dlang_parse_symbol (&decl, mangled) == NULL)
+	string_delete (&decl);
+    }
+
+  if (string_length (&decl) > 0)
+    {
+      string_need (&decl, 1);
+      *(decl.p) = '\0';
+      demangled = decl.b;
+    }
+
+  return demangled;
+}
+
diff --git a/libiberty/testsuite/Makefile.in b/libiberty/testsuite/Makefile.in
index 69ac1f5..eb2bccc 100644
--- a/libiberty/testsuite/Makefile.in
+++ b/libiberty/testsuite/Makefile.in
@@ -45,12 +45,15 @@ all:
 # CHECK is set to "really_check" or the empty string by configure.
 check: @CHECK@
 
-really-check: check-cplus-dem check-pexecute check-expandargv
+really-check: check-cplus-dem check-d-demangle check-pexecute check-expandargv
 
 # Run some tests of the demangler.
 check-cplus-dem: test-demangle $(srcdir)/demangle-expected
 	./test-demangle < $(srcdir)/demangle-expected
 
+check-d-demangle: test-demangle $(srcdir)/d-demangle-expected
+	./test-demangle < $(srcdir)/d-demangle-expected
+
 # Check the pexecute code.
 check-pexecute: test-pexecute
 	./test-pexecute
diff --git a/libiberty/testsuite/d-demangle-expected b/libiberty/testsuite/d-demangle-expected
new file mode 100644
index 0000000..2aeacb8
--- /dev/null
+++ b/libiberty/testsuite/d-demangle-expected
@@ -0,0 +1,936 @@
+# This file holds test cases for the D demangler.
+# Each test case looks like this:
+#  options
+#  input to be demangled
+#  expected output
+#
+# See demangle-expected for documentation of supported options.
+#
+# A line starting with `#' is ignored.
+# However, blank lines in this file are NOT ignored.
+#
+############
+#
+# Coverage Tests
+#
+--format=dlang
+_Dmain
+D main
+#
+--format=dlang
+_D8demangle4testPFLAiYi
+demangle.test
+#
+--format=dlang
+_D8demangle4testFaZv
+demangle.test(char)
+#
+--format=dlang
+_D8demangle4testFbZv
+demangle.test(bool)
+#
+--format=dlang
+_D8demangle4testFcZv
+demangle.test(creal)
+#
+--format=dlang
+_D8demangle4testFdZv
+demangle.test(double)
+#
+--format=dlang
+_D8demangle4testFeZv
+demangle.test(real)
+#
+--format=dlang
+_D8demangle4testFfZv
+demangle.test(float)
+#
+--format=dlang
+_D8demangle4testFgZv
+demangle.test(byte)
+#
+--format=dlang
+_D8demangle4testFhZv
+demangle.test(ubyte)
+#
+--format=dlang
+_D8demangle4testFiZv
+demangle.test(int)
+#
+--format=dlang
+_D8demangle4testFjZv
+demangle.test(ireal)
+#
+--format=dlang
+_D8demangle4testFkZv
+demangle.test(uint)
+#
+--format=dlang
+_D8demangle4testFlZv
+demangle.test(long)
+#
+--format=dlang
+_D8demangle4testFmZv
+demangle.test(ulong)
+#
+--format=dlang
+_D8demangle4testFnZv
+demangle.test(none)
+#
+--format=dlang
+_D8demangle4testFoZv
+demangle.test(ifloat)
+#
+--format=dlang
+_D8demangle4testFpZv
+demangle.test(idouble)
+#
+--format=dlang
+_D8demangle4testFqZv
+demangle.test(cfloat)
+#
+--format=dlang
+_D8demangle4testFrZv
+demangle.test(cdouble)
+#
+--format=dlang
+_D8demangle4testFsZv
+demangle.test(short)
+#
+--format=dlang
+_D8demangle4testFtZv
+demangle.test(ushort)
+#
+--format=dlang
+_D8demangle4testFuZv
+demangle.test(wchar)
+#
+--format=dlang
+_D8demangle4testFvZv
+demangle.test(void)
+#
+--format=dlang
+_D8demangle4testFwZv
+demangle.test(dchar)
+#
+--format=dlang
+_D8demangle4testFOaZv
+demangle.test(shared(char))
+#
+--format=dlang
+_D8demangle4testFxaZv
+demangle.test(const(char))
+#
+--format=dlang
+_D8demangle4testFyaZv
+demangle.test(immutable(char))
+#
+--format=dlang
+_D8demangle4testFNgaZv
+demangle.test(inout(char))
+#
+--format=dlang
+_D8demangle4testFOxaZv
+demangle.test(shared(const(char)))
+#
+--format=dlang
+_D8demangle4testFONgaZv
+demangle.test(shared(inout(char)))
+#
+--format=dlang
+_D8demangle4testFAaZv
+demangle.test(char[])
+#
+--format=dlang
+_D8demangle4testFAAaZv
+demangle.test(char[][])
+#
+--format=dlang
+_D8demangle4testFAAAaZv
+demangle.test(char[][][])
+#
+--format=dlang
+_D8demangle4testFG42aZv
+demangle.test(char[42])
+#
+--format=dlang
+_D8demangle4testFG42G42aZv
+demangle.test(char[42][42])
+#
+--format=dlang
+_D8demangle4testFG42G42G42aZv
+demangle.test(char[42][42][42])
+#
+--format=dlang
+_D8demangle4testFG1234567890aZv
+demangle.test(char[1234567890])
+#
+--format=dlang
+_D8demangle4testFHaaZv
+demangle.test(char[char])
+#
+--format=dlang
+_D8demangle4testFHHaaaZv
+demangle.test(char[char[char]])
+#
+--format=dlang
+_D8demangle4testFPaZv
+demangle.test(char*)
+#
+--format=dlang
+_D8demangle4testFPPaZv
+demangle.test(char**)
+#
+--format=dlang
+_D8demangle4testFPPPaZv
+demangle.test(char***)
+#
+--format=dlang
+_D8demangle4testFNhG8gZv
+demangle.test(__vector(byte[8]))
+#
+--format=dlang
+_D8demangle4testFNhG16gZv
+demangle.test(__vector(byte[16]))
+#
+--format=dlang
+_D8demangle4testFNhG32gZv
+demangle.test(__vector(byte[32]))
+#
+--format=dlang
+_D8demangle4testFNhG4sZv
+demangle.test(__vector(short[4]))
+#
+--format=dlang
+_D8demangle4testFNhG8sZv
+demangle.test(__vector(short[8]))
+#
+--format=dlang
+_D8demangle4testFNhG16sZv
+demangle.test(__vector(short[16]))
+#
+--format=dlang
+_D8demangle4testFNhG2iZv
+demangle.test(__vector(int[2]))
+#
+--format=dlang
+_D8demangle4testFNhG4iZv
+demangle.test(__vector(int[4]))
+#
+--format=dlang
+_D8demangle4testFNhG8iZv
+demangle.test(__vector(int[8]))
+#
+--format=dlang
+_D8demangle4testFNhG1lZv
+demangle.test(__vector(long[1]))
+#
+--format=dlang
+_D8demangle4testFNhG2lZv
+demangle.test(__vector(long[2]))
+#
+--format=dlang
+_D8demangle4testFNhG4lZv
+demangle.test(__vector(long[4]))
+#
+--format=dlang
+_D8demangle4testFNhG2fZv
+demangle.test(__vector(float[2]))
+#
+--format=dlang
+_D8demangle4testFNhG4fZv
+demangle.test(__vector(float[4]))
+#
+--format=dlang
+_D8demangle4testFNhG8fZv
+demangle.test(__vector(float[8]))
+#
+--format=dlang
+_D8demangle4testFNhG1dZv
+demangle.test(__vector(double[1]))
+#
+--format=dlang
+_D8demangle4testFNhG2dZv
+demangle.test(__vector(double[2]))
+#
+--format=dlang
+_D8demangle4testFNhG4dZv
+demangle.test(__vector(double[4]))
+#
+--format=dlang
+_D8demangle4testFI5identZv
+demangle.test(ident)
+#
+--format=dlang
+_D8demangle4testFI5ident4testZv
+demangle.test(ident.test)
+#
+--format=dlang
+_D8demangle4testFC5classZv
+demangle.test(class)
+#
+--format=dlang
+_D8demangle4testFC5class4testZv
+demangle.test(class.test)
+#
+--format=dlang
+_D8demangle4testFS6structZv
+demangle.test(struct)
+#
+--format=dlang
+_D8demangle4testFS6struct4testZv
+demangle.test(struct.test)
+#
+--format=dlang
+_D8demangle4testFE4enumZv
+demangle.test(enum)
+#
+--format=dlang
+_D8demangle4testFE4enum4testZv
+demangle.test(enum.test)
+#
+--format=dlang
+_D8demangle4testFT7typedefZv
+demangle.test(typedef)
+#
+--format=dlang
+_D8demangle4testFT7typedef4testZv
+demangle.test(typedef.test)
+#
+--format=dlang
+_D8demangle4testFJaZv
+demangle.test(out char)
+#
+--format=dlang
+_D8demangle4testFKaZv
+demangle.test(ref char)
+#
+--format=dlang
+_D8demangle4testFLaZv
+demangle.test(lazy char)
+#
+--format=dlang
+_D8demangle4testFMaZv
+demangle.test(scope char)
+#
+--format=dlang
+_D8demangle4testFaXv
+demangle.test(char...)
+#
+--format=dlang
+_D8demangle4testFaYv
+demangle.test(char, ...)
+#
+--format=dlang
+_D8demangle4testFaaYv
+demangle.test(char, char, ...)
+#
+--format=dlang
+_D8demangle4testFaaZv
+demangle.test(char, char)
+#
+--format=dlang
+_D8demangle4testFB0Zv
+demangle.test(Tuple!())
+#
+--format=dlang
+_D8demangle4testFB1aZv
+demangle.test(Tuple!(char))
+#
+--format=dlang
+_D8demangle4testFB2aaZv
+demangle.test(Tuple!(char, char))
+#
+--format=dlang
+_D8demangle4testFB3aaaZv
+demangle.test(Tuple!(char, char, char))
+#
+--format=dlang
+_D8demangle4testFB2OaaZv
+demangle.test(Tuple!(shared(char), char))
+#
+--format=dlang
+_D8demangle4testFB3aDFZaaZv
+demangle.test(Tuple!(char, char() delegate, char))
+#
+--format=dlang
+_D8demangle4testFDFZaZv
+demangle.test(char() delegate)
+#
+--format=dlang
+_D8demangle4testFDUZaZv
+demangle.test(extern(C) char() delegate)
+#
+--format=dlang
+_D8demangle4testFDWZaZv
+demangle.test(extern(Windows) char() delegate)
+#
+--format=dlang
+_D8demangle4testFDVZaZv
+demangle.test(extern(Pascal) char() delegate)
+#
+--format=dlang
+_D8demangle4testFDRZaZv
+demangle.test(extern(C++) char() delegate)
+#
+--format=dlang
+_D8demangle4testFFZaZv
+demangle.test(char() function)
+#
+--format=dlang
+_D8demangle4testFUZaZv
+demangle.test(extern(C) char() function)
+#
+--format=dlang
+_D8demangle4testFWZaZv
+demangle.test(extern(Windows) char() function)
+#
+--format=dlang
+_D8demangle4testFVZaZv
+demangle.test(extern(Pascal) char() function)
+#
+--format=dlang
+_D8demangle4testFRZaZv
+demangle.test(extern(C++) char() function)
+#
+--format=dlang
+_D8demangle4testFDFNaZaZv
+demangle.test(char() pure delegate)
+#
+--format=dlang
+_D8demangle4testFDFNbZaZv
+demangle.test(char() nothrow delegate)
+#
+--format=dlang
+_D8demangle4testFDFNcZaZv
+demangle.test(char() ref delegate)
+#
+--format=dlang
+_D8demangle4testFDFNdZaZv
+demangle.test(char() @property delegate)
+#
+--format=dlang
+_D8demangle4testFDFNeZaZv
+demangle.test(char() @trusted delegate)
+#
+--format=dlang
+_D8demangle4testFDFNfZaZv
+demangle.test(char() @safe delegate)
+#
+--format=dlang
+_D8demangle4testFDFNiZaZv
+demangle.test(char() @nogc delegate)
+#
+--format=dlang
+_D8demangle4testFDFNaNbZaZv
+demangle.test(char() pure nothrow delegate)
+#
+--format=dlang
+_D8demangle4testFDFNbNaZaZv
+demangle.test(char() nothrow pure delegate)
+#
+--format=dlang
+_D8demangle4testFDFNdNfNaZaZv
+demangle.test(char() @property @safe pure delegate)
+#
+--format=dlang
+_D8demangle4testFFNaZaZv
+demangle.test(char() pure function)
+#
+--format=dlang
+_D8demangle4testFFNbZaZv
+demangle.test(char() nothrow function)
+#
+--format=dlang
+_D8demangle4testFFNcZaZv
+demangle.test(char() ref function)
+#
+--format=dlang
+_D8demangle4testFFNdZaZv
+demangle.test(char() @property function)
+#
+--format=dlang
+_D8demangle4testFFNeZaZv
+demangle.test(char() @trusted function)
+#
+--format=dlang
+_D8demangle4testFFNfZaZv
+demangle.test(char() @safe function)
+#
+--format=dlang
+_D8demangle4testFFNiZaZv
+demangle.test(char() @nogc function)
+#
+--format=dlang
+_D8demangle4testFFNaNbZaZv
+demangle.test(char() pure nothrow function)
+#
+--format=dlang
+_D8demangle4testFFNbNaZaZv
+demangle.test(char() nothrow pure function)
+#
+--format=dlang
+_D8demangle4testFFNdNfNaZaZv
+demangle.test(char() @property @safe pure function)
+#
+--format=dlang
+_D8demangle4test6__initZ
+demangle.test.init$
+#
+--format=dlang
+_D8demangle4test6__vtblZ
+vtable for demangle.test
+#
+--format=dlang
+_D8demangle4test7__ClassZ
+ClassInfo for demangle.test
+#
+--format=dlang
+_D8demangle4test11__InterfaceZ
+Interface for demangle.test
+#
+--format=dlang
+_D8demangle4test12__ModuleInfoZ
+ModuleInfo for demangle.test
+#
+--format=dlang
+_D8demangle4test6__ctorMFZv
+demangle.test.this()
+#
+--format=dlang
+_D8demangle4test6__dtorMFZv
+demangle.test.~this()
+#
+--format=dlang
+_D8demangle4test6__postblitMFZv
+demangle.test.this(this)
+#
+--format=dlang
+_D8demangle4testFHAbaZv
+demangle.test(char[bool[]])
+#
+--format=dlang
+_D8demangle4testFHG42caZv
+demangle.test(char[creal[42]])
+#
+--format=dlang
+_D8demangle4testFAiXv
+demangle.test(int[]...)
+#
+--format=dlang
+_D8demangle4testFLAiXv
+demangle.test(lazy int[]...)
+#
+--format=dlang
+_D8demangle4testFAiYv
+demangle.test(int[], ...)
+#
+--format=dlang
+_D8demangle4testFLAiYv
+demangle.test(lazy int[], ...)
+#
+--format=dlang
+_D8demangle4testFLilZv
+demangle.test(lazy int, long)
+#
+--format=dlang
+_D8demangle4testFLliZv
+demangle.test(lazy long, int)
+#
+--format=dlang
+_D8demangle4testFLC6ObjectLDFLiZiZi
+demangle.test(lazy Object, lazy int(lazy int) delegate)
+#
+--format=dlang
+_D8demangle9__T4testZv
+demangle.test!()
+#
+--format=dlang
+_D8demangle11__T4testTaZv
+demangle.test!(char)
+#
+--format=dlang
+_D8demangle13__T4testTaTaZv
+demangle.test!(char, char)
+#
+--format=dlang
+_D8demangle15__T4testTaTaTaZv
+demangle.test!(char, char, char)
+#
+--format=dlang
+_D8demangle16__T4testTaTOiTaZv
+demangle.test!(char, shared(int), char)
+#
+--format=dlang
+_D8demangle17__T4testS6symbolZv
+demangle.test!(symbol)
+#
+--format=dlang
+_D8demangle21__T4testS6symbol3fooZv
+demangle.test!(symbol.foo)
+#
+--format=dlang
+_D8demangle25__T4testS6symbol3foo3barZv
+demangle.test!(symbol.foo.bar)
+#
+--format=dlang
+_D8demangle19__T4testTaS6symbolZv
+demangle.test!(char, symbol)
+#
+--format=dlang
+_D8demangle19__T4testS6symbolTaZv
+demangle.test!(symbol, char)
+#
+--format=dlang
+_D8demangle13__T4testVPinZv
+demangle.test!(null)
+#
+--format=dlang
+_D8demangle14__T4testVg123Zv
+demangle.test!(123)
+#
+--format=dlang
+_D8demangle14__T4testVi123Zv
+demangle.test!(123)
+#
+--format=dlang
+_D8demangle14__T4testVs123Zv
+demangle.test!(123)
+#
+--format=dlang
+_D8demangle14__T4testVh123Zv
+demangle.test!(123u)
+#
+--format=dlang
+_D8demangle14__T4testVk123Zv
+demangle.test!(123u)
+#
+--format=dlang
+_D8demangle14__T4testVt123Zv
+demangle.test!(123u)
+#
+--format=dlang
+_D8demangle14__T4testVl123Zv
+demangle.test!(123L)
+#
+--format=dlang
+_D8demangle14__T4testVm123Zv
+demangle.test!(123uL)
+#
+--format=dlang
+_D8demangle15__T4testViN123Zv
+demangle.test!(-123)
+#
+--format=dlang
+_D8demangle15__T4testVkN123Zv
+demangle.test!(-123u)
+#
+--format=dlang
+_D8demangle15__T4testVlN123Zv
+demangle.test!(-123L)
+#
+--format=dlang
+_D8demangle15__T4testVmN123Zv
+demangle.test!(-123uL)
+#
+--format=dlang
+_D8demangle12__T4testVb1Zv
+demangle.test!(true)
+#
+--format=dlang
+_D8demangle12__T4testVb0Zv
+demangle.test!(false)
+#
+--format=dlang
+_D8demangle13__T4testVa10Zv
+demangle.test!('\x0a')
+#
+--format=dlang
+_D8demangle13__T4testVa32Zv
+demangle.test!(' ')
+#
+--format=dlang
+_D8demangle13__T4testVa65Zv
+demangle.test!('A')
+#
+--format=dlang
+_D8demangle14__T4testVa126Zv
+demangle.test!('~')
+#
+--format=dlang
+_D8demangle15__T4testVu1000Zv
+demangle.test!('\u03e8')
+#
+--format=dlang
+_D8demangle17__T4testVw100000Zv
+demangle.test!('\U000186a0')
+#
+--format=dlang
+_D8demangle17__T4testVde0A8P6Zv
+demangle.test!(42.0000)
+#
+--format=dlang
+_D8demangle16__T4testVdeA8P2Zv
+demangle.test!(42.0000)
+#
+--format=dlang
+_D8demangle18__T4testVdeN0A8P6Zv
+demangle.test!(-42.0000)
+#
+--format=dlang
+_D8demangle31__T4testVde0F6E978D4FDF3B646P7Zv
+demangle.test!(123.456)
+#
+--format=dlang
+_D8demangle15__T4testVdeNANZv
+demangle.test!(NaN)
+#
+--format=dlang
+_D8demangle15__T4testVdeINFZv
+demangle.test!(Inf)
+#
+--format=dlang
+_D8demangle16__T4testVdeNINFZv
+demangle.test!(-Inf)
+#
+--format=dlang
+_D8demangle23__T4testVfe0FFFFFFP128Zv
+demangle.test!(3.40282e+38)
+#
+--format=dlang
+_D8demangle32__T4testVde0FFFFFFFFFFFFF8P1024Zv
+demangle.test!(1.79769e+308)
+#
+--format=dlang
+_D8demangle19__T4testVfe08PN125Zv
+demangle.test!(1.17549e-38)
+#
+--format=dlang
+_D8demangle20__T4testVde08PN1021Zv
+demangle.test!(2.22507e-308)
+#
+--format=dlang
+_D8demangle51__T4testVrc0C4CCCCCCCCCCCCCDP4c0B666666666666666P6Zv
+demangle.test!(12.3000+45.6000i)
+#
+--format=dlang
+_D8demangle52__T4testVrcN0C4CCCCCCCCCCCCCDP4c0B666666666666666P6Zv
+demangle.test!(-12.3000+45.6000i)
+#
+--format=dlang
+_D8demangle22__T4testVG3ua3_616263Zv
+demangle.test!("abc")
+#
+--format=dlang
+_D8demangle22__T4testVG3ud3_616263Zv
+demangle.test!("abc"d)
+#
+--format=dlang
+_D8demangle22__T4testVG3uw3_616263Zv
+demangle.test!("abc"w)
+#
+--format=dlang
+_D8demangle22__T4testVAiA4i1i2i3i4Zv
+demangle.test!([1, 2, 3, 4])
+#
+--format=dlang
+_D8demangle25__T4testVAdA2e08P1eN08P1Zv
+demangle.test!([1.00000, -1.00000])
+#
+--format=dlang
+_D8demangle23__T4testVHiiA2i1i2i3i4Zv
+demangle.test!([1:2, 3:4])
+#
+--format=dlang
+_D8demangle39__T4testVHAxaiA2a3_616263i1a3_646566i2Zv
+demangle.test!(["abc":1, "def":2])
+#
+--format=dlang
+_D8demangle28__T4testVS8demangle1SS2i1i2Zv
+demangle.test!(demangle.S(1, 2))
+#
+--format=dlang
+_D8demangle35__T4testVS8demangle1SS2i1a3_616263Zv
+demangle.test!(demangle.S(1, "abc"))
+#
+# Unittests
+#
+--format=dlang
+printf
+printf
+#
+--format=dlang
+_foo
+_foo
+#
+--format=dlang
+_D88
+_D88
+#
+--format=dlang
+_D5__T1aZv
+_D5__T1aZv
+#
+--format=dlang
+_D4test3fooAa
+test.foo
+#
+--format=dlang
+_D8demangle8demangleFAaZAa
+demangle.demangle(char[])
+#
+--format=dlang
+_D6object6Object8opEqualsFC6ObjectZi
+object.Object.opEquals(Object)
+#
+--format=dlang
+_D6object6Object8opAssignFC6ObjectZi
+object.Object.opAssign(Object)
+#
+--format=dlang
+_D4test2dgDFiYd
+test.dg
+#
+--format=dlang
+_D1a1bi
+a.b
+#
+--format=dlang
+_D1a1bPFiZi
+a.b
+#
+--format=dlang
+_D4test34__T3barVG3uw3_616263VG3wd3_646566Z1xi
+test.bar!("abc"w, "def"d).x
+#
+--format=dlang
+_D6plugin8generateFiiZAya
+plugin.generate(int, int)
+#
+--format=dlang
+_D6plugin8generateFiiZAxa
+plugin.generate(int, int)
+#
+--format=dlang
+_D6plugin8generateFiiZAOa
+plugin.generate(int, int)
+#
+--format=dlang
+_D8demangle3fnAFZv3fnBMFZv
+demangle.fnA().fnB()
+#
+--format=dlang
+_D8demangle4mainFZv1S3fnCFZv
+demangle.main().S.fnC()
+#
+--format=dlang
+_D8demangle4mainFZv1S3fnDMFZv
+demangle.main().S.fnD()
+#
+--format=dlang
+_D8demangle4mainFZv5localMFZi
+demangle.main().local()
+#
+--format=dlang
+_D3std5ascii9uppercaseyAa
+std.ascii.uppercase
+#
+--format=dlang
+_D3std6stream9BOMEndianyG5E3std6system6Endian
+std.stream.BOMEndian
+#
+--format=dlang
+_D3std8internal7uni_tab10unicodeNkoyS3std8internal3uni12CodepointSet
+std.internal.uni_tab.unicodeNko
+#
+--format=dlang
+_D2gc2gc2GC6addrOfMFPvZPv
+gc.gc.GC.addrOf(void*)
+#
+--format=dlang
+_D3std7process10setCLOEXECFibZv
+std.process.setCLOEXEC(int, bool)
+#
+--format=dlang
+_D3std6digest2md3MD53putMFNaNbNeMAxhXv
+std.digest.md.MD5.put(scope const(ubyte)[]...)
+#
+--format=dlang
+_D3std6mmfile6MmFile13opIndexAssignMFhmZh
+std.mmfile.MmFile.opIndexAssign(ubyte, ulong)
+#
+--format=dlang
+_D3std7process18escapeShellCommandFxAAaXAya
+std.process.escapeShellCommand(const(char[][])...)
+#
+--format=dlang
+_D4core4sync5mutex5Mutex6__ctorMFC6ObjectZC4core4sync5mutex5Mutex
+core.sync.mutex.Mutex.this(Object)
+#
+--format=dlang
+_D6object14TypeInfo_Array8argTypesMFNbNfJC8TypeInfoJC8TypeInfoZi
+object.TypeInfo_Array.argTypes(out TypeInfo, out TypeInfo)
+#
+--format=dlang
+_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7tryExecMFMDFZvZv
+rt.dmain2._d_run_main(int, char**, extern(C) int(char[][]) function*).tryExec(scope void() delegate)
+#
+--format=dlang
+_D6object9Exception6__ctorMFNaNbNfAyaAyamC6object9ThrowableZC9Exception
+object.Exception.this(immutable(char)[], immutable(char)[], ulong, object.Throwable)
+#
+--format=dlang
+_D3gcc3deh17parse_lsda_headerFPS3gcc6unwind7generic15_Unwind_ContextPhPS3gcc3deh16lsda_header_infoZPh
+gcc.deh.parse_lsda_header(gcc.unwind.generic._Unwind_Context*, ubyte*, gcc.deh.lsda_header_info*)
+#
+--format=dlang
+_D3std6socket23UnknownAddressReference6__ctorMFPS4core3sys5posix3sys6socket8sockaddrkZC3std6socket23UnknownAddressReference
+std.socket.UnknownAddressReference.this(core.sys.posix.sys.socket.sockaddr*, uint)
+#
+--format=dlang
+_D8demangle20__T2fnVAiA4i1i2i3i4Z2fnFZv
+demangle.fn!([1, 2, 3, 4]).fn()
+#
+--format=dlang
+_D8demangle10__T2fnVi1Z2fnFZv
+demangle.fn!(1).fn()
+#
+--format=dlang
+_D8demangle26__T2fnVS8demangle1SS2i1i2Z2fnFZv
+demangle.fn!(demangle.S(1, 2)).fn()
+#
+--format=dlang
+_D8demangle13__T2fnVeeNANZ2fnFZv
+demangle.fn!(NaN).fn()
+#
+--format=dlang
+_D8demangle14__T2fnVeeNINFZ2fnFZv
+demangle.fn!(-Inf).fn()
+#
+--format=dlang
+_D8demangle13__T2fnVeeINFZ2fnFZv
+demangle.fn!(Inf).fn()
+#
+--format=dlang
+_D8demangle21__T2fnVHiiA2i1i2i3i4Z2fnFZv
+demangle.fn!([1:2, 3:4]).fn()
+#
+--format=dlang
+_D8demangle2fnFNgiZNgi
+demangle.fn(inout(int))
+#
+--format=dlang
+_D8demangle29__T2fnVa97Va9Va0Vu257Vw65537Z2fnFZv
+demangle.fn!('a', '\x09', '\x00', '\u0101', '\U00010001').fn()
+#
+--format=dlang
+_D2gc11gctemplates56__T8mkBitmapTS3std5range13__T4iotaTiTiZ4iotaFiiZ6ResultZ8mkBitmapFNbNiNfPmmZv
+gc.gctemplates.mkBitmap!(std.range.iota!(int, int).iota(int, int).Result).mkBitmap(ulong*, ulong)
+#
+--format=dlang
+_D8serenity9persister6Sqlite70__T15SqlitePersisterTS8serenity9persister6Sqlite11__unittest6FZv4TestZ15SqlitePersister12__T7opIndexZ7opIndexMFmZS8serenity9persister6Sqlite11__unittest6FZv4Test
+serenity.persister.Sqlite.SqlitePersister!(serenity.persister.Sqlite.__unittest6().Test).SqlitePersister.opIndex!().opIndex(ulong)
+#
+--format=dlang
+_D4test4mainFZv5localMFZi
+test.main().local()

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-04 15:53 ` Ian Lance Taylor
  2014-08-04 16:38   ` Iain Buclaw
@ 2014-09-19  7:51   ` Iain Buclaw
  2014-09-23 12:07     ` Iain Buclaw
  2014-09-23 18:36     ` Ian Lance Taylor
  1 sibling, 2 replies; 16+ messages in thread
From: Iain Buclaw @ 2014-09-19  7:51 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches

On 4 August 2014 16:52, Ian Lance Taylor <iant@google.com> wrote:
> On Sun, Aug 3, 2014 at 11:12 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>
>> - I haven't signed any copyright assignments to GCC.  But I have
>> papers from Donald ready to send across.
>
> Definitely necessary before we can consider this.  Please get this
> squared away before proceeding with this patch.  Let us know if you
> need any help with this.
>

I've been informed by FSF assignments that this has now been
processed.  Is there anything left for me to address technically about
this change?

Iain.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-09-19  7:51   ` Iain Buclaw
@ 2014-09-23 12:07     ` Iain Buclaw
  2014-09-23 18:36     ` Ian Lance Taylor
  1 sibling, 0 replies; 16+ messages in thread
From: Iain Buclaw @ 2014-09-23 12:07 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: gcc-patches, Tom Tromey

On 19 September 2014 08:51, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
> On 4 August 2014 16:52, Ian Lance Taylor <iant@google.com> wrote:
>> On Sun, Aug 3, 2014 at 11:12 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>>
>>> - I haven't signed any copyright assignments to GCC.  But I have
>>> papers from Donald ready to send across.
>>
>> Definitely necessary before we can consider this.  Please get this
>> squared away before proceeding with this patch.  Let us know if you
>> need any help with this.
>>
>
> I've been informed by FSF assignments that this has now been
> processed.  Is there anything left for me to address technically about
> this change?
>

Thought I might just ping on this, incase I have missed any response
from anyone.

Iain.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-09-19  7:51   ` Iain Buclaw
  2014-09-23 12:07     ` Iain Buclaw
@ 2014-09-23 18:36     ` Ian Lance Taylor
  1 sibling, 0 replies; 16+ messages in thread
From: Ian Lance Taylor @ 2014-09-23 18:36 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gcc-patches

On Fri, Sep 19, 2014 at 12:51 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
> On 4 August 2014 16:52, Ian Lance Taylor <iant@google.com> wrote:
>> On Sun, Aug 3, 2014 at 11:12 AM, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
>>>
>>> - I haven't signed any copyright assignments to GCC.  But I have
>>> papers from Donald ready to send across.
>>
>> Definitely necessary before we can consider this.  Please get this
>> squared away before proceeding with this patch.  Let us know if you
>> need any help with this.
>>
>
> I've been informed by FSF assignments that this has now been
> processed.  Is there anything left for me to address technically about
> this change?

No.  Reviewed, tested, approved, and committed to mainline.

Ian

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-08-05 11:58     ` Iain Buclaw
@ 2014-10-14 14:17       ` Joel Brobecker
  2014-10-14 14:52         ` Ian Lance Taylor
  0 siblings, 1 reply; 16+ messages in thread
From: Joel Brobecker @ 2014-10-14 14:17 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: Ian Lance Taylor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1208 bytes --]

Hello Ian,

> libiberty/ChangeLog
> 2014-08-05  Iain Buclaw  <ibuclaw@gdcproject.org>
> 
>     * Makefile.in (CFILES): Add d-demangle.c.
>     (REQUIRED_OFILES): Add d-demangle.o.
>     * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case.
>     (cplus_demangle): Likewise.
>     * d-demangle.c: New file.
>     * testsuite/Makefile.in (really-check): Add check-d-demangle.
>     * testsuite/d-demangle-expected: New file.

As hinted on gdb-patches, this patch causes a GDB build failure
on Solaris 2.9, because it uses strtold which is not available.
According to gnulib's documentation, it should also break on
the following systems:

        NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, IRIX 6.5, OSF/1 4.0,
        Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS.

This patch attempts to fix the issue by adding a configure check
for strtold and adjusts the code to use strtod if strtold does not
exist.

Does this look OK to you? If yes, can one of the GCC maintainers
please review?

libiberty/ChangeLog:

        * configure.ac: Add check for strtold's availability.
        * configure, config.in: Regenerate.
        * d-demangle.c [!HAVE_STRTOLD]: #define strtold to strtod.

Thank you!

-- 
Joel

[-- Attachment #2: 0001-libiberty-fallback-on-strtod-if-strtold-is-not-avail.patch --]
[-- Type: text/x-diff, Size: 2778 bytes --]

From 9e4d74607075ef857dfa4e118f43641494aaff90 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Tue, 14 Oct 2014 09:54:05 -0400
Subject: [PATCH] libiberty: fallback on strtod if strtold is not available.

This patch fixes a build failurer on Solaris 2.9, and all other
systems that do not provide strtold.

libiberty/ChangeLog:

        * configure.ac: Add check for strtold's availability.
        * configure, config.in: Regenerate.
        * d-demangle.c [!HAVE_STRTOLD]: #define strtold to strtod.
---
 libiberty/config.in    | 3 +++
 libiberty/configure    | 2 +-
 libiberty/configure.ac | 2 +-
 libiberty/d-demangle.c | 3 +++
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/libiberty/configure.ac b/libiberty/configure.ac
index 3380819..da20a5f 100644
--- a/libiberty/configure.ac
+++ b/libiberty/configure.ac
@@ -401,7 +401,7 @@ if test "x" = "y"; then
     sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
      stpcpy stpncpy strcasecmp strchr strdup \
      strerror strncasecmp strndup strnlen strrchr strsignal strstr strtod \
-     strtol strtoul strverscmp sysconf sysctl sysmp \
+     strtol strtold strtoul strverscmp sysconf sysctl sysmp \
     table times tmpnam \
     vasprintf vfprintf vprintf vsprintf \
     wait3 wait4 waitpid)
diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
index d31bf94..59de083 100644
--- a/libiberty/d-demangle.c
+++ b/libiberty/d-demangle.c
@@ -46,6 +46,9 @@ If not, see <http://www.gnu.org/licenses/>.  */
 extern long strtol (const char *nptr, char **endptr, int base);
 extern long double strtold (const char *nptr, char **endptr);
 #endif
+#if !defined(HAVE_STRTOLD)
+#define strtold strtod
+#endif
 
 #include <demangle.h>
 #include "libiberty.h"
diff --git a/libiberty/config.in b/libiberty/config.in
index 1cf9c11..8c5f0b6 100644
--- a/libiberty/config.in
+++ b/libiberty/config.in
@@ -280,6 +280,9 @@
 /* Define to 1 if you have the `strtol' function. */
 #undef HAVE_STRTOL
 
+/* Define to 1 if you have the `strtold' function. */
+#undef HAVE_STRTOLD
+
 /* Define to 1 if you have the `strtoul' function. */
 #undef HAVE_STRTOUL
 
diff --git a/libiberty/configure b/libiberty/configure
index 96feaed..072b03b 100755
--- a/libiberty/configure
+++ b/libiberty/configure
@@ -5423,7 +5423,7 @@ if test "x" = "y"; then
     sbrk setenv setproctitle setrlimit sigsetmask snprintf spawnve spawnvpe \
      stpcpy stpncpy strcasecmp strchr strdup \
      strerror strncasecmp strndup strnlen strrchr strsignal strstr strtod \
-     strtol strtoul strverscmp sysconf sysctl sysmp \
+     strtol strtold strtoul strverscmp sysconf sysctl sysmp \
     table times tmpnam \
     vasprintf vfprintf vprintf vsprintf \
     wait3 wait4 waitpid
-- 
1.9.1


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 14:17       ` Joel Brobecker
@ 2014-10-14 14:52         ` Ian Lance Taylor
  2014-10-14 16:37           ` Iain Buclaw
  0 siblings, 1 reply; 16+ messages in thread
From: Ian Lance Taylor @ 2014-10-14 14:52 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Iain Buclaw, gcc-patches

On Tue, Oct 14, 2014 at 7:12 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>
>> libiberty/ChangeLog
>> 2014-08-05  Iain Buclaw  <ibuclaw@gdcproject.org>
>>
>>     * Makefile.in (CFILES): Add d-demangle.c.
>>     (REQUIRED_OFILES): Add d-demangle.o.
>>     * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case.
>>     (cplus_demangle): Likewise.
>>     * d-demangle.c: New file.
>>     * testsuite/Makefile.in (really-check): Add check-d-demangle.
>>     * testsuite/d-demangle-expected: New file.
>
> As hinted on gdb-patches, this patch causes a GDB build failure
> on Solaris 2.9, because it uses strtold which is not available.
> According to gnulib's documentation, it should also break on
> the following systems:
>
>         NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, IRIX 6.5, OSF/1 4.0,
>         Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS.
>
> This patch attempts to fix the issue by adding a configure check
> for strtold and adjusts the code to use strtod if strtold does not
> exist.
>
> Does this look OK to you? If yes, can one of the GCC maintainers
> please review?

It doesn't make sense to me to use strtod if strtold is required.  And
if strtold is not required, then it seems to me that we should always
use strtod.  It seems to me that the right options are either 1) use
strtod unconditionally; 2) add strtold to libiberty

Since option 1 is simpler, what bad things would happen if we use
strtod unconditionally?

Ian

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 14:52         ` Ian Lance Taylor
@ 2014-10-14 16:37           ` Iain Buclaw
  2014-10-14 17:14             ` Joel Brobecker
  0 siblings, 1 reply; 16+ messages in thread
From: Iain Buclaw @ 2014-10-14 16:37 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Joel Brobecker, gcc-patches

On 14 October 2014 15:28, Ian Lance Taylor <iant@google.com> wrote:
> On Tue, Oct 14, 2014 at 7:12 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>>
>>> libiberty/ChangeLog
>>> 2014-08-05  Iain Buclaw  <ibuclaw@gdcproject.org>
>>>
>>>     * Makefile.in (CFILES): Add d-demangle.c.
>>>     (REQUIRED_OFILES): Add d-demangle.o.
>>>     * cplus-dem.c (libiberty_demanglers): Add dlang_demangling case.
>>>     (cplus_demangle): Likewise.
>>>     * d-demangle.c: New file.
>>>     * testsuite/Makefile.in (really-check): Add check-d-demangle.
>>>     * testsuite/d-demangle-expected: New file.
>>
>> As hinted on gdb-patches, this patch causes a GDB build failure
>> on Solaris 2.9, because it uses strtold which is not available.
>> According to gnulib's documentation, it should also break on
>> the following systems:
>>
>>         NetBSD 3.0, OpenBSD 3.8, Minix 3.1.8, IRIX 6.5, OSF/1 4.0,
>>         Solaris 9, Cygwin, MSVC 9, Interix 3.5, BeOS.
>>
>> This patch attempts to fix the issue by adding a configure check
>> for strtold and adjusts the code to use strtod if strtold does not
>> exist.
>>
>> Does this look OK to you? If yes, can one of the GCC maintainers
>> please review?
>
> It doesn't make sense to me to use strtod if strtold is required.  And
> if strtold is not required, then it seems to me that we should always
> use strtod.  It seems to me that the right options are either 1) use
> strtod unconditionally; 2) add strtold to libiberty
>
> Since option 1 is simpler, what bad things would happen if we use
> strtod unconditionally?
>
> Ian

I've just seen this, so I'll repeat what I've said in gdb patches too.

The call to strtold is only needed to decode templates which have a
floating point value encoded inside. This value may or may not have a
greater than double precision.

Replacing long double with double will be fine with me.  I'll accept
that I didn't consider legacy in hindsight, and in reality it would be
rather rare to stumble upon the need for strtold.

Regards
Iain

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 16:37           ` Iain Buclaw
@ 2014-10-14 17:14             ` Joel Brobecker
  2014-10-14 17:33               ` Ian Lance Taylor
  2014-10-14 17:40               ` Iain Buclaw
  0 siblings, 2 replies; 16+ messages in thread
From: Joel Brobecker @ 2014-10-14 17:14 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: Ian Lance Taylor, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1140 bytes --]

> I've just seen this, so I'll repeat what I've said in gdb patches too.
> 
> The call to strtold is only needed to decode templates which have a
> floating point value encoded inside. This value may or may not have a
> greater than double precision.
> 
> Replacing long double with double will be fine with me.  I'll accept
> that I didn't consider legacy in hindsight, and in reality it would be
> rather rare to stumble upon the need for strtold.

Attached is a patch that switches it to strtod. Do you have any
test that could quickly verify it? That seems to be the best
approach, at least short-term. Later on, if we do want to use
higher precision, we can indeed add strtold in libiberty.

libiberty/ChangeLog:

        * d-demangle.c: Replace strtold with strtod in global comment.
        (strtold): Remove declaration.
        (strtod): New declaration.
        (dlang_parse_real): Declare value as double instead of long
        double.  Replace call to strtold by call to strtod.
        Update format in call to snprintf.

I verified that the patch allows GDB to build on both sparc-solaris
and x86_64-linux.

Thanks,
-- 
Joel

[-- Attachment #2: 0001-Use-strtod-instead-of-strtold-in-libiberty-d-demangl.patch --]
[-- Type: text/x-diff, Size: 2479 bytes --]

From 99f9794c6d2f4dabed0bbcf2cf362b1eb25ee2a7 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Tue, 14 Oct 2014 12:47:43 -0400
Subject: [PATCH] Use strtod instead of strtold in libiberty/d-demangle.c

strtold is currently used to decode templates which have a floating-point
value encoded inside; but this routine is not available on some systems,
such as Solaris 2.9 for instance.

This patch fixes the issue by replace the use of strtold by strtod.
It reduces a bit the precision, but it should still remain acceptable
in most cases.

libiberty/ChangeLog:

        * d-demangle.c: Replace strtold with strtod in global comment.
        (strtold): Remove declaration.
        (strtod): New declaration.
        (dlang_parse_real): Declare value as double instead of long
        double.  Replace call to strtold by call to strtod.
        Update format in call to snprintf.
---
 libiberty/d-demangle.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/libiberty/d-demangle.c b/libiberty/d-demangle.c
index d31bf94..bb481c0 100644
--- a/libiberty/d-demangle.c
+++ b/libiberty/d-demangle.c
@@ -28,7 +28,7 @@ If not, see <http://www.gnu.org/licenses/>.  */
 
 /* This file exports one function; dlang_demangle.
 
-   This file imports strtol and strtold for decoding mangled literals.  */
+   This file imports strtol and strtod for decoding mangled literals.  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -44,7 +44,7 @@ If not, see <http://www.gnu.org/licenses/>.  */
 #include <stdlib.h>
 #else
 extern long strtol (const char *nptr, char **endptr, int base);
-extern long double strtold (const char *nptr, char **endptr);
+extern double strtod (const char *nptr, char **endptr);
 #endif
 
 #include <demangle.h>
@@ -810,7 +810,7 @@ dlang_parse_real (string *decl, const char *mangled)
 {
   char buffer[64];
   int len = 0;
-  long double value;
+  double value;
   char *endptr;
 
   /* Handle NAN and +-INF.  */
@@ -877,12 +877,12 @@ dlang_parse_real (string *decl, const char *mangled)
 
   /* Convert buffer from hexadecimal to floating-point.  */
   buffer[len] = '\0';
-  value = strtold (buffer, &endptr);
+  value = strtod (buffer, &endptr);
 
   if (endptr == NULL || endptr != (buffer + len))
     return NULL;
 
-  len = snprintf (buffer, sizeof(buffer), "%#Lg", value);
+  len = snprintf (buffer, sizeof(buffer), "%#g", value);
   string_appendn (decl, buffer, len);
   return mangled;
 }
-- 
1.7.9.5


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 17:14             ` Joel Brobecker
@ 2014-10-14 17:33               ` Ian Lance Taylor
  2014-10-14 18:02                 ` Joel Brobecker
  2014-10-14 17:40               ` Iain Buclaw
  1 sibling, 1 reply; 16+ messages in thread
From: Ian Lance Taylor @ 2014-10-14 17:33 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Iain Buclaw, gcc-patches

On Tue, Oct 14, 2014 at 10:07 AM, Joel Brobecker <brobecker@adacore.com> wrote:
>
> libiberty/ChangeLog:
>
>         * d-demangle.c: Replace strtold with strtod in global comment.
>         (strtold): Remove declaration.
>         (strtod): New declaration.
>         (dlang_parse_real): Declare value as double instead of long
>         double.  Replace call to strtold by call to strtod.
>         Update format in call to snprintf.

This is OK.

Thanks.

Ian

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 17:14             ` Joel Brobecker
  2014-10-14 17:33               ` Ian Lance Taylor
@ 2014-10-14 17:40               ` Iain Buclaw
  1 sibling, 0 replies; 16+ messages in thread
From: Iain Buclaw @ 2014-10-14 17:40 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: Ian Lance Taylor, gcc-patches

On 14 October 2014 18:07, Joel Brobecker <brobecker@adacore.com> wrote:
>> I've just seen this, so I'll repeat what I've said in gdb patches too.
>>
>> The call to strtold is only needed to decode templates which have a
>> floating point value encoded inside. This value may or may not have a
>> greater than double precision.
>>
>> Replacing long double with double will be fine with me.  I'll accept
>> that I didn't consider legacy in hindsight, and in reality it would be
>> rather rare to stumble upon the need for strtold.
>
> Attached is a patch that switches it to strtod. Do you have any
> test that could quickly verify it? That seems to be the best
> approach, at least short-term. Later on, if we do want to use
> higher precision, we can indeed add strtold in libiberty.
>

See d-demangle-expected in the libiberty testsuite, in particular:

_D8demangle17__T4testVde0A8P6Zv
demangle.test!(42.0000)

_D8demangle16__T4testVdeA8P2Zv
demangle.test!(42.0000)

_D8demangle18__T4testVdeN0A8P6Zv
demangle.test!(-42.0000)

_D8demangle31__T4testVde0F6E978D4FDF3B646P7Zv
demangle.test!(123.456)


I doubt they would need adjusting.

Regards
Iain

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH] Add D demangling support to libiberty
  2014-10-14 17:33               ` Ian Lance Taylor
@ 2014-10-14 18:02                 ` Joel Brobecker
  0 siblings, 0 replies; 16+ messages in thread
From: Joel Brobecker @ 2014-10-14 18:02 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Iain Buclaw, gcc-patches

> > libiberty/ChangeLog:
> >
> >         * d-demangle.c: Replace strtold with strtod in global comment.
> >         (strtold): Remove declaration.
> >         (strtod): New declaration.
> >         (dlang_parse_real): Declare value as double instead of long
> >         double.  Replace call to strtold by call to strtod.
> >         Update format in call to snprintf.
> 
> This is OK.

Thanks, Ian. As suggested by Iain, I re-ran the libiberty
testsuite on x86_64-linux before committing the patch.

Thank you both!
-- 
Joel

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2014-10-14 18:01 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-03 18:13 [PATCH] Add D demangling support to libiberty Iain Buclaw
2014-08-04 15:53 ` Ian Lance Taylor
2014-08-04 16:38   ` Iain Buclaw
2014-08-05 11:58     ` Iain Buclaw
2014-10-14 14:17       ` Joel Brobecker
2014-10-14 14:52         ` Ian Lance Taylor
2014-10-14 16:37           ` Iain Buclaw
2014-10-14 17:14             ` Joel Brobecker
2014-10-14 17:33               ` Ian Lance Taylor
2014-10-14 18:02                 ` Joel Brobecker
2014-10-14 17:40               ` Iain Buclaw
2014-09-19  7:51   ` Iain Buclaw
2014-09-23 12:07     ` Iain Buclaw
2014-09-23 18:36     ` Ian Lance Taylor
2014-08-04 16:06 ` Tom Tromey
2014-08-04 16:38   ` Iain Buclaw

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).