gdb: Represent all languages as sub-classes of language_defn
authorAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 1 May 2020 11:16:58 +0000 (12:16 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 2 Jun 2020 12:53:10 +0000 (13:53 +0100)
This commit converts all languages to sub-classes of a language_defn
base class.

The motivation for this change is to make it easier to add new methods
onto languages without having to update all of the individual language
structures.  In the future it might be possible to move more things,
like expression parsing, into the language class(es) for better
encapsulation, however I have no plans to tackle this in the short
term.

This commit sets up a strategy for transitioning from the current
language system, where each language is an instance of the
language_defn structure, to the class hierarchy system.

The plan is to rename the existing language_defn into language_data,
and make this a base class for the new language_defn class, something
like this:

  struct language_data
  {
    ... old language_defn fields here ...
  };

  struct language_defn : public language_data
  {
    language_defn (const language_data d)
      : language_data (d)
    { .... }
  };

Then each existing language, for example ada_language_defn can be
converted into an instance of language_data, and passed into the
constructor of a new language class, something like this:

  language_data ada_language_data =
  {
    ... old ada_language_defn values here ...
  };

  struct ada_language : public language_defn
  {
    ada_language (ada_language_data)
    { .... }
  };

What this means is that immediately after the conversion nothing much
changes.  Every language is now its own class, but all the old
language fields still exist and can be accessed in the same way.

In later commits I will convert function pointers from the old
language_defn structure into real class methods on language_defn, with
overrides on sub-classes where needed.

At this point I imagine that those fields of the old language_defn
structure that contained only data will probably remain as data fields
within the new language_data base structure, it is only the methods
that I plan to change initially.

I tweaked how we manage the list of languages a bit, each language is
now registered as it is created, and this resulted in a small number
of changes in language.c.

Most of the changes in the *-lang.c files are identical.

There should be no user visible changes after this commit.

gdb/ChangeLog:

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

14 files changed:
gdb/ChangeLog
gdb/ada-lang.c
gdb/c-lang.c
gdb/d-lang.c
gdb/f-lang.c
gdb/go-lang.c
gdb/language.c
gdb/language.h
gdb/m2-lang.c
gdb/objc-lang.c
gdb/opencl-lang.c
gdb/p-lang.c
gdb/rust-exp.y
gdb/rust-lang.c

index b74167e31efee691b0c352411e2906ce5bb3f109..3c8f9fcb49d03a326536946b37fad3ecc964ef2a 100644 (file)
@@ -1,3 +1,101 @@
+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
index b4eeaaf08663cde00bb5c9d5fe3e258c0bd110ec..620db0a49e7fc90be54ac708d90b2658ce937c3e 100644 (file)
@@ -14061,7 +14061,10 @@ static const char *ada_extensions[] =
   ".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,
@@ -14110,6 +14113,20 @@ extern const struct language_defn ada_language_defn = {
   "(...)"                      /* 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;
index e549c5cb6571737af424f19a20077d2eb3a95a1b..4dac718cbac29d924a568817da022fabf76a5278 100644 (file)
@@ -885,7 +885,9 @@ static const char *c_extensions[] =
   ".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",
@@ -934,6 +936,20 @@ extern const struct language_defn c_language_defn =
   "{...}"                      /* 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,
@@ -1030,7 +1046,9 @@ static const char *cplus_extensions[] =
   ".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++",
@@ -1079,12 +1097,28 @@ extern const struct language_defn cplus_language_defn =
   "{...}"                      /* 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",
@@ -1133,12 +1167,25 @@ extern const struct language_defn asm_language_defn =
   "{...}"                      /* 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",
@@ -1186,3 +1233,16 @@ extern const struct language_defn minimal_language_defn =
   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;
index 951e664ceda107110246b8433212e9957f096a9c..c572ad7890e2c9611d14ca5440aa13a422a2f851 100644 (file)
@@ -205,7 +205,9 @@ static const char *d_extensions[] =
   ".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",
@@ -255,6 +257,20 @@ extern const struct language_defn d_language_defn =
   "{...}"                      /* 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 *
index 3c3e6ab34ba6d7ea1064879506e4addbde116211..46d386e0477c3cef7687c094dfb4cbdb1bf98562 100644 (file)
@@ -628,7 +628,9 @@ static const struct exp_descriptor exp_descriptor_f =
   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",
@@ -683,6 +685,20 @@ extern const struct language_defn f_language_defn =
   "(...)"                      /* 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)
 {
index c97db1b9db7fcb565e97bcb67825f5c218314820..f0b560803cd540813722ec7ad354bde46eca50c1 100644 (file)
@@ -576,7 +576,9 @@ go_language_arch_info (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",
@@ -626,6 +628,20 @@ extern const struct language_defn go_language_defn =
   "{...}"                      /* 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)
 {
index ff76ae7ece608676badf5b2ae715066cf269c40d..b3cbd6aadef333b4f7ac4344ad43bb6d455da4e8 100644 (file)
@@ -62,9 +62,6 @@ static void unk_lang_value_print (struct value *, struct ui_file *,
 
 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
@@ -77,7 +74,7 @@ enum case_sensitivity case_sensitivity = case_sensitive_on;
 
 /* 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
@@ -85,26 +82,9 @@ enum language_mode language_mode = language_mode_auto;
 
 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.  */
@@ -162,7 +142,7 @@ set_language_command (const char *ignore,
     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)
        {
@@ -377,7 +357,7 @@ set_language (enum language lang)
   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;
 }
@@ -474,7 +454,7 @@ range_error (const char *string,...)
 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;
 
@@ -489,7 +469,9 @@ language_enum (const char *str)
 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.  */
@@ -497,7 +479,7 @@ language_def (enum language lang)
 const char *
 language_str (enum language lang)
 {
-  return languages[lang]->la_name;
+  return language_def (lang)->la_name;
 }
 
 \f
@@ -512,16 +494,16 @@ add_set_language_command ()
   /* 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
@@ -533,7 +515,7 @@ add_set_language_command ()
   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)
@@ -548,7 +530,7 @@ add_set_language_command ()
                "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
@@ -583,7 +565,7 @@ add_set_language_command ()
 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)
        {
@@ -829,7 +811,9 @@ unknown_language_arch_info (struct gdbarch *gdbarch,
                                                       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",
@@ -878,9 +862,23 @@ const struct language_defn unknown_language_defn =
   "{...}"                      /* 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",
@@ -929,6 +927,20 @@ const struct language_defn auto_language_defn =
   "{...}"                      /* 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.  */
 
@@ -947,7 +959,7 @@ language_gdbarch_post_init (struct gdbarch *gdbarch)
   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,
@@ -1169,6 +1181,11 @@ For Fortran the default is off; for other languages the default is on."),
                        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";
index e112a91ec572c260a1b2fd819a3f0c2306ff9811..351ad490a83bd990bfbc1aae84fe3f8919ac7485 100644 (file)
@@ -169,9 +169,21 @@ struct language_pass_by_ref_info
   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.  */
 
@@ -471,6 +483,22 @@ struct language_defn
 
   };
 
+/* 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.
@@ -681,25 +709,6 @@ extern bool default_symbol_name_matcher
 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
index 5912670a9f0033c683404854fd3650e3c4f4b71f..57750b5cc4631d7d27f2145d83b9e6a3a04dc4cd 100644 (file)
@@ -375,7 +375,9 @@ const struct exp_descriptor exp_descriptor_modula2 =
   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",
@@ -424,6 +426,20 @@ extern const struct language_defn m2_language_defn =
   "{...}"                      /* 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)
 {
index d724433d565acc25de4d7cc3ab4733b2ad51f855..a1d035962c2ecead7236552a1948a5e4fc5df8ef 100644 (file)
@@ -364,7 +364,10 @@ static const char *objc_extensions[] =
   ".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,
@@ -412,6 +415,20 @@ extern const struct language_defn objc_language_defn = {
   "{...}"                      /* 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.
index ae95d77f2551eef1e5e635715fd97cbd6fe58f5b..1a7425f87632af8589ef7526cbaefc670babe7d1 100644 (file)
@@ -1042,7 +1042,8 @@ const struct exp_descriptor exp_descriptor_opencl =
   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",
@@ -1091,6 +1092,20 @@ extern const struct language_defn opencl_language_defn =
   "{...}"                      /* 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)
 {
index aa483336d2c2a57bac33a8a0b15f0b6ac0bc53b7..2f9598fed94244dec9723794deb1b6c70acd4b78 100644 (file)
@@ -429,7 +429,9 @@ static const char *p_extensions[] =
   ".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",
@@ -476,3 +478,17 @@ extern const struct language_defn pascal_language_defn =
   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;
index 47aa799754d7661b0c5e5b52e27fbc01ea9d8fa7..4e7878f67e1f93fe5cc4b02fe609d3eff008ee30 100644 (file)
@@ -2725,8 +2725,8 @@ rust_lex_tests (void)
 {
   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);
 
index 5958b058c10cceb05392b3a1f4ec4054f9183a57..152fe2f66c026441ff97490126d43bad13c0050b 100644 (file)
@@ -2101,7 +2101,9 @@ static const char *rust_extensions[] =
   ".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",
@@ -2149,3 +2151,17 @@ extern const struct language_defn rust_language_defn =
   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;