public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add d_main_name to dlang.c
@ 2013-11-19  1:53 Iain Buclaw
  2013-11-19 16:09 ` Tom Tromey
  0 siblings, 1 reply; 9+ messages in thread
From: Iain Buclaw @ 2013-11-19  1:53 UTC (permalink / raw)
  To: gdb-patches

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

Hi,

This is the first patch of a few that will eventually get sent across
as I write them.  Adds support for gdb to discover the source location
of D main function.

Regards,
Iain.

[-- Attachment #2: dmain-name.patch --]
[-- Type: text/x-patch, Size: 1994 bytes --]

--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2013-11-18  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+	* d-lang.h (d_main_name): Add declaration.
+	* d-lang.c (d_main_name): New function.
+	* symtab.c (find_main_name): Add call to d_main_name.
+
 2013-11-18  Tom Tromey  <tromey@redhat.com>
 
 	* common/gdb_stat.h: Remove.
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 35d92ea..d8067f2 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -29,6 +29,27 @@
 
 #include <ctype.h>
 
+/* The main function in the main package.  */
+static const char D_MAIN[] = "D main";
+
+/* Function returning the special symbol name used by D for the main
+   procedure in the main program if it is found in minimal symbol list.
+   This function tries to find minimal symbols so that it finds them even
+   if the program was compiled without debugging information.  */
+
+const char *
+d_main_name (void)
+{
+  struct minimal_symbol *msym;
+
+  msym = lookup_minimal_symbol (D_MAIN, NULL, NULL);
+  if (msym != NULL)
+    return D_MAIN;
+
+  /* No known entry procedure found, the main program is probably not D.  */
+  return NULL;
+}
+
 /* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
    Return 1 on success or 0 on failure.  */
 static int
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index fb6678a..4933431 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -22,6 +22,10 @@
 
 #include "symtab.h"
 
+/* Defined in d-lang.c  */
+
+extern const char *d_main_name (void);
+
 extern char *d_demangle (const char *mangled, int options);
 
 extern void d_val_print (struct type *type, const gdb_byte *valaddr,
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 8fac0be..6467313 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5018,6 +5018,13 @@ find_main_name (void)
       return;
     }
 
+  new_main_name = d_main_name ();
+  if (new_main_name != NULL)
+    {
+      set_main_name (new_main_name);
+      return;
+    }
+
   new_main_name = go_main_name ();
   if (new_main_name != NULL)
     {

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

* Re: [PATCH] Add d_main_name to dlang.c
  2013-11-19  1:53 [PATCH] Add d_main_name to dlang.c Iain Buclaw
@ 2013-11-19 16:09 ` Tom Tromey
  2013-11-19 17:50   ` Iain Buclaw
  0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2013-11-19 16:09 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gdb-patches

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

Iain> +2013-11-18  Iain Buclaw  <ibuclaw@gdcproject.org>
Iain> +
Iain> +	* d-lang.h (d_main_name): Add declaration.
Iain> +	* d-lang.c (d_main_name): New function.
Iain> +	* symtab.c (find_main_name): Add call to d_main_name.

Looks good to me.

Do you have a copyright assignment on file?
If not, contact me off-list and I'll get you started.

Tom

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

* Re: [PATCH] Add d_main_name to dlang.c
  2013-11-19 16:09 ` Tom Tromey
@ 2013-11-19 17:50   ` Iain Buclaw
  2013-11-19 18:06     ` Tom Tromey
  0 siblings, 1 reply; 9+ messages in thread
From: Iain Buclaw @ 2013-11-19 17:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb-patches

On 19 November 2013 15:52, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Iain" == Iain Buclaw <ibuclaw@gdcproject.org> writes:
>
> Iain> +2013-11-18  Iain Buclaw  <ibuclaw@gdcproject.org>
> Iain> +
> Iain> + * d-lang.h (d_main_name): Add declaration.
> Iain> + * d-lang.c (d_main_name): New function.
> Iain> + * symtab.c (find_main_name): Add call to d_main_name.
>
> Looks good to me.
>
> Do you have a copyright assignment on file?
> If not, contact me off-list and I'll get you started.
>
> Tom

By the way, it is more preferable to use the mangled name of the D
main function (_Dmain), or the pretty debug de-mangled name?  Both
work just as well in achieving the job.


Regards
Iain

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

* Re: [PATCH] Add d_main_name to dlang.c
  2013-11-19 17:50   ` Iain Buclaw
@ 2013-11-19 18:06     ` Tom Tromey
  2013-11-19 21:05       ` Pierre Muller
       [not found]       ` <39451.43601527$1384894769@news.gmane.org>
  0 siblings, 2 replies; 9+ messages in thread
From: Tom Tromey @ 2013-11-19 18:06 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gdb-patches

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

Iain> By the way, it is more preferable to use the mangled name of the D
Iain> main function (_Dmain), or the pretty debug de-mangled name?  Both
Iain> work just as well in achieving the job.

I don't think it matters.

I forgot to ask for a test case.  There really should be one.

Tom

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

* RE: [PATCH] Add d_main_name to dlang.c
  2013-11-19 18:06     ` Tom Tromey
@ 2013-11-19 21:05       ` Pierre Muller
       [not found]       ` <39451.43601527$1384894769@news.gmane.org>
  1 sibling, 0 replies; 9+ messages in thread
From: Pierre Muller @ 2013-11-19 21:05 UTC (permalink / raw)
  To: 'Tom Tromey', 'Iain Buclaw'; +Cc: gdb-patches



> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Tom Tromey
> Envoyé : mardi 19 novembre 2013 15:49
> À : Iain Buclaw
> Cc : gdb-patches@sourceware.org
> Objet : Re: [PATCH] Add d_main_name to dlang.c
> 
> >>>>> "Iain" == Iain Buclaw <ibuclaw@gdcproject.org> writes:
> 
> Iain> By the way, it is more preferable to use the mangled name of the
> D
> Iain> main function (_Dmain), or the pretty debug de-mangled name?
> Both
> Iain> work just as well in achieving the job.
> 
> I don't think it matters.

  I thought that in general, using the mangled name
would allow to find main even if you do not generate
any debug information, as long as you do not remove the
assembler symbols from the executable.
  This seems like a valid reason to prefer mangled name
over demangled, no?

Pierre

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

* Re: [PATCH] Add d_main_name to dlang.c
       [not found]       ` <39451.43601527$1384894769@news.gmane.org>
@ 2013-11-19 21:08         ` Tom Tromey
  2014-01-03 18:18           ` Iain Buclaw
  0 siblings, 1 reply; 9+ messages in thread
From: Tom Tromey @ 2013-11-19 21:08 UTC (permalink / raw)
  To: Pierre Muller; +Cc: 'Iain Buclaw', gdb-patches

Pierre>   I thought that in general, using the mangled name
Pierre> would allow to find main even if you do not generate
Pierre> any debug information, as long as you do not remove the
Pierre> assembler symbols from the executable.
Pierre>   This seems like a valid reason to prefer mangled name
Pierre> over demangled, no?

The demangled name ends up in the minimal symbol table as well.
It's convoluted but it ends up in symbol_find_demangled_name, which has
a case for language_d.

Tom

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

