gdb: Add new commands to list module variables and functions
authorAndrew Burgess <andrew.burgess@embecosm.com>
Wed, 10 Jul 2019 14:54:03 +0000 (15:54 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 31 Oct 2019 23:02:59 +0000 (23:02 +0000)
This patch adds two new commands "info module functions" and "info
module variables".  These commands list all of the functions and
variables grouped by module and then by file.

For example:

  (gdb) info module functions
  All functions in all modules:

  Module "mod1":

  File /some/path/gdb/testsuite/gdb.fortran/info-types.f90:
  35: void mod1::__copy_mod1_M1t1(Type m1t1, Type m1t1);
  25: void mod1::sub_m1_a(integer(kind=4));
  31: integer(kind=4) mod1::sub_m1_b(void);

  Module "mod2":

  File /some/path/gdb/testsuite/gdb.fortran/info-types.f90:
  41: void mod2::sub_m2_a(integer(kind=4), logical(kind=4));
  49: logical(kind=4) mod2::sub_m2_b(real(kind=4));

The new commands take set of flags that allow the output to be
filtered, the user can filter by variable/function name, type, or
containing module.

As GDB doesn't currently track the relationship between a module and
the variables or functions within it in the symbol table, so I filter
based on the module prefix in order to find the functions or variables
in each module.  What this makes clear is that a user could get this
same information using "info variables" and simply provide the prefix
themselves, for example:

  (gdb) info module functions -m mod1 _a
  All functions matching regular expression "_a",
   in all modules matching regular expression "mod1":

  Module "mod1":

  File /some/path/gdb/testsuite/gdb.fortran/info-types.f90:
  25: void mod1::sub_m1_a(integer(kind=4));

Is similar to:

  (gdb) info functions mod1::.*_a.*
  All functions matching regular expression "mod1::.*_a":

  File /some/path/gdb/testsuite/gdb.fortran/info-types.f90:
  25: void mod1::sub_m1_a(integer(kind=4));

The benefits I see for a separate command are that the user doesn't
have to think (or know) about the module prefix format, nor worry
about building a proper regexp.  The user can also easily scan across
modules without having to build complex regexps.

The new function search_module_symbols is extern in this patch despite
only being used within symtab.c, this is because a later patch in this
series will also be using this function from outside symtab.c.

This patch is a new implementation of an idea originally worked on by
Mark O'Connor, Chris January, David Lecomber, and Xavier Oro from ARM.

gdb/ChangeLog:

* symtab.c (info_module_cmdlist): New variable.
(info_module_command): New function.
(search_module_symbols): New function.
(info_module_subcommand): New function.
(struct info_modules_var_func_options): New struct.
(info_modules_var_func_options_defs): New variable.
(make_info_modules_var_func_options_def_group): New function.
(info_module_functions_command): New function.
(info_module_variables_command): New function.
(info_module_var_func_command_completer): New function.
(_initialize_symtab): Register new 'info module functions' and
'info module variables' commands.
* symtab.h (typedef symbol_search_in_module): New typedef.
(search_module_symbols): Declare new function.
* NEWS: Mention new commands.

gdb/doc/ChangeLog:

* gdb.texinfo (Symbols): Document new 'info module variables' and
'info module functions' commands.

gdb/testsuite/ChangeLog:

* gdb.fortran/info-modules.exp: Update expected results, and add
additional tests for 'info module functinos', and 'info module
variables'.
* gdb.fortran/info-types.exp: Update expected results.
* gdb.fortran/info-types.f90: Extend testcase with additional
module variables and functions.

Change-Id: I8c2960640e2e101b77eff54027d687e21ec22e2b

gdb/ChangeLog
gdb/NEWS
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/symtab.c
gdb/symtab.h
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.fortran/info-modules.exp
gdb/testsuite/gdb.fortran/info-types-2.f90
gdb/testsuite/gdb.fortran/info-types.exp
gdb/testsuite/gdb.fortran/info-types.f90

index 6dca96555ad3cdcb3a9c29c264420469fe440de8..2bd67260dc72cfc3ed42e60dd294fd9264f9f7b9 100644 (file)
@@ -1,3 +1,21 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * symtab.c (info_module_cmdlist): New variable.
+       (info_module_command): New function.
+       (search_module_symbols): New function.
+       (info_module_subcommand): New function.
+       (struct info_modules_var_func_options): New struct.
+       (info_modules_var_func_options_defs): New variable.
+       (make_info_modules_var_func_options_def_group): New function.
+       (info_module_functions_command): New function.
+       (info_module_variables_command): New function.
+       (info_module_var_func_command_completer): New function.
+       (_initialize_symtab): Register new 'info module functions' and
+       'info module variables' commands.
+       * symtab.h (typedef symbol_search_in_module): New typedef.
+       (search_module_symbols): Declare new function.
+       * NEWS: Mention new commands.
+
 2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * dwarf2read.c (dw2_symtab_iter_next): Handle MODULE_DOMAIN.
index d46f7094d406729654a37e300ee82232d41d66b4..59895bd68b38f94bd901a9cb846471d6498478b2 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -163,6 +163,20 @@ info modules [-q] [REGEXP]
   Return a list of Fortran modules matching REGEXP, or all modules if
   no REGEXP is given.
 
+info module functions [-q] [-m MODULE_REGEXP] [-t TYPE_REGEXP] [REGEXP]
+  Return a list of functions within all modules, grouped by module.
+  The list of functions can be restricted with the optional regular
+  expressions.  MODULE_REGEXP matches against the module name,
+  TYPE_REGEXP matches against the function type signature, and REGEXP
+  matches against the function name.
+
+info module variables [-q] [-m MODULE_REGEXP] [-t TYPE_REGEXP] [REGEXP]
+  Return a list of variables within all modules, grouped by module.
+  The list of variables can be restricted with the optional regular
+  expressions.  MODULE_REGEXP matches against the module name,
+  TYPE_REGEXP matches against the variable type, and REGEXP matches
+  against the variable name.
+
 * Changed commands
 
 help
index 52497a17725f6c8beff74449a68d0e3d104ac208..ce89ee444ea157d800a525487d559b4d0c11cb2d 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.texinfo (Symbols): Document new 'info module variables' and
+       'info module functions' commands.
+
 2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.texinfo (Symbols): Document new 'info modules' command.
index ee06df2bb2c7b45966086888756b92af93d42c1f..70e4be1524402a02a82cadce92fdae2076fb9bce 100644 (file)
@@ -18896,6 +18896,25 @@ The optional flag @samp{-q}, which stands for @samp{quiet}, disables
 printing header information and messages explaining why no modules
 have been printed.
 
+@kindex info module
+@cindex Fortran modules, information about
+@cindex functions and variables by Fortran module
+@cindex module functions and variables
+@item info module functions @r{[}-q@r{]} @r{[}-m @var{module-regexp}@r{]} @r{[}-t @var{type-regexp}@r{]} @r{[}@var{regexp}@r{]}
+@itemx info module variables @r{[}-q@r{]} @r{[}-m @var{module-regexp}@r{]} @r{[}-t @var{type-regexp}@r{]} @r{[}@var{regexp}@r{]}
+List all functions or variables within all Fortran modules.  The set
+of functions or variables listed can be limited by providing some or
+all of the optional regular expressions.  If @var{module-regexp} is
+provided, then only Fortran modules matching @var{module-regexp} will
+be searched.  Only functions or variables whose type matches the
+optional regular expression @var{type-regexp} will be listed.  And
+only functions or variables whose name matches the optional regular
+expression @var{regexp} will be listed.
+
+The optional flag @samp{-q}, which stands for @samp{quiet}, disables
+printing header information and messages explaining why no functions
+or variables have been printed.
+
 @kindex info classes
 @cindex Objective-C, classes and selectors
 @item info classes
index 4c14edae177668c41a159a97dbd1629136774214..72a54ec1ca0a02c2b96c156bfea5ba4f44a1796b 100644 (file)
@@ -6340,6 +6340,315 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym)
 
 \f
 
