Re: D language support

Mihail Zenkov
2010-01-13T04:42:18Z

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

> Please also make sure that you patch does not introduce any regression
> in our testsuite. Do you know how to test it? Basically, we run the
> testsuite before and after applying your patch, and verify that it
> does not introduce any new failures by comparing the gdb.sum files
> produced before and after. Please also make sure to mention which
> architecture this was tested on (typically x86-linux or x86_64-linux).

Tested on x86-linux. I have one regression and fix it.

> This is not a blocking comment, meaning that this is not a request
> to fix before your patch gets accepted, but I'm starting to think
> that the way you use your unbounded_string is to build the output
> before printing it. We typically would use a "ui_file" stream,
> for that. In your case, you want a "memory" ui-file. Have a look
> at ui-file.h, and in particular at mem_fileopen, ui_file_write,
> and ui_file_xstrdup. That should provide you all the infrastructure
> you need to get rid of this local "unbounded_string" type.
>
> I'll give you the choice: Look at this as part of this patch, or
> promise me that you'll look at it soon after this patch is in our tree.

You right, but in unbounded_string we allocate what we needed + 20 byte.
It allows to call allocation of memory less often. This way chose John
Demme. It effective way, when we need allocate many unbounded buffers
with big size. But in ours case we need only on small buffer.
I prefer another way - just allocate one buffer with size bigger than
worst case. It important in case with D language, as it can create only
static library at now. I do some test:

If we use ui_file we need call allocate 10275 times for "hello world"
and 86076 for real medium project on startup GDB.
If we use unbounded_string - 3130 and 25494.
If we use one buffer - 1214 and 8882.

Worst case size of buffer was 173 byte.

> > + if (ret != -1)
> > + break;
> > + default:
> > + ret = c_val_print (type, valaddr, embedded_offset, address, stream,
> > + recurse, options);
>
> This is surprising me a little. Don't you have plain struct types
> that are not dynamic arrays? Right now, the code seems to indicate
> that you don't expect any. Or maybe I missed something?

Look at this again. If we don't have dynamic array we ret -1. In this
case ret == -1 and we jump to default.

