diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 280247b..b6eb382 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -14002,6 +14002,7 @@ extern const struct language_defn ada_language_defn = {
   c_watch_location_expression,
   ada_get_symbol_name_cmp,	/* la_get_symbol_name_cmp */
   ada_iterate_over_symbols,
+  default_search_name_hash,
   &ada_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index cbad027..94f2510 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -128,6 +128,9 @@ struct buildsym_compunit
 
   /* The compunit we are building.  */
   struct compunit_symtab *compunit_symtab;
+
+  /* Language of this compunit_symtab.  */
+  enum language language;
 };
 
 /* The work-in-progress of the compunit we are building.
@@ -351,20 +354,23 @@ finish_block_internal (struct symbol *symbol,
 
   if (symbol)
     {
-      BLOCK_DICT (block) = dict_create_linear (&objfile->objfile_obstack,
-					       *listhead);
+      BLOCK_DICT (block)
+	= dict_create_linear (&objfile->objfile_obstack,
+			      buildsym_compunit->language, *listhead);
     }
   else
     {
       if (expandable)
 	{
-	  BLOCK_DICT (block) = dict_create_hashed_expandable ();
+	  BLOCK_DICT (block)
+	    = dict_create_hashed_expandable (buildsym_compunit->language);
 	  dict_add_pending (BLOCK_DICT (block), *listhead);
 	}
       else
 	{
 	  BLOCK_DICT (block) =
-	    dict_create_hashed (&objfile->objfile_obstack, *listhead);
+	    dict_create_hashed (&objfile->objfile_obstack,
+				buildsym_compunit->language, *listhead);
 	}
     }
 
@@ -768,7 +774,8 @@ start_subfile (const char *name)
    (or NULL if not known).  */
 
 static struct buildsym_compunit *
-start_buildsym_compunit (struct objfile *objfile, const char *comp_dir)
+start_buildsym_compunit (struct objfile *objfile, const char *comp_dir,
+			 enum language language)
 {
   struct buildsym_compunit *bscu;
 
@@ -777,6 +784,7 @@ start_buildsym_compunit (struct objfile *objfile, const char *comp_dir)
 
   bscu->objfile = objfile;
   bscu->comp_dir = (comp_dir == NULL) ? NULL : xstrdup (comp_dir);
+  bscu->language = language;
 
   /* Initialize the debug format string to NULL.  We may supply it
      later via a call to record_debugformat.  */
@@ -1041,17 +1049,20 @@ prepare_for_building (const char *name, CORE_ADDR start_addr)
    TAG_compile_unit DIE is seen.  It indicates the start of data for
    one original source file.
 
-   NAME is the name of the file (cannot be NULL).  COMP_DIR is the directory in
-   which the file was compiled (or NULL if not known).  START_ADDR is the
-   lowest address of objects in the file (or 0 if not known).  */
+   NAME is the name of the file (cannot be NULL).  COMP_DIR is the
+   directory in which the file was compiled (or NULL if not known).
+   START_ADDR is the lowest address of objects in the file (or 0 if
+   not known).  LANGUAGE is the language of the source file, or
+   language_unknown if not known, in which case it'll be deduced from
+   the filename.  */
 
 struct compunit_symtab *
 start_symtab (struct objfile *objfile, const char *name, const char *comp_dir,
-	      CORE_ADDR start_addr)
+	      CORE_ADDR start_addr, enum language language)
 {
   prepare_for_building (name, start_addr);
 
-  buildsym_compunit = start_buildsym_compunit (objfile, comp_dir);
+  buildsym_compunit = start_buildsym_compunit (objfile, comp_dir, language);
 
   /* Allocate the compunit symtab now.  The caller needs it to allocate
      non-primary symtabs.  It is also needed by get_macro_table.  */
@@ -1088,7 +1099,8 @@ restart_symtab (struct compunit_symtab *cust,
   prepare_for_building (name, start_addr);
 
   buildsym_compunit = start_buildsym_compunit (COMPUNIT_OBJFILE (cust),
-					       COMPUNIT_DIRNAME (cust));
+					       COMPUNIT_DIRNAME (cust),
+					       compunit_language (cust));
   buildsym_compunit->compunit_symtab = cust;
 }
 
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index 60109a0..80ca7da 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -23,6 +23,7 @@ struct objfile;
 struct symbol;
 struct addrmap;
 struct compunit_symtab;
