diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index fd3f5d1ead9..8ae94dcdbab 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -520,17 +520,17 @@ ada_get_tcb_types_info (void)
      C-like) lookups to get the first match.  */
 
   struct symbol *atcb_sym =
-    lookup_symbol_in_language (atcb_name, NULL, SEARCH_STRUCT_DOMAIN,
+    lookup_symbol_in_language (atcb_name, NULL, SEARCH_TYPE_DOMAIN,
 			       language_c, NULL).symbol;
   const struct symbol *common_atcb_sym =
-    lookup_symbol_in_language (common_atcb_name, NULL, SEARCH_STRUCT_DOMAIN,
+    lookup_symbol_in_language (common_atcb_name, NULL, SEARCH_TYPE_DOMAIN,
 			       language_c, NULL).symbol;
   const struct symbol *private_data_sym =
-    lookup_symbol_in_language (private_data_name, NULL, SEARCH_STRUCT_DOMAIN,
+    lookup_symbol_in_language (private_data_name, NULL, SEARCH_TYPE_DOMAIN,
 			       language_c, NULL).symbol;
   const struct symbol *entry_call_record_sym =
     lookup_symbol_in_language (entry_call_record_name, NULL,
-			       SEARCH_STRUCT_DOMAIN,
+			       SEARCH_TYPE_DOMAIN,
 			       language_c, NULL).symbol;
 
   if (atcb_sym == NULL || atcb_sym->type () == NULL)
@@ -538,7 +538,7 @@ ada_get_tcb_types_info (void)
       /* In Ravenscar run-time libs, the  ATCB does not have a dynamic
 	 size, so the symbol name differs.  */
       atcb_sym = lookup_symbol_in_language (atcb_name_fixed, NULL,
-					    SEARCH_STRUCT_DOMAIN, language_c,
+					    SEARCH_TYPE_DOMAIN, language_c,
 					    NULL).symbol;
 
       if (atcb_sym == NULL || atcb_sym->type () == NULL)
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 30a38035c52..abb1c1880d6 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1473,7 +1473,7 @@ patch_opaque_types (struct symtab *s)
 	 but search the whole chain, as there may be several syms
 	 from different files with the same name.  */
       if (real_sym->aclass () == LOC_TYPEDEF
-	  && real_sym->domain () == VAR_DOMAIN
+	  && real_sym->domain () == TYPE_DOMAIN
 	  && real_sym->type ()->code () == TYPE_CODE_PTR
 	  && real_sym->type ()->target_type ()->length () != 0)
 	{
@@ -1544,6 +1544,7 @@ process_coff_symbol (struct coff_symbol *cs,
 
   if (ISFCN (cs->c_type))
     {
+      sym->set_domain (FUNCTION_DOMAIN);
       sym->set_value_longest
 	(sym->value_longest () + objfile->text_section_offset ());
       sym->set_type
@@ -1626,7 +1627,7 @@ process_coff_symbol (struct coff_symbol *cs,
 
 	case C_TPDEF:
 	  sym->set_aclass_index (LOC_TYPEDEF);
-	  sym->set_domain (VAR_DOMAIN);
+	  sym->set_domain (TYPE_DOMAIN);
 
 	  /* If type has no name, give it one.  */
 	  if (sym->type ()->name () == 0)
diff --git a/gdb/ctfread.c b/gdb/ctfread.c
index 50bac18232e..cbb8c3f2b8a 100644
--- a/gdb/ctfread.c
+++ b/gdb/ctfread.c
@@ -505,7 +505,7 @@ new_symbol (struct ctf_context *ccp, struct type *type, ctf_id_t tid)
 	  case CTF_K_INTEGER:
 	  case CTF_K_FLOAT:
 	    sym->set_aclass_index (LOC_TYPEDEF);
-	    sym->set_domain (VAR_DOMAIN);
+	    sym->set_domain (TYPE_DOMAIN);
 	    break;
 	  case CTF_K_POINTER:
 	    break;
diff --git a/gdb/dwarf2/cooked-index.c b/gdb/dwarf2/cooked-index.c
index 2430dbd40f4..3800c3aa800 100644
--- a/gdb/dwarf2/cooked-index.c
+++ b/gdb/dwarf2/cooked-index.c
@@ -206,31 +206,7 @@ cooked_index_entry::matches (domain_search_flags kind) const
   if ((flags & IS_TYPE_DECLARATION) != 0)
     return false;
 
-  if ((kind & SEARCH_VAR_DOMAIN) != 0
-      && (tag == DW_TAG_variable
-	  || tag == DW_TAG_constant
-	  || tag == DW_TAG_enumerator))
-    return true;
-
-  if ((kind & SEARCH_STRUCT_DOMAIN) != 0
-      && (tag == DW_TAG_structure_type
-	  || tag == DW_TAG_class_type
-	  || tag == DW_TAG_union_type
-	  || tag == DW_TAG_enumeration_type))
-    return true;
-
-  if ((kind & SEARCH_MODULE_DOMAIN) != 0 && tag == DW_TAG_module)
-    return true;
-
-  if ((kind & SEARCH_TYPE_DOMAIN) != 0 && tag_is_type (tag))
-    return true;
-
-  if ((kind & SEARCH_FUNCTION_DOMAIN) != 0
-      && (tag == DW_TAG_subprogram
-	  || tag == DW_TAG_entry_point))
-    return true;
-
-  return false;
+  return tag_matches_domain (tag, kind, per_cu->lang ());
 }
 
 /* See cooked-index.h.  */
diff --git a/gdb/dwarf2/index-write.c b/gdb/dwarf2/index-write.c
index 081046d4237..15356c72cb2 100644
--- a/gdb/dwarf2/index-write.c
+++ b/gdb/dwarf2/index-write.c
@@ -1314,11 +1314,10 @@ write_cooked_index (cooked_index *table,
 	       || entry->tag == DW_TAG_constant
 	       || entry->tag == DW_TAG_enumerator)
 	kind = GDB_INDEX_SYMBOL_KIND_VARIABLE;
-      else if (entry->tag == DW_TAG_module
-	       || entry->tag == DW_TAG_common_block)
-	kind = GDB_INDEX_SYMBOL_KIND_OTHER;
-      else
+      else if (tag_is_type (entry->tag))
 	kind = GDB_INDEX_SYMBOL_KIND_TYPE;
+      else
+	kind = GDB_INDEX_SYMBOL_KIND_OTHER;
 
       symtab->add_index_entry (name, (entry->flags & IS_STATIC) != 0,
 			       kind, it->second);
diff --git a/gdb/dwarf2/read-debug-names.c b/gdb/dwarf2/read-debug-names.c
index 0e9b1eb878f..d7709bb91cb 100644
--- a/gdb/dwarf2/read-debug-names.c
+++ b/gdb/dwarf2/read-debug-names.c
@@ -20,6 +20,7 @@
 #include "defs.h"
 #include "read-debug-names.h"
 #include "dwarf2/aranges.h"
+#include "dwarf2/tag.h"
 
 #include "complaints.h"
 #include "cp-support.h"
@@ -828,38 +829,13 @@ dw2_debug_names_iterator::next ()
 	}
     }
 
-  domain_enum domain = UNDEF_DOMAIN;
-  switch (indexval.dwarf_tag)
-    {
-    case DW_TAG_variable:
-      domain = VAR_DOMAIN;
-      break;
-
-    case DW_TAG_subprogram:
-      domain = FUNCTION_DOMAIN;
-      break;
-
-    case DW_TAG_structure_type:
-    case DW_TAG_union_type:
-    case DW_TAG_enumeration_type:
-      domain = STRUCT_DOMAIN;
-      break;
-
-    case DW_TAG_typedef:
-      domain = TYPE_DOMAIN;
-      break;
-
-    case DW_TAG_label:
-      domain = LABEL_DOMAIN;
-      break;
-
-    case DW_TAG_module:
-      domain = MODULE_DOMAIN;
-      break;
-    }
-
-  domain_search_flags flags = to_search_flags (domain);
-  if ((flags & m_search) == 0)
+  /* We have to use language_cplus here, first because the CU's
+     language isn't set yet, and then second because C++ is the main
+     special case, and so this choice will match a superset of other
+     languages.  This hack can go away once the .debug_names writer is
+     fixed to be more corrects.  */
+  if (!tag_matches_domain ((dwarf_tag) indexval.dwarf_tag, m_search,
+			   language_cplus))
     goto again;
 
   return per_cu;
diff --git a/gdb/dwarf2/read-gdb-index.c b/gdb/dwarf2/read-gdb-index.c
index d4741166e61..bf4f828b007 100644
--- a/gdb/dwarf2/read-gdb-index.c
+++ b/gdb/dwarf2/read-gdb-index.c
@@ -236,7 +236,7 @@ dw2_expand_marked_cus
 	      mask = SEARCH_FUNCTION_DOMAIN;
 	      break;
 	    case GDB_INDEX_SYMBOL_KIND_TYPE:
-	      mask = SEARCH_TYPE_DOMAIN;
+	      mask = SEARCH_TYPE_DOMAIN | SEARCH_STRUCT_DOMAIN;
 	      break;
 	    case GDB_INDEX_SYMBOL_KIND_OTHER:
 	      mask = SEARCH_MODULE_DOMAIN;
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index 877918999b8..24459a0d166 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -5780,9 +5780,7 @@ fixup_go_packaging (struct dwarf2_cu *cu)
       sym = new (&objfile->objfile_obstack) symbol;
       sym->set_language (language_go, &objfile->objfile_obstack);
       sym->compute_and_set_names (saved_package_name, false, objfile->per_bfd);
-      /* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
-	 e.g., "main" finds the "main" module and not C's main().  */
-      sym->set_domain (STRUCT_DOMAIN);
+      sym->set_domain (TYPE_DOMAIN);
       sym->set_aclass_index (LOC_TYPEDEF);
       sym->set_type (type);
 
@@ -19052,7 +19050,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 
       /* Default assumptions.
 	 Use the passed type or decode it from the die.  */
-      sym->set_domain (VAR_DOMAIN);
+      sym->set_domain (UNDEF_DOMAIN);
       sym->set_aclass_index (LOC_OPTIMIZED_OUT);
       if (type != NULL)
 	sym->set_type (type);
@@ -19104,6 +19102,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	case DW_TAG_entry_point:
 	  /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
 	     finish_block.  */
+	  sym->set_domain (FUNCTION_DOMAIN);
 	  sym->set_aclass_index (LOC_BLOCK);
 	  /* DW_TAG_entry_point provides an additional entry_point to an
 	     existing sub_program.  Therefore, we inherit the "external"
@@ -19118,6 +19117,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	case DW_TAG_subprogram:
 	  /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
 	     finish_block.  */
+	  sym->set_domain (FUNCTION_DOMAIN);
 	  sym->set_aclass_index (LOC_BLOCK);
 	  attr2 = dwarf2_attr (die, DW_AT_external, cu);
 	  if ((attr2 != nullptr && attr2->as_boolean ())
@@ -19162,6 +19162,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	case DW_TAG_inlined_subroutine:
 	  /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
 	     finish_block.  */
+	  sym->set_domain (FUNCTION_DOMAIN);
 	  sym->set_aclass_index (LOC_BLOCK);
 	  sym->set_is_inlined (1);
 	  list_to_add = cu->list_in_scope;
@@ -19172,6 +19173,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	case DW_TAG_constant:
 	case DW_TAG_variable:
 	case DW_TAG_member:
+	  sym->set_domain (VAR_DOMAIN);
 	  /* Compilation with minimal debug info may result in
 	     variables with missing type entries.  Change the
 	     misleading `void' type to something sensible.  */
@@ -19320,6 +19322,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	       when we do not have enough information to show inlined frames;
 	       pretend it's a local variable in that case so that the user can
 	       still see it.  */
+	    sym->set_domain (VAR_DOMAIN);
 	    struct context_stack *curr
 	      = cu->get_builder ()->get_current_context_stack ();
 	    if (curr != nullptr && curr->name != nullptr)
@@ -19358,11 +19361,25 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	      sym->set_aclass_index (LOC_STATIC);
 	      sym->set_domain (VAR_DOMAIN);
 	    }
-	  else
+	  else if (cu->lang () == language_c
+		   || cu->lang () == language_cplus
+		   || cu->lang () == language_objc
+		   || cu->lang () == language_opencl
+		   || cu->lang () == language_minimal)
 	    {
+	      /* These languages have a tag namespace.  Note that
+		 there's a special hack for C++ in the matching code,
+		 so we don't need to enter a separate typedef for the
+		 tag.  */
 	      sym->set_aclass_index (LOC_TYPEDEF);
 	      sym->set_domain (STRUCT_DOMAIN);
 	    }
+	  else
+	    {
+	      /* Other languages don't have a tag namespace.  */
+	      sym->set_aclass_index (LOC_TYPEDEF);
+	      sym->set_domain (TYPE_DOMAIN);
+	    }
 
 	  /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't
 	     really ever be static objects: otherwise, if you try
@@ -19406,10 +19423,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	case DW_TAG_subrange_type:
 	case DW_TAG_generic_subrange:
 	  sym->set_aclass_index (LOC_TYPEDEF);
-	  sym->set_domain (VAR_DOMAIN);
+	  sym->set_domain (TYPE_DOMAIN);
 	  list_to_add = cu->list_in_scope;
 	  break;
 	case DW_TAG_enumerator:
+	  sym->set_domain (VAR_DOMAIN);
 	  attr = dwarf2_attr (die, DW_AT_const_value, cu);
 	  if (attr != nullptr)
 	    {
@@ -19427,6 +19445,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	  break;
 	case DW_TAG_imported_declaration:
 	case DW_TAG_namespace:
+	  sym->set_domain (TYPE_DOMAIN);
 	  sym->set_aclass_index (LOC_TYPEDEF);
 	  list_to_add = cu->get_builder ()->get_global_symbols ();
 	  break;
diff --git a/gdb/dwarf2/tag.h b/gdb/dwarf2/tag.h
index 2fae4cced78..2ceae5393b5 100644
--- a/gdb/dwarf2/tag.h
+++ b/gdb/dwarf2/tag.h
@@ -21,6 +21,7 @@
 #define GDB_DWARF2_TAG_H
 
 #include "dwarf2.h"
+#include "symtab.h"
 
 /* Return true if TAG represents a type, false otherwise.  */
 
@@ -64,4 +65,82 @@ tag_is_type (dwarf_tag tag)
     }
 }
 
+/* Return true if the given DWARF tag matches the specified search
+   domain flags.  LANG may affect the result, due to the "C++ tag
+   hack".  */
+
+static inline bool
+tag_matches_domain (dwarf_tag tag, domain_search_flags search, language lang)
+{
+  domain_search_flags flags = 0;
+  switch (tag)
+    {
+    case DW_TAG_variable:
+    case DW_TAG_enumerator:
+    case DW_TAG_constant:
+      flags = SEARCH_VAR_DOMAIN;
+      break;
+
+    case DW_TAG_subprogram:
+    case DW_TAG_entry_point:
+      flags = SEARCH_FUNCTION_DOMAIN;
+      break;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_enumeration_type:
+      {
+	if (lang == language_c
+	    || lang == language_objc
+	    || lang == language_opencl
+	    || lang == language_minimal)
+	  flags = SEARCH_STRUCT_DOMAIN;
+	else if (lang == language_cplus)
+	  flags = SEARCH_STRUCT_DOMAIN | SEARCH_TYPE_DOMAIN;
+	else
+	  flags = SEARCH_TYPE_DOMAIN;
+      }
+      break;
+
+    case DW_TAG_padding:
+    case DW_TAG_array_type:
+    case DW_TAG_pointer_type:
+    case DW_TAG_reference_type:
+    case DW_TAG_string_type:
+    case DW_TAG_subroutine_type:
+    case DW_TAG_ptr_to_member_type:
+    case DW_TAG_set_type:
+    case DW_TAG_subrange_type:
+    case DW_TAG_base_type:
+    case DW_TAG_const_type:
+    case DW_TAG_packed_type:
+    case DW_TAG_template_type_param:
+    case DW_TAG_volatile_type:
+    case DW_TAG_restrict_type:
+    case DW_TAG_interface_type:
+    case DW_TAG_namespace:
+    case DW_TAG_unspecified_type:
+    case DW_TAG_shared_type:
+    case DW_TAG_rvalue_reference_type:
+    case DW_TAG_coarray_type:
+    case DW_TAG_dynamic_type:
+    case DW_TAG_atomic_type:
+    case DW_TAG_immutable_type:
+    case DW_TAG_typedef:
+      flags = SEARCH_TYPE_DOMAIN;
+      break;
+
+    case DW_TAG_label:
+      flags = SEARCH_LABEL_DOMAIN;
+      break;
+
+    case DW_TAG_module:
+      flags = SEARCH_MODULE_DOMAIN;
+      break;
+    }
+
+  return (flags & search) != 0;
+}
+
 #endif /* GDB_DWARF2_TAG_H */
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index f4eff650799..970a9e4a4a5 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -2988,15 +2988,19 @@ check_typedef (struct type *type)
 	    return make_qualified_type (type, instance_flags, NULL);
 
 	  name = type->name ();
-	  /* FIXME: shouldn't we look in STRUCT_DOMAIN and/or
-	     VAR_DOMAIN as appropriate?  */
 	  if (name == NULL)
 	    {
 	      stub_noname_complaint ();
 	      return make_qualified_type (type, instance_flags, NULL);
 	    }
-	  sym = lookup_symbol (name, nullptr, SEARCH_STRUCT_DOMAIN,
-			       nullptr).symbol;
+	  domain_search_flag flag
+	    = ((type->language () == language_c
+		|| type->language () == language_objc
+		|| type->language () == language_opencl
+		|| type->language () == language_minimal)
+	       ? SEARCH_STRUCT_DOMAIN
+	       : SEARCH_TYPE_DOMAIN);
+	  sym = lookup_symbol (name, nullptr, flag, nullptr).symbol;
 	  if (sym)
 	    type->set_target_type (sym->type ());
 	  else					/* TYPE_CODE_UNDEF */
@@ -3077,8 +3081,6 @@ check_typedef (struct type *type)
   else if (type->is_stub () && !currently_reading_symtab)
     {
       const char *name = type->name ();
-      /* FIXME: shouldn't we look in STRUCT_DOMAIN and/or VAR_DOMAIN
-	 as appropriate?  */
       struct symbol *sym;
 
       if (name == NULL)
@@ -3086,8 +3088,14 @@ check_typedef (struct type *type)
 	  stub_noname_complaint ();
 	  return make_qualified_type (type, instance_flags, NULL);
 	}
-      sym = lookup_symbol (name, nullptr, SEARCH_STRUCT_DOMAIN,
-			   nullptr).symbol;
+      domain_search_flag flag
+	= ((type->language () == language_c
+	    || type->language () == language_objc
+	    || type->language () == language_opencl
+	    || type->language () == language_minimal)
+	   ? SEARCH_STRUCT_DOMAIN
+	   : SEARCH_TYPE_DOMAIN);
+      sym = lookup_symbol (name, nullptr, flag, nullptr).symbol;
       if (sym)
 	{
 	  /* Same as above for opaque types, we can replace the stub
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index a3afbbb8514..2e56e4bff61 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -1293,7 +1293,7 @@ package_name_p (const char *name, const struct block *block)
   struct symbol *sym;
   struct field_of_this_result is_a_field_of_this;
 
-  sym = lookup_symbol (name, block, SEARCH_STRUCT_DOMAIN,
+  sym = lookup_symbol (name, block, SEARCH_TYPE_DOMAIN,
 		       &is_a_field_of_this).symbol;
 
   if (sym
diff --git a/gdb/jit.c b/gdb/jit.c
index 7960d32acd1..f1dbf39f73f 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -581,7 +581,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
       new_block->set_end (gdb_block_iter.end);
 
       /* The name.  */
-      block_name->set_domain (VAR_DOMAIN);
+      block_name->set_domain (FUNCTION_DOMAIN);
       block_name->set_aclass_index (LOC_BLOCK);
       block_name->set_symtab (filetab);
       block_name->set_type (lookup_function_type (block_type));
diff --git a/gdb/language.c b/gdb/language.c
index d6f6831c190..c5bbc319963 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -974,7 +974,7 @@ language_arch_info::type_and_symbol::alloc_type_symbol
   symbol->set_is_objfile_owned (0);
   symbol->set_section_index (0);
   symbol->set_type (type);
-  symbol->set_domain (VAR_DOMAIN);
+  symbol->set_domain (TYPE_DOMAIN);
   symbol->set_aclass_index (LOC_TYPEDEF);
   return symbol;
 }
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 13c9401d171..4748b0cd7aa 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -753,7 +753,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
 	  break;
 	}
       s = new_symbol (name);
-      s->set_domain (VAR_DOMAIN);
+      s->set_domain (FUNCTION_DOMAIN);
       s->set_aclass_index (LOC_BLOCK);
       s->set_section_index (section_index);
       /* Type of the return value.  */
@@ -1297,7 +1297,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
       if (has_opaque_xref (cur_fdr, sh))
 	break;
       s = new_symbol (name);
-      s->set_domain (VAR_DOMAIN);
+      s->set_domain (TYPE_DOMAIN);
       s->set_aclass_index (LOC_TYPEDEF);
       s->set_value_block (top_stack->cur_block);
       s->set_type (t);
diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c
index af1b76f738a..66263b91bdc 100644
--- a/gdb/rust-parse.c
+++ b/gdb/rust-parse.c
@@ -454,7 +454,7 @@ rust_parser::rust_lookup_type (const char *name)
   const struct block *block = pstate->expression_context_block;
   munge_name_and_block (&name, &block);
 
-  result = ::lookup_symbol (name, block, SEARCH_STRUCT_DOMAIN, NULL);
+  result = ::lookup_symbol (name, block, SEARCH_TYPE_DOMAIN, nullptr);
   if (result.symbol != NULL)
     {
       update_innermost_block (result);
diff --git a/gdb/stabsread.c b/gdb/stabsread.c
index 071290fbe12..025cb2120d1 100644
--- a/gdb/stabsread.c
+++ b/gdb/stabsread.c
@@ -940,7 +940,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
       /* A static function definition.  */
       sym->set_type (read_type (&p, objfile));
       sym->set_aclass_index (LOC_BLOCK);
-      sym->set_domain (VAR_DOMAIN);
+      sym->set_domain (FUNCTION_DOMAIN);
       add_symbol_to_list (sym, get_file_symbols ());
       /* fall into process_function_types.  */
 
@@ -1011,7 +1011,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
       /* A global function definition.  */
       sym->set_type (read_type (&p, objfile));
       sym->set_aclass_index (LOC_BLOCK);
-      sym->set_domain (VAR_DOMAIN);
+      sym->set_domain (FUNCTION_DOMAIN);
       add_symbol_to_list (sym, get_global_symbols ());
       goto process_function_types;
 
@@ -1209,7 +1209,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
 
       sym->set_aclass_index (LOC_TYPEDEF);
       sym->set_value_longest (valu);
-      sym->set_domain (VAR_DOMAIN);
+      sym->set_domain (TYPE_DOMAIN);
       /* C++ vagaries: we may have a type which is derived from
 	 a base type which did not have its name defined when the
 	 derived class was output.  We fill in the derived class's
@@ -1328,7 +1328,7 @@ define_symbol (CORE_ADDR valu, const char *string, int desc, int type,
 	  *typedef_sym = *sym;
 	  typedef_sym->set_aclass_index (LOC_TYPEDEF);
 	  typedef_sym->set_value_longest (valu);
-	  typedef_sym->set_domain (VAR_DOMAIN);
+	  typedef_sym->set_domain (TYPE_DOMAIN);
 	  if (sym->type ()->name () == 0)
 	    sym->type ()->set_name
 	      (obconcat (&objfile->objfile_obstack, sym->linkage_name (),
diff --git a/gdb/sym-domains.def b/gdb/sym-domains.def
index cea25a5f5b3..7545631063b 100644
--- a/gdb/sym-domains.def
+++ b/gdb/sym-domains.def
@@ -47,7 +47,9 @@ DOMAIN (LABEL)
 DOMAIN (COMMON_BLOCK)
 
 /* TYPE_DOMAIN is for types and typedefs.  Note that tags are not
-   found here, see STRUCT_DOMAIN above.  */
+   found here, see STRUCT_DOMAIN above.  If a language does not have a
+   tag namespace, then all types (including structures, etc) are
+   here.  */
 
 DOMAIN (TYPE)
 
diff --git a/gdb/symtab.c b/gdb/symtab.c
index b8588355921..30b12d6f4eb 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -2681,32 +2681,10 @@ lookup_global_symbol (const char *name,
 bool
 symbol::matches (domain_search_flags flags) const
 {
-  if (language () != language_c
-      && language () != language_objc
-      && language () != language_opencl)
-    {
-      /* Only C languages distinguish tag and type namespaces.  */
-      if ((flags & SEARCH_TYPE_DOMAIN) != 0)
-	flags |= SEARCH_STRUCT_DOMAIN;
-    }
-
-  if ((flags & SEARCH_FUNCTION_DOMAIN) != 0
-      && domain () == VAR_DOMAIN
-      && aclass () == LOC_BLOCK)
-    return true;
-
-  if ((flags & SEARCH_VAR_DOMAIN) != 0
-      && domain () == VAR_DOMAIN)
-    return true;
-
-  if ((flags & SEARCH_TYPE_DOMAIN) != 0
-      && domain () == VAR_DOMAIN
-      && aclass () == LOC_TYPEDEF)
-    return true;
-
-  if ((flags & SEARCH_STRUCT_DOMAIN) != 0
-      && domain () == STRUCT_DOMAIN)
-    return true;
+  /* C++ has a typedef for every tag, and the types are in the struct
+     domain.  */
+  if (language () == language_cplus && (flags & SEARCH_TYPE_DOMAIN) != 0)
+    flags |= SEARCH_STRUCT_DOMAIN;
 
   return search_flags_matches (flags, m_domain);
 }
@@ -4908,59 +4886,42 @@ global_symbol_searcher::add_matching_symbols
 					 filenames, false))))
 		continue;
 
