diff --git a/gdb/NEWS b/gdb/NEWS
index 40b56727227..14c931602f4 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -104,6 +104,12 @@ maint show test-settings KIND
   A set of commands used by the testsuite for exercising the settings
   infrastructure.
 
+info modules [-q] [REGEXP]
+  Return a list of modules matching REGEXP, or all modules if no
+  REGEXP is given.  Only languages that generate DW_TAG_module in
+  their DWARF (for example Fortran) will give any results for this
+  command.
+
 * Changed commands
 
 help
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index c7f7abd9e87..71ee20f29d5 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18617,6 +18617,22 @@
 is printed only if its name matches @var{regexp} and its type matches
 @var{type_regexp}.
 
+@kindex info modules
+@cindex modules
+@item info modules [-q] [@var{regexp}]
+List all modules for which there is debugging information available.
+Modules are identified by @code{DW_TAG_module} in DWARF debugging
+information, only languages that use this tag will list modules with
+this command.  Currently Fortran is known to generate module
+information in its debug.
+
+If the optional @var{regexp} is provided then only modules whose name
+matches @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
+have been printed.
+
 @kindex info classes
 @cindex Objective-C, classes and selectors
 @item info classes
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 01cab752888..00012877da1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -6004,6 +6004,14 @@ dw2_debug_names_iterator::next ()
 	  goto again;
 	}
       break;
+    case MODULES_DOMAIN:
+      switch (indexval.dwarf_tag)
+	{
+	case DW_TAG_module:
+	  break;
+	default:
+	  goto again;
+	}
     default:
       break;
     }
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 6cc7566580a..95615e30f68 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1301,6 +1301,8 @@ recursively_search_psymtabs
 	  QUIT;
 
 	  if ((domain == ALL_DOMAIN
+	       || (domain == MODULES_DOMAIN
+		   && (*psym)->domain == MODULE_DOMAIN)
 	       || (domain == VARIABLES_DOMAIN
 		   && (*psym)->aclass != LOC_TYPEDEF
 		   && (*psym)->aclass != LOC_BLOCK)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d3a209608b7..793be13ab9d 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -297,6 +297,7 @@ search_domain_name (enum search_domain e)
     case VARIABLES_DOMAIN: return "VARIABLES_DOMAIN";
     case FUNCTIONS_DOMAIN: return "FUNCTIONS_DOMAIN";
     case TYPES_DOMAIN: return "TYPES_DOMAIN";
+    case MODULES_DOMAIN: return "MODULES_DOMAIN";
     case ALL_DOMAIN: return "ALL_DOMAIN";
     default: gdb_assert_not_reached ("bad search_domain");
     }
@@ -4365,7 +4366,7 @@ search_symbols (const char *regexp, enum search_domain kind,
   gdb::optional<compiled_regex> preg;
   gdb::optional<compiled_regex> treg;
 
-  gdb_assert (kind <= TYPES_DOMAIN);
+  gdb_assert (kind <= MODULES_DOMAIN);
 
   ourtype = types[kind];
   ourtype2 = types2[kind];
@@ -4540,7 +4541,9 @@ search_symbols (const char *regexp, enum search_domain kind,
 								     sym)))
 			      || (kind == TYPES_DOMAIN
 				  && SYMBOL_CLASS (sym) == LOC_TYPEDEF
-				  && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN))))
+				  && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
+			      || (kind == MODULES_DOMAIN
+				  && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN))))
 		    {
 		      /* match */
 		      result.emplace_back (i, sym);
@@ -4671,6 +4674,11 @@ print_symbol_info (enum search_domain kind,
 
       printf_filtered (";\n");
     }
+  /* Printing of modules is currently done here, maybe at some future
+     point we might want a language specific method to print the module
+     symbol so that we can customise the output more.  */
+  else if (kind == MODULES_DOMAIN)
+    printf_filtered ("%s\n", SYMBOL_PRINT_NAME (sym));
 }
 
 /* This help function for symtab_symbol_info() prints information
@@ -4711,11 +4719,11 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
 		    const char *t_regexp, int from_tty)
 {
   static const char * const classnames[] =
-    {"variable", "function", "type"};
+    {"variable", "function", "type", "module"};
   const char *last_filename = "";
   int first = 1;
 
-  gdb_assert (kind <= TYPES_DOMAIN);
+  gdb_assert (kind <= MODULES_DOMAIN);
 
   if (regexp != nullptr && *regexp == '\0')
     regexp = nullptr;
@@ -4934,6 +4942,22 @@ info_types_command_completer (struct cmd_list_element *ignore,
   symbol_completer (ignore, tracker, text, word);
 }
 
+/* Implement the 'info modules' command.  */
+
+static void
+info_modules_command (const char *args, int from_tty)
+{
+  info_types_options opts;
+
+  auto grp = make_info_types_options_def_group (&opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
+  if (args != nullptr && *args == '\0')
+    args = nullptr;
+  symtab_symbol_info (opts.quiet, true, args, MODULES_DOMAIN, NULL,
+		      from_tty);
+}
+
 /* Breakpoint all functions matching regular expression.  */
 
 void
@@ -6198,6 +6222,10 @@ Print information about all types matching REGEXP, or all types if no\n\
 REGEXP is given.  The optional flag -q disables printing of headers."));
   set_cmd_completer_handle_brkchars (c, info_types_command_completer);
 
+  c = add_info ("modules", info_modules_command,
+		_("All module names, or those matching REGEXP."));
+  set_cmd_completer_handle_brkchars (c, info_types_command_completer);
+
   add_info ("sources", info_sources_command,
 	    _("Source files in the program."));
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index c4fd520e735..6e8bca0a86a 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -799,8 +799,11 @@ enum search_domain
   /* All defined types */
   TYPES_DOMAIN = 2,
 
+  /* All modules.  */
+  MODULES_DOMAIN = 3,
+
   /* Any type.  */
-  ALL_DOMAIN = 3
+  ALL_DOMAIN = 4
 };
 
 extern const char *search_domain_name (enum search_domain);