+enum language;
 
 /* This module provides definitions used for creating and adding to
    the symbol table.  These routines are called from various symbol-
@@ -254,7 +255,8 @@ extern record_line_ftype record_line;
 extern struct compunit_symtab *start_symtab (struct objfile *objfile,
 					     const char *name,
 					     const char *comp_dir,
-					     CORE_ADDR start_addr);
+					     CORE_ADDR start_addr,
+					     enum language language);
 
 extern void restart_symtab (struct compunit_symtab *cust,
 			    const char *name, CORE_ADDR start_addr);
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index f86e26e..9749935 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -871,6 +871,7 @@ extern const struct language_defn c_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &c_varobj_ops,
   c_get_compile_context,
   c_compute_program,
@@ -1015,6 +1016,7 @@ extern const struct language_defn cplus_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &cplus_varobj_ops,
   NULL,
   NULL,
@@ -1068,6 +1070,7 @@ extern const struct language_defn asm_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
@@ -1121,6 +1124,7 @@ extern const struct language_defn minimal_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/coffread.c b/gdb/coffread.c
index 9db4792..db0b77a 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -394,7 +394,9 @@ coff_start_symtab (struct objfile *objfile, const char *name)
 		 NULL,
   /* The start address is irrelevant, since we set
      last_source_start_addr in coff_end_symtab.  */
-		 0);
+		 0,
+  /* Let buildsym.c deduce the language for this symtab.  */
+		 language_unknown);
   record_debugformat ("COFF");
 }
 
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 941d3ed..b89b636 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -247,6 +247,7 @@ extern const struct language_defn d_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index daa3ce9..d48575b 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -54,7 +54,6 @@
 #include "cp-support.h"
 #include "psympriv.h"
 #include "block.h"
-
 #include "aout/aout64.h"
 #include "aout/stab_gnu.h"	/* We always use GNU stabs, not
 				   native, now.  */
@@ -92,6 +91,7 @@ struct symloc
     int symbol_offset;
     int string_offset;
     int file_string_offset;
+    enum language pst_language;
   };
 
 #define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
@@ -101,6 +101,7 @@ struct symloc
 #define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
 #define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
 #define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+#define PST_LANGUAGE(p) (SYMLOC(p)->pst_language)
 
 
 /* The objfile we are currently reading.  */
@@ -2017,6 +2018,7 @@ start_psymtab (struct objfile *objfile, const char *filename, CORE_ADDR textlow,
 
   /* Deduce the source language from the filename for this psymtab.  */
   psymtab_language = deduce_language_from_filename (filename);
+  PST_LANGUAGE (result) = psymtab_language;
 
   return result;
 }
@@ -2403,7 +2405,8 @@ read_ofile_symtab (struct objfile *objfile, struct partial_symtab *pst)
 		 positive offsets.  */
 	    nlist.n_value = (nlist.n_value ^ 0x80000000) - 0x80000000;
 	  process_one_symbol (type, nlist.n_desc, nlist.n_value,
-			      namestring, section_offsets, objfile);
+			      namestring, section_offsets, objfile,
+			      PST_LANGUAGE (pst));
 	}
       /* We skip checking for a new .o or -l file; that should never
          happen in this routine.  */