+	      if (!sym->matches (kind))
+		continue;
+
 	      if (preg.has_value () && !preg->exec (sym->natural_name (), 0,
 						    nullptr, 0) == 0)
 		continue;
 
-	      bool matches = false;
-	      if (!matches && (kind & SEARCH_VAR_DOMAIN) != 0)
+	      if (((sym->domain () == VAR_DOMAIN
+		    || sym->domain () == FUNCTION_DOMAIN)
+		   && treg.has_value ()
+		   && !treg_matches_sym_type_name (*treg, sym)))
+		continue;
+
+	      if ((kind & SEARCH_VAR_DOMAIN) != 0)
 		{
-		  if (sym->aclass () != LOC_TYPEDEF
-		      && sym->aclass () != LOC_UNRESOLVED
-		      && sym->aclass () != LOC_BLOCK
+		  if (sym->aclass () == LOC_UNRESOLVED
 		      /* LOC_CONST can be used for more than
 			 just enums, e.g., c++ static const
 			 members.  We only want to skip enums
 			 here.  */
-		      && !(sym->aclass () == LOC_CONST
-			   && (sym->type ()->code ()
-			       == TYPE_CODE_ENUM))
-		      && (!treg.has_value ()
-			  || treg_matches_sym_type_name (*treg, sym)))
-		    matches = true;
-		}
-	      if (!matches && (kind & SEARCH_FUNCTION_DOMAIN) != 0)
-		{
-		  if (sym->aclass () == LOC_BLOCK
-		      && (!treg.has_value ()
-			  || treg_matches_sym_type_name (*treg,
-							 sym)))
-		    matches = true;
-		}
-	      if (!matches && (kind & SEARCH_TYPE_DOMAIN) != 0)
-		{
-		  if (sym->aclass () == LOC_TYPEDEF
-		      && sym->domain () != MODULE_DOMAIN)
-		    matches = true;
-		}
-	      if (!matches && (kind & SEARCH_MODULE_DOMAIN) != 0)
-		{
-		  if (sym->domain () == MODULE_DOMAIN
-		      && sym->line () != 0)
-		    matches = true;
+		      || (sym->aclass () == LOC_CONST
+			  && (sym->type ()->code () == TYPE_CODE_ENUM)))
+		    continue;
 		}
