From patchwork Sat Jan 30 16:29:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 10673 Received: (qmail 75797 invoked by alias); 30 Jan 2016 16:29:51 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 75785 invoked by uid 89); 30 Jan 2016 16:29:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=delegates, 786, UD:object, Anonymous X-HELO: mail-wm0-f48.google.com Received: from mail-wm0-f48.google.com (HELO mail-wm0-f48.google.com) (74.125.82.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Sat, 30 Jan 2016 16:29:46 +0000 Received: by mail-wm0-f48.google.com with SMTP id 128so19088893wmz.1 for ; Sat, 30 Jan 2016 08:29:45 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:sender:date:message-id:subject:from :to:content-type; bh=9fZF3c5/9t7Q192Zd/qMN56uXp5I3l1XAbP39TbMEtE=; b=lix+CleWKVRw8K3UyPEWB4DhAP76U3C8P6IPFaVoLkZID7rPXBgk1vWhIRiI3SN6so 8iefNJAgaTyiIxgPVe6u5nmlxJY7wjPmXcrFXQpmQ25GUPTBxdzaWP0V0HQ4RJuY4Qns 1Vfd/zhcTsAOTBIllJHXXG20rcPJbeJAFf82nztCU6q0G8KRWry5C23Q8mPg7A/9XV4p o/vK8jf0Z4rsiAOWnXGCQ5Bxm6hJIZ9vCZ35z/FMr++58q0NuXoGs4XhdnzhrzplrSch tIrZu+Cymd5FyiI8OKKWFMjDy18oDKS4O6I1bEAUVGZuYeS+iIuU89CipvAcT2g6bc4g r9rg== X-Gm-Message-State: AG10YOQZOvUo9a10HYMZcJNeZW9/q2n0D2+hswQ8HAutjkHdfRFG0oOamjJxCJktMtwzJ171Zjxng2CmNvAk9A== MIME-Version: 1.0 X-Received: by 10.28.173.71 with SMTP id w68mr3522479wme.88.1454171382866; Sat, 30 Jan 2016 08:29:42 -0800 (PST) Received: by 10.28.211.1 with HTTP; Sat, 30 Jan 2016 08:29:42 -0800 (PST) Date: Sat, 30 Jan 2016 17:29:42 +0100 Message-ID: Subject: [PATCH] [D] Add support for printing D types. From: Iain Buclaw To: GDB Patches X-IsSubscribed: yes Hi, This adds support for printing types as they would appear in D code. Tests cover pointers, function pointers, delegates, static arrays, dynamic arrays, associative arrays, strings (utf-8, 16 and 32), vectors and modules. Named types such as structs, unions, classes and enums will need some fudging of the compiler to not write out RTTI, however I have not had problems over the last months using them with this applied. Iain. gdb/ChangeLog: * Makefile.in (SFILES): Add d-typeprint.c (COMMON_OBJS): Add d-typeprint.o * d-lang.c (d_language_defn): Change c_print_type to d_print_type. * d-lang.h (d_print_type): New declaration. * d-typeprint.c: New file. * dwarf2read.c (read_structure_type): Set TYPE_DECLARED_CLASS also for classes in D language. gdb/testsuite/ChangeLog: * typeprint.S: New file. * typeprint.exp: New file. --- diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 5e8eb9a..3900029 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -838,7 +838,7 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ charset.c common/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-exp.y d-lang.c d-namespace.c d-valprint.c \ + d-exp.y d-lang.c d-namespace.c d-typeprint.c d-valprint.c \ cp-name-parser.y \ dbxread.c demangle.c dictionary.c disasm.c doublest.c \ dtrace-probe.c dummy-frame.c \ @@ -1063,7 +1063,8 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ m2-lang.o opencl-lang.o p-lang.o p-typeprint.o p-valprint.o \ sentinel-frame.o \ complaints.o typeprint.o \ - ada-typeprint.o c-typeprint.o f-typeprint.o m2-typeprint.o \ + ada-typeprint.o c-typeprint.o d-typeprint.o f-typeprint.o \ + m2-typeprint.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 \ diff --git a/gdb/d-lang.c b/gdb/d-lang.c index e8a08e1..409199b 100644 --- a/gdb/d-lang.c +++ b/gdb/d-lang.c @@ -206,7 +206,7 @@ static const struct language_defn d_language_defn = 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. */ + d_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. */ diff --git a/gdb/d-lang.h b/gdb/d-lang.h index 8f63f51..015fd93 100644 --- a/gdb/d-lang.h +++ b/gdb/d-lang.h @@ -20,6 +20,8 @@ #if !defined (D_LANG_H) #define D_LANG_H 1 +struct type_print_options; + #include "symtab.h" /* Language specific builtin types for D. Any additional types added @@ -78,6 +80,12 @@ extern struct block_symbol d_lookup_symbol_nonlocal (const struct language_defn extern struct block_symbol d_lookup_nested_symbol (struct type *, const char *, const struct block *); +/* Defined in d-typeprint.c. */ + +extern void d_print_type (struct type *type, const char *varstring, + struct ui_file *stream, int show, int level, + const struct type_print_options *flags); + /* Defined in d-valprint.c */ extern void d_val_print (struct type *type, const gdb_byte *valaddr, diff --git a/gdb/d-typeprint.c b/gdb/d-typeprint.c new file mode 100644 index 0000000..e94daed --- /dev/null +++ b/gdb/d-typeprint.c @@ -0,0 +1,384 @@ +/* Support for printing D types for GDB, the GNU debugger. + Copyright (C) 2016 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 . */ + +#include "defs.h" +#include "gdbtypes.h" +#include "demangle.h" +#include "typeprint.h" +#include "c-lang.h" +#include "cp-support.h" +#include "d-lang.h" + +/* Print the name of the type (or the ultimate pointer target, + function value or array element), or the description of a + structure or union. + + SHOW positive means print details about the type (e.g. enum + values), and print structure elements passing SHOW - 1 for show. + + SHOW negative means just print the type name or struct tag if there + is one. If there is no name, print something sensible but concise + like "struct {...}". + + SHOW zero means just print the type name or struct tag if there is + one. If there is no name, print something sensible but not as + concise like "struct {int x; int y;}". + + LEVEL is the number of spaces to indent by. + We increase it for some recursive calls. */ + +static void +d_type_print_base (struct type *type, struct ui_file *stream, int show, + int level, const struct type_print_options *flags) +{ + QUIT; + wrap_here (" "); + + if (type == NULL) + { + fputs_filtered ("", stream); + return; + } + + /* When SHOW is zero or less, and there is a valid type name, then always + just print the type name directly from the type. */ + if ((show <= 0) && (TYPE_NAME (type) != NULL)) + { + fputs_filtered (TYPE_NAME (type), stream); + return; + } + + if (TYPE_CODE (type) != TYPE_CODE_TYPEDEF) + type = check_typedef (type); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_TYPEDEF: + d_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level, flags); + break; + + case TYPE_CODE_ARRAY: + { + LONGEST low_bound, high_bound; + int is_vector = TYPE_VECTOR (type); + + if (is_vector) + fputs_filtered ("__vector(", stream); + + d_type_print_base (TYPE_TARGET_TYPE (type), stream, 0, level, flags); + fputs_filtered ("[", stream); + /* Bounds are not yet resolved, print a bounds placeholder instead. */ + if (TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCEXPR + || TYPE_HIGH_BOUND_KIND (TYPE_INDEX_TYPE (type)) == PROP_LOCLIST) + fputs_filtered ("variable length", stream); + else if (get_array_bounds (type, &low_bound, &high_bound)) + fprintf_filtered (stream, "%s", + plongest (high_bound - low_bound + 1)); + fputs_filtered ("]", stream); + + if (is_vector) + fputs_filtered (")", stream); + } + break; + + case TYPE_CODE_PTR: + { + struct type *target = TYPE_TARGET_TYPE (type); + int is_funcptr = (target != NULL + && TYPE_CODE (target) == TYPE_CODE_FUNC); + int is_class = (target != NULL + && TYPE_CODE (target) == TYPE_CODE_STRUCT + && TYPE_DECLARED_CLASS (target)); + + /* Want to show the contents of top-level class pointers. */ + if (show > 0 && !is_class) + show = 0; + + d_type_print_base (target, stream, show, level, flags); + + /* Function pointers have their own syntax. */ + if (is_funcptr) + { + int i; + + fputs_filtered (" function(", stream); + for (i = 0; i < TYPE_NFIELDS (target); i++) + { + struct field f = TYPE_FIELDS (target)[i]; + + if (i > 0) + fputs_filtered (", ", stream); + + d_type_print_base (FIELD_TYPE (f), stream, 0, level, flags); + } + fputs_filtered (")", stream); + } + else + { + /* Skip emitting the '*' for classes, as they are all represented + as pointer types in D. */ + if (!is_class) + fprintf_filtered (stream, "*"); + } + } + break; + + case TYPE_CODE_REF: + { + fputs_filtered ("ref ", stream); + d_type_print_base (TYPE_TARGET_TYPE (type), stream, + show, level, flags); + } + break; + + case TYPE_CODE_FUNC: + d_type_print_base (TYPE_TARGET_TYPE (type), stream, + show, level, flags); + break; + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + const char *tagname = TYPE_TAG_NAME (type); + + if (tagname != NULL) + { + char lastchar = tagname[strlen (tagname) - 1]; + + fputs_filtered (tagname, stream); + /* If it's a dynamic or associative array, or a delegate function, + don't print the underlying type structure. */ + if (lastchar == ']' || lastchar == ')') + break; + + /* String types in D are aliases to dynamic arrays, however their + aliases are written to debug instead of the underlying type. */ + if ((strcmp (tagname, "string") == 0 + || strcmp (tagname, "wstring") == 0 + || strcmp (tagname, "dstring") == 0) + && TYPE_NFIELDS (type) == 2 + && strcmp (TYPE_FIELD_NAME (type, 0), "length") == 0 + && strcmp (TYPE_FIELD_NAME (type, 1), "ptr") == 0) + break; + + if (show > 0) + fputs_filtered (" ", stream); + } + else + { + /* Anonymous class/struct/union. */ + if (TYPE_CODE (type) == TYPE_CODE_UNION) + fputs_filtered ("union ", stream); + else if (TYPE_DECLARED_CLASS (type)) + fputs_filtered ("class ", stream); + else + fputs_filtered ("struct ", stream); + } + + wrap_here (" "); + + if (show < 0) + { + /* If we just printed a tag name, no need to print anything else. */ + if (tagname == NULL) + fprintf_filtered (stream, "{...}"); + } + else if (show > 0 || TYPE_TAG_NAME (type) == NULL) + { + int len; + int i, j; + + // FIXME: print inheritance / interfaces + + fputs_filtered ("{\n", stream); + if ((TYPE_NFIELDS (type) == 0) && (TYPE_NFN_FIELDS (type) == 0)) + { + if (TYPE_STUB (type)) + fprintfi_filtered (level + 4, stream, "\n"); + else + fprintfi_filtered (level + 4, stream, "\n"); + } + + QUIT; + + /* If there is a base class for this type, + do not print the field that it occupies. */ + len = TYPE_NFIELDS (type); + for (i = TYPE_N_BASECLASSES (type); i < len; i++) + { + QUIT; + /* Don't print out virtual function table or monitor. + These are the first two fields placed in the class, + and should be marked as artificial. */ + if (i < 2 && TYPE_DECLARED_CLASS (type)) + { + if (TYPE_FIELD_ARTIFICIAL (type, i)) + continue; + else if (startswith (TYPE_FIELD_NAME (type, i), "__vptr")) + continue; + else if (startswith (TYPE_FIELD_NAME (type, i), "__monitor")) + continue; + } + + print_spaces_filtered (level + 4, stream); + + if (TYPE_FIELD_PROTECTED (type, i)) + fputs_filtered ("protected ", stream); + else if (TYPE_FIELD_PRIVATE (type, i)) + fputs_filtered ("private ", stream); + + if (field_is_static (&TYPE_FIELD (type, i))) + fputs_filtered ("static ", stream); + + d_print_type (TYPE_FIELD_TYPE (type, i), + TYPE_FIELD_NAME (type, i), + stream, show - 1, level + 4, flags); + fputs_filtered (";\n", stream); + } + + /* Print out the methods, artificial methods will be hidden. */ + len = TYPE_NFN_FIELDS (type); + if (!flags->print_methods) + len = 0; + + for (i = 0; i < len; i++) + { + for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); j++) + { + struct fn_field *fields = TYPE_FN_FIELDLIST1 (type, i); + const char *method_name; + char *mangled_name; + char *demangled_name; + struct type *target; + + /* Do not print out artificial methods. */ + if (TYPE_FN_FIELD_ARTIFICIAL (fields, j)) + continue; + + method_name = TYPE_FN_FIELDLIST_NAME (type, i); + + /* Build something we can demangle. */ + if (TYPE_FN_FIELD_STUB (fields, j)) + mangled_name = gdb_mangle_name (type, i, j); + else + { + const char *physname; + int physname_len; + + physname = TYPE_FN_FIELD_PHYSNAME (fields, j); + physname_len = strlen(physname); + + mangled_name = alloca (physname_len + 1); + memcpy (mangled_name, physname, physname_len); + mangled_name[physname_len] = '\0'; + } + + QUIT; + print_spaces_filtered (level + 4, stream); + + if (TYPE_FN_FIELD_PROTECTED (fields, j)) + fputs_filtered ("protected ", stream); + else if (TYPE_FN_FIELD_PRIVATE (fields, j)) + fputs_filtered ("private ", stream); + + if (TYPE_FN_FIELD_ABSTRACT (fields, j)) + fputs_filtered ("abstract ", stream); + if (TYPE_FN_FIELD_STATIC (fields, j)) + fputs_filtered ("static ", stream); + if (TYPE_FN_FIELD_FINAL (fields, j)) + fputs_filtered ("final ", stream); + if (TYPE_FN_FIELD_SYNCHRONIZED (fields, j)) + fputs_filtered ("synchronized ", stream); + + target = TYPE_TARGET_TYPE (TYPE_FN_FIELD_TYPE (fields, j)); + if (target == NULL) + { + /* Keep GDB from crashing here. */ + fprintf_filtered (stream, " %s;\n", + TYPE_FN_FIELD_PHYSNAME (fields, j)); + break; + } + else if (strcmp (method_name, "__ctor") != 0 + && strcmp (method_name, "__dtor") != 0 + && strcmp (method_name, "__postblit") != 0) + { + d_print_type (target, "", stream, -1, 0, flags); + fputs_filtered (" ", stream); + } + + demangled_name = gdb_demangle (mangled_name, DMGL_DLANG); + + if (demangled_name != NULL) + { + /* Skip to the base name of the demangled symbol. */ + char *p = strchr (demangled_name, '('); + gdb_assert (p != NULL); + while (p > demangled_name && p[-1] != '.') + p--; + + fputs_filtered (p, stream); + xfree (demangled_name); + } + else + fputs_filtered (mangled_name, stream); + + if (TYPE_FN_FIELD_STUB (fields, j)) + xfree (mangled_name); + + fputs_filtered (";\n", stream); + } + } + + fprintfi_filtered (level, stream, "}"); + } + } + break; + + case TYPE_CODE_MODULE: + fprintf_filtered (stream, "module %s", TYPE_TAG_NAME (type)); + break; + + default: + /* Handle types not explicitly handled by the other cases, + such as fundamental types. For these, just print whatever + the type name is, as recorded in the type itself. If there + is no type name, then hand it down to c_type_print_base. */ + if (TYPE_NAME (type) != NULL) + fprintfi_filtered (level, stream, "%s", TYPE_NAME (type)); + else + c_type_print_base (type, stream, show, level, flags); + break; + } +} + +/* LEVEL is the depth to indent lines by. */ + +void +d_print_type (struct type *type, const char *varstring, + struct ui_file *stream, int show, int level, + const struct type_print_options *flags) +{ + d_type_print_base (type, stream, show, level, flags); + + if (varstring != NULL && *varstring != '\0') + { + fputs_filtered (" ", stream); + fputs_filtered (varstring, stream); + } +} + diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 1020c12..6be6115 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13199,7 +13199,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) TYPE_CODE (type) = TYPE_CODE_STRUCT; } - if (cu->language == language_cplus && die->tag == DW_TAG_class_type) + if ((cu->language == language_cplus || cu->language == language_d) + && die->tag == DW_TAG_class_type) TYPE_DECLARED_CLASS (type) = 1; attr = dwarf2_attr (die, DW_AT_byte_size, cu); diff --git a/gdb/testsuite/gdb.dlang/typeprint.S b/gdb/testsuite/gdb.dlang/typeprint.S new file mode 100644 index 0000000..e8e1ae4 --- /dev/null +++ b/gdb/testsuite/gdb.dlang/typeprint.S @@ -0,0 +1,588 @@ +/* Copyright 2016 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 . */ + +/* This file was generated using: + + $ gdc -g -Og -dA typeprint.d -S -o typeprint.S + + with + + $ gdc -v + gcc version 6.0.0 20160123 (experimental) (GCC) + Target: x86_64-pc-linux-gnu + Thread model: posix + + And then manually cleaned up some debug comments. */ + .file "typeprint.d" + .text +.Ltext0: + .globl main + .type main, @function +main: +.LFB0: + .file 1 "typeprint.d" + # typeprint.d:3 + .loc 1 3 0 + .cfi_startproc + rep ret + .cfi_endproc +.LFE0: + .size main, .-main +.Letext0: + .file 2 "" + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0x235 # Length of Compilation Unit Info + .value 0x4 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x8 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF28 # DW_AT_producer: "GNU D 6.0.0 20160123 (experimental)" + .byte 0x13 # DW_AT_language + .long .LASF29 # DW_AT_name: "typeprint.d" + .long .LASF30 # DW_AT_comp_dir: "/tmp" + .quad .Ltext0 # DW_AT_low_pc + .quad .Letext0-.Ltext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x2d) DW_TAG_module) + .long .LASF31 # DW_AT_name: "typeprint" + # DW_AT_declaration + .long 0xbf # DW_AT_sibling + .uleb128 0x3 # (DIE (0x36) DW_TAG_subprogram) + # DW_AT_external + .long .LASF32 # DW_AT_name: "main" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0x3 # DW_AT_decl_line + .quad .LFB0 # DW_AT_low_pc + .quad .LFE0-.LFB0 # DW_AT_high_pc + .uleb128 0x1 # DW_AT_frame_base + .byte 0x9c # DW_OP_call_frame_cfa + # DW_AT_GNU_all_call_sites + .uleb128 0x4 # (DIE (0x4f) DW_TAG_variable) + .long .LASF0 # DW_AT_name: "vectorarray" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xf # DW_AT_decl_line + .long 0xbf # DW_AT_type + .uleb128 0x4 # (DIE (0x5a) DW_TAG_variable) + .long .LASF1 # DW_AT_name: "dstringvalue" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xe # DW_AT_decl_line + .long 0xd2 # DW_AT_type + .uleb128 0x4 # (DIE (0x65) DW_TAG_variable) + .long .LASF2 # DW_AT_name: "wstringvalue" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xd # DW_AT_decl_line + .long 0x10e # DW_AT_type + .uleb128 0x4 # (DIE (0x70) DW_TAG_variable) + .long .LASF3 # DW_AT_name: "stringvalue" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xc # DW_AT_decl_line + .long 0x143 # DW_AT_type + .uleb128 0x4 # (DIE (0x7b) DW_TAG_variable) + .long .LASF4 # DW_AT_name: "associativearray" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xb # DW_AT_decl_line + .long 0x178 # DW_AT_type + .uleb128 0x4 # (DIE (0x86) DW_TAG_variable) + .long .LASF5 # DW_AT_name: "dynamicarray" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0xa # DW_AT_decl_line + .long 0x191 # DW_AT_type + .uleb128 0x4 # (DIE (0x91) DW_TAG_variable) + .long .LASF6 # DW_AT_name: "delegateptr" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0x9 # DW_AT_decl_line + .long 0x1c1 # DW_AT_type + .uleb128 0x4 # (DIE (0x9c) DW_TAG_variable) + .long .LASF7 # DW_AT_name: "funcptr" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0x8 # DW_AT_decl_line + .long 0x214 # DW_AT_type + .uleb128 0x4 # (DIE (0xa7) DW_TAG_variable) + .long .LASF8 # DW_AT_name: "staticarray" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0x7 # DW_AT_decl_line + .long 0x21a # DW_AT_type + .uleb128 0x4 # (DIE (0xb2) DW_TAG_variable) + .long .LASF9 # DW_AT_name: "voidptr" + .byte 0x1 # DW_AT_decl_file (typeprint.d) + .byte 0x6 # DW_AT_decl_line + .long 0x18f # DW_AT_type + .byte 0 # end of children of DIE 0x36 + .byte 0 # end of children of DIE 0x2d + .uleb128 0x5 # (DIE (0xbf) DW_TAG_array_type) + # DW_AT_GNU_vector + .long 0xcb # DW_AT_type + .long 0xcb # DW_AT_sibling + .uleb128 0x6 # (DIE (0xc8) DW_TAG_subrange_type) + .byte 0x7 # DW_AT_upper_bound + .byte 0 # end of children of DIE 0xbf + .uleb128 0x7 # (DIE (0xcb) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF11 # DW_AT_name: "ubyte" + .uleb128 0x8 # (DIE (0xd2) DW_TAG_structure_type) + .long .LASF14 # DW_AT_name: "dstring" + .byte 0x10 # DW_AT_byte_size + .long 0xf5 # DW_AT_sibling + .uleb128 0x9 # (DIE (0xdc) DW_TAG_member) + .long .LASF10 # DW_AT_name: "length" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0xf5 # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0xa # (DIE (0xe8) DW_TAG_member) + .ascii "ptr\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0xfc # DW_AT_type + .byte 0x8 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0xd2 + .uleb128 0x7 # (DIE (0xf5) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF12 # DW_AT_name: "ulong" + .uleb128 0xb # (DIE (0xfc) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x109 # DW_AT_type + .uleb128 0x7 # (DIE (0x102) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF13 # DW_AT_name: "dchar" + .uleb128 0xc # (DIE (0x109) DW_TAG_const_type) + .long 0x102 # DW_AT_type + .uleb128 0x8 # (DIE (0x10e) DW_TAG_structure_type) + .long .LASF15 # DW_AT_name: "wstring" + .byte 0x10 # DW_AT_byte_size + .long 0x131 # DW_AT_sibling + .uleb128 0x9 # (DIE (0x118) DW_TAG_member) + .long .LASF10 # DW_AT_name: "length" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0xf5 # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0xa # (DIE (0x124) DW_TAG_member) + .ascii "ptr\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x131 # DW_AT_type + .byte 0x8 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x10e + .uleb128 0xb # (DIE (0x131) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x13e # DW_AT_type + .uleb128 0x7 # (DIE (0x137) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF16 # DW_AT_name: "wchar" + .uleb128 0xc # (DIE (0x13e) DW_TAG_const_type) + .long 0x137 # DW_AT_type + .uleb128 0x8 # (DIE (0x143) DW_TAG_structure_type) + .long .LASF17 # DW_AT_name: "string" + .byte 0x10 # DW_AT_byte_size + .long 0x166 # DW_AT_sibling + .uleb128 0x9 # (DIE (0x14d) DW_TAG_member) + .long .LASF10 # DW_AT_name: "length" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0xf5 # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0xa # (DIE (0x159) DW_TAG_member) + .ascii "ptr\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x166 # DW_AT_type + .byte 0x8 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x143 + .uleb128 0xb # (DIE (0x166) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x173 # DW_AT_type + .uleb128 0x7 # (DIE (0x16c) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x8 # DW_AT_encoding + .long .LASF18 # DW_AT_name: "char" + .uleb128 0xc # (DIE (0x173) DW_TAG_const_type) + .long 0x16c # DW_AT_type + .uleb128 0x8 # (DIE (0x178) DW_TAG_structure_type) + .long .LASF19 # DW_AT_name: "uint[uint]" + .byte 0x8 # DW_AT_byte_size + .long 0x18f # DW_AT_sibling + .uleb128 0xa # (DIE (0x182) DW_TAG_member) + .ascii "ptr\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x18f # DW_AT_type + .byte 0 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x178 + .uleb128 0xd # (DIE (0x18f) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .uleb128 0x8 # (DIE (0x191) DW_TAG_structure_type) + .long .LASF20 # DW_AT_name: "long[]" + .byte 0x10 # DW_AT_byte_size + .long 0x1b4 # DW_AT_sibling + .uleb128 0x9 # (DIE (0x19b) DW_TAG_member) + .long .LASF10 # DW_AT_name: "length" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0xf5 # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0xa # (DIE (0x1a7) DW_TAG_member) + .ascii "ptr\0" # DW_AT_name + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x1b4 # DW_AT_type + .byte 0x8 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x191 + .uleb128 0xb # (DIE (0x1b4) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x1ba # DW_AT_type + .uleb128 0x7 # (DIE (0x1ba) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF21 # DW_AT_name: "long" + .uleb128 0x8 # (DIE (0x1c1) DW_TAG_structure_type) + .long .LASF22 # DW_AT_name: "char delegate(byte)" + .byte 0x10 # DW_AT_byte_size + .long 0x1e4 # DW_AT_sibling + .uleb128 0x9 # (DIE (0x1cb) DW_TAG_member) + .long .LASF23 # DW_AT_name: "object" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x18f # DW_AT_type + .byte 0 # DW_AT_data_member_location + .uleb128 0x9 # (DIE (0x1d7) DW_TAG_member) + .long .LASF24 # DW_AT_name: "func" + .byte 0x2 # DW_AT_decl_file () + .byte 0 # DW_AT_decl_line + .long 0x1ff # DW_AT_type + .byte 0x8 # DW_AT_data_member_location + .byte 0 # end of children of DIE 0x1c1 + .uleb128 0xe # (DIE (0x1e4) DW_TAG_subroutine_type) + .long 0x16c # DW_AT_type + .long 0x1f8 # DW_AT_sibling + .uleb128 0xf # (DIE (0x1ed) DW_TAG_formal_parameter) + .long 0x18f # DW_AT_type + .uleb128 0xf # (DIE (0x1f2) DW_TAG_formal_parameter) + .long 0x1f8 # DW_AT_type + .byte 0 # end of children of DIE 0x1e4 + .uleb128 0x7 # (DIE (0x1f8) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF25 # DW_AT_name: "byte" + .uleb128 0xb # (DIE (0x1ff) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x1e4 # DW_AT_type + .uleb128 0xe # (DIE (0x205) DW_TAG_subroutine_type) + .long 0x16c # DW_AT_type + .long 0x214 # DW_AT_sibling + .uleb128 0xf # (DIE (0x20e) DW_TAG_formal_parameter) + .long 0x1f8 # DW_AT_type + .byte 0 # end of children of DIE 0x205 + .uleb128 0xb # (DIE (0x214) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long 0x205 # DW_AT_type + .uleb128 0x10 # (DIE (0x21a) DW_TAG_array_type) + .long 0x231 # DW_AT_type + .long 0x22a # DW_AT_sibling + .uleb128 0x11 # (DIE (0x223) DW_TAG_subrange_type) + .long 0x22a # DW_AT_type + .byte 0 # DW_AT_upper_bound + .byte 0 # end of children of DIE 0x21a + .uleb128 0x7 # (DIE (0x22a) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF26 # DW_AT_name: "sizetype" + .uleb128 0x7 # (DIE (0x231) DW_TAG_base_type) + .byte 0x2 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .long .LASF27 # DW_AT_name: "short" + .byte 0 # end of children of DIE 0xb + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x17 # (DW_FORM_sec_offset) + .byte 0 + .byte 0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x1e # (TAG: DW_TAG_module) + .byte 0x1 # DW_children_yes + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3c # (DW_AT_declaration) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x7 # (DW_FORM_data8) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x18 # (DW_FORM_exprloc) + .uleb128 0x2117 # (DW_AT_GNU_all_call_sites) + .uleb128 0x19 # (DW_FORM_flag_present) + .byte 0 + .byte 0 + .uleb128 0x4 # (abbrev code) + .uleb128 0x34 # (TAG: DW_TAG_variable) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x1 # (TAG: DW_TAG_array_type) + .byte 0x1 # DW_children_yes + .uleb128 0x2107 # (DW_AT_GNU_vector) + .uleb128 0x19 # (DW_FORM_flag_present) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x6 # (abbrev code) + .uleb128 0x21 # (TAG: DW_TAG_subrange_type) + .byte 0 # DW_children_no + .uleb128 0x2f # (DW_AT_upper_bound) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0 + .byte 0 + .uleb128 0x8 # (abbrev code) + .uleb128 0x13 # (TAG: DW_TAG_structure_type) + .byte 0x1 # DW_children_yes + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x9 # (abbrev code) + .uleb128 0xd # (TAG: DW_TAG_member) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x38 # (DW_AT_data_member_location) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0xa # (abbrev code) + .uleb128 0xd # (TAG: DW_TAG_member) + .byte 0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x38 # (DW_AT_data_member_location) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0xb # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0xc # (abbrev code) + .uleb128 0x26 # (TAG: DW_TAG_const_type) + .byte 0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0xd # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .uleb128 0xe # (abbrev code) + .uleb128 0x15 # (TAG: DW_TAG_subroutine_type) + .byte 0x1 # DW_children_yes + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0xf # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x10 # (abbrev code) + .uleb128 0x1 # (TAG: DW_TAG_array_type) + .byte 0x1 # DW_children_yes + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x1 # (DW_AT_sibling) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0 + .byte 0 + .uleb128 0x11 # (abbrev code) + .uleb128 0x21 # (TAG: DW_TAG_subrange_type) + .byte 0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2f # (DW_AT_upper_bound) + .uleb128 0xb # (DW_FORM_data1) + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x2c # Length of Address Ranges Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x8 # Size of Address + .byte 0 # Size of Segment Descriptor + .value 0 # Pad to 16 byte boundary + .value 0 + .quad .Ltext0 # Address + .quad .Letext0-.Ltext0 # Length + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF14: + .string "dstring" +.LASF19: + .string "uint[uint]" +.LASF3: + .string "stringvalue" +.LASF17: + .string "string" +.LASF23: + .string "object" +.LASF5: + .string "dynamicarray" +.LASF16: + .string "wchar" +.LASF25: + .string "byte" +.LASF1: + .string "dstringvalue" +.LASF10: + .string "length" +.LASF30: + .string "/tmp" +.LASF13: + .string "dchar" +.LASF27: + .string "short" +.LASF31: + .string "typeprint" +.LASF2: + .string "wstringvalue" +.LASF6: + .string "delegateptr" +.LASF32: + .string "main" +.LASF4: + .string "associativearray" +.LASF26: + .string "sizetype" +.LASF21: + .string "long" +.LASF29: + .string "typeprint.d" +.LASF22: + .string "char delegate(byte)" +.LASF12: + .string "ulong" +.LASF28: + .string "GNU D 6.0.0 20160123 (experimental)" +.LASF11: + .string "ubyte" +.LASF8: + .string "staticarray" +.LASF7: + .string "funcptr" +.LASF0: + .string "vectorarray" +.LASF9: + .string "voidptr" +.LASF15: + .string "wstring" +.LASF24: + .string "func" +.LASF18: + .string "char" +.LASF20: + .string "long[]" + .ident "GCC: (GNU) 6.0.0 20160123 (experimental)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.dlang/typeprint.exp b/gdb/testsuite/gdb.dlang/typeprint.exp new file mode 100644 index 0000000..9e42480 --- /dev/null +++ b/gdb/testsuite/gdb.dlang/typeprint.exp @@ -0,0 +1,80 @@ +# Copyright (C) 2016 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 . + +# Test printing various built-in types. + +load_lib "d-support.exp" +load_lib "dwarf.exp" + +if { [skip_d_tests] } { continue } + +# This test can only be run on x86-64 targets which support DWARF. +if {![dwarf2_support] || ![istarget "x86_64-*-*"] || ![is_lp64_target]} { + return 0 +} + +standard_testfile .S + +# Compile and start with a fresh gdb. + +if {[prepare_for_testing $testfile.exp $testfile $srcfile {nodebug}]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +# Simple pointer type. +gdb_test "ptype voidptr" "type = void\\*" + +# Simple array type. +gdb_test "ptype staticarray" "type = short\\\[1\\\]" + +# Function types are also pointers, but printed without the asterisk. +gdb_test "ptype funcptr" "type = char function\\(byte\\)" + +# Delegates are two-field record types, but only the name is printed. +gdb_test "ptype delegateptr" "type = char delegate\\(byte\\)" +gdb_test "ptype delegateptr.object" "type = void\\*" +gdb_test "ptype delegateptr.func" "type = char function\\(void\\*, byte\\)" + +# Likewise for dynamic arrays. +gdb_test "ptype dynamicarray" "type = long\\\[\\\]" +gdb_test "ptype dynamicarray.length" "type = ulong" +gdb_test "ptype dynamicarray.ptr" "type = long\\*" + +# Likewise for associative arrays. +gdb_test "ptype associativearray" "type = uint\\\[uint\\\]" +gdb_test "ptype associativearray.ptr" "type = void\\*" + +# Strings are really dynamic arrays, but they are given a typename. +gdb_test "ptype stringvalue" "type = string" +gdb_test "ptype stringvalue.length" "type = ulong" +gdb_test "ptype stringvalue.ptr" "type = char\\*" + +gdb_test "ptype wstringvalue" "type = wstring" +gdb_test "ptype wstringvalue.length" "type = ulong" +gdb_test "ptype wstringvalue.ptr" "type = wchar\\*" + +gdb_test "ptype dstringvalue" "type = dstring" +gdb_test "ptype dstringvalue.length" "type = ulong" +gdb_test "ptype dstringvalue.ptr" "type = dchar\\*" + +# Vectors have their own special syntax. +gdb_test "ptype vectorarray" "type = __vector\\(ubyte\\\[8\\\]\\)" + +# Finally, recognize D modules. +gdb_test "ptype typeprint" "type = module typeprint"