Enable async mode in the target in attach_cmd.
[binutils-gdb.git] / gdb / linespec.c
index 06ec78bb599b35a074435f17475de8d32a10cd7e..707a3a2586a2ce6d80e5d2f607119befacb78acd 100644 (file)
@@ -1,6 +1,6 @@
 /* Parser for linespec for the GNU debugger, GDB.
 
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "ada-lang.h"
 #include "stack.h"
 #include "location.h"
-#include "common/function-view.h"
-#include "common/def-vector.h"
+#include "gdbsupport/function-view.h"
+#include "gdbsupport/def-vector.h"
 #include <algorithm>
+#include "inferior.h"
 
 /* An enumeration of the various things a user might attempt to
    complete for a linespec location.  */
@@ -72,15 +73,11 @@ enum class linespec_complete_what
   /* An expression.  E.g., "break foo if EXPR", or "break *EXPR".  */
   EXPRESSION,
 
-  /* A linespec keyword ("if"/"thread"/"task").
+  /* A linespec keyword ("if"/"thread"/"task"/"-force-condition").
      E.g., "break func threa<tab>".  */
   KEYWORD,
 };
 
-/* Typedef for unique_ptrs of vectors of symtabs.  */
-
-typedef std::unique_ptr<std::vector<symtab *>> symtab_vector_up;
-
 /* An address entry is used to ensure that any given location is only
    added to the result a single time.  It holds an address and the
    program space from which the address came.  */
@@ -98,29 +95,29 @@ struct address_entry
 struct linespec
 {
   /* An explicit location describing the SaLs.  */
-  struct explicit_location explicit_loc;
+  struct explicit_location explicit_loc {};
+
+  /* The list of symtabs to search to which to limit the search.
 
-  /* The list of symtabs to search to which to limit the search.  May not
-     be NULL.  If explicit.SOURCE_FILENAME is NULL (no user-specified
-     filename), FILE_SYMTABS should contain one single NULL member.  This
-     will cause the code to use the default symtab.  */
-  std::vector<symtab *> *file_symtabs;
+     If explicit.SOURCE_FILENAME is NULL (no user-specified filename),
+     FILE_SYMTABS should contain one single NULL member.  This will cause the
+     code to use the default symtab.  */
+  std::vector<symtab *> file_symtabs;
 
   /* A list of matching function symbols and minimal symbols.  Both lists
-     may be NULL (or empty) if no matching symbols were found.  */
-  std::vector<symbol *> *function_symbols;
-  std::vector<bound_minimal_symbol> *minimal_symbols;
+     may be empty if no matching symbols were found.  */
+  std::vector<block_symbol> function_symbols;
+  std::vector<bound_minimal_symbol> minimal_symbols;
 
   /* A structure of matching label symbols and the corresponding
-     function symbol in which the label was found.  Both may be NULL
-     or both must be non-NULL.  */
+     function symbol in which the label was found.  Both may be empty
+     or both must be non-empty.  */
   struct
   {
-    std::vector<symbol *> *label_symbols;
-    std::vector<symbol *> *function_symbols;
+    std::vector<block_symbol> label_symbols;
+    std::vector<block_symbol> function_symbols;
   } labels;
 };
-typedef struct linespec *linespec_p;
 
 /* A canonical linespec represented as a symtab-related string.
 
@@ -189,31 +186,46 @@ struct collect_info
   struct linespec_state *state;
 
   /* A list of symtabs to which to restrict matches.  */
-  std::vector<symtab *> *file_symtabs;
+  const std::vector<symtab *> *file_symtabs;
 
   /* The result being accumulated.  */
   struct
   {
-    std::vector<symbol *> *symbols;
+    std::vector<block_symbol> *symbols;
     std::vector<bound_minimal_symbol> *minimal_symbols;
   } result;
 
   /* Possibly add a symbol to the results.  */
-  bool add_symbol (symbol *sym);
+  virtual bool add_symbol (block_symbol *bsym);
 };
 
 bool
-collect_info::add_symbol (symbol *sym)
+collect_info::add_symbol (block_symbol *bsym)
 {
   /* In list mode, add all matching symbols, regardless of class.
      This allows the user to type "list a_global_variable".  */
-  if (SYMBOL_CLASS (sym) == LOC_BLOCK || this->state->list_mode)
-    this->result.symbols->push_back (sym);
+  if (bsym->symbol->aclass () == LOC_BLOCK || this->state->list_mode)
+    this->result.symbols->push_back (*bsym);
 
   /* Continue iterating.  */
   return true;
 }
 
+/* Custom collect_info for symbol_searcher.  */
+
+struct symbol_searcher_collect_info
+  : collect_info
+{
+  bool add_symbol (block_symbol *bsym) override
+  {
+    /* Add everything.  */
+    this->result.symbols->push_back (*bsym);
+
+    /* Continue iterating.  */
+    return true;
+  }
+};
+
 /* Token types  */
 
 enum ls_token_type
@@ -243,12 +255,13 @@ typedef enum ls_token_type linespec_token_type;
 
 /* List of keywords.  This is NULL-terminated so that it can be used
    as enum completer.  */
-const char * const linespec_keywords[] = { "if", "thread", "task", NULL };
+const char * const linespec_keywords[] = { "if", "thread", "task", "-force-condition", NULL };
 #define IF_KEYWORD_INDEX 0
+#define FORCE_KEYWORD_INDEX 3
 
 /* A token of the linespec lexer  */
 
-struct ls_token
+struct linespec_token
 {
   /* The type of the token  */
   linespec_token_type type;
@@ -263,15 +276,24 @@ struct ls_token
     const char *keyword;
   } data;
 };
-typedef struct ls_token linespec_token;
 
 #define LS_TOKEN_STOKEN(TOK) (TOK).data.string
 #define LS_TOKEN_KEYWORD(TOK) (TOK).data.keyword
 
 /* An instance of the linespec parser.  */
 
-struct ls_parser
+struct linespec_parser
 {
+  linespec_parser (int flags, const struct language_defn *language,
+                  struct program_space *search_pspace,
+                  struct symtab *default_symtab,
+                  int default_line,
+                  struct linespec_result *canonical);
+
+  ~linespec_parser ();
+
+  DISABLE_COPY_AND_ASSIGN (linespec_parser);
+
   /* Lexer internal data  */
   struct
   {
@@ -284,43 +306,42 @@ struct ls_parser
 
     /* The current token.  */
     linespec_token current;
-  } lexer;
+  } lexer {};
 
   /* Is the entire linespec quote-enclosed?  */
-  int is_quote_enclosed;
+  int is_quote_enclosed = 0;
 
   /* The state of the parse.  */
-  struct linespec_state state;
+  struct linespec_state state {};
 #define PARSER_STATE(PPTR) (&(PPTR)->state)
 
   /* The result of the parse.  */
-  struct linespec result;
+  linespec result;
 #define PARSER_RESULT(PPTR) (&(PPTR)->result)
 
   /* What the parser believes the current word point should complete
      to.  */
-  linespec_complete_what complete_what;
+  linespec_complete_what complete_what = linespec_complete_what::NOTHING;
 
   /* The completion word point.  The parser advances this as it skips
      tokens.  At some point the input string will end or parsing will
      fail, and then we attempt completion at the captured completion
      word point, interpreting the string at completion_word as
      COMPLETE_WHAT.  */
-  const char *completion_word;
+  const char *completion_word = nullptr;
 
   /* If the current token was a quoted string, then this is the
      quoting character (either " or ').  */
-  int completion_quote_char;
+  int completion_quote_char = 0;
 
   /* If the current token was a quoted string, then this points at the
      end of the quoted string.  */
-  const char *completion_quote_end;
+  const char *completion_quote_end = nullptr;
 
   /* If parsing for completion, then this points at the completion
      tracker.  Otherwise, this is NULL.  */
-  struct completion_tracker *completion_tracker;
+  struct completion_tracker *completion_tracker = nullptr;
 };
-typedef struct ls_parser linespec_parser;
 
 /* A convenience macro for accessing the explicit location result of
    the parser.  */