-	      if (matches)
+	      if (sym->domain () == MODULE_DOMAIN && sym->line () == 0)
+		continue;
+
+	      if (result_set->size () < m_max_search_results)
 		{
-		  if (result_set->size () < m_max_search_results)
-		    {
-		      /* Match, insert if not already in the results.  */
-		      symbol_search ss (block, sym);
-		      if (result_set->find (ss) == result_set->end ())
-			result_set->insert (ss);
-		    }
-		  else
-		    return false;
+		  /* Match, insert if not already in the results.  */
+		  symbol_search ss (block, sym);
+		  if (result_set->find (ss) == result_set->end ())
+		    result_set->insert (ss);
 		}
+	      else
+		return false;
 	    }
 	}
     }
@@ -5123,12 +5084,12 @@ symbol_to_info_string (struct symbol *sym, int block)
   gdb_assert (block == GLOBAL_BLOCK || block == STATIC_BLOCK);
 
   if (block == STATIC_BLOCK
-      && sym->domain () == VAR_DOMAIN
-      && sym->aclass () != LOC_TYPEDEF)
+      && (sym->domain () == VAR_DOMAIN
+	  || sym->domain () == FUNCTION_DOMAIN))
     str += "static ";
 
   /* Typedef that is not a C++ class.  */
-  if (sym->domain () == VAR_DOMAIN && sym->aclass () == LOC_TYPEDEF)
+  if (sym->domain () == TYPE_DOMAIN)
     {
       string_file tmp_stream;
 
@@ -5147,7 +5108,8 @@ symbol_to_info_string (struct symbol *sym, int block)
       str += tmp_stream.string ();
     }
   /* variable, func, or typedef-that-is-c++-class.  */
