public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb: Represent all languages as sub-classes of language_defn
@ 2020-06-02 13:12 Andrew Burgess
  0 siblings, 0 replies; only message in thread
From: Andrew Burgess @ 2020-06-02 13:12 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=0874fd075b2a519022259a3cc48e650dc1daeeab

commit 0874fd075b2a519022259a3cc48e650dc1daeeab
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date:   Fri May 1 12:16:58 2020 +0100

    gdb: Represent all languages as sub-classes of language_defn
    
    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.

Diff:
---
 gdb/ChangeLog     | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/ada-lang.c    | 19 ++++++++++-
 gdb/c-lang.c      | 68 +++++++++++++++++++++++++++++++++++---
 gdb/d-lang.c      | 18 +++++++++-
 gdb/f-lang.c      | 18 +++++++++-
 gdb/go-lang.c     | 18 +++++++++-
 gdb/language.c    | 99 ++++++++++++++++++++++++++++++++-----------------------
 gdb/language.h    | 51 ++++++++++++++++------------
 gdb/m2-lang.c     | 18 +++++++++-
 gdb/objc-lang.c   | 19 ++++++++++-
 gdb/opencl-lang.c | 17 +++++++++-
 gdb/p-lang.c      | 18 +++++++++-
 gdb/rust-exp.y    |  4 +--
 gdb/rust-lang.c   | 18 +++++++++-
 14 files changed, 406 insertions(+), 77 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b74167e31ef..3c8f9fcb49d 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -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
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index b4eeaaf0866..620db0a49e7 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -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;
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index e549c5cb657..4dac718cbac 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -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;
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 951e664ceda..c572ad7890e 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -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 *
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 3c3e6ab34ba..46d386e0477 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -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)
 {
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index c97db1b9db7..f0b560803cd 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -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)
 {
diff --git a/gdb/language.c b/gdb/language.c
index ff76ae7ece6..b3cbd6aadef 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -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";
diff --git a/gdb/language.h b/gdb/language.h
index e112a91ec57..351ad490a83 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -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
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 5912670a9f0..57750b5cc46 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -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)
 {
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index d724433d565..a1d035962c2 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -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.
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index ae95d77f255..1a7425f8763 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -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)
 {
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index aa483336d2c..2f9598fed94 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -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;
diff --git a/gdb/rust-exp.y b/gdb/rust-exp.y
index 47aa799754d..4e7878f67e1 100644
--- a/gdb/rust-exp.y
+++ b/gdb/rust-exp.y
@@ -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);
 
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 5958b058c10..152fe2f66c0 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -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;


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2020-06-02 13:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-02 13:12 [binutils-gdb] gdb: Represent all languages as sub-classes of language_defn Andrew Burgess

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).