[v2,01/11] gdb: add symbol_search_kind enum for global_symbol_searcher

Message ID 20261001020952.698419-2-simon.marchi@polymtl.ca
State New
Headers
Series [v2,01/11] gdb: add symbol_search_kind enum for global_symbol_searcher |

Commit Message

Simon Marchi Oct. 1, 2026, 2:09 a.m. UTC
  From: Simon Marchi <simon.marchi@efficios.com>

While reading the global_symbol_searcher code, something that was not clear
to me was that despite accepting a domain_search_flags, searches are
mutually exclusive between types, variables and functions.

One snippet of code that really confused me was (now removed by previous
commit ca1c3c309d "gdb: Skip useless minsym scan in variable-only symbol
searches"):

		  if ((kind & SEARCH_FUNCTION_DOMAIN) != 0
		      ? (find_compunit_symtab_for_pc
			 (msymbol->value_address (objfile)) == NULL)
		      : (lookup_symbol_in_objfile_from_linkage_name
			 (objfile, msymbol->linkage_name (),
			  SEARCH_VFT)
			 .symbol == NULL))

I kept thinking: what if you search for both functions and variables,
this will take the "function" path, this can't work.  The answer is that
it's not supposed to happen.

This patch adds the symbol_search_kind enum and uses it in
global_symbol_searcher (and a few caller functions), making it clear
that you search just one kind at a time.

The new enum has a certain overlap with enum domain_search_flag, but I
think that having the more scoped enum makes global_symbol_searcher
easier to understand, by specifying clearly what it needs to handle.

Change-Id: I4a3f4752c7be51a4da5831f9780d21e6e7271b38
---
 gdb/mi/mi-symbol-cmds.c |  36 +++++++------
 gdb/python/python.c     |   2 +-
 gdb/symtab.c            | 112 ++++++++++++++++++++++------------------
 gdb/symtab.h            |  34 ++++++++----
 4 files changed, 106 insertions(+), 78 deletions(-)
  

Comments

Andrew Burgess Oct. 1, 2026, 10:30 a.m. UTC | #1
I think this is looking good.  Just one minor comment inline below:

simon.marchi@polymtl.ca writes:

> @@ -5166,20 +5179,18 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
>        const char *classname;
>        switch (kind)
>  	{
> -	case VAR_DOMAIN:
> +	case symbol_search_kind::VARIABLE:
>  	  classname = "variable";
>  	  break;
> -	case FUNCTION_DOMAIN:
> +	case symbol_search_kind::FUNCTION:
>  	  classname = "function";
>  	  break;
> -	case TYPE_DOMAIN:
> +	case symbol_search_kind::TYPE:
>  	  classname = "type";
>  	  break;
> -	case MODULE_DOMAIN:
> +	case symbol_search_kind::MODULE:
>  	  classname = "module";
>  	  break;
> -	default:
> -	  gdb_assert_not_reached ("invalid domain enum");
>  	}

I initially wrote: please don't drop the default case, but then I
checked the V1 review and saw this change was made specifically to
address the feedback there.

What I don't understand is you said:

> > I think we could drop the "default" case as part of this refactoring.  All
> > cases are handled; we lose compile time warnings for unhandled cases with
> > the "default" case.
> 
> Agreed that we can drop the default.  Note that we don't build with
> -Wswitch, but we specifically enable it locally here and there.

If the warning is mostly off, including here, then deleting the default
seems like the wrong choice.

I'm not too fussed, I think there's a middle group, that would keep my
happy:

 1. initialise classname to nullptr, and

 2. follow this switch statement with:
      gdb_assert (classname != nullptr);

Even with the warning on it doesn't protect us from random garbage being
cast to type symbol_search_kind and then passed to this function, which
the 'default:' case does protect against.  But the trailing assert is
probably better anyway as it ensures each switch case is doing what
needs to be done.

With that:

Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew
  
Simon Marchi Oct. 1, 2026, 1:22 p.m. UTC | #2
On 10/1/26 6:30 AM, Andrew Burgess wrote:
> 
> I think this is looking good.  Just one minor comment inline below:
> 
> simon.marchi@polymtl.ca writes:
> 
>> @@ -5166,20 +5179,18 @@ symtab_symbol_info (bool quiet, bool exclude_minsyms,
>>        const char *classname;
>>        switch (kind)
>>  	{
>> -	case VAR_DOMAIN:
>> +	case symbol_search_kind::VARIABLE:
>>  	  classname = "variable";
>>  	  break;
>> -	case FUNCTION_DOMAIN:
>> +	case symbol_search_kind::FUNCTION:
>>  	  classname = "function";
>>  	  break;
>> -	case TYPE_DOMAIN:
>> +	case symbol_search_kind::TYPE:
>>  	  classname = "type";
>>  	  break;
>> -	case MODULE_DOMAIN:
>> +	case symbol_search_kind::MODULE:
>>  	  classname = "module";
>>  	  break;
>> -	default:
>> -	  gdb_assert_not_reached ("invalid domain enum");
>>  	}
> 
> I initially wrote: please don't drop the default case, but then I
> checked the V1 review and saw this change was made specifically to
> address the feedback there.
> 
> What I don't understand is you said:
> 
>>> I think we could drop the "default" case as part of this refactoring.  All
>>> cases are handled; we lose compile time warnings for unhandled cases with
>>> the "default" case.
>>
>> Agreed that we can drop the default.  Note that we don't build with
>> -Wswitch, but we specifically enable it locally here and there.
> 
> If the warning is mostly off, including here, then deleting the default
> seems like the wrong choice.
> 
> I'm not too fussed, I think there's a middle group, that would keep my
> happy:
> 
>  1. initialise classname to nullptr, and
> 
>  2. follow this switch statement with:
>       gdb_assert (classname != nullptr);

You're right, I applied the suggestion without thinking too much about
it.  We definitely want an assert to fire instead of printing from an
uninitialized pointer.  If that same code was in a function of its own,
I would have done it like this:

static const char *
ssk_to_string (symbol_search_kind kind)
{
  switch (kind)
    {
    case symbol_search_kind::VARIABLE:
      return "variable";

    case symbol_search_kind::FUNCTION:
      return "function";

    case symbol_search_kind::TYPE:
      return "type";

    case symbol_search_kind::MODULE:
      return "module";
    }

  gdb_assert_not_reached ("invalid symbol_search_kind value");
}

There is even an example of that in the same patch (the to_search_flags
function).

I'll initialize the variable with nullptr and add a nullptr check after
the switch.  I prefer this over the default, because if we ever enable
-Wswitch (which will probably never happen, I tried it before and it was
painful), then we'll get a compile-time error if we are missing a case.

I don't think that this code is duplicated anywhere, so I don't think
it's worth moving it to a separate function.

> 
> Even with the warning on it doesn't protect us from random garbage being
> cast to type symbol_search_kind and then passed to this function, which
> the 'default:' case does protect against.  But the trailing assert is
> probably better anyway as it ensures each switch case is doing what
> needs to be done.
> 
> With that:
> 
> Approved-By: Andrew Burgess <aburgess@redhat.com>

Thanks,

Simon
  
Tom Tromey Oct. 1, 2026, 3:35 p.m. UTC | #3
>>>>> "Simon" == Simon Marchi <simon.marchi@polymtl.ca> writes:

Simon> You're right, I applied the suggestion without thinking too much about
Simon> it.  We definitely want an assert to fire instead of printing from an
Simon> uninitialized pointer.  If that same code was in a function of its own,
Simon> I would have done it like this:
[...]

Simon> I'll initialize the variable with nullptr and add a nullptr check after
Simon> the switch.  I prefer this over the default, because if we ever enable
Simon> -Wswitch (which will probably never happen, I tried it before and it was
Simon> painful), then we'll get a compile-time error if we are missing a case.

I tend to think that only some subset of switches really need this
treatment anyway.  A while ago I asked for an easier way to enable
-Wswitch-enum selectively:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108811

I guess we could accomplish this today with _Pragma if we didn't mind
wrapping such switches in begin/end pairs.

I think -Wswitch-enum is maybe better than -Wswitch and in the switches
that matter, gdb shouldn't have a 'default', just a total enumeration of
cases.

Tom
  

Patch

diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 58f2feef5533..30b8ec495e8f 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -71,7 +71,7 @@  mi_cmd_symbol_list_lines (const char *command, const char *const *argv,
    results.  */
 
 static void
-output_debug_symbol (ui_out *uiout, domain_search_flags kind,
+output_debug_symbol (ui_out *uiout, symbol_search_kind kind,
 		     struct symbol *sym, int block)
 {
   ui_out_emit_tuple tuple_emitter (uiout);
@@ -80,7 +80,8 @@  output_debug_symbol (ui_out *uiout, domain_search_flags kind,
     uiout->field_unsigned ("line", sym->line ());
   uiout->field_string ("name", sym->print_name ());
 
-  if ((kind & (SEARCH_FUNCTION_DOMAIN | SEARCH_VAR_DOMAIN)) != 0)
+  if (kind == symbol_search_kind::FUNCTION
+      || kind == symbol_search_kind::VARIABLE)
     {
       string_file tmp_stream;
       type_print (sym->type (), "", &tmp_stream, -1);
@@ -111,7 +112,7 @@  output_nondebug_symbol (ui_out *uiout, const bound_minimal_symbol &msymbol)
    and then prints the matching [m]symbols in an MI structured format.  */
 
 static void
-mi_symbol_info (domain_search_flags kind, const char *name_regexp,
+mi_symbol_info (symbol_search_kind kind, const char *name_regexp,
 		const char *type_regexp, bool exclude_minsyms,
 		size_t max_results)
 {
@@ -188,7 +189,7 @@  parse_max_results_option (const char *arg)
    Processes command line options from ARGV and ARGC.  */
 
 static void
-mi_info_functions_or_variables (domain_search_flags kind,
+mi_info_functions_or_variables (symbol_search_kind kind,
 				const char *const *argv, int argc)
 {
   size_t max_results = SIZE_MAX;
@@ -215,7 +216,7 @@  mi_info_functions_or_variables (domain_search_flags kind,
   while (1)
     {
       const char *cmd_string
-	= ((kind == SEARCH_FUNCTION_DOMAIN)
+	= ((kind == symbol_search_kind::FUNCTION)
 	   ? "-symbol-info-functions" : "-symbol-info-variables");
       int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg);
       if (opt < 0)
@@ -251,7 +252,7 @@  using module_symbol_search_iterator
 static module_symbol_search_iterator
 output_module_symbols_in_single_module_and_file
 	(struct ui_out *uiout, module_symbol_search_iterator iter,
-	 const module_symbol_search_iterator end, domain_search_flags kind)
+	 const module_symbol_search_iterator end, symbol_search_kind kind)
 {
   /* The symbol for the module in which the first result resides.  */
   const symbol *first_module_symbol = iter->first.symbol;
@@ -286,7 +287,7 @@  output_module_symbols_in_single_module_and_file
 static module_symbol_search_iterator
 output_module_symbols_in_single_module
 	(struct ui_out *uiout, module_symbol_search_iterator iter,
-	 const module_symbol_search_iterator end, domain_search_flags kind)
+	 const module_symbol_search_iterator end, symbol_search_kind kind)
 {
   gdb_assert (iter->first.symbol != nullptr);
   gdb_assert (iter->second.symbol != nullptr);
@@ -314,7 +315,7 @@  output_module_symbols_in_single_module
    command line options passed to the MI command.  */
 
 static void
-mi_info_module_functions_or_variables (domain_search_flags kind,
+mi_info_module_functions_or_variables (symbol_search_kind kind,
 				       const char *const *argv, int argc)
 {
   const char *module_regexp = nullptr;
@@ -341,7 +342,7 @@  mi_info_module_functions_or_variables (domain_search_flags kind,
   while (1)
     {
       const char *cmd_string
-	= ((kind == SEARCH_FUNCTION_DOMAIN)
+	= ((kind == symbol_search_kind::FUNCTION)
 	   ? "-symbol-info-module-functions"
 	   : "-symbol-info-module-variables");
       int opt = mi_getopt (cmd_string, argc, argv, opts, &oind, &oarg);
@@ -383,7 +384,7 @@  void
 mi_cmd_symbol_info_functions (const char *command, const char *const *argv,
 			      int argc)
 {
-  mi_info_functions_or_variables (SEARCH_FUNCTION_DOMAIN, argv, argc);
+  mi_info_functions_or_variables (symbol_search_kind::FUNCTION, argv, argc);
 }
 
 /* Implement -symbol-info-module-functions command.  */
@@ -392,7 +393,8 @@  void
 mi_cmd_symbol_info_module_functions (const char *command,
 				     const char *const *argv, int argc)
 {
-  mi_info_module_functions_or_variables (SEARCH_FUNCTION_DOMAIN, argv, argc);
+  mi_info_module_functions_or_variables (symbol_search_kind::FUNCTION,
+					 argv, argc);
 }
 
 /* Implement -symbol-info-module-variables command.  */
@@ -401,7 +403,8 @@  void
 mi_cmd_symbol_info_module_variables (const char *command,
 				     const char *const *argv, int argc)
 {
-  mi_info_module_functions_or_variables (SEARCH_VAR_DOMAIN, argv, argc);
+  mi_info_module_functions_or_variables (symbol_search_kind::VARIABLE,
+					 argv, argc);
 }
 
 /* Implement -symbol-inf-modules command.  */
@@ -444,7 +447,8 @@  mi_cmd_symbol_info_modules (const char *command, const char *const *argv,
 	}
     }
 
-  mi_symbol_info (SEARCH_MODULE_DOMAIN, regexp, nullptr, true, max_results);
+  mi_symbol_info (symbol_search_kind::MODULE, regexp, nullptr, true,
+		  max_results);
 }
 
 /* Implement -symbol-info-types command.  */
@@ -487,8 +491,8 @@  mi_cmd_symbol_info_types (const char *command, const char *const *argv,
 	}
     }
 
-  mi_symbol_info (SEARCH_TYPE_DOMAIN | SEARCH_STRUCT_DOMAIN, regexp, nullptr,
-		  true, max_results);
+  mi_symbol_info (symbol_search_kind::TYPE, regexp, nullptr, true,
+		  max_results);
 }
 
 /* Implement -symbol-info-variables command.  */
@@ -497,5 +501,5 @@  void
 mi_cmd_symbol_info_variables (const char *command, const char *const *argv,
 			      int argc)
 {
-  mi_info_functions_or_variables (SEARCH_VAR_DOMAIN, argv, argc);
+  mi_info_functions_or_variables (symbol_search_kind::VARIABLE, argv, argc);
 }
diff --git a/gdb/python/python.c b/gdb/python/python.c
index d51cd83966be..467317b7996e 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -848,7 +848,7 @@  gdbpy_rbreak (PyObject *self, PyObject *args, PyObject *kw)
       minsyms_p = cmp;
     }
 
-  global_symbol_searcher spec (SEARCH_FUNCTION_DOMAIN, regex);
+  global_symbol_searcher spec (symbol_search_kind::FUNCTION, regex);
 
   /* The "symtabs" keyword is any Python iterable object that returns
      a gdb.Symtab on each iteration.  If specified, iterate through
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 27070f74f83e..f80e96b48285 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4698,11 +4698,31 @@  treg_matches_sym_type_name (const compiled_regex &treg,
   return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
 }
 
+/* Return the domain search flags matching symbols of kind KIND.  */
+
+static domain_search_flags
+to_search_flags (symbol_search_kind kind)
+{
+  switch (kind)
+    {
+    case symbol_search_kind::VARIABLE:
+      return SEARCH_VAR_DOMAIN;
+    case symbol_search_kind::FUNCTION:
+      return SEARCH_FUNCTION_DOMAIN;
+    case symbol_search_kind::TYPE:
+      return SEARCH_TYPE_DOMAIN | SEARCH_STRUCT_DOMAIN;
+    case symbol_search_kind::MODULE:
+      return SEARCH_MODULE_DOMAIN;
+    }
+
+  gdb_assert_not_reached ("invalid symbol_search_kind");
+}
+
 /* See symtab.h.  */
 
 bool
 global_symbol_searcher::is_suitable_msymbol
-	(const domain_search_flags kind, const minimal_symbol *msymbol)
+	(symbol_search_kind kind, const minimal_symbol *msymbol)
 {
   switch (msymbol->type ())
     {
@@ -4710,12 +4730,12 @@  global_symbol_searcher::is_suitable_msymbol
     case mst_bss:
     case mst_file_data:
     case mst_file_bss:
-      return (kind & SEARCH_VAR_DOMAIN) != 0;
+      return kind == symbol_search_kind::VARIABLE;
     case mst_text:
     case mst_file_text:
     case mst_solib_trampoline:
     case mst_text_gnu_ifunc:
-      return (kind & SEARCH_FUNCTION_DOMAIN) != 0;
+      return kind == symbol_search_kind::FUNCTION;
     default:
       return false;
     }
@@ -4727,7 +4747,6 @@  bool
 global_symbol_searcher::expand_symtabs
 	(objfile *objfile, const std::optional<compiled_regex> &preg) const
 {
-  domain_search_flags kind = m_kind;
   bool found_func_msymbol_without_debug_info = false;
 
   auto do_file_match = [&] (const char *filename, bool basenames)
@@ -4748,7 +4767,7 @@  global_symbol_searcher::expand_symtabs
      },
      NULL,
      SEARCH_GLOBAL_BLOCK | SEARCH_STATIC_BLOCK,
-     kind);
+     to_search_flags (m_kind));
 
   /* Here, we search through the minimal symbol tables for functions that
      match, and force their symbols to be read.  The symbol will then be found
@@ -4764,7 +4783,7 @@  global_symbol_searcher::expand_symtabs
      symtab.  When no file names were given the caller unconditionally rescans
      the minimal symbols for SEARCH_VAR_DOMAIN.  */
   if (m_filenames.empty ()
-      && (kind & SEARCH_FUNCTION_DOMAIN) != 0)
+      && m_kind == symbol_search_kind::FUNCTION)
     {
       for (minimal_symbol *msymbol : objfile->msymbols ())
 	{
@@ -4773,7 +4792,7 @@  global_symbol_searcher::expand_symtabs
 	  if (msymbol->created_by_gdb)
 	    continue;
 
-	  if (is_suitable_msymbol (kind, msymbol))
+	  if (is_suitable_msymbol (m_kind, msymbol))
 	    {
 	      if (!preg.has_value ()
 		  || preg->exec (msymbol->natural_name (), 0,
@@ -4804,7 +4823,7 @@  global_symbol_searcher::add_matching_symbols
 	 const std::optional<compiled_regex> &treg,
 	 std::set<symbol_search> *result_set) const
 {
-  domain_search_flags kind = m_kind;
+  domain_search_flags domain = to_search_flags (m_kind);
 
   /* Add matching symbols (if not already present).  */
   for (compunit_symtab &cust : objfile->compunits ())
@@ -4832,7 +4851,7 @@  global_symbol_searcher::add_matching_symbols
 					 m_filenames, false))))
 		continue;
 
-	      if (!sym->matches (kind))
+	      if (!sym->matches (domain))
 		continue;
 
 	      if (preg.has_value () && preg->exec (sym->natural_name (), 0,
@@ -4845,7 +4864,7 @@  global_symbol_searcher::add_matching_symbols
 		   && !treg_matches_sym_type_name (*treg, sym)))
 		continue;
 
-	      if ((kind & SEARCH_VAR_DOMAIN) != 0)
+	      if (m_kind == symbol_search_kind::VARIABLE)
 		{
 		  if (sym->loc_class () == LOC_UNRESOLVED
 		      /* LOC_CONST can be used for more than
@@ -4882,8 +4901,6 @@  global_symbol_searcher::add_matching_msymbols
 	(objfile *objfile, const std::optional<compiled_regex> &preg,
 	 std::vector<symbol_search> *results) const
 {
-  domain_search_flags kind = m_kind;
-
   for (minimal_symbol *msymbol : objfile->msymbols ())
     {
       QUIT;
@@ -4891,7 +4908,7 @@  global_symbol_searcher::add_matching_msymbols
       if (msymbol->created_by_gdb)
 	continue;
 
-      if (is_suitable_msymbol (kind, msymbol))
+      if (is_suitable_msymbol (m_kind, msymbol))
 	{
 	  if (!preg.has_value ()
 	      || preg->exec (msymbol->natural_name (), 0,
@@ -4899,7 +4916,7 @@  global_symbol_searcher::add_matching_msymbols
 	    {
 	      /* For functions we can do a quick check of whether the
 		 symbol might be found via find_pc_symtab.  */
-	      if ((kind & SEARCH_FUNCTION_DOMAIN) == 0
+	      if (m_kind != symbol_search_kind::FUNCTION
 		  || (find_compunit_symtab_for_pc
 		      (msymbol->value_address (objfile)) == NULL))
 		{
@@ -5006,12 +5023,12 @@  global_symbol_searcher::search () const
      minimal symbol, as we assume that a minimal symbol does not have a
      type.  */
   if ((found_func_msymbol_without_debug_info
-       || (m_filenames.empty () && (m_kind & SEARCH_VAR_DOMAIN) != 0))
+       || (m_filenames.empty () && m_kind == symbol_search_kind::VARIABLE))
       && !m_exclude_minsyms
       && !treg.has_value ())
     {
-      gdb_assert ((m_kind & (SEARCH_VAR_DOMAIN | SEARCH_FUNCTION_DOMAIN))
-		  != 0);
+      gdb_assert (m_kind == symbol_search_kind::VARIABLE
+		  || m_kind == symbol_search_kind::FUNCTION);
       for (objfile &objfile : current_program_space->objfiles ())
 	if (!add_matching_msymbols (&objfile, preg, &result))
 	  break;
@@ -5143,7 +5160,7 @@  print_msymbol_info (bound_minimal_symbol msymbol)
 
 static void
 symtab_symbol_info (bool quiet, bool exclude_minsyms,
-		    const char *regexp, domain_enum kind,
+		    const char *regexp, symbol_search_kind kind,
 		    const char *t_regexp, int from_tty)
 {
   const char *last_filename = "";
@@ -5152,11 +5169,7 @@  symtab_symbol_info (bool quiet, bool exclude_minsyms,
   if (regexp != nullptr && *regexp == '\0')
     regexp = nullptr;
 
-  domain_search_flags flags = to_search_flags (kind);
-  if (kind == TYPE_DOMAIN)
-    flags |= SEARCH_STRUCT_DOMAIN;
-
-  global_symbol_searcher spec (flags, regexp);
+  global_symbol_searcher spec (kind, regexp);
   spec.set_symbol_type_regexp (t_regexp);
   spec.set_exclude_minsyms (exclude_minsyms);
   std::vector<symbol_search> symbols = spec.search ();
@@ -5166,20 +5179,18 @@  symtab_symbol_info (bool quiet, bool exclude_minsyms,
       const char *classname;
       switch (kind)
 	{
-	case VAR_DOMAIN:
+	case symbol_search_kind::VARIABLE:
 	  classname = "variable";
 	  break;
-	case FUNCTION_DOMAIN:
+	case symbol_search_kind::FUNCTION:
 	  classname = "function";
 	  break;
-	case TYPE_DOMAIN:
+	case symbol_search_kind::TYPE:
 	  classname = "type";
 	  break;
-	case MODULE_DOMAIN:
+	case symbol_search_kind::MODULE:
 	  classname = "module";
 	  break;
-	default:
-	  gdb_assert_not_reached ("invalid domain enum");
 	}
 
       if (regexp != NULL)
@@ -5304,7 +5315,7 @@  info_variables_command (const char *args, int from_tty)
     args = nullptr;
 
   symtab_symbol_info
-    (opts.quiet, opts.exclude_minsyms, args, VAR_DOMAIN,
+    (opts.quiet, opts.exclude_minsyms, args, symbol_search_kind::VARIABLE,
      opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
      from_tty);
 }
@@ -5323,7 +5334,7 @@  info_functions_command (const char *args, int from_tty)
     args = nullptr;
 
   symtab_symbol_info
-    (opts.quiet, opts.exclude_minsyms, args, FUNCTION_DOMAIN,
+    (opts.quiet, opts.exclude_minsyms, args, symbol_search_kind::FUNCTION,
      opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
      from_tty);
 }
@@ -5366,8 +5377,8 @@  info_types_command (const char *args, int from_tty)
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
     args = nullptr;
-  symtab_symbol_info (opts.quiet, false, args, TYPE_DOMAIN, nullptr,
-		      from_tty);
+  symtab_symbol_info (opts.quiet, false, args, symbol_search_kind::TYPE,
+		      nullptr, from_tty);
 }
 
 /* Command completer for 'info types' command.  */
@@ -5399,8 +5410,8 @@  info_modules_command (const char *args, int from_tty)
     (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
   if (args != nullptr && *args == '\0')
     args = nullptr;
-  symtab_symbol_info (opts.quiet, true, args, MODULE_DOMAIN, nullptr,
-		      from_tty);
+  symtab_symbol_info (opts.quiet, true, args, symbol_search_kind::MODULE,
+		      nullptr, from_tty);
 }
 
 /* Implement the 'info main' command.  */
@@ -5441,7 +5452,7 @@  rbreak_command (const char *regexp, int from_tty)
      because the std::move nullifies file_name.  */
   bool file_name_p = file_name != nullptr;
 
-  global_symbol_searcher spec (SEARCH_FUNCTION_DOMAIN, regexp);
+  global_symbol_searcher spec (symbol_search_kind::FUNCTION, regexp);
   if (file_name_p)
     spec.add_filename (std::move (file_name));
   std::vector<symbol_search> symbols = spec.search ();
@@ -6654,12 +6665,12 @@  static struct cmd_list_element *info_module_cmdlist = NULL;
 
 std::vector<module_symbol_search>
 search_module_symbols (const char *module_regexp, const char *regexp,
-		       const char *type_regexp, domain_search_flags kind)
+		       const char *type_regexp, symbol_search_kind kind)
 {
   std::vector<module_symbol_search> results;
 
   /* Search for all modules matching MODULE_REGEXP.  */
-  global_symbol_searcher spec1 (SEARCH_MODULE_DOMAIN, module_regexp);
+  global_symbol_searcher spec1 (symbol_search_kind::MODULE, module_regexp);
   spec1.set_exclude_minsyms (true);
   std::vector<symbol_search> modules = spec1.search ();
 
@@ -6705,9 +6716,10 @@  search_module_symbols (const char *module_regexp, const char *regexp,
 static void
 info_module_subcommand (bool quiet, const char *module_regexp,
 			const char *regexp, const char *type_regexp,
-			domain_search_flags kind)
+			symbol_search_kind kind)
 {
-  gdb_assert (kind == SEARCH_FUNCTION_DOMAIN || kind == SEARCH_VAR_DOMAIN);
+  gdb_assert (kind == symbol_search_kind::FUNCTION
+	      || kind == symbol_search_kind::VARIABLE);
 
   /* Print a header line.  Don't build the header line bit by bit as this
      prevents internationalisation.  */
@@ -6718,12 +6730,12 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 	  if (type_regexp == nullptr)
 	    {
 	      if (regexp == nullptr)
-		gdb_printf ((kind == SEARCH_VAR_DOMAIN
+		gdb_printf ((kind == symbol_search_kind::VARIABLE
 			     ? _("All variables in all modules:")
 			     : _("All functions in all modules:")));
 	      else
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables matching regular expression"
 			" \"%s\" in all modules:")
 		    : _("All functions matching regular expression"
@@ -6734,7 +6746,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 	    {
 	      if (regexp == nullptr)
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables with type matching regular "
 			"expression \"%s\" in all modules:")
 		    : _("All functions with type matching regular "
@@ -6742,7 +6754,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 		   type_regexp);
 	      else
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables matching regular expression "
 			"\"%s\",\n\twith type matching regular "
 			"expression \"%s\" in all modules:")
@@ -6758,7 +6770,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 	    {
 	      if (regexp == nullptr)
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables in all modules matching regular "
 			"expression \"%s\":")
 		    : _("All functions in all modules matching regular "
@@ -6766,7 +6778,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 		   module_regexp);
 	      else
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables matching regular expression "
 			"\"%s\",\n\tin all modules matching regular "
 			"expression \"%s\":")
@@ -6779,7 +6791,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 	    {
 	      if (regexp == nullptr)
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables with type matching regular "
 			"expression \"%s\"\n\tin all modules matching "
 			"regular expression \"%s\":")
@@ -6789,7 +6801,7 @@  info_module_subcommand (bool quiet, const char *module_regexp,
 		   type_regexp, module_regexp);
 	      else
 		gdb_printf
-		  ((kind == SEARCH_VAR_DOMAIN
+		  ((kind == symbol_search_kind::VARIABLE
 		    ? _("All variables matching regular expression "
 			"\"%s\",\n\twith type matching regular expression "
 			"\"%s\",\n\tin all modules matching regular "
@@ -6901,7 +6913,7 @@  info_module_functions_command (const char *args, int from_tty)
     (opts.quiet,
      opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
      opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
-     SEARCH_FUNCTION_DOMAIN);
+     symbol_search_kind::FUNCTION);
 }
 
 /* Implements the 'info module variables' command.  */
@@ -6920,7 +6932,7 @@  info_module_variables_command (const char *args, int from_tty)
     (opts.quiet,
      opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
      opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
-     SEARCH_VAR_DOMAIN);
+     symbol_search_kind::VARIABLE);
 }
 
 /* Command completer for 'info module ...' sub-commands.  */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 6443216fd7f0..d21933759b6a 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -2586,6 +2586,24 @@  struct symbol_search
 				  const symbol_search &sym_b);
 };
 
+/* The kind of symbols searched for by global_symbol_searcher.  */
+
+enum class symbol_search_kind
+{
+  /* Variables, excluding enum constants.  */
+  VARIABLE,
+
+  /* Functions.  */
+  FUNCTION,
+
+  /* Type names, including those with a struct/union/enum prefix (STRUCT
+     domain).  */
+  TYPE,
+
+  /* Fortran modules.  */
+  MODULE,
+};
+
 /* In order to search for global symbols of a particular kind matching
    particular regular expressions, create an instance of this structure and
    call the SEARCH member function.  */
@@ -2594,7 +2612,7 @@  class global_symbol_searcher
 public:
 
   /* Constructor.  */
-  global_symbol_searcher (domain_search_flags kind,
+  global_symbol_searcher (symbol_search_kind kind,
 			  const char *symbol_name_regexp)
     : m_kind (kind),
       m_symbol_name_regexp (symbol_name_regexp)
@@ -2635,14 +2653,8 @@  class global_symbol_searcher
   /* The set of source files to search in for matching symbols.  */
   std::vector<gdb::unique_xmalloc_ptr<char>> m_filenames;
 
-  /* The kind of symbols are we searching for.
-     VARIABLES_DOMAIN - Search all symbols, excluding functions, type
-			names, and constants (enums).
-     FUNCTIONS_DOMAIN - Search all functions..
-     TYPES_DOMAIN     - Search all type names.
-     MODULES_DOMAIN   - Search all Fortran modules.
-     ALL_DOMAIN       - Not valid for this function.  */
-  domain_search_flags m_kind;
+  /* The kind of symbols we are searching for.  */
+  symbol_search_kind m_kind;
 
   /* Regular expression to match against the symbol name.  */
   const char *m_symbol_name_regexp = nullptr;
@@ -2686,7 +2698,7 @@  class global_symbol_searcher
 			      std::vector<symbol_search> *results) const;
 
   /* Return true if MSYMBOL is of type KIND.  */
-  static bool is_suitable_msymbol (const domain_search_flags kind,
+  static bool is_suitable_msymbol (symbol_search_kind kind,
 				   const minimal_symbol *msymbol);
 };
 
@@ -2703,7 +2715,7 @@  using module_symbol_search = std::pair<symbol_search, symbol_search>;
    within the module.  */
 extern std::vector<module_symbol_search> search_module_symbols
 	(const char *module_regexp, const char *regexp,
-	 const char *type_regexp, domain_search_flags kind);
+	 const char *type_regexp, symbol_search_kind kind);
 
 /* Convert a global or static symbol SYM (based on BLOCK, which should be
    either GLOBAL_BLOCK or STATIC_BLOCK) into a string for use in 'info'