aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog18
-rw-r--r--gdb/NEWS14
-rw-r--r--gdb/doc/ChangeLog5
-rw-r--r--gdb/doc/gdb.texinfo19
-rw-r--r--gdb/symtab.c348
-rw-r--r--gdb/symtab.h16
-rw-r--r--gdb/testsuite/ChangeLog9
-rw-r--r--gdb/testsuite/gdb.fortran/info-modules.exp123
-rw-r--r--gdb/testsuite/gdb.fortran/info-types-2.f9016
-rw-r--r--gdb/testsuite/gdb.fortran/info-types.exp6
-rw-r--r--gdb/testsuite/gdb.fortran/info-types.f9015
11 files changed, 586 insertions, 3 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 6dca96555ad..2bd67260dc7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,23 @@
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.
(dw2_expand_marked_cus): Handle MODULES_DOMAIN.
(dw2_debug_names_iterator::next): Handle MODULE_DOMAIN and
diff --git a/gdb/NEWS b/gdb/NEWS
index d46f7094d40..59895bd68b3 100644
--- 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
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 52497a17725..ce89ee444ea 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,5 +1,10 @@
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.
2019-10-31 Philippe Waroquiers <philippe.waroquiers@skynet.be>
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ee06df2bb2c..70e4be15244 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -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
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 4c14edae177..72a54ec1ca0 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -6340,6 +6340,315 @@ get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym)
+/* 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);
+}
+
+
+
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."));
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 72d1c7ff848..eac44aee156 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -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);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 6514c0764dc..4d1eecdb5c0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,14 @@
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.
* gdb.fortran/info-types.exp: Build with new file.
* gdb.fortran/info-types.f90: Include and use new module.
diff --git a/gdb/testsuite/gdb.fortran/info-modules.exp b/gdb/testsuite/gdb.fortran/info-modules.exp
index f961d28b000..43570066d2f 100644
--- a/gdb/testsuite/gdb.fortran/info-modules.exp
+++ b/gdb/testsuite/gdb.fortran/info-modules.exp
@@ -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;" ]
+
diff --git a/gdb/testsuite/gdb.fortran/info-types-2.f90 b/gdb/testsuite/gdb.fortran/info-types-2.f90
index a4044184233..3fe2259da49 100644
--- a/gdb/testsuite/gdb.fortran/info-types-2.f90
+++ b/gdb/testsuite/gdb.fortran/info-types-2.f90
@@ -17,4 +17,20 @@
! 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
diff --git a/gdb/testsuite/gdb.fortran/info-types.exp b/gdb/testsuite/gdb.fortran/info-types.exp
index 954e083e406..324b4e01296 100644
--- a/gdb/testsuite/gdb.fortran/info-types.exp
+++ b/gdb/testsuite/gdb.fortran/info-types.exp
@@ -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;(" \
".*)?"]
diff --git a/gdb/testsuite/gdb.fortran/info-types.f90 b/gdb/testsuite/gdb.fortran/info-types.f90
index ec52ef98efc..d3513aca304 100644
--- a/gdb/testsuite/gdb.fortran/info-types.f90
+++ b/gdb/testsuite/gdb.fortran/info-types.f90
@@ -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