@@ -2498,12 +2501,14 @@ cp_set_block_scope (const struct symbol *symbol,
    the pst->section_offsets.  All symbols that refer to memory
    locations need to be offset by these amounts.
    OBJFILE is the object file from which we are reading symbols.  It
-   is used in end_symtab.  */
+   is used in end_symtab.
+   LANGUAGE is the language of the symtab.
+*/
 
 void
 process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 		    const struct section_offsets *section_offsets,
-		    struct objfile *objfile)
+		    struct objfile *objfile, enum language language)
 {
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
   struct context_stack *newobj;
@@ -2717,7 +2722,7 @@ process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
       function_start_offset = 0;
 
       start_stabs ();
-      start_symtab (objfile, name, NULL, valu);
+      start_symtab (objfile, name, NULL, valu, language);
       record_debugformat ("stabs");
       break;
 
diff --git a/gdb/dictionary.c b/gdb/dictionary.c
index b2cfca2..1ffa4f3 100644
--- a/gdb/dictionary.c
+++ b/gdb/dictionary.c
@@ -165,6 +165,7 @@ struct dictionary_linear_expandable
 
 struct dictionary
 {
+  const struct language_defn *language;
   const struct dict_vector *vector;
   union
   {
@@ -179,6 +180,7 @@ struct dictionary
 /* Accessor macros.  */
 
 #define DICT_VECTOR(d)			(d)->vector
+#define DICT_LANGUAGE(d)                (d)->language
 
 /* These can be used for DICT_HASHED_EXPANDABLE, too.  */
 
@@ -245,8 +247,6 @@ static struct symbol *iter_match_next_hashed (const char *name,
 					      symbol_compare_ftype *compare,
 					      struct dict_iterator *iterator);
 
-static unsigned int dict_hash (const char *string);
-
 /* Functions only for DICT_HASHED.  */
 
 static int size_hashed (const struct dictionary *dict);
@@ -348,12 +348,11 @@ static void expand_hashtable (struct dictionary *dict);
 
 /* The creation functions.  */
 
-/* Create a dictionary implemented via a fixed-size hashtable.  All
-   memory it uses is allocated on OBSTACK; the environment is
-   initialized from SYMBOL_LIST.  */
+/* See dictionary.h.  */
 
 struct dictionary *
 dict_create_hashed (struct obstack *obstack,
+		    enum language language,
 		    const struct pending *symbol_list)
 {
   struct dictionary *retval;
@@ -363,6 +362,7 @@ dict_create_hashed (struct obstack *obstack,
 
   retval = XOBNEW (obstack, struct dictionary);
   DICT_VECTOR (retval) = &dict_hashed_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
 
   /* Calculate the number of symbols, and allocate space for them.  */
   for (list_counter = symbol_list;
@@ -391,17 +391,15 @@ dict_create_hashed (struct obstack *obstack,
   return retval;
 }
 
-/* Create a dictionary implemented via a hashtable that grows as
-   necessary.  The dictionary is initially empty; to add symbols to
-   it, call dict_add_symbol().  Call dict_free() when you're done with
-   it.  */
+/* See dictionary.h.  */
 
 extern struct dictionary *
-dict_create_hashed_expandable (void)
+dict_create_hashed_expandable (enum language language)
 {
   struct dictionary *retval = XNEW (struct dictionary);
 
   DICT_VECTOR (retval) = &dict_hashed_expandable_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
   DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
   DICT_HASHED_BUCKETS (retval) = XCNEWVEC (struct symbol *,
 					   DICT_EXPANDABLE_INITIAL_CAPACITY);
@@ -410,13 +408,11 @@ dict_create_hashed_expandable (void)
   return retval;
 }
 
-/* Create a dictionary implemented via a fixed-size array.  All memory
-   it uses is allocated on OBSTACK; the environment is initialized
-   from the SYMBOL_LIST.  The symbols are ordered in the same order
-   that they're found in SYMBOL_LIST.  */
+/* See dictionary.h.  */
 
 struct dictionary *
 dict_create_linear (struct obstack *obstack,
+		    enum language language,
 		    const struct pending *symbol_list)
 {
   struct dictionary *retval;
@@ -426,6 +422,7 @@ dict_create_linear (struct obstack *obstack,
 
   retval = XOBNEW (obstack, struct dictionary);
   DICT_VECTOR (retval) = &dict_linear_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
 
   /* Calculate the number of symbols, and allocate space for them.  */
   for (list_counter = symbol_list;
@@ -455,17 +452,15 @@ dict_create_linear (struct obstack *obstack,
   return retval;
 }
 
-/* Create a dictionary implemented via an array that grows as
-   necessary.  The dictionary is initially empty; to add symbols to
-   it, call dict_add_symbol().  Call dict_free() when you're done with
-   it.  */
+/* See dictionary.h.  */
 
 struct dictionary *
-dict_create_linear_expandable (void)
+dict_create_linear_expandable (enum language language)
 {
   struct dictionary *retval = XNEW (struct dictionary);
 
   DICT_VECTOR (retval) = &dict_linear_expandable_vector;
+  DICT_LANGUAGE (retval) = language_def (language);
   DICT_LINEAR_NSYMS (retval) = 0;
   DICT_LINEAR_EXPANDABLE_CAPACITY (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
   DICT_LINEAR_SYMS (retval)
@@ -638,7 +633,9 @@ iter_match_first_hashed (const struct dictionary *dict, const char *name,
 			 symbol_compare_ftype *compare,
 			 struct dict_iterator *iterator)
 {
-  unsigned int hash_index = dict_hash (name) % DICT_HASHED_NBUCKETS (dict);
+  unsigned int hash_index
+    = (search_name_hash (DICT_LANGUAGE (dict)->la_language, name)
+       % DICT_HASHED_NBUCKETS (dict));
   struct symbol *sym;
 
   DICT_ITERATOR_DICT (iterator) = dict;
@@ -689,10 +686,15 @@ insert_symbol_hashed (struct dictionary *dict,
 		      struct symbol *sym)
 {
   unsigned int hash_index;
+  unsigned int hash;
   struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
 
-  hash_index = 
-    dict_hash (SYMBOL_SEARCH_NAME (sym)) % DICT_HASHED_NBUCKETS (dict);
+  /* We don't want to insert a symbol into a dictionary of a different
+     language.  The two may not use the same hashing algorithm.  */
+  gdb_assert (SYMBOL_LANGUAGE (sym) == DICT_LANGUAGE (dict)->la_language);
+
+  hash = search_name_hash (SYMBOL_LANGUAGE (sym), SYMBOL_SEARCH_NAME (sym));
+  hash_index = hash % DICT_HASHED_NBUCKETS (dict);
   sym->hash_next = buckets[hash_index];
   buckets[hash_index] = sym;
 }
@@ -765,13 +767,10 @@ expand_hashtable (struct dictionary *dict)
   xfree (old_buckets);
 }
 
-/* Produce an unsigned hash value from STRING0 that is consistent
-   with strcmp_iw, strcmp, and, at least on Ada symbols, wild_match.
-   That is, two identifiers equivalent according to any of those three
-   comparison operators hash to the same value.  */
+/* See dictionary.h.  */
 
-static unsigned int
-dict_hash (const char *string0)
+unsigned int
+default_search_name_hash (const char *string0)
 {
   /* The Ada-encoded version of a name P1.P2...Pn has either the form
      P1__P2__...Pn<suffix> or _ada_P1__P2__...Pn<suffix> (where the Pi
diff --git a/gdb/dictionary.h b/gdb/dictionary.h
index 4f4f160..e4a9315 100644
--- a/gdb/dictionary.h
+++ b/gdb/dictionary.h
@@ -35,42 +35,46 @@ struct dictionary;
 struct symbol;
 struct obstack;
 struct pending;
-
+struct language_defn;
 
 /* The creation functions for various implementations of
    dictionaries.  */
 
-/* Create a dictionary implemented via a fixed-size hashtable.  All
-   memory it uses is allocated on OBSTACK; the environment is
-   initialized from SYMBOL_LIST.  */
+/* Create a dictionary of symbols of language LANGUAGE implemented via
+   a fixed-size hashtable.  All memory it uses is allocated on
+   OBSTACK; the environment is initialized from SYMBOL_LIST.  */
 
 extern struct dictionary *dict_create_hashed (struct obstack *obstack,
+					      enum language language,
 					      const struct pending
 					      *symbol_list);
 
-/* Create a dictionary implemented via a hashtable that grows as
-   necessary.  The dictionary is initially empty; to add symbols to
-   it, call dict_add_symbol().  Call dict_free() when you're done with
-   it.  */
+/* Create a dictionary of symbols of language LANGUAGE, implemented
+   via a hashtable that grows as necessary.  The dictionary is
+   initially empty; to add symbols to it, call dict_add_symbol().
+   Call dict_free() when you're done with it.  */
 
-extern struct dictionary *dict_create_hashed_expandable (void);
+extern struct dictionary *
+  dict_create_hashed_expandable (enum language language);
 
-/* Create a dictionary implemented via a fixed-size array.  All memory
-   it uses is allocated on OBSTACK; the environment is initialized
-   from the SYMBOL_LIST.  The symbols are ordered in the same order
-   that they're found in SYMBOL_LIST.  */
+/* Create a dictionary of symbols of language LANGUAGE, implemented
+   via a fixed-size array.  All memory it uses is allocated on
+   OBSTACK; the environment is initialized from the SYMBOL_LIST.  The
+   symbols are ordered in the same order that they're found in
+   SYMBOL_LIST.  */
 
 extern struct dictionary *dict_create_linear (struct obstack *obstack,
+					      enum language language,
 					      const struct pending
 					      *symbol_list);
 
-/* Create a dictionary implemented via an array that grows as
-   necessary.  The dictionary is initially empty; to add symbols to
-   it, call dict_add_symbol().  Call dict_free() when you're done with
-   it.  */
-
-extern struct dictionary *dict_create_linear_expandable (void);
+/* Create a dictionary of symbols of language LANGUAGE, implemented
+   via an array that grows as necessary.  The dictionary is initially
+   empty; to add symbols to it, call dict_add_symbol().  Call
+   dict_free() when you're done with it.  */
 
+extern struct dictionary *
+  dict_create_linear_expandable (enum language language);
 
 /* The functions providing the interface to dictionaries.  Note that
    the most common parts of the interface, namely symbol lookup, are
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2c2ecda..3c547c1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -18874,7 +18874,7 @@ dwarf2_start_symtab (struct dwarf2_cu *cu,
 		     const char *name, const char *comp_dir, CORE_ADDR low_pc)
 {
   struct compunit_symtab *cust
-    = start_symtab (cu->objfile, name, comp_dir, low_pc);
+    = start_symtab (cu->objfile, name, comp_dir, low_pc, cu->language);
 
   record_debugformat ("DWARF 2");
   record_producer (cu->producer);
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 903cfd1..cfef64f 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -293,6 +293,7 @@ extern const struct language_defn f_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/go-lang.c b/gdb/go-lang.c
index 60bb3c5..befd937 100644
--- a/gdb/go-lang.c
+++ b/gdb/go-lang.c
@@ -608,6 +608,7 @@ extern const struct language_defn go_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/jit.c b/gdb/jit.c
index ddf1005..c30a06a 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -661,12 +661,14 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
   size_t blockvector_size;
   CORE_ADDR begin, end;
   struct blockvector *bv;
+  enum language language;
 
   actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
 
   cust = allocate_compunit_symtab (objfile, stab->file_name);
   allocate_symtab (cust, stab->file_name);
   add_compunit_symtab_to_objfile (cust);
+  language = compunit_language (cust);
 
   /* JIT compilers compile in memory.  */
   COMPUNIT_DIRNAME (cust) = NULL;
@@ -711,7 +713,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
 					   "void");
 
       BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
-                                                   NULL);
+						   language, NULL);
       /* The address range.  */
       BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
       BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
@@ -749,7 +751,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
 		   ? allocate_global_block (&objfile->objfile_obstack)
 		   : allocate_block (&objfile->objfile_obstack));
       BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
-                                                   NULL);
+						   language, NULL);
       BLOCK_SUPERBLOCK (new_block) = block_iter;
       block_iter = new_block;
 
diff --git a/gdb/language.c b/gdb/language.c
index 073039e..8f52b73 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -843,6 +843,7 @@ const struct language_defn unknown_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
@@ -893,6 +894,7 @@ const struct language_defn auto_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/language.h b/gdb/language.h
index f4852c1..cc8ec46 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -392,6 +392,11 @@ struct language_defn
       (const struct block *block, const char *name, domain_enum domain,
        gdb::function_view<symbol_found_callback_ftype> callback);
 
+    /* Hash the given symbol search name.  Use
+       default_search_name_hash if no special treatment is
+       required.  */
+    unsigned int (*la_search_name_hash) (const char *name);
+
     /* Various operations on varobj.  */
     const struct lang_varobj_ops *la_varobj_ops;
 
@@ -611,6 +616,14 @@ void default_print_typedef (struct type *type, struct symbol *new_symbol,
 void default_get_string (struct value *value, gdb_byte **buffer, int *length,
 			 struct type **char_type, const char **charset);
 
+/* Default name hashing function.  */
+
+/* Produce an unsigned hash value from SEARCH_NAME that is consistent
+   with strcmp_iw, strcmp, and, at least on Ada symbols, wild_match.
+   That is, two identifiers equivalent according to any of those three
+   comparison operators hash to the same value.  */
+extern unsigned int default_search_name_hash (const char *search_name);
+
 void c_get_string (struct value *value, gdb_byte **buffer, int *length,
 		   struct type **char_type, const char **charset);
 
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index b9ab2b3..66ac34c 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -396,6 +396,7 @@ extern const struct language_defn m2_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index 8e27194..fa5c14b 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -236,7 +236,7 @@ static struct type *new_type (char *);
 
 enum block_type { FUNCTION_BLOCK, NON_FUNCTION_BLOCK };
 
-static struct block *new_block (enum block_type);
+static struct block *new_block (enum block_type, enum language);
 
 static struct compunit_symtab *new_symtab (const char *, int, struct objfile *);
 
@@ -811,7 +811,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
 	TYPE_PROTOTYPED (SYMBOL_TYPE (s)) = 1;
 
       /* Create and enter a new lexical context.  */
-      b = new_block (FUNCTION_BLOCK);
+      b = new_block (FUNCTION_BLOCK, SYMBOL_LANGUAGE (s));
       SYMBOL_BLOCK_VALUE (s) = b;
       BLOCK_FUNCTION (b) = s;
       BLOCK_START (b) = BLOCK_END (b) = sh->value;
@@ -1144,7 +1144,7 @@ parse_symbol (SYMR *sh, union aux_ext *ax, char *ext_sh, int bigend,
 	}
 
       top_stack->blocktype = stBlock;
-      b = new_block (NON_FUNCTION_BLOCK);
+      b = new_block (NON_FUNCTION_BLOCK, psymtab_language);
       BLOCK_START (b) = sh->value + top_stack->procadr;
       BLOCK_SUPERBLOCK (b) = top_stack->cur_block;
       top_stack->cur_block = b;
@@ -4026,6 +4026,7 @@ psymtab_to_symtab_1 (struct objfile *objfile,
 	  if (ECOFF_IS_STAB (&sh) || (name[0] == '#'))
 	    {
 	      int type_code = ECOFF_UNMARK_STAB (sh.index);
+	      enum language language = PST_PRIVATE (pst)->pst_language;
 
 	      /* We should never get non N_STAB symbols here, but they
 	         should be harmless, so keep process_one_symbol from
@@ -4053,14 +4054,14 @@ psymtab_to_symtab_1 (struct objfile *objfile,
 		    {
 		      last_symtab_ended = 0;
 		      process_one_symbol (type_code, 0, valu, name,
-					  section_offsets, objfile);
+					  section_offsets, objfile, language);
 		    }
 		}
 	      /* Similarly a hack.  */
 	      else if (name[0] == '#')
 		{
 		  process_one_symbol (N_SLINE, 0, valu, name,
-				      section_offsets, objfile);
+				      section_offsets, objfile, language);
 		}
 	      if (type_code == N_FUN)
 		{
@@ -4721,16 +4722,18 @@ new_symtab (const char *name, int maxlines, struct objfile *objfile)
   struct compunit_symtab *cust = allocate_compunit_symtab (objfile, name);
   struct symtab *symtab;
   struct blockvector *bv;
+  enum language lang;
 
   add_compunit_symtab_to_objfile (cust);
   symtab = allocate_symtab (cust, name);
 
   SYMTAB_LINETABLE (symtab) = new_linetable (maxlines);
+  lang = compunit_language (cust);
 
   /* All symtabs must have at least two blocks.  */
   bv = new_bvect (2);
-  BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK);
-  BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK);
+  BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
+  BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
   BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) =
     BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
   COMPUNIT_BLOCKVECTOR (cust) = bv;
@@ -4812,13 +4815,13 @@ new_bvect (int nblocks)
   return bv;
 }
 
-/* Allocate and zero a new block, and set its BLOCK_DICT.  If function
-   is non-zero, assume the block is associated to a function, and make
-   sure that the symbols are stored linearly; otherwise, store them
-   hashed.  */
+/* Allocate and zero a new block of language LANGUAGE, and set its
+   BLOCK_DICT.  If function is non-zero, assume the block is
+   associated to a function, and make sure that the symbols are stored
+   linearly; otherwise, store them hashed.  */
 
 static struct block *
-new_block (enum block_type type)
+new_block (enum block_type type, enum language language)
 {
   /* FIXME: carlton/2003-09-11: This should use allocate_block to
      allocate the block.  Which, in turn, suggests that the block
@@ -4826,9 +4829,9 @@ new_block (enum block_type type)
   struct block *retval = XCNEW (struct block);
 
   if (type == FUNCTION_BLOCK)
-    BLOCK_DICT (retval) = dict_create_linear_expandable ();
+    BLOCK_DICT (retval) = dict_create_linear_expandable (language);
   else
-    BLOCK_DICT (retval) = dict_create_hashed_expandable ();
+    BLOCK_DICT (retval) = dict_create_hashed_expandable (language);
 
   return retval;
 }
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 6ffe85e..4dbc7f2 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -405,6 +405,7 @@ extern const struct language_defn objc_language_defn = {
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 9b0f015..e5aff0d 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1085,6 +1085,7 @@ extern const struct language_defn opencl_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 439a377..2dca923 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -456,6 +456,7 @@ extern const struct language_defn pascal_language_defn =
   c_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c
index 817976a..f0d9968 100644
--- a/gdb/rust-lang.c
+++ b/gdb/rust-lang.c
@@ -2190,6 +2190,7 @@ extern const struct language_defn rust_language_defn =
   rust_watch_location_expression,
   NULL,				/* la_get_symbol_name_cmp */
   iterate_over_symbols,
+  default_search_name_hash,
   &default_varobj_ops,
   NULL,
   NULL,
diff --git a/gdb/stabsread.h b/gdb/stabsread.h
index b37be1a..b803cf9 100644
--- a/gdb/stabsread.h
+++ b/gdb/stabsread.h
@@ -17,6 +17,7 @@
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 struct objfile;
+enum language;
 
 /* Definitions, prototypes, etc for stabs debugging format support
    functions.
@@ -169,7 +170,7 @@ extern struct partial_symtab *dbx_end_psymtab
 
 extern void process_one_symbol (int, int, CORE_ADDR, const char *,
 				const struct section_offsets *,
-				struct objfile *);
+				struct objfile *, enum language);
 
 extern void elfstab_build_psymtabs (struct objfile *objfile,
 				    asection *stabsect,
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d4e107a..ba2c559 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1803,6 +1803,14 @@ demangle_for_lookup (const char *name, enum language lang,
   return name;
 }
 
+/* See symtab.h.  */
+
+unsigned int
+search_name_hash (enum language language, const char *search_name)
+{
+  return language_def (language)->la_search_name_hash (search_name);
+}
+
 /* See symtab.h.
 
    This function (or rather its subordinates) have a bunch of loops and
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 35949f0..da5cf25 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -277,6 +277,11 @@ extern const char *symbol_search_name (const struct general_symbol_info *);
 #define SYMBOL_MATCHES_SEARCH_NAME(symbol, name)			\
   (strcmp_iw (SYMBOL_SEARCH_NAME (symbol), (name)) == 0)
 
+/* Compute the hash of the given symbol search name of a symbol of
+   language LANGUAGE.  */
+extern unsigned int search_name_hash (enum language language,
+				      const char *search_name);
+
 /* Classification types for a minimal symbol.  These should be taken as
    "advisory only", since if gdb can't easily figure out a
    classification it simply selects mst_unknown.  It may also have to
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 138f941..0d6f290 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -1044,7 +1044,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
   last_csect_name = 0;
 
   start_stabs ();
-  start_symtab (objfile, filestring, (char *) NULL, file_start_addr);
+  start_symtab (objfile, filestring, (char *) NULL, file_start_addr,
+		language_unknown);
   record_debugformat (debugfmt);
   symnum = ((struct symloc *) pst->read_symtab_private)->first_symnum;
   max_symnum =
@@ -1137,7 +1138,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
 	    }
 
 	  start_stabs ();
-	  start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0);
+	  start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0,
+			language_unknown);
 	  record_debugformat (debugfmt);
 	  cur_src_end_addr = first_object_file_end;
 	  /* Done with all files, everything from here on is globals.  */
@@ -1227,7 +1229,7 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
 			  /* Give all csects for this source file the same
 			     name.  */
 			  start_symtab (objfile, filestring, NULL,
-					(CORE_ADDR) 0);
+					(CORE_ADDR) 0, language_unknown);
 			  record_debugformat (debugfmt);
 			}
 
@@ -1347,7 +1349,8 @@ read_xcoff_symtab (struct objfile *objfile, struct partial_symtab *pst)
 	    filestring = cs->c_name;
 
 	  start_stabs ();
-	  start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0);
+	  start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0,
+			language_unknown);
 	  record_debugformat (debugfmt);
 	  last_csect_name = 0;
 
