/* D language support routines for GDB, the GNU debugger.
- Copyright (C) 2005-2014 Free Software Foundation, Inc.
+ Copyright (C) 2005-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "varobj.h"
#include "d-lang.h"
#include "c-lang.h"
-#include <string.h>
+#include "demangle.h"
+#include "cp-support.h"
+#include "gdbarch.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 bound_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.minsym != 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. */
-char *
+
+gdb::unique_xmalloc_ptr<char>
d_demangle (const char *symbol, int options)
{
- struct obstack tempbuf;
- char *out_str;
- unsigned char is_func = 0;
-
- if (symbol == NULL)
- 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;
- else
- {
- obstack_free (&tempbuf, NULL);
- return NULL;
- }
-
- if (!extract_identifiers (symbol, &tempbuf))
- {
- 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 gdb_demangle (symbol, options | DMGL_DLANG);
}
-/* Table mapping opcodes into strings for printing operators
- and precedences of the operators. */
-static const struct op_print d_op_print_tab[] =
+/* Class representing the D language. */
+
+class d_language : public language_defn
{
- {",", 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}
+public:
+ d_language ()
+ : language_defn (language_d)
+ { /* Nothing. */ }
+
+ /* See language.h. */
+
+ const char *name () const override
+ { return "d"; }
+
+ /* See language.h. */
+
+ const char *natural_name () const override
+ { return "D"; }
+
+ /* See language.h. */
+
+ const std::vector<const char *> &filename_extensions () const override
+ {
+ static const std::vector<const char *> extensions = { ".d" };
+ return extensions;
+ }
+
+ /* See language.h. */
+ void language_arch_info (struct gdbarch *gdbarch,
+ struct language_arch_info *lai) const override
+ {
+ const struct builtin_d_type *builtin = builtin_d_type (gdbarch);
+
+ /* Helper function to allow shorter lines below. */
+ auto add = [&] (struct type * t)
+ {
+ lai->add_primitive_type (t);
+ };
+
+ add (builtin->builtin_void);
+ add (builtin->builtin_bool);
+ add (builtin->builtin_byte);
+ add (builtin->builtin_ubyte);
+ add (builtin->builtin_short);
+ add (builtin->builtin_ushort);
+ add (builtin->builtin_int);
+ add (builtin->builtin_uint);
+ add (builtin->builtin_long);
+ add (builtin->builtin_ulong);
+ add (builtin->builtin_cent);
+ add (builtin->builtin_ucent);
+ add (builtin->builtin_float);
+ add (builtin->builtin_double);
+ add (builtin->builtin_real);
+ add (builtin->builtin_ifloat);
+ add (builtin->builtin_idouble);
+ add (builtin->builtin_ireal);
+ add (builtin->builtin_cfloat);
+ add (builtin->builtin_cdouble);
+ add (builtin->builtin_creal);
+ add (builtin->builtin_char);
+ add (builtin->builtin_wchar);
+ add (builtin->builtin_dchar);
+
+ lai->set_string_char_type (builtin->builtin_char);
+ lai->set_bool_type (builtin->builtin_bool, "bool");
+ }
+
+ /* See language.h. */
+ bool sniff_from_mangled_name
+ (const char *mangled,
+ gdb::unique_xmalloc_ptr<char> *demangled) const override
+ {
+ *demangled = d_demangle (mangled, 0);
+ return *demangled != NULL;
+ }
+
+ /* See language.h. */
+
+ gdb::unique_xmalloc_ptr<char> demangle_symbol (const char *mangled,
+ int options) const override
+ {
+ return d_demangle (mangled, options);
+ }
+
+ /* See language.h. */
+
+ void print_type (struct type *type, const char *varstring,
+ struct ui_file *stream, int show, int level,
+ const struct type_print_options *flags) const override
+ {
+ c_print_type (type, varstring, stream, show, level, flags);
+ }
+
+ /* See language.h. */
+
+ void value_print_inner
+ (struct value *val, struct ui_file *stream, int recurse,
+ const struct value_print_options *options) const override
+ {
+ return d_value_print_inner (val, stream, recurse, options);
+ }
+
+ /* See language.h. */
+
+ struct block_symbol lookup_symbol_nonlocal
+ (const char *name, const struct block *block,
+ const domain_enum domain) const override
+ {
+ return d_lookup_symbol_nonlocal (this, name, block, domain);
+ }
+
+ /* See language.h. */
+
+ int parser (struct parser_state *ps) const override
+ {
+ return d_parse (ps);
+ }
+
+ /* See language.h. */
+
+ const char *name_of_this () const override
+ { return "this"; }
};
-static const struct language_defn d_language_defn =
+/* Single instance of the D language class. */
+
+static d_language d_language_defn;
+
+/* Build all D language types for the specified architecture. */
+
+static void *
+build_d_types (struct gdbarch *gdbarch)
{
- "d",
- "D",
- language_d,
- range_check_off,
- case_sensitive_on,
- array_row_major,
- macro_expansion_no,
- &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. */
- default_read_var_value, /* la_read_var_value */
- NULL, /* Language specific skip_trampoline. */
- "this",
- basic_lookup_symbol_nonlocal,
- basic_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,
- NULL, /* la_get_symbol_name_cmp */
- iterate_over_symbols,
- &default_varobj_ops,
- LANG_MAGIC
-};
+ 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, TARGET_CHAR_BIT, "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", gdbarch_float_format (gdbarch));
+ builtin_d_type->builtin_double
+ = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
+ "double", gdbarch_double_format (gdbarch));
+ builtin_d_type->builtin_real
+ = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+ "real", gdbarch_long_double_format (gdbarch));
+
+ builtin_d_type->builtin_byte->set_instance_flags
+ (builtin_d_type->builtin_byte->instance_flags ()
+ | TYPE_INSTANCE_FLAG_NOTTEXT);
+
+ builtin_d_type->builtin_ubyte->set_instance_flags
+ (builtin_d_type->builtin_ubyte->instance_flags ()
+ | TYPE_INSTANCE_FLAG_NOTTEXT);
+
+ /* Imaginary and complex types. */
+ builtin_d_type->builtin_ifloat
+ = arch_float_type (gdbarch, gdbarch_float_bit (gdbarch),
+ "ifloat", gdbarch_float_format (gdbarch));
+ builtin_d_type->builtin_idouble
+ = arch_float_type (gdbarch, gdbarch_double_bit (gdbarch),
+ "idouble", gdbarch_double_format (gdbarch));
+ builtin_d_type->builtin_ireal
+ = arch_float_type (gdbarch, gdbarch_long_double_bit (gdbarch),
+ "ireal", gdbarch_long_double_format (gdbarch));
+ builtin_d_type->builtin_cfloat
+ = init_complex_type ("cfloat", builtin_d_type->builtin_float);
+ builtin_d_type->builtin_cdouble
+ = init_complex_type ("cdouble", builtin_d_type->builtin_double);
+ builtin_d_type->builtin_creal
+ = init_complex_type ("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");
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_d_language;
+ return builtin_d_type;
+}
+
+static struct gdbarch_data *d_type_data;
+
+/* Return the D type table for the specified architecture. */
+
+const struct builtin_d_type *
+builtin_d_type (struct gdbarch *gdbarch)
+{
+ return (const struct builtin_d_type *) gdbarch_data (gdbarch, d_type_data);
+}
+void _initialize_d_language ();
void
-_initialize_d_language (void)
+_initialize_d_language ()
{
- add_language (&d_language_defn);
+ d_type_data = gdbarch_data_register_post_init (build_d_types);
}