Explicit locations -label completer
[deliverable/binutils-gdb.git] / gdb / linespec.c
index d2089b5dd9d1dae7324983e2d537110152b08083..0216bf123e68624268e4100a58d2b64e6dc09da2 100644 (file)
@@ -1,6 +1,6 @@
 /* Parser for linespec for the GNU debugger, GDB.
 
-   Copyright (C) 1986-2015 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -43,6 +43,8 @@
 #include "filenames.h"
 #include "ada-lang.h"
 #include "stack.h"
+#include "location.h"
+#include "common/function-view.h"
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -64,73 +66,26 @@ typedef struct bound_minimal_symbol bound_minimal_symbol_d;
 
 DEF_VEC_O (bound_minimal_symbol_d);
 
-/* An enumeration of possible signs for a line offset.  */
-enum offset_relative_sign
-{
-  /* No sign  */
-  LINE_OFFSET_NONE,
-
-  /* A plus sign ("+")  */
-  LINE_OFFSET_PLUS,
-
-  /* A minus sign ("-")  */
-  LINE_OFFSET_MINUS,
-
-  /* A special "sign" for unspecified offset.  */
-  LINE_OFFSET_UNKNOWN
-};
-
-/* A line offset in a linespec.  */
-
-struct line_offset
-{
-  /* Line offset and any specified sign.  */
-  int offset;
-  enum offset_relative_sign sign;
-};
-
 /* A linespec.  Elements of this structure are filled in by a parser
    (either parse_linespec or some other function).  The structure is
    then converted into SALs by convert_linespec_to_sals.  */
 
 struct linespec
 {
-  /* An expression and the resulting PC.  Specifying an expression
-     currently precludes the use of other members.  */
-
-  /* The expression entered by the user.  */
-  const char *expression;
-
-  /* The resulting PC expression derived from evaluating EXPRESSION.  */
-  CORE_ADDR expr_pc;
-
-  /* Any specified file symtabs.  */
-
-  /* The user-supplied source filename or NULL if none was specified.  */
-  const char *source_filename;
+  /* An explicit location describing the SaLs.  */
+  struct explicit_location explicit_loc;
 
   /* The list of symtabs to search to which to limit the search.  May not
-     be NULL.  If 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.  */
+     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.  */
   VEC (symtab_ptr) *file_symtabs;
 
-  /* The name of a function or method and any matching symbols.  */
-
-  /* The user-specified function name.  If no function name was
-     supplied, this may be NULL.  */
-  const char *function_name;
-
   /* A list of matching function symbols and minimal symbols.  Both lists
      may be NULL if no matching symbols were found.  */
   VEC (symbolp) *function_symbols;
   VEC (bound_minimal_symbol_d) *minimal_symbols;
 
-  /* The name of a label and matching symbols.  */
-
-  /* The user-specified label name.  */
-  const char *label_name;
-
   /* 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.  */
@@ -139,10 +94,6 @@ struct linespec
     VEC (symbolp) *label_symbols;
     VEC (symbolp) *function_symbols;
   } labels;
-
-  /* Line offset.  It may be LINE_OFFSET_UNKNOWN, meaning that no
-   offset was specified.  */
-  struct line_offset line_offset;
 };
 typedef struct linespec *linespec_p;
 
@@ -173,6 +124,10 @@ struct linespec_state
   /* The program space as seen when the module was entered.  */
   struct program_space *program_space;
 
+  /* If not NULL, the search is restricted to just this program
+     space.  */
+  struct program_space *search_pspace;
+
   /* The default symtab to use, if no other symtab is specified.  */
   struct symtab *default_symtab;
 
@@ -195,6 +150,9 @@ struct linespec_state
   /* This is a set of address_entry objects which is used to prevent
      duplicate symbols from being entered into the result.  */
   htab_t addr_set;
+
+  /* Are we building a linespec?  */
+  int is_linespec;
 };
 
 /* This is a helper object that is used when collecting symbols into a
@@ -214,8 +172,23 @@ struct collect_info
     VEC (symbolp) *symbols;
     VEC (bound_minimal_symbol_d) *minimal_symbols;
   } result;
+
+  /* Possibly add a symbol to the results.  */
+  bool add_symbol (symbol *sym);
 };
 
+bool
+collect_info::add_symbol (symbol *sym)
+{
+  /* 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)
+    VEC_safe_push (symbolp, this->result.symbols, sym);
+
+  /* Continue iterating.  */
+  return true;
+}
+
 /* Token types  */
 
 enum ls_token_type
@@ -243,9 +216,9 @@ enum ls_token_type
 };
 typedef enum ls_token_type linespec_token_type;
 
-/* List of keywords  */
-
-static const char * const linespec_keywords[] = { "if", "thread", "task" };
+/* 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 };
 #define IF_KEYWORD_INDEX 0
 
 /* A token of the linespec lexer  */
@@ -281,8 +254,8 @@ struct ls_parser
     const char *saved_arg;
 
     /* Head of the input stream.  */
-    const char **stream;
-#define PARSER_STREAM(P) (*(P)->lexer.stream)
+    const char *stream;
+#define PARSER_STREAM(P) ((P)->lexer.stream)
 
     /* The current token.  */
     linespec_token current;
@@ -301,28 +274,33 @@ struct ls_parser
 };
 typedef struct ls_parser linespec_parser;
 
+/* A convenience macro for accessing the explicit location result of
+   the parser.  */
+#define PARSER_EXPLICIT(PPTR) (&PARSER_RESULT ((PPTR))->explicit_loc)
+
 /* Prototypes for local functions.  */
 
-static void iterate_over_file_blocks (struct symtab *symtab,
-                                     const char *name, domain_enum domain,
-                                     symbol_found_callback_ftype *callback,
-                                     void *data);
+static void iterate_over_file_blocks
+  (struct symtab *symtab, const char *name, domain_enum domain,
+   gdb::function_view<symbol_found_callback_ftype> callback);
 
 static void initialize_defaults (struct symtab **default_symtab,
                                 int *default_line);
 
-static CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
+CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
 
 static struct symtabs_and_lines decode_objc (struct linespec_state *self,
                                             linespec_p ls,
-                                            const char **argptr);
+                                            const char *arg);
 
