inf-ptrace: Return an IGNORE event if waitpid() fails.
[binutils-gdb.git] / gdb / symtab.c
index 655b3dabf62d1c3cff64aac5e98dab4c96af3bb9..1a39372aad02be4c0cc8f19a9ef24ae04ab46095 100644 (file)
@@ -1,6 +1,6 @@
 /* Symbol table lookup for the GNU debugger, GDB.
 
-   Copyright (C) 1986-2021 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -27,7 +27,7 @@
 #include "symfile.h"
 #include "objfiles.h"
 #include "gdbcmd.h"
-#include "gdb_regex.h"
+#include "gdbsupport/gdb_regex.h"
 #include "expression.h"
 #include "language.h"
 #include "demangle.h"
@@ -47,7 +47,7 @@
 #include "hashtab.h"
 #include "typeprint.h"
 
-#include "gdb_obstack.h"
+#include "gdbsupport/gdb_obstack.h"
 #include "block.h"
 #include "dictionary.h"
 
@@ -331,13 +331,79 @@ search_domain_name (enum search_domain e)
 
 /* See symtab.h.  */
 
+program_space *
+symtab::pspace () const
+{
+  return this->objfile ()->pspace;
+}
+
+/* See symtab.h.  */
+
+call_site *
+compunit_symtab::find_call_site (CORE_ADDR pc) const
+{
+  if (m_call_site_htab == nullptr)
+    return nullptr;
+
+  CORE_ADDR delta
+    = this->objfile ()->section_offsets[this->block_line_section ()];
+  CORE_ADDR unrelocated_pc = pc - delta;
+
+  struct call_site call_site_local (unrelocated_pc, nullptr, nullptr);
+  void **slot
+    = htab_find_slot (m_call_site_htab, &call_site_local, NO_INSERT);
+  if (slot == nullptr)
+    return nullptr;
+
+  return (call_site *) *slot;
+}
+
+/* See symtab.h.  */
+
+void
+compunit_symtab::set_call_site_htab (htab_t call_site_htab)
+{
+  gdb_assert (m_call_site_htab == nullptr);
+  m_call_site_htab = call_site_htab;
+}
+
+/* See symtab.h.  */
+
+void
+compunit_symtab::set_primary_filetab (symtab *primary_filetab)
+{
+  symtab *prev_filetab = nullptr;
+
+  /* Move PRIMARY_FILETAB to the head of the filetab list.  */
+  for (symtab *filetab : this->filetabs ())
+    {
+      if (filetab == primary_filetab)
+       {
+         if (prev_filetab != nullptr)
+           {
+             prev_filetab->next = primary_filetab->next;
+             primary_filetab->next = m_filetabs;
+             m_filetabs = primary_filetab;
+           }
+
+         break;
+       }
+
+      prev_filetab = filetab;
+    }
+
+  gdb_assert (primary_filetab == m_filetabs);
+}
+
+/* See symtab.h.  */
+
 struct symtab *
-compunit_primary_filetab (const struct compunit_symtab *cust)
+compunit_symtab::primary_filetab () const
 {
-  gdb_assert (COMPUNIT_FILETABS (cust) != NULL);
+  gdb_assert (m_filetabs != nullptr);
 
   /* The primary file symtab is the first one in the list.  */
-  return COMPUNIT_FILETABS (cust);
+  return m_filetabs;
 }
 
 /* See symtab.h.  */
@@ -345,11 +411,11 @@ compunit_primary_filetab (const struct compunit_symtab *cust)
 enum language
 compunit_language (const struct compunit_symtab *cust)
 {
-  struct symtab *symtab = compunit_primary_filetab (cust);
+  struct symtab *symtab = cust->primary_filetab ();
 
 /* The language of the compunit symtab is the language of its primary
    source file.  */
-  return SYMTAB_LANGUAGE (symtab);
+  return symtab->language ();
 }
 
 /* See symtab.h.  */