* Re: [PATCH] Add d_main_name to dlang.c
  2013-11-19 21:08         ` Tom Tromey
@ 2014-01-03 18:18           ` Iain Buclaw
  2014-01-07  9:53             ` Iain Buclaw
  0 siblings, 1 reply; 9+ messages in thread
From: Iain Buclaw @ 2014-01-03 18:18 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pierre Muller, gdb-patches

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

On 19 November 2013 21:03, Tom Tromey <tromey@redhat.com> wrote:
> Pierre>   I thought that in general, using the mangled name
> Pierre> would allow to find main even if you do not generate
> Pierre> any debug information, as long as you do not remove the
> Pierre> assembler symbols from the executable.
> Pierre>   This seems like a valid reason to prefer mangled name
> Pierre> over demangled, no?
>
> The demangled name ends up in the minimal symbol table as well.
> It's convoluted but it ends up in symbol_find_demangled_name, which has
> a case for language_d.
>
> Tom

Hi Tom,

(I've just realised that I my last reply was not cc'd into gdb-patches)

The assignments should now be processed.

Since November, I've made a few more changes that are reflected in
this new patch.

I would add some more tests for D, but I feel that should write a
complete parser for D expressions first (d-exp.y) - this will be done
at a later date.

Regards
Iain.

[-- Attachment #2: dsupport.patch --]
[-- Type: text/x-diff, Size: 55263 bytes --]

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index db32995..5dfc561 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,21 @@
+2014-01-03  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+	* d-lang.h (d_main_name, builtin_d_type)
+	(d_parse_symbol): Add declarations.
+	(struct builtin_d_type): New data type.
+	* d-lang.c (d_main_name, d_language_arch_info)
+	(build_d_types, builtin_d_type): New functions.
+	(enum d_primitive_types): New data type.
+	(d_language_defn): Update to use d_language_arch_info and
+	macro_expansion_no.
+	(d_type_data): New static variable.
+	(_initialize_d_language): Initialize d_type_data.
+	(extract_identifiers, extract_type_info): Remove functions.
+	(d_demangle): Use d_parse_symbol implemented in d-support.c to
+	demangle D symbols.
+	* d-support.c: New file.
+	* symtab.c (find_main_name): Add call to d_main_name.
+
 2014-01-01  Joel Brobecker  <brobecker@adacore.com>
 
 	Update year range in copyright notice of all files.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 824b26b..f557bfe 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -727,7 +727,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	charset.c cleanups.c cli-out.c coffread.c coff-pe-read.c \
 	complaints.c completer.c continuations.c corefile.c corelow.c \
 	cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
-	d-lang.c d-valprint.c \
+	d-lang.c d-support.c d-valprint.c \
 	cp-name-parser.y \
 	dbxread.c demangle.c dictionary.c disasm.c doublest.c dummy-frame.c \
 	dwarf2expr.c dwarf2loc.c dwarf2read.c dwarf2-frame.c \
@@ -947,6 +947,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	inline-frame.o \
 	gnu-v2-abi.o gnu-v3-abi.o cp-abi.o cp-support.o \
 	cp-namespace.o \
+	d-support.o \
 	reggroups.o regset.o \
 	trad-frame.o \
 	tramp-frame.o \
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 13b5438..5d61d02 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -23,111 +23,28 @@
 #include "varobj.h"
 #include "d-lang.h"
 #include "c-lang.h"
-#include <string.h>
 #include "parser-defs.h"
 #include "gdb_obstack.h"
 
-#include <ctype.h>
+/* The name of the symbol to use to get the name of the main subprogram.  */
+static const char D_MAIN[] = "D main";
 
-/* Extract identifiers from MANGLED_STR and append it to TEMPBUF.
-   Return 1 on success or 0 on failure.  */
-static int
-extract_identifiers (const char *mangled_str, struct obstack *tempbuf)
+/* Function returning the special symbol name used by D for the main
+   procedure in the main program if it is found in minimal symbol list.
+   This function tries to find minimal symbols so that it finds them even
+   if the program was compiled without debugging information.  */
+
+const char *
+d_main_name (void)
 {
-  long i = 0;
+  struct minimal_symbol *msym;
 
-  while (isdigit (*mangled_str))
-    {
-      char *end_ptr;
-
-      i = strtol (mangled_str, &end_ptr, 10);
-      mangled_str = end_ptr;
-      if (i <= 0 || strlen (mangled_str) < i)
-        return 0;
-      obstack_grow (tempbuf, mangled_str, i);
-      mangled_str += i;
-      obstack_grow_str (tempbuf, ".");
-    }
-  if (*mangled_str == '\0' || i == 0)
-    return 0;
-  obstack_blank (tempbuf, -1);
-  return 1;
-}
+  msym = lookup_minimal_symbol (D_MAIN, NULL, NULL);
+  if (msym != NULL)
+    return D_MAIN;
 
-/* Extract and demangle type from MANGLED_STR and append it to TEMPBUF.
-   Return 1 on success or 0 on failure.  */
-static int
-extract_type_info (const char *mangled_str, struct obstack *tempbuf)
-{
-  if (*mangled_str == '\0')
-    return 0;
-  switch (*mangled_str++)
-    {
-      case 'A': /* dynamic array */
-      case 'G': /* static array */
-      case 'H': /* associative array */
-	if (!extract_type_info (mangled_str, tempbuf))
-	  return 0;
-	obstack_grow_str (tempbuf, "[]");
-	return 1;
-      case 'P': /* pointer */
-	if (!extract_type_info (mangled_str, tempbuf))
-	  return 0;
-	obstack_grow_str (tempbuf, "*");
-	return 1;
-      case 'R': /* reference */
-	if (!extract_type_info (mangled_str, tempbuf))
-	  return 0;
-	obstack_grow_str (tempbuf, "&");
-	return 1;
-      case 'Z': /* return value */
-	return extract_type_info (mangled_str, tempbuf);
-      case 'J': /* out */
-	obstack_grow_str (tempbuf, "out ");
-	return extract_type_info (mangled_str, tempbuf);
-      case 'K': /* inout */
-	obstack_grow_str (tempbuf, "inout ");
-	return extract_type_info (mangled_str, tempbuf);
-      case 'E': /* enum */
-      case 'T': /* typedef */
-      case 'D': /* delegate */
-      case 'C': /* class */
-      case 'S': /* struct */
-	return extract_identifiers (mangled_str, tempbuf);
-
-      /* basic types: */
-      case 'n': obstack_grow_str (tempbuf, "none"); return 1;
-      case 'v': obstack_grow_str (tempbuf, "void"); return 1;
-      case 'g': obstack_grow_str (tempbuf, "byte"); return 1;
-      case 'h': obstack_grow_str (tempbuf, "ubyte"); return 1;
-      case 's': obstack_grow_str (tempbuf, "short"); return 1;
-      case 't': obstack_grow_str (tempbuf, "ushort"); return 1;
-      case 'i': obstack_grow_str (tempbuf, "int"); return 1;
-      case 'k': obstack_grow_str (tempbuf, "uint"); return 1;
-      case 'l': obstack_grow_str (tempbuf, "long"); return 1;
-      case 'm': obstack_grow_str (tempbuf, "ulong"); return 1;
-      case 'f': obstack_grow_str (tempbuf, "float"); return 1;
-      case 'd': obstack_grow_str (tempbuf, "double"); return 1;
-      case 'e': obstack_grow_str (tempbuf, "real"); return 1;
-
-      /* imaginary and complex: */
-      case 'o': obstack_grow_str (tempbuf, "ifloat"); return 1;
-      case 'p': obstack_grow_str (tempbuf, "idouble"); return 1;
-      case 'j': obstack_grow_str (tempbuf, "ireal"); return 1;
-      case 'q': obstack_grow_str (tempbuf, "cfloat"); return 1;
-      case 'r': obstack_grow_str (tempbuf, "cdouble"); return 1;
-      case 'c': obstack_grow_str (tempbuf, "creal"); return 1;
-
-      /* other types: */
-      case 'b': obstack_grow_str (tempbuf, "bit"); return 1;
-      case 'a': obstack_grow_str (tempbuf, "char"); return 1;
-      case 'u': obstack_grow_str (tempbuf, "wchar"); return 1;
-      case 'w': obstack_grow_str (tempbuf, "dchar"); return 1;
-
-      default:
-	obstack_grow_str (tempbuf, "unknown");
-	return 1;
-    }
+  /* No known entry procedure found, the main program is probably not D.  */
+  return NULL;
 }
 
 /* Implements the la_demangle language_defn routine for language D.  */
@@ -135,69 +52,36 @@ char *
 d_demangle (const char *symbol, int options)
 {
   struct obstack tempbuf;
-  char *out_str;
-  unsigned char is_func = 0;
+  char *result;
 
-  if (symbol == NULL)
+  if (symbol == NULL || *symbol == '\0')
     return NULL;
   else if (strcmp (symbol, "_Dmain") == 0)
     return xstrdup ("D main");
 
   obstack_init (&tempbuf);
-  
-  if (symbol[0] == '_' && symbol[1] == 'D')
-    {
-      symbol += 2;
-      is_func = 1;
-    }
-  else if (strncmp (symbol, "__Class_", 8) == 0)
-    symbol += 8;
-  else if (strncmp (symbol, "__init_", 7) == 0)
-    symbol += 7;
-  else if (strncmp (symbol, "__vtbl_", 7) == 0)
-    symbol += 7;
-  else if (strncmp (symbol, "__modctor_", 10) == 0)
-    symbol += 10;
-  else if (strncmp (symbol, "__moddtor_", 10) == 0)
-    symbol += 10;
-  else if (strncmp (symbol, "__ModuleInfo_", 13) == 0)
-    symbol += 13;
+
+  if (strncmp (symbol, "_D", 2) == 0)
+    symbol += 2;
   else
     {
       obstack_free (&tempbuf, NULL);
       return NULL;
     }
-  
-  if (!extract_identifiers (symbol, &tempbuf))
+
+  if (d_parse_symbol (&tempbuf, symbol) != NULL)
+    {
+      obstack_grow_str0 (&tempbuf, "");
+      result = xstrdup (obstack_finish (&tempbuf));
+      obstack_free (&tempbuf, NULL);
+    }
+  else
     {
       obstack_free (&tempbuf, NULL);
       return NULL;
     }
 
-  obstack_grow_str (&tempbuf, "(");
-  if (is_func == 1 && *symbol == 'F')
-    {
-      symbol++;
-      while (*symbol != '\0' && *symbol != 'Z')
-	{
-	  if (is_func == 1)
-	    is_func++;
-	  else
-	    obstack_grow_str (&tempbuf, ", ");
-	  if (!extract_type_info (symbol, &tempbuf))
-	    {
-	      obstack_free (&tempbuf, NULL);
-	      return NULL;
-	   }
-	}
-     }
-  obstack_grow_str0 (&tempbuf, ")");
-
-  /* Doesn't display the return type, but wouldn't be too hard to do.  */
-
-  out_str = xstrdup (obstack_finish (&tempbuf));
-  obstack_free (&tempbuf, NULL);
-  return out_str;
+  return result;
 }
 
 /* Table mapping opcodes into strings for printing operators
@@ -236,6 +120,98 @@ static const struct op_print d_op_print_tab[] =
   {NULL, 0, 0, 0}
 };
 
+enum d_primitive_types {
+  d_primitive_type_void,
+  d_primitive_type_bool,
+  d_primitive_type_byte,
+  d_primitive_type_ubyte,
+  d_primitive_type_short,
+  d_primitive_type_ushort,
+  d_primitive_type_int,
+  d_primitive_type_uint,
+  d_primitive_type_long,
+  d_primitive_type_ulong,
+  d_primitive_type_cent,
+  d_primitive_type_ucent,
+  d_primitive_type_float,
+  d_primitive_type_double,
+  d_primitive_type_real,
+  d_primitive_type_ifloat,
+  d_primitive_type_idouble,
+  d_primitive_type_ireal,
+  d_primitive_type_cfloat,
+  d_primitive_type_cdouble,
+  d_primitive_type_creal,
+  d_primitive_type_char,
+  d_primitive_type_wchar,
+  d_primitive_type_dchar,
+  nr_d_primitive_types
+};
+
+static void
+d_language_arch_info (struct gdbarch *gdbarch,
+		      struct language_arch_info *lai)
+{
+  const struct builtin_d_type *builtin = builtin_d_type (gdbarch);
+
+  lai->string_char_type = builtin->builtin_char;
+  lai->primitive_type_vector
+    = GDBARCH_OBSTACK_CALLOC (gdbarch, nr_d_primitive_types + 1,
+			      struct type *);
+
+  lai->primitive_type_vector [d_primitive_type_void]
+    = builtin->builtin_void;
+  lai->primitive_type_vector [d_primitive_type_bool]
+    = builtin->builtin_bool;
+  lai->primitive_type_vector [d_primitive_type_byte]
+    = builtin->builtin_byte;
+  lai->primitive_type_vector [d_primitive_type_ubyte]
+    = builtin->builtin_ubyte;
+  lai->primitive_type_vector [d_primitive_type_short]
+    = builtin->builtin_short;
+  lai->primitive_type_vector [d_primitive_type_ushort]
+    = builtin->builtin_ushort;
+  lai->primitive_type_vector [d_primitive_type_int]
+    = builtin->builtin_int;
+  lai->primitive_type_vector [d_primitive_type_uint]
+    = builtin->builtin_uint;
+  lai->primitive_type_vector [d_primitive_type_long]
+    = builtin->builtin_long;
+  lai->primitive_type_vector [d_primitive_type_ulong]
+    = builtin->builtin_ulong;
+  lai->primitive_type_vector [d_primitive_type_cent]
+    = builtin->builtin_cent;
+  lai->primitive_type_vector [d_primitive_type_ucent]
+    = builtin->builtin_ucent;
+  lai->primitive_type_vector [d_primitive_type_float]
+    = builtin->builtin_float;
+  lai->primitive_type_vector [d_primitive_type_double]
+    = builtin->builtin_double;
+  lai->primitive_type_vector [d_primitive_type_real]
+    = builtin->builtin_real;
+  lai->primitive_type_vector [d_primitive_type_ifloat]
+    = builtin->builtin_ifloat;
+  lai->primitive_type_vector [d_primitive_type_idouble]
+    = builtin->builtin_idouble;
+  lai->primitive_type_vector [d_primitive_type_ireal]
+    = builtin->builtin_ireal;
+  lai->primitive_type_vector [d_primitive_type_cfloat]
+    = builtin->builtin_cfloat;
+  lai->primitive_type_vector [d_primitive_type_cdouble]
+    = builtin->builtin_cdouble;
+  lai->primitive_type_vector [d_primitive_type_creal]
+    = builtin->builtin_creal;
+  lai->primitive_type_vector [d_primitive_type_char]
+    = builtin->builtin_char;
+  lai->primitive_type_vector [d_primitive_type_wchar]
+    = builtin->builtin_wchar;
+  lai->primitive_type_vector [d_primitive_type_dchar]
+    = builtin->builtin_dchar;
+
+  lai->bool_type_symbol = "bool";
+  lai->bool_type_default = builtin->builtin_bool;
+}
+
 static const struct language_defn d_language_defn =
 {
   "d",
@@ -244,7 +220,7 @@ static const struct language_defn d_language_defn =
   range_check_off,
   case_sensitive_on,
   array_row_major,
-  macro_expansion_c,
+  macro_expansion_no,
   &exp_descriptor_c,
   c_parse,
   c_error,
@@ -259,8 +235,8 @@ static const struct language_defn d_language_defn =
   c_value_print,		/* Print a top-level value.  */
   default_read_var_value,	/* la_read_var_value */
   NULL,				/* Language specific skip_trampoline.  */
-  "this",
-  basic_lookup_symbol_nonlocal, 
+  "this",			/* name_of_this */
+  basic_lookup_symbol_nonlocal,
   basic_lookup_transparent_type,
   d_demangle,			/* Language specific symbol demangler.  */
   NULL,				/* Language specific
@@ -270,7 +246,7 @@ static const struct language_defn d_language_defn =
   0,				/* String lower bound.  */
   default_word_break_characters,
   default_make_symbol_completion_list,
-  c_language_arch_info,
+  d_language_arch_info,
   default_print_array_index,
   default_pass_by_reference,
   c_get_string,
@@ -280,11 +256,98 @@ static const struct language_defn d_language_defn =
   LANG_MAGIC
 };
 
+static void *
+build_d_types (struct gdbarch *gdbarch)
+{
+  struct builtin_d_type *builtin_d_type
+    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct builtin_d_type);
+
+  /* Basic types.  */
+  builtin_d_type->builtin_void
+    = arch_type (gdbarch, TYPE_CODE_VOID, 1, "void");
+  builtin_d_type->builtin_bool
+    = arch_boolean_type (gdbarch, 8, 1, "bool");
+  builtin_d_type->builtin_byte
+    = arch_integer_type (gdbarch, 8, 0, "byte");
+  builtin_d_type->builtin_ubyte
+    = arch_integer_type (gdbarch, 8, 1, "ubyte");
+  builtin_d_type->builtin_short
+    = arch_integer_type (gdbarch, 16, 0, "short");
+  builtin_d_type->builtin_ushort
+    = arch_integer_type (gdbarch, 16, 1, "ushort");
+  builtin_d_type->builtin_int
+    = arch_integer_type (gdbarch, 32, 0, "int");
+  builtin_d_type->builtin_uint
+    = arch_integer_type (gdbarch, 32, 1, "uint");
+  builtin_d_type->builtin_long
+    = arch_integer_type (gdbarch, 64, 0, "long");
+  builtin_d_type->builtin_ulong
+    = arch_integer_type (gdbarch, 64, 1, "ulong");
+  builtin_d_type->builtin_cent
+    = arch_integer_type (gdbarch, 128, 0, "cent");
+  builtin_d_type->builtin_ucent
+    = arch_integer_type (gdbarch, 128, 1, "ucent");
+  builtin_d_type->builtin_float
+    = arch_float_type (gdbarch, gdbarch_float_bit (gdbarch),
+		       "float", NULL);
+  builtin_d_type->builtin_double
+    = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
+		       "double", NULL);
+  builtin_d_type->builtin_real
+    = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+		       "real", NULL);
+
+  TYPE_INSTANCE_FLAGS (builtin_d_type->builtin_byte)
+    |= TYPE_INSTANCE_FLAG_NOTTEXT;
+  TYPE_INSTANCE_FLAGS (builtin_d_type->builtin_ubyte)
+    |= TYPE_INSTANCE_FLAG_NOTTEXT;
+
+  /* Imaginary and complex types.  */
+  builtin_d_type->builtin_ifloat
+    = arch_float_type (gdbarch, gdbarch_float_bit (gdbarch),
+		       "ifloat", NULL);
+  builtin_d_type->builtin_idouble
+    = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
+		       "idouble", NULL);
+  builtin_d_type->builtin_ireal
+    = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+		       "ireal", NULL);
+  builtin_d_type->builtin_cfloat
+    = arch_complex_type (gdbarch, "cfloat",
+			 builtin_d_type->builtin_float);
+  builtin_d_type->builtin_cdouble
+    = arch_complex_type (gdbarch, "cdouble",
+			 builtin_d_type->builtin_double);
+  builtin_d_type->builtin_creal
+    = arch_complex_type (gdbarch, "creal",
+			 builtin_d_type->builtin_real);
+
+  /* Character types.  */
+  builtin_d_type->builtin_char
+    = arch_character_type (gdbarch, 8, 1, "char");
+  builtin_d_type->builtin_wchar
+    = arch_character_type (gdbarch, 16, 1, "wchar");
+  builtin_d_type->builtin_dchar
+    = arch_character_type (gdbarch, 32, 1, "dchar");
+
+  return builtin_d_type;
+}
+
+static struct gdbarch_data *d_type_data;
+
+const struct builtin_d_type *
+builtin_d_type (struct gdbarch *gdbarch)
+{
+  return gdbarch_data (gdbarch, d_type_data);
+}
+
 /* Provide a prototype to silence -Wmissing-prototypes.  */
 extern initialize_file_ftype _initialize_d_language;
 
 void
 _initialize_d_language (void)
 {
+  d_type_data = gdbarch_data_register_post_init (build_d_types);
+
   add_language (&d_language_defn);
 }
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
index 8834a1d..d61a57c 100644
--- a/gdb/d-lang.h
+++ b/gdb/d-lang.h
@@ -22,6 +22,38 @@
 
 #include "symtab.h"
 
+struct builtin_d_type
+{
+  struct type *builtin_void;
+  struct type *builtin_bool;
+  struct type *builtin_byte;
+  struct type *builtin_ubyte;
+  struct type *builtin_short;
+  struct type *builtin_ushort;
+  struct type *builtin_int;
+  struct type *builtin_uint;
+  struct type *builtin_long;
+  struct type *builtin_ulong;
+  struct type *builtin_cent;
+  struct type *builtin_ucent;
+  struct type *builtin_float;
+  struct type *builtin_double;
+  struct type *builtin_real;
+  struct type *builtin_ifloat;
+  struct type *builtin_idouble;
+  struct type *builtin_ireal;
+  struct type *builtin_cfloat;
+  struct type *builtin_cdouble;
+  struct type *builtin_creal;
+  struct type *builtin_char;
+  struct type *builtin_wchar;
+  struct type *builtin_dchar;
+};
+
+/* Defined in d-lang.c  */
+
+extern const char *d_main_name (void);
+
 extern char *d_demangle (const char *mangled, int options);
 
 extern void d_val_print (struct type *type, const gdb_byte *valaddr,
@@ -30,4 +62,10 @@ extern void d_val_print (struct type *type, const gdb_byte *valaddr,
 			 const struct value *val,
 			 const struct value_print_options *options);
 
+extern const struct builtin_d_type *builtin_d_type (struct gdbarch *);
+
+/* Defined in d-support.c  */
+
+extern const char *d_parse_symbol (struct obstack *, const char *);
+
 #endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-support.c b/gdb/d-support.c
new file mode 100644
index 0000000..318acf8
--- /dev/null
+++ b/gdb/d-support.c
@@ -0,0 +1,606 @@
+/* D language support routines for GDB, the GNU debugger.
+
+   Copyright (C) 2014 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "d-lang.h"
+#include "gdb_obstack.h"
+
+#include "safe-ctype.h"
+
+static const char *parse_function_args (struct obstack *, const char *);
+static const char *parse_type (struct obstack *, const char *);
+
+/* Demangle the calling convention from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_call_convention (struct obstack *tempbuf, const char *mangle)
+{
+  if (mangle == NULL || *mangle == '\0')
+    return mangle;
+
+  switch (*mangle)
+    {
+    case 'F': /* (D) */
+      mangle++;
+      break;
+    case 'U': /* (C) */
+      mangle++;
+      obstack_grow_str (tempbuf, "extern(C) ");
+      break;
+    case 'W': /* (Windows) */
+      mangle++;
+      obstack_grow_str (tempbuf, "extern(Windows) ");
+      break;
+    case 'V': /* (Pascal) */
+      mangle++;
+      obstack_grow_str (tempbuf, "extern(Pascal) ");
+      break;
+    case 'R': /* (C++) */
+      mangle++;
+      obstack_grow_str (tempbuf, "extern(C++) ");
+      break;
+    default:
+      return NULL;
+    }
+
+  return mangle;
+}
+
+/* Demangle the D function attributes from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_attributes (struct obstack *tempbuf, const char *mangle)
+{
+  if (mangle == NULL || *mangle == '\0')
+    return mangle;
+
+  while (*mangle == 'N')
+    {
+      mangle++;
+      switch (*mangle)
+	{
+	case 'a': /* pure */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "pure ");
+	  continue;
+	case 'b': /* nothrow */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "nothrow ");
+	  continue;
+	case 'c': /* ref */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "ref ");
+	  continue;
+	case 'd': /* @property */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "@property ");
+	  continue;
+	case 'e': /* @trusted */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "@trusted ");
+	  continue;
+	case 'f': /* @safe */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "@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.  */
+	  mangle--;
+	}
+      break;
+    }
+  return mangle;
+}
+
+/* Demangle the function type from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_function_type (struct obstack *tempbuf, const char *mangle)
+{
+  struct obstack obattr, obargs, obtype;
+  char *attr, *args, *type;
+  size_t szattr, szargs, sztype;
+
+  if (mangle == NULL || *mangle == '\0')
+    return mangle;
+
+  /* The order of the mangled string is:
+     TypeFunction ::
+        CallConvention FuncAttrs Arguments ArgClose Type
+
+     The demangled string is re-ordered as:
+        CallConvention Type Arguments FuncAttrs
+   */
+  obstack_init (&obattr);
+  obstack_init (&obargs);
+  obstack_init (&obtype);
+
+  /* Function call convention.  */
+  mangle = parse_call_convention (tempbuf, mangle);
+
+  /* Function attributes.  */
+  mangle = parse_attributes (&obattr, mangle);
+  szattr = obstack_object_size (&obattr);
+  attr = obstack_finish (&obattr);
+
+  /* Function arguments.  */
+  mangle = parse_function_args (&obargs, mangle);
+  szargs = obstack_object_size (&obargs);
+  args = obstack_finish (&obargs);
+
+  /* Function return type.  */
+  mangle = parse_type (&obtype, mangle);
+  sztype = obstack_object_size (&obtype);
+  type = obstack_finish (&obtype);
+
+  /* Append to buffer in order. */
+  obstack_grow (tempbuf, type, sztype);
+  obstack_grow_str (tempbuf, "(");
+  obstack_grow (tempbuf, args, szargs);
+  obstack_grow_str (tempbuf, ") ");
+  obstack_grow (tempbuf, attr, szattr);
+
+  obstack_free (&obattr, NULL);
+  obstack_free (&obargs, NULL);
+  obstack_free (&obtype, NULL);
+  return mangle;
+}
+
+/* Demangle the argument list from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_function_args (struct obstack *tempbuf, const char *mangle)
+{
+  size_t n = 0;
+
+  while (mangle && *mangle != '\0')
+    {
+      switch (*mangle)
+	{
+	case 'X': /* (variadic T t...) style.  */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "...");
+	  return mangle;
+	case 'Y': /* (variadic T t, ...) style.  */
+	  mangle++;
+	  obstack_grow_str (tempbuf, ", ...");
+	  return mangle;
+	case 'Z': /* Normal function.  */
+	  mangle++;
+	  return mangle;
+	}
+
+      if (n++)
+	obstack_grow_str (tempbuf, ", ");
+
+      if (*mangle == 'M') /* scope(T) */
+	{
+	  mangle++;
+	  obstack_grow_str (tempbuf, "scope ");
+	}
+
+      switch (*mangle)
+	{
+	case 'J': /* out(T) */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "out ");
+	  break;
+	case 'K': /* ref(T) */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "ref ");
+	  break;
+	case 'L': /* lazy(T) */
+	  mangle++;
+	  obstack_grow_str (tempbuf, "lazy ");
+	  break;
+	}
+      mangle = parse_type (tempbuf, mangle);
+    }
+  return mangle;
+}
+
+/* Demangle the type from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_type (struct obstack *tempbuf, const char *mangle)
+{
+  if (mangle == NULL || *mangle == '\0')
+    return mangle;
+
+  switch (*mangle)
+    {
+    case 'O': /* shared(T) */
+      mangle++;
+      obstack_grow_str (tempbuf, "shared(");
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, ")");
+      return mangle;
+    case 'x': /* const(T) */
+      mangle++;
+      obstack_grow_str (tempbuf, "const(");
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, ")");
+      return mangle;
+    case 'y': /* immutable(T) */
+      mangle++;
+      obstack_grow_str (tempbuf, "immutable(");
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, ")");
+      return mangle;
+    case 'N':
+      mangle++;
+      if (*mangle == 'g') /* wild(T) */
+	{
+	  mangle++;
+	  obstack_grow_str (tempbuf, "inout(");
+	  mangle = parse_type (tempbuf, mangle);
+	  obstack_grow_str (tempbuf, ")");
+	  return mangle;
+	}
+      else if (*mangle == 'h') /* vector(T) */
+	{
+	  mangle++;
+	  /* The basetype for vectors are always static arrays.  */
+	  if (*mangle != 'G')
+	    return NULL;
+	  obstack_grow_str (tempbuf, "__vector(");
+	  mangle = parse_type (tempbuf, mangle);
+	  obstack_grow_str (tempbuf, ")");
+	  return mangle;
+	}
+      else
+	return NULL;
+    case 'A': /* dynamic array (T[]) */
+      mangle++;
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "[]");
+      return mangle;
+    case 'G': /* static array (T[N]) */
+    {
+      const char *numptr;
+      size_t num = 0;
+      mangle++;
+
+      numptr = mangle;
+      while (ISDIGIT (*mangle))
+	{
+	  num++;
+	  mangle++;
+	}
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "[");
+      obstack_grow (tempbuf, numptr, num);
+      obstack_grow_str (tempbuf, "]");
+      return mangle;
+    }
+    case 'H': /* associative array (T[T]) */
+    {
+      struct obstack obtype;
+      char *type;
+      size_t sztype;
+      mangle++;
+
+      obstack_init (&obtype);
+      mangle = parse_type (&obtype, mangle);
+      sztype = obstack_object_size (&obtype);
+      type = obstack_finish (&obtype);
+
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "[");
+      obstack_grow (tempbuf, type, sztype);
+      obstack_grow_str (tempbuf, "]");
+
+      obstack_free (&obtype, NULL);
+      return mangle;
+    }
+    case 'P': /* pointer (T*) */
+      mangle++;
+      mangle = parse_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "*");
+      return mangle;
+    case 'I': /* ident T */
+    case 'C': /* class T */
+    case 'S': /* struct T */
+    case 'E': /* enum T */
+    case 'T': /* typedef T */
+      mangle++;
+      return d_parse_symbol (tempbuf, mangle);
+    case 'D': /* delegate T */
+      mangle++;
+      mangle = parse_function_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "delegate");
+      return mangle;
+    case 'B': /* tuple T */
+      /* TODO: Handle this.  */
+      return NULL;
+
+    /* Function types */
+    case 'F': case 'U': case 'W':
+    case 'V': case 'R':
+      mangle = parse_function_type (tempbuf, mangle);
+      obstack_grow_str (tempbuf, "function");
+      return mangle;
+
+    /* Basic types */
+    case 'n':
+      mangle++;
+      obstack_grow_str (tempbuf, "none");
+      return mangle;
+    case 'v':
+      mangle++;
+      obstack_grow_str (tempbuf, "void");
+      return mangle;
+    case 'g':
+      mangle++;
+      obstack_grow_str (tempbuf, "byte");
+      return mangle;
+    case 'h':
+      mangle++;
+      obstack_grow_str (tempbuf, "ubyte");
+      return mangle;
+    case 's':
+      mangle++;
+      obstack_grow_str (tempbuf, "short");
+      return mangle;
+    case 't':
+      mangle++;
+      obstack_grow_str (tempbuf, "ushort");
+      return mangle;
+    case 'i':
+      mangle++;
+      obstack_grow_str (tempbuf, "int");
+      return mangle;
+    case 'k':
+      mangle++;
+      obstack_grow_str (tempbuf, "uint");
+      return mangle;
+    case 'l':
+      mangle++;
+      obstack_grow_str (tempbuf, "long");
+      return mangle;
+    case 'm':
+      mangle++;
+      obstack_grow_str (tempbuf, "ulong");
+      return mangle;
+    case 'f':
+      mangle++;
+      obstack_grow_str (tempbuf, "float");
+      return mangle;
+    case 'd':
+      mangle++;
+      obstack_grow_str (tempbuf, "double");
+      return mangle;
+    case 'e':
+      mangle++;
+      obstack_grow_str (tempbuf, "real");
+      return mangle;
+
+    /* Imaginary and Complex types */
+    case 'o':
+      mangle++;
+      obstack_grow_str (tempbuf, "ifloat");
+      return mangle;
+    case 'p':
+      mangle++;
+      obstack_grow_str (tempbuf, "idouble");
+      return mangle;
+    case 'j':
+      mangle++;
+      obstack_grow_str (tempbuf, "ireal");
+      return mangle;
+    case 'q':
+      mangle++;
+      obstack_grow_str (tempbuf, "cfloat");
+      return mangle;
+    case 'r':
+      mangle++;
+      obstack_grow_str (tempbuf, "cdouble");
+      return mangle;
+    case 'c':
+      mangle++;
+      obstack_grow_str (tempbuf, "creal");
+      return mangle;
+
+    /* Other types */
+    case 'b':
+      mangle++;
+      obstack_grow_str (tempbuf, "bool");
+      return mangle;
+    case 'a':
+      mangle++;
+      obstack_grow_str (tempbuf, "char");
+      return mangle;
+    case 'u':
+      mangle++;
+      obstack_grow_str (tempbuf, "wchar");
+      return mangle;
+    case 'w':
+      mangle++;
+      obstack_grow_str (tempbuf, "dchar");
+      return mangle;
+
+    default: /* unhandled */
+      return NULL;
+    }
+}
+
+/* Extract the identifier from MANGLE and append it to TEMPBUF.
+   Return the remaining string on success or NULL on failure.  */
+static const char *
+parse_identifier (struct obstack *tempbuf, const char *mangle)
+{
+  if (mangle == NULL || *mangle == '\0')
+    return mangle;
+
+  if (ISDIGIT (*mangle))
+    {
+      char *endptr;
+      long i = strtol (mangle, &endptr, 10);
+
+      if (i <= 0 || strlen (endptr) < i)
+	return NULL;
+
+      mangle = endptr;
+
+      /* No support for demangling templates.  */
+      if (i >= 5 && strncmp (mangle, "__T", 3) == 0)
+	return NULL;
+
+      if (strncmp (mangle, "__ctor", i) == 0)
+	{
+	  /* Constructor symbol for a class/struct.  */
+	  obstack_grow_str (tempbuf, "this");
+	  mangle += i;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__dtor", i) == 0)
+	{
+	  /* Destructor symbol for a class/struct.  */
+	  obstack_grow_str (tempbuf, "~this");
+	  mangle += i;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__postblit", i) == 0)
+	{
+	  /* Postblit symbol for a struct.  */
+	  obstack_grow_str (tempbuf, "this(this)");
+	  mangle += i;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__initZ", i+1) == 0)
+	{
+	  /* The static initialiser for a given symbol.  */
+	  obstack_grow_str (tempbuf, "init$");
+	  mangle += i + 1;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__ClassZ", i+1) == 0)
+	{
+	  /* The classinfo symbol for a given class.  */
+	  obstack_grow_str (tempbuf, "classinfo$");
+	  mangle += i + 1;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__vtblZ", i+1) == 0)
+	{
+	  /* The vtable symbol for a given class.  */
+	  obstack_grow_str (tempbuf, "vtbl$");
+	  mangle += i + 1;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__InterfaceZ", i+1) == 0)
+	{
+	  /* The interface symbol for a given class.  */
+	  obstack_grow_str (tempbuf, "interface$");
+	  mangle += i + 1;
+	  return mangle;
+	}
+      else if (strncmp (mangle, "__ModuleInfoZ", i+1) == 0)
+	{
+	  /* The ModuleInfo symbol for a given module.  */
+	  obstack_grow_str (tempbuf, "moduleinfo$");
+	  mangle += i + 1;
+	  return mangle;
+	}
+      obstack_grow (tempbuf, mangle, i);
+      mangle += i;
+    }
+  else
+    return NULL;
+
+  return mangle;
+}
+
+static int
+call_convention_p (const char *mangle)
+{
+  size_t i;
+
+  switch (*mangle)
+    {
+    case 'F': case 'U': case 'V':
+    case 'W': case 'R':
+      return 1;
+
+    case 'M': /* Prefix for functions needing 'this' */
+      i = 1;
+      if (mangle[i] == 'x')
+	i++;
+
+      switch (mangle[i])
+	{
+	case 'F': case 'U': case 'V':
+	case 'W': case 'R':
+	  return 1;
+	}
+
+    default:
+      return 0;
+    }
+}
+
+/* Extract and demangle the symbol in MANGLE and append it to TEMPBUF.
+   Return the remaining signature on success or NULL on failure.  */
+const char *
+d_parse_symbol (struct obstack *tempbuf, const char *mangle)
+{
+  size_t n = 0;
+  do
+    {
+      if (n++)
+	obstack_grow_str (tempbuf, ".");
+
+      mangle = parse_identifier (tempbuf, mangle);
+
+      if (mangle && call_convention_p (mangle))
+	{
+	  char *saved;
+
+	  /* Skip over 'this' parameter.  */
+	  if (*mangle == 'M')
+	    mangle += (mangle[1] == 'x') ? 2 : 1;
+
+	  /* Skip over calling convention and attributes in qualified name.  */
+	  saved = obstack_next_free (tempbuf);
+	  mangle = parse_call_convention (tempbuf, mangle);
+	  mangle = parse_attributes (tempbuf, mangle);
+	  obstack_next_free (tempbuf) = saved;
+
+	  obstack_grow_str (tempbuf, "(");
+	  mangle = parse_function_args (tempbuf, mangle);
+	  obstack_grow_str (tempbuf, ")");
+
+	  /* Demangle the function return type as a kind of sanity test.  */
+	  if (mangle && !ISDIGIT (*mangle))
+	    {
+	      saved = obstack_next_free (tempbuf);
+	      mangle = parse_type (tempbuf, mangle);
+	      obstack_next_free (tempbuf) = saved;
+	    }
+	}
+    }
+  while (mangle && ISDIGIT (*mangle));
+
+  return mangle;
+}
+
diff --git a/gdb/symtab.c b/gdb/symtab.c
index f215586..4bfff0a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -5055,6 +5055,13 @@ find_main_name (void)
       return;
     }
 
+  new_main_name = d_main_name ();
+  if (new_main_name != NULL)
+    {
+      set_main_name (new_main_name);
+      return;
+    }
+
   new_main_name = go_main_name ();
   if (new_main_name != NULL)
     {
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 662d161..54af145 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,13 @@
+2014-01-03  Iain Buclaw  <ibuclaw@gdcproject.org>
+
+	* configure.ac: Create gdb.dlang/Makefile.
+	* configure: Regenerate.
+	* Makefile.in (ALL_SUBDIRS): Add gdb.dlang.
+	* gdb.dlang/Makefile.in: New file.
+	* gdb.dlang/demangle.exp: New file.
+	* lib/gdb.exp (skip_d_tests): New proc.
+	* lib/d-support.exp: New file.
+
 2013-12-19  Sergio Durigan Junior  <sergiodj@redhat.com>
 
 	PR breakpoints/16297
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 2204a3c..7a44660 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -33,7 +33,7 @@ EXEEXT = @EXEEXT@
 SUBDIRS = @subdirs@
 RPATH_ENVVAR = @RPATH_ENVVAR@
 ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.btrace gdb.cell gdb.cp \
-	gdb.disasm gdb.dwarf2 gdb.fortran gdb.gdb gdb.go gdb.hp \
+	gdb.disasm gdb.dlang gdb.dwarf2 gdb.fortran gdb.gdb gdb.go gdb.hp \
 	gdb.java gdb.linespec gdb.mi gdb.modula2 gdb.multi \
 	gdb.objc gdb.opencl gdb.opt gdb.pascal gdb.python gdb.server \
 	gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml \
diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure
index da590f3..94542a6 100755
--- a/gdb/testsuite/configure
+++ b/gdb/testsuite/configure
@@ -3448,7 +3448,7 @@ done
 
 
 
-ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.perf/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.dlang/Makefile gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.perf/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
 
 cat >confcache <<\_ACEOF
 # This file is a shell script that caches the results of configure
@@ -4158,6 +4158,7 @@ do
     "gdb.cp/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.cp/Makefile" ;;
     "gdb.disasm/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.disasm/Makefile" ;;
     "gdb.dwarf2/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.dwarf2/Makefile" ;;
+    "gdb.dlang/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.dlang/Makefile" ;;
     "gdb.fortran/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.fortran/Makefile" ;;
     "gdb.go/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.go/Makefile" ;;
     "gdb.server/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.server/Makefile" ;;
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index f25b939..61d0bff 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -91,7 +91,8 @@ AC_OUTPUT([Makefile \
   gdb.ada/Makefile \
   gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.btrace/Makefile \
   gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile \
-  gdb.fortran/Makefile gdb.go/Makefile gdb.server/Makefile gdb.java/Makefile \
+  gdb.dlang/Makefile gdb.fortran/Makefile gdb.go/Makefile \
+  gdb.server/Makefile gdb.java/Makefile \
   gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile \
   gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile \
   gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile \
diff --git a/gdb/testsuite/gdb.dlang/Makefile.in b/gdb/testsuite/gdb.dlang/Makefile.in
new file mode 100644
index 0000000..5527c3e
--- /dev/null
+++ b/gdb/testsuite/gdb.dlang/Makefile.in
@@ -0,0 +1,15 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES =
+
+all info install-info dvi install uninstall installcheck check:
+	@echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+	-rm -f *~ *.o *.ci
+	-rm -f *.dwo *.dwp
+	-rm -f core ${EXECUTABLES}
+
+distclean maintainer-clean realclean: clean
+	-rm -f Makefile config.status config.log gdb.log gdb.sum
diff --git a/gdb/testsuite/gdb.dlang/demangle.exp b/gdb/testsuite/gdb.dlang/demangle.exp
new file mode 100644
index 0000000..b38fcbd
--- /dev/null
+++ b/gdb/testsuite/gdb.dlang/demangle.exp
@@ -0,0 +1,227 @@
+# Copyright (C) 2014 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Test D demangling.
+# The tests here intentionally do not require a D compiler.
+
+load_lib "d-support.exp"
+
+if { [skip_d_tests] } { continue }
+
+### Utility function for test_demangling and test_demangling_exact.
+proc test_demangling {test result} {
+    gdb_test_exact "maintenance demangle $test" $result $test
+}
+
+#
+#  Test D demangler
+#
+
+proc test_d_demangling {} {
+    global gdb_prompt
+
+    test_demangling "_Dmain" "D main"
+
+    test_demangling "_D8demangle4testFaZv" "demangle.test(char)"
+    test_demangling "_D8demangle4testFbZv" "demangle.test(bool)"
+    test_demangling "_D8demangle4testFcZv" "demangle.test(creal)"
+    test_demangling "_D8demangle4testFdZv" "demangle.test(double)"
+    test_demangling "_D8demangle4testFeZv" "demangle.test(real)"
+    test_demangling "_D8demangle4testFfZv" "demangle.test(float)"
+    test_demangling "_D8demangle4testFgZv" "demangle.test(byte)"
+    test_demangling "_D8demangle4testFhZv" "demangle.test(ubyte)"
+    test_demangling "_D8demangle4testFiZv" "demangle.test(int)"
+    test_demangling "_D8demangle4testFjZv" "demangle.test(ireal)"
+    test_demangling "_D8demangle4testFkZv" "demangle.test(uint)"
+    test_demangling "_D8demangle4testFlZv" "demangle.test(long)"
+    test_demangling "_D8demangle4testFmZv" "demangle.test(ulong)"
+    test_demangling "_D8demangle4testFnZv" "demangle.test(none)"
+    test_demangling "_D8demangle4testFoZv" "demangle.test(ifloat)"
+    test_demangling "_D8demangle4testFpZv" "demangle.test(idouble)"
+    test_demangling "_D8demangle4testFqZv" "demangle.test(cfloat)"
+    test_demangling "_D8demangle4testFrZv" "demangle.test(cdouble)"
+    test_demangling "_D8demangle4testFsZv" "demangle.test(short)"
+    test_demangling "_D8demangle4testFtZv" "demangle.test(ushort)"
+    test_demangling "_D8demangle4testFuZv" "demangle.test(wchar)"
+    test_demangling "_D8demangle4testFvZv" "demangle.test(void)"
+    test_demangling "_D8demangle4testFwZv" "demangle.test(dchar)"
+
+    test_demangling "_D8demangle4testFOaZv" "demangle.test(shared(char))"
+    test_demangling "_D8demangle4testFxaZv" "demangle.test(const(char))"
+    test_demangling "_D8demangle4testFyaZv" "demangle.test(immutable(char))"
+    test_demangling "_D8demangle4testFNgaZv" "demangle.test(inout(char))"
+    test_demangling "_D8demangle4testFOxaZv" "demangle.test(shared(const(char)))"
+    test_demangling "_D8demangle4testFONgaZv" "demangle.test(shared(inout(char)))"
+    test_demangling "_D8demangle4testFAaZv" "demangle.test(char\[\])"
+    test_demangling "_D8demangle4testFAAaZv" "demangle.test(char\[\]\[\])"
+    test_demangling "_D8demangle4testFAAAaZv" "demangle.test(char\[\]\[\]\[\])"
+    test_demangling "_D8demangle4testFG42aZv" "demangle.test(char\[42\])"
+    test_demangling "_D8demangle4testFG42G42aZv" "demangle.test(char\[42\]\[42\])"
+    test_demangling "_D8demangle4testFG42G42G42aZv" "demangle.test(char\[42\]\[42\]\[42\])"
+    test_demangling "_D8demangle4testFG1234567890aZv" "demangle.test(char\[1234567890\])"
+    test_demangling "_D8demangle4testFHaaZv" "demangle.test(char\[char\])"
+    test_demangling "_D8demangle4testFHHaaaZv" "demangle.test(char\[char\[char\]\])"
+    test_demangling "_D8demangle4testFPaZv" "demangle.test(char*)"
+    test_demangling "_D8demangle4testFPPaZv" "demangle.test(char**)"
+    test_demangling "_D8demangle4testFPPPaZv" "demangle.test(char***)"
+
+    test_demangling "_D8demangle4testFNhG8gZv" "demangle.test(__vector(byte\[8\]))"
+    test_demangling "_D8demangle4testFNhG16gZv" "demangle.test(__vector(byte\[16\]))"
+    test_demangling "_D8demangle4testFNhG32gZv" "demangle.test(__vector(byte\[32\]))"
+    test_demangling "_D8demangle4testFNhG4sZv" "demangle.test(__vector(short\[4\]))"
+    test_demangling "_D8demangle4testFNhG8sZv" "demangle.test(__vector(short\[8\]))"
+    test_demangling "_D8demangle4testFNhG16sZv" "demangle.test(__vector(short\[16\]))"
+    test_demangling "_D8demangle4testFNhG2iZv" "demangle.test(__vector(int\[2\]))"
+    test_demangling "_D8demangle4testFNhG4iZv" "demangle.test(__vector(int\[4\]))"
+    test_demangling "_D8demangle4testFNhG8iZv" "demangle.test(__vector(int\[8\]))"
+    test_demangling "_D8demangle4testFNhG1lZv" "demangle.test(__vector(long\[1\]))"
+    test_demangling "_D8demangle4testFNhG2lZv" "demangle.test(__vector(long\[2\]))"
+    test_demangling "_D8demangle4testFNhG4lZv" "demangle.test(__vector(long\[4\]))"
+    test_demangling "_D8demangle4testFNhG2fZv" "demangle.test(__vector(float\[2\]))"
+    test_demangling "_D8demangle4testFNhG4fZv" "demangle.test(__vector(float\[4\]))"
+    test_demangling "_D8demangle4testFNhG8fZv" "demangle.test(__vector(float\[8\]))"
+    test_demangling "_D8demangle4testFNhG1dZv" "demangle.test(__vector(double\[1\]))"
+    test_demangling "_D8demangle4testFNhG2dZv" "demangle.test(__vector(double\[2\]))"
+    test_demangling "_D8demangle4testFNhG4dZv" "demangle.test(__vector(double\[4\]))"
+
+    test_demangling "_D8demangle4testFI5identZv" "demangle.test(ident)"
+    test_demangling "_D8demangle4testFI5ident4testZv" "demangle.test(ident.test)"
+    test_demangling "_D8demangle4testFC5classZv" "demangle.test(class)"
+    test_demangling "_D8demangle4testFC5class4testZv" "demangle.test(class.test)"
+    test_demangling "_D8demangle4testFS6structZv" "demangle.test(struct)"
+    test_demangling "_D8demangle4testFS6struct4testZv" "demangle.test(struct.test)"
+    test_demangling "_D8demangle4testFE4enumZv" "demangle.test(enum)"
+    test_demangling "_D8demangle4testFE4enum4testZv" "demangle.test(enum.test)"
+    test_demangling "_D8demangle4testFT7typedefZv" "demangle.test(typedef)"
+    test_demangling "_D8demangle4testFT7typedef4testZv" "demangle.test(typedef.test)"
+
+    test_demangling "_D8demangle4testFJaZv" "demangle.test(out char)"
+    test_demangling "_D8demangle4testFKaZv" "demangle.test(ref char)"
+    test_demangling "_D8demangle4testFLaZv" "demangle.test(lazy char)"
+    test_demangling "_D8demangle4testFMaZv" "demangle.test(scope char)"
+    test_demangling "_D8demangle4testFaXv" "demangle.test(char...)"
+    test_demangling "_D8demangle4testFaYv" "demangle.test(char, ...)"
+    test_demangling "_D8demangle4testFaaYv" "demangle.test(char, char, ...)"
+    test_demangling "_D8demangle4testFaaZv" "demangle.test(char, char)"
+
+    test_demangling "_D8demangle4testFDFZaZv" "demangle.test(char() delegate)"
+    test_demangling "_D8demangle4testFDUZaZv" "demangle.test(extern(C) char() delegate)"
+    test_demangling "_D8demangle4testFDWZaZv" "demangle.test(extern(Windows) char() delegate)"
+    test_demangling "_D8demangle4testFDVZaZv" "demangle.test(extern(Pascal) char() delegate)"
+    test_demangling "_D8demangle4testFDRZaZv" "demangle.test(extern(C++) char() delegate)"
+
+    test_demangling "_D8demangle4testFFZaZv" "demangle.test(char() function)"
+    test_demangling "_D8demangle4testFUZaZv" "demangle.test(extern(C) char() function)"
+    test_demangling "_D8demangle4testFWZaZv" "demangle.test(extern(Windows) char() function)"
+    test_demangling "_D8demangle4testFVZaZv" "demangle.test(extern(Pascal) char() function)"
+    test_demangling "_D8demangle4testFRZaZv" "demangle.test(extern(C++) char() function)"
+
+    test_demangling "_D8demangle4testFDFNaZaZv" "demangle.test(char() pure delegate)"
+    test_demangling "_D8demangle4testFDFNbZaZv" "demangle.test(char() nothrow delegate)"
+    test_demangling "_D8demangle4testFDFNcZaZv" "demangle.test(char() ref delegate)"
+    test_demangling "_D8demangle4testFDFNdZaZv" "demangle.test(char() @property delegate)"
+    test_demangling "_D8demangle4testFDFNeZaZv" "demangle.test(char() @trusted delegate)"
+    test_demangling "_D8demangle4testFDFNfZaZv" "demangle.test(char() @safe delegate)"
+
+    test_demangling "_D8demangle4testFFNaZaZv" "demangle.test(char() pure function)"
+    test_demangling "_D8demangle4testFFNbZaZv" "demangle.test(char() nothrow function)"
+    test_demangling "_D8demangle4testFFNcZaZv" "demangle.test(char() ref function)"
+    test_demangling "_D8demangle4testFFNdZaZv" "demangle.test(char() @property function)"
+    test_demangling "_D8demangle4testFFNeZaZv" "demangle.test(char() @trusted function)"
+    test_demangling "_D8demangle4testFFNfZaZv" "demangle.test(char() @safe function)"
+    test_demangling "_D8demangle4testFFNaNbZaZv" "demangle.test(char() pure nothrow function)"
+    test_demangling "_D8demangle4testFFNbNaZaZv" "demangle.test(char() nothrow pure function)"
+    test_demangling "_D8demangle4testFFNdNfNaZaZv" "demangle.test(char() @property @safe pure function)"
+
+    test_demangling "_D8demangle4test6__vtblZ" "demangle.test.vtbl$"
+    test_demangling "_D8demangle4test6__initZ" "demangle.test.init$"
+    test_demangling "_D8demangle4test12__ModuleInfoZ" "demangle.test.moduleinfo$"
+    test_demangling "_D8demangle4test7__ClassZ" "demangle.test.classinfo$"
+    test_demangling "_D8demangle4test11__InterfaceZ" "demangle.test.interface$"
+
+    test_demangling "_D8demangle4test6__ctorMFZv" "demangle.test.this()"
+    test_demangling "_D8demangle4test6__dtorMFZv" "demangle.test.~this()"
+    test_demangling "_D8demangle4test6__postblitMFZv" "demangle.test.this(this)"
+
+    test_demangling "_D8demangle4testFHAbaZv" "demangle.test(char\[bool\[\]\])"
+    test_demangling "_D8demangle4testFHG42caZv" "demangle.test(char\[creal\[42\]\])"
+    test_demangling "_D8demangle4testFAiXv" "demangle.test(int\[\]...)"
+    test_demangling "_D8demangle4testFLAiXv" "demangle.test(lazy int\[\]...)"
+    test_demangling "_D8demangle4testFAiYv" "demangle.test(int\[\], ...)"
+    test_demangling "_D8demangle4testFLAiYv" "demangle.test(lazy int\[\], ...)"
+    test_demangling "_D8demangle4testFLilZv" "demangle.test(lazy int, long)"
+    test_demangling "_D8demangle4testFLliZv" "demangle.test(lazy long, int)"
+
+    test_demangling "_D8demangle4testPFLAiYi" "demangle.test"
+    test_demangling "_D1a1bi" "a.b"
+    test_demangling "_D1a1bPFiZi" "a.b"
+    test_demangling "_D4test3fooAa" "test.foo"
+    test_demangling "_D4test2dgDFiYd" "test.dg"
+    test_demangling "_D8demangle8demangleFAaZAa" "demangle.demangle(char\[\])"
+    test_demangling "_D6object6Object8opAssignFC6ObjectZi" "object.Object.opAssign(Object)"
+    test_demangling "_D6object6Object8opEqualsFC6ObjectZi" "object.Object.opEquals(Object)"
+    test_demangling "_D8demangle4testFLC6ObjectLDFLiZiZi" "demangle.test(lazy Object, lazy int(lazy int) delegate)"
+    test_demangling "_D6plugin8generateFiiZAya" "plugin.generate(int, int)"
+    test_demangling "_D8demangle3fnAFZv3fnBMFZv" "demangle.fnA().fnB()"
+    test_demangling "_D8demangle4mainFZv1S3fnCFZv" "demangle.main().S.fnC()"
+    test_demangling "_D8demangle4mainFZv1S3fnDMFZv" "demangle.main().S.fnD()"
+    test_demangling "_D8demangle2fnFNgiZNgi" "demangle.fn(inout(int))"
+    test_demangling "_D8demangle4mainFZv5localMFZi" "demangle.main().local()"
+    test_demangling "_D3std5ascii9uppercaseyAa" "std.ascii.uppercase"
+    test_demangling "_D3std6stream9BOMEndianyG5E3std6system6Endian" "std.stream.BOMEndian"
+    test_demangling "_D3std8internal7uni_tab10unicodeNkoyS3std8internal3uni12CodepointSet" "std.internal.uni_tab.unicodeNko"
+    test_demangling "_D2gc2gc2GC6addrOfMFPvZPv" "gc.gc.GC.addrOf(void*)"
+    test_demangling "_D3std7process10setCLOEXECFibZv" "std.process.setCLOEXEC(int, bool)"
+    test_demangling "_D3std6digest2md3MD53putMFNaNbNeMAxhXv" "std.digest.md.MD5.put(scope const(ubyte)\[\]...)"
+    test_demangling "_D3std6mmfile6MmFile13opIndexAssignMFhmZh" "std.mmfile.MmFile.opIndexAssign(ubyte, ulong)"
+    test_demangling "_D3std7process18escapeShellCommandFxAAaXAya" "std.process.escapeShellCommand(const(char\[\]\[\])...)"
+    test_demangling "_D4core4sync5mutex5Mutex6__ctorMFC6ObjectZC4core4sync5mutex5Mutex" "core.sync.mutex.Mutex.this(Object)"
+    test_demangling "_D6object14TypeInfo_Array8argTypesMFNbNfJC8TypeInfoJC8TypeInfoZi" "object.TypeInfo_Array.argTypes(out TypeInfo, out TypeInfo)"
+    test_demangling "_D2rt6dmain211_d_run_mainUiPPaPUAAaZiZi7tryExecMFMDFZvZv" "rt.dmain2._d_run_main(int, char**, extern(C) int(char\[\]\[\]) function*).tryExec(scope void() delegate)"
+    test_demangling "_D6object9Exception6__ctorMFNaNbNfAyaAyamC6object9ThrowableZC9Exception" "object.Exception.this(immutable(char)\[\], immutable(char)\[\], ulong, object.Throwable)"
+    test_demangling "_D3gcc3deh17parse_lsda_headerFPS3gcc6unwind7generic15_Unwind_ContextPhPS3gcc3deh16lsda_header_infoZPh" "gcc.deh.parse_lsda_header(gcc.unwind.generic._Unwind_Context*, ubyte*, gcc.deh.lsda_header_info*)"
+    test_demangling "_D3std6socket23UnknownAddressReference6__ctorMFPS4core3sys5posix3sys6socket8sockaddrkZC3std6socket23UnknownAddressReference" "std.socket.UnknownAddressReference.this(core.sys.posix.sys.socket.sockaddr*, uint)"
+}
+
+proc catch_demangling_errors {command} {
+    if {[catch $command result]} {
+	puts "ERROR: demangle.exp: while running $command: $result"
+    }
+}
+
+# Test support for different demangling styles.  Note that this does
+# not depend upon running the test program and does not depend upon
+# gdb being able to lookup any D symbols.  It simply calls the 
+# internal demangler with synthesized strings and tests the results.
+
+proc do_tests {} {
+    global subdir
+    global gdb_prompt
+
+    # Start with a fresh gdb.
+
+    gdb_exit
+    gdb_start
+
+    gdb_test_no_output "set language d"
+    gdb_test_no_output "set width 0"
+
+    # Using catch_demangling_errors this way ensures that, if one of
+    # the functions raises a Tcl error, then it'll get reported, and
+    # the rest of the functions will still run.
+    catch_demangling_errors test_d_demangling
+}
+
+do_tests
diff --git a/gdb/testsuite/lib/d-support.exp b/gdb/testsuite/lib/d-support.exp
new file mode 100644
index 0000000..fe86787
--- /dev/null
+++ b/gdb/testsuite/lib/d-support.exp
@@ -0,0 +1,34 @@
+# Copyright 2014 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Auxiliary function to set the language to D.
+# The result is 1 (true) for success, 0 (false) for failure.
+
+proc set_lang_d {} {
+    if [gdb_test_no_output "set language d"] {
+	return 0
+    }
+    if [gdb_test "show language" ".* source language is \"d\"." \
+	   "set language to \"d\""] {
+	return 0
+    }
+    return 1
+}
+
+# D version of runto_main.
+
+proc d_runto_main { } {
+    return [runto _Dmain]
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 2713ddf..6367632 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1568,6 +1568,12 @@ proc skip_java_tests {} {
     return 0
 }
 
+# Return a 1 if I don't even want to try to test D.
+
+proc skip_d_tests {} {
+    return 0
+}
+
 # Return a 1 for configurations that do not support Python scripting.
 
 proc skip_python_tests {} {

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

* Re: [PATCH] Add d_main_name to dlang.c
  2014-01-03 18:18           ` Iain Buclaw
