+2020-06-02 Andrew Burgess <andrew.burgess@embecosm.com>
+
+ * gdb/ada-lang.c (ada_language_defn): Convert to...
+ (ada_language_data): ...this.
+ (class ada_language): New class.
+ (ada_language_defn): New static global.
+ * gdb/c-lang.c (c_language_defn): Convert to...
+ (c_language_data): ...this.
+ (class c_language): New class.
+ (c_language_defn): New static global.
+ (cplus_language_defn): Convert to...
+ (cplus_language_data): ...this.
+ (class cplus_language): New class.
+ (cplus_language_defn): New static global.
+ (asm_language_defn): Convert to...
+ (asm_language_data): ...this.
+ (class asm_language): New class.
+ (asm_language_defn): New static global.
+ (minimal_language_defn): Convert to...
+ (minimal_language_data): ...this.
+ (class minimal_language): New class.
+ (minimal_language_defn): New static global.
+ * gdb/d-lang.c (d_language_defn): Convert to...
+ (d_language_data): ...this.
+ (class d_language): New class.
+ (d_language_defn): New static global.
+ * gdb/f-lang.c (f_language_defn): Convert to...
+ (f_language_data): ...this.
+ (class f_language): New class.
+ (f_language_defn): New static global.
+ * gdb/go-lang.c (go_language_defn): Convert to...
+ (go_language_data): ...this.
+ (class go_language): New class.
+ (go_language_defn): New static global.
+ * gdb/language.c (unknown_language_defn): Remove declaration.
+ (current_language): Initialize to nullptr, real initialization is
+ moved to _initialize_language.
+ (languages): Delete global.
+ (language_defn::languages): Define.
+ (set_language_command): Use language_defn::languages.
+ (set_language): Likewise.
+ (range_error): Likewise.
+ (language_enum): Likewise.
+ (language_def): Likewise.
+ (add_set_language_command): Use language_def::languages for the
+ language list, and language_def to lookup language pointers.
+ (skip_language_trampoline): Use language_defn::languages.
+ (unknown_language_defn): Convert to...
+ (unknown_language_data): ...this.
+ (class unknown_language): New class.
+ (unknown_language_defn): New static global.
+ (auto_language_defn): Convert to...
+ (auto_language_data): ...this.
+ (class auto_language): New class.
+ (auto_language_defn): New static global.
+ (language_gdbarch_post_init): Use language_defn::languages.
+ (_initialize_language): Initialize current_language.
+ * gdb/language.h (struct language_defn): Rename to...
+ (struct language_data): ...this.
+ (struct language_defn): New.
+ (auto_language_defn): Delete.
+ (unknown_language_defn): Delete.
+ (minimal_language_defn): Delete.
+ (ada_language_defn): Delete.
+ (asm_language_defn): Delete.
+ (c_language_defn): Delete.
+ (cplus_language_defn): Delete.
+ (d_language_defn): Delete.
+ (f_language_defn): Delete.
+ (go_language_defn): Delete.
+ (m2_language_defn): Delete.
+ (objc_language_defn): Delete.
+ (opencl_language_defn): Delete.
+ (pascal_language_defn): Delete.
+ (rust_language_defn): Delete.
+ * gdb/m2-lang.c (m2_language_defn): Convert to...
+ (m2_language_data): ...this.
+ (class m2_language): New class.
+ (m2_language_defn): New static global.
+ * gdb/objc-lang.c (objc_language_defn): Convert to...
+ (objc_language_data): ...this.
+ (class objc_language): New class.
+ (objc_language_defn): New static global.
+ * gdb/opencl-lang.c (opencl_language_defn): Convert to...
+ (opencl_language_data): ...this.
+ (class opencl_language): New class.
+ (opencl_language_defn): New static global.
+ * gdb/p-lang.c (pascal_language_defn): Convert to...
+ (pascal_language_data): ...this.
+ (class pascal_language): New class.
+ (pascal_language_defn): New static global.
+ * gdb/rust-exp.y (rust_lex_tests): Use language_def to find
+ language pointer, update comment format.
+ * gdb/rust-lang.c (rust_language_defn): Convert to...
+ (rust_language_data): ...this.
+ (class rust_language): New class.
+ (rust_language_defn): New static global.
+
2020-06-01 Andrew Burgess <andrew.burgess@embecosm.com>
* dwarf2/read.c (class lnp_state_machine) <m_last_address>: New
".adb", ".ads", ".a", ".ada", ".dg", NULL
};
-extern const struct language_defn ada_language_defn = {
+/* Constant data that describes the Ada language. */
+
+extern const struct language_data ada_language_data =
+{
"ada", /* Language name */
"Ada",
language_ada,
"(...)" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the Ada language. */
+
+class ada_language : public language_defn
+{
+public:
+ ada_language ()
+ : language_defn (language_ada, ada_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the Ada language class. */
+
+static ada_language ada_language_defn;
+
/* Command-list for the "set/show ada" prefix command. */
static struct cmd_list_element *set_ada_list;
static struct cmd_list_element *show_ada_list;
".c", NULL
};
-extern const struct language_defn c_language_defn =
+/* Constant data that describes the C language. */
+
+extern const struct language_data c_language_data =
{
"c", /* Language name */
"C",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the C language. */
+
+class c_language : public language_defn
+{
+public:
+ c_language ()
+ : language_defn (language_c, c_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the C language class. */
+
+static c_language c_language_defn;
+
enum cplus_primitive_types {
cplus_primitive_type_int,
cplus_primitive_type_long,
".C", ".cc", ".cp", ".cpp", ".cxx", ".c++", NULL
};
-extern const struct language_defn cplus_language_defn =
+/* Constant data that describes the C++ language. */
+
+extern const struct language_data cplus_language_data =
{
"c++", /* Language name */
"C++",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* A class for the C++ language. */
+
+class cplus_language : public language_defn
+{
+public:
+ cplus_language ()
+ : language_defn (language_cplus, cplus_language_data)
+ { /* Nothing. */ }
+};
+
+/* The single instance of the C++ language class. */
+
+static cplus_language cplus_language_defn;
+
static const char *asm_extensions[] =
{
".s", ".sx", ".S", NULL
};
-extern const struct language_defn asm_language_defn =
+/* Constant data that describes the ASM language. */
+
+extern const struct language_data asm_language_data =
{
"asm", /* Language name */
"assembly",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* A class for the ASM language. */
+
+class asm_language : public language_defn
+{
+public:
+ asm_language ()
+ : language_defn (language_asm, asm_language_data)
+ { /* Nothing. */ }
+};
+
+/* The single instance of the ASM language class. */
+static asm_language asm_language_defn;
+
/* The following language_defn does not represent a real language.
It just provides a minimal support a-la-C that should allow users
to do some simple operations when debugging applications that use
a language currently not supported by GDB. */
-extern const struct language_defn minimal_language_defn =
+extern const struct language_data minimal_language_data =
{
"minimal", /* Language name */
"Minimal",
c_is_string_type_p,
"{...}" /* la_struct_too_deep_ellipsis */
};
+
+/* A class for the minimal language. */
+
+class minimal_language : public language_defn
+{
+public:
+ minimal_language ()
+ : language_defn (language_minimal, minimal_language_data)
+ { /* Nothing. */ }
+};
+
+/* The single instance of the minimal language class. */
+static minimal_language minimal_language_defn;
".d", NULL
};
-extern const struct language_defn d_language_defn =
+/* Constant data that describes the D language. */
+
+extern const struct language_data d_language_data =
{
"d",
"D",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the D language. */
+
+class d_language : public language_defn
+{
+public:
+ d_language ()
+ : language_defn (language_d, d_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the D language class. */
+
+static d_language d_language_defn;
+
/* Build all D language types for the specified architecture. */
static void *
evaluate_subexp_f
};
-extern const struct language_defn f_language_defn =
+/* Constant data that describes the Fortran language. */
+
+extern const struct language_data f_language_data =
{
"fortran",
"Fortran",
"(...)" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the Fortran language. */
+
+class f_language : public language_defn
+{
+public:
+ f_language ()
+ : language_defn (language_fortran, f_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the Fortran language class. */
+
+static f_language f_language_defn;
+
static void *
build_fortran_types (struct gdbarch *gdbarch)
{
lai->bool_type_default = builtin->builtin_bool;
}
-extern const struct language_defn go_language_defn =
+/* Constant data that describes the Go language. */
+
+extern const struct language_data go_language_data =
{
"go",
"Go",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the Go language. */
+
+class go_language : public language_defn
+{
+public:
+ go_language ()
+ : language_defn (language_go, go_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the Go language class. */
+
+static go_language go_language_defn;
+
static void *
build_go_types (struct gdbarch *gdbarch)
{
static CORE_ADDR unk_lang_trampoline (struct frame_info *, CORE_ADDR pc);
-/* Forward declaration */
-extern const struct language_defn unknown_language_defn;
-
/* The current (default at startup) state of type and range checking.
(If the modes are set to "auto", though, these are changed based
on the default language at startup, and then again based on the
/* The current language and language_mode (see language.h). */
-const struct language_defn *current_language = &unknown_language_defn;
+const struct language_defn *current_language = nullptr;
enum language_mode language_mode = language_mode_auto;
/* The language that the user expects to be typing in (the language
const struct language_defn *expected_language;
-/* The list of supported languages. Keep this in the same order as
- the 'enum language' values. */
-
-static const struct language_defn *languages[] = {
- &unknown_language_defn,
- &auto_language_defn,
- &c_language_defn,
- &objc_language_defn,
- &cplus_language_defn,
- &d_language_defn,
- &go_language_defn,
- &f_language_defn,
- &m2_language_defn,
- &asm_language_defn,
- &pascal_language_defn,
- &opencl_language_defn,
- &rust_language_defn,
- &minimal_language_defn,
- &ada_language_defn,
-};
+/* Define the array containing all languages. */
+
+const struct language_defn *language_defn::languages[nr_languages];
/* The current values of the "set language/range/case-sensitive" enum
commands. */
language = "auto";
/* Search the list of languages for a match. */
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
{
if (strcmp (lang->la_name, language) == 0)
{
enum language prev_language;
prev_language = current_language->la_language;
- current_language = languages[lang];
+ current_language = language_def (lang);
set_range_case ();
return prev_language;
}
enum language
language_enum (const char *str)
{
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
if (strcmp (lang->la_name, str) == 0)
return lang->la_language;
const struct language_defn *
language_def (enum language lang)
{
- return languages[lang];
+ const struct language_defn *l = language_defn::languages[lang];
+ gdb_assert (l != nullptr);
+ return l;
}
/* Return the language as a string. */
const char *
language_str (enum language lang)
{
- return languages[lang]->la_name;
+ return language_def (lang)->la_name;
}
\f
/* Build the language names array, to be used as enumeration in the
"set language" enum command. +1 for "local" and +1 for NULL
termination. */
- language_names = new const char *[ARRAY_SIZE (languages) + 2];
+ language_names = new const char *[ARRAY_SIZE (language_defn::languages) + 2];
/* Display "auto", "local" and "unknown" first, and then the rest,
alpha sorted. */
const char **language_names_p = language_names;
- *language_names_p++ = auto_language_defn.la_name;
+ *language_names_p++ = language_def (language_auto)->la_name;
*language_names_p++ = "local";
- *language_names_p++ = unknown_language_defn.la_name;
+ *language_names_p++ = language_def (language_unknown)->la_name;
const char **sort_begin = language_names_p;
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
{
/* Already handled above. */
if (lang->la_language == language_auto
std::sort (sort_begin, language_names_p, compare_cstrings);
/* Add the filename extensions. */
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
if (lang->la_filename_extensions != NULL)
{
for (size_t i = 0; lang->la_filename_extensions[i] != NULL; ++i)
"The currently understood settings are:\n\nlocal or "
"auto Automatic setting based on source file"));
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
{
/* Already dealt with these above. */
if (lang->la_language == language_unknown
CORE_ADDR
skip_language_trampoline (struct frame_info *frame, CORE_ADDR pc)
{
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
{
if (lang->skip_trampoline != NULL)
{
struct type *);
}
-const struct language_defn unknown_language_defn =
+/* Constant data that describes the unknown language. */
+
+extern const struct language_data unknown_language_data =
{
"unknown",
"Unknown",
"{...}" /* la_struct_too_deep_ellipsis */
};
-/* These two structs define fake entries for the "local" and "auto"
- options. */
-const struct language_defn auto_language_defn =
+/* Class representing the unknown language. */
+
+class unknown_language : public language_defn
+{
+public:
+ unknown_language ()
+ : language_defn (language_unknown, unknown_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the unknown language class. */
+
+static unknown_language unknown_language_defn;
+
+/* Constant data for the fake "auto" language. */
+
+extern const struct language_data auto_language_data =
{
"auto",
"Auto",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the fake "auto" language. */
+
+class auto_language : public language_defn
+{
+public:
+ auto_language ()
+ : language_defn (language_auto, auto_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the fake "auto" language. */
+
+static auto_language auto_language_defn;
+
\f
/* Per-architecture language information. */
struct language_gdbarch *l;
l = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct language_gdbarch);
- for (const auto &lang : languages)
+ for (const auto &lang : language_defn::languages)
if (lang != NULL && lang->la_language_arch_info != NULL)
{
lang->la_language_arch_info (gdbarch,
show_case_command,
&setlist, &showlist);
+ /* In order to call SET_LANGUAGE (below) we need to make sure that
+ CURRENT_LANGUAGE is not NULL. So first set the language to unknown,
+ then we can change the language to 'auto'. */
+ current_language = language_def (language_unknown);
+
add_set_language_command ();
language = "auto";
bool destructible = true;
};
-/* Structure tying together assorted information about a language. */
+/* Structure tying together assorted information about a language.
-struct language_defn
+ As we move over from the old structure based languages to a class
+ hierarchy of languages this structure will continue to contain a
+ mixture of both data and function pointers.
+
+ Once the class hierarchy of languages in place the first task is to
+ remove the function pointers from this structure and convert them into
+ member functions on the different language classes.
+
+ The current plan it to keep the constant data that describes a language
+ in this structure, and have each language pass in an instance of this
+ structure at construction time. */
+
+struct language_data
{
/* Name of the language. */
};
+/* Base class from which all other language classes derive. */
+
+struct language_defn : language_data
+{
+ language_defn (enum language lang, const language_data &init_data)
+ : language_data (init_data)
+ {
+ /* We should only ever create one instance of each language. */
+ gdb_assert (languages[lang] == nullptr);
+ languages[lang] = this;
+ }
+
+ /* List of all known languages. */
+ static const struct language_defn *languages[nr_languages];
+};
+
/* Pointer to the language_defn for our current language. This pointer
always points to *some* valid struct; it can be used without checking
it for validity.
symbol_name_matcher_ftype *get_symbol_name_matcher
(const language_defn *lang, const lookup_name_info &lookup_name);
-/* The languages supported by GDB. */
-
-extern const struct language_defn auto_language_defn;
-extern const struct language_defn unknown_language_defn;
-extern const struct language_defn minimal_language_defn;
-
-extern const struct language_defn ada_language_defn;
-extern const struct language_defn asm_language_defn;
-extern const struct language_defn c_language_defn;
-extern const struct language_defn cplus_language_defn;
-extern const struct language_defn d_language_defn;
-extern const struct language_defn f_language_defn;
-extern const struct language_defn go_language_defn;
-extern const struct language_defn m2_language_defn;
-extern const struct language_defn objc_language_defn;
-extern const struct language_defn opencl_language_defn;
-extern const struct language_defn pascal_language_defn;
-extern const struct language_defn rust_language_defn;
-
/* Save the current language and restore it upon destruction. */
class scoped_restore_current_language
evaluate_subexp_modula2
};
-extern const struct language_defn m2_language_defn =
+/* Constant data describing the M2 language. */
+
+extern const struct language_data m2_language_data =
{
"modula-2",
"Modula-2",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the M2 language. */
+
+class m2_language : public language_defn
+{
+public:
+ m2_language ()
+ : language_defn (language_m2, m2_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the M2 language. */
+
+static m2_language m2_language_defn;
+
static void *
build_m2_types (struct gdbarch *gdbarch)
{
".m", NULL
};
-extern const struct language_defn objc_language_defn = {
+/* Constant data representing the Objective-C language. */
+
+extern const struct language_data objc_language_data =
+{
"objective-c", /* Language name */
"Objective-C",
language_objc,
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the Objective-C language. */
+
+class objc_language : public language_defn
+{
+public:
+ objc_language ()
+ : language_defn (language_objc, objc_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the class representing the Objective-C language. */
+
+static objc_language objc_language_defn;
+
/*
* ObjC:
* Following functions help construct Objective-C message calls.
evaluate_subexp_opencl
};
-extern const struct language_defn opencl_language_defn =
+/* Constant data representing the OpenCL language. */
+extern const struct language_data opencl_language_data =
{
"opencl", /* Language name */
"OpenCL C",
"{...}" /* la_struct_too_deep_ellipsis */
};
+/* Class representing the OpenCL language. */
+
+class opencl_language : public language_defn
+{
+public:
+ opencl_language ()
+ : language_defn (language_opencl, opencl_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the OpenCL language class. */
+
+static opencl_language opencl_language_defn;
+
static void *
build_opencl_types (struct gdbarch *gdbarch)
{
".pas", ".p", ".pp", NULL
};
-extern const struct language_defn pascal_language_defn =
+/* Constant data representing the Pascal language. */
+
+extern const struct language_data pascal_language_data =
{
"pascal", /* Language name */
"Pascal",
pascal_is_string_type_p,
"{...}" /* la_struct_too_deep_ellipsis */
};
+
+/* Class representing the Pascal language. */
+
+class pascal_language : public language_defn
+{
+public:
+ pascal_language ()
+ : language_defn (language_pascal, pascal_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the Pascal language class. */
+
+static pascal_language pascal_language_defn;
{
int i;
- // Set up dummy "parser", so that rust_type works.
- struct parser_state ps (&rust_language_defn, target_gdbarch (),
+ /* Set up dummy "parser", so that rust_type works. */
+ struct parser_state ps (language_def (language_rust), target_gdbarch (),
nullptr, 0, 0, nullptr, 0, nullptr);
rust_parser parser (&ps);
".rs", NULL
};
-extern const struct language_defn rust_language_defn =
+/* Constant data representing the Rust language. */
+
+extern const struct language_data rust_language_data =
{
"rust",
"Rust",
rust_is_string_type_p,
"{...}" /* la_struct_too_deep_ellipsis */
};
+
+/* Class representing the Rust language. */
+
+class rust_language : public language_defn
+{
+public:
+ rust_language ()
+ : language_defn (language_rust, rust_language_data)
+ { /* Nothing. */ }
+};
+
+/* Single instance of the Rust language class. */
+
+static rust_language rust_language_defn;