diff --git a/gdb/testsuite/gdb.fortran/info-modules.exp b/gdb/testsuite/gdb.fortran/info-modules.exp
new file mode 100644
index 00000000000..33110236271
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/info-modules.exp
@@ -0,0 +1,61 @@
+# Copyright 2019 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# 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'.
+
+load_lib "fortran.exp"
+
+if { [skip_fortran_tests] } { continue }
+
+standard_testfile info-types.f90
+
+if { [prepare_for_testing "failed to prepare" $testfile $srcfile {debug f90}] } {
+    return -1
+}
+
+if { ![runto MAIN__] } {
+    perror "Could not run to breakpoint `MAIN__'."
+    continue
+}
+
+gdb_test "info modules" \
+    [multi_line \
+	 "All defined modules:" \
+	 "" \
+	 "File .*:" \
+	 "16:\[\t \]+mod1" \
+	 "22:\[\t \]+mod2" ]
+
+gdb_test "info modules 1" \
+    [multi_line \
+	 "All modules matching regular expression \"1\":" \
+	 "" \
+	 "File .*:" \
+	 "16:\[\t \]+mod1" ]
+
+gdb_test "info modules 2" \
+    [multi_line \
+	 "All modules matching regular expression \"2\":" \
+	 "" \
+	 "File .*:" \
+	 "22:\[\t \]+mod2" ]
+
+gdb_test "info modules mod" \
+    [multi_line \
+	 "All modules matching regular expression \"mod\":" \
+	 "" \
+	 "File .*:" \
+	 "16:\[\t \]+mod1" \
+	 "22:\[\t \]+mod2" ]
diff --git a/gdb/testsuite/gdb.fortran/info-types.exp b/gdb/testsuite/gdb.fortran/info-types.exp
index 81e67395e8a..b0656bce2b7 100644
--- a/gdb/testsuite/gdb.fortran/info-types.exp
+++ b/gdb/testsuite/gdb.fortran/info-types.exp
@@ -44,4 +44,4 @@ gdb_test "info types" \
 	 "\[\t \]+${logical4}" \
 	 "20:\[\t \]+Type __vtype_mod1_M1t1;" \
 	 "17:\[\t \]+Type m1t1;" \
-	 "22:\[\t \]+Type s1;" ]
+	 "26:\[\t \]+Type s1;" ]
diff --git a/gdb/testsuite/gdb.fortran/info-types.f90 b/gdb/testsuite/gdb.fortran/info-types.f90
index 0e27e1ddf08..859a9485c8f 100644
--- a/gdb/testsuite/gdb.fortran/info-types.f90
+++ b/gdb/testsuite/gdb.fortran/info-types.f90
@@ -19,8 +19,13 @@ module mod1
   end type m1t1
 end module mod1
 
+module mod2
+  integer :: mod2_var_1 = 123
+end module mod2
+
 program info_types_test
   use mod1
+  use mod2
 
   type :: s1
      integer :: a