-  else if (sym->domain () == VAR_DOMAIN || sym->domain () == STRUCT_DOMAIN)
+  else if (sym->domain () == VAR_DOMAIN || sym->domain () == STRUCT_DOMAIN
+	   || sym->domain () == FUNCTION_DOMAIN)
     {
       string_file tmp_stream;
 
diff --git a/gdb/testsuite/gdb.ada/info_auto_lang.exp b/gdb/testsuite/gdb.ada/info_auto_lang.exp
index dc92659670b..cb2a5a7a172 100644
--- a/gdb/testsuite/gdb.ada/info_auto_lang.exp
+++ b/gdb/testsuite/gdb.ada/info_auto_lang.exp
@@ -65,8 +65,8 @@ set type_in_c(ada_syntax) [multi_line \
 			      "${decimal}:	record" \
 			      "    some_component_in_c: int;" \
 			      "end record" ]
-set type_in_ada(c_syntax) "${decimal}:	struct global_pack__some_type_in_ada;"
-set type_in_ada(ada_syntax)  "${decimal}:	global_pack.some_type_in_ada;"
+set type_in_ada(c_syntax) "${decimal}:	struct global_pack__some_type_in_ada"
+set type_in_ada(ada_syntax)  "${decimal}:	global_pack.some_type_in_ada"
 
 set var_in_c(c_syntax)     "${decimal}:	some_type_in_c some_struct_in_c;"
 set var_in_c(ada_syntax)   "${decimal}:	some_struct_in_c: some_type_in_c;"
diff --git a/gdb/testsuite/gdb.ada/ptype-o.exp b/gdb/testsuite/gdb.ada/ptype-o.exp
index 1a2817da6bc..f7782199d58 100644
--- a/gdb/testsuite/gdb.ada/ptype-o.exp
+++ b/gdb/testsuite/gdb.ada/ptype-o.exp
@@ -43,5 +43,5 @@ foreach_with_prefix scenario {all minimal} {
 	# crash.
 	set exp ".*"
     }
-    gdb_test "ptype/o struct prog__rec" $exp
+    gdb_test "ptype/o prog__rec" $exp
 }