@@ -339,22 +360,23 @@ static void initialize_defaults (struct symtab **default_symtab,
 CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
 
 static std::vector<symtab_and_line> decode_objc (struct linespec_state *self,
-                                                linespec_p ls,
+                                                linespec *ls,
                                                 const char *arg);
 
-static symtab_vector_up symtabs_from_filename
+static std::vector<symtab *> symtabs_from_filename
   (const char *, struct program_space *pspace);
 
-static std::vector<symbol *> *find_label_symbols
-  (struct linespec_state *self, std::vector<symbol *> *function_symbols,
-   std::vector<symbol *> *label_funcs_ret, const char *name,
-   bool completion_mode = false);
+static std::vector<block_symbol> find_label_symbols
+  (struct linespec_state *self,
+   const std::vector<block_symbol> &function_symbols,
+   std::vector<block_symbol> *label_funcs_ret,
+   const char *name, bool completion_mode = false);
 
 static void find_linespec_symbols (struct linespec_state *self,
-                                  std::vector<symtab *> *file_symtabs,
+                                  const std::vector<symtab *> &file_symtabs,
                                   const char *name,
                                   symbol_name_match_type name_match_type,
-                                  std::vector<symbol *> *symbols,
+                                  std::vector<block_symbol> *symbols,
                                   std::vector<bound_minimal_symbol> *minsyms);
 
 static struct line_offset
@@ -374,26 +396,26 @@ static void add_all_symbol_names_from_pspace
     (struct collect_info *info, struct program_space *pspace,
      const std::vector<const char *> &names, enum search_domain search_domain);
 
-static symtab_vector_up
+static std::vector<symtab *>
   collect_symtabs_from_filename (const char *file,
                                 struct program_space *pspace);
 
 static std::vector<symtab_and_line> decode_digits_ordinary
   (struct linespec_state *self,
-   linespec_p ls,
+   linespec *ls,
    int line,
    linetable_entry **best_entry);
 
 static std::vector<symtab_and_line> decode_digits_list_mode
   (struct linespec_state *self,
-   linespec_p ls,
+   linespec *ls,
    struct symtab_and_line val);
 
 static void minsym_found (struct linespec_state *self, struct objfile *objfile,
                          struct minimal_symbol *msymbol,
                          std::vector<symtab_and_line> *result);
 
-static bool compare_symbols (const struct symbol *a, const struct symbol *b);
+static bool compare_symbols (const block_symbol &a, const block_symbol &b);
 
 static bool compare_msymbols (const bound_minimal_symbol &a,
                              const bound_minimal_symbol &b);
@@ -401,7 +423,7 @@ static bool compare_msymbols (const bound_minimal_symbol &a,
 /* Permitted quote characters for the parser.  This is different from the
    completer's quote characters to allow backward compatibility with the
    previous parser.  */
-static const char *const linespec_quote_characters = "\"\'";
+static const char linespec_quote_characters[] = "\"\'";
 
 /* Lexer functions.  */
 
@@ -457,21 +479,45 @@ linespec_lexer_lex_keyword (const char *p)
        {
          int len = strlen (linespec_keywords[i]);
 
-         /* If P begins with one of the keywords and the next
-            character is whitespace, we may have found a keyword.
-            It is only a keyword if it is not followed by another
-            keyword.  */
-         if (strncmp (p, linespec_keywords[i], len) == 0
-             && isspace (p[len]))
+         /* If P begins with
+
+            - "thread" or "task" and the next character is
+            whitespace, we may have found a keyword.  It is only a
+            keyword if it is not followed by another keyword.
+
+            - "-force-condition", the next character may be EOF
+            since this keyword does not take any arguments.  Otherwise,
+            it should be followed by a keyword.
+
+            - "if", ALWAYS stop the lexer, since it is not possible to
+            predict what is going to appear in the condition, which can
+            only be parsed after SaLs have been found.  */
+         if (strncmp (p, linespec_keywords[i], len) == 0)
            {
              int j;
 
-             /* Special case: "if" ALWAYS stops the lexer, since it
-                is not possible to predict what is going to appear in
-                the condition, which can only be parsed after SaLs have
-                been found.  */
-             if (i != IF_KEYWORD_INDEX)
+             if (i == FORCE_KEYWORD_INDEX && p[len] == '\0')
+               return linespec_keywords[i];
+
+             if (!isspace (p[len]))
+               continue;
+
+             if (i == FORCE_KEYWORD_INDEX)
+               {
+                 p += len;
+                 p = skip_spaces (p);
+                 for (j = 0; linespec_keywords[j] != NULL; ++j)
+                   {
+                     int nextlen = strlen (linespec_keywords[j]);
+
+                     if (strncmp (p, linespec_keywords[j], nextlen) == 0
+                         && isspace (p[nextlen]))
+                       return linespec_keywords[i];
+                   }
+               }
+             else if (i != IF_KEYWORD_INDEX)
                {
+                 /* We matched a "thread" or "task".  */
                  p += len;
                  p = skip_spaces (p);
                  for (j = 0; linespec_keywords[j] != NULL; ++j)
@@ -535,7 +581,7 @@ copy_token_string (linespec_token token)
   const char *str, *s;
 
   if (token.type == LSTOKEN_KEYWORD)
-    return gdb::unique_xmalloc_ptr<char> (xstrdup (LS_TOKEN_KEYWORD (token)));
+    return make_unique_xstrdup (LS_TOKEN_KEYWORD (token));
 
   str = LS_TOKEN_STOKEN (token).ptr;
   s = remove_trailing_whitespace (str, str + LS_TOKEN_STOKEN (token).length);
@@ -740,7 +786,9 @@ linespec_lexer_lex_string (linespec_parser *parser)
              /* Do not tokenize ABI tags such as "[abi:cxx11]".  */
              else if (PARSER_STREAM (parser) - start > 4
                       && startswith (PARSER_STREAM (parser) - 4, "[abi"))
-               ++(PARSER_STREAM (parser));
+               {
+                 /* Nothing.  */
+               }
 
              /* Do not tokenify if the input length so far is one
                 (i.e, a single-letter drive name) and the next character
@@ -778,16 +826,16 @@ linespec_lexer_lex_string (linespec_parser *parser)
                      == language_cplus)
                  && (PARSER_STREAM (parser) - start) >= CP_OPERATOR_LEN)
                {
-                 const char *p = PARSER_STREAM (parser);
+                 const char *op = PARSER_STREAM (parser);
 
-                 while (p > start && isspace (p[-1]))
-                   p--;
-                 if (p - start >= CP_OPERATOR_LEN)
+                 while (op > start && isspace (op[-1]))
+                   op--;
+                 if (op - start >= CP_OPERATOR_LEN)
                    {
-                     p -= CP_OPERATOR_LEN;
-                     if (strncmp (p, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
-                         && (p == start
-                             || !(isalnum (p[-1]) || p[-1] == '_')))
+                     op -= CP_OPERATOR_LEN;
+                     if (strncmp (op, CP_OPERATOR_STR, CP_OPERATOR_LEN) == 0
+                         && (op == start
+                             || !(isalnum (op[-1]) || op[-1] == '_')))
                        {
                          /* This is an operator name.  Keep going.  */
                          ++(PARSER_STREAM (parser));
@@ -798,15 +846,15 @@ linespec_lexer_lex_string (linespec_parser *parser)
                    }
                }
 
-             const char *p = find_parameter_list_end (PARSER_STREAM (parser));
-             PARSER_STREAM (parser) = p;
+             const char *end = find_parameter_list_end (PARSER_STREAM (parser));
+             PARSER_STREAM (parser) = end;
 
              /* Don't loop around to the normal \0 case above because
                 we don't want to misinterpret a potential keyword at
                 the end of the token when the string isn't
                 "()<>"-balanced.  This handles "b
                 function(thread<tab>" in completion mode.  */
-             if (*p == '\0')
+             if (*end == '\0')
                {
                  LS_TOKEN_STOKEN (token).ptr = start;
                  LS_TOKEN_STOKEN (token).length
@@ -824,9 +872,9 @@ linespec_lexer_lex_string (linespec_parser *parser)
                   == language_cplus)
                  && (PARSER_STREAM (parser) - start) > CP_OPERATOR_LEN)
                {
-                 const char *p = strstr (start, CP_OPERATOR_STR);
+                 const char *op = strstr (start, CP_OPERATOR_STR);
 
-                 if (p != NULL && is_operator_name (p))
+                 if (op != NULL && is_operator_name (op))
                    {
                      /* This is an operator name.  Keep going.  */
                      ++(PARSER_STREAM (parser));
@@ -841,6 +889,7 @@ linespec_lexer_lex_string (linespec_parser *parser)
            }
 
          /* Advance the stream.  */
+         gdb_assert (*(PARSER_STREAM (parser)) != '\0');
          ++(PARSER_STREAM (parser));
        }
     }
@@ -883,10 +932,10 @@ linespec_lexer_lex_one (linespec_parser *parser)
 
        case '+': case '-':
        case '0': case '1': case '2': case '3': case '4':
-        case '5': case '6': case '7': case '8': case '9':
-           if (!linespec_lexer_lex_number (parser, &(parser->lexer.current)))
+       case '5': case '6': case '7': case '8': case '9':
+          if (!linespec_lexer_lex_number (parser, &(parser->lexer.current)))
             parser->lexer.current = linespec_lexer_lex_string (parser);
-          break;
+         break;
 
        case ':':
          /* If we have a scope operator, lex the input as a string.
@@ -1031,11 +1080,12 @@ add_sal_to_sals (struct linespec_state *self,
             the time being.  */
          if (symname != NULL && sal->line != 0
              && self->language->la_language == language_ada)
-           canonical->suffix = xstrprintf ("%s:%d", symname, sal->line);
+           canonical->suffix = xstrprintf ("%s:%d", symname,
+                                           sal->line).release ();
          else if (symname != NULL)
            canonical->suffix = xstrdup (symname);
          else
-           canonical->suffix = xstrprintf ("%d", sal->line);
+           canonical->suffix = xstrprintf ("%d", sal->line).release ();
          canonical->symtab = sal->symtab;
        }
       else
@@ -1110,59 +1160,55 @@ iterate_over_all_matching_symtabs
    struct program_space *search_pspace, bool include_inline,
    gdb::function_view<symbol_found_callback_ftype> callback)
 {
-  struct objfile *objfile;
-  struct program_space *pspace;
-
-  ALL_PSPACES (pspace)
-  {
-    if (search_pspace != NULL && search_pspace != pspace)
-      continue;
-    if (pspace->executing_startup)
-      continue;
-
-    set_current_program_space (pspace);
-
-    ALL_OBJFILES (objfile)
+  for (struct program_space *pspace : program_spaces)
     {
-      struct compunit_symtab *cu;
+      if (search_pspace != NULL && search_pspace != pspace)
+       continue;
+      if (pspace->executing_startup)
+       continue;
 
-      if (objfile->sf)
-       objfile->sf->qf->expand_symtabs_matching (objfile,
-                                                 NULL,
-                                                 lookup_name,
-                                                 NULL, NULL,
-                                                 search_domain);
+      set_current_program_space (pspace);
 
-      ALL_OBJFILE_COMPUNITS (objfile, cu)
+      for (objfile *objfile : current_program_space->objfiles ())
        {
-         struct symtab *symtab = COMPUNIT_FILETABS (cu);
-
-         iterate_over_file_blocks (symtab, lookup_name, name_domain, callback);
+         objfile->expand_symtabs_matching (NULL, &lookup_name, NULL, NULL,
+                                           (SEARCH_GLOBAL_BLOCK
+                                            | SEARCH_STATIC_BLOCK),
+                                           UNDEF_DOMAIN,
+                                           search_domain);
 
-         if (include_inline)
+         for (compunit_symtab *cu : objfile->compunits ())
            {
-             struct block *block;
-             int i;
+             struct symtab *symtab = cu->primary_filetab ();
+
+             iterate_over_file_blocks (symtab, lookup_name, name_domain,
+                                       callback);
 
-             for (i = FIRST_LOCAL_BLOCK;
-                  i < BLOCKVECTOR_NBLOCKS (SYMTAB_BLOCKVECTOR (symtab));
-                  i++)
+             if (include_inline)
                {
-                 block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
-                 state->language->la_iterate_over_symbols
-                   (block, lookup_name, name_domain, [&] (symbol *sym)
-                    {
-                      /* Restrict calls to CALLBACK to symbols
-                         representing inline symbols only.  */
-                      if (SYMBOL_INLINED (sym))
-                        return callback (sym);
-                      return true;
-                    });
+                 const struct block *block;
+                 int i;
+
+                 for (i = FIRST_LOCAL_BLOCK;
+                      i < BLOCKVECTOR_NBLOCKS (symtab->blockvector ());
+                      i++)
+                   {
+                     block = BLOCKVECTOR_BLOCK (symtab->blockvector (), i);
+                     state->language->iterate_over_symbols
+                       (block, lookup_name, name_domain,
+                        [&] (block_symbol *bsym)
+                        {
+                          /* Restrict calls to CALLBACK to symbols
+                             representing inline symbols only.  */
+                          if (bsym->symbol->is_inlined ())
+                            return callback (bsym);
+                          return true;
+                        });
+                   }
                }
            }
        }
     }
-  }
 }
 
 /* Returns the block to be used for symbol searches from
@@ -1171,16 +1217,10 @@ iterate_over_all_matching_symtabs
 static const struct block *
 get_current_search_block (void)
 {
-  const struct block *block;
-  enum language save_language;
-
   /* get_selected_block can change the current language when there is
      no selected frame yet.  */
-  save_language = current_language->la_language;
-  block = get_selected_block (0);
-  set_language (save_language);
-
-  return block;
+  scoped_restore_current_language save_language;
+  return get_selected_block (0);
 }
 
 /* Iterate over static and global blocks.  */