[-- Attachment #2: gdb-100113-d.patch --]
[-- Type: application/octet-stream, Size: 26830 bytes --]

gdb/ChangeLog:
D language support.
* Makefile.in (SFILES): Add d-lang.c d-valprint.c.
(COMMON_OBS): Add d-lang.o d-valprint.o.
(HFILES_NO_SRCDIR): Add d-lang.h.
* c-lang.c: Make c_emit_char and exp_descriptor_c public.
* c-lang.h: Add declaration c_emit_char and exp_descriptor_c.
* d-lang.c: New file.
* d-lang.h: New file.
* d-valprint.c: New file.
* defs.h (enum language): Add language_d.
* doc/gdb.texinfo: Add mention about D language support.
* dwarf2read.c (set_cu_language): Add DW_LANG_D.
* language.c (binop_result_type, integral_type, character_type)
(string_type, boolean_type, structured_type): Add language_d.
* symfile.c (init_filename_language_table): Add language_d.
* symtab.c Include d-lang.h.
(symbol_init_language_specific, symbol_find_demangled_name)
(symbol_natural_name, lookup_symbol_in_language)
(symbol_demangled_name, symbol_matches_domain): Add language_d.
* testsuite/gdb.base/default.exp: fix "set language" test.

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4d3e02a..7acd968 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -641,6 +641,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
charset.c cli-out.c coffread.c coff-pe-read.c \
complaints.c completer.c corefile.c \
cp-abi.c cp-support.c cp-namespace.c cp-valprint.c \
+ d-lang.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 \
@@ -707,7 +708,7 @@ cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h gnu-v2-abi.h \
exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h \
i386bsd-nat.h xml-support.h xml-tdesc.h alphabsd-tdep.h gdb_obstack.h \
ia64-tdep.h ada-lang.h varobj.h frv-tdep.h nto-tdep.h serial.h \
-c-lang.h frame.h event-loop.h block.h cli/cli-setshow.h \
+c-lang.h d-lang.h frame.h event-loop.h block.h cli/cli-setshow.h \
cli/cli-decode.h cli/cli-cmds.h cli/cli-dump.h \
cli/cli-script.h macrotab.h symtab.h version.h gnulib/wchar.in.h \
gnulib/string.in.h gnulib/str-two-way.h gnulib/extra/link-warning.h \
@@ -810,7 +811,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
dbxread.o coffread.o coff-pe-read.o \
dwarf2read.o mipsread.o stabsread.o corefile.o \
dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
- ada-lang.o c-lang.o f-lang.o objc-lang.o \
+ ada-lang.o c-lang.o d-lang.o f-lang.o objc-lang.o \
ada-tasks.o \
ui-out.o cli-out.o \
varobj.o vec.o wrapper.o \
@@ -820,7 +821,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
sentinel-frame.o \
complaints.o typeprint.o \
ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \
- ada-valprint.o c-valprint.o cp-valprint.o f-valprint.o m2-valprint.o \
+ ada-valprint.o c-valprint.o cp-valprint.o d-valprint.o f-valprint.o \
+ m2-valprint.o \
serial.o mdebugread.o top.o utils.o \
ui-file.o \
user-regs.o \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 66a9901..7b7e5da 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -253,7 +253,7 @@ print_wchar (gdb_wint_t w, const gdb_byte *orig, int orig_len,
string whose delimiter is QUOTER. Note that that format for printing
characters and strings is language specific. */

-static void
+void
c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter)
{
enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
@@ -1133,7 +1133,7 @@ c_language_arch_info (struct gdbarch *gdbarch,
lai->bool_type_default = builtin->builtin_int;
}

-static const struct exp_descriptor exp_descriptor_c =
+const struct exp_descriptor exp_descriptor_c =
{
print_subexp_standard,
operator_length_standard,
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index c2c5252..4d23364 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -87,6 +87,10 @@ extern void c_printstr (struct ui_file * stream, struct type *elttype,
extern void c_language_arch_info (struct gdbarch *gdbarch,
struct language_arch_info *lai);

+extern const struct exp_descriptor exp_descriptor_c;
+
+extern void c_emit_char (int c, struct type *type, struct ui_file *stream, int quoter);
+
/* These are in c-typeprint.c: */

extern void c_type_print_base (struct type *, struct ui_file *, int, int);
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
new file mode 100644
index 0000000..62f40be
--- /dev/null
+++ b/gdb/d-lang.c
@@ -0,0 +1,302 @@
+/* D language support routines for GDB, the GNU debugger.
+
+ Copyright (C) 2005, 2006, 2008, 2009, 2010 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 "symtab.h"
+#include "language.h"
+#include "d-lang.h"
+#include "c-lang.h"
+#include "gdb_string.h"
+#include "parser-defs.h"
+
+#include <ctype.h>
+
+static char* out_str;
+static char* out_pos;
+static char* mangled_str;
+
+/* Append string SRC to the end of string OUT_STR.
+ LEN is the length of SRC. */
+static void
+append_len (char* src, size_t len)
+{
+ int size = out_pos - out_str;
+
+ if (size < 1024) {
+ memcpy (out_pos, src, len);
+ out_pos += len;
+ }
+}
+
+/* Append string SRC to the end of string OUT_STR. */
+static void
+append (char* src)
+{
+ append_len (src, strlen (src));
+}
+
+/* Extract identifiers from MANGLED_STR and append it to OUT_STR.
+ Return 1 on success or 0 on failure. */
+static int
+extract_identifiers ()
+{
+ long i = 0;
+
+ while (isdigit (*mangled_str))
+ {
+ i = strtol (mangled_str, &mangled_str, 10);
+ if (i <= 0 && strlen (mangled_str) < i)
+ return 0;
+ append_len (mangled_str, i);
+ mangled_str += i;
+ append (".");
+ }
+ if (*mangled_str == '\0' || i == 0)
+ return 0;
+ out_pos--;
+ return 1;
+}
+
+/* Extract and demangle type from MANGLED_STR and append it to OUT_STR.
+ Return 1 on success or 0 on failure. */
+static int
+extract_type_info ()
+{
+ 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 ())
+ return 0;
+ append ("[]");
+ return 1;
+ case 'P': /* pointer */
+ if (!extract_type_info ())
+ return 0;
+ append ("*");
+ return 1;
+ case 'R': /* reference */
+ if (!extract_type_info ())
+ return 0;
+ append ("&");
+ return 1;
+ case 'Z': /* return value */
+ return extract_type_info ();
+ case 'J': /* out */
+ append ("out ");
+ return extract_type_info ();
+ case 'K': /* inout */
+ append ("inout ");
+ return extract_type_info ();
+ case 'E': /* enum */
+ case 'T': /* typedef */
+ case 'D': /* delegate */
+ case 'C': /* class */
+ case 'S': /* struct */
+ return extract_identifiers ();
+
+ /* basic types: */
+ case 'n': append ("none"); return 1;
+ case 'v': append ("void"); return 1;
+ case 'g': append ("byte"); return 1;
+ case 'h': append ("ubyte"); return 1;
+ case 's': append ("short"); return 1;
+ case 't': append ("ushort"); return 1;
+ case 'i': append ("int"); return 1;
+ case 'k': append ("uint"); return 1;
+ case 'l': append ("long"); return 1;
+ case 'm': append ("ulong"); return 1;
+ case 'f': append ("float"); return 1;
+ case 'd': append ("double"); return 1;
+ case 'e': append ("real"); return 1;
+
+ /* imaginary and complex: */
+ case 'o': append ("ifloat"); return 1;
+ case 'p': append ("idouble"); return 1;
+ case 'j': append ("ireal"); return 1;
+ case 'q': append ("cfloat"); return 1;
+ case 'r': append ("cdouble"); return 1;
+ case 'c': append ("creal"); return 1;
+
+ /* other types: */
+ case 'b': append ("bit"); return 1;
+ case 'a': append ("char"); return 1;
+ case 'u': append ("wchar"); return 1;
+ case 'w': append ("dchar"); return 1;
+
+ default:
+ append ("unknown");
+ return 1;
+ }
+}
+
+/* Implements the la_demangle language_defn routine for language D. */
+char *
+d_demangle (const char* symbol, int options)
+{
+ unsigned char is_func = 0;
+ int size;
+
+ mangled_str = (char *) symbol;
+
+ if (mangled_str == NULL)
+ return NULL;
+ else if (strcmp (mangled_str, "_Dmain") == 0)
+ return xstrdup ("D main");
+
+ out_str = xmalloc(1024);
+ out_pos = out_str;
+
+ if (mangled_str[0] == '_' && mangled_str[1] == 'D')
+ {
+ mangled_str += 2;
+ is_func = 1;
+ } else if (mangled_str == strstr (mangled_str, "__Class_"))
+ mangled_str += 8;
+ else if (mangled_str == strstr (mangled_str, "__init_"))
+ mangled_str += 7;
+ else if (mangled_str == strstr (mangled_str, "__vtbl_"))
+ mangled_str += 7;
+ else if (mangled_str == strstr (mangled_str, "__modctor_"))
+ mangled_str += 10;
+ else if (mangled_str == strstr (mangled_str, "__moddtor_"))
+ mangled_str += 10;
+ else if (mangled_str == strstr (mangled_str, "__ModuleInfo_"))
+ mangled_str += 13;
+ else
+ {
+ xfree (out_str);
+ return NULL;
+ }
+
+ if (!extract_identifiers ())
+ {
+ xfree (out_str);
+ return NULL;
+ }
+
+ append ("(");
+ if (is_func == 1 && *mangled_str == 'F')
+ {
+ mangled_str++;
+ while (*mangled_str != '\0' && *mangled_str != 'Z')
+ {
+ if (is_func == 1)
+ is_func++;
+ else
+ append (", ");
+ if (!extract_type_info ())
+ {
+ xfree (out_str);
+ return NULL;
+ }
+ }
+ }
+ append (")");
+
+ /* Doesn't display the return type, but wouldn't be too hard to do. */
+
+ size = out_pos - out_str;
+ out_str[size] = 0;
+ out_str = xrealloc (out_str, size + 1);
+ return out_str;
+}
+
+/* Table mapping opcodes into strings for printing operators
+ and precedences of the operators. */
+static const struct op_print d_op_print_tab[] =
+{
+ {",", BINOP_COMMA, PREC_COMMA, 0},
+ {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
+ {"||", BINOP_LOGICAL_OR, PREC_LOGICAL_OR, 0},
+ {"&&", BINOP_LOGICAL_AND, PREC_LOGICAL_AND, 0},
+ {"|", BINOP_BITWISE_IOR, PREC_BITWISE_IOR, 0},
+ {"^", BINOP_BITWISE_XOR, PREC_BITWISE_XOR, 0},
+ {"&", BINOP_BITWISE_AND, PREC_BITWISE_AND, 0},
+ {"==", BINOP_EQUAL, PREC_EQUAL, 0},
+ {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
+ {"<=", BINOP_LEQ, PREC_ORDER, 0},
+ {">=", BINOP_GEQ, PREC_ORDER, 0},
+ {">", BINOP_GTR, PREC_ORDER, 0},
+ {"<", BINOP_LESS, PREC_ORDER, 0},
+ {">>", BINOP_RSH, PREC_SHIFT, 0},
+ {"<<", BINOP_LSH, PREC_SHIFT, 0},
+ {"+", BINOP_ADD, PREC_ADD, 0},
+ {"-", BINOP_SUB, PREC_ADD, 0},
+ {"*", BINOP_MUL, PREC_MUL, 0},
+ {"/", BINOP_DIV, PREC_MUL, 0},
+ {"%", BINOP_REM, PREC_MUL, 0},
+ {"@", BINOP_REPEAT, PREC_REPEAT, 0},
+ {"-", UNOP_NEG, PREC_PREFIX, 0},
+ {"!", UNOP_LOGICAL_NOT, PREC_PREFIX, 0},
+ {"~", UNOP_COMPLEMENT, PREC_PREFIX, 0},
+ {"*", UNOP_IND, PREC_PREFIX, 0},
+ {"&", UNOP_ADDR, PREC_PREFIX, 0},
+ {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
+ {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
+ {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
+ {NULL, 0, 0, 0}
+};
+
+static const struct language_defn d_language_defn =
+{
+ "d", /* Language name */
+ language_d,
+ range_check_off,
+ type_check_off,
+ case_sensitive_on,
+ array_row_major,
+ macro_expansion_c,
+ &exp_descriptor_c,
+ c_parse,
+ c_error,
+ null_post_parser,
+ c_printchar, /* Print a character constant */
+ c_printstr, /* Function to print string constant */
+ c_emit_char, /* Print a single char */
+ c_print_type, /* Print a type using appropriate syntax */
+ c_print_typedef, /* Print a typedef using appropriate syntax */
+ d_val_print, /* Print a value using appropriate syntax */
+ c_value_print, /* Print a top-level value */
+ NULL, /* Language specific skip_trampoline */
+ "this", /* name_of_this */
+ basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
+ basic_lookup_transparent_type,/* lookup_transparent_type */
+ d_demangle, /* Language specific symbol demangler */
+ NULL, /* Language specific class_name_from_physname */
+ d_op_print_tab, /* expression operators for printing */
+ 1, /* c-style arrays */
+ 0, /* String lower bound */
+ default_word_break_characters,
+ default_make_symbol_completion_list,
+ c_language_arch_info,
+ default_print_array_index,
+ default_pass_by_reference,
+ c_get_string,
+ LANG_MAGIC
+};
+
+void
+_initialize_d_language (void)
+{
+ add_language (&d_language_defn);
+}
diff --git a/gdb/d-lang.h b/gdb/d-lang.h
new file mode 100644
index 0000000..6af2c66
--- /dev/null
+++ b/gdb/d-lang.h
@@ -0,0 +1,31 @@
+/* D language support definitions for GDB, the GNU debugger.
+
+ Copyright (C) 2005, 2006, 2008, 2009, 2010 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/>. */
+
+#if !defined (D_LANG_H)
+#define D_LANG_H 1
+
+#include "symtab.h"
+
+extern char* d_demangle (const char* mangled, int options);
+
+extern int d_val_print (struct type *type, const gdb_byte *valaddr,
+ int embedded_offset, CORE_ADDR address,
+ struct ui_file *stream, int recurse,
+ const struct value_print_options *options);
+#endif /* !defined (D_LANG_H) */
diff --git a/gdb/d-valprint.c b/gdb/d-valprint.c
new file mode 100644
index 0000000..67b32b7
--- /dev/null
+++ b/gdb/d-valprint.c
@@ -0,0 +1,91 @@
+/* Support for printing D values for GDB, the GNU debugger.
+
+ Copyright (C) 2008, 2009, 2010 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 "gdbtypes.h"
+#include "gdbcore.h"
+#include "d-lang.h"
+#include "c-lang.h"
+
+/* Assuming that TYPE is a TYPE_CODE_STRUCT, verify that TYPE is
+ a dynamic array, and then print its value to STREAM. Return
+ the number of string characters printed, or -1 if TYPE is not
+ a dynamic array. */
+static int
+dynamic_array_type (struct type *type, const gdb_byte *valaddr,
+ int embedded_offset, CORE_ADDR address,
+ struct ui_file *stream, int recurse,
+ const struct value_print_options *options)
+{
+ if (TYPE_NFIELDS (type) == 2
+ && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_INT
+ && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0
+ && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0)
+ {
+ CORE_ADDR addr;
+ struct type *elttype;
+ struct type *true_type;
+ struct type *ptr_type;
+ struct type *range_type;
+ const gdb_byte *ptraddr;
+ struct value *val;
+ int length;
+
+ length = unpack_field_as_long (type, valaddr + embedded_offset, 0);
+
+ ptr_type = TYPE_FIELD_TYPE (type, 1);
+ elttype = check_typedef (TYPE_TARGET_TYPE (ptr_type));
+ addr = unpack_pointer (ptr_type,
+ valaddr + TYPE_FIELD_BITPOS (type, 1) / 8
+ + embedded_offset);
+ true_type = check_typedef (elttype);
+
+ true_type = lookup_array_range_type (true_type, 0, length - 1);
+ val = value_at (true_type, addr);
+ ptraddr = value_contents (val);
+
+ return d_val_print (true_type, ptraddr, 0, addr, stream, recurse + 1,
+ options);
+ }
+ return -1;
+}
+
+/* Implements the la_val_print routine for language D. */
+int
+d_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset,
+ CORE_ADDR address, struct ui_file *stream, int recurse,
+ const struct value_print_options *options)
+{
+ int ret;
+
+ CHECK_TYPEDEF (type);
+ switch (TYPE_CODE (type))
+ {
+ case TYPE_CODE_STRUCT:
+ ret = dynamic_array_type (type, valaddr, embedded_offset, address,
+ stream, recurse, options);
+ if (ret != -1)
+ break;
+ default:
+ ret = c_val_print (type, valaddr, embedded_offset, address, stream,
+ recurse, options);
+ }
+
+ return ret;
+}
diff --git a/gdb/defs.h b/gdb/defs.h
index 5d251b5..2c14c80 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -188,6 +188,7 @@ enum language
language_auto, /* Placeholder for automatic setting */
language_c, /* C */
language_cplus, /* C++ */
+ language_d, /* D */
language_objc, /* Objective-C */
language_java, /* Java */
language_fortran, /* Fortran */
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5b78f50..d203649 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -213,6 +213,10 @@ You can use @value{GDBN} to debug programs written in C and C@t{++}.
For more information, see @ref{Supported Languages,,Supported Languages}.
For more information, see @ref{C,,C and C++}.

+@cindex D
+Support for D is partial. For information on D, see
+@ref{D,,D}.
+
@cindex Modula-2
Support for Modula-2 is partial. For information on Modula-2, see
@ref{Modula-2,,Modula-2}.
@@ -10554,6 +10558,9 @@ C source file
@itemx .c++
C@t{++} source file

+@item .d
+D source file
+
@item .m
Objective-C source file

@@ -10831,7 +10838,7 @@ being set automatically by @value{GDBN}.
@node Supported Languages
@section Supported Languages

-@value{GDBN} supports C, C@t{++}, Objective-C, Fortran, Java, Pascal,
+@value{GDBN} supports C, C@t{++}, D, Objective-C, Fortran, Java, Pascal,
assembly, Modula-2, and Ada.
@c This is false ...
Some @value{GDBN} features may be used in expressions regardless of the
@@ -10850,6 +10857,7 @@ language reference or tutorial.

@menu
* C:: C and C@t{++}
+* D:: D
* Objective-C:: Objective-C
* Fortran:: Fortran
* Pascal:: Pascal
@@ -11387,6 +11395,14 @@ In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
to inspect @code{_Decimal128} values stored in floating point registers.
See @ref{PowerPC,,PowerPC} for more details.

+@node D
+@subsection D
+
+@cindex D
+@value{GDBN} can be used to debug programs written in D and compiled with
+GDC, LDC or DMD. Currently @value{GDBN} supports only one D specific
+features - dynamic arrays.
+
@node Objective-C
@subsection Objective-C

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 7623035..4eafdc5 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7515,6 +7515,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
case DW_LANG_C_plus_plus:
cu->language = language_cplus;
break;
+ case DW_LANG_D:
+ cu->language = language_d;
+ break;
case DW_LANG_Fortran77:
case DW_LANG_Fortran90:
case DW_LANG_Fortran95:
diff --git a/gdb/language.c b/gdb/language.c
index 3500a97..6aa8f0e 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -486,6 +486,7 @@ binop_result_type (struct value *v1, struct value *v2)
{
case language_c:
case language_cplus:
+ case language_d:
case language_objc:
if (TYPE_CODE (t1) == TYPE_CODE_FLT)
return TYPE_CODE (t2) == TYPE_CODE_FLT && l2 > l1 ?
@@ -597,6 +598,7 @@ integral_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_d:
case language_objc:
return (TYPE_CODE (type) != TYPE_CODE_INT) &&
(TYPE_CODE (type) != TYPE_CODE_ENUM) ? 0 : 1;
@@ -637,6 +639,7 @@ character_type (struct type *type)

case language_c:
case language_cplus:
+ case language_d:
case language_objc:
return (TYPE_CODE (type) == TYPE_CODE_INT) &&
TYPE_LENGTH (type) == sizeof (char)
@@ -659,6 +662,7 @@ string_type (struct type *type)

case language_c:
case language_cplus:
+ case language_d:
case language_objc:
/* C does not have distinct string type. */
return (0);
@@ -678,6 +682,7 @@ boolean_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_d:
case language_objc:
/* Might be more cleanly handled by having a
TYPE_CODE_INT_NOT_BOOL for (the deleted) CHILL and such
@@ -717,6 +722,7 @@ structured_type (struct type *type)
{
case language_c:
case language_cplus:
+ case language_d:
case language_objc:
return (TYPE_CODE (type) == TYPE_CODE_STRUCT) ||
(TYPE_CODE (type) == TYPE_CODE_UNION) ||
diff --git a/gdb/symfile.c b/gdb/symfile.c
index cee84db..48d23da 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2534,6 +2534,7 @@ init_filename_language_table (void)
filename_language_table =
xmalloc (fl_table_size * sizeof (*filename_language_table));
add_filename_language (".c", language_c);
+ add_filename_language (".d", language_d);
add_filename_language (".C", language_cplus);
add_filename_language (".cc", language_cplus);
add_filename_language (".cp", language_cplus);
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 7f5dabd..be6f23a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -39,6 +39,7 @@
#include "source.h"
#include "filenames.h" /* for FILENAME_CMP */
#include "objc-lang.h"
+#include "d-lang.h"
#include "ada-lang.h"
#include "p-lang.h"
#include "addrmap.h"
@@ -413,6 +414,7 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
{
gsymbol->language = language;
if (gsymbol->language == language_cplus
+ || gsymbol->language == language_d
|| gsymbol->language == language_java
|| gsymbol->language == language_objc)
{
@@ -516,6 +518,16 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
return demangled;
}
}
+ if (gsymbol->language == language_d
+ || gsymbol->language == language_auto)
+ {
+ demangled = d_demangle(mangled, 0);
+ if (demangled != NULL)
+ {
+ gsymbol->language = language_d;
+ return demangled;
+ }
+ }
return NULL;
}

@@ -693,6 +705,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
switch (gsymbol->language)
{
case language_cplus:
+ case language_d:
case language_java:
case language_objc:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -718,6 +731,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
switch (gsymbol->language)
{
case language_cplus:
+ case language_d:
case language_java:
case language_objc:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
@@ -1263,7 +1277,7 @@ lookup_symbol_in_language (const char *name, const struct block *block,

modified_name = name;

- /* If we are using C++ or Java, demangle the name before doing a lookup, so
+ /* If we are using C++, D, or Java, demangle the name before doing a lookup, so
we can always binary search. */
if (lang == language_cplus)
{
@@ -1286,6 +1300,16 @@ lookup_symbol_in_language (const char *name, const struct block *block,
}
}
}
+ else if (current_language->la_language == language_d)
+ {
+ demangled_name = d_demangle (name, 0);
+ if (demangled_name)
+ {
+ mangled_name = name;
+ modified_name = demangled_name;
+ make_cleanup (xfree, demangled_name);
+ }
+ }
else if (lang == language_java)
{
demangled_name = cplus_demangle (name,
@@ -1734,6 +1758,7 @@ symbol_matches_domain (enum language symbol_language,
A Java class declaration also defines a typedef for the class.
Similarly, any Ada type declaration implicitly defines a typedef. */
if (symbol_language == language_cplus
+ || symbol_language == language_d
|| symbol_language == language_java
|| symbol_language == language_ada)
{
diff --git a/gdb/testsuite/gdb.base/default.exp b/gdb/testsuite/gdb.base/default.exp
index ab7a846..8cb4a5c 100644
--- a/gdb/testsuite/gdb.base/default.exp
+++ b/gdb/testsuite/gdb.base/default.exp
@@ -530,7 +530,7 @@ gdb_test "set history size" "Argument required .integer to set it to.*" "set his
#test set history
gdb_test "set history" "\"set history\" must be followed by the name of a history subcommand.(\[^\r\n\]*\[\r\n\])+List of set history subcommands:(\[^\r\n\]*\[\r\n\])+set history expansion -- Set history expansion on command input(\[^\r\n\]*\[\r\n\])+set history filename -- Set the filename in which to record the command history(\[^\r\n\]*\[\r\n\])+set history save -- Set saving of the history record on exit(\[^\r\n\]*\[\r\n\])+set history size -- Set the size of the command history(\[^\r\n\]*\[\r\n\])+Type \"help set history\" followed by set history subcommand name for full documentation.(\[^\r\n\]*\[\r\n\])+Command name abbreviations are allowed if unambiguous." "set history"
#test set language
-gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
+gdb_test "set language" "Requires an argument. Valid arguments are auto, local, unknown, ada, c, c.., asm, minimal, d, fortran, objective-c, java, modula-2, pascal, scheme." "set language"
#test set listsize
gdb_test "set listsize" "Argument required .integer to set it to.*" "set listsize"
#test set print "p" abbreviation