Change symbol_set_names to take an objfile_per_bfd_storage
[deliverable/binutils-gdb.git] / gdb / symtab.c
index 16a6b2eb6f3f5a38f0b92ea433782a798d6e5e2c..d5e18a64d06c12d1153d2b8cb5fbb8ea4470a802 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
 
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -43,6 +43,7 @@
 #include "cli/cli-utils.h"
 #include "fnmatch.h"
 #include "hashtab.h"
+#include "typeprint.h"
 
 #include "gdb_obstack.h"
 #include "block.h"
@@ -54,7 +55,7 @@
 #include <ctype.h>
 #include "cp-abi.h"
 #include "cp-support.h"
-#include "observer.h"
+#include "observable.h"
 #include "solist.h"
 #include "macrotab.h"
 #include "macroscope.h"
 #include "filename-seen-cache.h"
 #include "arch-utils.h"
 #include <algorithm>
+#include "common/pathstuff.h"
 
 /* Forward declarations for local functions.  */
 
-static void rbreak_command (char *, int);
+static void rbreak_command (const char *, int);
 
 static int find_line_common (struct linetable *, int, int *, int);
 
 static struct block_symbol
   lookup_symbol_aux (const char *name,
+                    symbol_name_match_type match_type,
                     const struct block *block,
                     const domain_enum domain,
                     enum language language,
@@ -82,6 +85,7 @@ static struct block_symbol
 
 static
 struct block_symbol lookup_local_symbol (const char *name,
+                                        symbol_name_match_type match_type,
                                         const struct block *block,
                                         const domain_enum domain,
                                         enum language language);
@@ -401,12 +405,11 @@ iterate_over_some_symtabs (const char *name,
                           gdb::function_view<bool (symtab *)> callback)
 {
   struct compunit_symtab *cust;
-  struct symtab *s;
   const char* base_name = lbasename (name);
 
   for (cust = first; cust != NULL && cust != after_last; cust = cust->next)
     {
-      ALL_COMPUNIT_FILETABS (cust, s)
+      for (symtab *s : compunit_filetabs (cust))
        {
          if (compare_filenames_for_search (s->filename, name))
            {
@@ -460,7 +463,6 @@ void
 iterate_over_symtabs (const char *name,
                      gdb::function_view<bool (symtab *)> callback)
 {
-  struct objfile *objfile;
   gdb::unique_xmalloc_ptr<char> real_path;
 
   /* Here we are interested in canonicalizing an absolute path, not
@@ -471,7 +473,7 @@ iterate_over_symtabs (const char *name,
       gdb_assert (IS_ABSOLUTE_PATH (real_path.get ()));
     }
 
-  ALL_OBJFILES (objfile)
+  for (objfile *objfile : all_objfiles (current_program_space))
     {
       if (iterate_over_some_symtabs (name, real_path.get (),
                                     objfile->compunit_symtabs, NULL,
@@ -482,7 +484,7 @@ iterate_over_symtabs (const char *name,
   /* Same search rules as above apply here, but now we look thru the
      psymtabs.  */
 
-  ALL_OBJFILES (objfile)
+  for (objfile *objfile : all_objfiles (current_program_space))
     {
       if (objfile->sf
          && objfile->sf->qf->map_symtabs_matching_filename (objfile,
@@ -525,7 +527,7 @@ gdb_mangle_name (struct type *type, int method_id, int signature_id)
   struct fn_field *method = &f[signature_id];
   const char *field_name = TYPE_FN_FIELDLIST_NAME (type, method_id);
   const char *physname = TYPE_FN_FIELD_PHYSNAME (f, signature_id);
-  const char *newname = type_name_no_tag (type);
+  const char *newname = TYPE_NAME (type);
 
   /* Does the form of physname indicate that it is the full mangled name
      of a constructor (not just the args)?  */
@@ -705,14 +707,14 @@ eq_demangled_name_entry (const void *a, const void *b)
    name.  The entry is hashed via just the mangled name.  */
 
 static void
-create_demangled_names_hash (struct objfile *objfile)
+create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
 {
   /* Choose 256 as the starting size of the hash table, somewhat arbitrarily.
      The hash table code will round this up to the next prime number.
      Choosing a much larger table size wastes memory, and saves only about
      1% in symbol reading.  */
 
-  objfile->per_bfd->demangled_names_hash = htab_create_alloc
+  per_bfd->demangled_names_hash = htab_create_alloc
     (256, hash_demangled_name_entry, eq_demangled_name_entry,
      NULL, xcalloc, xfree);
 }
@@ -729,7 +731,6 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 {
   char *demangled = NULL;
   int i;
-  int recognized;
 
   if (gsymbol->language == language_unknown)
     gsymbol->language = language_auto;
@@ -771,13 +772,12 @@ symbol_find_demangled_name (struct general_symbol_info *gsymbol,
 void
 symbol_set_names (struct general_symbol_info *gsymbol,
                  const char *linkage_name, int len, int copy_name,
-                 struct objfile *objfile)
+                 struct objfile_per_bfd_storage *per_bfd)
 {
   struct demangled_name_entry **slot;
   /* A 0-terminated copy of the linkage name.  */
   const char *linkage_name_copy;
   struct demangled_name_entry entry;
-  struct objfile_per_bfd_storage *per_bfd = objfile->per_bfd;
 
   if (gsymbol->language == language_ada)
     {
@@ -800,7 +800,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
     }
 
   if (per_bfd->demangled_names_hash == NULL)
-    create_demangled_names_hash (objfile);
+    create_demangled_names_hash (per_bfd);
 
   if (linkage_name[len] != '\0')
     {
@@ -815,6 +815,11 @@ symbol_set_names (struct general_symbol_info *gsymbol,
   else
     linkage_name_copy = linkage_name;
 
+  /* Set the symbol language.  */
+  char *demangled_name_ptr
+    = symbol_find_demangled_name (gsymbol, linkage_name_copy);
+  gdb::unique_xmalloc_ptr<char> demangled_name (demangled_name_ptr);
+
   entry.mangled = linkage_name_copy;
   slot = ((struct demangled_name_entry **)
          htab_find_slot (per_bfd->demangled_names_hash,
@@ -827,9 +832,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
       || (gsymbol->language == language_go
          && (*slot)->demangled[0] == '\0'))
     {
-      char *demangled_name = symbol_find_demangled_name (gsymbol,
-                                                        linkage_name_copy);
-      int demangled_len = demangled_name ? strlen (demangled_name) : 0;
+      int demangled_len = demangled_name ? strlen (demangled_name.get ()) : 0;
 
       /* Suppose we have demangled_name==NULL, copy_name==0, and
         linkage_name_copy==linkage_name.  In this case, we already have the
@@ -867,10 +870,7 @@ symbol_set_names (struct general_symbol_info *gsymbol,
        }
 
       if (demangled_name != NULL)
-       {
-         strcpy ((*slot)->demangled, demangled_name);
-         xfree (demangled_name);
-       }
+       strcpy ((*slot)->demangled, demangled_name.get());
       else
        (*slot)->demangled[0] = '\0';
     }
@@ -946,6 +946,18 @@ symbol_search_name (const struct general_symbol_info *gsymbol)
   else
     return symbol_natural_name (gsymbol);
 }
+
+/* See symtab.h.  */
+
+bool
+symbol_matches_search_name (const struct general_symbol_info *gsymbol,
+                           const lookup_name_info &name)
+{
+  symbol_name_matcher_ftype *name_match
+    = get_symbol_name_matcher (language_def (gsymbol->language), name);
+  return name_match (symbol_search_name (gsymbol), name, NULL);
+}
+
 \f
 
 /* Return 1 if the two sections are the same, or if they could
@@ -998,9 +1010,12 @@ matching_obj_sections (struct obj_section *obj_first,
 
   /* Otherwise check that they are in corresponding objfiles.  */
 
-  ALL_OBJFILES (obj)
-    if (obj->obfd == first->owner)
-      break;
+  for (objfile *objfile : all_objfiles (current_program_space))
+    if (objfile->obfd == first->owner)
+      {
+       obj = objfile;
+       break;
+      }
   gdb_assert (obj != NULL);
 
   if (obj->separate_debug_objfile != NULL
@@ -1018,7 +1033,6 @@ matching_obj_sections (struct obj_section *obj_first,
 void
 expand_symtab_containing_pc (CORE_ADDR pc, struct obj_section *section)
 {
-  struct objfile *objfile;
   struct bound_minimal_symbol msymbol;
 
   /* If we know that this is not a text address, return failure.  This is
@@ -1033,16 +1047,16 @@ expand_symtab_containing_pc (CORE_ADDR pc, struct obj_section *section)
          || MSYMBOL_TYPE (msymbol.minsym) == mst_file_bss))
     return;
 
-  ALL_OBJFILES (objfile)
-  {
-    struct compunit_symtab *cust = NULL;
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      struct compunit_symtab *cust = NULL;
 
-    if (objfile->sf)
-      cust = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile, msymbol,
-                                                           pc, section, 0);
-    if (cust)
-      return;
-  }
+      if (objfile->sf)
+       cust = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile, msymbol,
+                                                             pc, section, 0);
+      if (cust)
+       return;
+    }
 }
 \f
 /* Hash function for the symbol cache.  */
@@ -1103,11 +1117,12 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
     }
   else if (slot_name != NULL && name != NULL)
     {
-      /* It's important that we use the same comparison that was done the
-        first time through.  If the slot records a found symbol, then this
-        means using strcmp_iw on SYMBOL_SEARCH_NAME.  See dictionary.c.
-        It also means using symbol_matches_domain for found symbols.
-        See block.c.
+      /* It's important that we use the same comparison that was done
+        the first time through.  If the slot records a found symbol,
+        then this means using the symbol name comparison function of
+        the symbol's language with SYMBOL_SEARCH_NAME.  See
+        dictionary.c.  It also means using symbol_matches_domain for
+        found symbols.  See block.c.
 
         If the slot records a not-found symbol, then require a precise match.
         We could still be lax with whitespace like strcmp_iw though.  */
@@ -1122,9 +1137,11 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
       else
        {
          struct symbol *sym = slot->value.found.symbol;
+         lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
 
-         if (strcmp_iw (slot_name, name) != 0)
+         if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
            return 0;
+
          if (!symbol_matches_domain (SYMBOL_LANGUAGE (sym),
                                      slot_domain, domain))
            return 0;
@@ -1256,7 +1273,7 @@ set_symbol_cache_size (unsigned int new_size)
 /* Called when symbol-cache-size is set.  */
 
 static void
-set_symbol_cache_size_handler (char *args, int from_tty,
+set_symbol_cache_size_handler (const char *args, int from_tty,
                               struct cmd_list_element *c)
 {
   if (new_symbol_cache_size > MAX_SYMBOL_CACHE_SIZE)
@@ -1729,7 +1746,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
       addr = SYMBOL_VALUE_ADDRESS (sym);
       break;
     case LOC_BLOCK:
-      addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+      addr = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
       break;
 
     default:
@@ -1743,6 +1760,48 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
   return sym;
 }
 
+/* See symtab.h.  */
+
+demangle_for_lookup_info::demangle_for_lookup_info
+  (const lookup_name_info &lookup_name, language lang)
+{
+  demangle_result_storage storage;
+
+  if (lookup_name.ignore_parameters () && lang == language_cplus)
+    {
+      gdb::unique_xmalloc_ptr<char> without_params
+       = cp_remove_params_if_any (lookup_name.name ().c_str (),
+                                  lookup_name.completion_mode ());
+
+      if (without_params != NULL)
+       {
+         if (lookup_name.match_type () != symbol_name_match_type::SEARCH_NAME)
+           m_demangled_name = demangle_for_lookup (without_params.get (),
+                                                   lang, storage);
+         return;
+       }
+    }
+
+  if (lookup_name.match_type () == symbol_name_match_type::SEARCH_NAME)
+    m_demangled_name = lookup_name.name ();
+  else
+    m_demangled_name = demangle_for_lookup (lookup_name.name ().c_str (),
+                                           lang, storage);
+}
+
+/* See symtab.h.  */
+
+const lookup_name_info &
+lookup_name_info::match_any ()
+{
+  /* Lookup any symbol that "" would complete.  I.e., this matches all
+     symbol names.  */
+  static const lookup_name_info lookup_name ({}, symbol_name_match_type::FULL,
+                                            true);
+
+  return lookup_name;
+}
+
 /* Compute the demangled form of NAME as used by the various symbol
    lookup functions.  The result can either be the input NAME
    directly, or a pointer to a buffer owned by the STORAGE object.
@@ -1795,6 +1854,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
@@ -1815,7 +1882,9 @@ lookup_symbol_in_language (const char *name, const struct block *block,
   demangle_result_storage storage;
   const char *modified_name = demangle_for_lookup (name, lang, storage);
 
-  return lookup_symbol_aux (modified_name, block, domain, lang,
+  return lookup_symbol_aux (modified_name,
+                           symbol_name_match_type::FULL,
+                           block, domain, lang,
                            is_a_field_of_this);
 }
 
@@ -1833,6 +1902,16 @@ lookup_symbol (const char *name, const struct block *block,
 
 /* See symtab.h.  */
 
+struct block_symbol
+lookup_symbol_search_name (const char *search_name, const struct block *block,
+                          domain_enum domain)
+{
+  return lookup_symbol_aux (search_name, symbol_name_match_type::SEARCH_NAME,
+                           block, domain, language_asm, NULL);
+}
+
+/* See symtab.h.  */
+
 struct block_symbol
 lookup_language_this (const struct language_defn *lang,
                      const struct block *block)
@@ -1854,7 +1933,9 @@ lookup_language_this (const struct language_defn *lang,
     {
       struct symbol *sym;
 
-      sym = block_lookup_symbol (block, lang->la_name_of_this, VAR_DOMAIN);
+      sym = block_lookup_symbol (block, lang->la_name_of_this,
+                                symbol_name_match_type::SEARCH_NAME,
+                                VAR_DOMAIN);
       if (sym != NULL)
        {
          if (symbol_lookup_debug > 1)
@@ -1925,7 +2006,8 @@ check_field (struct type *type, const char *name,
    (e.g., demangled name) of the symbol that we're looking for.  */
 
 static struct block_symbol
-lookup_symbol_aux (const char *name, const struct block *block,
+lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
+                  const struct block *block,
                   const domain_enum domain, enum language language,
                   struct field_of_this_result *is_a_field_of_this)
 {
@@ -1954,7 +2036,7 @@ lookup_symbol_aux (const char *name, const struct block *block,
   /* Search specified block and its superiors.  Don't search
      STATIC_BLOCK or GLOBAL_BLOCK.  */
 
-  result = lookup_local_symbol (name, block, domain, language);
+  result = lookup_local_symbol (name, match_type, block, domain, language);
   if (result.symbol != NULL)
     {
       if (symbol_lookup_debug)
@@ -2036,7 +2118,9 @@ lookup_symbol_aux (const char *name, const struct block *block,
    Don't search STATIC_BLOCK or GLOBAL_BLOCK.  */
 
 static struct block_symbol
-lookup_local_symbol (const char *name, const struct block *block,
+lookup_local_symbol (const char *name,
+                    symbol_name_match_type match_type,
+                    const struct block *block,
                     const domain_enum domain,
                     enum language language)
 {
@@ -2051,18 +2135,18 @@ lookup_local_symbol (const char *name, const struct block *block,
 
   while (block != static_block)
     {
-      sym = lookup_symbol_in_block (name, block, domain);
+      sym = lookup_symbol_in_block (name, match_type, block, domain);
       if (sym != NULL)
        return (struct block_symbol) {sym, block};
 
       if (language == language_cplus || language == language_fortran)
         {
-          struct block_symbol sym
+          struct block_symbol blocksym
            = cp_lookup_symbol_imports_or_template (scope, name, block,
                                                    domain);
 
-          if (sym.symbol != NULL)
-            return sym;
+          if (blocksym.symbol != NULL)
+            return blocksym;
         }
 
       if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block))
@@ -2080,23 +2164,23 @@ lookup_local_symbol (const char *name, const struct block *block,
 struct objfile *
 lookup_objfile_from_block (const struct block *block)
 {
-  struct objfile *obj;
-  struct compunit_symtab *cust;
-
   if (block == NULL)
     return NULL;
 
   block = block_global_block (block);
   /* Look through all blockvectors.  */
-  ALL_COMPUNITS (obj, cust)
-    if (block == BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust),
-                                   GLOBAL_BLOCK))
-      {
-       if (obj->separate_debug_objfile_backlink)
-         obj = obj->separate_debug_objfile_backlink;
+  for (objfile *obj : all_objfiles (current_program_space))
+    {
+      for (compunit_symtab *cust : objfile_compunits (obj))
+       if (block == BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust),
+                                       GLOBAL_BLOCK))
+         {
+           if (obj->separate_debug_objfile_backlink)
+             obj = obj->separate_debug_objfile_backlink;
 
-       return obj;
-      }
+           return obj;
+         }
+    }
 
   return NULL;
 }
@@ -2104,7 +2188,8 @@ lookup_objfile_from_block (const struct block *block)
 /* See symtab.h.  */
 
 struct symbol *
-lookup_symbol_in_block (const char *name, const struct block *block,
+lookup_symbol_in_block (const char *name, symbol_name_match_type match_type,
+                       const struct block *block,
                        const domain_enum domain)
 {
   struct symbol *sym;
@@ -2120,7 +2205,7 @@ lookup_symbol_in_block (const char *name, const struct block *block,
                          domain_name (domain));
     }
 
-  sym = block_lookup_symbol (block, name, domain);
+  sym = block_lookup_symbol (block, name, match_type, domain);
   if (sym)
     {
       if (symbol_lookup_debug > 1)
@@ -2168,8 +2253,6 @@ static struct block_symbol
 lookup_symbol_in_objfile_symtabs (struct objfile *objfile, int block_index,
                                  const char *name, const domain_enum domain)
 {
-  struct compunit_symtab *cust;
-
   gdb_assert (block_index == GLOBAL_BLOCK || block_index == STATIC_BLOCK);
 
   if (symbol_lookup_debug > 1)
@@ -2182,7 +2265,7 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile, int block_index,
                          name, domain_name (domain));
     }
 
-  ALL_OBJFILE_COMPUNITS (objfile, cust)
+  for (compunit_symtab *cust : objfile_compunits (objfile))
     {
       const struct blockvector *bv;
       const struct block *block;
@@ -2309,7 +2392,8 @@ lookup_symbol_via_quick_fns (struct objfile *objfile, int block_index,
 
   bv = COMPUNIT_BLOCKVECTOR (cust);
   block = BLOCKVECTOR_BLOCK (bv, block_index);
-  result.symbol = block_lookup_symbol (block, name, domain);
+  result.symbol = block_lookup_symbol (block, name,
+                                      symbol_name_match_type::FULL, domain);
   if (result.symbol == NULL)
     error_in_psymtab_expansion (block_index, name, cust);
 
@@ -2422,7 +2506,9 @@ lookup_symbol_in_static_block (const char *name,
                          domain_name (domain));
     }
 
-  sym = lookup_symbol_in_block (name, static_block, domain);
+  sym = lookup_symbol_in_block (name,
+                               symbol_name_match_type::FULL,
+                               static_block, domain);
   if (symbol_lookup_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
@@ -2487,7 +2573,6 @@ struct block_symbol
 lookup_static_symbol (const char *name, const domain_enum domain)
 {
   struct symbol_cache *cache = get_symbol_cache (current_program_space);
-  struct objfile *objfile;
   struct block_symbol result;
   struct block_symbol_cache *bsc;
   struct symbol_cache_slot *slot;
@@ -2503,7 +2588,7 @@ lookup_static_symbol (const char *name, const domain_enum domain)
       return result;
     }
 
-  ALL_OBJFILES (objfile)
+  for (objfile *objfile : all_objfiles (current_program_space))
     {
       result = lookup_symbol_in_objfile (objfile, STATIC_BLOCK, name, domain);
       if (result.symbol != NULL)
@@ -2674,12 +2759,11 @@ static struct type *
 basic_lookup_transparent_type_1 (struct objfile *objfile, int block_index,
                                 const char *name)
 {
-  const struct compunit_symtab *cust;
   const struct blockvector *bv;
   const struct block *block;
   const struct symbol *sym;
 
-  ALL_OBJFILE_COMPUNITS (objfile, cust)
+  for (compunit_symtab *cust : objfile_compunits (objfile))
     {
       bv = COMPUNIT_BLOCKVECTOR (cust);
       block = BLOCKVECTOR_BLOCK (bv, block_index);
@@ -2704,7 +2788,6 @@ basic_lookup_transparent_type_1 (struct objfile *objfile, int block_index,
 struct type *
 basic_lookup_transparent_type (const char *name)
 {
-  struct objfile *objfile;
   struct type *t;
 
   /* Now search all the global symbols.  Do the symtab's first, then
@@ -2712,19 +2795,19 @@ basic_lookup_transparent_type (const char *name)
      of the desired name as a global, then do psymtab-to-symtab
      conversion on the fly and return the found symbol.  */
 
-  ALL_OBJFILES (objfile)
-  {
-    t = basic_lookup_transparent_type_1 (objfile, GLOBAL_BLOCK, name);
-    if (t)
-      return t;
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      t = basic_lookup_transparent_type_1 (objfile, GLOBAL_BLOCK, name);
+      if (t)
+       return t;
+    }
 
-  ALL_OBJFILES (objfile)
-  {
-    t = basic_lookup_transparent_type_quick (objfile, GLOBAL_BLOCK, name);
-    if (t)
-      return t;
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      t = basic_lookup_transparent_type_quick (objfile, GLOBAL_BLOCK, name);
+      if (t)
+       return t;
+    }
 
   /* Now search the static file-level symbols.
      Not strictly correct, but more useful than an error.
@@ -2733,19 +2816,19 @@ basic_lookup_transparent_type (const char *name)
      of the desired name as a file-level static, then do psymtab-to-symtab
      conversion on the fly and return the found symbol.  */
 
-  ALL_OBJFILES (objfile)
-  {
-    t = basic_lookup_transparent_type_1 (objfile, STATIC_BLOCK, name);
-    if (t)
-      return t;
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      t = basic_lookup_transparent_type_1 (objfile, STATIC_BLOCK, name);
+      if (t)
+       return t;
+    }
 
-  ALL_OBJFILES (objfile)
-  {
-    t = basic_lookup_transparent_type_quick (objfile, STATIC_BLOCK, name);
-    if (t)
-      return t;
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      t = basic_lookup_transparent_type_quick (objfile, STATIC_BLOCK, name);
+      if (t)
+       return t;
+    }
 
   return (struct type *) 0;
 }
@@ -2759,7 +2842,8 @@ basic_lookup_transparent_type (const char *name)
    search continues.  */
 
 void
-iterate_over_symbols (const struct block *block, const char *name,
+iterate_over_symbols (const struct block *block,
+                     const lookup_name_info &name,
                      const domain_enum domain,
                      gdb::function_view<symbol_found_callback_ftype> callback)
 {
@@ -2771,7 +2855,9 @@ iterate_over_symbols (const struct block *block, const char *name,
       if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
                                 SYMBOL_DOMAIN (sym), domain))
        {
-         if (!callback (sym))
+         struct block_symbol block_sym = {sym, block};
+
+         if (!callback (&block_sym))
            return;
        }
     }
@@ -2783,9 +2869,7 @@ iterate_over_symbols (const struct block *block, const char *name,
 struct compunit_symtab *
 find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
 {
-  struct compunit_symtab *cust;
   struct compunit_symtab *best_cust = NULL;
-  struct objfile *objfile;
   CORE_ADDR distance = 0;
   struct bound_minimal_symbol msymbol;
 
@@ -2818,76 +2902,81 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
      It also happens for objfiles that have their functions reordered.
      For these, the symtab we are looking for is not necessarily read in.  */
 
-  ALL_COMPUNITS (objfile, cust)
-  {
-    struct block *b;
-    const struct blockvector *bv;
-
-    bv = COMPUNIT_BLOCKVECTOR (cust);
-    b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
+  for (objfile *obj_file : all_objfiles (current_program_space))
+    {
+      for (compunit_symtab *cust : objfile_compunits (obj_file))
+       {
+         struct block *b;
+         const struct blockvector *bv;
 
-    if (BLOCK_START (b) <= pc
-       && BLOCK_END (b) > pc
-       && (distance == 0
-           || BLOCK_END (b) - BLOCK_START (b) < distance))
-      {
-       /* For an objfile that has its functions reordered,
-          find_pc_psymtab will find the proper partial symbol table
-          and we simply return its corresponding symtab.  */
-       /* In order to better support objfiles that contain both
-          stabs and coff debugging info, we continue on if a psymtab
-          can't be found.  */
-       if ((objfile->flags & OBJF_REORDERED) && objfile->sf)
-         {
-           struct compunit_symtab *result;
-
-           result
-             = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile,
-                                                              msymbol,
-                                                              pc, section,
-                                                              0);
-           if (result != NULL)
-             return result;
-         }
-       if (section != 0)
-         {
-           struct block_iterator iter;
-           struct symbol *sym = NULL;
+         bv = COMPUNIT_BLOCKVECTOR (cust);
+         b = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
 
-           ALL_BLOCK_SYMBOLS (b, iter, sym)
-             {
-               fixup_symbol_section (sym, objfile);
-               if (matching_obj_sections (SYMBOL_OBJ_SECTION (objfile, sym),
-                                          section))
-                 break;
-             }
-           if (sym == NULL)
-             continue;         /* No symbol in this symtab matches
-                                  section.  */
-         }
-       distance = BLOCK_END (b) - BLOCK_START (b);
-       best_cust = cust;
-      }
-  }
+         if (BLOCK_START (b) <= pc
+             && BLOCK_END (b) > pc
+             && (distance == 0
+                 || BLOCK_END (b) - BLOCK_START (b) < distance))
+           {
+             /* For an objfile that has its functions reordered,
+                find_pc_psymtab will find the proper partial symbol table
+                and we simply return its corresponding symtab.  */
+             /* In order to better support objfiles that contain both
+                stabs and coff debugging info, we continue on if a psymtab
+                can't be found.  */
+             if ((obj_file->flags & OBJF_REORDERED) && obj_file->sf)
+               {
+                 struct compunit_symtab *result;
+
+                 result
+                   = obj_file->sf->qf->find_pc_sect_compunit_symtab (obj_file,
+                                                                     msymbol,
+                                                                     pc,
+                                                                     section,
+                                                                     0);
+                 if (result != NULL)
+                   return result;
+               }
+             if (section != 0)
+               {
+                 struct block_iterator iter;
+                 struct symbol *sym = NULL;
+
+                 ALL_BLOCK_SYMBOLS (b, iter, sym)
+                   {
+                     fixup_symbol_section (sym, obj_file);
+                     if (matching_obj_sections (SYMBOL_OBJ_SECTION (obj_file,
+                                                                    sym),
+                                                section))
+                       break;
+                   }
+                 if (sym == NULL)
+                   continue;           /* No symbol in this symtab matches
+                                          section.  */
+               }
+             distance = BLOCK_END (b) - BLOCK_START (b);
+             best_cust = cust;
+           }
+       }
+    }
 
   if (best_cust != NULL)
     return best_cust;
 
   /* Not found in symtabs, search the "quick" symtabs (e.g. psymtabs).  */
 
-  ALL_OBJFILES (objfile)
-  {
-    struct compunit_symtab *result;
-
-    if (!objfile->sf)
-      continue;
-    result = objfile->sf->qf->find_pc_sect_compunit_symtab (objfile,
-                                                           msymbol,
-                                                           pc, section,
-                                                           1);
-    if (result != NULL)
-      return result;
-  }
+  for (objfile *objf : all_objfiles (current_program_space))
+    {
+      struct compunit_symtab *result;
+
+      if (!objf->sf)
+       continue;
+      result = objf->sf->qf->find_pc_sect_compunit_symtab (objf,
+                                                          msymbol,
+                                                          pc, section,
+                                                          1);
+      if (result != NULL)
+       return result;
+    }
 
   return NULL;
 }
@@ -2901,6 +2990,43 @@ find_pc_compunit_symtab (CORE_ADDR pc)
 {
   return find_pc_sect_compunit_symtab (pc, find_pc_mapped_section (pc));
 }
+
+/* See symtab.h.  */
+
+struct symbol *
+find_symbol_at_address (CORE_ADDR address)
+{
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      if (objfile->sf == NULL
+         || objfile->sf->qf->find_compunit_symtab_by_address == NULL)
+       continue;
+
+      struct compunit_symtab *symtab
+       = objfile->sf->qf->find_compunit_symtab_by_address (objfile, address);
+      if (symtab != NULL)
+       {
+         const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (symtab);
+
+         for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
+           {
+             struct block *b = BLOCKVECTOR_BLOCK (bv, i);
+             struct block_iterator iter;
+             struct symbol *sym;
+
+             ALL_BLOCK_SYMBOLS (b, iter, sym)
+               {
+                 if (SYMBOL_CLASS (sym) == LOC_STATIC
+                     && SYMBOL_VALUE_ADDRESS (sym) == address)
+                   return sym;
+               }
+           }
+       }
+    }
+
+  return NULL;
+}
+
 \f
 
 /* Find the source file and line number for a given PC value and SECTION.
@@ -2918,16 +3044,12 @@ find_pc_compunit_symtab (CORE_ADDR pc)
    find the one whose first PC is closer than that of the next line in this
    symtab.  */
 
-/* If it's worth the effort, we could be using a binary search.  */
-
 struct symtab_and_line
 find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
 {
   struct compunit_symtab *cust;
-  struct symtab *iter_s;
   struct linetable *l;
   int len;
-  int i;
   struct linetable_entry *item;
   const struct blockvector *bv;
   struct bound_minimal_symbol msymbol;
@@ -3062,7 +3184,7 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
      They all have the same apriori range, that we found was right;
      but they have different line tables.  */
 
-  ALL_COMPUNIT_FILETABS (cust, iter_s)
+  for (symtab *iter_s : compunit_filetabs (cust))
     {
       /* Find the best line in this symtab.  */
       l = SYMTAB_LINETABLE (iter_s);
@@ -3086,15 +3208,17 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
       if (item->pc > pc && (!alt || item->pc < alt->pc))
        alt = item;
 
-      for (i = 0; i < len; i++, item++)
-       {
-         /* Leave prev pointing to the linetable entry for the last line
-            that started at or before PC.  */
-         if (item->pc > pc)
-           break;
+      auto pc_compare = [](const CORE_ADDR & comp_pc,
+                          const struct linetable_entry & lhs)->bool
+      {
+       return comp_pc < lhs.pc;
+      };
 
-         prev = item;
-       }
+      struct linetable_entry *first = item;
+      struct linetable_entry *last = item + len;
+      item = std::upper_bound (first, last, pc, pc_compare);
+      if (item != first)
+       prev = item - 1;                /* Found a matching item.  */
 
       /* At this point, prev points at the line whose start addr is <= pc, and
          item points at the next line.  If we ran off the end of the linetable
@@ -3117,10 +3241,10 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
        }
 
       /* If another line (denoted by ITEM) is in the linetable and its
-         PC is after BEST's PC, but before the current BEST_END, then
+        PC is after BEST's PC, but before the current BEST_END, then
         use ITEM's PC as the new best_end.  */
-      if (best && i < len && item->pc > best->pc
-          && (best_end == 0 || best_end > item->pc))
+      if (best && item < last && item->pc > best->pc
+         && (best_end == 0 || best_end > item->pc))
        best_end = item->pc;
     }
 
@@ -3192,7 +3316,7 @@ find_pc_line_symtab (CORE_ADDR pc)
    If not found, return NULL.  */
 
 struct symtab *
-find_line_symtab (struct symtab *symtab, int line,
+find_line_symtab (struct symtab *sym_tab, int line,
                  int *index, int *exact_match)
 {
   int exact = 0;  /* Initialized here to avoid a compiler warning.  */
@@ -3205,8 +3329,8 @@ find_line_symtab (struct symtab *symtab, int line,
   struct symtab *best_symtab;
 
   /* First try looking it up in the given symtab.  */
-  best_linetable = SYMTAB_LINETABLE (symtab);
-  best_symtab = symtab;
+  best_linetable = SYMTAB_LINETABLE (sym_tab);
+  best_symtab = sym_tab;
   best_index = find_line_common (best_linetable, line, &exact, 0);
   if (best_index < 0 || !exact)
     {
@@ -3222,52 +3346,54 @@ find_line_symtab (struct symtab *symtab, int line,
          BEST_INDEX and BEST_LINETABLE identify the item for it.  */
       int best;
 
-      struct objfile *objfile;
-      struct compunit_symtab *cu;
-      struct symtab *s;
-
       if (best_index >= 0)
        best = best_linetable->item[best_index].line;
       else
        best = 0;
 
-      ALL_OBJFILES (objfile)
-      {
-       if (objfile->sf)
-         objfile->sf->qf->expand_symtabs_with_fullname (objfile,
-                                                  symtab_to_fullname (symtab));
-      }
-
-      ALL_FILETABS (objfile, cu, s)
-      {
-       struct linetable *l;
-       int ind;
+      for (objfile *objfile : all_objfiles (current_program_space))
+       {
+         if (objfile->sf)
+           objfile->sf->qf->expand_symtabs_with_fullname
+             (objfile, symtab_to_fullname (sym_tab));
+       }
 
-       if (FILENAME_CMP (symtab->filename, s->filename) != 0)
-         continue;
-       if (FILENAME_CMP (symtab_to_fullname (symtab),
-                         symtab_to_fullname (s)) != 0)
-         continue;     
-       l = SYMTAB_LINETABLE (s);
-       ind = find_line_common (l, line, &exact, 0);
-       if (ind >= 0)
-         {
-           if (exact)
-             {
-               best_index = ind;
-               best_linetable = l;
-               best_symtab = s;
-               goto done;
-             }
-           if (best == 0 || l->item[ind].line < best)
-             {
-               best = l->item[ind].line;
-               best_index = ind;
-               best_linetable = l;
-               best_symtab = s;
-             }
-         }
-      }
+      for (objfile *objfile : all_objfiles (current_program_space))
+       {
+         for (compunit_symtab *cu : objfile_compunits (objfile))
+           {
+             for (symtab *s : compunit_filetabs (cu))
+               {
+                 struct linetable *l;
+                 int ind;
+
+                 if (FILENAME_CMP (sym_tab->filename, s->filename) != 0)
+                   continue;
+                 if (FILENAME_CMP (symtab_to_fullname (sym_tab),
+                                   symtab_to_fullname (s)) != 0)
+                   continue;   
+                 l = SYMTAB_LINETABLE (s);
+                 ind = find_line_common (l, line, &exact, 0);
+                 if (ind >= 0)
+                   {
+                     if (exact)
+                       {
+                         best_index = ind;
+                         best_linetable = l;
+                         best_symtab = s;
+                         goto done;
+                       }
+                     if (best == 0 || l->item[ind].line < best)
+                       {
+                         best = l->item[ind].line;
+                         best_index = ind;
+                         best_linetable = l;
+                         best_symtab = s;
+                       }
+                   }
+               }
+           }
+       }
     }
 done:
   if (best_index < 0)
@@ -3447,46 +3573,37 @@ find_pc_line_pc_range (CORE_ADDR pc, CORE_ADDR *startptr, CORE_ADDR *endptr)
   return sal.symtab != 0;
 }
 
-/* Given a function symbol SYM, find the symtab and line for the start
-   of the function.
-   If the argument FUNFIRSTLINE is nonzero, we want the first line
-   of real code inside the function.
-   This function should return SALs matching those from minsym_found,
-   otherwise false multiple-locations breakpoints could be placed.  */
+/* Helper for find_function_start_sal.  Does most of the work, except
+   setting the sal's symbol.  */
 
-struct symtab_and_line
-find_function_start_sal (struct symbol *sym, int funfirstline)
+static symtab_and_line
+find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section,
+                          bool funfirstline)
 {
-  fixup_symbol_section (sym, NULL);
-
-  obj_section *section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
-  symtab_and_line sal
-    = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
-  sal.symbol = sym;
+  symtab_and_line sal = find_pc_sect_line (func_addr, section, 0);
 
   if (funfirstline && sal.symtab != NULL
       && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
          || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
     {
-      struct gdbarch *gdbarch = symbol_arch (sym);
+      struct gdbarch *gdbarch = get_objfile_arch (SYMTAB_OBJFILE (sal.symtab));
 
-      sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+      sal.pc = func_addr;
       if (gdbarch_skip_entrypoint_p (gdbarch))
        sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
       return sal;
     }
 
   /* We always should have a line for the function start address.
-     If we don't, something is odd.  Create a plain SAL refering
+     If we don't, something is odd.  Create a plain SAL referring
      just the PC and hope that skip_prologue_sal (if requested)
      can find a line number for after the prologue.  */
-  if (sal.pc < BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))
+  if (sal.pc < func_addr)
     {
       sal = {};
       sal.pspace = current_program_space;
-      sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+      sal.pc = func_addr;
       sal.section = section;
-      sal.symbol = sym;
     }
 
   if (funfirstline)
@@ -3495,6 +3612,38 @@ find_function_start_sal (struct symbol *sym, int funfirstline)
   return sal;
 }
 
+/* See symtab.h.  */
+
+symtab_and_line
+find_function_start_sal (CORE_ADDR func_addr, obj_section *section,
+                        bool funfirstline)
+{
+  symtab_and_line sal
+    = find_function_start_sal_1 (func_addr, section, funfirstline);
+
+  /* find_function_start_sal_1 does a linetable search, so it finds
+     the symtab and linenumber, but not a symbol.  Fill in the
+     function symbol too.  */
+  sal.symbol = find_pc_sect_containing_function (sal.pc, sal.section);
+
+  return sal;
+}
+
+/* See symtab.h.  */
+
+symtab_and_line
+find_function_start_sal (symbol *sym, bool funfirstline)
+{
+  fixup_symbol_section (sym, NULL);
+  symtab_and_line sal
+    = find_function_start_sal_1 (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)),
+                                SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym),
+                                funfirstline);
+  sal.symbol = sym;
+  return sal;
+}
+
+
 /* Given a function start address FUNC_ADDR and SYMTAB, find the first
    address for that function that has an entry in SYMTAB's line info
    table.  If such an entry cannot be found, return FUNC_ADDR
@@ -3567,7 +3716,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
       fixup_symbol_section (sym, NULL);
 
       objfile = symbol_objfile (sym);
-      pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
+      pc = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
       section = SYMBOL_OBJ_SECTION (objfile, sym);
       name = SYMBOL_LINKAGE_NAME (sym);
     }
@@ -3628,7 +3777,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
       /* Check if gdbarch_skip_prologue left us in mid-line, and the next
         line is still part of the same function.  */
       if (skip && start_sal.pc != pc
-         && (sym ? (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
+         && (sym ? (BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) <= start_sal.end
                     && start_sal.end < BLOCK_END (SYMBOL_BLOCK_VALUE (sym)))
              : (lookup_minimal_symbol_by_pc_section (start_sal.end, section).minsym
                 == lookup_minimal_symbol_by_pc_section (pc, section).minsym)))
@@ -3825,14 +3974,14 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
 symbol *
 find_function_alias_target (bound_minimal_symbol msymbol)
 {
-  if (!msymbol_is_text (msymbol.minsym))
+  CORE_ADDR func_addr;
+  if (!msymbol_is_function (msymbol.objfile, msymbol.minsym, &func_addr))
     return NULL;
 
-  CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
-  symbol *sym = find_pc_function (addr);
+  symbol *sym = find_pc_function (func_addr);
   if (sym != NULL
       && SYMBOL_CLASS (sym) == LOC_BLOCK
-      && BLOCK_START (SYMBOL_BLOCK_VALUE (sym)) == addr)
+      && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == func_addr)
     return sym;
 
   return NULL;
@@ -4033,11 +4182,8 @@ output_partial_symbol_filename (const char *filename, const char *fullname,
 }
 
 static void
-info_sources_command (char *ignore, int from_tty)
+info_sources_command (const char *ignore, int from_tty)
 {
-  struct compunit_symtab *cu;
-  struct symtab *s;
-  struct objfile *objfile;
   struct output_source_filename_data data;
 
   if (!have_full_symbols () && !have_partial_symbols ())
@@ -4052,12 +4198,18 @@ info_sources_command (char *ignore, int from_tty)
   printf_filtered ("Source files for which symbols have been read in:\n\n");
 
   data.first = 1;
-  ALL_FILETABS (objfile, cu, s)
-  {
-    const char *fullname = symtab_to_fullname (s);
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      for (compunit_symtab *cu : objfile_compunits (objfile))
+       {
+         for (symtab *s : compunit_filetabs (cu))
+           {
+             const char *fullname = symtab_to_fullname (s);
 
-    output_source_filename (fullname, &data);
-  }
+             output_source_filename (fullname, &data);
+           }
+       }
+    }
   printf_filtered ("\n\n");
 
   printf_filtered ("Source files for which symbols "
@@ -4114,6 +4266,49 @@ symbol_search::compare_search_syms (const symbol_search &sym_a,
                 SYMBOL_PRINT_NAME (sym_b.symbol));
 }
 
+/* Returns true if the type_name of symbol_type of SYM matches TREG.
+   If SYM has no symbol_type or symbol_name, returns false.  */
+
+bool
+treg_matches_sym_type_name (const compiled_regex &treg,
+                           const struct symbol *sym)
+{
+  struct type *sym_type;
+  std::string printed_sym_type_name;
+
+  if (symbol_lookup_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+                         "treg_matches_sym_type_name\n     sym %s\n",
+                         SYMBOL_NATURAL_NAME (sym));
+    }
+
+  sym_type = SYMBOL_TYPE (sym);
+  if (sym_type == NULL)
+    return false;
+
+  {
+    scoped_switch_to_sym_language_if_auto l (sym);
+
+    printed_sym_type_name = type_to_string (sym_type);
+  }
+
+
+  if (symbol_lookup_debug > 1)
+    {
+      fprintf_unfiltered (gdb_stdlog,
+                         "     sym_type_name %s\n",
+                         printed_sym_type_name.c_str ());
+    }
+
+
+  if (printed_sym_type_name.empty ())
+    return false;
+
+  return treg.exec (printed_sym_type_name.c_str (), 0, NULL, 0) == 0;
+}
+
+
 /* Sort the symbols in RESULT and remove duplicates.  */
 
 static void
@@ -4129,7 +4324,9 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
 
    Only symbols of KIND are searched:
    VARIABLES_DOMAIN - search all symbols, excluding functions, type names,
-                      and constants (enums)
+                      and constants (enums).
+                     if T_REGEXP is not NULL, only returns var that have
+                     a type matching regular expression T_REGEXP.
    FUNCTIONS_DOMAIN - search all functions
    TYPES_DOMAIN     - search all type names
    ALL_DOMAIN       - an internal error for this function
@@ -4140,16 +4337,14 @@ sort_search_symbols_remove_dups (std::vector<symbol_search> *result)
 
 std::vector<symbol_search>
 search_symbols (const char *regexp, enum search_domain kind,
+               const char *t_regexp,
                int nfiles, const char *files[])
 {
-  struct compunit_symtab *cust;
   const struct blockvector *bv;
   struct block *b;
   int i = 0;
   struct block_iterator iter;
   struct symbol *sym;
-  struct objfile *objfile;
-  struct minimal_symbol *msymbol;
   int found_misc = 0;
   static const enum minimal_symbol_type types[]
     = {mst_data, mst_text, mst_abs};
@@ -4165,6 +4360,7 @@ search_symbols (const char *regexp, enum search_domain kind,
   enum minimal_symbol_type ourtype4;
   std::vector<symbol_search> result;
   gdb::optional<compiled_regex> preg;
+  gdb::optional<compiled_regex> treg;
 
   gdb_assert (kind <= TYPES_DOMAIN);
 
@@ -4181,7 +4377,6 @@ search_symbols (const char *regexp, enum search_domain kind,
          and <TYPENAME> or <OPERATOR>.  */
       const char *opend;
       const char *opname = operator_chars (regexp, &opend);
-      int errcode;
 
       if (*opname)
        {
@@ -4215,6 +4410,13 @@ search_symbols (const char *regexp, enum search_domain kind,
       preg.emplace (regexp, cflags, _("Invalid regexp"));
     }
 
+  if (t_regexp != NULL)
+    {
+      int cflags = REG_NOSUB | (case_sensitivity == case_sensitive_off
+                               ? REG_ICASE : 0);
+      treg.emplace (t_regexp, cflags, _("Invalid regexp"));
+    }
+
   /* Search through the partial symtabs *first* for all symbols
      matching the regexp.  That way we don't have to reproduce all of
      the machinery below.  */
@@ -4223,10 +4425,12 @@ search_symbols (const char *regexp, enum search_domain kind,
                             return file_matches (filename, files, nfiles,
                                                  basenames);
                           },
+                          lookup_name_info::match_any (),
                           [&] (const char *symname)
                           {
-                            return (!preg || preg->exec (symname,
-                                                         0, NULL, 0) == 0);
+                            return (!preg.has_value ()
+                                    || preg->exec (symname,
+                                                   0, NULL, 0) == 0);
                           },
                           NULL,
                           kind);
@@ -4249,122 +4453,147 @@ search_symbols (const char *regexp, enum search_domain kind,
 
   if (nfiles == 0 && (kind == VARIABLES_DOMAIN || kind == FUNCTIONS_DOMAIN))
     {
-      ALL_MSYMBOLS (objfile, msymbol)
-      {
-        QUIT;
+      for (objfile *objfile : all_objfiles (current_program_space))
+       {
+         for (minimal_symbol *msymbol : objfile_msymbols (objfile))
+           {
+             QUIT;
 
-       if (msymbol->created_by_gdb)
-         continue;
+             if (msymbol->created_by_gdb)
+               continue;
 
-       if (MSYMBOL_TYPE (msymbol) == ourtype
-           || MSYMBOL_TYPE (msymbol) == ourtype2
-           || MSYMBOL_TYPE (msymbol) == ourtype3
-           || MSYMBOL_TYPE (msymbol) == ourtype4)
-         {
-           if (!preg
-               || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
-                              NULL, 0) == 0)
-             {
-               /* Note: An important side-effect of these lookup functions
-                  is to expand the symbol table if msymbol is found, for the
-                  benefit of the next loop on ALL_COMPUNITS.  */
-               if (kind == FUNCTIONS_DOMAIN
-                   ? (find_pc_compunit_symtab
-                      (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) == NULL)
-                   : (lookup_symbol_in_objfile_from_linkage_name
-                      (objfile, MSYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
-                      .symbol == NULL))
-                 found_misc = 1;
-             }
-         }
-      }
+             if (MSYMBOL_TYPE (msymbol) == ourtype
+                 || MSYMBOL_TYPE (msymbol) == ourtype2
+                 || MSYMBOL_TYPE (msymbol) == ourtype3
+                 || MSYMBOL_TYPE (msymbol) == ourtype4)
+               {
+                 if (!preg.has_value ()
+                     || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+                                    NULL, 0) == 0)
+                   {
+                     /* Note: An important side-effect of these
+                        lookup functions is to expand the symbol
+                        table if msymbol is found, for the benefit of
+                        the next loop on compunits.  */
+                     if (kind == FUNCTIONS_DOMAIN
+                         ? (find_pc_compunit_symtab
+                            (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
+                            == NULL)
+                         : (lookup_symbol_in_objfile_from_linkage_name
+                            (objfile, MSYMBOL_LINKAGE_NAME (msymbol),
+                             VAR_DOMAIN)
+                            .symbol == NULL))
+                       found_misc = 1;
+                   }
+               }
+           }
+       }
     }
 
-  ALL_COMPUNITS (objfile, cust)
-  {
-    bv = COMPUNIT_BLOCKVECTOR (cust);
-    for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
-      {
-       b = BLOCKVECTOR_BLOCK (bv, i);
-       ALL_BLOCK_SYMBOLS (b, iter, sym)
-         {
-           struct symtab *real_symtab = symbol_symtab (sym);
-
-           QUIT;
-
-           /* Check first sole REAL_SYMTAB->FILENAME.  It does not need to be
-              a substring of symtab_to_fullname as it may contain "./" etc.  */
-           if ((file_matches (real_symtab->filename, files, nfiles, 0)
-                || ((basenames_may_differ
-                     || file_matches (lbasename (real_symtab->filename),
-                                      files, nfiles, 1))
-                    && file_matches (symtab_to_fullname (real_symtab),
-                                     files, nfiles, 0)))
-               && ((!preg
-                    || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
-                                   NULL, 0) == 0)
-                   && ((kind == VARIABLES_DOMAIN
-                        && SYMBOL_CLASS (sym) != LOC_TYPEDEF
-                        && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
-                        && SYMBOL_CLASS (sym) != LOC_BLOCK
-                        /* LOC_CONST can be used for more than just enums,
-                           e.g., c++ static const members.
-                           We only want to skip enums here.  */
-                        && !(SYMBOL_CLASS (sym) == LOC_CONST
-                             && (TYPE_CODE (SYMBOL_TYPE (sym))
-                                 == TYPE_CODE_ENUM)))
-                       || (kind == FUNCTIONS_DOMAIN 
-                           && SYMBOL_CLASS (sym) == LOC_BLOCK)
-                       || (kind == TYPES_DOMAIN
-                           && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
-             {
-               /* match */
-               result.emplace_back (i, sym);
-             }
-         }
-      }
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      for (compunit_symtab *cust : objfile_compunits (objfile))
+       {
+         bv = COMPUNIT_BLOCKVECTOR (cust);
+         for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
+           {
+             b = BLOCKVECTOR_BLOCK (bv, i);
+             ALL_BLOCK_SYMBOLS (b, iter, sym)
+               {
+                 struct symtab *real_symtab = symbol_symtab (sym);
+
+                 QUIT;
+
+                 /* Check first sole REAL_SYMTAB->FILENAME.  It does
+                    not need to be a substring of symtab_to_fullname as
+                    it may contain "./" etc.  */
+                 if ((file_matches (real_symtab->filename, files, nfiles, 0)
+                      || ((basenames_may_differ
+                           || file_matches (lbasename (real_symtab->filename),
+                                            files, nfiles, 1))
+                          && file_matches (symtab_to_fullname (real_symtab),
+                                           files, nfiles, 0)))
+                     && ((!preg.has_value ()
+                          || preg->exec (SYMBOL_NATURAL_NAME (sym), 0,
+                                         NULL, 0) == 0)
+                         && ((kind == VARIABLES_DOMAIN
+                              && SYMBOL_CLASS (sym) != LOC_TYPEDEF
+                              && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
+                              && SYMBOL_CLASS (sym) != LOC_BLOCK
+                              /* LOC_CONST can be used for more than
+                                 just enums, e.g., c++ static const
+                                 members.  We only want to skip enums
+                                 here.  */
+                              && !(SYMBOL_CLASS (sym) == LOC_CONST
+                                   && (TYPE_CODE (SYMBOL_TYPE (sym))
+                                       == TYPE_CODE_ENUM))
+                              && (!treg.has_value ()
+                                  || treg_matches_sym_type_name (*treg, sym)))
+                             || (kind == FUNCTIONS_DOMAIN
+                                 && SYMBOL_CLASS (sym) == LOC_BLOCK
+                                 && (!treg.has_value ()
+                                     || treg_matches_sym_type_name (*treg,
+                                                                    sym)))
+                             || (kind == TYPES_DOMAIN
+                                 && SYMBOL_CLASS (sym) == LOC_TYPEDEF))))
+                   {
+                     /* match */
+                     result.emplace_back (i, sym);
+                   }
+               }
+           }
+       }
+    }
 
   if (!result.empty ())
     sort_search_symbols_remove_dups (&result);
 
   /* If there are no eyes, avoid all contact.  I mean, if there are
-     no debug symbols, then add matching minsyms.  */
+     no debug symbols, then add matching minsyms.  But if the user wants
+     to see symbols matching a type regexp, then never give a minimal symbol,
+     as we assume that a minimal symbol does not have a type.  */
 
-  if (found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
+  if ((found_misc || (nfiles == 0 && kind != FUNCTIONS_DOMAIN))
+      && !treg.has_value ())
     {
-      ALL_MSYMBOLS (objfile, msymbol)
-      {
-        QUIT;
+      for (objfile *objfile : all_objfiles (current_program_space))
+       {
+         for (minimal_symbol *msymbol : objfile_msymbols (objfile))
+           {
+             QUIT;
 
-       if (msymbol->created_by_gdb)
-         continue;
+             if (msymbol->created_by_gdb)
+               continue;
 
-       if (MSYMBOL_TYPE (msymbol) == ourtype
-           || MSYMBOL_TYPE (msymbol) == ourtype2
-           || MSYMBOL_TYPE (msymbol) == ourtype3
-           || MSYMBOL_TYPE (msymbol) == ourtype4)
-         {
-           if (!preg || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
+             if (MSYMBOL_TYPE (msymbol) == ourtype
+                 || MSYMBOL_TYPE (msymbol) == ourtype2
+                 || MSYMBOL_TYPE (msymbol) == ourtype3
+                 || MSYMBOL_TYPE (msymbol) == ourtype4)
+               {
+                 if (!preg.has_value ()
+                     || preg->exec (MSYMBOL_NATURAL_NAME (msymbol), 0,
                                     NULL, 0) == 0)
-             {
-               /* For functions we can do a quick check of whether the
-                  symbol might be found via find_pc_symtab.  */
-               if (kind != FUNCTIONS_DOMAIN
-                   || (find_pc_compunit_symtab
-                       (MSYMBOL_VALUE_ADDRESS (objfile, msymbol)) == NULL))
-                 {
-                   if (lookup_symbol_in_objfile_from_linkage_name
-                       (objfile, MSYMBOL_LINKAGE_NAME (msymbol), VAR_DOMAIN)
-                       .symbol == NULL)
-                     {
-                       /* match */
-                       result.emplace_back (i, msymbol, objfile);
-                     }
-                 }
-             }
-         }
-      }
+                   {
+                     /* For functions we can do a quick check of whether the
+                        symbol might be found via find_pc_symtab.  */
+                     if (kind != FUNCTIONS_DOMAIN
+                         || (find_pc_compunit_symtab
+                             (MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
+                             == NULL))
+                       {
+                         if (lookup_symbol_in_objfile_from_linkage_name
+                             (objfile, MSYMBOL_LINKAGE_NAME (msymbol),
+                              VAR_DOMAIN)
+                             .symbol == NULL)
+                           {
+                             /* match */
+                             result.emplace_back (i, msymbol, objfile);
+                           }
+                       }
+                   }
+               }
+           }
+       }
     }
 
   return result;
@@ -4372,21 +4601,33 @@ search_symbols (const char *regexp, enum search_domain kind,
 
 /* Helper function for symtab_symbol_info, this function uses
    the data returned from search_symbols() to print information
-   regarding the match to gdb_stdout.  */
+   regarding the match to gdb_stdout.  If LAST is not NULL,
+   print file and line number information for the symbol as
+   well.  Skip printing the filename if it matches LAST.  */
 
 static void
 print_symbol_info (enum search_domain kind,
                   struct symbol *sym,
                   int block, const char *last)
 {
+  scoped_switch_to_sym_language_if_auto l (sym);
   struct symtab *s = symbol_symtab (sym);
-  const char *s_filename = symtab_to_filename_for_display (s);
 
-  if (last == NULL || filename_cmp (last, s_filename) != 0)
+  if (last != NULL)
     {
-      fputs_filtered ("\nFile ", gdb_stdout);
-      fputs_filtered (s_filename, gdb_stdout);
-      fputs_filtered (":\n", gdb_stdout);
+      const char *s_filename = symtab_to_filename_for_display (s);
+
+      if (filename_cmp (last, s_filename) != 0)
+       {
+         fputs_filtered ("\nFile ", gdb_stdout);
+         fputs_filtered (s_filename, gdb_stdout);
+         fputs_filtered (":\n", gdb_stdout);
+       }
+
+      if (SYMBOL_LINE (sym) != 0)
+       printf_filtered ("%d:\t", SYMBOL_LINE (sym));
+      else
+       puts_filtered ("\t");
     }
 
   if (kind != TYPES_DOMAIN && block == STATIC_BLOCK)
@@ -4436,23 +4677,45 @@ print_msymbol_info (struct bound_minimal_symbol msymbol)
    matches.  */
 
 static void
-symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
+symtab_symbol_info (bool quiet,
+                   const char *regexp, enum search_domain kind,
+                   const char *t_regexp, int from_tty)
 {
   static const char * const classnames[] =
     {"variable", "function", "type"};
-  const char *last_filename = NULL;
+  const char *last_filename = "";
   int first = 1;
 
   gdb_assert (kind <= TYPES_DOMAIN);
 
   /* Must make sure that if we're interrupted, symbols gets freed.  */
-  std::vector<symbol_search> symbols = search_symbols (regexp, kind, 0, NULL);
+  std::vector<symbol_search> symbols = search_symbols (regexp, kind,
+                                                      t_regexp, 0, NULL);
 
-  if (regexp != NULL)
-    printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
-                    classnames[kind], regexp);
-  else
-    printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+  if (!quiet)
+    {
+      if (regexp != NULL)
+       {
+         if (t_regexp != NULL)
+           printf_filtered
+             (_("All %ss matching regular expression \"%s\""
+                " with type matching regulation expression \"%s\":\n"),
+              classnames[kind], regexp, t_regexp);
+         else
+           printf_filtered (_("All %ss matching regular expression \"%s\":\n"),
+                            classnames[kind], regexp);
+       }
+      else
+       {
+         if (t_regexp != NULL)
+           printf_filtered
+             (_("All defined %ss"
+                " with type matching regulation expression \"%s\" :\n"),
+              classnames[kind], t_regexp);
+         else
+           printf_filtered (_("All defined %ss:\n"), classnames[kind]);
+       }
+    }
 
   for (const symbol_search &p : symbols)
     {
@@ -4462,7 +4725,8 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
        {
          if (first)
            {
-             printf_filtered (_("\nNon-debugging symbols:\n"));
+             if (!quiet)
+               printf_filtered (_("\nNon-debugging symbols:\n"));
              first = 0;
            }
          print_msymbol_info (p.msymbol);
@@ -4480,22 +4744,53 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
 }
 
 static void
-info_variables_command (char *regexp, int from_tty)
+info_variables_command (const char *args, int from_tty)
 {
-  symtab_symbol_info (regexp, VARIABLES_DOMAIN, from_tty);
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet = false;
+
+  while (args != NULL
+        && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info variables", args);
+
+  symtab_symbol_info (quiet,
+                     regexp.empty () ? NULL : regexp.c_str (),
+                     VARIABLES_DOMAIN,
+                     t_regexp.empty () ? NULL : t_regexp.c_str (),
+                     from_tty);
 }
 
+
 static void
-info_functions_command (char *regexp, int from_tty)
+info_functions_command (const char *args, int from_tty)
 {
-  symtab_symbol_info (regexp, FUNCTIONS_DOMAIN, from_tty);
+  std::string regexp;
+  std::string t_regexp;
+  bool quiet = false;
+
+  while (args != NULL
+        && extract_info_print_args (&args, &quiet, &regexp, &t_regexp))
+    ;
+
+  if (args != NULL)
+    report_unrecognized_option_error ("info functions", args);
+
+  symtab_symbol_info (quiet,
+                     regexp.empty () ? NULL : regexp.c_str (),
+                     FUNCTIONS_DOMAIN,
+                     t_regexp.empty () ? NULL : t_regexp.c_str (),
+                     from_tty);
 }
 
 
 static void
-info_types_command (char *regexp, int from_tty)
+info_types_command (const char *regexp, int from_tty)
 {
-  symtab_symbol_info (regexp, TYPES_DOMAIN, from_tty);
+  symtab_symbol_info (false, regexp, TYPES_DOMAIN, NULL, from_tty);
 }
 
 /* Breakpoint all functions matching regular expression.  */
@@ -4506,27 +4801,17 @@ rbreak_command_wrapper (char *regexp, int from_tty)
   rbreak_command (regexp, from_tty);
 }
 
-/* A cleanup function that calls end_rbreak_breakpoints.  */
-
-static void
-do_end_rbreak_breakpoints (void *ignore)
-{
-  end_rbreak_breakpoints ();
-}
-
 static void
-rbreak_command (char *regexp, int from_tty)
+rbreak_command (const char *regexp, int from_tty)
 {
-  struct cleanup *old_chain;
-  char *string = NULL;
-  int len = 0;
+  std::string string;
   const char **files = NULL;
   const char *file_name;
   int nfiles = 0;
 
   if (regexp)
     {
-      char *colon = strchr (regexp, ':');
+      const char *colon = strchr (regexp, ':');
 
       if (colon && *(colon + 1) != ':')
        {
@@ -4548,10 +4833,10 @@ rbreak_command (char *regexp, int from_tty)
 
   std::vector<symbol_search> symbols = search_symbols (regexp,
                                                       FUNCTIONS_DOMAIN,
+                                                      NULL,
                                                       nfiles, files);
 
-  start_rbreak_breakpoints ();
-  old_chain = make_cleanup (do_end_rbreak_breakpoints, NULL);
+  scoped_rbreak_breakpoints finalize;
   for (const symbol_search &p : symbols)
     {
       if (p.msymbol.minsym == NULL)
@@ -4559,125 +4844,76 @@ rbreak_command (char *regexp, int from_tty)
          struct symtab *symtab = symbol_symtab (p.symbol);
          const char *fullname = symtab_to_fullname (symtab);
 
-         int newlen = (strlen (fullname)
-                       + strlen (SYMBOL_LINKAGE_NAME (p.symbol))
-                       + 4);
-
-         if (newlen > len)
-           {
-             string = (char *) xrealloc (string, newlen);
-             len = newlen;
-           }
-         strcpy (string, fullname);
-         strcat (string, ":'");
-         strcat (string, SYMBOL_LINKAGE_NAME (p.symbol));
-         strcat (string, "'");
-         break_command (string, from_tty);
-         print_symbol_info (FUNCTIONS_DOMAIN,
-                            p.symbol,
-                            p.block,
-                            symtab_to_filename_for_display (symtab));
+         string = string_printf ("%s:'%s'", fullname,
+                                 SYMBOL_LINKAGE_NAME (p.symbol));
+         break_command (&string[0], from_tty);
+         print_symbol_info (FUNCTIONS_DOMAIN, p.symbol, p.block, NULL);
        }
       else
        {
-         int newlen = (strlen (MSYMBOL_LINKAGE_NAME (p.msymbol.minsym)) + 3);
+         string = string_printf ("'%s'",
+                                 MSYMBOL_LINKAGE_NAME (p.msymbol.minsym));
 
-         if (newlen > len)
-           {
-             string = (char *) xrealloc (string, newlen);
-             len = newlen;
-           }
-         strcpy (string, "'");
-         strcat (string, MSYMBOL_LINKAGE_NAME (p.msymbol.minsym));
-         strcat (string, "'");
-
-         break_command (string, from_tty);
+         break_command (&string[0], from_tty);
          printf_filtered ("<function, no debug info> %s;\n",
                           MSYMBOL_PRINT_NAME (p.msymbol.minsym));
        }
     }
-
-  do_cleanups (old_chain);
 }
 \f
 
-/* Evaluate if NAME matches SYM_TEXT and SYM_TEXT_LEN.
-
-   Either sym_text[sym_text_len] != '(' and then we search for any
-   symbol starting with SYM_TEXT text.
-
-   Otherwise sym_text[sym_text_len] == '(' and then we require symbol name to
-   be terminated at that point.  Partial symbol tables do not have parameters
-   information.  */
+/* Evaluate if SYMNAME matches LOOKUP_NAME.  */
 
 static int
-compare_symbol_name (const char *name, const char *sym_text, int sym_text_len)
+compare_symbol_name (const char *symbol_name, language symbol_language,
+                    const lookup_name_info &lookup_name,
+                    completion_match_result &match_res)
 {
-  int (*ncmp) (const char *, const char *, size_t);
-
-  ncmp = (case_sensitivity == case_sensitive_on ? strncmp : strncasecmp);
+  const language_defn *lang = language_def (symbol_language);
 
-  if (ncmp (name, sym_text, sym_text_len) != 0)
-    return 0;
+  symbol_name_matcher_ftype *name_match
+    = get_symbol_name_matcher (lang, lookup_name);
 
-  if (sym_text[sym_text_len] == '(')
-    {
-      /* User searches for `name(someth...'.  Require NAME to be terminated.
-        Normally psymtabs and gdbindex have no parameter types so '\0' will be
-        present but accept even parameters presence.  In this case this
-        function is in fact strcmp_iw but whitespace skipping is not supported
-        for tab completion.  */
-
-      if (name[sym_text_len] != '\0' && name[sym_text_len] != '(')
-       return 0;
-    }
-
-  return 1;
+  return name_match (symbol_name, lookup_name, &match_res);
 }
 
-/*  Test to see if the symbol specified by SYMNAME (which is already
-   demangled for C++ symbols) matches SYM_TEXT in the first SYM_TEXT_LEN
-   characters.  If so, add it to the current completion list.  */
+/*  See symtab.h.  */
 
-static void
+void
 completion_list_add_name (completion_tracker &tracker,
+                         language symbol_language,
                          const char *symname,
-                         const char *sym_text, int sym_text_len,
+                         const lookup_name_info &lookup_name,
                          const char *text, const char *word)
 {
+  completion_match_result &match_res
+    = tracker.reset_completion_match_result ();
+
   /* Clip symbols that cannot match.  */
-  if (!compare_symbol_name (symname, sym_text, sym_text_len))
+  if (!compare_symbol_name (symname, symbol_language, lookup_name, match_res))
     return;
 
+  /* Refresh SYMNAME from the match string.  It's potentially
+     different depending on language.  (E.g., on Ada, the match may be
+     the encoded symbol name wrapped in "<>").  */
+  symname = match_res.match.match ();
+  gdb_assert (symname != NULL);
+
   /* We have a match for a completion, so add SYMNAME to the current list
      of matches.  Note that the name is moved to freshly malloc'd space.  */
 
   {
-    char *newobj;
-
-    if (word == sym_text)
-      {
-       newobj = (char *) xmalloc (strlen (symname) + 5);
-       strcpy (newobj, symname);
-      }
-    else if (word > sym_text)
-      {
-       /* Return some portion of symname.  */
-       newobj = (char *) xmalloc (strlen (symname) + 5);
-       strcpy (newobj, symname + (word - sym_text));
-      }
-    else
-      {
-       /* Return some of SYM_TEXT plus symname.  */
-       newobj = (char *) xmalloc (strlen (symname) + (sym_text - word) + 5);
-       strncpy (newobj, word, sym_text - word);
-       newobj[sym_text - word] = '\0';
-       strcat (newobj, symname);
-      }
-
-    gdb::unique_xmalloc_ptr<char> completion (newobj);
-
-    tracker.add_completion (std::move (completion));
+    gdb::unique_xmalloc_ptr<char> completion
+      = make_completion_match_str (symname, text, word);
+
+    /* Here we pass the match-for-lcd object to add_completion.  Some
+       languages match the user text against substrings of symbol
+       names in some cases.  E.g., in C++, "b push_ba" completes to
+       "std::vector::push_back", "std::string::push_back", etc., and
+       in this case we want the completion lowest common denominator
+       to be "push_back" instead of "std::".  */
+    tracker.add_completion (std::move (completion),
+                           &match_res.match_for_lcd, text, word);
   }
 }
 
@@ -4686,11 +4922,12 @@ completion_list_add_name (completion_tracker &tracker,
 static void
 completion_list_add_symbol (completion_tracker &tracker,
                            symbol *sym,
-                           const char *sym_text, int sym_text_len,
+                           const lookup_name_info &lookup_name,
                            const char *text, const char *word)
 {
-  completion_list_add_name (tracker, SYMBOL_NATURAL_NAME (sym),
-                           sym_text, sym_text_len, text, word);
+  completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+                           SYMBOL_NATURAL_NAME (sym),
+                           lookup_name, text, word);
 }
 
 /* completion_list_add_name wrapper for struct minimal_symbol.  */
@@ -4698,20 +4935,22 @@ completion_list_add_symbol (completion_tracker &tracker,
 static void
 completion_list_add_msymbol (completion_tracker &tracker,
                             minimal_symbol *sym,
-                            const char *sym_text, int sym_text_len,
+                            const lookup_name_info &lookup_name,
                             const char *text, const char *word)
 {
-  completion_list_add_name (tracker, MSYMBOL_NATURAL_NAME (sym),
-                           sym_text, sym_text_len, text, word);
+  completion_list_add_name (tracker, MSYMBOL_LANGUAGE (sym),
+                           MSYMBOL_NATURAL_NAME (sym),
+                           lookup_name, text, word);
 }
 
+
 /* ObjC: In case we are completing on a selector, look as the msymbol
    again and feed all the selectors into the mill.  */
 
 static void
 completion_list_objc_symbol (completion_tracker &tracker,
                             struct minimal_symbol *msymbol,
-                            const char *sym_text, int sym_text_len,
+                            const lookup_name_info &lookup_name,
                             const char *text, const char *word)
 {
   static char *tmp = NULL;
@@ -4726,10 +4965,12 @@ completion_list_objc_symbol (completion_tracker &tracker,
   if ((method[0] != '-') && (method[0] != '+'))
     return;
 
-  if (sym_text[0] == '[')
+  if (text[0] == '[')
     /* Complete on shortened method method.  */
-    completion_list_add_name (tracker, method + 1,
-                             sym_text, sym_text_len, text, word);
+    completion_list_add_name (tracker, language_objc,
+                             method + 1,
+                             lookup_name,
+                             text, word);
 
   while ((strlen (method) + 1) >= tmplen)
     {
@@ -4750,11 +4991,11 @@ completion_list_objc_symbol (completion_tracker &tracker,
       memcpy (tmp, method, (category - method));
       tmp[category - method] = ' ';
       memcpy (tmp + (category - method) + 1, selector, strlen (selector) + 1);
-      completion_list_add_name (tracker, tmp,
-                               sym_text, sym_text_len, text, word);
-      if (sym_text[0] == '[')
-       completion_list_add_name (tracker, tmp + 1,
-                                 sym_text, sym_text_len, text, word);
+      completion_list_add_name (tracker, language_objc, tmp,
+                               lookup_name, text, word);
+      if (text[0] == '[')
+       completion_list_add_name (tracker, language_objc, tmp + 1,
+                                 lookup_name, text, word);
     }
 
   if (selector != NULL)
@@ -4765,8 +5006,8 @@ completion_list_objc_symbol (completion_tracker &tracker,
       if (tmp2 != NULL)
        *tmp2 = '\0';
 
-      completion_list_add_name (tracker, tmp,
-                               sym_text, sym_text_len, text, word);
+      completion_list_add_name (tracker, language_objc, tmp,
+                               lookup_name, text, word);
     }
 }
 
@@ -4819,7 +5060,7 @@ language_search_unquoted_string (const char *text, const char *p)
 static void
 completion_list_add_fields (completion_tracker &tracker,
                            struct symbol *sym,
-                           const char *sym_text, int sym_text_len,
+                           const lookup_name_info &lookup_name,
                            const char *text, const char *word)
 {
   if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
@@ -4831,17 +5072,95 @@ completion_list_add_fields (completion_tracker &tracker,
       if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
        for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++)
          if (TYPE_FIELD_NAME (t, j))
-           completion_list_add_name (tracker, TYPE_FIELD_NAME (t, j),
-                                     sym_text, sym_text_len, text, word);
+           completion_list_add_name (tracker, SYMBOL_LANGUAGE (sym),
+                                     TYPE_FIELD_NAME (t, j),
+                                     lookup_name, text, word);
+    }
+}
+
+/* See symtab.h.  */
+
+bool
+symbol_is_function_or_method (symbol *sym)
+{
+  switch (TYPE_CODE (SYMBOL_TYPE (sym)))
+    {
+    case TYPE_CODE_FUNC:
+    case TYPE_CODE_METHOD:
+      return true;
+    default:
+      return false;
+    }
+}
+
+/* See symtab.h.  */
+
+bool
+symbol_is_function_or_method (minimal_symbol *msymbol)
+{
+  switch (MSYMBOL_TYPE (msymbol))
+    {
+    case mst_text:
+    case mst_text_gnu_ifunc:
+    case mst_solib_trampoline:
+    case mst_file_text:
+      return true;
+    default:
+      return false;
     }
 }
 
+/* See symtab.h.  */
+
+bound_minimal_symbol
+find_gnu_ifunc (const symbol *sym)
+{
+  if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+    return {};
+
+  lookup_name_info lookup_name (SYMBOL_SEARCH_NAME (sym),
+                               symbol_name_match_type::SEARCH_NAME);
+  struct objfile *objfile = symbol_objfile (sym);
+
+  CORE_ADDR address = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
+  minimal_symbol *ifunc = NULL;
+
+  iterate_over_minimal_symbols (objfile, lookup_name,
+                               [&] (minimal_symbol *minsym)
+    {
+      if (MSYMBOL_TYPE (minsym) == mst_text_gnu_ifunc
+         || MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
+       {
+         CORE_ADDR msym_addr = MSYMBOL_VALUE_ADDRESS (objfile, minsym);
+         if (MSYMBOL_TYPE (minsym) == mst_data_gnu_ifunc)
+           {
+             struct gdbarch *gdbarch = get_objfile_arch (objfile);
+             msym_addr
+               = gdbarch_convert_from_func_ptr_addr (gdbarch,
+                                                     msym_addr,
+                                                     current_top_target ());
+           }
+         if (msym_addr == address)
+           {
+             ifunc = minsym;
+             return true;
+           }
+       }
+      return false;
+    });
+
+  if (ifunc != NULL)
+    return {ifunc, objfile};
+  return {};
+}
+
 /* Add matching symbols from SYMTAB to the current completion list.  */
 
 static void
 add_symtab_completions (struct compunit_symtab *cust,
                        completion_tracker &tracker,
-                       const char *sym_text, int sym_text_len,
+                       complete_symbol_mode mode,
+                       const lookup_name_info &lookup_name,
                        const char *text, const char *word,
                        enum type_code code)
 {
@@ -4859,11 +5178,14 @@ add_symtab_completions (struct compunit_symtab *cust,
       b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), i);
       ALL_BLOCK_SYMBOLS (b, iter, sym)
        {
+         if (completion_skip_symbol (mode, sym))
+           continue;
+
          if (code == TYPE_CODE_UNDEF
              || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
                  && TYPE_CODE (SYMBOL_TYPE (sym)) == code))
            completion_list_add_symbol (tracker, sym,
-                                       sym_text, sym_text_len,
+                                       lookup_name,
                                        text, word);
        }
     }
@@ -4871,8 +5193,8 @@ add_symtab_completions (struct compunit_symtab *cust,
 
 void
 default_collect_symbol_completion_matches_break_on
-  (completion_tracker &tracker,
-   complete_symbol_mode mode,
+  (completion_tracker &tracker, complete_symbol_mode mode,
+   symbol_name_match_type name_match_type,
    const char *text, const char *word,
    const char *break_on, enum type_code code)
 {
@@ -4881,16 +5203,11 @@ default_collect_symbol_completion_matches_break_on
      won't be that many.  */
 
   struct symbol *sym;
-  struct compunit_symtab *cust;
-  struct minimal_symbol *msymbol;
-  struct objfile *objfile;
   const struct block *b;
   const struct block *surrounding_static_block, *surrounding_global_block;
   struct block_iterator iter;
   /* The symbol we are completing on.  Points in same buffer as text.  */
   const char *sym_text;
-  /* Length of sym_text.  */
-  int sym_text_len;
 
   /* Now look for the symbol we are supposed to complete on.  */
   if (mode == complete_symbol_mode::LINESPEC)
@@ -4946,22 +5263,7 @@ default_collect_symbol_completion_matches_break_on
       }
   }
 
-  sym_text_len = strlen (sym_text);
-
-  /* Prepare SYM_TEXT_LEN for compare_symbol_name.  */
-
-  if (current_language->la_language == language_cplus
-      || current_language->la_language == language_fortran)
-    {
-      /* These languages may have parameters entered by user but they are never
-        present in the partial symbol tables.  */
-
-      const char *cs = (const char *) memchr (sym_text, '(', sym_text_len);
-
-      if (cs)
-       sym_text_len = cs - sym_text;
-    }
-  gdb_assert (sym_text[sym_text_len] == '\0' || sym_text[sym_text_len] == '(');
+  lookup_name_info lookup_name (sym_text, name_match_type, true);
 
   /* At this point scan through the misc symbol vectors and add each
      symbol you find to the list.  Eventually we want to ignore
@@ -4970,40 +5272,42 @@ default_collect_symbol_completion_matches_break_on
 
   if (code == TYPE_CODE_UNDEF)
     {
-      ALL_MSYMBOLS (objfile, msymbol)
+      for (objfile *objfile : all_objfiles (current_program_space))
        {
-         QUIT;
+         for (minimal_symbol *msymbol : objfile_msymbols (objfile))
+           {
+             QUIT;
 
-         completion_list_add_msymbol (tracker,
-                                      msymbol, sym_text, sym_text_len,
-                                      text, word);
+             if (completion_skip_symbol (mode, msymbol))
+               continue;
 
-         completion_list_objc_symbol (tracker,
-                                      msymbol, sym_text, sym_text_len,
-                                      text, word);
+             completion_list_add_msymbol (tracker, msymbol, lookup_name,
+                                          sym_text, word);
+
+             completion_list_objc_symbol (tracker, msymbol, lookup_name,
+                                          sym_text, word);
+           }
        }
     }
 
   /* Add completions for all currently loaded symbol tables.  */
-  ALL_COMPUNITS (objfile, cust)
-    add_symtab_completions (cust, tracker,
-                           sym_text, sym_text_len, text, word, code);
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      for (compunit_symtab *cust : objfile_compunits (objfile))
+       add_symtab_completions (cust, tracker, mode, lookup_name,
+                               sym_text, word, code);
+    }
 
   /* Look through the partial symtabs for all symbols which begin by
      matching SYM_TEXT.  Expand all CUs that you find to the list.  */
   expand_symtabs_matching (NULL,
-                          [&] (const char *name) /* symbol matcher */
-                            {
-                              return compare_symbol_name (name,
-                                                          sym_text,
-                                                          sym_text_len);
-                            },
+                          lookup_name,
+                          NULL,
                           [&] (compunit_symtab *symtab) /* expansion notify */
                             {
                               add_symtab_completions (symtab,
-                                                      tracker,
-                                                      sym_text, sym_text_len,
-                                                      text, word, code);
+                                                      tracker, mode, lookup_name,
+                                                      sym_text, word, code);
                             },
                           ALL_DOMAIN);
 
@@ -5024,18 +5328,15 @@ default_collect_symbol_completion_matches_break_on
          {
            if (code == TYPE_CODE_UNDEF)
              {
-               completion_list_add_symbol (tracker, sym,
-                                           sym_text, sym_text_len, text,
-                                           word);
-               completion_list_add_fields (tracker, sym,
-                                           sym_text, sym_text_len, text,
-                                           word);
+               completion_list_add_symbol (tracker, sym, lookup_name,
+                                           sym_text, word);
+               completion_list_add_fields (tracker, sym, lookup_name,
+                                           sym_text, word);
              }
            else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
                     && TYPE_CODE (SYMBOL_TYPE (sym)) == code)
-             completion_list_add_symbol (tracker, sym,
-                                         sym_text, sym_text_len, text,
-                                         word);
+             completion_list_add_symbol (tracker, sym, lookup_name,
+                                         sym_text, word);
          }
 
        /* Stop when we encounter an enclosing function.  Do not stop for
@@ -5052,13 +5353,13 @@ default_collect_symbol_completion_matches_break_on
     {
       if (surrounding_static_block != NULL)
        ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym)
-         completion_list_add_fields (tracker, sym,
-                                     sym_text, sym_text_len, text, word);
+         completion_list_add_fields (tracker, sym, lookup_name,
+                                     sym_text, word);
 
       if (surrounding_global_block != NULL)
        ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym)
-         completion_list_add_fields (tracker, sym,
-                                     sym_text, sym_text_len, text, word);
+         completion_list_add_fields (tracker, sym, lookup_name,
+                                     sym_text, word);
     }
 
   /* Skip macros if we are completing a struct tag -- arguable but
@@ -5066,7 +5367,7 @@ default_collect_symbol_completion_matches_break_on
   if (current_language->la_macro_expansion == macro_expansion_c
       && code == TYPE_CODE_UNDEF)
     {
-      struct macro_scope *scope;
+      gdb::unique_xmalloc_ptr<struct macro_scope> scope;
 
       /* This adds a macro's name to the current completion list.  */
       auto add_macro_name = [&] (const char *macro_name,
@@ -5074,9 +5375,8 @@ default_collect_symbol_completion_matches_break_on
                                 macro_source_file *,
                                 int)
        {
-         completion_list_add_name (tracker, macro_name,
-                                   sym_text, sym_text_len,
-                                   text, word);
+         completion_list_add_name (tracker, language_c, macro_name,
+                                   lookup_name, sym_text, word);
        };
 
       /* Add any macros visible in the default scope.  Note that this
@@ -5088,11 +5388,8 @@ default_collect_symbol_completion_matches_break_on
         completion time.  */
       scope = default_macro_scope ();
       if (scope)
-       {
-         macro_for_each_in_scope (scope->file, scope->line,
-                                  add_macro_name);
-         xfree (scope);
-       }
+       macro_for_each_in_scope (scope->file, scope->line,
+                                add_macro_name);
 
       /* User-defined macros are always visible.  */
       macro_for_each (macro_user_macros, add_macro_name);
@@ -5102,10 +5399,12 @@ default_collect_symbol_completion_matches_break_on
 void
 default_collect_symbol_completion_matches (completion_tracker &tracker,
                                           complete_symbol_mode mode,
+                                          symbol_name_match_type name_match_type,
                                           const char *text, const char *word,
                                           enum type_code code)
 {
   return default_collect_symbol_completion_matches_break_on (tracker, mode,
+                                                            name_match_type,
                                                             text, word, "",
                                                             code);
 }
@@ -5116,9 +5415,11 @@ default_collect_symbol_completion_matches (completion_tracker &tracker,
 void
 collect_symbol_completion_matches (completion_tracker &tracker,
                                   complete_symbol_mode mode,
+                                  symbol_name_match_type name_match_type,
                                   const char *text, const char *word)
 {
   current_language->la_collect_symbol_completion_matches (tracker, mode,
+                                                         name_match_type,
                                                          text, word,
                                                          TYPE_CODE_UNDEF);
 }
@@ -5132,11 +5433,13 @@ collect_symbol_completion_matches_type (completion_tracker &tracker,
                                        enum type_code code)
 {
   complete_symbol_mode mode = complete_symbol_mode::EXPRESSION;
+  symbol_name_match_type name_match_type = symbol_name_match_type::EXPRESSION;
 
   gdb_assert (code == TYPE_CODE_UNION
              || code == TYPE_CODE_STRUCT
              || code == TYPE_CODE_ENUM);
   current_language->la_collect_symbol_completion_matches (tracker, mode,
+                                                         name_match_type,
                                                          text, word, code);
 }
 
@@ -5146,13 +5449,12 @@ collect_symbol_completion_matches_type (completion_tracker &tracker,
 void
 collect_file_symbol_completion_matches (completion_tracker &tracker,
                                        complete_symbol_mode mode,
+                                       symbol_name_match_type name_match_type,
                                        const char *text, const char *word,
                                        const char *srcfile)
 {
   /* The symbol we are completing on.  Points in same buffer as text.  */
   const char *sym_text;
-  /* Length of sym_text.  */
-  int sym_text_len;
 
   /* Now look for the symbol we are supposed to complete on.
      FIXME: This should be language-specific.  */
@@ -5200,16 +5502,15 @@ collect_file_symbol_completion_matches (completion_tracker &tracker,
       }
   }
 
-  sym_text_len = strlen (sym_text);
+  lookup_name_info lookup_name (sym_text, name_match_type, true);
 
   /* Go through symtabs for SRCFILE and check the externs and statics
      for symbols which match.  */
   iterate_over_symtabs (srcfile, [&] (symtab *s)
     {
       add_symtab_completions (SYMTAB_COMPUNIT (s),
-                             tracker,
-                             sym_text, sym_text_len,
-                             text, word, TYPE_CODE_UNDEF);
+                             tracker, mode, lookup_name,
+                             sym_text, word, TYPE_CODE_UNDEF);
       return false;
     });
 }
@@ -5222,30 +5523,7 @@ static void
 add_filename_to_list (const char *fname, const char *text, const char *word,
                      completion_list *list)
 {
-  char *newobj;
-  size_t fnlen = strlen (fname);
-
-  if (word == text)
-    {
-      /* Return exactly fname.  */
-      newobj = (char *) xmalloc (fnlen + 5);
-      strcpy (newobj, fname);
-    }
-  else if (word > text)
-    {
-      /* Return some portion of fname.  */
-      newobj = (char *) xmalloc (fnlen + 5);
-      strcpy (newobj, fname + (word - text));
-    }
-  else
-    {
-      /* Return some of TEXT plus fname.  */
-      newobj = (char *) xmalloc (fnlen + (text - word) + 5);
-      strncpy (newobj, word, text - word);
-      newobj[text - word] = '\0';
-      strcat (newobj, fname);
-    }
-  list->emplace_back (newobj);
+  list->emplace_back (make_completion_match_str (fname, text, word));
 }
 
 static int
@@ -5312,9 +5590,6 @@ maybe_add_partial_symtab_filename (const char *filename, const char *fullname,
 completion_list
 make_source_files_completion_list (const char *text, const char *word)
 {
-  struct compunit_symtab *cu;
-  struct symtab *s;
-  struct objfile *objfile;
   size_t text_len = strlen (text);
   completion_list list;
   const char *base_name;
@@ -5325,28 +5600,34 @@ make_source_files_completion_list (const char *text, const char *word)
 
   filename_seen_cache filenames_seen;
 
-  ALL_FILETABS (objfile, cu, s)
+  for (objfile *objfile : all_objfiles (current_program_space))
     {
-      if (not_interesting_fname (s->filename))
-       continue;
-      if (!filenames_seen.seen (s->filename)
-         && filename_ncmp (s->filename, text, text_len) == 0)
-       {
-         /* This file matches for a completion; add it to the current
-            list of matches.  */
-         add_filename_to_list (s->filename, text, word, &list);
-       }
-      else
+      for (compunit_symtab *cu : objfile_compunits (objfile))
        {
-         /* NOTE: We allow the user to type a base name when the
-            debug info records leading directories, but not the other
-            way around.  This is what subroutines of breakpoint
-            command do when they parse file names.  */
-         base_name = lbasename (s->filename);
-         if (base_name != s->filename
-             && !filenames_seen.seen (base_name)
-             && filename_ncmp (base_name, text, text_len) == 0)
-           add_filename_to_list (base_name, text, word, &list);
+         for (symtab *s : compunit_filetabs (cu))
+           {
+             if (not_interesting_fname (s->filename))
+               continue;
+             if (!filenames_seen.seen (s->filename)
+                 && filename_ncmp (s->filename, text, text_len) == 0)
+               {
+                 /* This file matches for a completion; add it to the current
+                    list of matches.  */
+                 add_filename_to_list (s->filename, text, word, &list);
+               }
+             else
+               {
+                 /* NOTE: We allow the user to type a base name when the
+                    debug info records leading directories, but not the other
+                    way around.  This is what subroutines of breakpoint
+                    command do when they parse file names.  */
+                 base_name = lbasename (s->filename);
+                 if (base_name != s->filename
+                     && !filenames_seen.seen (base_name)
+                     && filename_ncmp (base_name, text, text_len) == 0)
+                   add_filename_to_list (base_name, text, word, &list);
+               }
+           }
        }
     }
 
@@ -5429,7 +5710,6 @@ static void
 find_main_name (void)
 {
   const char *new_main_name;
-  struct objfile *objfile;
 
   /* First check the objfiles to see whether a debuginfo reader has
      picked up the appropriate main name.  Historically the main name
@@ -5437,15 +5717,15 @@ find_main_name (void)
      relies on the order of objfile creation -- which still isn't
      guaranteed to get the correct answer, but is just probably more
      accurate.  */
-  ALL_OBJFILES (objfile)
-  {
-    if (objfile->per_bfd->name_of_main != NULL)
-      {
-       set_main_name (objfile->per_bfd->name_of_main,
-                      objfile->per_bfd->language_of_main);
-       return;
-      }
-  }
+  for (objfile *objfile : all_objfiles (current_program_space))
+    {
+      if (objfile->per_bfd->name_of_main != NULL)
+       {
+         set_main_name (objfile->per_bfd->name_of_main,
+                        objfile->per_bfd->language_of_main);
+         return;
+       }
+    }
 
   /* Try to see if the main procedure is in Ada.  */
   /* FIXME: brobecker/2005-03-07: Another way of doing this would
@@ -5705,7 +5985,7 @@ allocate_template_symbol (struct objfile *objfile)
   struct template_symbol *result;
 
   result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
-  initialize_objfile_symbol_1 (&result->base);
+  initialize_objfile_symbol_1 (result);
 
   return result;
 }
@@ -5760,14 +6040,26 @@ _initialize_symtab (void)
   symbol_cache_key
     = register_program_space_data_with_cleanup (NULL, symbol_cache_cleanup);
 
-  add_info ("variables", info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+  add_info ("variables", info_variables_command,
+           info_print_args_help (_("\
+All global and static variable names or those matching REGEXPs.\n\
+Usage: info variables [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+                                 _("global and static variables")));
   if (dbx_commands)
-    add_com ("whereis", class_info, info_variables_command, _("\
-All global and static variable names, or those matching REGEXP."));
+    add_com ("whereis", class_info, info_variables_command,
+            info_print_args_help (_("\
+All global and static variable names, or those matching REGEXPs.\n\
+Usage: whereis [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the global and static variables.\n"),
+                                  _("global and static variables")));
 
   add_info ("functions", info_functions_command,
-           _("All function names, or those matching REGEXP."));
+           info_print_args_help (_("\
+All function names or those matching REGEXPs.\n\
+Usage: info functions [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the functions.\n"),
+                                 _("functions")));
 
   /* FIXME:  This command has at least the following problems:
      1.  It prints builtin types (in a very strange and confusing fashion).
@@ -5851,7 +6143,7 @@ If zero then the symbol cache is disabled."),
           _("Flush the symbol cache for each program space."),
           &maintenancelist);
 
-  observer_attach_executable_changed (symtab_observer_executable_changed);
-  observer_attach_new_objfile (symtab_new_objfile_observer);
-  observer_attach_free_objfile (symtab_free_objfile_observer);
+  gdb::observers::executable_changed.attach (symtab_observer_executable_changed);
+  gdb::observers::new_objfile.attach (symtab_new_objfile_observer);
+  gdb::observers::free_objfile.attach (symtab_free_objfile_observer);
 }
This page took 0.059587 seconds and 4 git commands to generate.