@@ -1190,12 +1230,12 @@ iterate_over_file_blocks
   (struct symtab *symtab, const lookup_name_info &name,
    domain_enum domain, gdb::function_view<symbol_found_callback_ftype> callback)
 {
-  struct block *block;
+  const struct block *block;
 
-  for (block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
+  for (block = BLOCKVECTOR_BLOCK (symtab->blockvector (), STATIC_BLOCK);
        block != NULL;
        block = BLOCK_SUPERBLOCK (block))
-    LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback);
+    current_language->iterate_over_symbols (block, name, domain, callback);
 }
 
 /* A helper for find_method.  This finds all methods in type T of
@@ -1208,7 +1248,7 @@ find_methods (struct type *t, enum language t_lang, const char *name,
              std::vector<struct type *> *superclasses)
 {
   int ibase;
-  const char *class_name = TYPE_NAME (t);
+  const char *class_name = t->name ();
 
   /* Ignore this class if it doesn't have a name.  This is ugly, but
      unless we figure out how to get the physname without the name of
@@ -1218,30 +1258,19 @@ find_methods (struct type *t, enum language t_lang, const char *name,
       int method_counter;
       lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
       symbol_name_matcher_ftype *symbol_name_compare
-       = get_symbol_name_matcher (language_def (t_lang), lookup_name);
+       = language_def (t_lang)->get_symbol_name_matcher (lookup_name);
 
       t = check_typedef (t);
 
       /* Loop over each method name.  At this level, all overloads of a name
-         are counted as a single name.  There is an inner loop which loops over
-         each overload.  */
+        are counted as a single name.  There is an inner loop which loops over
+        each overload.  */
 
       for (method_counter = TYPE_NFN_FIELDS (t) - 1;
           method_counter >= 0;
           --method_counter)
        {
          const char *method_name = TYPE_FN_FIELDLIST_NAME (t, method_counter);
-         char dem_opname[64];
-
-         if (startswith (method_name, "__") ||
-             startswith (method_name, "op") ||
-             startswith (method_name, "type"))
-           {
-             if (cplus_demangle_opname (method_name, dem_opname, DMGL_ANSI))
-               method_name = dem_opname;
-             else if (cplus_demangle_opname (method_name, dem_opname, 0))
-               method_name = dem_opname;
-           }
 
          if (symbol_name_compare (method_name, lookup_name, NULL))
            {
@@ -1437,7 +1466,7 @@ convert_results_to_lsals (struct linespec_state *self,
 
 /* A structure that contains two string representations of a struct
    linespec_canonical_name:
-     - one where the the symtab's fullname is used;
+     - one where the symtab's fullname is used;
      - one where the filename followed the "set filename-display"
        setting.  */
 
@@ -1484,7 +1513,7 @@ decode_line_2 (struct linespec_state *self,
               std::vector<symtab_and_line> *result,
               const char *select_mode)
 {
-  char *args;
+  const char *args;
   const char *prompt;
   int i;
   std::vector<const char *> filters;
@@ -1679,12 +1708,12 @@ undefined_label_error (const char *function, const char *label)
 {
   if (function != NULL)
     throw_error (NOT_FOUND_ERROR,
-                _("No label \"%s\" defined in function \"%s\"."),
-                label, function);
+               _("No label \"%s\" defined in function \"%s\"."),
+               label, function);
   else
     throw_error (NOT_FOUND_ERROR,
-                _("No label \"%s\" defined in current function."),
-                label);
+               _("No label \"%s\" defined in current function."),
+               label);
 }
 
 /* Throw a source file not found error.  */
@@ -1760,9 +1789,6 @@ linespec_parse_basic (linespec_parser *parser)
 {
   gdb::unique_xmalloc_ptr<char> name;
   linespec_token token;
-  std::vector<symbol *> symbols;
-  std::vector<symbol *> *labels;
-  std::vector<bound_minimal_symbol> minimal_symbols;
 
   /* Get the next token.  */
   token = linespec_lexer_lex_one (parser);
@@ -1859,6 +1885,9 @@ linespec_parse_basic (linespec_parser *parser)
     }
   else
     {
+      std::vector<block_symbol> symbols;
+      std::vector<bound_minimal_symbol> minimal_symbols;
+
       /* Try looking it up as a function/method.  */
       find_linespec_symbols (PARSER_STATE (parser),
                             PARSER_RESULT (parser)->file_symtabs, name.get (),
@@ -1867,24 +1896,23 @@ linespec_parse_basic (linespec_parser *parser)
 
       if (!symbols.empty () || !minimal_symbols.empty ())
        {
-         PARSER_RESULT (parser)->function_symbols
-           = new std::vector<symbol *> (std::move (symbols));
-         PARSER_RESULT (parser)->minimal_symbols
-           = new std::vector<bound_minimal_symbol>
-               (std::move (minimal_symbols));
+         PARSER_RESULT (parser)->function_symbols = std::move (symbols);
+         PARSER_RESULT (parser)->minimal_symbols = std::move (minimal_symbols);
          PARSER_EXPLICIT (parser)->function_name = name.release ();
        }
       else
        {
          /* NAME was not a function or a method.  So it must be a label
             name or user specified variable like "break foo.c:$zippo".  */
-         labels = find_label_symbols (PARSER_STATE (parser), NULL,
-                                      &symbols, name.get ());
-         if (labels != NULL)
+         std::vector<block_symbol> labels
+           = find_label_symbols (PARSER_STATE (parser), {}, &symbols,
+                                 name.get ());
+
+         if (!labels.empty ())
            {
-             PARSER_RESULT (parser)->labels.label_symbols = labels;
+             PARSER_RESULT (parser)->labels.label_symbols = std::move (labels);
              PARSER_RESULT (parser)->labels.function_symbols
-               = new std::vector<symbol *> (std::move (symbols));
+                 = std::move (symbols);
              PARSER_EXPLICIT (parser)->label_name = name.release ();
            }
          else if (token.type == LSTOKEN_STRING
@@ -1979,18 +2007,21 @@ linespec_parse_basic (linespec_parser *parser)
            }
          else
            {
+             std::vector<block_symbol> symbols;
+
              /* Grab a copy of the label's name and look it up.  */
              name = copy_token_string (token);
-             labels
+             std::vector<block_symbol> labels
                = find_label_symbols (PARSER_STATE (parser),
                                      PARSER_RESULT (parser)->function_symbols,
                                      &symbols, name.get ());
 
-             if (labels != NULL)
+             if (!labels.empty ())
                {
-                 PARSER_RESULT (parser)->labels.label_symbols = labels;
+                 PARSER_RESULT (parser)->labels.label_symbols
+                   = std::move (labels);
                  PARSER_RESULT (parser)->labels.function_symbols
-                   = new std::vector<symbol *> (std::move (symbols));
+                   = std::move (symbols);
                  PARSER_EXPLICIT (parser)->label_name = name.release ();
                }
              else
@@ -2036,7 +2067,7 @@ linespec_parse_basic (linespec_parser *parser)
    locations.  */
 
 static void
-canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
+canonicalize_linespec (struct linespec_state *state, const linespec *ls)
 {
   struct event_location *canon;
   struct explicit_location *explicit_loc;
@@ -2058,29 +2089,24 @@ canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
       if (explicit_loc->function_name == NULL)
        {
          /* No function was specified, so add the symbol name.  */
-         gdb_assert (!ls->labels.function_symbols->empty ()
-                     && (ls->labels.function_symbols->size () == 1));
-         struct symbol *s = ls->labels.function_symbols->front ();
-         explicit_loc->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
+         gdb_assert (ls->labels.function_symbols.size () == 1);
+         block_symbol s = ls->labels.function_symbols.front ();
+         explicit_loc->function_name = xstrdup (s.symbol->natural_name ());
        }
     }
 
   /* If this location originally came from a linespec, save a string
      representation of it for display and saving to file.  */
   if (state->is_linespec)
-    {
-      char *linespec = explicit_location_to_linespec (explicit_loc);
-
-      set_event_location_string (canon, linespec);
-      xfree (linespec);
-    }
+    set_event_location_string (canon,
+                              explicit_location_to_linespec (explicit_loc));
 }
 
 /* Given a line offset in LS, construct the relevant SALs.  */
 
 static std::vector<symtab_and_line>
 create_sals_line_offset (struct linespec_state *self,
-                        linespec_p ls)
+                        linespec *ls)
 {
   int use_default = 0;
 
@@ -2090,20 +2116,17 @@ create_sals_line_offset (struct linespec_state *self,
      set_default_source_symtab_and_line uses
      select_source_symtab that calls us with such an argument.  */
 
-  if (ls->file_symtabs->size () == 1
-      && ls->file_symtabs->front () == nullptr)
+  if (ls->file_symtabs.size () == 1
+      && ls->file_symtabs.front () == nullptr)
     {
-      const char *fullname;
-
       set_current_program_space (self->program_space);
 
       /* Make sure we have at least a default source line.  */
       set_default_source_symtab_and_line ();
       initialize_defaults (&self->default_symtab, &self->default_line);
-      fullname = symtab_to_fullname (self->default_symtab);
-      symtab_vector_up r =
-       collect_symtabs_from_filename (fullname, self->search_pspace);
-      ls->file_symtabs = r.release ();
+      ls->file_symtabs
+       = collect_symtabs_from_filename (self->default_symtab->filename,
+                                        self->search_pspace);
       use_default = 1;
     }
 
@@ -2192,7 +2215,7 @@ create_sals_line_offset (struct linespec_state *self,
              skip_prologue_sal (&intermediate_results[i]);
            intermediate_results[i].symbol = sym;
            add_sal_to_sals (self, &values, &intermediate_results[i],
-                            sym ? SYMBOL_NATURAL_NAME (sym) : NULL, 0);
+                            sym ? sym->natural_name () : NULL, 0);
          }
     }
 
@@ -2230,38 +2253,41 @@ convert_address_location_to_sals (struct linespec_state *self,
 /* Create and return SALs from the linespec LS.  */
 
 static std::vector<symtab_and_line>
-convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
+convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
 {
   std::vector<symtab_and_line> sals;
 
-  if (ls->labels.label_symbols != NULL)
+  if (!ls->labels.label_symbols.empty ())
     {
       /* We have just a bunch of functions/methods or labels.  */
-      for (const auto &sym : *ls->labels.label_symbols)
+      struct symtab_and_line sal;
+
+      for (const auto &sym : ls->labels.label_symbols)
        {
-         struct symtab_and_line sal;
-         struct program_space *pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+         struct program_space *pspace
+           = symbol_symtab (sym.symbol)->pspace ();
 
-         if (symbol_to_sal (&sal, state->funfirstline, sym)
+         if (symbol_to_sal (&sal, state->funfirstline, sym.symbol)
              && maybe_add_address (state->addr_set, pspace, sal.pc))
            add_sal_to_sals (state, &sals, &sal,
-                            SYMBOL_NATURAL_NAME (sym), 0);
+                            sym.symbol->natural_name (), 0);
        }
     }
-  else if (ls->function_symbols != NULL || ls->minimal_symbols != NULL)
+  else if (!ls->function_symbols.empty () || !ls->minimal_symbols.empty ())
     {
       /* We have just a bunch of functions and/or methods.  */
-      if (ls->function_symbols != NULL)
+      if (!ls->function_symbols.empty ())
        {
          /* Sort symbols so that symbols with the same program space are next
             to each other.  */
-         std::sort (ls->function_symbols->begin (),
-                    ls->function_symbols->end (),
+         std::sort (ls->function_symbols.begin (),
+                    ls->function_symbols.end (),
                     compare_symbols);
 
-         for (const auto &sym : *ls->function_symbols)
+         for (const auto &sym : ls->function_symbols)
            {
-             program_space *pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+             program_space *pspace
+               = symbol_symtab (sym.symbol)->pspace ();
              set_current_program_space (pspace);
 
              /* Don't skip to the first line of the function if we
@@ -2271,13 +2297,13 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
              bool found_ifunc = false;
 
              if (state->funfirstline
-                  && ls->minimal_symbols != NULL
-                  && SYMBOL_CLASS (sym) == LOC_BLOCK)
+                  && !ls->minimal_symbols.empty ()
+                  && sym.symbol->aclass () == LOC_BLOCK)
                {
                  const CORE_ADDR addr
-                   = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym));
+                   = BLOCK_ENTRY_PC (SYMBOL_BLOCK_VALUE (sym.symbol));
 
-                 for (const auto &elem : *ls->minimal_symbols)
+                 for (const auto &elem : ls->minimal_symbols)
                    {
                      if (MSYMBOL_TYPE (elem.minsym) == mst_text_gnu_ifunc
                          || MSYMBOL_TYPE (elem.minsym) == mst_data_gnu_ifunc)
@@ -2286,12 +2312,12 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
                          if (MSYMBOL_TYPE (elem.minsym) == mst_data_gnu_ifunc)
                            {
                              struct gdbarch *gdbarch
-                               = get_objfile_arch (elem.objfile);
+                               = elem.objfile->arch ();
                              msym_addr
                                = (gdbarch_convert_from_func_ptr_addr
                                   (gdbarch,
                                    msym_addr,
-                                   current_top_target ()));
+                                   current_inferior ()->top_target ()));
                            }
 
                          if (msym_addr == addr)
@@ -2306,22 +2332,22 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
              if (!found_ifunc)
                {
                  symtab_and_line sal;
-                 if (symbol_to_sal (&sal, state->funfirstline, sym)
+                 if (symbol_to_sal (&sal, state->funfirstline, sym.symbol)
                      && maybe_add_address (state->addr_set, pspace, sal.pc))
                    add_sal_to_sals (state, &sals, &sal,
-                                    SYMBOL_NATURAL_NAME (sym), 0);
+                                    sym.symbol->natural_name (), 0);
                }
            }
        }
 
-      if (ls->minimal_symbols != NULL)
+      if (!ls->minimal_symbols.empty ())
        {
          /* Sort minimal symbols by program space, too  */
-         std::sort (ls->minimal_symbols->begin (),
-                    ls->minimal_symbols->end (),
+         std::sort (ls->minimal_symbols.begin (),
+                    ls->minimal_symbols.end (),
                     compare_msymbols);
 
-         for (const auto &elem : *ls->minimal_symbols)
+         for (const auto &elem : ls->minimal_symbols)
            {
              program_space *pspace = elem.objfile->pspace;
              set_current_program_space (pspace);
@@ -2365,42 +2391,40 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
 static void
 convert_explicit_location_to_linespec (struct linespec_state *self,
-                                      linespec_p result,
+                                      linespec *result,
                                       const char *source_filename,
                                       const char *function_name,
                                       symbol_name_match_type fname_match_type,
                                       const char *label_name,
                                       struct line_offset line_offset)
 {
-  std::vector<symbol *> symbols;
-  std::vector<symbol *> *labels;
   std::vector<bound_minimal_symbol> minimal_symbols;
 
   result->explicit_loc.func_name_match_type = fname_match_type;
 
   if (source_filename != NULL)
     {
-      TRY
+      try
        {
          result->file_symtabs
-           = symtabs_from_filename (source_filename,
-                                    self->search_pspace).release ();
+           = symtabs_from_filename (source_filename, self->search_pspace);
        }
-      CATCH (except, RETURN_MASK_ERROR)
+      catch (const gdb_exception_error &except)
        {
          source_file_not_found_error (source_filename);
        }
-      END_CATCH
       result->explicit_loc.source_filename = xstrdup (source_filename);
     }
   else
     {
       /* A NULL entry means to use the default symtab.  */
-      result->file_symtabs->push_back (nullptr);
+      result->file_symtabs.push_back (nullptr);
     }
 
   if (function_name != NULL)
     {
+      std::vector<block_symbol> symbols;
+
       find_linespec_symbols (self, result->file_symtabs,
                             function_name, fname_match_type,
                             &symbols, &minimal_symbols);
@@ -2410,25 +2434,24 @@ convert_explicit_location_to_linespec (struct linespec_state *self,
                                result->explicit_loc.source_filename);
 
       result->explicit_loc.function_name = xstrdup (function_name);
-      result->function_symbols
-       = new std::vector<symbol *> (std::move (symbols));
-      result->minimal_symbols
-       = new std::vector<bound_minimal_symbol> (std::move (minimal_symbols));
+      result->function_symbols = std::move (symbols);
+      result->minimal_symbols = std::move (minimal_symbols);
     }
 
   if (label_name != NULL)
     {
-      labels = find_label_symbols (self, result->function_symbols,
-                                  &symbols, label_name);
+      std::vector<block_symbol> symbols;
+      std::vector<block_symbol> labels
+       = find_label_symbols (self, result->function_symbols,
+                             &symbols, label_name);
 
-      if (labels == NULL)
+      if (labels.empty ())
        undefined_label_error (result->explicit_loc.function_name,
                               label_name);
 
       result->explicit_loc.label_name = xstrdup (label_name);
       result->labels.label_symbols = labels;
-      result->labels.function_symbols
-       = new std::vector<symbol *> (std::move (symbols));
+      result->labels.function_symbols = std::move (symbols);
     }
 
   if (line_offset.sign != LINE_OFFSET_UNKNOWN)
@@ -2439,7 +2462,7 @@ convert_explicit_location_to_linespec (struct linespec_state *self,
 
 static std::vector<symtab_and_line>
 convert_explicit_location_to_sals (struct linespec_state *self,
-                                  linespec_p result,
+                                  linespec *result,
                                   const struct explicit_location *explicit_loc)
 {
   convert_explicit_location_to_linespec (self, result,
@@ -2471,7 +2494,7 @@ convert_explicit_location_to_sals (struct linespec_state *self,
    label_name_spec -> STRING
    function_name_spec -> STRING
    offset_spec -> NUMBER
-               -> '+' NUMBER
+              -> '+' NUMBER
               -> '-' NUMBER
 
    This may all be followed by several keywords such as "if EXPR",
@@ -2499,15 +2522,16 @@ convert_explicit_location_to_sals (struct linespec_state *self,
    if no file is validly specified.  Callers must check that.
    Also, the line number returned may be invalid.  */
 
-/* Parse the linespec in ARG.  MATCH_TYPE indicates how function names
-   should be matched.  */
+/* Parse the linespec in ARG, which must not be nullptr.  MATCH_TYPE
+   indicates how function names should be matched.  */
 
 static std::vector<symtab_and_line>
 parse_linespec (linespec_parser *parser, const char *arg,
                symbol_name_match_type match_type)
 {
-  linespec_token token;
-  struct gdb_exception file_exception = exception_none;
+  gdb_assert (arg != nullptr);
+
+  struct gdb_exception file_exception;
 
   /* A special case to start.  It has become quite popular for
      IDEs to work around bugs in the previous parser by quoting
@@ -2515,11 +2539,10 @@ parse_linespec (linespec_parser *parser, const char *arg,
   parser->is_quote_enclosed = 0;
   if (parser->completion_tracker == NULL
       && !is_ada_operator (arg)
+      && *arg != '\0'
       && strchr (linespec_quote_characters, *arg) != NULL)
     {
-      const char *end;
-
-      end = skip_quote_char (arg + 1, *arg);
+      const char *end = skip_quote_char (arg + 1, *arg);
       if (end != NULL && is_closing_quote_enclosed (end))
        {
          /* Here's the special case.  Skip ARG past the initial
@@ -2560,14 +2583,14 @@ parse_linespec (linespec_parser *parser, const char *arg,
   /* Start parsing.  */
 
   /* Get the first token.  */
-  token = linespec_lexer_consume_token (parser);
+  linespec_token token = linespec_lexer_consume_token (parser);
 
   /* It must be either LSTOKEN_STRING or LSTOKEN_NUMBER.  */
   if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
     {
       /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB.  */
       if (parser->completion_tracker == NULL)
-       PARSER_RESULT (parser)->file_symtabs->push_back (nullptr);
+       PARSER_RESULT (parser)->file_symtabs.push_back (nullptr);
 
       /* User specified a convenience variable or history value.  */
       gdb::unique_xmalloc_ptr<char> var = copy_token_string (token);
@@ -2606,18 +2629,16 @@ parse_linespec (linespec_parser *parser, const char *arg,
       gdb::unique_xmalloc_ptr<char> user_filename = copy_token_string (token);
 
       /* Check if the input is a filename.  */
-      TRY
+      try
        {
-         symtab_vector_up r
+         PARSER_RESULT (parser)->file_symtabs
            = symtabs_from_filename (user_filename.get (),
                                     PARSER_STATE (parser)->search_pspace);
-         PARSER_RESULT (parser)->file_symtabs = r.release ();
        }
-      CATCH (ex, RETURN_MASK_ERROR)
+      catch (gdb_exception_error &ex)
        {
-         file_exception = ex;
+         file_exception = std::move (ex);
        }
-      END_CATCH
 
       if (file_exception.reason >= 0)
        {
@@ -2633,7 +2654,7 @@ parse_linespec (linespec_parser *parser, const char *arg,
       else
        {
          /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB.  */
-         PARSER_RESULT (parser)->file_symtabs->push_back (nullptr);
+         PARSER_RESULT (parser)->file_symtabs.push_back (nullptr);
        }
     }
   /* If the next token is not EOI, KEYWORD, or COMMA, issue an error.  */
@@ -2649,22 +2670,22 @@ parse_linespec (linespec_parser *parser, const char *arg,
   else
     {
       /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB.  */
-      PARSER_RESULT (parser)->file_symtabs->push_back (nullptr);
+      PARSER_RESULT (parser)->file_symtabs.push_back (nullptr);
     }
 
   /* Parse the rest of the linespec.  */
   linespec_parse_basic (parser);
 
   if (parser->completion_tracker == NULL
-      && PARSER_RESULT (parser)->function_symbols == NULL
-      && PARSER_RESULT (parser)->labels.label_symbols == NULL
+      && PARSER_RESULT (parser)->function_symbols.empty ()
+      && PARSER_RESULT (parser)->labels.label_symbols.empty ()
       && PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
-      && PARSER_RESULT (parser)->minimal_symbols == NULL)
+      && PARSER_RESULT (parser)->minimal_symbols.empty ())
     {
       /* The linespec didn't parse.  Re-throw the file exception if
         there was one.  */
       if (file_exception.reason < 0)
-       throw_exception (file_exception);
+       throw_exception (std::move (file_exception));
 
       /* Otherwise, the symbol is not found.  */
       symbol_not_found_error (PARSER_EXPLICIT (parser)->function_name,
@@ -2723,22 +2744,18 @@ linespec_state_constructor (struct linespec_state *self,
 
 /* Initialize a new linespec parser.  */
 
-static void
-linespec_parser_new (linespec_parser *parser,
-                    int flags, const struct language_defn *language,
-                    struct program_space *search_pspace,
-                    struct symtab *default_symtab,
-                    int default_line,
-                    struct linespec_result *canonical)
+linespec_parser::linespec_parser (int flags,
+                                 const struct language_defn *language,
+                                 struct program_space *search_pspace,
+                                 struct symtab *default_symtab,
+                                 int default_line,
+                                 struct linespec_result *canonical)
 {
-  memset (parser, 0, sizeof (linespec_parser));
-  parser->lexer.current.type = LSTOKEN_CONSUMED;
-  memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
-  PARSER_RESULT (parser)->file_symtabs = new std::vector<symtab *> ();
-  PARSER_EXPLICIT (parser)->func_name_match_type
+  lexer.current.type = LSTOKEN_CONSUMED;
+  PARSER_EXPLICIT (this)->func_name_match_type
     = symbol_name_match_type::WILD;
-  PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
-  linespec_state_constructor (PARSER_STATE (parser), flags, language,
+  PARSER_EXPLICIT (this)->line_offset.sign = LINE_OFFSET_UNKNOWN;
+  linespec_state_constructor (PARSER_STATE (this), flags, language,
                              search_pspace,
                              default_symtab, default_line, canonical);
 }
@@ -2749,26 +2766,18 @@ static void
 linespec_state_destructor (struct linespec_state *self)
 {
   htab_delete (self->addr_set);
+  xfree (self->canonical_names);
 }
 
 /* Delete a linespec parser.  */
 
-static void
-linespec_parser_delete (void *arg)
+linespec_parser::~linespec_parser ()
 {
-  linespec_parser *parser = (linespec_parser *) arg;
+  xfree (PARSER_EXPLICIT (this)->source_filename);
+  xfree (PARSER_EXPLICIT (this)->label_name);
+  xfree (PARSER_EXPLICIT (this)->function_name);
 
-  xfree (PARSER_EXPLICIT (parser)->source_filename);
-  xfree (PARSER_EXPLICIT (parser)->label_name);
-  xfree (PARSER_EXPLICIT (parser)->function_name);
-
-  delete PARSER_RESULT (parser)->file_symtabs;
-  delete PARSER_RESULT (parser)->function_symbols;
-  delete PARSER_RESULT (parser)->minimal_symbols;
-  delete PARSER_RESULT (parser)->labels.label_symbols;
-  delete PARSER_RESULT (parser)->labels.function_symbols;
-
-  linespec_state_destructor (PARSER_STATE (parser));
+  linespec_state_destructor (PARSER_STATE (this));
 }
 
 /* See description in linespec.h.  */
@@ -2776,16 +2785,13 @@ linespec_parser_delete (void *arg)
 void
 linespec_lex_to_end (const char **stringp)
 {
-  linespec_parser parser;
-  struct cleanup *cleanup;
   linespec_token token;
   const char *orig;
 
   if (stringp == NULL || *stringp == NULL)
     return;
 
-  linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
-  cleanup = make_cleanup (linespec_parser_delete, &parser);
+  linespec_parser parser (0, current_language, NULL, NULL, 0, NULL);
   parser.lexer.saved_arg = *stringp;
   PARSER_STREAM (&parser) = orig = *stringp;
 
@@ -2801,7 +2807,6 @@ linespec_lex_to_end (const char **stringp)
   while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
 
   *stringp += PARSER_STREAM (&parser) - orig;
-  do_cleanups (cleanup);
 }
 
 /* See linespec.h.  */
@@ -2899,21 +2904,17 @@ complete_label (completion_tracker &tracker,
                linespec_parser *parser,
                const char *label_name)
 {
-  std::vector<symbol *> label_function_symbols;
-  std::vector<symbol *> *labels
+  std::vector<block_symbol> label_function_symbols;
+  std::vector<block_symbol> labels
     = find_label_symbols (PARSER_STATE (parser),
                          PARSER_RESULT (parser)->function_symbols,
                          &label_function_symbols,
                          label_name, true);
 
-  if (labels != nullptr)
+  for (const auto &label : labels)
     {
-      for (const auto &label : *labels)
-       {
-         char *match = xstrdup (SYMBOL_SEARCH_NAME (label));
-         tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
-       }
-      delete labels;
+      char *match = xstrdup (label.symbol->search_name ());
+      tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
     }
 }
 
@@ -2927,15 +2928,11 @@ linespec_complete_label (completion_tracker &tracker,
                         symbol_name_match_type func_name_match_type,
                         const char *label_name)
 {
-  linespec_parser parser;
-  struct cleanup *cleanup;
-
-  linespec_parser_new (&parser, 0, language, NULL, NULL, 0, NULL);
-  cleanup = make_cleanup (linespec_parser_delete, &parser);
+  linespec_parser parser (0, language, NULL, NULL, 0, NULL);
 
   line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN };
 
-  TRY
+  try
     {
       convert_explicit_location_to_linespec (PARSER_STATE (&parser),
                                             PARSER_RESULT (&parser),
@@ -2944,16 +2941,12 @@ linespec_complete_label (completion_tracker &tracker,
                                             func_name_match_type,
                                             NULL, unknown_offset);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
-      do_cleanups (cleanup);
       return;
     }
-  END_CATCH
 
   complete_label (tracker, &parser, label_name);
-
-  do_cleanups (cleanup);
 }
 
 /* See description in linespec.h.  */
@@ -2962,12 +2955,9 @@ void
 linespec_complete (completion_tracker &tracker, const char *text,
                   symbol_name_match_type match_type)
 {
-  linespec_parser parser;
-  struct cleanup *cleanup;
   const char *orig = text;
 
-  linespec_parser_new (&parser, 0, current_language, NULL, NULL, 0, NULL);
-  cleanup = make_cleanup (linespec_parser_delete, &parser);
+  linespec_parser parser (0, current_language, NULL, NULL, 0, NULL);
   parser.lexer.saved_arg = text;
   PARSER_EXPLICIT (&parser)->func_name_match_type = match_type;
   PARSER_STREAM (&parser) = text;
@@ -2977,14 +2967,13 @@ linespec_complete (completion_tracker &tracker, const char *text,
 
   /* Parse as much as possible.  parser.completion_word will hold
      furthest completion point we managed to parse to.  */
-  TRY
+  try
     {
       parse_linespec (&parser, text, match_type);
     }
-  CATCH (except, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &except)
     {
     }
-  END_CATCH
 
   if (parser.completion_quote_char != '\0'
       && parser.completion_quote_end != NULL
@@ -3023,17 +3012,15 @@ linespec_complete (completion_tracker &tracker, const char *text,
 
       const char *func_name = PARSER_EXPLICIT (&parser)->function_name;
 
-      std::vector<symbol *> function_symbols;
+      std::vector<block_symbol> function_symbols;
       std::vector<bound_minimal_symbol> minimal_symbols;
       find_linespec_symbols (PARSER_STATE (&parser),
                             PARSER_RESULT (&parser)->file_symtabs,
                             func_name, match_type,
                             &function_symbols, &minimal_symbols);
 
-      PARSER_RESULT (&parser)->function_symbols
-       = new std::vector<symbol *> (std::move (function_symbols));
-      PARSER_RESULT (&parser)->minimal_symbols
-       = new std::vector<bound_minimal_symbol> (std::move (minimal_symbols));
+      PARSER_RESULT (&parser)->function_symbols = std::move (function_symbols);
+      PARSER_RESULT (&parser)->minimal_symbols = std::move (minimal_symbols);
 
       complete_label (tracker, &parser, parser.completion_word);
     }
@@ -3150,8 +3137,6 @@ linespec_complete (completion_tracker &tracker, const char *text,
                                       NULL);
        }
     }
-
-  do_cleanups (cleanup);
 }
 
 /* A helper function for decode_line_full and decode_line_1 to
@@ -3168,17 +3153,16 @@ event_location_to_sals (linespec_parser *parser,
     case LINESPEC_LOCATION:
       {
        PARSER_STATE (parser)->is_linespec = 1;
-       TRY
+       try
          {
            const linespec_location *ls = get_linespec_location (location);
            result = parse_linespec (parser,
                                     ls->spec_string, ls->match_type);
          }
-       CATCH (except, RETURN_MASK_ERROR)
+       catch (const gdb_exception_error &except)
          {
-           throw_exception (except);
+           throw;
          }
-       END_CATCH
       }
       break;
 
@@ -3226,16 +3210,14 @@ event_location_to_sals (linespec_parser *parser,
 /* See linespec.h.  */
 
 void
-decode_line_full (const struct event_location *location, int flags,
+decode_line_full (struct event_location *location, int flags,
                  struct program_space *search_pspace,
                  struct symtab *default_symtab,
                  int default_line, struct linespec_result *canonical,
                  const char *select_mode,
                  const char *filter)
 {
-  struct cleanup *cleanups;
   std::vector<const char *> filters;
-  linespec_parser parser;
   struct linespec_state *state;
 
   gdb_assert (canonical != NULL);
@@ -3247,10 +3229,9 @@ decode_line_full (const struct event_location *location, int flags,
              || select_mode == multiple_symbols_cancel);
   gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
 
-  linespec_parser_new (&parser, flags, current_language,
-                      search_pspace, default_symtab,
-                      default_line, canonical);
-  cleanups = make_cleanup (linespec_parser_delete, &parser);
+  linespec_parser parser (flags, current_language,
+                         search_pspace, default_symtab,
+                         default_line, canonical);
 
   scoped_restore_current_program_space restore_pspace;
 
@@ -3258,20 +3239,19 @@ decode_line_full (const struct event_location *location, int flags,
                                                                location);
   state = PARSER_STATE (&parser);
 
+  if (result.size () == 0)
+    throw_error (NOT_SUPPORTED_ERROR, _("Location %s not available"),
+                event_location_to_string (location));
+
   gdb_assert (result.size () == 1 || canonical->pre_expanded);
   canonical->pre_expanded = 1;
 
   /* Arrange for allocated canonical names to be freed.  */
-  if (!result.empty ())
+  std::vector<gdb::unique_xmalloc_ptr<char>> hold_names;
+  for (int i = 0; i < result.size (); ++i)
     {
-      int i;
-
-      make_cleanup (xfree, state->canonical_names);
-      for (i = 0; i < result.size (); ++i)
-       {
-         gdb_assert (state->canonical_names[i].suffix != NULL);
-         make_cleanup (xfree, state->canonical_names[i].suffix);
-       }
+      gdb_assert (state->canonical_names[i].suffix != NULL);
+      hold_names.emplace_back (state->canonical_names[i].suffix);
     }
 
   if (select_mode == NULL)
@@ -3294,8 +3274,6 @@ decode_line_full (const struct event_location *location, int flags,
     }
   else
     decode_line_2 (state, &result, select_mode);
-
-  do_cleanups (cleanups);
 }
 
 /* See linespec.h.  */
@@ -3306,21 +3284,13 @@ decode_line_1 (const struct event_location *location, int flags,
               struct symtab *default_symtab,
               int default_line)
 {
-  linespec_parser parser;
-  struct cleanup *cleanups;
-
-  linespec_parser_new (&parser, flags, current_language,
-                      search_pspace, default_symtab,
-                      default_line, NULL);
-  cleanups = make_cleanup (linespec_parser_delete, &parser);
+  linespec_parser parser (flags, current_language,
+                         search_pspace, default_symtab,
+                         default_line, NULL);
 
   scoped_restore_current_program_space restore_pspace;
 
-  std::vector<symtab_and_line> result = event_location_to_sals (&parser,
-                                                               location);
-
-  do_cleanups (cleanups);
-  return result;
+  return event_location_to_sals (&parser, location);
 }
 
 /* See linespec.h.  */
@@ -3361,8 +3331,7 @@ decode_line_with_last_displayed (const char *string, int flags)
        ? decode_line_1 (location.get (), flags, NULL,
                        get_last_displayed_symtab (),
                        get_last_displayed_line ())
-       : decode_line_1 (location.get (), flags, NULL,
-                       (struct symtab *) NULL, 0));
+       : decode_line_1 (location.get (), flags, NULL, NULL, 0));
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
@@ -3372,7 +3341,7 @@ decode_line_with_last_displayed (const char *string, int flags)
 
 \f
 
-/* First, some functions to initialize stuff at the beggining of the
+/* First, some functions to initialize stuff at the beginning of the
    function.  */
 
 static void
@@ -3381,7 +3350,7 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
   if (*default_symtab == 0)
     {
       /* Use whatever we have for the default source line.  We don't use
-         get_current_or_default_symtab_and_line as it can recurse and call
+        get_current_or_default_symtab_and_line as it can recurse and call
         us back!  */
       struct symtab_and_line cursal = 
        get_current_source_symtab_and_line ();
@@ -3419,7 +3388,7 @@ linespec_expression_to_pc (const char **exp_ptr)
    the existing C++ code to let the user choose one.  */
 
 static std::vector<symtab_and_line>
-decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
+decode_objc (struct linespec_state *self, linespec *ls, const char *arg)
 {
   struct collect_info info;
   std::vector<const char *> symbol_names;
@@ -3431,7 +3400,7 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
 
   info.file_symtabs = &symtabs;
 
-  std::vector<symbol *> symbols;
+  std::vector<block_symbol> symbols;
   info.result.symbols = &symbols;
   std::vector<bound_minimal_symbol> minimal_symbols;
   info.result.minimal_symbols = &minimal_symbols;
@@ -3453,9 +3422,8 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
       saved_arg[new_argptr - arg] = '\0';
 
       ls->explicit_loc.function_name = xstrdup (saved_arg);
-      ls->function_symbols = new std::vector<symbol *> (std::move (symbols));
-      ls->minimal_symbols
-       = new std::vector<bound_minimal_symbol> (std::move (minimal_symbols));
+      ls->function_symbols = std::move (symbols);
+      ls->minimal_symbols = std::move (minimal_symbols);
       values = convert_linespec_to_sals (self, ls);
 
       if (self->canonical)
@@ -3492,57 +3460,52 @@ class decode_compound_collector
 {
 public:
   decode_compound_collector ()
+    : m_unique_syms (htab_create_alloc (1, htab_hash_pointer,
+                                       htab_eq_pointer, NULL,
+                                       xcalloc, xfree))
   {
-    m_unique_syms = htab_create_alloc (1, htab_hash_pointer,
-                                      htab_eq_pointer, NULL,
-                                      xcalloc, xfree);
-  }
-
-  ~decode_compound_collector ()
-  {
-    if (m_unique_syms != NULL)
-      htab_delete (m_unique_syms);
   }
 
   /* Return all symbols collected.  */
-  std::vector<symbol *> release_symbols ()
+  std::vector<block_symbol> release_symbols ()
   {
     return std::move (m_symbols);
   }
 
   /* Callable as a symbol_found_callback_ftype callback.  */
-  bool operator () (symbol *sym);
+  bool operator () (block_symbol *bsym);
 
 private:
   /* A hash table of all symbols we found.  We use this to avoid
      adding any symbol more than once.  */
-  htab_t m_unique_syms;
+  htab_up m_unique_syms;
 
   /* The result vector.  */
-  std::vector<symbol *>  m_symbols;
+  std::vector<block_symbol>  m_symbols;
 };
 
 bool
-decode_compound_collector::operator () (symbol *sym)
+decode_compound_collector::operator () (block_symbol *bsym)
 {
   void **slot;
   struct type *t;
+  struct symbol *sym = bsym->symbol;
 
-  if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+  if (sym->aclass () != LOC_TYPEDEF)
     return true; /* Continue iterating.  */
 
-  t = SYMBOL_TYPE (sym);
+  t = sym->type ();
   t = check_typedef (t);
-  if (TYPE_CODE (t) != TYPE_CODE_STRUCT
-      && TYPE_CODE (t) != TYPE_CODE_UNION
-      && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
+  if (t->code () != TYPE_CODE_STRUCT
+      && t->code () != TYPE_CODE_UNION
+      && t->code () != TYPE_CODE_NAMESPACE)
     return true; /* Continue iterating.  */
 
-  slot = htab_find_slot (m_unique_syms, sym, INSERT);
+  slot = htab_find_slot (m_unique_syms.get (), sym, INSERT);
   if (!*slot)
     {
       *slot = sym;
-      m_symbols.push_back (sym);
+      m_symbols.push_back (*bsym);
     }
 
   return true; /* Continue iterating.  */
@@ -3552,16 +3515,16 @@ decode_compound_collector::operator () (symbol *sym)
 
 /* Return any symbols corresponding to CLASS_NAME in FILE_SYMTABS.  */
 
-static std::vector<symbol *>
+static std::vector<block_symbol>
 lookup_prefix_sym (struct linespec_state *state,
-                  std::vector<symtab *> *file_symtabs,
+                  const std::vector<symtab *> &file_symtabs,
                   const char *class_name)
 {
   decode_compound_collector collector;
 
   lookup_name_info lookup_name (class_name, symbol_name_match_type::FULL);
 
-  for (const auto &elt : *file_symtabs)
+  for (const auto &elt : file_symtabs)
     {
       if (elt == nullptr)
        {
@@ -3576,8 +3539,8 @@ lookup_prefix_sym (struct linespec_state *state,
        {
          /* Program spaces that are executing startup should have
             been filtered out earlier.  */
-         gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
-         set_current_program_space (SYMTAB_PSPACE (elt));
+         gdb_assert (!elt->pspace ()->executing_startup);
+         set_current_program_space (elt->pspace ());
          iterate_over_file_blocks (elt, lookup_name, STRUCT_DOMAIN, collector);
          iterate_over_file_blocks (elt, lookup_name, VAR_DOMAIN, collector);
        }
@@ -3591,20 +3554,20 @@ lookup_prefix_sym (struct linespec_state *state,
    symbols with the same program space end up next to each other.  */
 
 static bool
-compare_symbols (const struct symbol *a, const struct symbol *b)
+compare_symbols (const block_symbol &a, const block_symbol &b)
 {
   uintptr_t uia, uib;
 
-  uia = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (a));
-  uib = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (b));
+  uia = (uintptr_t) symbol_symtab (a.symbol)->pspace ();
+  uib = (uintptr_t) symbol_symtab (b.symbol)->pspace ();
 
   if (uia < uib)
     return true;
   if (uia > uib)
     return false;
 
-  uia = (uintptr_t) a;
-  uib = (uintptr_t) b;
+  uia = (uintptr_t) a.symbol;
+  uib = (uintptr_t) b.symbol;
 
   if (uia < uib)
     return true;
@@ -3679,9 +3642,11 @@ find_superclass_methods (std::vector<struct type *> &&superclasses,
    in SYMBOLS (for debug symbols) and MINSYMS (for minimal symbols).  */
 
 static void
-find_method (struct linespec_state *self, std::vector<symtab *> *file_symtabs,
+find_method (struct linespec_state *self,
+            const std::vector<symtab *> &file_symtabs,
             const char *class_name, const char *method_name,
-            std::vector<symbol *> *sym_classes, std::vector<symbol *> *symbols,
+            std::vector<block_symbol> *sym_classes,
+            std::vector<block_symbol> *symbols,
             std::vector<bound_minimal_symbol> *minsyms)
 {
   size_t last_result_len;
@@ -3695,7 +3660,7 @@ find_method (struct linespec_state *self, std::vector<symtab *> *file_symtabs,
             compare_symbols);
 
   info.state = self;
-  info.file_symtabs = file_symtabs;
+  info.file_symtabs = &file_symtabs;
   info.result.symbols = symbols;
   info.result.minimal_symbols = minsyms;
 
@@ -3709,32 +3674,33 @@ find_method (struct linespec_state *self, std::vector<symtab *> *file_symtabs,
      because we collect data across the program space before deciding
      what to do.  */
   last_result_len = 0;
-  unsigned int ix = 0;
-  for (const auto &sym : *sym_classes)
+  for (const auto &elt : *sym_classes)
     {
       struct type *t;
       struct program_space *pspace;
+      struct symbol *sym = elt.symbol;
+      unsigned int ix = &elt - &*sym_classes->begin ();
 
       /* Program spaces that are executing startup should have
         been filtered out earlier.  */
-      pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+      pspace = symbol_symtab (sym)->pspace ();
       gdb_assert (!pspace->executing_startup);
       set_current_program_space (pspace);
-      t = check_typedef (SYMBOL_TYPE (sym));
-      find_methods (t, SYMBOL_LANGUAGE (sym),
+      t = check_typedef (sym->type ());
+      find_methods (t, sym->language (),
                    method_name, &result_names, &superclass_vec);
 
       /* Handle all items from a single program space at once; and be
         sure not to miss the last batch.  */
       if (ix == sym_classes->size () - 1
          || (pspace
-             != SYMTAB_PSPACE (symbol_symtab (sym_classes->at (ix + 1)))))
+             != symbol_symtab (sym_classes->at (ix + 1).symbol)->pspace ()))
        {
          /* If we did not find a direct implementation anywhere in
             this program space, consider superclasses.  */
          if (result_names.size () == last_result_len)
            find_superclass_methods (std::move (superclass_vec), method_name,
-                                    SYMBOL_LANGUAGE (sym), &result_names);
+                                    sym->language (), &result_names);
 
          /* We have a list of candidate symbol names, so now we
             iterate over the symbol tables looking for all
@@ -3744,7 +3710,6 @@ find_method (struct linespec_state *self, std::vector<symtab *> *file_symtabs,
 
          superclass_vec.clear ();
          last_result_len = result_names.size ();
-         ++ix;
        }
     }
 
@@ -3767,33 +3732,26 @@ class symtab_collector
 {
 public:
   symtab_collector ()
-    : m_symtabs (new std::vector<symtab *> ())
-  {
-    m_symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
-                                 NULL);
-  }
-
-  ~symtab_collector ()
+    : m_symtab_table (htab_create (1, htab_hash_pointer, htab_eq_pointer,
+                                  NULL))
   {
-    if (m_symtab_table != NULL)
-      htab_delete (m_symtab_table);
   }
 
   /* Callable as a symbol_found_callback_ftype callback.  */
   bool operator () (symtab *sym);
 
-  /* Releases ownership of the collected symtabs and returns them.  */
-  symtab_vector_up release_symtabs ()
+  /* Return an rvalue reference to the collected symtabs.  */
+  std::vector<symtab *> &&release_symtabs ()
   {
     return std::move (m_symtabs);
   }
 
 private:
   /* The result vector of symtabs.  */
-  symtab_vector_up m_symtabs;
+  std::vector<symtab *> m_symtabs;
 
   /* This is used to ensure the symtabs are unique.  */
-  htab_t m_symtab_table;
+  htab_up m_symtab_table;
 };
 
 bool
@@ -3801,11 +3759,11 @@ symtab_collector::operator () (struct symtab *symtab)
 {
   void **slot;
 
-  slot = htab_find_slot (m_symtab_table, symtab, INSERT);
+  slot = htab_find_slot (m_symtab_table.get (), symtab, INSERT);
   if (!*slot)
     {
       *slot = symtab;
-      m_symtabs->push_back (symtab);
+      m_symtabs.push_back (symtab);
     }
 
   return false;
@@ -3817,7 +3775,7 @@ symtab_collector::operator () (struct symtab *symtab)
    SEARCH_PSPACE is not NULL, the search is restricted to just that
    program space.  */
 
-static symtab_vector_up
+static std::vector<symtab *>
 collect_symtabs_from_filename (const char *file,
                               struct program_space *search_pspace)
 {
@@ -3826,10 +3784,8 @@ collect_symtabs_from_filename (const char *file,
   /* Find that file's data.  */
   if (search_pspace == NULL)
     {
-      struct program_space *pspace;
-
-      ALL_PSPACES (pspace)
-        {
+      for (struct program_space *pspace : program_spaces)
+       {
          if (pspace->executing_startup)
            continue;
 
@@ -3849,14 +3805,14 @@ collect_symtabs_from_filename (const char *file,
 /* Return all the symtabs associated to the FILENAME.  If SEARCH_PSPACE is
    not NULL, the search is restricted to just that program space.  */
 
-static symtab_vector_up
+static std::vector<symtab *>
 symtabs_from_filename (const char *filename,
                       struct program_space *search_pspace)
 {
-  symtab_vector_up result
+  std::vector<symtab *> result
     = collect_symtabs_from_filename (filename, search_pspace);
 
-  if (result->empty ())
+  if (result.empty ())
     {
       if (!have_full_symbols () && !have_partial_symbols ())
        throw_error (NOT_FOUND_ERROR,
@@ -3868,15 +3824,45 @@ symtabs_from_filename (const char *filename,
   return result;
 }
 
+/* See symtab.h.  */
+
+void
+symbol_searcher::find_all_symbols (const std::string &name,
+                                  const struct language_defn *language,
+                                  enum search_domain search_domain,
+                                  std::vector<symtab *> *search_symtabs,
+                                  struct program_space *search_pspace)
+{
+  symbol_searcher_collect_info info;
+  struct linespec_state state;
+
+  memset (&state, 0, sizeof (state));
+  state.language = language;
+  info.state = &state;
+
+  info.result.symbols = &m_symbols;
+  info.result.minimal_symbols = &m_minimal_symbols;
+  std::vector<symtab *> all_symtabs;
+  if (search_symtabs == nullptr)
+    {
+      all_symtabs.push_back (nullptr);
+      search_symtabs = &all_symtabs;
+    }
+  info.file_symtabs = search_symtabs;
+
+  add_matching_symbols_to_info (name.c_str (), symbol_name_match_type::WILD,
+                               search_domain, &info, search_pspace);
+}
+
 /* Look up a function symbol named NAME in symtabs FILE_SYMTABS.  Matching
    debug symbols are returned in SYMBOLS.  Matching minimal symbols are
    returned in MINSYMS.  */
 
 static void
 find_function_symbols (struct linespec_state *state,
-                      std::vector<symtab *> *file_symtabs, const char *name,
+                      const std::vector<symtab *> &file_symtabs, const char *name,
                       symbol_name_match_type name_match_type,
-                      std::vector<symbol *> *symbols,
+                      std::vector<block_symbol> *symbols,
                       std::vector<bound_minimal_symbol> *minsyms)
 {
   struct collect_info info;
@@ -3885,7 +3871,7 @@ find_function_symbols (struct linespec_state *state,
   info.state = state;
   info.result.symbols = symbols;
   info.result.minimal_symbols = minsyms;
-  info.file_symtabs = file_symtabs;
+  info.file_symtabs = &file_symtabs;
 
   /* Try NAME as an Objective-C selector.  */
   find_imps (name, &symbol_names);
@@ -3902,15 +3888,16 @@ find_function_symbols (struct linespec_state *state,
 
 static void
 find_linespec_symbols (struct linespec_state *state,
-                      std::vector<symtab *> *file_symtabs,
+                      const std::vector<symtab *> &file_symtabs,
                       const char *lookup_name,
                       symbol_name_match_type name_match_type,
-                      std::vector <symbol *> *symbols,
+                      std::vector <block_symbol> *symbols,
                       std::vector<bound_minimal_symbol> *minsyms)
 {
-  std::string canon = cp_canonicalize_string_no_typedefs (lookup_name);
-  if (!canon.empty ())
-    lookup_name = canon.c_str ();
+  gdb::unique_xmalloc_ptr<char> canon
+    = cp_canonicalize_string_no_typedefs (lookup_name);
+  if (canon != nullptr)
+    lookup_name = canon.get ();
 
   /* It's important to not call expand_symtabs_matching unnecessarily
      as it can really slow things down (by unnecessarily expanding
@@ -3959,12 +3946,12 @@ find_linespec_symbols (struct linespec_state *state,
       method = last;
 
       /* Find a list of classes named KLASS.  */
-      std::vector<symbol *> classes
+      std::vector<block_symbol> classes
        = lookup_prefix_sym (state, file_symtabs, klass.c_str ());
       if (!classes.empty ())
        {
          /* Now locate a list of suitable methods named METHOD.  */
-         TRY
+         try
            {
              find_method (state, file_symtabs,
                           klass.c_str (), method.c_str (),
@@ -3973,12 +3960,11 @@ find_linespec_symbols (struct linespec_state *state,
 
          /* If successful, we're done.  If NOT_FOUND_ERROR
             was not thrown, rethrow the exception that we did get.  */
-         CATCH (except, RETURN_MASK_ERROR)
+         catch (const gdb_exception_error &except)
            {
              if (except.error != NOT_FOUND_ERROR)
-               throw_exception (except);
+               throw;
            }
-         END_CATCH
        }
     }
 }
@@ -3994,8 +3980,8 @@ static void
 find_label_symbols_in_block (const struct block *block,
                             const char *name, struct symbol *fn_sym,
                             bool completion_mode,
-                            std::vector<symbol *> *result,
-                            std::vector<symbol *> *label_funcs_ret)
+                            std::vector<block_symbol> *result,
+                            std::vector<block_symbol> *label_funcs_ret)
 {
   if (completion_mode)
     {
@@ -4008,46 +3994,48 @@ find_label_symbols_in_block (const struct block *block,
 
       ALL_BLOCK_SYMBOLS (block, iter, sym)
        {
-         if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
-                                    SYMBOL_DOMAIN (sym), LABEL_DOMAIN)
-             && cmp (SYMBOL_SEARCH_NAME (sym), name, name_len) == 0)
+         if (symbol_matches_domain (sym->language (),
+                                    sym->domain (), LABEL_DOMAIN)
+             && cmp (sym->search_name (), name, name_len) == 0)
            {
-             result->push_back (sym);
-             label_funcs_ret->push_back (fn_sym);
+             result->push_back ({sym, block});
+             label_funcs_ret->push_back ({fn_sym, block});
            }
        }
     }
   else
     {
-      struct symbol *sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol;
+      struct block_symbol label_sym
+       = lookup_symbol (name, block, LABEL_DOMAIN, 0);
 
-      if (sym != NULL)
+      if (label_sym.symbol != NULL)
        {
-         result->push_back (sym);
-         label_funcs_ret->push_back (fn_sym);
+         result->push_back (label_sym);
+         label_funcs_ret->push_back ({fn_sym, block});
        }
     }
 }
 
-/* Return all labels that match name NAME in FUNCTION_SYMBOLS or NULL
-   if no matches were found.
+/* Return all labels that match name NAME in FUNCTION_SYMBOLS.
 
    Return the actual function symbol in which the label was found in
    LABEL_FUNC_RET.  If COMPLETION_MODE is true, then NAME is
    interpreted as a label name prefix.  Otherwise, only labels named
    exactly NAME match.  */
 
-static std::vector<symbol *> *
+
+static std::vector<block_symbol>
 find_label_symbols (struct linespec_state *self,
-                   std::vector<symbol *> *function_symbols,
-                   std::vector<symbol *> *label_funcs_ret, const char *name,
+                   const std::vector<block_symbol> &function_symbols,
+                   std::vector<block_symbol> *label_funcs_ret,
+                   const char *name,
                    bool completion_mode)
 {
   const struct block *block;
   struct symbol *fn_sym;
-  std::vector<symbol *> result;
+  std::vector<block_symbol> result;
 
-  if (function_symbols == NULL)
+  if (function_symbols.empty ())
     {
       set_current_program_space (self->program_space);
       block = get_current_search_block ();
@@ -4056,8 +4044,10 @@ find_label_symbols (struct linespec_state *self,
           block && !BLOCK_FUNCTION (block);
           block = BLOCK_SUPERBLOCK (block))
        ;
+
       if (!block)
-       return NULL;
+       return {};
+
       fn_sym = BLOCK_FUNCTION (block);
 
       find_label_symbols_in_block (block, name, fn_sym, completion_mode,
@@ -4065,19 +4055,18 @@ find_label_symbols (struct linespec_state *self,
     }
   else
     {
-      for (const auto &elt : *function_symbols)
+      for (const auto &elt : function_symbols)
        {
-         set_current_program_space (SYMTAB_PSPACE (symbol_symtab (elt)));
-         block = SYMBOL_BLOCK_VALUE (elt);
+         fn_sym = elt.symbol;
+         set_current_program_space (symbol_symtab (fn_sym)->pspace ());
+         block = SYMBOL_BLOCK_VALUE (fn_sym);
 
-         find_label_symbols_in_block (block, name, elt, completion_mode,
+         find_label_symbols_in_block (block, name, fn_sym, completion_mode,
                                       &result, label_funcs_ret);
        }
     }
 
-  if (!result.empty ())
-    return new std::vector<symbol *> (std::move (result));
-  return nullptr;
+  return result;
 }
 
 \f
@@ -4086,27 +4075,27 @@ find_label_symbols (struct linespec_state *self,
 
 static std::vector<symtab_and_line>
 decode_digits_list_mode (struct linespec_state *self,
-                        linespec_p ls,
+                        linespec *ls,
                         struct symtab_and_line val)
 {
   gdb_assert (self->list_mode);
 
   std::vector<symtab_and_line> values;
 
-  for (const auto &elt : *ls->file_symtabs)
+  for (const auto &elt : ls->file_symtabs)
     {
       /* The logic above should ensure this.  */
       gdb_assert (elt != NULL);
 
-      set_current_program_space (SYMTAB_PSPACE (elt));
+      set_current_program_space (elt->pspace ());
 
       /* Simplistic search just for the list command.  */
       val.symtab = find_line_symtab (elt, val.line, NULL, NULL);
       if (val.symtab == NULL)
        val.symtab = elt;
-      val.pspace = SYMTAB_PSPACE (elt);
+      val.pspace = elt->pspace ();
       val.pc = 0;
-      val.explicit_line = 1;
+      val.explicit_line = true;
 
       add_sal_to_sals (self, &values, &val, NULL, 0);
     }
@@ -4114,32 +4103,34 @@ decode_digits_list_mode (struct linespec_state *self,
   return values;
 }
 
-/* A helper for create_sals_line_offset that iterates over the symtabs,
-   adding lines to the VEC.  */
+/* A helper for create_sals_line_offset that iterates over the symtabs
+   associated with LS and returns a vector of corresponding symtab_and_line
+   structures.  */
 
 static std::vector<symtab_and_line>
 decode_digits_ordinary (struct linespec_state *self,
-                       linespec_p ls,
+                       linespec *ls,
                        int line,
                        struct linetable_entry **best_entry)
 {
   std::vector<symtab_and_line> sals;
-  for (const auto &elt : *ls->file_symtabs)
+  for (const auto &elt : ls->file_symtabs)
     {
       std::vector<CORE_ADDR> pcs;
 
       /* The logic above should ensure this.  */
       gdb_assert (elt != NULL);
 
-      set_current_program_space (SYMTAB_PSPACE (elt));
+      set_current_program_space (elt->pspace ());
 
       pcs = find_pcs_for_symtab_line (elt, line, best_entry);
       for (CORE_ADDR pc : pcs)
        {
          symtab_and_line sal;
-         sal.pspace = SYMTAB_PSPACE (elt);
+         sal.pspace = elt->pspace ();
          sal.symtab = elt;
          sal.line = line;
+         sal.explicit_line = true;
          sal.pc = pc;
          sals.push_back (std::move (sal));
        }
@@ -4172,7 +4163,7 @@ linespec_parse_variable (struct linespec_state *self, const char *variable)
       sscanf ((variable[1] == '$') ? variable + 2 : variable + 1, "%d", &index);
       val_history
        = access_value_history ((variable[1] == '$') ? -index : index);
-      if (TYPE_CODE (value_type (val_history)) != TYPE_CODE_INT)
+      if (value_type (val_history)->code () != TYPE_CODE_INT)
        error (_("History values used in line "
                 "specs must have integer values."));
       offset.offset = value_as_long (val_history);
@@ -4224,7 +4215,7 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
 
   if (is_function)
     {
-      const char *msym_name = MSYMBOL_LINKAGE_NAME (msymbol);
+      const char *msym_name = msymbol->linkage_name ();
 
       if (MSYMBOL_TYPE (msymbol) == mst_text_gnu_ifunc
          || MSYMBOL_TYPE (msymbol) == mst_data_gnu_ifunc)
@@ -4250,45 +4241,10 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
       sal.pspace = current_program_space;
     }
 
-  sal.section = MSYMBOL_OBJ_SECTION (objfile, msymbol);
+  sal.section = msymbol->obj_section (objfile);
 
   if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
-    add_sal_to_sals (self, result, &sal, MSYMBOL_NATURAL_NAME (msymbol), 0);
-}
-
-/* A helper function to classify a minimal_symbol_type according to
-   priority.  */
-
-static int
-classify_mtype (enum minimal_symbol_type t)
-{
-  switch (t)
-    {
-    case mst_file_text:
-    case mst_file_data:
-    case mst_file_bss:
-      /* Intermediate priority.  */
-      return 1;
-
-    case mst_solib_trampoline:
-      /* Lowest priority.  */
-      return 2;
-
-    default:
-      /* Highest priority.  */
-      return 0;
-    }
-}
-
-/* Callback for std::sort that sorts symbols by priority.  */
-
-static bool
-compare_msyms (const bound_minimal_symbol &a, const bound_minimal_symbol &b)
-{
-  enum minimal_symbol_type ta = MSYMBOL_TYPE (a.minsym);
-  enum minimal_symbol_type tb = MSYMBOL_TYPE (b.minsym);
-
-  return classify_mtype (ta) < classify_mtype (tb);
+    add_sal_to_sals (self, result, &sal, msymbol->natural_name (), 0);
 }
 
 /* Helper for search_minsyms_for_name that adds the symbol to the
@@ -4317,8 +4273,7 @@ add_minsym (struct minimal_symbol *minsym, struct objfile *objfile,
   if (!list_mode && !msymbol_is_function (objfile, minsym))
     return;
 
-  struct bound_minimal_symbol mo = {minsym, objfile};
-  msyms->push_back (mo);
+  msyms->emplace_back (minsym, objfile);
   return;
 }
 
@@ -4339,66 +4294,91 @@ search_minsyms_for_name (struct collect_info *info,
 
   if (symtab == NULL)
     {
-      struct program_space *pspace;
-
-      ALL_PSPACES (pspace)
-      {
-       struct objfile *objfile;
-
-       if (search_pspace != NULL && search_pspace != pspace)
-         continue;
-       if (pspace->executing_startup)
-         continue;
+      for (struct program_space *pspace : program_spaces)
+       {
+         if (search_pspace != NULL && search_pspace != pspace)
+           continue;
+         if (pspace->executing_startup)
+           continue;
 
-       set_current_program_space (pspace);
+         set_current_program_space (pspace);
 
-       ALL_OBJFILES (objfile)
-       {
-         iterate_over_minimal_symbols (objfile, name,
-                                       [&] (struct minimal_symbol *msym)
-                                         {
-                                           add_minsym (msym, objfile, nullptr,
-                                                       info->state->list_mode,
-                                                       &minsyms);
-                                           return false;
-                                         });
+         for (objfile *objfile : current_program_space->objfiles ())
+           {
+             iterate_over_minimal_symbols (objfile, name,
+                                           [&] (struct minimal_symbol *msym)
+                                           {
+                                             add_minsym (msym, objfile, nullptr,
+                                                         info->state->list_mode,
+                                                         &minsyms);
+                                             return false;
+                                           });
+           }
        }
-      }
     }
   else
     {
-      if (search_pspace == NULL || SYMTAB_PSPACE (symtab) == search_pspace)
+      if (search_pspace == NULL || symtab->pspace () == search_pspace)
        {
-         set_current_program_space (SYMTAB_PSPACE (symtab));
+         set_current_program_space (symtab->pspace ());
          iterate_over_minimal_symbols
-           (SYMTAB_OBJFILE (symtab), name,
+           (symtab->objfile (), name,
             [&] (struct minimal_symbol *msym)
               {
-                add_minsym (msym, SYMTAB_OBJFILE (symtab), symtab,
+                add_minsym (msym, symtab->objfile (), symtab,
                             info->state->list_mode, &minsyms);
                 return false;
               });
        }
     }
 
-  if (!minsyms.empty ())
+  /* Return true if TYPE is a static symbol.  */
+  auto msymbol_type_is_static = [] (enum minimal_symbol_type type)
     {
-      int classification;
+      switch (type)
+       {
+       case mst_file_text:
+       case mst_file_data:
+       case mst_file_bss:
+       return true;
+       default:
+       return false;
+       }
+    };
 
-      std::sort (minsyms.begin (), minsyms.end (), compare_msyms);
+  /* Add minsyms to the result set, but filter out trampoline symbols
+     if we also found extern symbols with the same name.  I.e., don't
+     set a breakpoint on both '<foo@plt>' and 'foo', assuming that
+     'foo' is the symbol that the plt resolves to.  */
+  for (const bound_minimal_symbol &item : minsyms)
+    {
+      bool skip = false;
+      if (MSYMBOL_TYPE (item.minsym) == mst_solib_trampoline)
+       {
+         for (const bound_minimal_symbol &item2 : minsyms)
+           {
+             if (&item2 == &item)
+               continue;
 
-      /* Now the minsyms are in classification order.  So, we walk
-        over them and process just the minsyms with the same
-        classification as the very first minsym in the list.  */
-      classification = classify_mtype (MSYMBOL_TYPE (minsyms[0].minsym));
+             /* Trampoline symbols can only jump to exported
+                symbols.  */
+             if (msymbol_type_is_static (MSYMBOL_TYPE (item2.minsym)))
+               continue;
 
-      for (const bound_minimal_symbol &item : minsyms)
-       {
-         if (classify_mtype (MSYMBOL_TYPE (item.minsym)) != classification)
-           break;
+             if (strcmp (item.minsym->linkage_name (),
+                         item2.minsym->linkage_name ()) != 0)
+               continue;
 
-         info->result.minimal_symbols->push_back (item);
+             /* Found a global minsym with the same name as the
+                trampoline.  Don't create a location for this
+                trampoline.  */
+             skip = true;
+             break;
+           }
        }
+
+      if (!skip)
+       info->result.minimal_symbols->push_back (item);
     }
 }
 
@@ -4421,28 +4401,29 @@ add_matching_symbols_to_info (const char *name,
        {
          iterate_over_all_matching_symtabs (info->state, lookup_name,
                                             VAR_DOMAIN, search_domain,
-                                            pspace, true, [&] (symbol *sym)
-           { return info->add_symbol (sym); });
+                                            pspace, true,
+                                            [&] (block_symbol *bsym)
+           { return info->add_symbol (bsym); });
          search_minsyms_for_name (info, lookup_name, pspace, NULL);
        }
-      else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
+      else if (pspace == NULL || pspace == elt->pspace ())
        {
          int prev_len = info->result.symbols->size ();
 
          /* Program spaces that are executing startup should have
             been filtered out earlier.  */
-         gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
-         set_current_program_space (SYMTAB_PSPACE (elt));
+         gdb_assert (!elt->pspace ()->executing_startup);
+         set_current_program_space (elt->pspace ());
          iterate_over_file_blocks (elt, lookup_name, VAR_DOMAIN,
-                                   [&] (symbol *sym)
-           { return info->add_symbol (sym); });
+                                   [&] (block_symbol *bsym)
+           { return info->add_symbol (bsym); });
 
          /* If no new symbols were found in this iteration and this symtab
             is in assembler, we might actually be looking for a label for
             which we don't have debug info.  Check for a minimal symbol in
             this case.  */
          if (prev_len == info->result.symbols->size ()
-             && elt->language == language_asm)
+             && elt->language () == language_asm)
            search_minsyms_for_name (info, lookup_name, pspace, elt);
        }
     }
@@ -4457,21 +4438,21 @@ static int
 symbol_to_sal (struct symtab_and_line *result,
               int funfirstline, struct symbol *sym)
 {
-  if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+  if (sym->aclass () == LOC_BLOCK)
     {
       *result = find_function_start_sal (sym, funfirstline);
       return 1;
     }
   else
     {
-      if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
+      if (sym->aclass () == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
        {
          *result = {};
          result->symtab = symbol_symtab (sym);
          result->symbol = sym;
-         result->line = SYMBOL_LINE (sym);
+         result->line = sym->line ();
          result->pc = SYMBOL_VALUE_ADDRESS (sym);
-         result->pspace = SYMTAB_PSPACE (result->symtab);
+         result->pspace = result->symtab->pspace ();
          result->explicit_pc = 1;
          return 1;
        }
@@ -4479,15 +4460,15 @@ symbol_to_sal (struct symtab_and_line *result,
        {
          /* Nothing.  */
        }
-      else if (SYMBOL_LINE (sym) != 0)
+      else if (sym->line () != 0)
        {
          /* We know its line number.  */
          *result = {};
          result->symtab = symbol_symtab (sym);
          result->symbol = sym;
-         result->line = SYMBOL_LINE (sym);
+         result->line = sym->line ();
          result->pc = SYMBOL_VALUE_ADDRESS (sym);
-         result->pspace = SYMTAB_PSPACE (result->symtab);
+         result->pspace = result->symtab->pspace ();
          return 1;
        }
     }