@ 2014-01-07  9:53             ` Iain Buclaw
  2014-01-07 10:44               ` Joel Brobecker
  0 siblings, 1 reply; 9+ messages in thread
From: Iain Buclaw @ 2014-01-07  9:53 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pierre Muller, gdb-patches

On 3 January 2014 18:18, Iain Buclaw <ibuclaw@gdcproject.org> wrote:
> On 19 November 2013 21:03, Tom Tromey <tromey@redhat.com> wrote:
>> Pierre>   I thought that in general, using the mangled name
>> Pierre> would allow to find main even if you do not generate
>> Pierre> any debug information, as long as you do not remove the
>> Pierre> assembler symbols from the executable.
>> Pierre>   This seems like a valid reason to prefer mangled name
>> Pierre> over demangled, no?
>>
>> The demangled name ends up in the minimal symbol table as well.
>> It's convoluted but it ends up in symbol_find_demangled_name, which has
>> a case for language_d.
>>
>> Tom
>
> Hi Tom,
>
> (I've just realised that I my last reply was not cc'd into gdb-patches)
>
> The assignments should now be processed.
>
> Since November, I've made a few more changes that are reflected in
> this new patch.
>
> I would add some more tests for D, but I feel that should write a
> complete parser for D expressions first (d-exp.y) - this will be done
> at a later date.
>