diff --git a/gdb/testsuite/gdb.fortran/info-types.exp b/gdb/testsuite/gdb.fortran/info-types.exp
index ab1d8947729..52ce7ace89d 100644
--- a/gdb/testsuite/gdb.fortran/info-types.exp
+++ b/gdb/testsuite/gdb.fortran/info-types.exp
@@ -44,7 +44,7 @@ GDBInfoSymbols::check_header "All defined types:"
 GDBInfoSymbols::check_optional_entry "${srcfile}" "" "${character1}"
 GDBInfoSymbols::check_entry "${srcfile}" "" "${integer4}"
 GDBInfoSymbols::check_entry "${srcfile}" "" "${logical4}"
-GDBInfoSymbols::check_entry "${srcfile}" "$decimal" "Type m1t1;"
+GDBInfoSymbols::check_entry "${srcfile}" "$decimal" "Type m1t1"
 GDBInfoSymbols::check_entry "${srcfile}" "" "${real4}"
 
 # The emission of the 'Type s1' at global scope is actually not expected.  The
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index d161ad34c2f..589208cda68 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1491,6 +1491,7 @@ process_xcoff_symbol (struct xcoff_symbol *cs, struct objfile *objfile)
       sym->set_linkage_name (SYMNAME_ALLOC (name, symname_alloced));
       sym->set_type (builtin_type (objfile)->nodebug_text_symbol);
 