+/* Hold the sub-commands of 'info module'.  */
+
+static struct cmd_list_element *info_module_cmdlist = NULL;
+
+/* Implement the 'info module' command, just displays some help text for
+   the available sub-commands.  */
+
+static void
+info_module_command (const char *args, int from_tty)
+{
+  help_list (info_module_cmdlist, "info module ", class_info, gdb_stdout);
+}
+
+/* See symtab.h.  */
+
+std::vector<module_symbol_search>
+search_module_symbols (const char *module_regexp, const char *regexp,
+                      const char *type_regexp, search_domain kind)
+{
+  std::vector<module_symbol_search> results;
+
+  /* Search for all modules matching MODULE_REGEXP.  */
+  std::vector<symbol_search> modules = search_symbols (module_regexp,
+                                                      MODULES_DOMAIN,
+                                                      NULL, 0, NULL,
+                                                      true);
+
+  /* Now search for all symbols of the required KIND matching the required
+     regular expressions.  We figure out which ones are in which modules
+     below.  */
+  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
+                                                      type_regexp, 0,
+                                                      NULL, true);
+
+  /* Now iterate over all MODULES, checking to see which items from
+     SYMBOLS are in each module.  */
+  for (const symbol_search &p : modules)
+    {
+      QUIT;
+
+      /* This is a module.  */
+      gdb_assert (p.symbol != nullptr);
+
+      std::string prefix = SYMBOL_PRINT_NAME (p.symbol);
+      prefix += "::";
+
+      for (const symbol_search &q : symbols)
+       {
+         if (q.symbol == nullptr)
+           continue;
+
+         if (strncmp (SYMBOL_PRINT_NAME (q.symbol), prefix.c_str (),
+                      prefix.size ()) != 0)
+           continue;
+
+         results.push_back ({p, q});
+       }
+    }
+
+  return results;
+}
+
+/* Implement the core of both 'info module functions' and 'info module
+   variables'.  */
+
+static void
+info_module_subcommand (bool quiet, const char *module_regexp,
+                       const char *regexp, const char *type_regexp,
+                       search_domain kind)
+{
+  /* Print a header line.  Don't build the header line bit by bit as this
+     prevents internationalisation.  */
+  if (!quiet)
+    {
+      if (module_regexp == nullptr)
+       {
+         if (type_regexp == nullptr)
+           {
+             if (regexp == nullptr)
+               printf_filtered ((kind == VARIABLES_DOMAIN
+                                 ? _("All variables in all modules:")
+                                 : _("All functions in all modules:")));
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression"
+                       " \"%s\" in all modules:")
+                   : _("All functions matching regular expression"
+                       " \"%s\" in all modules:")),
+                  regexp);
+           }
+         else
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables with type matching regular "
+                       "expression \"%s\" in all modules:")
+                   : _("All functions with type matching regular "
+                       "expression \"%s\" in all modules:")),
+                  type_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\twith type matching regular "
+                       "expression \"%s\" in all modules:")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\twith type matching regular "
+                       "expression \"%s\" in all modules:")),
+                  regexp, type_regexp);
+           }
+       }
+      else
+       {
+         if (type_regexp == nullptr)
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables in all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions in all modules matching regular "
+                       "expression \"%s\":")),
+                  module_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")),
+                  regexp, module_regexp);
+           }
+         else
+           {
+             if (regexp == nullptr)
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables with type matching regular "
+                       "expression \"%s\"\n\tin all modules matching "
+                       "regular expression \"%s\":")
+                   : _("All functions with type matching regular "
+                       "expression \"%s\"\n\tin all modules matching "
+                       "regular expression \"%s\":")),
+                  type_regexp, module_regexp);
+             else
+               printf_filtered
+                 ((kind == VARIABLES_DOMAIN
+                   ? _("All variables matching regular expression "
+                       "\"%s\",\n\twith type matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")
+                   : _("All functions matching regular expression "
+                       "\"%s\",\n\twith type matching regular expression "
+                       "\"%s\",\n\tin all modules matching regular "
+                       "expression \"%s\":")),
+                  regexp, type_regexp, module_regexp);
+           }
+       }
+      printf_filtered ("\n");
+    }
+
+  /* Find all symbols of type KIND matching the given regular expressions
+     along with the symbols for the modules in which those symbols
+     reside.  */
+  std::vector<module_symbol_search> module_symbols
+    = search_module_symbols (module_regexp, regexp, type_regexp, kind);
+
+  std::sort (module_symbols.begin (), module_symbols.end (),
+            [] (const module_symbol_search &a, const module_symbol_search &b)
+            {
+              if (a.first < b.first)
+                return true;
+              else if (a.first == b.first)
+                return a.second < b.second;
+              else
+                return false;
+            });
+
+  const char *last_filename = "";
+  const symbol *last_module_symbol = nullptr;
+  for (const module_symbol_search &ms : module_symbols)
+    {
+      const symbol_search &p = ms.first;
+      const symbol_search &q = ms.second;
+
+      gdb_assert (q.symbol != nullptr);
+
+      if (last_module_symbol != p.symbol)
+       {
+         printf_filtered ("\n");
+         printf_filtered (_("Module \"%s\":\n"),
+                          SYMBOL_PRINT_NAME (p.symbol));
+         last_module_symbol = p.symbol;
+         last_filename = "";
+       }
+
+      print_symbol_info (FUNCTIONS_DOMAIN, q.symbol, q.block,
+                        last_filename);
+      last_filename
+       = symtab_to_filename_for_display (symbol_symtab (q.symbol));
+    }
+}
+
+/* Hold the option values for the 'info module .....' sub-commands.  */
+
+struct info_modules_var_func_options
+{
+  bool quiet = false;
+  char *type_regexp = nullptr;
+  char *module_regexp = nullptr;
+
+  ~info_modules_var_func_options ()
+  {
+    xfree (type_regexp);
+    xfree (module_regexp);
+  }
+};
+
+/* The options used by 'info module variables' and 'info module functions'
+   commands.  */
+
+static const gdb::option::option_def info_modules_var_func_options_defs [] = {
+  gdb::option::boolean_option_def<info_modules_var_func_options> {
+    "q",
+    [] (info_modules_var_func_options *opt) { return &opt->quiet; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  },
+
+  gdb::option::string_option_def<info_modules_var_func_options> {
+    "t",
+    [] (info_modules_var_func_options *opt) { return &opt->type_regexp; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  },
+
+  gdb::option::string_option_def<info_modules_var_func_options> {
+    "m",
+    [] (info_modules_var_func_options *opt) { return &opt->module_regexp; },
+    nullptr, /* show_cmd_cb */
+    nullptr /* set_doc */
+  }
+};
+
+/* Return the option group used by the 'info module ...' sub-commands.  */
+
+static inline gdb::option::option_def_group
+make_info_modules_var_func_options_def_group
+       (info_modules_var_func_options *opts)
+{
+  return {{info_modules_var_func_options_defs}, opts};
+}
+
+/* Implements the 'info module functions' command.  */
+
+static void
+info_module_functions_command (const char *args, int from_tty)
+{
+  info_modules_var_func_options opts;
+  auto grp = make_info_modules_var_func_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+
+  info_module_subcommand (opts.quiet, opts.module_regexp, args,
+                         opts.type_regexp, FUNCTIONS_DOMAIN);
+}
+
+/* Implements the 'info module variables' command.  */
+
+static void
+info_module_variables_command (const char *args, int from_tty)
+{
+  info_modules_var_func_options opts;
+  auto grp = make_info_modules_var_func_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+
+  info_module_subcommand (opts.quiet, opts.module_regexp, args,
+                         opts.type_regexp, VARIABLES_DOMAIN);
+}
+
+/* Command completer for 'info module ...' sub-commands.  */
+
+static void
+info_module_var_func_command_completer (struct cmd_list_element *ignore,
+                                       completion_tracker &tracker,
+                                       const char *text,
+                                       const char * /* word */)
+{
+
+  const auto group = make_info_modules_var_func_options_def_group (nullptr);
+  if (gdb::option::complete_options
+      (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+    return;
+
+  const char *word = advance_to_expression_complete_word_point (tracker, text);
+  symbol_completer (ignore, tracker, text, word);
+}
+
+\f
+
 void
 _initialize_symtab (void)
 {
@@ -6402,6 +6711,45 @@ Options:\n\
                _("All module names, or those matching REGEXP."));
   set_cmd_completer_handle_brkchars (c, info_types_command_completer);
 
+  add_prefix_cmd ("module", class_info, info_module_command, _("\
+Print information about modules."),
+                 &info_module_cmdlist, "info module ",
+                 0, &infolist);
+
+  c = add_cmd ("functions", class_info, info_module_functions_command, _("\
+Display functions arranged by modules.\n\
+Usage: info module functions [-q] [-m MODREGEXP] [-t TYPEREGEXP] [REGEXP]\n\
+Print a summary of all functions within each Fortran module, grouped by\n\
+module and file.  For each function the line on which the function is\n\
+defined is given along with the type signature and name of the function.\n\
+\n\
+If REGEXP is provided then only functions whose name matches REGEXP are\n\
+listed.  If MODREGEXP is provided then only functions in modules matching\n\
+MODREGEXP are listed.  If TYPEREGEXP is given then only functions whose\n\
+type signature matches TYPEREGEXP are listed.\n\
+\n\
+The -q flag suppresses printing some header information."),
+              &info_module_cmdlist);
+  set_cmd_completer_handle_brkchars
+    (c, info_module_var_func_command_completer);
+
+  c = add_cmd ("variables", class_info, info_module_variables_command, _("\
+Display variables arranged by modules.\n\
+Usage: info module variables [-q] [-m MODREGEXP] [-t TYPEREGEXP] [REGEXP]\n\
+Print a summary of all variables within each Fortran module, grouped by\n\
+module and file.  For each variable the line on which the variable is\n\
+defined is given along with the type and name of the variable.\n\
+\n\
+If REGEXP is provided then only variables whose name matches REGEXP are\n\
+listed.  If MODREGEXP is provided then only variables in modules matching\n\
+MODREGEXP are listed.  If TYPEREGEXP is given then only variables whose\n\
+type matches TYPEREGEXP are listed.\n\
+\n\
+The -q flag suppresses printing some header information."),
+              &info_module_cmdlist);
+  set_cmd_completer_handle_brkchars
+    (c, info_module_var_func_command_completer);
+
   add_com ("rbreak", class_breakpoint, rbreak_command,
           _("Set a breakpoint for all functions matching REGEXP."));
 
index 72d1c7ff84854b3ae3486a3626bc1259b810dd09..eac44aee15657ca7e78ed5e2ff7f242abbee86d4 100644 (file)
@@ -2072,6 +2072,22 @@ extern std::vector<symbol_search> search_symbols (const char *,
                                                  int,
                                                  const char **,
                                                  bool);
+
+/* When searching for Fortran symbols within modules (functions/variables)
+   we return a vector of this type.  The first item in the pair is the
+   module symbol, and the second item is the symbol for the function or
+   variable we found.  */
+typedef std::pair<symbol_search, symbol_search> module_symbol_search;
+
+/* Searches the symbols to find function and variables symbols (depending
+   on KIND) within Fortran modules.  The MODULE_REGEXP matches against the
+   name of the module, REGEXP matches against the name of the symbol within
+   the module, and TYPE_REGEXP matches against the type of the symbol
+   within the module.  */
+extern std::vector<module_symbol_search> search_module_symbols
+       (const char *module_regexp, const char *regexp,
+        const char *type_regexp, search_domain kind);
+
 extern bool treg_matches_sym_type_name (const compiled_regex &treg,
                                        const struct symbol *sym);
 
index 6514c0764dc85f534b48c9f73fb9623d757e6157..4d1eecdb5c0723470b63f9c8a2c808d60402b3da 100644 (file)
@@ -1,3 +1,12 @@
+2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.fortran/info-modules.exp: Update expected results, and add
+       additional tests for 'info module functinos', and 'info module
+       variables'.
+       * gdb.fortran/info-types.exp: Update expected results.
+       * gdb.fortran/info-types.f90: Extend testcase with additional
+       module variables and functions.
+
 2019-10-31  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.fortran/info-modules.exp: New file.
index f961d28b000e4e3b8a0af64dfd49170ac3678483..43570066d2f7db3b6673f964da00d7944b23c75b 100644 (file)
@@ -13,7 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# This file tests 'info modules'.
+# This file tests 'info modules', 'info module functions', and 'info
+# module variables'.
 
 load_lib "fortran.exp"
 
@@ -31,6 +32,12 @@ if { ![runto MAIN__] } {
     continue
 }
 
+set logical4 [fortran_logical4]
+set integer4 [fortran_int4]
+set real4 [fortran_real4]
+
+# Test 'info modules' command.
+
 gdb_test "info modules" \
     [multi_line \
         "All defined modules:" \
@@ -64,3 +71,117 @@ gdb_test "info modules mod" \
         "" \
         "File .*${srcfile}:" \
         "16:\[\t \]+mod1" ]
+
+# Test 'info module functions'.
+
+gdb_test "info module functions" \
+    [multi_line \
+        "All functions in all modules:" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "22:\[\t \]+void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);" \
+        "30:\[\t \]+${logical4} mod2::sub_m2_b\\(${real4}\\);" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*${srcfile}:" \
+        "35:\[\t \]+void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);" \
+        "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
+        "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
+
+gdb_test "info module functions -m mod1" \
+    [multi_line \
+        "All functions in all modules matching regular expression \"mod1\":" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*:" \
+        "35:\[\t \]+void mod1::__copy_mod1_M1t1\\(Type m1t1, Type m1t1\\);" \
+        "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
+        "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
+
+gdb_test "info module functions -t integer" \
+    [multi_line \
+        "All functions with type matching regular expression \"integer\" in all modules:" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "22:\[\t \]+void mod2::sub_m2_a\\(${integer4}, ${logical4}\\);" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*${srcfile}:" \
+        "25:\[\t \]+void mod1::sub_m1_a\\(${integer4}\\);" \
+        "31:\[\t \]+${integer4} mod1::sub_m1_b\\(void\\);" ]
+
+# Test 'info module variables'.
+
+gdb_test "info module variables" \
+    [multi_line \
+        "All variables in all modules:" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
+        "20:\[\t \]+${real4} mod2::mod2_var_2;" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*${srcfile}:" \
+        "35:\[\t \]+Type m1t1 mod1::__def_init_mod1_M1t1;" \
+        "35:\[\t \]+Type __vtype_mod1_M1t1 mod1::__vtab_mod1_M1t1;" \
+        "21:\[\t \]+${real4} mod1::mod1_var_1;" \
+        "22:\[\t \]+${integer4} mod1::mod1_var_2;" ]
+
+gdb_test "info module variables -t real" \
+    [multi_line \
+        "All variables with type matching regular expression \"real\" in all modules:" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*:" \
+        "20:\[\t \]+${real4} mod2::mod2_var_2;" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*:" \
+        "21:\[\t \]+${real4} mod1::mod1_var_1;" ]
+
+gdb_test "info module variables -m mod2" \
+    [multi_line \
+        "All variables in all modules matching regular expression \"mod2\":" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
+        "20:\[\t \]+${real4} mod2::mod2_var_2;" ]
+
+gdb_test "info module variables -m mod2 -t real" \
+    [multi_line \
+        "All variables with type matching regular expression \"real\"" \
+        "      in all modules matching regular expression \"mod2\":" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*${srcfile2}:" \
+        "20:\[\t \]+${real4} mod2::mod2_var_2;" ]
+
+gdb_test "info module variables _1" \
+    [multi_line \
+        "All variables matching regular expression \"_1\" in all modules:" \
+        "" \
+        "Module \"mod2\":" \
+        "" \
+        "File .*:" \
+        "19:\[\t \]+${integer4} mod2::mod2_var_1;" \
+        "" \
+        "Module \"mod1\":" \
+        "" \
+        "File .*:" \
+        "21:\[\t \]+${real4} mod1::mod1_var_1;" ]
+
index a4044184233ce346b7ab15d6c7eee759dbdcd594..3fe2259da495e76db5bd955b40d3e36b6fece8dd 100644 (file)
 ! mod2 is defined.
 module mod2
   integer :: mod2_var_1 = 123
+  real, parameter :: mod2_var_2 = 0.5
+contains
+  subroutine sub_m2_a(a, b)
+    integer :: a
+    logical :: b
+    print*, "sub_m2_a = ", abc
+    print*, "a = ", a
+    print*, "b = ", b
+  end subroutine sub_m2_a
+
+  logical function sub_m2_b(x)
+    real :: x
+    print*, "sub_m2_b = ", cde
+    print*, "x = ", x
+    sub_m2_b = .true.
+  end function sub_m2_b
 end module mod2
index 954e083e4069efaaf8293d7269cc999880c4f982..324b4e01296acb5949763122b50cd8850fc163d4 100644 (file)
@@ -35,6 +35,7 @@ set integer4 [fortran_int4]
 set integer8 [fortran_int8]
 set logical4 [fortran_logical4]
 set character1 [fortran_character1]
+set real4 [fortran_real4]
 
 gdb_test "info types" \
     [multi_line \
@@ -45,7 +46,8 @@ gdb_test "info types" \
         "\[\t \]+${integer4}" \
         "(\[\t \]+${integer8}" \
         ")?\[\t \]+${logical4}" \
-        "(20:\[\t \]+Type __vtype_mod1_M1t1;" \
+        "(35:\[\t \]+Type __vtype_mod1_M1t1;" \
         ")?$decimal:\[\t \]+Type m1t1;" \
-        "22:\[\t \]+Type s1;(" \
+        "\[\t \]+${real4}" \
+        "37:\[\t \]+Type s1;(" \
         ".*)?"]
index ec52ef98efc9973ff3d03b60390bc9e355587200..d3513aca3041cba451ee15fbf39d49536580d808 100644 (file)
@@ -17,6 +17,21 @@ module mod1
   type :: m1t1
      integer :: b
   end type m1t1
+
+  real :: mod1_var_1 = 1.0
+  integer, parameter :: mod1_var_2 = 456
+
+contains
+  subroutine sub_m1_a(arg)
+    integer :: arg
+    print*, "sub_m1_a"
+    print*, "arg = ", arg
+  end subroutine sub_m1_a
+
+  integer function sub_m1_b()
+    print*, "sub_m1_b"
+    sub_m1_b = 3
+  end function sub_m1_b
 end module mod1
 
 program info_types_test