@@ -475,7 +541,7 @@ iterate_over_some_symtabs (const char *name,
 
   for (cust = first; cust != NULL && cust != after_last; cust = cust->next)
     {
-      for (symtab *s : compunit_filetabs (cust))
+      for (symtab *s : cust->filetabs ())
        {
          if (compare_filenames_for_search (s->filename, name))
            {
@@ -791,11 +857,11 @@ create_demangled_names_hash (struct objfile_per_bfd_storage *per_bfd)
 
 /* See symtab.h  */
 
-char *
+gdb::unique_xmalloc_ptr<char>
 symbol_find_demangled_name (struct general_symbol_info *gsymbol,
                            const char *mangled)
 {
-  char *demangled = NULL;
+  gdb::unique_xmalloc_ptr<char> demangled;
   int i;
 
   if (gsymbol->language () == language_unknown)
@@ -901,8 +967,8 @@ general_symbol_info::compute_and_set_names (gdb::string_view linkage_name,
        linkage_name_copy = linkage_name;
 
       if (demangled_name.get () == nullptr)
-        demangled_name.reset
-          (symbol_find_demangled_name (this, linkage_name_copy.data ()));
+        demangled_name
+          = symbol_find_demangled_name (this, linkage_name_copy.data ());
 
       /* Suppose we have demangled_name==NULL, copy_name==0, and
         linkage_name_copy==linkage_name.  In this case, we already have the
@@ -1163,7 +1229,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
   else
     {
       slot_name = slot->value.found.symbol->search_name ();
-      slot_domain = SYMBOL_DOMAIN (slot->value.found.symbol);
+      slot_domain = slot->value.found.symbol->domain ();
     }
 
   /* NULL names match.  */
@@ -1198,7 +1264,7 @@ eq_symbol_entry (const struct symbol_cache_slot *slot,
          struct symbol *sym = slot->value.found.symbol;
          lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
 
-         if (!SYMBOL_MATCHES_SEARCH_NAME (sym, lookup_name))
+         if (!symbol_matches_search_name (sym, lookup_name))
            return 0;
 
          if (!symbol_matches_domain (sym->language (), slot_domain, domain))
@@ -1516,7 +1582,7 @@ symbol_cache_dump (const struct symbol_cache *cache)
                printf_filtered ("  [%4u] = %s, %s %s\n", i,
                                 host_address_to_string (context),
                                 found->print_name (),
-                                domain_name (SYMBOL_DOMAIN (found)));
+                                domain_name (found->domain ()));
                break;
              }
            }
@@ -1609,7 +1675,7 @@ maintenance_print_symbol_cache_statistics (const char *args, int from_tty)
       /* If the cache hasn't been created yet, avoid creating one.  */
       cache = symbol_cache_key.get (pspace);
       if (cache == NULL)
-       printf_filtered ("  empty, no stats available\n");
+       printf_filtered ("  empty, no stats available\n");
       else
        symbol_cache_stats (cache);
     }
@@ -1698,8 +1764,7 @@ fixup_section (struct general_symbol_info *ginfo,
          if (fallback == -1)
            fallback = idx;
 
-         if (obj_section_addr (s) - offset <= addr
-             && addr < obj_section_endaddr (s) - offset)
+         if (s->addr () - offset <= addr && addr < s->endaddr () - offset)
            {
              ginfo->set_section_index (idx);
              return;
@@ -1724,7 +1789,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
   if (!sym)
     return NULL;
 
-  if (!SYMBOL_OBJFILE_OWNED (sym))
+  if (!sym->is_objfile_owned ())
     return sym;
 
   /* We either have an OBJFILE, or we can get at it from the sym's
@@ -1740,7 +1805,7 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
   /* We should have an objfile by now.  */
   gdb_assert (objfile);
 
-  switch (SYMBOL_CLASS (sym))
+  switch (sym->aclass ())
     {
     case LOC_STATIC:
     case LOC_LABEL:
@@ -1829,9 +1894,10 @@ demangle_for_lookup (const char *name, enum language lang,
      lookup, so we can always binary search.  */
   if (lang == language_cplus)
     {
-      char *demangled_name = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
+      gdb::unique_xmalloc_ptr<char> demangled_name
+       = gdb_demangle (name, DMGL_ANSI | DMGL_PARAMS);
       if (demangled_name != NULL)
-       return storage.set_malloc_ptr (demangled_name);
+       return storage.set_malloc_ptr (std::move (demangled_name));
 
       /* If we were given a non-mangled name, canonicalize it
         according to the language (so far only for C++).  */
@@ -1841,16 +1907,16 @@ demangle_for_lookup (const char *name, enum language lang,
     }
   else if (lang == language_d)
     {
-      char *demangled_name = d_demangle (name, 0);
+      gdb::unique_xmalloc_ptr<char> demangled_name = d_demangle (name, 0);
       if (demangled_name != NULL)
-       return storage.set_malloc_ptr (demangled_name);
+       return storage.set_malloc_ptr (std::move (demangled_name));
     }
   else if (lang == language_go)
     {
-      char *demangled_name
+      gdb::unique_xmalloc_ptr<char> demangled_name
        = language_def (language_go)->demangle_symbol (name, 0);
       if (demangled_name != NULL)
-       return storage.set_malloc_ptr (demangled_name);
+       return storage.set_malloc_ptr (std::move (demangled_name));
     }
 
   return name;
@@ -1974,7 +2040,7 @@ check_field (struct type *type, const char *name,
 
   for (i = type->num_fields () - 1; i >= TYPE_N_BASECLASSES (type); i--)
     {
-      const char *t_field_name = TYPE_FIELD_NAME (type, i);
+      const char *t_field_name = type->field (i).name ();
 
       if (t_field_name && (strcmp_iw (t_field_name, name) == 0))
        {
@@ -2064,12 +2130,12 @@ lookup_symbol_aux (const char *name, symbol_name_match_type match_type,
 
       if (result.symbol)
        {
-         struct type *t = result.symbol->type;
+         struct type *t = result.symbol->type ();
 
          /* I'm not really sure that type of this can ever
             be typedefed; just be safe.  */
          t = check_typedef (t);
-         if (t->code () == TYPE_CODE_PTR || TYPE_IS_REFERENCE (t))
+         if (t->is_pointer_or_reference ())
            t = TYPE_TARGET_TYPE (t);
 
          if (t->code () != TYPE_CODE_STRUCT
@@ -2251,7 +2317,7 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile,
       const struct block *block;
       struct block_symbol result;
 
-      bv = COMPUNIT_BLOCKVECTOR (cust);
+      bv = cust->blockvector ();
       block = BLOCKVECTOR_BLOCK (bv, block_index);
       result.symbol = block_lookup_symbol_primary (block, name, domain);
       result.block = block;
@@ -2263,7 +2329,7 @@ lookup_symbol_in_objfile_symtabs (struct objfile *objfile,
          break;
        }
       if (symbol_matches_domain (result.symbol->language (),
-                                SYMBOL_DOMAIN (result.symbol), domain))
+                                result.symbol->domain (), domain))
        {
          struct symbol *better
            = better_symbol (other.symbol, result.symbol, domain);
@@ -2346,7 +2412,7 @@ Internal: %s symbol `%s' found in %s psymtab but not in symtab.\n\
 (if a template, try specifying an instantiation: %s<type>)."),
         block_index == GLOBAL_BLOCK ? "global" : "static",
         name,
-        symtab_to_filename_for_display (compunit_primary_filetab (cust)),
+        symtab_to_filename_for_display (cust->primary_filetab ()),
         name, name);
 }
 
@@ -2384,7 +2450,7 @@ lookup_symbol_via_quick_fns (struct objfile *objfile,
       return {};
     }
 
-  bv = COMPUNIT_BLOCKVECTOR (cust);
+  bv = cust->blockvector ();
   block = BLOCKVECTOR_BLOCK (bv, block_index);
   result.symbol = block_lookup_symbol (block, name,
                                       symbol_name_match_type::FULL, domain);
@@ -2734,14 +2800,14 @@ basic_lookup_transparent_type_quick (struct objfile *objfile,
   if (cust == NULL)
     return NULL;
 
-  bv = COMPUNIT_BLOCKVECTOR (cust);
+  bv = cust->blockvector ();
   block = BLOCKVECTOR_BLOCK (bv, block_index);
   sym = block_find_symbol (block, name, STRUCT_DOMAIN,
                           block_find_non_opaque_type, NULL);
   if (sym == NULL)
     error_in_psymtab_expansion (block_index, name, cust);
-  gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
-  return SYMBOL_TYPE (sym);
+  gdb_assert (!TYPE_IS_OPAQUE (sym->type ()));
+  return sym->type ();
 }
 
 /* Subroutine of basic_lookup_transparent_type to simplify it.
@@ -2759,14 +2825,14 @@ basic_lookup_transparent_type_1 (struct objfile *objfile,
 
   for (compunit_symtab *cust : objfile->compunits ())
     {
-      bv = COMPUNIT_BLOCKVECTOR (cust);
+      bv = cust->blockvector ();
       block = BLOCKVECTOR_BLOCK (bv, block_index);
       sym = block_find_symbol (block, name, STRUCT_DOMAIN,
                               block_find_non_opaque_type, NULL);
       if (sym != NULL)
        {
-         gdb_assert (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)));
-         return SYMBOL_TYPE (sym);
+         gdb_assert (!TYPE_IS_OPAQUE (sym->type ()));
+         return sym->type ();
        }
     }
 
@@ -2840,7 +2906,7 @@ iterate_over_symbols (const struct block *block,
 
   ALL_BLOCK_SYMBOLS_WITH_NAME (block, name, iter, sym)
     {
-      if (symbol_matches_domain (sym->language (), SYMBOL_DOMAIN (sym), domain))
+      if (symbol_matches_domain (sym->language (), sym->domain (), domain))
        {
          struct block_symbol block_sym = {sym, block};
 
@@ -2904,7 +2970,7 @@ find_pc_sect_compunit_symtab (CORE_ADDR pc, struct obj_section *section)
     {
       for (compunit_symtab *cust : obj_file->compunits ())
        {
-         const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust);
+         const struct blockvector *bv = cust->blockvector ();
          const struct block *global_block
            = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
          CORE_ADDR start = BLOCK_START (global_block);
@@ -3010,7 +3076,7 @@ find_symbol_at_address (CORE_ADDR address)
      ADDR.  */
   auto search_symtab = [] (compunit_symtab *symtab, CORE_ADDR addr) -> symbol *
     {
-      const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (symtab);
+      const struct blockvector *bv = symtab->blockvector ();
 
       for (int i = GLOBAL_BLOCK; i <= STATIC_BLOCK; ++i)
        {
@@ -3020,7 +3086,7 @@ find_symbol_at_address (CORE_ADDR address)
 
          ALL_BLOCK_SYMBOLS (b, iter, sym)
            {
-             if (SYMBOL_CLASS (sym) == LOC_STATIC
+             if (sym->aclass () == LOC_STATIC
                  && SYMBOL_VALUE_ADDRESS (sym) == addr)
                return sym;
            }
@@ -3218,16 +3284,16 @@ find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
       return val;
     }
 
-  bv = COMPUNIT_BLOCKVECTOR (cust);
+  bv = cust->blockvector ();
 
   /* Look at all the symtabs that share this blockvector.
      They all have the same apriori range, that we found was right;
      but they have different line tables.  */
 
-  for (symtab *iter_s : compunit_filetabs (cust))
+  for (symtab *iter_s : cust->filetabs ())
     {
       /* Find the best line in this symtab.  */
-      l = SYMTAB_LINETABLE (iter_s);
+      l = iter_s->linetable ();
       if (!l)
        continue;
       len = l->nitems;
@@ -3396,7 +3462,7 @@ find_line_symtab (struct symtab *sym_tab, int line,
   struct symtab *best_symtab;
 
   /* First try looking it up in the given symtab.  */
-  best_linetable = SYMTAB_LINETABLE (sym_tab);
+  best_linetable = sym_tab->linetable ();
   best_symtab = sym_tab;
   best_index = find_line_common (best_linetable, line, &exact, 0);
   if (best_index < 0 || !exact)
@@ -3425,7 +3491,7 @@ find_line_symtab (struct symtab *sym_tab, int line,
        {
          for (compunit_symtab *cu : objfile->compunits ())
            {
-             for (symtab *s : compunit_filetabs (cu))
+             for (symtab *s : cu->filetabs ())
                {
                  struct linetable *l;
                  int ind;
@@ -3435,7 +3501,7 @@ find_line_symtab (struct symtab *sym_tab, int line,
                  if (FILENAME_CMP (symtab_to_fullname (sym_tab),
                                    symtab_to_fullname (s)) != 0)
                    continue;   
-                 l = SYMTAB_LINETABLE (s);
+                 l = s->linetable ();
                  ind = find_line_common (l, line, &exact, 0);
                  if (ind >= 0)
                    {
@@ -3487,14 +3553,14 @@ find_pcs_for_symtab_line (struct symtab *symtab, int line,
       int was_exact;
       int idx;
 
-      idx = find_line_common (SYMTAB_LINETABLE (symtab), line, &was_exact,
+      idx = find_line_common (symtab->linetable (), line, &was_exact,
                              start);
       if (idx < 0)
        break;
 
       if (!was_exact)
        {
-         struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
+         struct linetable_entry *item = &symtab->linetable ()->item[idx];
 
          if (*best_item == NULL
              || (item->line < (*best_item)->line && item->is_stmt))
@@ -3503,7 +3569,7 @@ find_pcs_for_symtab_line (struct symtab *symtab, int line,
          break;
        }
 
-      result.push_back (SYMTAB_LINETABLE (symtab)->item[idx].pc);
+      result.push_back (symtab->linetable ()->item[idx].pc);
       start = idx + 1;
     }
 
@@ -3528,7 +3594,7 @@ find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
   symtab = find_line_symtab (symtab, line, &ind, NULL);
   if (symtab != NULL)
     {
-      l = SYMTAB_LINETABLE (symtab);
+      l = symtab->linetable ();
       *pc = l->item[ind].pc;
       return true;
     }
@@ -3651,10 +3717,10 @@ find_function_start_sal_1 (CORE_ADDR func_addr, obj_section *section,
   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))
+      && (sal.symtab->compunit ()->locations_valid ()
+         || sal.symtab->language () == language_asm))
     {
-      struct gdbarch *gdbarch = SYMTAB_OBJFILE (sal.symtab)->arch ();
+      struct gdbarch *gdbarch = sal.symtab->objfile ()->arch ();
 
       sal.pc = func_addr;
       if (gdbarch_skip_entrypoint_p (gdbarch))
@@ -3725,7 +3791,7 @@ skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab)
   int i;
 
   /* Give up if this symbol has no lineinfo table.  */
-  l = SYMTAB_LINETABLE (symtab);
+  l = symtab->linetable ();
   if (l == NULL)
     return func_addr;
 
@@ -3782,7 +3848,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
      is likely to be the wrong choice.  */
   if (sal->symtab != nullptr
       && sal->explicit_line
-      && SYMTAB_LANGUAGE (sal->symtab) == language_asm)
+      && sal->symtab->language () == language_asm)
     return;
 
   scoped_restore_current_pspace_and_thread restore_pspace_thread;
@@ -3827,7 +3893,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
      have proven the CU (Compilation Unit) supports it.  sal->SYMTAB does not
      have to be set by the caller so we use SYM instead.  */
   if (sym != NULL
-      && COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (symbol_symtab (sym))))
+      && symbol_symtab (sym)->compunit ()->locations_valid ())
     force_skip = 0;
 
   saved_pc = pc;
@@ -3921,9 +3987,9 @@ skip_prologue_sal (struct symtab_and_line *sal)
       b = BLOCK_SUPERBLOCK (b);
     }
   if (function_block != NULL
-      && SYMBOL_LINE (BLOCK_FUNCTION (function_block)) != 0)
+      && BLOCK_FUNCTION (function_block)->line () != 0)
     {
-      sal->line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
+      sal->line = BLOCK_FUNCTION (function_block)->line ();
       sal->symtab = symbol_symtab (BLOCK_FUNCTION (function_block));
     }
 }
@@ -3965,9 +4031,9 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
         The GNU assembler emits separate line notes for each instruction
         in a multi-instruction macro, but compilers generally will not
         do this.  */
-      if (prologue_sal.symtab->language != language_asm)
+      if (prologue_sal.symtab->language () != language_asm)
        {
-         struct linetable *linetable = SYMTAB_LINETABLE (prologue_sal.symtab);
+         struct linetable *linetable = prologue_sal.symtab->linetable ();
          int idx = 0;
 
          /* Skip any earlier lines, and any end-of-sequence marker
@@ -4053,7 +4119,7 @@ find_function_alias_target (bound_minimal_symbol msymbol)
 
   symbol *sym = find_pc_function (func_addr);
   if (sym != NULL
-      && SYMBOL_CLASS (sym) == LOC_BLOCK
+      && sym->aclass () == LOC_BLOCK
       && BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym)) == func_addr)
     return sym;
 
@@ -4200,48 +4266,131 @@ operator_chars (const char *p, const char **end)
 }
 \f
 
-/* What part to match in a file name.  */
+/* See class declaration.  */
 
-struct filename_partial_match_opts
+info_sources_filter::info_sources_filter (match_on match_type,
+                                          const char *regexp)
+  : m_match_type (match_type),
+    m_regexp (regexp)
 {
-  /* Only match the directory name part.   */
-  bool dirname = false;
+  /* Setup the compiled regular expression M_C_REGEXP based on M_REGEXP.  */
+  if (m_regexp != nullptr && *m_regexp != '\0')
+    {
+      gdb_assert (m_regexp != nullptr);
 
-  /* Only match the basename part.  */
-  bool basename = false;
-};
+      int cflags = REG_NOSUB;
+#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
+      cflags |= REG_ICASE;
+#endif
+      m_c_regexp.emplace (m_regexp, cflags, _("Invalid regexp"));
+    }
+}
 
-/* Data structure to maintain printing state for output_source_filename.  */
+/* See class declaration.  */
 
-struct output_source_filename_data
+bool
+info_sources_filter::matches (const char *fullname) const
 {
-  /* Output only filenames matching REGEXP.  */
-  std::string regexp;
-  gdb::optional<compiled_regex> c_regexp;
-  /* Possibly only match a part of the filename.  */
-  filename_partial_match_opts partial_match;
+  /* Does it match regexp?  */
+  if (m_c_regexp.has_value ())
+    {
+      const char *to_match;
+      std::string dirname;
 
+      switch (m_match_type)
+        {
+        case match_on::DIRNAME:
+          dirname = ldirname (fullname);
+          to_match = dirname.c_str ();
+          break;
+        case match_on::BASENAME:
+          to_match = lbasename (fullname);
+          break;
+        case match_on::FULLNAME:
+          to_match = fullname;
+          break;
+       default:
+         gdb_assert_not_reached ("bad m_match_type");
+        }
+
+      if (m_c_regexp->exec (to_match, 0, NULL, 0) != 0)
+        return false;
+    }
 
-  /* Cache of what we've seen so far.  */
-  struct filename_seen_cache *filename_seen_cache;
+  return true;
+}
 
-  /* Flag of whether we're printing the first one.  */
-  int first;
+/* Data structure to maintain the state used for printing the results of
+   the 'info sources' command.  */
 
-  /* Worker for sources_info.  Force line breaks at ,'s.
-     NAME is the name to print.  */
-  void output (const char *name);
+struct output_source_filename_data
+{
+  /* Create an object for displaying the results of the 'info sources'
+     command to UIOUT.  FILTER must remain valid and unchanged for the
+     lifetime of this object as this object retains a reference to FILTER.  */
+  output_source_filename_data (struct ui_out *uiout,
+                              const info_sources_filter &filter)
+    : m_filter (filter),
+      m_uiout (uiout)
+  { /* Nothing.  */ }
+
+  DISABLE_COPY_AND_ASSIGN (output_source_filename_data);
+
+  /* Reset enough state of this object so we can match against a new set of
+     files.  The existing regular expression is retained though.  */
+  void reset_output ()
+  {
+    m_first = true;
+    m_filename_seen_cache.clear ();
+  }
+
+  /* Worker for sources_info, outputs the file name formatted for either
+     cli or mi (based on the current_uiout).  In cli mode displays
+     FULLNAME with a comma separating this name from any previously
+     printed name (line breaks are added at the comma).  In MI mode
+     outputs a tuple containing DISP_NAME (the files display name),
+     FULLNAME, and EXPANDED_P (true when this file is from a fully
+     expanded symtab, otherwise false).  */
+  void output (const char *disp_name, const char *fullname, bool expanded_p);
 
   /* An overload suitable for use as a callback to
      quick_symbol_functions::map_symbol_filenames.  */
   void operator() (const char *filename, const char *fullname)
   {
-    output (fullname != nullptr ? fullname : filename);
+    /* The false here indicates that this file is from an unexpanded
+       symtab.  */
+    output (filename, fullname, false);
+  }
+
+  /* Return true if at least one filename has been printed (after a call to
+     output) since either this object was created, or the last call to
+     reset_output.  */
+  bool printed_filename_p () const
+  {
+    return !m_first;
   }
+
+private:
+
+  /* Flag of whether we're printing the first one.  */
+  bool m_first = true;
+
+  /* Cache of what we've seen so far.  */
+  filename_seen_cache m_filename_seen_cache;
+
+  /* How source filename should be filtered.  */
+  const info_sources_filter &m_filter;
+
+  /* The object to which output is sent.  */
+  struct ui_out *m_uiout;
 };
 
+/* See comment in class declaration above.  */
+
 void
-output_source_filename_data::output (const char *name)
+output_source_filename_data::output (const char *disp_name,
+                                    const char *fullname,
+                                    bool expanded_p)
 {
   /* Since a single source file can result in several partial symbol
      tables, we need to avoid printing it more than once.  Note: if
@@ -4252,42 +4401,52 @@ output_source_filename_data::output (const char *name)
      situation.  I'm not sure whether this can also happen for
      symtabs; it doesn't hurt to check.  */
 
-  /* Was NAME already seen?  */
-  if (filename_seen_cache->seen (name))
-    {
-      /* Yes; don't print it again.  */
-      return;
-    }
-
-  /* Does it match regexp?  */
-  if (c_regexp.has_value ())
-    {
-      const char *to_match;
-      std::string dirname;
+  /* Was NAME already seen?  If so, then don't print it again.  */
+  if (m_filename_seen_cache.seen (fullname))
+    return;
 
-      if (partial_match.dirname)
-       {
-         dirname = ldirname (name);
-         to_match = dirname.c_str ();
-       }
-      else if (partial_match.basename)
-       to_match = lbasename (name);
-      else
-       to_match = name;
+  /* If the filter rejects this file then don't print it.  */
+  if (!m_filter.matches (fullname))
+    return;
 
-      if (c_regexp->exec (to_match, 0, NULL, 0) != 0)
-       return;
-    }
+  ui_out_emit_tuple ui_emitter (m_uiout, nullptr);
 
   /* Print it and reset *FIRST.  */
-  if (! first)
-    printf_filtered (", ");
-  first = 0;
+  if (!m_first)
+    m_uiout->text (", ");
+  m_first = false;
 
-  wrap_here ("");
-  fputs_styled (name, file_name_style.style (), gdb_stdout);
+  m_uiout->wrap_hint (0);
+  if (m_uiout->is_mi_like_p ())
+    {
+      m_uiout->field_string ("file", disp_name, file_name_style.style ());
+      if (fullname != nullptr)
+       m_uiout->field_string ("fullname", fullname,
+                              file_name_style.style ());
+      m_uiout->field_string ("debug-fully-read",
+                            (expanded_p ? "true" : "false"));
+    }
+  else
+    {
+      if (fullname == nullptr)
+       fullname = disp_name;
+      m_uiout->field_string ("fullname", fullname,
+                            file_name_style.style ());
+    }
 }
 
+/* For the 'info sources' command, what part of the file names should we be
+   matching the user supplied regular expression against?  */
+
+struct filename_partial_match_opts
+{
+  /* Only match the directory name part.   */
+  bool dirname = false;
+
+  /* Only match the basename part.  */
+  bool basename = false;
+};
+
 using isrc_flag_option_def
   = gdb::option::flag_option_def<filename_partial_match_opts>;
 
@@ -4316,31 +4475,6 @@ make_info_sources_options_def_group (filename_partial_match_opts *isrc_opts)
   return {{info_sources_option_defs}, isrc_opts};
 }
 
-/* Prints the header message for the source files that will be printed
-   with the matching info present in DATA.  SYMBOL_MSG is a message
-   that tells what will or has been done with the symbols of the
-   matching source files.  */
-
-static void
-print_info_sources_header (const char *symbol_msg,
-                          const struct output_source_filename_data *data)
-{
-  puts_filtered (symbol_msg);
-  if (!data->regexp.empty ())
-    {
-      if (data->partial_match.dirname)
-       printf_filtered (_("(dirname matching regular expression \"%s\")"),
-                        data->regexp.c_str ());
-      else if (data->partial_match.basename)
-       printf_filtered (_("(basename matching regular expression \"%s\")"),
-                        data->regexp.c_str ());
-      else
-       printf_filtered (_("(filename matching regular expression \"%s\")"),
-                        data->regexp.c_str ());
-    }
-  puts_filtered ("\n");
-}
-
 /* Completer for "info sources".  */
 
 static void
@@ -4354,71 +4488,116 @@ info_sources_command_completer (cmd_list_element *ignore,
     return;
 }
 
-static void
-info_sources_command (const char *args, int from_tty)
-{
-  struct output_source_filename_data data;
-
-  if (!have_full_symbols () && !have_partial_symbols ())
-    {
-      error (_("No symbol table is loaded.  Use the \"file\" command."));
-    }
-
-  filename_seen_cache filenames_seen;
-
-  auto group = make_info_sources_options_def_group (&data.partial_match);
-
-  gdb::option::process_options
-    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
-
-  if (args != NULL && *args != '\000')
-    data.regexp = args;
-
-  data.filename_seen_cache = &filenames_seen;
-  data.first = 1;
+/* See symtab.h.  */
 
-  if (data.partial_match.dirname && data.partial_match.basename)
-    error (_("You cannot give both -basename and -dirname to 'info sources'."));
-  if ((data.partial_match.dirname || data.partial_match.basename)
-      && data.regexp.empty ())
-     error (_("Missing REGEXP for 'info sources'."));
+void
+info_sources_worker (struct ui_out *uiout,
+                    bool group_by_objfile,
+                    const info_sources_filter &filter)
+{
+  output_source_filename_data data (uiout, filter);
 
-  if (data.regexp.empty ())
-    data.c_regexp.reset ();
-  else
-    {
-      int cflags = REG_NOSUB;
-#ifdef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
-      cflags |= REG_ICASE;
-#endif
-      data.c_regexp.emplace (data.regexp.c_str (), cflags,
-                            _("Invalid regexp"));
-    }
+  ui_out_emit_list results_emitter (uiout, "files");
+  gdb::optional<ui_out_emit_tuple> output_tuple;
+  gdb::optional<ui_out_emit_list> sources_list;
 
-  print_info_sources_header
-    (_("Source files for which symbols have been read in:\n"), &data);
+  gdb_assert (group_by_objfile || uiout->is_mi_like_p ());
 
   for (objfile *objfile : current_program_space->objfiles ())
     {
+      if (group_by_objfile)
+       {
+         output_tuple.emplace (uiout, nullptr);
+         uiout->field_string ("filename", objfile_name (objfile));
+         uiout->text (":\n");
+         bool debug_fully_readin = !objfile->has_unexpanded_symtabs ();
+         if (uiout->is_mi_like_p ())
+           {
+             const char *debug_info_state;
+             if (objfile_has_symbols (objfile))
+               {
+                 if (debug_fully_readin)
+                   debug_info_state = "fully-read";
+                 else
+                   debug_info_state = "partially-read";
+               }
+             else
+               debug_info_state = "none";
+             current_uiout->field_string ("debug-info", debug_info_state);
+           }
+         else
+           {
+             if (!debug_fully_readin)
+               uiout->text ("(Full debug information has not yet been read "
+                            "for this file.)\n");
+             if (!objfile_has_symbols (objfile))
+               uiout->text ("(Objfile has no debug information.)\n");
+             uiout->text ("\n");
+           }
+         sources_list.emplace (uiout, "sources");
+       }
+
       for (compunit_symtab *cu : objfile->compunits ())
        {
-         for (symtab *s : compunit_filetabs (cu))
+         for (symtab *s : cu->filetabs ())
            {
+             const char *file = symtab_to_filename_for_display (s);
              const char *fullname = symtab_to_fullname (s);
-
-             data.output (fullname);
+             data.output (file, fullname, true);
            }
        }
+
+      if (group_by_objfile)
+       {
+         objfile->map_symbol_filenames (data, true /* need_fullname */);
+         if (data.printed_filename_p ())
+           uiout->text ("\n\n");
+         data.reset_output ();
+         sources_list.reset ();
+         output_tuple.reset ();
+       }
+    }
+
+  if (!group_by_objfile)
+    {
+      data.reset_output ();
+      map_symbol_filenames (data, true /*need_fullname*/);
     }
-  printf_filtered ("\n\n");
+}
+
+/* Implement the 'info sources' command.  */
+
+static void
+info_sources_command (const char *args, int from_tty)
+{
+  if (!have_full_symbols () && !have_partial_symbols ())
+    error (_("No symbol table is loaded.  Use the \"file\" command."));
+
+  filename_partial_match_opts match_opts;
+  auto group = make_info_sources_options_def_group (&match_opts);
+  gdb::option::process_options
+    (&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_ERROR, group);
+
+  if (match_opts.dirname && match_opts.basename)
+    error (_("You cannot give both -basename and -dirname to 'info sources'."));
 
-  print_info_sources_header
-    (_("Source files for which symbols will be read in on demand:\n"), &data);
+  const char *regex = nullptr;
+  if (args != NULL && *args != '\000')
+    regex = args;
+
+  if ((match_opts.dirname || match_opts.basename) && regex == nullptr)
+    error (_("Missing REGEXP for 'info sources'."));
+
+  info_sources_filter::match_on match_type;
+  if (match_opts.dirname)
+    match_type = info_sources_filter::match_on::DIRNAME;
+  else if (match_opts.basename)
+    match_type = info_sources_filter::match_on::BASENAME;
+  else
+    match_type = info_sources_filter::match_on::FULLNAME;
 
-  filenames_seen.clear ();
-  data.first = 1;
-  map_symbol_filenames (data, true /*need_fullname*/);
-  printf_filtered ("\n");
+  info_sources_filter filter (match_type, regex);
+  info_sources_worker (current_uiout, true, filter);
 }
 
 /* Compare FILE against all the entries of FILENAMES.  If BASENAMES is
@@ -4478,7 +4657,7 @@ treg_matches_sym_type_name (const compiled_regex &treg,
                          sym->natural_name ());
     }
 
-  sym_type = SYMBOL_TYPE (sym);
+  sym_type = sym->type ();
   if (sym_type == NULL)
     return false;
 
@@ -4535,11 +4714,16 @@ global_symbol_searcher::expand_symtabs
   enum search_domain kind = m_kind;
   bool found_msymbol = false;
 
+  auto do_file_match = [&] (const char *filename, bool basenames)
+    {
+      return file_matches (filename, filenames, basenames);
+    };
+  gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher = nullptr;
+  if (!filenames.empty ())
+    file_matcher = do_file_match;
+
   objfile->expand_symtabs_matching
-    ([&] (const char *filename, bool basenames)
-     {
-       return file_matches (filename, filenames, basenames);
-     },
+    (file_matcher,
      &lookup_name_info::match_any (),
      [&] (const char *symname)
      {
@@ -4617,7 +4801,7 @@ global_symbol_searcher::add_matching_symbols
   /* Add matching symbols (if not already present).  */
   for (compunit_symtab *cust : objfile->compunits ())
     {
-      const struct blockvector *bv  = COMPUNIT_BLOCKVECTOR (cust);
+      const struct blockvector *bv  = cust->blockvector ();
 
       for (block_enum block : { GLOBAL_BLOCK, STATIC_BLOCK })
        {
@@ -4644,29 +4828,29 @@ global_symbol_searcher::add_matching_symbols
                       || preg->exec (sym->natural_name (), 0,
                                      NULL, 0) == 0)
                      && ((kind == VARIABLES_DOMAIN
-                          && SYMBOL_CLASS (sym) != LOC_TYPEDEF
-                          && SYMBOL_CLASS (sym) != LOC_UNRESOLVED
-                          && SYMBOL_CLASS (sym) != LOC_BLOCK
+                          && sym->aclass () != LOC_TYPEDEF
+                          && sym->aclass () != LOC_UNRESOLVED
+                          && sym->aclass () != 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
-                               && (SYMBOL_TYPE (sym)->code ()
+                          && !(sym->aclass () == LOC_CONST
+                               && (sym->type ()->code ()
                                    == TYPE_CODE_ENUM))
                           && (!treg.has_value ()
                               || treg_matches_sym_type_name (*treg, sym)))
                          || (kind == FUNCTIONS_DOMAIN
-                             && SYMBOL_CLASS (sym) == LOC_BLOCK
+                             && sym->aclass () == LOC_BLOCK
                              && (!treg.has_value ()
                                  || treg_matches_sym_type_name (*treg,
                                                                 sym)))
                          || (kind == TYPES_DOMAIN
-                             && SYMBOL_CLASS (sym) == LOC_TYPEDEF
-                             && SYMBOL_DOMAIN (sym) != MODULE_DOMAIN)
+                             && sym->aclass () == LOC_TYPEDEF
+                             && sym->domain () != MODULE_DOMAIN)
                          || (kind == MODULES_DOMAIN
-                             && SYMBOL_DOMAIN (sym) == MODULE_DOMAIN
-                             && SYMBOL_LINE (sym) != 0))))
+                             && sym->domain () == MODULE_DOMAIN
+                             && sym->line () != 0))))
                {
                  if (result_set->size () < m_max_search_results)
                    {
@@ -4846,7 +5030,7 @@ symbol_to_info_string (struct symbol *sym, int block,
 
   /* Typedef that is not a C++ class.  */
   if (kind == TYPES_DOMAIN
-      && SYMBOL_DOMAIN (sym) != STRUCT_DOMAIN)
+      && sym->domain () != STRUCT_DOMAIN)
     {
       string_file tmp_stream;
 
@@ -4858,21 +5042,21 @@ symbol_to_info_string (struct symbol *sym, int block,
         For the struct printing case below, things are worse, we force
         printing of the ";" in this function, which is going to be wrong
         for languages that don't require a ";" between statements.  */
-      if (SYMBOL_TYPE (sym)->code () == TYPE_CODE_TYPEDEF)
-       typedef_print (SYMBOL_TYPE (sym), sym, &tmp_stream);
+      if (sym->type ()->code () == TYPE_CODE_TYPEDEF)
+       typedef_print (sym->type (), sym, &tmp_stream);
       else
-       type_print (SYMBOL_TYPE (sym), "", &tmp_stream, -1);
+       type_print (sym->type (), "", &tmp_stream, -1);
       str += tmp_stream.string ();
     }
   /* variable, func, or typedef-that-is-c++-class.  */
   else if (kind < TYPES_DOMAIN
           || (kind == TYPES_DOMAIN
-              && SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN))
+              && sym->domain () == STRUCT_DOMAIN))
     {
       string_file tmp_stream;
 
-      type_print (SYMBOL_TYPE (sym),
-                 (SYMBOL_CLASS (sym) == LOC_TYPEDEF
+      type_print (sym->type (),
+                 (sym->aclass () == LOC_TYPEDEF
                   ? "" : sym->print_name ()),
                  &tmp_stream, 0);
 
@@ -4914,8 +5098,8 @@ print_symbol_info (enum search_domain kind,
                                          s_filename));
        }
 
-      if (SYMBOL_LINE (sym) != 0)
-       printf_filtered ("%d:\t", SYMBOL_LINE (sym));
+      if (sym->line () != 0)
+       printf_filtered ("%d:\t", sym->line ());
       else
        puts_filtered ("\t");
     }
@@ -5034,12 +5218,7 @@ struct info_vars_funcs_options
 {
   bool quiet = false;
   bool exclude_minsyms = false;
-  char *type_regexp = nullptr;
-
-  ~info_vars_funcs_options ()
-  {
-    xfree (type_regexp);
-  }
+  std::string type_regexp;
 };
 
 /* The options used by the 'info variables' and 'info functions'
@@ -5062,8 +5241,7 @@ static const gdb::option::option_def info_vars_funcs_options_defs[] = {
 
   gdb::option::string_option_def<info_vars_funcs_options> {
     "t",
-    [] (info_vars_funcs_options *opt) { return &opt->type_regexp;
-  },
+    [] (info_vars_funcs_options *opt) { return &opt->type_regexp; },
     nullptr, /* show_cmd_cb */
     nullptr /* set_doc */
   }
@@ -5107,8 +5285,10 @@ info_variables_command (const char *args, int from_tty)
   if (args != nullptr && *args == '\0')
     args = nullptr;
 
-  symtab_symbol_info (opts.quiet, opts.exclude_minsyms, args, VARIABLES_DOMAIN,
-                     opts.type_regexp, from_tty);
+  symtab_symbol_info
+    (opts.quiet, opts.exclude_minsyms, args, VARIABLES_DOMAIN,
+     opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+     from_tty);
 }
 
 /* Implement the 'info functions' command.  */
@@ -5124,8 +5304,10 @@ info_functions_command (const char *args, int from_tty)
   if (args != nullptr && *args == '\0')
     args = nullptr;
 
-  symtab_symbol_info (opts.quiet, opts.exclude_minsyms, args,
-                     FUNCTIONS_DOMAIN, opts.type_regexp, from_tty);
+  symtab_symbol_info
+    (opts.quiet, opts.exclude_minsyms, args, FUNCTIONS_DOMAIN,
+     opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+     from_tty);
 }
 
 /* Holds the -q option for the 'info types' command.  */
@@ -5343,8 +5525,8 @@ completion_list_add_symbol (completion_tracker &tracker,
      the msymbol name and removes the msymbol name from the completion
      tracker.  */
   if (sym->language () == language_cplus
-      && SYMBOL_DOMAIN (sym) == VAR_DOMAIN
-      && SYMBOL_CLASS (sym) == LOC_BLOCK)
+      && sym->domain () == VAR_DOMAIN
+      && sym->aclass () == LOC_BLOCK)
     {
       /* The call to canonicalize returns the empty string if the input
         string is already in canonical form, thanks to this we don't
@@ -5489,17 +5671,17 @@ completion_list_add_fields (completion_tracker &tracker,
                            const lookup_name_info &lookup_name,
                            const char *text, const char *word)
 {
-  if (SYMBOL_CLASS (sym) == LOC_TYPEDEF)
+  if (sym->aclass () == LOC_TYPEDEF)
     {
-      struct type *t = SYMBOL_TYPE (sym);
+      struct type *t = sym->type ();
       enum type_code c = t->code ();
       int j;
 
       if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT)
        for (j = TYPE_N_BASECLASSES (t); j < t->num_fields (); j++)
-         if (TYPE_FIELD_NAME (t, j))
+         if (t->field (j).name ())
            completion_list_add_name (tracker, sym->language (),
-                                     TYPE_FIELD_NAME (t, j),
+                                     t->field (j).name (),
                                      lookup_name, text, word);
     }
 }
@@ -5509,7 +5691,7 @@ completion_list_add_fields (completion_tracker &tracker,
 bool
 symbol_is_function_or_method (symbol *sym)
 {
-  switch (SYMBOL_TYPE (sym)->code ())
+  switch (sym->type ()->code ())
     {
     case TYPE_CODE_FUNC:
     case TYPE_CODE_METHOD:
@@ -5541,7 +5723,7 @@ symbol_is_function_or_method (minimal_symbol *msymbol)
 bound_minimal_symbol
 find_gnu_ifunc (const symbol *sym)
 {
-  if (SYMBOL_CLASS (sym) != LOC_BLOCK)
+  if (sym->aclass () != LOC_BLOCK)
     return {};
 
   lookup_name_info lookup_name (sym->search_name (),
@@ -5599,15 +5781,15 @@ add_symtab_completions (struct compunit_symtab *cust,
   for (i = GLOBAL_BLOCK; i <= STATIC_BLOCK; i++)
     {
       QUIT;
-      b = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cust), i);
+      b = BLOCKVECTOR_BLOCK (cust->blockvector (), i);
       ALL_BLOCK_SYMBOLS (b, iter, sym)
        {
          if (completion_skip_symbol (mode, sym))
            continue;
 
          if (code == TYPE_CODE_UNDEF
-             || (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
-                 && SYMBOL_TYPE (sym)->code () == code))
+             || (sym->domain () == STRUCT_DOMAIN
+                 && sym->type ()->code () == code))
            completion_list_add_symbol (tracker, sym,
                                        lookup_name,
                                        text, word);
@@ -5637,55 +5819,55 @@ default_collect_symbol_completion_matches_break_on
   if (mode == complete_symbol_mode::LINESPEC)
     sym_text = text;
   else
-  {
-    const char *p;
-    char quote_found;
-    const char *quote_pos = NULL;
+    {
+      const char *p;
+      char quote_found;
+      const char *quote_pos = NULL;
 
-    /* First see if this is a quoted string.  */
-    quote_found = '\0';
-    for (p = text; *p != '\0'; ++p)
-      {
-       if (quote_found != '\0')
-         {
-           if (*p == quote_found)
-             /* Found close quote.  */
-             quote_found = '\0';
-           else if (*p == '\\' && p[1] == quote_found)
-             /* A backslash followed by the quote character
-                doesn't end the string.  */
-             ++p;
-         }
-       else if (*p == '\'' || *p == '"')
-         {
-           quote_found = *p;
-           quote_pos = p;
-         }
-      }
-    if (quote_found == '\'')
-      /* A string within single quotes can be a symbol, so complete on it.  */
-      sym_text = quote_pos + 1;
-    else if (quote_found == '"')
-      /* A double-quoted string is never a symbol, nor does it make sense
-        to complete it any other way.  */
-      {
-       return;
-      }
-    else
-      {
-       /* It is not a quoted string.  Break it based on the characters
-          which are in symbols.  */
-       while (p > text)
-         {
-           if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
-               || p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
-             --p;
-           else
-             break;
-         }
-       sym_text = p;
-      }
-  }
+      /* First see if this is a quoted string.  */
+      quote_found = '\0';
+      for (p = text; *p != '\0'; ++p)
+       {
+         if (quote_found != '\0')
+           {
+             if (*p == quote_found)
+               /* Found close quote.  */
+               quote_found = '\0';
+             else if (*p == '\\' && p[1] == quote_found)
+               /* A backslash followed by the quote character
+                  doesn't end the string.  */
+               ++p;
+           }
+         else if (*p == '\'' || *p == '"')
+           {
+             quote_found = *p;
+             quote_pos = p;
+           }
+       }
+      if (quote_found == '\'')
+       /* A string within single quotes can be a symbol, so complete on it.  */
+       sym_text = quote_pos + 1;
+      else if (quote_found == '"')
+       /* A double-quoted string is never a symbol, nor does it make sense
+          to complete it any other way.  */
+       {
+         return;
+       }
+      else
+       {
+         /* It is not a quoted string.  Break it based on the characters
+            which are in symbols.  */
+         while (p > text)
+           {
+             if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0'
+                 || p[-1] == ':' || strchr (break_on, p[-1]) != NULL)
+               --p;
+             else
+               break;
+           }
+         sym_text = p;
+       }
+    }
 
   lookup_name_info lookup_name (sym_text, name_match_type, true);
 
@@ -5759,8 +5941,8 @@ default_collect_symbol_completion_matches_break_on
                completion_list_add_fields (tracker, sym, lookup_name,
                                            sym_text, word);
              }
-           else if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN
-                    && SYMBOL_TYPE (sym)->code () == code)
+           else if (sym->domain () == STRUCT_DOMAIN
+                    && sym->type ()->code () == code)
              completion_list_add_symbol (tracker, sym, lookup_name,
                                          sym_text, word);
          }
@@ -5874,46 +6056,46 @@ collect_file_symbol_completion_matches (completion_tracker &tracker,
   if (mode == complete_symbol_mode::LINESPEC)
     sym_text = text;
   else
-  {
-    const char *p;
-    char quote_found;
-    const char *quote_pos = NULL;
+    {
+      const char *p;
+      char quote_found;
+      const char *quote_pos = NULL;
 
-    /* First see if this is a quoted string.  */
-    quote_found = '\0';
-    for (p = text; *p != '\0'; ++p)
-      {
-       if (quote_found != '\0')
-         {
-           if (*p == quote_found)
-             /* Found close quote.  */
-             quote_found = '\0';
-           else if (*p == '\\' && p[1] == quote_found)
-             /* A backslash followed by the quote character
-                doesn't end the string.  */
-             ++p;
-         }
-       else if (*p == '\'' || *p == '"')
-         {
-           quote_found = *p;
-           quote_pos = p;
-         }
-      }
-    if (quote_found == '\'')
-      /* A string within single quotes can be a symbol, so complete on it.  */
-      sym_text = quote_pos + 1;
-    else if (quote_found == '"')
-      /* A double-quoted string is never a symbol, nor does it make sense
-        to complete it any other way.  */
-      {
-       return;
-      }
-    else
-      {
-       /* Not a quoted string.  */
-       sym_text = language_search_unquoted_string (text, p);
-      }
-  }
+      /* First see if this is a quoted string.  */
+      quote_found = '\0';
+      for (p = text; *p != '\0'; ++p)
+       {
+         if (quote_found != '\0')
+           {
+             if (*p == quote_found)
+               /* Found close quote.  */
+               quote_found = '\0';
+             else if (*p == '\\' && p[1] == quote_found)
+               /* A backslash followed by the quote character
+                  doesn't end the string.  */
+               ++p;
+           }
+         else if (*p == '\'' || *p == '"')
+           {
+             quote_found = *p;
+             quote_pos = p;
+           }
+       }
+      if (quote_found == '\'')
+       /* A string within single quotes can be a symbol, so complete on it.  */
+       sym_text = quote_pos + 1;
+      else if (quote_found == '"')
+       /* A double-quoted string is never a symbol, nor does it make sense
+          to complete it any other way.  */
+       {
+         return;
+       }
+      else
+       {
+         /* Not a quoted string.  */
+         sym_text = language_search_unquoted_string (text, p);
+       }
+    }
 
   lookup_name_info lookup_name (sym_text, name_match_type, true);
 
@@ -5921,7 +6103,7 @@ collect_file_symbol_completion_matches (completion_tracker &tracker,
      for symbols which match.  */
   iterate_over_symtabs (srcfile, [&] (symtab *s)
     {
-      add_symtab_completions (SYMTAB_COMPUNIT (s),
+      add_symtab_completions (s->compunit (),
                              tracker, mode, lookup_name,
                              sym_text, word, TYPE_CODE_UNDEF);
       return false;
@@ -6016,7 +6198,7 @@ make_source_files_completion_list (const char *text, const char *word)
     {
       for (compunit_symtab *cu : objfile->compunits ())
        {
-         for (symtab *s : compunit_filetabs (cu))
+         for (symtab *s : cu->filetabs ())
            {
              if (not_interesting_fname (s->filename))
                continue;
@@ -6229,13 +6411,12 @@ producer_is_realview (const char *producer)
     "ARM/Thumb C/C++ Compiler, RVCT",
     "ARM C/C++ Compiler, RVCT"
   };
-  int i;
 
   if (producer == NULL)
     return false;
 
-  for (i = 0; i < ARRAY_SIZE (arm_idents); i++)
-    if (startswith (producer, arm_idents[i]))
+  for (const char *ident : arm_idents)
+    if (startswith (producer, ident))
       return true;
 
   return false;
@@ -6353,8 +6534,8 @@ initialize_ordinary_address_classes (void)
 struct objfile *
 symbol_objfile (const struct symbol *symbol)
 {
-  gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
-  return SYMTAB_OBJFILE (symbol->owner.symtab);
+  gdb_assert (symbol->is_objfile_owned ());
+  return symbol->owner.symtab->objfile ();
 }
 
 /* See symtab.h.  */
@@ -6362,9 +6543,9 @@ symbol_objfile (const struct symbol *symbol)
 struct gdbarch *
 symbol_arch (const struct symbol *symbol)
 {
-  if (!SYMBOL_OBJFILE_OWNED (symbol))
+  if (!symbol->is_objfile_owned ())
     return symbol->owner.arch;
-  return SYMTAB_OBJFILE (symbol->owner.symtab)->arch ();
+  return symbol->owner.symtab->objfile ()->arch ();
 }
 
 /* See symtab.h.  */
@@ -6372,7 +6553,7 @@ symbol_arch (const struct symbol *symbol)
 struct symtab *
 symbol_symtab (const struct symbol *symbol)
 {
-  gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
+  gdb_assert (symbol->is_objfile_owned ());
   return symbol->owner.symtab;
 }
 
@@ -6381,7 +6562,7 @@ symbol_symtab (const struct symbol *symbol)
 void
 symbol_set_symtab (struct symbol *symbol, struct symtab *symtab)
 {
-  gdb_assert (SYMBOL_OBJFILE_OWNED (symbol));
+  gdb_assert (symbol->is_objfile_owned ());
   symbol->owner.symtab = symtab;
 }
 
@@ -6391,7 +6572,7 @@ CORE_ADDR
 get_symbol_address (const struct symbol *sym)
 {
   gdb_assert (sym->maybe_copied);
-  gdb_assert (SYMBOL_CLASS (sym) == LOC_STATIC);
+  gdb_assert (sym->aclass () == LOC_STATIC);
 
   const char *linkage_name = sym->linkage_name ();
 
@@ -6637,14 +6818,8 @@ info_module_subcommand (bool quiet, const char *module_regexp,
 struct info_modules_var_func_options
 {
   bool quiet = false;
-  char *type_regexp = nullptr;
-  char *module_regexp = nullptr;
-
-  ~info_modules_var_func_options ()
-  {
-    xfree (type_regexp);
-    xfree (module_regexp);
-  }
+  std::string type_regexp;
+  std::string module_regexp;
 };
 
 /* The options used by 'info module variables' and 'info module functions'
@@ -6694,8 +6869,11 @@ info_module_functions_command (const char *args, int from_tty)
   if (args != nullptr && *args == '\0')
     args = nullptr;
 
-  info_module_subcommand (opts.quiet, opts.module_regexp, args,
-                         opts.type_regexp, FUNCTIONS_DOMAIN);
+  info_module_subcommand
+    (opts.quiet,
+     opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
+     opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+     FUNCTIONS_DOMAIN);
 }
 
 /* Implements the 'info module variables' command.  */
@@ -6710,8 +6888,11 @@ info_module_variables_command (const char *args, int from_tty)
   if (args != nullptr && *args == '\0')
     args = nullptr;
 
-  info_module_subcommand (opts.quiet, opts.module_regexp, args,
-                         opts.type_regexp, VARIABLES_DOMAIN);
+  info_module_subcommand
+    (opts.quiet,
+     opts.module_regexp.empty () ? nullptr : opts.module_regexp.c_str (), args,
+     opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
+     VARIABLES_DOMAIN);
 }
 
 /* Command completer for 'info module ...' sub-commands.  */
@@ -6778,7 +6959,8 @@ Print information about all types matching REGEXP, or all types if no\n\
 REGEXP is given.  The optional flag -q disables printing of headers."));
   set_cmd_completer_handle_brkchars (c, info_types_command_completer);
 
-  const auto info_sources_opts = make_info_sources_options_def_group (nullptr);
+  const auto info_sources_opts
+    = make_info_sources_options_def_group (nullptr);
 
   static std::string info_sources_help
     = gdb::option::build_help (_("\