-static VEC (symtab_ptr) *symtabs_from_filename (const char *);
+static VEC (symtab_ptr) *symtabs_from_filename (const char *,
+                                               struct program_space *pspace);
 
 static VEC (symbolp) *find_label_symbols (struct linespec_state *self,
                                          VEC (symbolp) *function_symbols,
                                          VEC (symbolp) **label_funcs_ret,
-                                         const char *name);
+                                         const char *name,
+                                         bool completion_mode = false);
 
 static void find_linespec_symbols (struct linespec_state *self,
                                   VEC (symtab_ptr) *file_symtabs,
@@ -345,7 +323,9 @@ static void add_all_symbol_names_from_pspace (struct collect_info *info,
                                              struct program_space *pspace,
                                              VEC (const_char_ptr) *names);
 
-static VEC (symtab_ptr) *collect_symtabs_from_filename (const char *file);
+static VEC (symtab_ptr) *
+  collect_symtabs_from_filename (const char *file,
+                                struct program_space *pspace);
 
 static void decode_digits_ordinary (struct linespec_state *self,
                                    linespec_p ls,
@@ -366,8 +346,6 @@ static int compare_symbols (const void *a, const void *b);
 
 static int compare_msymbols (const void *a, const void *b);
 
-static const char *find_toplevel_char (const char *s, char c);
-
 /* Permitted quote characters for the parser.  This is different from the
    completer's quote characters to allow backward compatibility with the
    previous parser.  */
@@ -423,7 +401,7 @@ linespec_lexer_lex_keyword (const char *p)
 
   if (p != NULL)
     {
-      for (i = 0; i < ARRAY_SIZE (linespec_keywords); ++i)
+      for (i = 0; linespec_keywords[i] != NULL; ++i)
        {
          int len = strlen (linespec_keywords[i]);
 
@@ -444,7 +422,7 @@ linespec_lexer_lex_keyword (const char *p)
                {
                  p += len;
                  p = skip_spaces_const (p);
-                 for (j = 0; j < ARRAY_SIZE (linespec_keywords); ++j)
+                 for (j = 0; linespec_keywords[j] != NULL; ++j)
                    {
                      int nextlen = strlen (linespec_keywords[j]);
 
@@ -462,10 +440,9 @@ linespec_lexer_lex_keyword (const char *p)
   return NULL;
 }
 
-/* Does STRING represent an Ada operator?  If so, return the length
-   of the decoded operator name.  If not, return 0.  */
+/*  See description in linespec.h.  */
 
-static int
+int
 is_ada_operator (const char *string)
 {
   const struct ada_opname_map *mapping;
@@ -712,10 +689,9 @@ linespec_lexer_lex_string (linespec_parser *parser)
            {
              if ((PARSER_STATE (parser)->language->la_language
                   == language_cplus)
-                 && (PARSER_STREAM (parser) - start) > 8
-                 /* strlen ("operator") */)
+                 && (PARSER_STREAM (parser) - start) > CP_OPERATOR_LEN)
                {
-                 char *p = strstr (start, "operator");
+                 const char *p = strstr (start, CP_OPERATOR_STR);
 
                  if (p != NULL && is_operator_name (p))
                    {
@@ -856,7 +832,7 @@ add_sal_to_sals_basic (struct symtabs_and_lines *sals,
                       struct symtab_and_line *sal)
 {
   ++sals->nelts;
-  sals->sals = xrealloc (sals->sals, sals->nelts * sizeof (sals->sals[0]));
+  sals->sals = XRESIZEVEC (struct symtab_and_line, sals->sals, sals->nelts);
   sals->sals[sals->nelts - 1] = *sal;
 }
 
@@ -879,13 +855,12 @@ add_sal_to_sals (struct linespec_state *self,
     {
       struct linespec_canonical_name *canonical;
 
-      self->canonical_names = xrealloc (self->canonical_names,
-                                       (sals->nelts
-                                        * sizeof (*self->canonical_names)));
+      self->canonical_names = XRESIZEVEC (struct linespec_canonical_name,
+                                         self->canonical_names, sals->nelts);
       canonical = &self->canonical_names[sals->nelts - 1];
       if (!literal_canonical && sal->symtab)
        {
-         const char *fullname = symtab_to_fullname (sal->symtab);
+         symtab_to_fullname (sal->symtab);
 
          /* Note that the filter doesn't have to be a valid linespec
             input.  We only apply the ":LINE" treatment to Ada for
@@ -915,7 +890,7 @@ add_sal_to_sals (struct linespec_state *self,
 static hashval_t
 hash_address_entry (const void *p)
 {
-  const struct address_entry *aep = p;
+  const struct address_entry *aep = (const struct address_entry *) p;
   hashval_t hash;
 
   hash = iterative_hash_object (aep->pspace, 0);
@@ -927,8 +902,8 @@ hash_address_entry (const void *p)
 static int
 eq_address_entry (const void *a, const void *b)
 {
-  const struct address_entry *aea = a;
-  const struct address_entry *aeb = b;
+  const struct address_entry *aea = (const struct address_entry *) a;
+  const struct address_entry *aeb = (const struct address_entry *) b;
 
   return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
 }
@@ -956,81 +931,26 @@ maybe_add_address (htab_t set, struct program_space *pspace, CORE_ADDR addr)
   return 1;
 }
 
-/* A callback function and the additional data to call it with.  */
-
-struct symbol_and_data_callback
-{
-  /* The callback to use.  */
-  symbol_found_callback_ftype *callback;
-
-  /* Data to be passed to the callback.  */
-  void *data;
-};
-
-/* A helper for iterate_over_all_matching_symtabs that is used to
-   restrict calls to another callback to symbols representing inline
-   symbols only.  */
-
-static int
-iterate_inline_only (struct symbol *sym, void *d)
-{
-  if (SYMBOL_INLINED (sym))
-    {
-      struct symbol_and_data_callback *cad = d;
-
-      return cad->callback (sym, cad->data);
-    }
-  return 1; /* Continue iterating.  */
-}
-
-/* Some data for the expand_symtabs_matching callback.  */
-
-struct symbol_matcher_data
-{
-  /* The lookup name against which symbol name should be compared.  */
-  const char *lookup_name;
-
-  /* The routine to be used for comparison.  */
-  symbol_name_cmp_ftype symbol_name_cmp;
-};
-
-/* A helper for iterate_over_all_matching_symtabs that is passed as a
-   callback to the expand_symtabs_matching method.  */
-
-static int
-iterate_name_matcher (const char *name, void *d)
-{
-  const struct symbol_matcher_data *data = d;
-
-  if (data->symbol_name_cmp (name, data->lookup_name) == 0)
-    return 1; /* Expand this symbol's symbol table.  */
-  return 0; /* Skip this symbol.  */
-}
-
 /* A helper that walks over all matching symtabs in all objfiles and
    calls CALLBACK for each symbol matching NAME.  If SEARCH_PSPACE is
    not NULL, then the search is restricted to just that program
-   space.  If INCLUDE_INLINE is nonzero then symbols representing
+   space.  If INCLUDE_INLINE is true then symbols representing
    inlined instances of functions will be included in the result.  */
 
 static void
-iterate_over_all_matching_symtabs (struct linespec_state *state,
-                                  const char *name,
-                                  const domain_enum domain,
-                                  symbol_found_callback_ftype *callback,
-                                  void *data,
-                                  struct program_space *search_pspace,
-                                  int include_inline)
+iterate_over_all_matching_symtabs
+  (struct linespec_state *state, const char *name, const domain_enum domain,
+   struct program_space *search_pspace, bool include_inline,
+   gdb::function_view<symbol_found_callback_ftype> callback)
 {
   struct objfile *objfile;
   struct program_space *pspace;
-  struct symbol_matcher_data matcher_data;
 
-  matcher_data.lookup_name = name;
-  matcher_data.symbol_name_cmp =
-    state->language->la_get_symbol_name_cmp != NULL
-    ? state->language->la_get_symbol_name_cmp (name)
-    : strcmp_iw;
+  /* The routine to be used for comparison.  */
+  symbol_name_cmp_ftype symbol_name_cmp
+    = (state->language->la_get_symbol_name_cmp != NULL
+       ? state->language->la_get_symbol_name_cmp (name)
+       : strcmp_iw);
 
   ALL_PSPACES (pspace)
   {
@@ -1046,20 +966,24 @@ iterate_over_all_matching_symtabs (struct linespec_state *state,
       struct compunit_symtab *cu;
 
       if (objfile->sf)
-       objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
-                                                 iterate_name_matcher,
-                                                 NULL, ALL_DOMAIN,
-                                                 &matcher_data);
+       objfile->sf->qf->expand_symtabs_matching
+         (objfile,
+          NULL,
+          [&] (const char *symbol_name)
+          {
+            return symbol_name_cmp (symbol_name, name) == 0;
+          },
+          NULL,
+          ALL_DOMAIN);
 
       ALL_OBJFILE_COMPUNITS (objfile, cu)
        {
          struct symtab *symtab = COMPUNIT_FILETABS (cu);
 
-         iterate_over_file_blocks (symtab, name, domain, callback, data);
+         iterate_over_file_blocks (symtab, name, domain, callback);
 
          if (include_inline)
            {
-             struct symbol_and_data_callback cad = { callback, data };
              struct block *block;
              int i;
 
@@ -1069,7 +993,14 @@ iterate_over_all_matching_symtabs (struct linespec_state *state,
                {
                  block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), i);
                  state->language->la_iterate_over_symbols
-                   (block, name, domain, iterate_inline_only, &cad);
+                   (block, name, domain, [&] (symbol *sym)
+                    {
+                      /* Restrict calls to CALLBACK to symbols
+                         representing inline symbols only.  */
+                      if (SYMBOL_INLINED (sym))
+                        return callback (sym);
+                      return true;
+                    });
                }
            }
        }
@@ -1098,16 +1029,16 @@ get_current_search_block (void)
 /* Iterate over static and global blocks.  */
 
 static void
-iterate_over_file_blocks (struct symtab *symtab,
-                         const char *name, domain_enum domain,
-                         symbol_found_callback_ftype *callback, void *data)
+iterate_over_file_blocks
+  (struct symtab *symtab, const char *name, domain_enum domain,
+   gdb::function_view<symbol_found_callback_ftype> callback)
 {
   struct block *block;
 
   for (block = BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symtab), STATIC_BLOCK);
        block != NULL;
        block = BLOCK_SUPERBLOCK (block))
-    LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
+    LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback);
 }
 
 /* A helper for find_method.  This finds all methods in type T which
@@ -1129,7 +1060,7 @@ find_methods (struct type *t, const char *name,
     {
       int method_counter;
 
-      CHECK_TYPEDEF (t);
+      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
@@ -1183,7 +1114,7 @@ find_methods (struct type *t, const char *name,
    strings.  Also, ignore the char within a template name, like a ','
    within foo<int, int>.  */
 
-static const char *
+const char *
 find_toplevel_char (const char *s, char c)
 {
   int quoted = 0;              /* zero if we're not in quotes;
@@ -1341,8 +1272,8 @@ struct decode_line_2_item
 static int
 decode_line_2_compare_items (const void *ap, const void *bp)
 {
-  const struct decode_line_2_item *a = ap;
-  const struct decode_line_2_item *b = bp;
+  const struct decode_line_2_item *a = (const struct decode_line_2_item *) ap;
+  const struct decode_line_2_item *b = (const struct decode_line_2_item *) bp;
   int retval;
 
   retval = strcmp (a->displayform, b->displayform);
@@ -1362,11 +1293,11 @@ decode_line_2 (struct linespec_state *self,
               struct symtabs_and_lines *result,
               const char *select_mode)
 {
-  char *args, *prompt;
+  char *args;
+  const char *prompt;
   int i;
   struct cleanup *old_chain;
   VEC (const_char_ptr) *filters = NULL;
-  struct get_number_or_range_state state;
   struct decode_line_2_item *items;
   int items_count;
 
@@ -1378,7 +1309,7 @@ decode_line_2 (struct linespec_state *self,
 
   /* Prepare ITEMS array.  */
   items_count = result->nelts;
-  items = xmalloc (sizeof (*items) * items_count);
+  items = XNEWVEC (struct decode_line_2_item, items_count);
   make_cleanup (xfree, items);
   for (i = 0; i < items_count; ++i)
     {
@@ -1447,12 +1378,10 @@ decode_line_2 (struct linespec_state *self,
   if (args == 0 || *args == 0)
     error_no_arg (_("one or more choice numbers"));
 
-  init_number_or_range (&state, args);
-  while (!state.finished)
+  number_or_range_parser parser (args);
+  while (!parser.finished ())
     {
-      int num;
-
-      num = get_number_or_range (&state);
+      int num = parser.get_number ();
 
       if (num == 0)
        error (_("canceled"));
@@ -1557,10 +1486,9 @@ unexpected_linespec_error (linespec_parser *parser)
       || token.type == LSTOKEN_KEYWORD)
     {
       char *string;
-      struct cleanup *cleanup;
 
       string = copy_token_string (token);
-      cleanup = make_cleanup (xfree, string);
+      make_cleanup (xfree, string);
       throw_error (GENERIC_ERROR,
                   _("malformed linespec error: unexpected %s, \"%s\""),
                   token_type_strings[token.type], string);
@@ -1571,11 +1499,35 @@ unexpected_linespec_error (linespec_parser *parser)
                 token_type_strings[token.type]);
 }
 
-/* Parse and return a line offset in STRING.  */
+/* Throw an undefined label error.  */
 
-static struct line_offset
+static void ATTRIBUTE_NORETURN
+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);
+  else
+    throw_error (NOT_FOUND_ERROR,
+                _("No label \"%s\" defined in current function."),
+                label);
+}
+
+/* Throw a source file not found error.  */
+
+static void ATTRIBUTE_NORETURN
+source_file_not_found_error (const char *name)
+{
+  throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
+}
+
+/* See description in linespec.h.  */
+
+struct line_offset
 linespec_parse_line_offset (const char *string)
 {
+  const char *start = string;
   struct line_offset line_offset = {0, LINE_OFFSET_NONE};
 
   if (*string == '+')
@@ -1589,6 +1541,9 @@ linespec_parse_line_offset (const char *string)
       ++string;
     }
 
+  if (*string != '\0' && !isdigit (*string))
+    error (_("malformed line offset: \"%s\""), start);
+
   /* Right now, we only allow base 10 for offsets.  */
   line_offset.offset = atoi (string);
   return line_offset;
@@ -1617,7 +1572,7 @@ linespec_parse_basic (linespec_parser *parser)
       /* Record the line offset and get the next token.  */
       name = copy_token_string (token);
       cleanup = make_cleanup (xfree, name);
-      PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name);
+      PARSER_EXPLICIT (parser)->line_offset = linespec_parse_line_offset (name);
       do_cleanups (cleanup);
 
       /* Get the next token.  */
@@ -1654,7 +1609,7 @@ linespec_parse_basic (linespec_parser *parser)
     {
       PARSER_RESULT (parser)->function_symbols = symbols;
       PARSER_RESULT (parser)->minimal_symbols = minimal_symbols;
-      PARSER_RESULT (parser)->function_name = name;
+      PARSER_EXPLICIT (parser)->function_name = name;
       symbols = NULL;
       discard_cleanups (cleanup);
     }
@@ -1668,7 +1623,7 @@ linespec_parse_basic (linespec_parser *parser)
        {
          PARSER_RESULT (parser)->labels.label_symbols = labels;
          PARSER_RESULT (parser)->labels.function_symbols = symbols;
-         PARSER_RESULT (parser)->label_name = name;
+         PARSER_EXPLICIT (parser)->label_name = name;
          symbols = NULL;
          discard_cleanups (cleanup);
        }
@@ -1676,14 +1631,14 @@ linespec_parse_basic (linespec_parser *parser)
               && *LS_TOKEN_STOKEN (token).ptr == '$')
        {
          /* User specified a convenience variable or history value.  */
-         PARSER_RESULT (parser)->line_offset
+         PARSER_EXPLICIT (parser)->line_offset
            = linespec_parse_variable (PARSER_STATE (parser), name);
 
-         if (PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
+         if (PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
            {
              /* The user-specified variable was not valid.  Do not
                 throw an error here.  parse_linespec will do it for us.  */
-             PARSER_RESULT (parser)->function_name = name;
+             PARSER_EXPLICIT (parser)->function_name = name;
              discard_cleanups (cleanup);
              return;
            }
@@ -1698,7 +1653,7 @@ linespec_parse_basic (linespec_parser *parser)
             an error here.  parse_linespec will do it for us.  */
 
          /* Save a copy of the name we were trying to lookup.  */
-         PARSER_RESULT (parser)->function_name = name;
+         PARSER_EXPLICIT (parser)->function_name = name;
          discard_cleanups (cleanup);
          return;
        }
@@ -1718,7 +1673,7 @@ linespec_parse_basic (linespec_parser *parser)
             get the next token.  */
          name = copy_token_string (token);
          cleanup = make_cleanup (xfree, name);
-         PARSER_RESULT (parser)->line_offset
+         PARSER_EXPLICIT (parser)->line_offset
            = linespec_parse_line_offset (name);
          do_cleanups (cleanup);
 
@@ -1738,16 +1693,15 @@ linespec_parse_basic (linespec_parser *parser)
            {
              PARSER_RESULT (parser)->labels.label_symbols = labels;
              PARSER_RESULT (parser)->labels.function_symbols = symbols;
-             PARSER_RESULT (parser)->label_name = name;
+             PARSER_EXPLICIT (parser)->label_name = name;
              symbols = NULL;
              discard_cleanups (cleanup);
            }
          else
            {
              /* We don't know what it was, but it isn't a label.  */
-             throw_error (NOT_FOUND_ERROR,
-                          _("No label \"%s\" defined in function \"%s\"."),
-                          name, PARSER_RESULT (parser)->function_name);
+             undefined_label_error (PARSER_EXPLICIT (parser)->function_name,
+                                    name);
            }
 
          /* Check for a line offset.  */
@@ -1761,11 +1715,11 @@ linespec_parse_basic (linespec_parser *parser)
              if (token.type != LSTOKEN_NUMBER)
                unexpected_linespec_error (parser);
 
-             /* Record the lione offset and get the next token.  */
+             /* Record the line offset and get the next token.  */
              name = copy_token_string (token);
              cleanup = make_cleanup (xfree, name);
 
-             PARSER_RESULT (parser)->line_offset
+             PARSER_EXPLICIT (parser)->line_offset
                = linespec_parse_line_offset (name);
              do_cleanups (cleanup);
 
@@ -1782,74 +1736,50 @@ linespec_parse_basic (linespec_parser *parser)
 }
 
 /* Canonicalize the linespec contained in LS.  The result is saved into
-   STATE->canonical.  */
+   STATE->canonical.  This function handles both linespec and explicit
+   locations.  */
 
 static void
-canonicalize_linespec (struct linespec_state *state, linespec_p ls)
+canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
 {
+  struct event_location *canon;
+  struct explicit_location *explicit_loc;
+
   /* If canonicalization was not requested, no need to do anything.  */
   if (!state->canonical)
     return;
 
-  /* Shortcut expressions, which can only appear by themselves.  */
-  if (ls->expression != NULL)
-    state->canonical->addr_string = xstrdup (ls->expression);
-  else
-    {
-      struct ui_file *buf;
-      int need_colon = 0;
-
-      buf = mem_fileopen ();
-      if (ls->source_filename)
-       {
-         fputs_unfiltered (ls->source_filename, buf);
-         need_colon = 1;
-       }
+  /* Save everything as an explicit location.  */
+  state->canonical->location
+    = new_explicit_location (&ls->explicit_loc);
+  canon = state->canonical->location.get ();
+  explicit_loc = get_explicit_location (canon);
 
-      if (ls->function_name)
-       {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-         fputs_unfiltered (ls->function_name, buf);
-         need_colon = 1;
-       }
+  if (explicit_loc->label_name != NULL)
+    {
+      state->canonical->special_display = 1;
 
-      if (ls->label_name)
+      if (explicit_loc->function_name == NULL)
        {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-
-         if (ls->function_name == NULL)
-           {
-             struct symbol *s;
-
-             /* No function was specified, so add the symbol name.  */
-             gdb_assert (ls->labels.function_symbols != NULL
-                         && (VEC_length (symbolp, ls->labels.function_symbols)
-                             == 1));
-             s = VEC_index (symbolp, ls->labels.function_symbols, 0);
-             fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
-             fputc_unfiltered (':', buf);
-           }
-
-         fputs_unfiltered (ls->label_name, buf);
-         need_colon = 1;
-         state->canonical->special_display = 1;
+         struct symbol *s;
+
+         /* No function was specified, so add the symbol name.  */
+         gdb_assert (ls->labels.function_symbols != NULL
+                     && (VEC_length (symbolp, ls->labels.function_symbols)
+                         == 1));
+         s = VEC_index (symbolp, ls->labels.function_symbols, 0);
+         explicit_loc->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
        }
+    }
 
-      if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
-       {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-         fprintf_filtered (buf, "%s%d",
-                           (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
-                            : (ls->line_offset.sign
-                               == LINE_OFFSET_PLUS ? "+" : "-")),
-                           ls->line_offset.offset);
-       }
+  /* 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);
 
-      state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
-      ui_file_delete (buf);
+      set_event_location_string (canon, linespec);
+      xfree (linespec);
     }
 }
 
@@ -1886,22 +1816,23 @@ create_sals_line_offset (struct linespec_state *self,
       fullname = symtab_to_fullname (self->default_symtab);
       VEC_pop (symtab_ptr, ls->file_symtabs);
       VEC_free (symtab_ptr, ls->file_symtabs);
-      ls->file_symtabs = collect_symtabs_from_filename (fullname);
+      ls->file_symtabs = collect_symtabs_from_filename (fullname,
+                                                       self->search_pspace);
       use_default = 1;
     }
 
-  val.line = ls->line_offset.offset;
-  switch (ls->line_offset.sign)
+  val.line = ls->explicit_loc.line_offset.offset;
+  switch (ls->explicit_loc.line_offset.sign)
     {
     case LINE_OFFSET_PLUS:
-      if (ls->line_offset.offset == 0)
+      if (ls->explicit_loc.line_offset.offset == 0)
        val.line = 5;
       if (use_default)
        val.line = self->default_line + val.line;
       break;
 
     case LINE_OFFSET_MINUS:
-      if (ls->line_offset.offset == 0)
+      if (ls->explicit_loc.line_offset.offset == 0)
        val.line = 15;
       if (use_default)
        val.line = self->default_line - val.line;
@@ -1993,9 +1924,9 @@ create_sals_line_offset (struct linespec_state *self,
 
   if (values.nelts == 0)
     {
-      if (ls->source_filename)
+      if (ls->explicit_loc.source_filename)
        throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
-                    val.line, ls->source_filename);
+                    val.line, ls->explicit_loc.source_filename);
       else
        throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
                     val.line);
@@ -2004,6 +1935,24 @@ create_sals_line_offset (struct linespec_state *self,
   return values;
 }
 
+/* Convert the given ADDRESS into SaLs.  */
+
+static struct symtabs_and_lines
+convert_address_location_to_sals (struct linespec_state *self,
+                                 CORE_ADDR address)
+{
+  struct symtab_and_line sal;
+  struct symtabs_and_lines sals = {NULL, 0};
+
+  sal = find_pc_line (address, 0);
+  sal.pc = address;
+  sal.section = find_pc_overlay (address);
+  sal.explicit_pc = 1;
+  add_sal_to_sals (self, &sals, &sal, core_addr_to_string (address), 1);
+
+  return sals;
+}
+
 /* Create and return SALs from the linespec LS.  */
 
 static struct symtabs_and_lines
@@ -2011,18 +1960,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 {
   struct symtabs_and_lines sals = {NULL, 0};
 
-  if (ls->expression != NULL)
-    {
-      struct symtab_and_line sal;
-
-      /* We have an expression.  No other attribute is allowed.  */
-      sal = find_pc_line (ls->expr_pc, 0);
-      sal.pc = ls->expr_pc;
-      sal.section = find_pc_overlay (ls->expr_pc);
-      sal.explicit_pc = 1;
-      add_sal_to_sals (state, &sals, &sal, ls->expression, 1);
-    }
-  else if (ls->labels.label_symbols != NULL)
+  if (ls->labels.label_symbols != NULL)
     {
       /* We have just a bunch of functions/methods or labels.  */
       int i;
@@ -2085,13 +2023,13 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
            }
        }
     }
-  else if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+  else if (ls->explicit_loc.line_offset.sign != LINE_OFFSET_UNKNOWN)
     {
       /* Only an offset was specified.  */
        sals = create_sals_line_offset (state, ls);
 
        /* Make sure we have a filename for canonicalization.  */
-       if (ls->source_filename == NULL)
+       if (ls->explicit_loc.source_filename == NULL)
          {
            const char *fullname = symtab_to_fullname (state->default_symtab);
 
@@ -2099,7 +2037,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
               form so that displaying SOURCE_FILENAME can follow the current
               FILENAME_DISPLAY_STRING setting.  But as it is used only rarely
               it has been kept for code simplicity only in absolute form.  */
-           ls->source_filename = xstrdup (fullname);
+           ls->explicit_loc.source_filename = xstrdup (fullname);
          }
     }
   else
@@ -2116,14 +2054,94 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
   return sals;
 }
 
+/* Build RESULT from the explicit location components SOURCE_FILENAME,
+   FUNCTION_NAME, LABEL_NAME and LINE_OFFSET.  */
+
+static void
+convert_explicit_location_to_linespec (struct linespec_state *self,
+                                      linespec_p result,
+                                      const char *source_filename,
+                                      const char *function_name,
+                                      const char *label_name,
+                                      struct line_offset line_offset)
+{
+  VEC (symbolp) *symbols, *labels;
+  VEC (bound_minimal_symbol_d) *minimal_symbols;
+
+  if (source_filename != NULL)
+    {
+      TRY
+       {
+         result->file_symtabs
+           = symtabs_from_filename (source_filename, self->search_pspace);
+       }
+      CATCH (except, RETURN_MASK_ERROR)
+       {
+         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.  */
+      VEC_safe_push (symtab_ptr, result->file_symtabs, NULL);
+    }
+
+  if (function_name != NULL)
+    {
+      find_linespec_symbols (self, result->file_symtabs,
+                            function_name, &symbols,
+                            &minimal_symbols);
+
+      if (symbols == NULL && minimal_symbols == NULL)
+       symbol_not_found_error (function_name,
+                               result->explicit_loc.source_filename);
+
+      result->explicit_loc.function_name = xstrdup (function_name);
+      result->function_symbols = symbols;
+      result->minimal_symbols = minimal_symbols;
+    }
+
+  if (label_name != NULL)
+    {
+      symbols = NULL;
+      labels = find_label_symbols (self, result->function_symbols,
+                                  &symbols, label_name);
+
+      if (labels == NULL)
+       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 = symbols;
+    }
+
+  if (line_offset.sign != LINE_OFFSET_UNKNOWN)
+    result->explicit_loc.line_offset = line_offset;
+}
+
+/* Convert the explicit location EXPLICIT_LOC into SaLs.  */
+
+static struct symtabs_and_lines
+convert_explicit_location_to_sals (struct linespec_state *self,
+                                  linespec_p result,
+                                  const struct explicit_location *explicit_loc)
+{
+  convert_explicit_location_to_linespec (self, result,
+                                        explicit_loc->source_filename,
+                                        explicit_loc->function_name,
+                                        explicit_loc->label_name,
+                                        explicit_loc->line_offset);
+  return convert_linespec_to_sals (self, result);
+}
+
 /* Parse a string that specifies a linespec.
-   Pass the address of a char * variable; that variable will be
-   advanced over the characters actually parsed.
 
    The basic grammar of linespecs:
 
-   linespec -> expr_spec | var_spec | basic_spec
-   expr_spec -> '*' STRING
+   linespec -> var_spec | basic_spec
    var_spec -> '$' (STRING | NUMBER)
 
    basic_spec -> file_offset_spec | function_spec | label_spec
@@ -2167,10 +2185,10 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
    if no file is validly specified.  Callers must check that.
    Also, the line number returned may be invalid.  */
 
-/* Parse the linespec in ARGPTR.  */
+/* Parse the linespec in ARG.  */
 
 static struct symtabs_and_lines
-parse_linespec (linespec_parser *parser, const char **argptr)
+parse_linespec (linespec_parser *parser, const char *arg)
 {
   linespec_token token;
   struct symtabs_and_lines values;
@@ -2181,30 +2199,30 @@ parse_linespec (linespec_parser *parser, const char **argptr)
      IDEs to work around bugs in the previous parser by quoting
      the entire linespec, so we attempt to deal with this nicely.  */
   parser->is_quote_enclosed = 0;
-  if (!is_ada_operator (*argptr)
-      && strchr (linespec_quote_characters, **argptr) != NULL)
+  if (!is_ada_operator (arg)
+      && strchr (linespec_quote_characters, *arg) != NULL)
     {
       const char *end;
 
-      end = skip_quote_char (*argptr + 1, **argptr);
+      end = skip_quote_char (arg + 1, *arg);
       if (end != NULL && is_closing_quote_enclosed (end))
        {
-         /* Here's the special case.  Skip ARGPTR past the initial
+         /* Here's the special case.  Skip ARG past the initial
             quote.  */
-         ++(*argptr);
+         ++arg;
          parser->is_quote_enclosed = 1;
        }
     }
 
-  parser->lexer.saved_arg = *argptr;
-  parser->lexer.stream = argptr;
+  parser->lexer.saved_arg = arg;
+  parser->lexer.stream = arg;
 
   /* Initialize the default symtab and line offset.  */
   initialize_defaults (&PARSER_STATE (parser)->default_symtab,
                       &PARSER_STATE (parser)->default_line);
 
   /* Objective-C shortcut.  */
-  values = decode_objc (PARSER_STATE (parser), PARSER_RESULT (parser), argptr);
+  values = decode_objc (PARSER_STATE (parser), PARSER_RESULT (parser), arg);
   if (values.sals != NULL)
     return values;
 
@@ -2214,33 +2232,7 @@ parse_linespec (linespec_parser *parser, const char **argptr)
   token = linespec_lexer_lex_one (parser);
 
   /* It must be either LSTOKEN_STRING or LSTOKEN_NUMBER.  */
-  if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '*')
-    {
-      char *expr;
-      const char *copy;
-
-      /* User specified an expression, *EXPR.  */
-      copy = expr = copy_token_string (token);
-      cleanup = make_cleanup (xfree, expr);
-      PARSER_RESULT (parser)->expr_pc = linespec_expression_to_pc (&copy);
-      discard_cleanups (cleanup);
-      PARSER_RESULT (parser)->expression = expr;
-
-      /* This is a little hacky/tricky.  If linespec_expression_to_pc
-        did not evaluate the entire token, then we must find the
-        string COPY inside the original token buffer.  */
-      if (*copy != '\0')
-       {
-         PARSER_STREAM (parser) = strstr (parser->lexer.saved_arg, copy);
-         gdb_assert (PARSER_STREAM (parser) != NULL);
-       }
-
-      /* Consume the token.  */
-      linespec_lexer_consume_token (parser);
-
-      goto convert_to_sals;
-    }
-  else if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
+  if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
     {
       char *var;
 
@@ -2250,13 +2242,13 @@ parse_linespec (linespec_parser *parser, const char **argptr)
       /* User specified a convenience variable or history value.  */
       var = copy_token_string (token);
       cleanup = make_cleanup (xfree, var);
-      PARSER_RESULT (parser)->line_offset
+      PARSER_EXPLICIT (parser)->line_offset
        = linespec_parse_variable (PARSER_STATE (parser), var);
       do_cleanups (cleanup);
 
       /* If a line_offset wasn't found (VAR is the name of a user
         variable/function), then skip to normal symbol processing.  */
-      if (PARSER_RESULT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
+      if (PARSER_EXPLICIT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
        {
          /* Consume this token.  */
          linespec_lexer_consume_token (parser);
@@ -2283,7 +2275,8 @@ parse_linespec (linespec_parser *parser, const char **argptr)
       TRY
        {
          PARSER_RESULT (parser)->file_symtabs
-           = symtabs_from_filename (user_filename);
+           = symtabs_from_filename (user_filename,
+                                    PARSER_STATE (parser)->search_pspace);
        }
       CATCH (ex, RETURN_MASK_ERROR)
        {
@@ -2294,7 +2287,7 @@ parse_linespec (linespec_parser *parser, const char **argptr)
       if (file_exception.reason >= 0)
        {
          /* Symtabs were found for the file.  Record the filename.  */
-         PARSER_RESULT (parser)->source_filename = user_filename;
+         PARSER_EXPLICIT (parser)->source_filename = user_filename;
 
          /* Get the next token.  */
          token = linespec_lexer_consume_token (parser);
@@ -2331,7 +2324,7 @@ parse_linespec (linespec_parser *parser, const char **argptr)
 
   if (PARSER_RESULT (parser)->function_symbols == NULL
       && PARSER_RESULT (parser)->labels.label_symbols == NULL
-      && PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
+      && PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
       && PARSER_RESULT (parser)->minimal_symbols == NULL)
     {
       /* The linespec didn't parse.  Re-throw the file exception if
@@ -2340,8 +2333,8 @@ parse_linespec (linespec_parser *parser, const char **argptr)
        throw_exception (file_exception);
 
       /* Otherwise, the symbol is not found.  */
-      symbol_not_found_error (PARSER_RESULT (parser)->function_name,
-                             PARSER_RESULT (parser)->source_filename);
+      symbol_not_found_error (PARSER_EXPLICIT (parser)->function_name,
+                             PARSER_EXPLICIT (parser)->source_filename);
     }
 
  convert_to_sals:
@@ -2365,6 +2358,7 @@ parse_linespec (linespec_parser *parser, const char **argptr)
 static void
 linespec_state_constructor (struct linespec_state *self,
                            int flags, const struct language_defn *language,
+                           struct program_space *search_pspace,
                            struct symtab *default_symtab,
                            int default_line,
                            struct linespec_result *canonical)
@@ -2373,12 +2367,14 @@ linespec_state_constructor (struct linespec_state *self,
   self->language = language;
   self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
   self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
+  self->search_pspace = search_pspace;
   self->default_symtab = default_symtab;
   self->default_line = default_line;
   self->canonical = canonical;
   self->program_space = current_program_space;
   self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
                                      xfree, xcalloc, xfree);
+  self->is_linespec = 0;
 }
 
 /* Initialize a new linespec parser.  */
@@ -2386,14 +2382,17 @@ linespec_state_constructor (struct linespec_state *self,
 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)
 {
+  memset (parser, 0, sizeof (linespec_parser));
   parser->lexer.current.type = LSTOKEN_CONSUMED;
   memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
-  PARSER_RESULT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
+  PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
   linespec_state_constructor (PARSER_STATE (parser), flags, language,
+                             search_pspace,
                              default_symtab, default_line, canonical);
 }
 
@@ -2412,10 +2411,9 @@ linespec_parser_delete (void *arg)
 {
   linespec_parser *parser = (linespec_parser *) arg;
 
-  xfree ((char *) PARSER_RESULT (parser)->expression);
-  xfree ((char *) PARSER_RESULT (parser)->source_filename);
-  xfree ((char *) PARSER_RESULT (parser)->label_name);
-  xfree ((char *) PARSER_RESULT (parser)->function_name);
+  xfree (PARSER_EXPLICIT (parser)->source_filename);
+  xfree (PARSER_EXPLICIT (parser)->label_name);
+  xfree (PARSER_EXPLICIT (parser)->function_name);
 
   if (PARSER_RESULT (parser)->file_symtabs != NULL)
     VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs);
@@ -2435,10 +2433,199 @@ linespec_parser_delete (void *arg)
   linespec_state_destructor (PARSER_STATE (parser));
 }
 
+/* See description in linespec.h.  */
+
+void
+linespec_lex_to_end (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);
+  parser.lexer.saved_arg = *stringp;
+  PARSER_STREAM (&parser) = orig = *stringp;
+
+  do
+    {
+      /* Stop before any comma tokens;  we need it to keep it
+        as the next token in the string.  */
+      token = linespec_lexer_peek_token (&parser);
+      if (token.type == LSTOKEN_COMMA)
+       break;
+      token = linespec_lexer_consume_token (&parser);
+    }
+  while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
+
+  *stringp += PARSER_STREAM (&parser) - orig;
+  do_cleanups (cleanup);
+}
+
+/* See linespec.h.  */
+
+void
+linespec_complete_function (completion_tracker &tracker,
+                           const char *function,
+                           const char *source_filename)
+{
+  complete_symbol_mode mode = complete_symbol_mode::LINESPEC;
+
+  if (source_filename != NULL)
+    {
+      collect_file_symbol_completion_matches (tracker, mode,
+                                             function, function,
+                                             source_filename);
+    }
+  else
+    collect_symbol_completion_matches (tracker, mode, function, function);
+}
+
+/* Helper for linespec_complete_label.  Find labels that match
+   LABEL_NAME in the function symbols listed in the PARSER, and add
+   them to the tracker.  */
+
+static void
+complete_label (completion_tracker &tracker,
+               linespec_parser *parser,
+               const char *label_name)
+{
+  VEC (symbolp) *label_function_symbols = NULL;
+  VEC (symbolp) *labels
+    = find_label_symbols (PARSER_STATE (parser),
+                         PARSER_RESULT (parser)->function_symbols,
+                         &label_function_symbols,
+                         label_name, true);
+
+  symbol *label;
+  for (int ix = 0;
+       VEC_iterate (symbolp, labels, ix, label); ++ix)
+    {
+      char *match = xstrdup (SYMBOL_SEARCH_NAME (label));
+      tracker.add_completion (gdb::unique_xmalloc_ptr<char> (match));
+    }
+  VEC_free (symbolp, labels);
+}
+
+/* See linespec.h.  */
+
+void
+linespec_complete_label (completion_tracker &tracker,
+                        const struct language_defn *language,
+                        const char *source_filename,
+                        const char *function_name,
+                        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);
+
+  line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN };
+
+  TRY
+    {
+      convert_explicit_location_to_linespec (PARSER_STATE (&parser),
+                                            PARSER_RESULT (&parser),
+                                            source_filename,
+                                            function_name,
+                                            NULL, unknown_offset);
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      do_cleanups (cleanup);
+      return;
+    }
+  END_CATCH
+
+  complete_label (tracker, &parser, label_name);
+
+  do_cleanups (cleanup);
+}
+
+/* A helper function for decode_line_full and decode_line_1 to
+   turn LOCATION into symtabs_and_lines.  */
+
+static struct symtabs_and_lines
+event_location_to_sals (linespec_parser *parser,
+                       const struct event_location *location)
+{
+  struct symtabs_and_lines result = {NULL, 0};
+
+  switch (event_location_type (location))
+    {
+    case LINESPEC_LOCATION:
+      {
+       PARSER_STATE (parser)->is_linespec = 1;
+       TRY
+         {
+           result = parse_linespec (parser, get_linespec_location (location));
+         }
+       CATCH (except, RETURN_MASK_ERROR)
+         {
+           throw_exception (except);
+         }
+       END_CATCH
+      }
+      break;
+
+    case ADDRESS_LOCATION:
+      {
+       const char *addr_string = get_address_string_location (location);
+       CORE_ADDR addr = get_address_location (location);
+
+       if (addr_string != NULL)
+         {
+           char *expr = xstrdup (addr_string);
+           const char *const_expr = expr;
+           struct cleanup *cleanup = make_cleanup (xfree, expr);
+
+           addr = linespec_expression_to_pc (&const_expr);
+           if (PARSER_STATE (parser)->canonical != NULL)
+             PARSER_STATE (parser)->canonical->location
+               = copy_event_location (location);
+
+           do_cleanups (cleanup);
+         }
+
+       result = convert_address_location_to_sals (PARSER_STATE (parser),
+                                                  addr);
+      }
+      break;
+
+    case EXPLICIT_LOCATION:
+      {
+       const struct explicit_location *explicit_loc;
+
+       explicit_loc = get_explicit_location_const (location);
+       result = convert_explicit_location_to_sals (PARSER_STATE (parser),
+                                                   PARSER_RESULT (parser),
+                                                   explicit_loc);
+      }
+      break;
+
+    case PROBE_LOCATION:
+      /* Probes are handled by their own decoders.  */
+      gdb_assert_not_reached ("attempt to decode probe location");
+      break;
+
+    default:
+      gdb_assert_not_reached ("unhandled event location type");
+    }
+
+  return result;
+}
+
 /* See linespec.h.  */
 
 void
-decode_line_full (char **argptr, int flags,
+decode_line_full (const 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,
@@ -2449,7 +2636,6 @@ decode_line_full (char **argptr, int flags,
   VEC (const_char_ptr) *filters = NULL;
   linespec_parser parser;
   struct linespec_state *state;
-  const char *copy, *orig;
 
   gdb_assert (canonical != NULL);
   /* The filter only makes sense for 'all'.  */
@@ -2460,18 +2646,17 @@ decode_line_full (char **argptr, int flags,
              || select_mode == multiple_symbols_cancel);
   gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
 
-  linespec_parser_new (&parser, flags, current_language, default_symtab,
+  linespec_parser_new (&parser, flags, current_language,
+                      search_pspace, default_symtab,
                       default_line, canonical);
   cleanups = make_cleanup (linespec_parser_delete, &parser);
-  save_current_program_space ();
 
-  orig = copy = *argptr;
-  result = parse_linespec (&parser, &copy);
-  *argptr += copy - orig;
+  scoped_restore_current_program_space restore_pspace;
+
+  result = event_location_to_sals (&parser, location);
   state = PARSER_STATE (&parser);
 
   gdb_assert (result.nelts == 1 || canonical->pre_expanded);
-  gdb_assert (canonical->addr_string != NULL);
   canonical->pre_expanded = 1;
 
   /* Arrange for allocated canonical names to be freed.  */
@@ -2489,7 +2674,7 @@ decode_line_full (char **argptr, int flags,
 
   if (select_mode == NULL)
     {
-      if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+      if (interp_ui_out (top_level_interpreter ())->is_mi_like_p ())
        select_mode = multiple_symbols_all;
       else
        select_mode = multiple_symbols_select_mode ();
@@ -2515,23 +2700,23 @@ decode_line_full (char **argptr, int flags,
 /* See linespec.h.  */
 
 struct symtabs_and_lines
-decode_line_1 (char **argptr, int flags,
+decode_line_1 (const struct event_location *location, int flags,
+              struct program_space *search_pspace,
               struct symtab *default_symtab,
               int default_line)
 {
   struct symtabs_and_lines result;
   linespec_parser parser;
   struct cleanup *cleanups;
-  const char *copy, *orig;
 
-  linespec_parser_new (&parser, flags, current_language, default_symtab,
+  linespec_parser_new (&parser, flags, current_language,
+                      search_pspace, default_symtab,
                       default_line, NULL);
   cleanups = make_cleanup (linespec_parser_delete, &parser);
-  save_current_program_space ();
 
-  orig = copy = *argptr;
-  result = parse_linespec (&parser, &copy);
-  *argptr += copy - orig;
+  scoped_restore_current_program_space restore_pspace;
+
+  result = event_location_to_sals (&parser, location);
 
   do_cleanups (cleanups);
   return result;
@@ -2552,11 +2737,14 @@ decode_line_with_current_source (char *string, int flags)
      and get a default source symtab+line or it will recursively call us!  */
   cursal = get_current_source_symtab_and_line ();
 
-  sals = decode_line_1 (&string, flags,
+  event_location_up location = string_to_event_location (&string,
+                                                        current_language);
+  sals = decode_line_1 (location.get (), flags, NULL,
                        cursal.symtab, cursal.line);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
   return sals;
 }
 
@@ -2570,15 +2758,19 @@ decode_line_with_last_displayed (char *string, int flags)
   if (string == 0)
     error (_("Empty line specification."));
 
+  event_location_up location = string_to_event_location (&string,
+                                                        current_language);
   if (last_displayed_sal_is_valid ())
-    sals = decode_line_1 (&string, flags,
+    sals = decode_line_1 (location.get (), flags, NULL,
                          get_last_displayed_symtab (),
                          get_last_displayed_line ());
   else
-    sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
+    sals = decode_line_1 (location.get (), flags, NULL,
+                         (struct symtab *) NULL, 0);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
   return sals;
 }
 
@@ -2608,7 +2800,7 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
 /* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR,
    advancing EXP_PTR past any parsed text.  */
 
-static CORE_ADDR
+CORE_ADDR
 linespec_expression_to_pc (const char **exp_ptr)
 {
   if (current_program_space->executing_startup)
@@ -2631,7 +2823,7 @@ linespec_expression_to_pc (const char **exp_ptr)
    the existing C++ code to let the user choose one.  */
 
 static struct symtabs_and_lines
-decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
+decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
 {
   struct collect_info info;
   VEC (const_char_ptr) *symbol_names = NULL;
@@ -2649,7 +2841,7 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
   values.nelts = 0;
   values.sals = NULL;
 
-  new_argptr = find_imps (*argptr, &symbol_names); 
+  new_argptr = find_imps (arg, &symbol_names);
   if (VEC_empty (const_char_ptr, symbol_names))
     {
       do_cleanups (cleanup);
@@ -2663,76 +2855,109 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
     {
       char *saved_arg;
 
-      saved_arg = alloca (new_argptr - *argptr + 1);
-      memcpy (saved_arg, *argptr, new_argptr - *argptr);
-      saved_arg[new_argptr - *argptr] = '\0';
+      saved_arg = (char *) alloca (new_argptr - arg + 1);
+      memcpy (saved_arg, arg, new_argptr - arg);
+      saved_arg[new_argptr - arg] = '\0';
 
-      ls->function_name = xstrdup (saved_arg);
+      ls->explicit_loc.function_name = xstrdup (saved_arg);
       ls->function_symbols = info.result.symbols;
       ls->minimal_symbols = info.result.minimal_symbols;
       values = convert_linespec_to_sals (self, ls);
 
       if (self->canonical)
        {
+         char *str;
+
          self->canonical->pre_expanded = 1;
-         if (ls->source_filename)
-           self->canonical->addr_string
-             = xstrprintf ("%s:%s", ls->source_filename, saved_arg);
+
+         if (ls->explicit_loc.source_filename)
+           {
+             str = xstrprintf ("%s:%s",
+                               ls->explicit_loc.source_filename, saved_arg);
+           }
          else
-           self->canonical->addr_string = xstrdup (saved_arg);
+           str = xstrdup (saved_arg);
+
+         make_cleanup (xfree, str);
+         self->canonical->location = new_linespec_location (&str);
        }
     }
 
-  *argptr = new_argptr;
-
   do_cleanups (cleanup);
 
   return values;
 }
 
-/* An instance of this type is used when collecting prefix symbols for
-   decode_compound.  */
+namespace {
 
-struct decode_compound_collector
+/* A function object that serves as symbol_found_callback_ftype
+   callback for iterate_over_symbols.  This is used by
+   lookup_prefix_sym to collect type symbols.  */
+class decode_compound_collector
 {
-  /* The result vector.  */
-  VEC (symbolp) *symbols;
+public:
+  decode_compound_collector ()
+    : m_symbols (NULL)
+  {
+    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);
+  }
 
+  /* Releases ownership of the collected symbols and returns them.  */
+  VEC (symbolp) *release_symbols ()
+  {
+    VEC (symbolp) *res = m_symbols;
+    m_symbols = NULL;
+    return res;
+  }
+
+  /* Callable as a symbol_found_callback_ftype callback.  */
+  bool operator () (symbol *sym);
+
+private:
   /* A hash table of all symbols we found.  We use this to avoid
      adding any symbol more than once.  */
-  htab_t unique_syms;
-};
+  htab_t m_unique_syms;
 
-/* A callback for iterate_over_symbols that is used by
-   lookup_prefix_sym to collect type symbols.  */
+  /* The result vector.  */
+  VEC (symbolp) *m_symbols;
+};
 
-static int
-collect_one_symbol (struct symbol *sym, void *d)
+bool
+decode_compound_collector::operator () (symbol *sym)
 {
-  struct decode_compound_collector *collector = d;
   void **slot;
   struct type *t;
 
   if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
-    return 1; /* Continue iterating.  */
+    return true; /* Continue iterating.  */
 
   t = SYMBOL_TYPE (sym);
-  CHECK_TYPEDEF (t);
+  t = check_typedef (t);
   if (TYPE_CODE (t) != TYPE_CODE_STRUCT
       && TYPE_CODE (t) != TYPE_CODE_UNION
       && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
-    return 1; /* Continue iterating.  */
+    return true; /* Continue iterating.  */
 
-  slot = htab_find_slot (collector->unique_syms, sym, INSERT);
+  slot = htab_find_slot (m_unique_syms, sym, INSERT);
   if (!*slot)
     {
       *slot = sym;
-      VEC_safe_push (symbolp, collector->symbols, sym);
+      VEC_safe_push (symbolp, m_symbols, sym);
     }
 
-  return 1; /* Continue iterating.  */
+  return true; /* Continue iterating.  */
 }
 
+} // namespace
+
 /* Return any symbols corresponding to CLASS_NAME in FILE_SYMTABS.  */
 
 static VEC (symbolp) *
@@ -2741,28 +2966,16 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs,
 {
   int ix;
   struct symtab *elt;
-  struct decode_compound_collector collector;
-  struct cleanup *outer;
-  struct cleanup *cleanup;
-
-  collector.symbols = NULL;
-  outer = make_cleanup (VEC_cleanup (symbolp), &collector.symbols);
-
-  collector.unique_syms = htab_create_alloc (1, htab_hash_pointer,
-                                            htab_eq_pointer, NULL,
-                                            xcalloc, xfree);
-  cleanup = make_cleanup_htab_delete (collector.unique_syms);
+  decode_compound_collector collector;
 
   for (ix = 0; VEC_iterate (symtab_ptr, file_symtabs, ix, elt); ++ix)
     {
       if (elt == NULL)
        {
          iterate_over_all_matching_symtabs (state, class_name, STRUCT_DOMAIN,
-                                            collect_one_symbol, &collector,
-                                            NULL, 0);
+                                            NULL, false, collector);
          iterate_over_all_matching_symtabs (state, class_name, VAR_DOMAIN,
-                                            collect_one_symbol, &collector,
-                                            NULL, 0);
+                                            NULL, false, collector);
        }
       else
        {
@@ -2770,16 +2983,12 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs,
             been filtered out earlier.  */
          gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
          set_current_program_space (SYMTAB_PSPACE (elt));
-         iterate_over_file_blocks (elt, class_name, STRUCT_DOMAIN,
-                                   collect_one_symbol, &collector);
-         iterate_over_file_blocks (elt, class_name, VAR_DOMAIN,
-                                   collect_one_symbol, &collector);
+         iterate_over_file_blocks (elt, class_name, STRUCT_DOMAIN, collector);
+         iterate_over_file_blocks (elt, class_name, VAR_DOMAIN, collector);
        }
     }
 
-  do_cleanups (cleanup);
-  discard_cleanups (outer);
-  return collector.symbols;
+  return collector.release_symbols ();
 }
 
 /* A qsort comparison function for symbols.  The resulting order does
@@ -2789,8 +2998,8 @@ lookup_prefix_sym (struct linespec_state *state, VEC (symtab_ptr) *file_symtabs,
 static int
 compare_symbols (const void *a, const void *b)
 {
-  struct symbol * const *sa = a;
-  struct symbol * const *sb = b;
+  struct symbol * const *sa = (struct symbol * const*) a;
+  struct symbol * const *sb = (struct symbol * const*) b;
   uintptr_t uia, uib;
 
   uia = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sa));
@@ -2817,8 +3026,10 @@ compare_symbols (const void *a, const void *b)
 static int
 compare_msymbols (const void *a, const void *b)
 {
-  const struct bound_minimal_symbol *sa = a;
-  const struct bound_minimal_symbol *sb = b;
+  const struct bound_minimal_symbol *sa
+    = (const struct bound_minimal_symbol *) a;
+  const struct bound_minimal_symbol *sb
+    = (const struct bound_minimal_symbol *) b;
   uintptr_t uia, uib;
 
   uia = (uintptr_t) sa->objfile->pspace;
@@ -2983,71 +3194,106 @@ find_method (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs,
 
 \f
 
-/* This object is used when collecting all matching symtabs.  */
+namespace {
+
+/* This function object is a callback for iterate_over_symtabs, used
+   when collecting all matching symtabs.  */
 
-struct symtab_collector
+class symtab_collector
 {
+public:
+  symtab_collector ()
+  {
+    m_symtabs = NULL;
+    m_symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
+                                 NULL);
+  }
+
+  ~symtab_collector ()
+  {
+    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.  */
+  VEC (symtab_ptr) *release_symtabs ()
+  {
+    VEC (symtab_ptr) *res = m_symtabs;
+    m_symtabs = NULL;
+    return res;
+  }
+
+private:
   /* The result vector of symtabs.  */
-  VEC (symtab_ptr) *symtabs;
+  VEC (symtab_ptr) *m_symtabs;
 
   /* This is used to ensure the symtabs are unique.  */
-  htab_t symtab_table;
+  htab_t m_symtab_table;
 };
 
-/* Callback for iterate_over_symtabs.  */
-
-static int
-add_symtabs_to_list (struct symtab *symtab, void *d)
+bool
+symtab_collector::operator () (struct symtab *symtab)
 {
-  struct symtab_collector *data = d;
   void **slot;
 
-  slot = htab_find_slot (data->symtab_table, symtab, INSERT);
+  slot = htab_find_slot (m_symtab_table, symtab, INSERT);
   if (!*slot)
     {
       *slot = symtab;
-      VEC_safe_push (symtab_ptr, data->symtabs, symtab);
+      VEC_safe_push (symtab_ptr, m_symtabs, symtab);
     }
 
-  return 0;
+  return false;
 }
 
-/* Given a file name, return a VEC of all matching symtabs.  */
+} // namespace
+
+/* Given a file name, return a VEC of all matching symtabs.  If
+   SEARCH_PSPACE is not NULL, the search is restricted to just that
+   program space.  */
 
 static VEC (symtab_ptr) *
-collect_symtabs_from_filename (const char *file)
+collect_symtabs_from_filename (const char *file,
+                              struct program_space *search_pspace)
 {
-  struct symtab_collector collector;
-  struct cleanup *cleanups;
-  struct program_space *pspace;
-
-  collector.symtabs = NULL;
-  collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
-                                       NULL);
-  cleanups = make_cleanup_htab_delete (collector.symtab_table);
+  symtab_collector collector;
 
   /* Find that file's data.  */
-  ALL_PSPACES (pspace)
-  {
-    if (pspace->executing_startup)
-      continue;
+  if (search_pspace == NULL)
+    {
+      struct program_space *pspace;
 
-    set_current_program_space (pspace);
-    iterate_over_symtabs (file, add_symtabs_to_list, &collector);
-  }
+      ALL_PSPACES (pspace)
+        {
+         if (pspace->executing_startup)
+           continue;
 
-  do_cleanups (cleanups);
-  return collector.symtabs;
+         set_current_program_space (pspace);
+         iterate_over_symtabs (file, collector);
+       }
+    }
+  else
+    {
+      set_current_program_space (search_pspace);
+      iterate_over_symtabs (file, collector);
+    }
+
+  return collector.release_symtabs ();
 }
 
-/* Return all the symtabs associated to the FILENAME.  */
+/* Return all the symtabs associated to the FILENAME.  If SEARCH_PSPACE is
+   not NULL, the search is restricted to just that program space.  */
 
 static VEC (symtab_ptr) *
-symtabs_from_filename (const char *filename)
+symtabs_from_filename (const char *filename,
+                      struct program_space *search_pspace)
 {
   VEC (symtab_ptr) *result;
   
-  result = collect_symtabs_from_filename (filename);
+  result = collect_symtabs_from_filename (filename, search_pspace);
 
   if (VEC_empty (symtab_ptr, result))
     {
@@ -3055,7 +3301,7 @@ symtabs_from_filename (const char *filename)
        throw_error (NOT_FOUND_ERROR,
                     _("No symbol table is loaded.  "
                       "Use the \"file\" command."));
-      throw_error (NOT_FOUND_ERROR, _("No source file named %s."), filename);
+      source_file_not_found_error (filename);
     }
 
   return result;
@@ -3084,9 +3330,10 @@ find_function_symbols (struct linespec_state *state,
   /* Try NAME as an Objective-C selector.  */
   find_imps (name, &symbol_names);
   if (!VEC_empty (const_char_ptr, symbol_names))
-    add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
+    add_all_symbol_names_from_pspace (&info, state->search_pspace,
+                                     symbol_names);
   else
-    add_matching_symbols_to_info (name, &info, NULL);
+    add_matching_symbols_to_info (name, &info, state->search_pspace);
 
   do_cleanups (cleanup);
 
@@ -3117,27 +3364,28 @@ find_linespec_symbols (struct linespec_state *state,
                       VEC (symbolp) **symbols,
                       VEC (bound_minimal_symbol_d) **minsyms)
 {
-  struct cleanup *cleanup;
-  char *canon;
+  demangle_result_storage demangle_storage;
+  std::string ada_lookup_storage;
   const char *lookup_name;
 
-  cleanup = demangle_for_lookup (name, state->language->la_language,
-                                &lookup_name);
   if (state->language->la_language == language_ada)
     {
       /* In Ada, the symbol lookups are performed using the encoded
          name rather than the demangled name.  */
-      lookup_name = ada_name_for_lookup (name);
-      make_cleanup (xfree, (void *) lookup_name);
+      ada_lookup_storage = ada_name_for_lookup (name);
+      lookup_name = ada_lookup_storage.c_str ();
     }
-
-  canon = cp_canonicalize_string_no_typedefs (lookup_name);
-  if (canon != NULL)
+  else
     {
-      lookup_name = canon;
-      make_cleanup (xfree, canon);
+      lookup_name = demangle_for_lookup (name,
+                                        state->language->la_language,
+                                        demangle_storage);
     }
 
+  std::string canon = cp_canonicalize_string_no_typedefs (lookup_name);
+  if (!canon.empty ())
+    lookup_name = canon.c_str ();
+
   /* It's important to not call expand_symtabs_matching unnecessarily
      as it can really slow things down (by unnecessarily expanding
      potentially 1000s of symtabs, which when debugging some apps can
@@ -3156,7 +3404,7 @@ find_linespec_symbols (struct linespec_state *state,
   if (VEC_empty (symbolp, *symbols)
       && VEC_empty (bound_minimal_symbol_d, *minsyms))
     {
-      char *klass, *method;
+      std::string klass, method;
       const char *last, *p, *scope_op;
       VEC (symbolp) *classes;
 
@@ -3164,12 +3412,6 @@ find_linespec_symbols (struct linespec_state *state,
         name into namespaces${SCOPE_OPERATOR}class_name and method_name.  */
       scope_op = "::";
       p = find_toplevel_string (lookup_name, scope_op);
-      if (p == NULL)
-       {
-         /* No C++ scope operator.  Try Java.  */
-         scope_op = ".";
-         p = find_toplevel_string (lookup_name, scope_op);
-       }
 
       last = NULL;
       while (p != NULL)
@@ -3182,35 +3424,29 @@ find_linespec_symbols (struct linespec_state *state,
         we already attempted to lookup the entire name as a symbol
         and failed.  */
       if (last == NULL)
-       {
-         do_cleanups (cleanup);
-         return;
-       }
+       return;
 
       /* LOOKUP_NAME points to the class name.
         LAST points to the method name.  */
-      klass = xmalloc ((last - lookup_name + 1) * sizeof (char));
-      make_cleanup (xfree, klass);
-      strncpy (klass, lookup_name, last - lookup_name);
-      klass[last - lookup_name] = '\0';
+      klass = std::string (lookup_name, last - lookup_name);
 
       /* Skip past the scope operator.  */
       last += strlen (scope_op);
-      method = xmalloc ((strlen (last) + 1) * sizeof (char));
-      make_cleanup (xfree, method);
-      strcpy (method, last);
+      method = last;
 
       /* Find a list of classes named KLASS.  */
-      classes = lookup_prefix_sym (state, file_symtabs, klass);
-      make_cleanup (VEC_cleanup (symbolp), &classes);
+      classes = lookup_prefix_sym (state, file_symtabs, klass.c_str ());
+      struct cleanup *old_chain
+       = make_cleanup (VEC_cleanup (symbolp), &classes);
 
       if (!VEC_empty (symbolp, classes))
        {
          /* Now locate a list of suitable methods named METHOD.  */
          TRY
            {
-             find_method (state, file_symtabs, klass, method, classes,
-                          symbols, minsyms);
+             find_method (state, file_symtabs,
+                          klass.c_str (), method.c_str (),
+                          classes, symbols, minsyms);
            }
 
          /* If successful, we're done.  If NOT_FOUND_ERROR
@@ -3222,18 +3458,68 @@ find_linespec_symbols (struct linespec_state *state,
            }
          END_CATCH
        }
+
+      do_cleanups (old_chain);
     }
+}
 
-  do_cleanups (cleanup);
+/* Helper for find_label_symbols.  Find all labels that match name
+   NAME in BLOCK.  Return all labels that match 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 a label named
+   exactly NAME match.  */
+
+static void
+find_label_symbols_in_block (const struct block *block,
+                            const char *name, struct symbol *fn_sym,
+                            bool completion_mode,
+                            VEC (symbolp) **result,
+                            VEC (symbolp) **label_funcs_ret)
+{
+  if (completion_mode)
+    {
+      struct block_iterator iter;
+      struct symbol *sym;
+      size_t name_len = strlen (name);
+
+      int (*cmp) (const char *, const char *, size_t);
+      cmp = case_sensitivity == case_sensitive_on ? strncmp : strncasecmp;
+
+      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)
+           {
+             VEC_safe_push (symbolp, *result, sym);
+             VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
+           }
+       }
+    }
+  else
+    {
+      struct symbol *sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol;
+
+      if (sym != NULL)
+       {
+         VEC_safe_push (symbolp, *result, sym);
+         VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
+       }
+    }
 }
 
-/* Return all labels named NAME in FUNCTION_SYMBOLS.  Return the
-   actual function symbol in which the label was found in LABEL_FUNC_RET.  */
+/* 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 VEC (symbolp) *
 find_label_symbols (struct linespec_state *self,
                    VEC (symbolp) *function_symbols,
-                   VEC (symbolp) **label_funcs_ret, const char *name)
+                   VEC (symbolp) **label_funcs_ret, const char *name,
+                   bool completion_mode)
 {
   int ix;
   const struct block *block;
@@ -3254,13 +3540,8 @@ find_label_symbols (struct linespec_state *self,
        return NULL;
       fn_sym = BLOCK_FUNCTION (block);
 
-      sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
-
-      if (sym != NULL)
-       {
-         VEC_safe_push (symbolp, result, sym);
-         VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
-       }
+      find_label_symbols_in_block (block, name, fn_sym, completion_mode,
+                                  &result, label_funcs_ret);
     }
   else
     {
@@ -3269,13 +3550,9 @@ find_label_symbols (struct linespec_state *self,
        {
          set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym)));
          block = SYMBOL_BLOCK_VALUE (fn_sym);
-         sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
 
-         if (sym != NULL)
-           {
-             VEC_safe_push (symbolp, result, sym);
-             VEC_safe_push (symbolp, *label_funcs_ret, fn_sym);
-           }
+         find_label_symbols_in_block (block, name, fn_sym, completion_mode,
+                                      &result, label_funcs_ret);
        }
     }
 
@@ -3332,9 +3609,7 @@ decode_digits_ordinary (struct linespec_state *self,
 
   for (ix = 0; VEC_iterate (symtab_ptr, ls->file_symtabs, ix, elt); ++ix)
     {
-      int i;
-      VEC (CORE_ADDR) *pcs;
-      CORE_ADDR pc;
+      std::vector<CORE_ADDR> pcs;
 
       /* The logic above should ensure this.  */
       gdb_assert (elt != NULL);
@@ -3342,7 +3617,7 @@ decode_digits_ordinary (struct linespec_state *self,
       set_current_program_space (SYMTAB_PSPACE (elt));
 
       pcs = find_pcs_for_symtab_line (elt, line, best_entry);
-      for (i = 0; VEC_iterate (CORE_ADDR, pcs, i, pc); ++i)
+      for (CORE_ADDR pc : pcs)
        {
          struct symtab_and_line sal;
 
@@ -3353,8 +3628,6 @@ decode_digits_ordinary (struct linespec_state *self,
          sal.pc = pc;
          add_sal_to_sals_basic (sals, &sal);
        }
-
-      VEC_free (CORE_ADDR, pcs);
     }
 }
 
@@ -3417,22 +3690,10 @@ linespec_parse_variable (struct linespec_state *self, const char *variable)
 }
 \f
 
-/* A callback used to possibly add a symbol to the results.  */
-
-static int
-collect_symbols (struct symbol *sym, void *data)
-{
-  struct collect_info *info = data;
-
-  /* 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 || info->state->list_mode)
-    VEC_safe_push (symbolp, info->result.symbols, sym);
-  return 1; /* Continue iterating.  */
-}
-
 /* We've found a minimal symbol MSYMBOL in OBJFILE to associate with our
-   linespec; return the SAL in RESULT.  */
+   linespec; return the SAL in RESULT.  This function should return SALs
+   matching those from find_function_start_sal, otherwise false
+   multiple-locations breakpoints could be placed.  */
 
 static void
 minsym_found (struct linespec_state *self, struct objfile *objfile,
@@ -3454,7 +3715,25 @@ minsym_found (struct linespec_state *self, struct objfile *objfile,
     sal = find_pc_sect_line (pc, NULL, 0);
 
   if (self->funfirstline)
-    skip_prologue_sal (&sal);
+    {
+      if (sal.symtab != NULL
+         && (COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (sal.symtab))
+             || SYMTAB_LANGUAGE (sal.symtab) == language_asm))
+       {
+         /* If gdbarch_convert_from_func_ptr_addr does not apply then
+            sal.SECTION, sal.LINE&co. will stay correct from above.
+            If gdbarch_convert_from_func_ptr_addr applies then
+            sal.SECTION is cleared from above and sal.LINE&co. will
+            stay correct from the last find_pc_sect_line above.  */
+         sal.pc = MSYMBOL_VALUE_ADDRESS (objfile, msymbol);
+         sal.pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc,
+                                                      &current_target);
+         if (gdbarch_skip_entrypoint_p (gdbarch))
+           sal.pc = gdbarch_skip_entrypoint (gdbarch, sal.pc);
+       }
+      else
+       skip_prologue_sal (&sal);
+    }
 
   if (maybe_add_address (self->addr_set, objfile->pspace, sal.pc))
     add_sal_to_sals (self, result, &sal, MSYMBOL_NATURAL_NAME (msymbol), 0);
@@ -3510,8 +3789,8 @@ classify_mtype (enum minimal_symbol_type t)
 static int
 compare_msyms (const void *a, const void *b)
 {
-  const bound_minimal_symbol_d *moa = a;
-  const bound_minimal_symbol_d *mob = b;
+  const bound_minimal_symbol_d *moa = (const bound_minimal_symbol_d *) a;
+  const bound_minimal_symbol_d *mob = (const bound_minimal_symbol_d *) b;
   enum minimal_symbol_type ta = MSYMBOL_TYPE (moa->minsym);
   enum minimal_symbol_type tb = MSYMBOL_TYPE (mob->minsym);
 
@@ -3524,7 +3803,7 @@ compare_msyms (const void *a, const void *b)
 static void
 add_minsym (struct minimal_symbol *minsym, void *d)
 {
-  struct collect_minsyms *info = d;
+  struct collect_minsyms *info = (struct collect_minsyms *) d;
   bound_minimal_symbol_d mo;
 
   mo.minsym = minsym;
@@ -3678,8 +3957,8 @@ add_matching_symbols_to_info (const char *name,
       if (elt == NULL)
        {
          iterate_over_all_matching_symtabs (info->state, name, VAR_DOMAIN,
-                                            collect_symbols, info,
-                                            pspace, 1);
+                                            pspace, true, [&] (symbol *sym)
+           { return info->add_symbol (sym); });
          search_minsyms_for_name (info, name, pspace, NULL);
        }
       else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
@@ -3690,8 +3969,8 @@ add_matching_symbols_to_info (const char *name,
             been filtered out earlier.  */
          gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
          set_current_program_space (SYMTAB_PSPACE (elt));
-         iterate_over_file_blocks (elt, name, VAR_DOMAIN,
-                                   collect_symbols, info);
+         iterate_over_file_blocks (elt, name, VAR_DOMAIN, [&] (symbol *sym)
+           { return info->add_symbol (sym); });
 
          /* If no new symbols were found in this iteration and this symtab
             is in assembler, we might actually be looking for a label for
@@ -3748,43 +4027,23 @@ symbol_to_sal (struct symtab_and_line *result,
   return 0;
 }
 
-/* See the comment in linespec.h.  */
-
-void
-init_linespec_result (struct linespec_result *lr)
-{
-  memset (lr, 0, sizeof (*lr));
-}
-
-/* See the comment in linespec.h.  */
-
-void
-destroy_linespec_result (struct linespec_result *ls)
+linespec_result::~linespec_result ()
 {
   int i;
   struct linespec_sals *lsal;
 
-  xfree (ls->addr_string);
-  for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
+  for (i = 0; VEC_iterate (linespec_sals, sals, i, lsal); ++i)
     {
       xfree (lsal->canonical);
       xfree (lsal->sals.sals);
     }
-  VEC_free (linespec_sals, ls->sals);
+  VEC_free (linespec_sals, sals);
 }
 
-/* Cleanup function for a linespec_result.  */
+/* Return the quote characters permitted by the linespec parser.  */
 
-static void
-cleanup_linespec_result (void *a)
-{
-  destroy_linespec_result (a);
-}
-
-/* See the comment in linespec.h.  */
-
-struct cleanup *
-make_cleanup_destroy_linespec_result (struct linespec_result *ls)
+const char *
+get_gdb_linespec_parser_quote_characters (void)
 {
-  return make_cleanup (cleanup_linespec_result, ls);
+  return linespec_quote_characters;
 }
This page took 0.053831 seconds and 4 git commands to generate.