+      sym->set_domain (FUNCTION_DOMAIN);
       sym->set_aclass_index (LOC_BLOCK);
       sym2 = new (&objfile->objfile_obstack) symbol (*sym);
 
@@ -2546,7 +2547,7 @@ scan_xcoff_symtab (minimal_symbol_reader &reader,
 			/* Also a typedef with the same name.  */
 			pst->add_psymbol (std::string_view (namestring,
 							    p - namestring),
-					  true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+					  true, TYPE_DOMAIN, LOC_TYPEDEF, -1,
 					  psymbol_placement::STATIC,
 					  unrelocated_addr (0),
 					  psymtab_language,
@@ -2561,7 +2562,7 @@ scan_xcoff_symtab (minimal_symbol_reader &reader,
 		  {
 		    pst->add_psymbol (std::string_view (namestring,
 							p - namestring),
-				      true, VAR_DOMAIN, LOC_TYPEDEF, -1,
+				      true, TYPE_DOMAIN, LOC_TYPEDEF, -1,
 				      psymbol_placement::STATIC,
 				      unrelocated_addr (0),
 				      psymtab_language,
@@ -2661,7 +2662,7 @@ scan_xcoff_symtab (minimal_symbol_reader &reader,
 		  }
 		pst->add_psymbol (std::string_view (namestring,
 						    p - namestring),
-				  true, VAR_DOMAIN, LOC_BLOCK,
+				  true, FUNCTION_DOMAIN, LOC_BLOCK,
 				  SECT_OFF_TEXT (objfile),
 				  psymbol_placement::STATIC,
 				  unrelocated_addr (symbol.n_value),
@@ -2688,7 +2689,7 @@ scan_xcoff_symtab (minimal_symbol_reader &reader,
 
 		pst->add_psymbol (std::string_view (namestring,
 						    p - namestring),
-				  true, VAR_DOMAIN, LOC_BLOCK,
+				  true, FUNCTION_DOMAIN, LOC_BLOCK,
 				  SECT_OFF_TEXT (objfile),
 				  psymbol_placement::GLOBAL,
 				  unrelocated_addr (symbol.n_value),