By the way, would it be best to split this up into smaller changes?

Regards
Iain.

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

* Re: [PATCH] Add d_main_name to dlang.c
  2014-01-07  9:53             ` Iain Buclaw
@ 2014-01-07 10:44               ` Joel Brobecker
  0 siblings, 0 replies; 9+ messages in thread
From: Joel Brobecker @ 2014-01-07 10:44 UTC (permalink / raw)
  To: Iain Buclaw; +Cc: gdb-patches

> By the way, would it be best to split this up into smaller changes?

If they can and should be applied independently, most definitely.
This has two strong advantages I can think of:
  - In case problem requiring a revert (I am not speaking of your
    patch!), it allows us to revert the one patch that causes problem,
    while keepping the rest;
  - It makes it much easier to review the patches, first because
    they are easier to digest, and second because we can review
    them one at a time, making it more likely for us to find the time
    to do so.

-- 
Joel

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

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

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-11-19  1:53 [PATCH] Add d_main_name to dlang.c Iain Buclaw
2013-11-19 16:09 ` Tom Tromey
2013-11-19 17:50   ` Iain Buclaw
2013-11-19 18:06     ` Tom Tromey
2013-11-19 21:05       ` Pierre Muller
     [not found]       ` <39451.43601527$1384894769@news.gmane.org>
2013-11-19 21:08         ` Tom Tromey
2014-01-03 18:18           ` Iain Buclaw
2014-01-07  9:53             ` Iain Buclaw
2014-01-07 10:44               ` Joel Brobecker

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).