[PUSHED] Locations API / Explicit Locations

Message ID 1439342670-13334-1-git-send-email-keiths@redhat.com
State New, archived
Headers

Commit Message

Keith Seitz Aug. 12, 2015, 1:24 a.m. UTC
  With a very, very big "Thank You!" to Doug Evans for his help and patience,
I've finally pushed this series.

Keith

commit 5f700d83f7f3ea422d789c51a25f04818bf788d7
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: rename "address string"/"addr_string" to "location"
    
    This patch renames all occurrances of "addr_string" and "address
    string" in the breakpoint/linespec APIs.  This will emphasize the
    change from address strings used in setting breakpoints (et al) to the
    new locations-based API introduced in subsequent patches.
    
    gdb/ChangeLog:
    
    	* breakpoint.h (struct breakpoint_ops) <create_sals_from_address>:
    	Renamed to create_sals_from_location.
    	<decode_linespec>: Renamed to decode_location.
    	Update all callers.
    	* breakpoint.c (create_sals_from_address_default): Renamed to ...
    	(create_sals_from_location_default): ... this.
    	(addr_string_to_sals): Renamed to ...
    	(location_to_sals): ... this.
    	(decode_linespec_default): Renamed to ...
    	(decode_location_default): ... this.
    	(base_breakpoint_create_sals_from_address): Renamed to ...
    	(base_breakpoint_create_sals_from_location): ... this.
    	(bkpt_create_sals_from_address): Renamed to ...
    	(bkpt_create_sals_from_location): ... this.
    	(bkpt_decode_linespec): Renamed to ...
    	(bkpt_decode_location): ... this.
    	(bkpt_probe_create_sals_from_address): Renamed to ...
    	(bkpt_probe_create_sals_from_location): ... this.
    	(tracepoint_create_sals_from_address): Renamed to ...
    	(tracepoint_create_sals_from_location): ... this.
    	(tracepoint_decode_linespec): Renamed to ...
    	(tracepoint_decode_location): ... this.
    	(tracepoint_probe_create_sals_from_address): Renamed to ...
    	(tracepoint_probe_create_sals_from_location): ... this.
    	(tracepoint_probe_decode_linespec): Renamed to ...
    	(tracepoint_probe_decode_location): ... this.
    	(strace_marker_create_sals_from_address): Renamed to ...
    	(strace_marker_create_sals_from_location): ... this.
    	(decode_linespec_default): Renamed to ...
    	(decode_location_default): ... this.
  

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a104670..487f86c 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,36 @@ 
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+	* breakpoint.h (struct breakpoint_ops) <create_sals_from_address>:
+	Renamed to create_sals_from_location.
+	<decode_linespec>: Renamed to decode_location.
+	Update all callers.
+	* breakpoint.c (create_sals_from_address_default): Renamed to ...
+	(create_sals_from_location_default): ... this.
+	(addr_string_to_sals): Renamed to ...
+	(location_to_sals): ... this.
+	(decode_linespec_default): Renamed to ...
+	(decode_location_default): ... this.
+	(base_breakpoint_create_sals_from_address): Renamed to ...
+	(base_breakpoint_create_sals_from_location): ... this.
+	(bkpt_create_sals_from_address): Renamed to ...
+	(bkpt_create_sals_from_location): ... this.
+	(bkpt_decode_linespec): Renamed to ...
+	(bkpt_decode_location): ... this.
+	(bkpt_probe_create_sals_from_address): Renamed to ...
+	(bkpt_probe_create_sals_from_location): ... this.
+	(tracepoint_create_sals_from_address): Renamed to ...
+	(tracepoint_create_sals_from_location): ... this.
+	(tracepoint_decode_linespec): Renamed to ...
+	(tracepoint_decode_location): ... this.
+	(tracepoint_probe_create_sals_from_address): Renamed to ...
+	(tracepoint_probe_create_sals_from_location): ... this.
+	(tracepoint_probe_decode_linespec): Renamed to ...
+	(tracepoint_probe_decode_location): ... this.
+	(strace_marker_create_sals_from_address): Renamed to ...
+	(strace_marker_create_sals_from_location): ... this.
+	(decode_linespec_default): Renamed to ...
+	(decode_location_default): ... this.
+
 2015-08-10  Doug Evans  <dje@google.com>
 	    Keith Seitz  <keiths@redhat.com>
 
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index f5616c8..927176f 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -228,7 +228,7 @@  re_set_exception_catchpoint (struct breakpoint *self)
 	{
 	  char *spec = ASTRDUP (exception_functions[kind].function);
 
-	  self->ops->decode_linespec (self, &spec, &sals);
+	  self->ops->decode_location (self, &spec, &sals);
 	}
       CATCH (ex, RETURN_MASK_ERROR)
 	{
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 91a53b9..1d1cb03 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -108,10 +108,10 @@  static int breakpoint_re_set_one (void *);
 
 static void breakpoint_re_set_default (struct breakpoint *);
 
-static void create_sals_from_address_default (char **,
-					      struct linespec_result *,
-					      enum bptype, char *,
-					      char **);
+static void create_sals_from_location_default (char **,
+					       struct linespec_result *,
+					       enum bptype, char *,
+					       char **);
 
 static void create_breakpoints_sal_default (struct gdbarch *,
 					    struct linespec_result *,
@@ -121,7 +121,7 @@  static void create_breakpoints_sal_default (struct gdbarch *,
 					    const struct breakpoint_ops *,
 					    int, int, int, unsigned);
 
-static void decode_linespec_default (struct breakpoint *, char **,
+static void decode_location_default (struct breakpoint *, char **,
 				     struct symtabs_and_lines *);
 
 static void clear_command (char *, int);
@@ -9609,8 +9609,8 @@  create_breakpoint (struct gdbarch *gdbarch,
 
   TRY
     {
-      ops->create_sals_from_address (&arg, &canonical, type_wanted,
-				     addr_start, &copy_arg);
+      ops->create_sals_from_location (&arg, &canonical, type_wanted,
+				      addr_start, &copy_arg);
     }
   CATCH (e, RETURN_MASK_ERROR)
     {
@@ -12711,11 +12711,11 @@  base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
 }
 
 static void
-base_breakpoint_create_sals_from_address (char **arg,
-					  struct linespec_result *canonical,
-					  enum bptype type_wanted,
-					  char *addr_start,
-					  char **copy_arg)
+base_breakpoint_create_sals_from_location (char **arg,
+					   struct linespec_result *canonical,
+					   enum bptype type_wanted,
+					   char *addr_start,
+					   char **copy_arg)
 {
   internal_error_pure_virtual_called ();
 }
@@ -12737,7 +12737,7 @@  base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-base_breakpoint_decode_linespec (struct breakpoint *b, char **s,
+base_breakpoint_decode_location (struct breakpoint *b, char **s,
 				 struct symtabs_and_lines *sals)
 {
   internal_error_pure_virtual_called ();
@@ -12775,9 +12775,9 @@  struct breakpoint_ops base_breakpoint_ops =
   base_breakpoint_print_one_detail,
   base_breakpoint_print_mention,
   base_breakpoint_print_recreate,
-  base_breakpoint_create_sals_from_address,
+  base_breakpoint_create_sals_from_location,
   base_breakpoint_create_breakpoints_sal,
-  base_breakpoint_decode_linespec,
+  base_breakpoint_decode_location,
   base_breakpoint_explains_signal,
   base_breakpoint_after_condition_true,
 };
@@ -12947,12 +12947,12 @@  bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
 }
 
 static void
-bkpt_create_sals_from_address (char **arg,
+bkpt_create_sals_from_location (char **arg,
 			       struct linespec_result *canonical,
 			       enum bptype type_wanted,
 			       char *addr_start, char **copy_arg)
 {
-  create_sals_from_address_default (arg, canonical, type_wanted,
+  create_sals_from_location_default (arg, canonical, type_wanted,
 				    addr_start, copy_arg);
 }
 
@@ -12978,10 +12978,10 @@  bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-bkpt_decode_linespec (struct breakpoint *b, char **s,
+bkpt_decode_location (struct breakpoint *b, char **s,
 		      struct symtabs_and_lines *sals)
 {
-  decode_linespec_default (b, s, sals);
+  decode_location_default (b, s, sals);
 }
 
 /* Virtual table for internal breakpoints.  */
@@ -13181,10 +13181,10 @@  bkpt_probe_remove_location (struct bp_location *bl)
 }
 
 static void
-bkpt_probe_create_sals_from_address (char **arg,
-				     struct linespec_result *canonical,
-				     enum bptype type_wanted,
-				     char *addr_start, char **copy_arg)
+bkpt_probe_create_sals_from_location (char **arg,
+				      struct linespec_result *canonical,
+				      enum bptype type_wanted,
+				      char *addr_start, char **copy_arg)
 {
   struct linespec_sals lsal;
 
@@ -13197,7 +13197,7 @@  bkpt_probe_create_sals_from_address (char **arg,
 }
 
 static void
-bkpt_probe_decode_linespec (struct breakpoint *b, char **s,
+bkpt_probe_decode_location (struct breakpoint *b, char **s,
 			    struct symtabs_and_lines *sals)
 {
   *sals = parse_probes (s, NULL);
@@ -13290,12 +13290,12 @@  tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
 }
 
 static void
-tracepoint_create_sals_from_address (char **arg,
+tracepoint_create_sals_from_location (char **arg,
 				     struct linespec_result *canonical,
 				     enum bptype type_wanted,
 				     char *addr_start, char **copy_arg)
 {
-  create_sals_from_address_default (arg, canonical, type_wanted,
+  create_sals_from_location_default (arg, canonical, type_wanted,
 				    addr_start, copy_arg);
 }
 
@@ -13321,10 +13321,10 @@  tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-tracepoint_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_decode_location (struct breakpoint *b, char **s,
 			    struct symtabs_and_lines *sals)
 {
-  decode_linespec_default (b, s, sals);
+  decode_location_default (b, s, sals);
 }
 
 struct breakpoint_ops tracepoint_breakpoint_ops;
@@ -13333,22 +13333,22 @@  struct breakpoint_ops tracepoint_breakpoint_ops;
    static probe.  */
 
 static void
-tracepoint_probe_create_sals_from_address (char **arg,
-					   struct linespec_result *canonical,
-					   enum bptype type_wanted,
-					   char *addr_start, char **copy_arg)
+tracepoint_probe_create_sals_from_location (char **arg,
+					    struct linespec_result *canonical,
+					    enum bptype type_wanted,
+					    char *addr_start, char **copy_arg)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_create_sals_from_address (arg, canonical, type_wanted,
-				       addr_start, copy_arg);
+  bkpt_probe_create_sals_from_location (arg, canonical, type_wanted,
+					addr_start, copy_arg);
 }
 
 static void
-tracepoint_probe_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_probe_decode_location (struct breakpoint *b, char **s,
 				  struct symtabs_and_lines *sals)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_decode_linespec (b, s, sals);
+  bkpt_probe_decode_location (b, s, sals);
 }
 
 static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
@@ -13434,10 +13434,10 @@  dprintf_after_condition_true (struct bpstats *bs)
    markers (`-m').  */
 
 static void
-strace_marker_create_sals_from_address (char **arg,
-					struct linespec_result *canonical,
-					enum bptype type_wanted,
-					char *addr_start, char **copy_arg)
+strace_marker_create_sals_from_location (char **arg,
+					 struct linespec_result *canonical,
+					 enum bptype type_wanted,
+					 char *addr_start, char **copy_arg)
 {
   struct linespec_sals lsal;
 
@@ -13510,7 +13510,7 @@  strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-strace_marker_decode_linespec (struct breakpoint *b, char **s,
+strace_marker_decode_location (struct breakpoint *b, char **s,
 			       struct symtabs_and_lines *sals)
 {
   struct tracepoint *tp = (struct tracepoint *) b;
@@ -14055,7 +14055,7 @@  update_breakpoint_locations (struct breakpoint *b,
    On return, FOUND will be 1 if any SaL was found, zero otherwise.  */
 
 static struct symtabs_and_lines
-addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
+location_to_sals (struct breakpoint *b, char *addr_string, int *found)
 {
   char *s;
   struct symtabs_and_lines sals = {0};
@@ -14066,7 +14066,7 @@  addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
 
   TRY
     {
-      b->ops->decode_linespec (b, &s, &sals);
+      b->ops->decode_location (b, &s, &sals);
     }
   CATCH (e, RETURN_MASK_ERROR)
     {
@@ -14148,7 +14148,7 @@  breakpoint_re_set_default (struct breakpoint *b)
   struct symtabs_and_lines expanded = {0};
   struct symtabs_and_lines expanded_end = {0};
 
-  sals = addr_string_to_sals (b, b->addr_string, &found);
+  sals = location_to_sals (b, b->addr_string, &found);
   if (found)
     {
       make_cleanup (xfree, sals.sals);
@@ -14157,7 +14157,7 @@  breakpoint_re_set_default (struct breakpoint *b)
 
   if (b->addr_string_range_end)
     {
-      sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found);
+      sals_end = location_to_sals (b, b->addr_string_range_end, &found);
       if (found)
 	{
 	  make_cleanup (xfree, sals_end.sals);
@@ -14172,7 +14172,7 @@  breakpoint_re_set_default (struct breakpoint *b)
    calls parse_breakpoint_sals.  Return 1 for success, zero for failure.  */
 
 static void
-create_sals_from_address_default (char **arg,
+create_sals_from_location_default (char **arg,
 				  struct linespec_result *canonical,
 				  enum bptype type_wanted,
 				  char *addr_start, char **copy_arg)
@@ -14205,10 +14205,10 @@  create_breakpoints_sal_default (struct gdbarch *gdbarch,
 }
 
 /* Decode the line represented by S by calling decode_line_full.  This is the
-   default function for the `decode_linespec' method of breakpoint_ops.  */
+   default function for the `decode_location' method of breakpoint_ops.  */
 
 static void
-decode_linespec_default (struct breakpoint *b, char **s,
+decode_location_default (struct breakpoint *b, char **s,
 			 struct symtabs_and_lines *sals)
 {
   struct linespec_result canonical;
@@ -15588,9 +15588,9 @@  initialize_breakpoint_ops (void)
   ops->insert_location = bkpt_insert_location;
   ops->remove_location = bkpt_remove_location;
   ops->breakpoint_hit = bkpt_breakpoint_hit;
-  ops->create_sals_from_address = bkpt_create_sals_from_address;
+  ops->create_sals_from_location = bkpt_create_sals_from_location;
   ops->create_breakpoints_sal = bkpt_create_breakpoints_sal;
-  ops->decode_linespec = bkpt_decode_linespec;
+  ops->decode_location = bkpt_decode_location;
 
   /* The breakpoint_ops structure to be used in regular breakpoints.  */
   ops = &bkpt_breakpoint_ops;
@@ -15638,8 +15638,8 @@  initialize_breakpoint_ops (void)
   *ops = bkpt_breakpoint_ops;
   ops->insert_location = bkpt_probe_insert_location;
   ops->remove_location = bkpt_probe_remove_location;
-  ops->create_sals_from_address = bkpt_probe_create_sals_from_address;
-  ops->decode_linespec = bkpt_probe_decode_linespec;
+  ops->create_sals_from_location = bkpt_probe_create_sals_from_location;
+  ops->decode_location = bkpt_probe_decode_location;
 
   /* Watchpoints.  */
   ops = &watchpoint_breakpoint_ops;
@@ -15677,22 +15677,22 @@  initialize_breakpoint_ops (void)
   ops->print_one_detail = tracepoint_print_one_detail;
   ops->print_mention = tracepoint_print_mention;
   ops->print_recreate = tracepoint_print_recreate;
-  ops->create_sals_from_address = tracepoint_create_sals_from_address;
+  ops->create_sals_from_location = tracepoint_create_sals_from_location;
   ops->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
-  ops->decode_linespec = tracepoint_decode_linespec;
+  ops->decode_location = tracepoint_decode_location;
 
   /* Probe tracepoints.  */
   ops = &tracepoint_probe_breakpoint_ops;
   *ops = tracepoint_breakpoint_ops;
-  ops->create_sals_from_address = tracepoint_probe_create_sals_from_address;
-  ops->decode_linespec = tracepoint_probe_decode_linespec;
+  ops->create_sals_from_location = tracepoint_probe_create_sals_from_location;
+  ops->decode_location = tracepoint_probe_decode_location;
 
   /* Static tracepoints with marker (`-m').  */
   ops = &strace_marker_breakpoint_ops;
   *ops = tracepoint_breakpoint_ops;
-  ops->create_sals_from_address = strace_marker_create_sals_from_address;
+  ops->create_sals_from_location = strace_marker_create_sals_from_location;
   ops->create_breakpoints_sal = strace_marker_create_breakpoints_sal;
-  ops->decode_linespec = strace_marker_decode_linespec;
+  ops->decode_location = strace_marker_decode_location;
 
   /* Fork catchpoints.  */
   ops = &catch_fork_breakpoint_ops;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 94d9385..4406260 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -574,14 +574,14 @@  struct breakpoint_ops
   /* Print to FP the CLI command that recreates this breakpoint.  */
   void (*print_recreate) (struct breakpoint *, struct ui_file *fp);
 
-  /* Create SALs from address string, storing the result in linespec_result.
+  /* Create SALs from location, storing the result in linespec_result.
 
      For an explanation about the arguments, see the function
-     `create_sals_from_address_default'.
+     `create_sals_from_location_default'.
 
      This function is called inside `create_breakpoint'.  */
-  void (*create_sals_from_address) (char **, struct linespec_result *,
-				    enum bptype, char *, char **);
+  void (*create_sals_from_location) (char **, struct linespec_result *,
+				     enum bptype, char *, char **);
 
   /* This method will be responsible for creating a breakpoint given its SALs.
      Usually, it just calls `create_breakpoints_sal' (for ordinary
@@ -597,12 +597,12 @@  struct breakpoint_ops
 				  int, const struct breakpoint_ops *,
 				  int, int, int, unsigned);
 
-  /* Given the address string (second parameter), this method decodes it
+  /* Given the location (second parameter), this method decodes it
      and provides the SAL locations related to it.  For ordinary breakpoints,
      it calls `decode_line_full'.
 
-     This function is called inside `addr_string_to_sals'.  */
-  void (*decode_linespec) (struct breakpoint *, char **,
+     This function is called inside `location_to_sals'.  */
+  void (*decode_location) (struct breakpoint *, char **,
 			   struct symtabs_and_lines *);
 
   /* Return true if this breakpoint explains a signal.  See



commit c7c1b3e998a77eb077ac3c08c88a97d2e11dfef0
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: introduce new struct event_location-based API
    
    This patch introduces the new breakpoint/"linespec" API based on
    a new struct event_location.  This API currently only supports
    traditional linespecs, maintaining the status quo of the code base.
    Future patches will add additional functionality for other location
    types such as address locations.
    
    gdb/ChangeLog:
    
    	* Makefile.in (SFILES): Add location.c.
    	(HFILES_NO_SRCDIR): Add location.h.
    	(COMMON_OBS): Add location.o.
    	* linespec.c (linespec_lex_to_end): New function.
    	* linespec.h (linespec_lex_to_end): Declare.
    	* location.c: New file.
    	* location.h: New file.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 487f86c..7b6be92 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,15 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* Makefile.in (SFILES): Add location.c.
+	(HFILES_NO_SRCDIR): Add location.h.
+	(COMMON_OBS): Add location.o.
+	* linespec.c (linespec_lex_to_end): New function.
+	* linespec.h (linespec_lex_to_end): Declare.
+	* location.c: New file.
+	* location.h: New file.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* breakpoint.h (struct breakpoint_ops) <create_sals_from_address>:
 	Renamed to create_sals_from_location.
 	<decode_linespec>: Renamed to decode_location.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index fdbfb42..596ddeb 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -857,7 +857,7 @@  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	inline-frame.c \
 	interps.c \
 	jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c jv-varobj.c \
-	language.c linespec.c minidebug.c \
+	language.c linespec.c location.c minidebug.c \
 	m2-exp.y m2-lang.c m2-typeprint.c m2-valprint.c \
 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
 	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c memory-map.c \
@@ -943,7 +943,7 @@  mi/mi-out.h mi/mi-main.h mi/mi-common.h mi/mi-cmds.h linux-nat.h \
 complaints.h gdb_proc_service.h gdb_regex.h xtensa-tdep.h inf-loop.h \
 common/gdb_wait.h common/gdb_assert.h solib.h ppc-tdep.h cp-support.h glibc-tdep.h \
 interps.h auxv.h gdbcmd.h tramp-frame.h mipsnbsd-tdep.h	\
-amd64-linux-tdep.h linespec.h i387-tdep.h mn10300-tdep.h \
+amd64-linux-tdep.h linespec.h location.h i387-tdep.h mn10300-tdep.h \
 sparc64-tdep.h monitor.h ppcobsd-tdep.h srec.h \
 coff-pe-read.h parser-defs.h gdb_ptrace.h mips-linux-tdep.h \
 m68k-tdep.h spu-tdep.h jv-lang.h environ.h amd64-tdep.h \
@@ -1026,7 +1026,7 @@  COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
 	block.o symtab.o psymtab.o symfile.o symfile-debug.o symmisc.o \
 	linespec.o dictionary.o \
-	infcall.o \
+	location.o infcall.o \
 	infcmd.o infrun.o \
 	expprint.o environ.o stack.o thread.o \
 	exceptions.o \
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 2fe845f..5c4ed3f 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2435,6 +2435,54 @@  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;
+  volatile struct gdb_exception e;
+  const char *orig;
+
+  if (stringp == NULL || *stringp == NULL)
+    return;
+
+  linespec_parser_new (&parser, 0, current_language, 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;
+
+      /* For addresses advance the parser stream past
+	 any parsed input and stop lexing.  */
+      if (token.type == LSTOKEN_STRING
+	  && *LS_TOKEN_STOKEN (token).ptr == '*')
+	{
+	  const char *arg;
+
+	  arg = *stringp;
+	  (void) linespec_expression_to_pc (&arg);
+	  PARSER_STREAM (&parser) = arg;
+	  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
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 7e66024..77ec46d 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -156,4 +156,9 @@  extern struct symtabs_and_lines decode_line_with_last_displayed (char *, int);
    the keyword.  If not, return NULL.  */
 
 extern const char *linespec_lexer_lex_keyword (const char *p);
+
+/* Find the end of the (first) linespec pointed to by *STRINGP.
+   STRINGP will be advanced to this point.  */
+
+extern void linespec_lex_to_end (char **stringp);
 #endif /* defined (LINESPEC_H) */
diff --git a/gdb/location.c b/gdb/location.c
new file mode 100644
index 0000000..44f3dc6
--- /dev/null
+++ b/gdb/location.c
@@ -0,0 +1,220 @@ 
+/* Data structures and API for event locations in GDB.
+   Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+#include "gdb_assert.h"
+#include "location.h"
+#include "symtab.h"
+#include "language.h"
+#include "linespec.h"
+#include "cli/cli-utils.h"
+#include "probe.h"
+
+#include <ctype.h>
+#include <string.h>
+
+/* An event location used to set a stop event in the inferior.
+   This structure is an amalgam of the various ways
+   to specify where a stop event should be set.  */
+
+struct event_location
+{
+  /* The type of this breakpoint specification.  */
+  enum event_location_type type;
+#define EL_TYPE(PTR) (PTR)->type
+
+  union
+  {
+    /* A generic "this is a string specification" for a location.
+       This representation is used by both "normal" linespecs and
+       probes.  */
+    char *addr_string;
+#define EL_LINESPEC(PTR) ((PTR)->u.addr_string)
+  } u;
+
+  /* Cached string representation of this location.  This is used, e.g., to
+     save stop event locations to file.  Malloc'd.  */
+  char *as_string;
+#define EL_STRING(PTR) ((PTR)->as_string)
+};
+
+/* See description in location.h.  */
+
+enum event_location_type
+event_location_type (const struct event_location *location)
+{
+  return EL_TYPE (location);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
+new_linespec_location (char **linespec)
+{
+  struct event_location *location;
+
+  location = XCNEW (struct event_location);
+  EL_TYPE (location) = LINESPEC_LOCATION;
+  if (*linespec != NULL)
+    {
+      char *p;
+      char *orig = *linespec;
+
+      linespec_lex_to_end (linespec);
+      p = remove_trailing_whitespace (orig, *linespec);
+      if ((p - orig) > 0)
+	EL_LINESPEC (location) = savestring (orig, p - orig);
+    }
+  return location;
+}
+
+/* See description in location.h.  */
+
+const char *
+get_linespec_location (const struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == LINESPEC_LOCATION);
+  return EL_LINESPEC (location);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
+copy_event_location (const struct event_location *src)
+{
+  struct event_location *dst;
+
+  dst = XCNEW (struct event_location);
+  EL_TYPE (dst) = EL_TYPE (src);
+  if (EL_STRING (src) != NULL)
+    EL_STRING (dst) = xstrdup (EL_STRING (src));
+
+  switch (EL_TYPE (src))
+    {
+    case LINESPEC_LOCATION:
+      if (EL_LINESPEC (src) != NULL)
+	EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src));
+      break;
+
+    default:
+      gdb_assert_not_reached ("unknown event location type");
+    }
+
+  return dst;
+}
+
+/* A cleanup function for struct event_location.  */
+
+static void
+delete_event_location_cleanup (void *data)
+{
+  struct event_location *location = (struct event_location *) data;
+
+  delete_event_location (location);
+}
+
+/* See description in location.h.  */
+
+struct cleanup *
+make_cleanup_delete_event_location (struct event_location *location)
+{
+  return make_cleanup (delete_event_location_cleanup, location);
+}
+
+/* See description in location.h.  */
+
+void
+delete_event_location (struct event_location *location)
+{
+  if (location != NULL)
+    {
+      xfree (EL_STRING (location));
+
+      switch (EL_TYPE (location))
+	{
+	case LINESPEC_LOCATION:
+	  xfree (EL_LINESPEC (location));
+	  break;
+
+	default:
+	  gdb_assert_not_reached ("unknown event location type");
+	}
+
+      xfree (location);
+    }
+}
+
+/* See description in location.h.  */
+
+const char *
+event_location_to_string (struct event_location *location)
+{
+  if (EL_STRING (location) == NULL)
+    {
+      switch (EL_TYPE (location))
+	{
+	case LINESPEC_LOCATION:
+	  if (EL_LINESPEC (location) != NULL)
+	    EL_STRING (location) = xstrdup (EL_LINESPEC (location));
+	  break;
+
+	default:
+	  gdb_assert_not_reached ("unknown event location type");
+	}
+    }
+
+  return EL_STRING (location);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
+string_to_event_location (char **stringp,
+			  const struct language_defn *language)
+{
+  struct event_location *location;
+
+  location = new_linespec_location (stringp);
+  return location;
+}
+
+/* See description in location.h.  */
+
+int
+event_location_empty_p (const struct event_location *location)
+{
+  switch (EL_TYPE (location))
+    {
+    case LINESPEC_LOCATION:
+      /* Linespecs are never "empty."  (NULL is a valid linespec)  */
+      return 0;
+
+    default:
+      gdb_assert_not_reached ("unknown event location type");
+    }
+}
+
+/* See description in location.h.  */
+
+void
+set_event_location_string (struct event_location *location,
+			   const char *string)
+{
+  xfree (EL_STRING (location));
+  EL_STRING (location) = string == NULL ?  NULL : xstrdup (string);
+}
diff --git a/gdb/location.h b/gdb/location.h
new file mode 100644
index 0000000..d35fecb
--- /dev/null
+++ b/gdb/location.h
@@ -0,0 +1,99 @@ 
+/* Data structures and API for event locations in GDB.
+   Copyright (C) 2013-2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LOCATIONS_H
+#define LOCATIONS_H 1
+
+struct language_defn;
+struct event_location;
+
+/* An enumeration of the various ways to specify a stop event
+   location (used with create_breakpoint).  */
+
+enum event_location_type
+{
+  /* A traditional linespec.  */
+  LINESPEC_LOCATION
+};
+
+/* Return the type of the given event location.  */
+
+extern enum event_location_type
+  event_location_type (const struct event_location *);
+
+/* Return a string representation of the LOCATION.
+   This function may return NULL for unspecified linespecs,
+   e.g, LOCATION_LINESPEC and addr_string is NULL.
+
+   The result is cached in LOCATION.  */
+
+extern const char *
+  event_location_to_string (struct event_location *location);
+
+/* Create a new linespec location.  The return result is malloc'd
+   and should be freed with delete_event_location.  */
+
+extern struct event_location *
+  new_linespec_location (char **linespec);
+
+/* Return the linespec location (a string) of the given event_location
+   (which must be of type LINESPEC_LOCATION).  */
+
+extern const char *
+  get_linespec_location (const struct event_location *location);
+
+/* Free an event location and any associated data.  */
+
+extern void delete_event_location (struct event_location *location);
+
+/* Make a cleanup to free LOCATION.  */
+
+extern struct cleanup *
+  make_cleanup_delete_event_location (struct event_location *location);
+
+/* Return a copy of the given SRC location.  */
+
+extern struct event_location *
+  copy_event_location (const struct event_location *src);
+
+/* Attempt to convert the input string in *ARGP into an event_location.
+   ARGP is advanced past any processed input.  Returns an event_location
+   (malloc'd) if an event location was successfully found in *ARGP,
+   NULL otherwise.
+
+   This function may call error() if *ARGP looks like properly formed,
+   but invalid, input, e.g., if it is called with missing argument parameters
+   or invalid options.
+
+   The return result must be freed with delete_event_location.  */
+
+extern struct event_location *
+  string_to_event_location (char **argp,
+			    const struct language_defn *langauge);
+
+/* A convenience function for testing for unset locations.  */
+
+extern int event_location_empty_p (const struct event_location *location);
+
+/* Set the location's string representation.  If STRING is NULL, clear
+   the string representation.  */
+
+extern void
+  set_event_location_string (struct event_location *location,
+			     const char *string);
+#endif /* LOCATIONS_H */



commit f00aae0f7b11c4dc85c38d5fad46975033ba3fff
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: use new location API
    
    This patch converts the code base to use the new struct event_location
    API being introduced. This patch preserves the current functionality and
    adds no new features.
    
    The "big picture" API usage introduced by this patch may be illustrated
    with a simple exmaple. Where previously developers would write:
    
    void
    my_command (char *arg, int from_tty)
    {
       create_breakpoint (..., arg, ...);
       ...
    }
    
    one now uses:
    
    void
    my_command (char *arg, int from_tty)
    {
       struct event_locaiton *location;
       struct cleanup *back_to;
    
       location = string_to_event_locaiton (&arg, ...);
       back_to = make_cleanup_delete_event_location (location);
       create_breakpoint (..., location, ...);
       do_cleanups (back_to);
    }
    
    Linespec-decoding functions (now called location-decoding) such as
    decode_line_full no longer skip argument pointers over processed input.
    That functionality has been moved into string_to_event_location as
    demonstrated above.
    
    gdb/ChangeLog
    
    	* ax-gdb.c: Include location.h.
    	(agent_command_1) Use linespec location instead of address
    	string.
    	* break-catch-throw.c: Include location.h.
    	(re_set_exception_catchpoint): Use linespec locations instead
    	of address strings.
    	* breakpoint.c: Include location.h.
    	(create_overlay_event_breakpoint, create_longjmp_master_breakpoint)
    	(create_std_terminate_master_breakpoint)
    	(create_exception_master_breakpoint, update_breakpoints_after_exec):
    	Use linespec location instead of address string.
    	(print_breakpoint_location):  Use locations and
    	event_location_to_string.
    	Print extra_string for pending locations for non-MI streams.
    	(print_one_breakpoint_location): Use locations and
    	event_location_to_string.
    	(init_raw_breakpoint_without_location): Initialize b->location.
    	(create_thread_event_breakpoint): Use linespec location instead of
    	address string.
    	(init_breakpoint_sal): Likewise.
    	Only save extra_string if it is non-NULL and not the empty string.
    	Use event_location_to_string instead of `addr_string'.
    	Constify `p' and `endp'.
    	Use skip_spaces_const/skip_space_const instead of non-const versions.
    	Copy the location into the breakpoint.
    	If LOCATION is NULL, save the breakpoint address as a linespec location
    	instead of an address string.
    	(create_breakpoint_sal): Change `addr_string' parameter to a struct
    	event_location. All uses updated.
    	(create_breakpoints_sal): Likewise for local variable `addr_string'.
    	(parse_breakpoint_sals): Use locations instead of address strings.
    	Remove check for empty linespec with conditional.
    	Refactor.
    	(decode_static_tracepoint_spec): Make argument const and update
    	function.
    	(create_breakpoint): Change `arg' to a struct event_location and
    	rename.
    	Remove `copy_arg' and `addr_start'.
    	If EXTRA_STRING is empty, set it to NULL.
    	Don't populate `canonical' for pending breakpoints.
    	Pass `extra_string' to find_condition_and_thread.
    	Clear `extra_string' if `rest' was NULL.
    	Do not error with "garbage after location" if setting a dprintf
    	breakpoint.
    	Copy the location into the breakpoint instead of an address string.
    	(break_command_1): Use string_to_event_location and pass this to
    	create_breakpoint instead of an address string.
    	Check against `arg_cp' for a probe linespec.
    	(dprintf_command): Use string_to_event_location and pass this to
    	create_breakpoint instead of an address string.
    	Throw an exception if no format string was specified.
    	(print_recreate_ranged_breakpoint): Use event_location_to_string
    	instead of address strings.
    	(break_range_command, until_break_command)
    	(init_ada_exception_breakpoint): Use locations instead
    	of address strings.
    	(say_where): Print out extra_string for pending locations.
    	(base_breakpoint_dtor): Delete `location' and `location_range_end' of
    	the breakpoint.
    	(base_breakpoint_create_sals_from_location): Use struct event_location
    	instead of address string.
    	Remove `addr_start' and `copy_arg' parameters.
    	(base_breakpoint_decode_location): Use struct event_location instead of
    	address string.
    	(bkpt_re_set): Use locations instead of address strings.
    	Use event_location_empty_p to check for unset location.
    	(bkpt_print_recreate): Use event_location_to_string instead of
    	an address string.
    	Print out extra_string for pending locations.
    	(bkpt_create_sals_from_location, bkpt_decode_location)
     	(bkpt_probe_create_sals_from_location): Use struct event_location
    	instead of address string.
    	(bkpt_probe_decode_location): Use struct event_location instead of
    	address string.
    	(tracepoint_print_recreate): Use event_location_to_string to
    	recreate the tracepoint.
    	(tracepoint_create_sals_from_location, tracepoint_decode_location)
    	(tracepoint_probe_create_sals_from_location)
    	(tracepoint_probe_decode_location): Use struct event_location
    	instead of address string.
    	(dprintf_print_recreate): Use event_location_to_string to recreate
    	the dprintf.
    	(dprintf_re_set): Remove check for valid/missing format string.
    	(strace_marker_create_sals_from_location)
    	(strace_marker_create_breakpoints_sal, strace_marker_decode_location)
    	(update_static_tracepoint): Use struct event_location instead of
    	address string.
    	(location_to_sals): Likewise.
    	Pass `extra_string' to find_condition_and_thread.
    	For newly resolved pending breakpoint locations, clear the location's
    	string representation.
    	Assert that the breakpoint's condition string is NULL when
    	condition_not_parsed.
    	(breakpoint_re_set_default, create_sals_from_location_default)
    	(decode_location_default, trace_command, ftrace_command)
    	(strace_command, create_tracepoint_from_upload): Use locations
    	instead of address strings.
    	* breakpoint.h (struct breakpoint_ops) <create_sals_from_location>:
    	Use struct event_location instead of address string.
    	Update all uses.
    	<decode_location>: Likewise.
    	(struct breakpoint) <addr_string>: Change to struct event_location
    	and rename `location'.
    	<addr_string_range_end>: Change to struct event_location and rename
    	`location_range_end'.
    	(create_breakpoint): Use struct event_location instead of address
    	string.
    	* cli/cli-cmds.c: Include location.h.
    	(edit_command, list_command): Use locations instead of address strings.
    	* elfread.c: Include location.h.
    	(elf_gnu_ifunc_resolver_return_stop): Use event_location_to_string.
    	* guile/scm-breakpoint.c: Include location.h.
    	(bpscm_print_breakpoint_smob): Use event_location_to_string.
    	(gdbscm_register_breakpoint): Use locations instead of address
    	strings.
    	* linespec.c: Include location.h.
    	(struct ls_parser) <stream>: Change to const char *.
    	(PARSER_STREAM): Update.
    	(lionespec_lexer_lex_keyword): According to find_condition_and_thread,
    	keywords must be followed by whitespace.
    	(canonicalize_linespec): Save a linespec location into `canonical'.
    	Save a canonical linespec into `canonical'.
    	(parse_linespec): Change `argptr' to const char * and rename `arg'.
    	All uses updated.
    	Update function description.
    	(linespec_parser_new): Initialize `parser'.
    	Update initialization of  parsing stream.
    	(event_location_to_sals): New function.
    	(decode_line_full): Change `argptr' to a struct event_location and
    	rename it `location'.
    	Use locations instead of address strings.
    	Call event_location_to_sals instead of parse_linespec.
    	(decode_line_1): Likewise.
    	(decode_line_with_current_source, decode_line_with_last_displayed)
    	Use locations instead of address strings.
    	(decode_objc): Likewise.
    	Change `argptr' to const char * and rename `arg'.
    	(destroy_linespec_result): Delete the linespec result's location
    	instead of freeing the address string.
    	* linespec.h (struct linespec_result) <addr_string>: Change to
    	struct event_location and rename to ...
    	<location>: ... this.
    	(decode_line_1, decode_line_full): Change `argptr' to struct
    	event_location.  All callers updated.
    	* mi/mi-cmd-break.c: Include language.h, location.h, and linespec.h.
    	(mi_cmd_break_insert_1): Use locations instead of address strings.
    	Throw an error if there was "garbage" at the end of the specified
    	linespec.
    	* probe.c: Include location.h.
    	(parse_probes): Change `argptr' to struct event_location.
    	Use event locations instead of address strings.
    	* probe.h (parse_probes): Change `argptr' to struct event_location.
    	* python/py-breakpoint.c: Include location.h.
    	(bppy_get_location): Constify local variable `str'.
    	Use event_location_to_string.
    	(bppy_init): Use locations instead of address strings.
    	* python/py-finishbreakpoint.c: Include location.h.
    	(bpfinishpy_init): Remove local variable `addr_str'.
    	Use locations instead of address strings.
    	* python/python.c: Include location.h.
    	(gdbpy_decode_line): Use locations instead of address strings.
    	* remote.c: Include location.h.
    	(remote_download_tracepoint): Use locations instead of address
    	strings.
    	* spu-tdep.c: Include location.h.
    	(spu_catch_start): Remove local variable `buf'.
    	Use locations instead of address strings.
    	* tracepoint.c: Include location.h.
    	(scope_info): Use locations instead of address strings.
    	(encode_source_string): Constify parameter `src'.
    	* tracepoint.h (encode_source_string): Likewise.
    
    gdb/testsuite/ChangeLog
    
    	* gdb.base/dprintf-pending.exp: Update dprintf "without format"
    	test.
    	Add tests for missing ",FMT" and ",".

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7b6be92..f6dc1b6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,179 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* ax-gdb.c: Include location.h.
+	(agent_command_1) Use linespec location instead of address
+	string.
+	* break-catch-throw.c: Include location.h.
+	(re_set_exception_catchpoint): Use linespec locations instead
+	of address strings.
+	* breakpoint.c: Include location.h.
+	(create_overlay_event_breakpoint, create_longjmp_master_breakpoint)
+	(create_std_terminate_master_breakpoint)
+	(create_exception_master_breakpoint, update_breakpoints_after_exec):
+	Use linespec location instead of address string.
+	(print_breakpoint_location):  Use locations and
+	event_location_to_string.
+	Print extra_string for pending locations for non-MI streams.
+	(print_one_breakpoint_location): Use locations and
+	event_location_to_string.
+	(init_raw_breakpoint_without_location): Initialize b->location.
+	(create_thread_event_breakpoint): Use linespec location instead of
+	address string.
+	(init_breakpoint_sal): Likewise.
+	Only save extra_string if it is non-NULL and not the empty string.
+	Use event_location_to_string instead of `addr_string'.
+	Constify `p' and `endp'.
+	Use skip_spaces_const/skip_space_const instead of non-const versions.
+	Copy the location into the breakpoint.
+	If LOCATION is NULL, save the breakpoint address as a linespec location
+	instead of an address string.
+	(create_breakpoint_sal): Change `addr_string' parameter to a struct
+	event_location. All uses updated.
+	(create_breakpoints_sal): Likewise for local variable `addr_string'.
+	(parse_breakpoint_sals): Use locations instead of address strings.
+	Remove check for empty linespec with conditional.
+	Refactor.
+	(decode_static_tracepoint_spec): Make argument const and update
+	function.
+	(create_breakpoint): Change `arg' to a struct event_location and
+	rename.
+	Remove `copy_arg' and `addr_start'.
+	If EXTRA_STRING is empty, set it to NULL.
+	Don't populate `canonical' for pending breakpoints.
+	Pass `extra_string' to find_condition_and_thread.
+	Clear `extra_string' if `rest' was NULL.
+	Do not error with "garbage after location" if setting a dprintf
+	breakpoint.
+	Copy the location into the breakpoint instead of an address string.
+	(break_command_1): Use string_to_event_location and pass this to
+	create_breakpoint instead of an address string.
+	Check against `arg_cp' for a probe linespec.
+	(dprintf_command): Use string_to_event_location and pass this to
+	create_breakpoint instead of an address string.
+	Throw an exception if no format string was specified.
+	(print_recreate_ranged_breakpoint): Use event_location_to_string
+	instead of address strings.
+	(break_range_command, until_break_command)
+	(init_ada_exception_breakpoint): Use locations instead
+	of address strings.
+	(say_where): Print out extra_string for pending locations.
+	(base_breakpoint_dtor): Delete `location' and `location_range_end' of
+	the breakpoint.
+	(base_breakpoint_create_sals_from_location): Use struct event_location
+	instead of address string.
+	Remove `addr_start' and `copy_arg' parameters.
+	(base_breakpoint_decode_location): Use struct event_location instead of
+	address string.
+	(bkpt_re_set): Use locations instead of address strings.
+	Use event_location_empty_p to check for unset location.
+	(bkpt_print_recreate): Use event_location_to_string instead of
+	an address string.
+	Print out extra_string for pending locations.
+	(bkpt_create_sals_from_location, bkpt_decode_location)
+	(bkpt_probe_create_sals_from_location): Use struct event_location
+	instead of address string.
+	(bkpt_probe_decode_location): Use struct event_location instead of
+	address string.
+	(tracepoint_print_recreate): Use event_location_to_string to
+	recreate the tracepoint.
+	(tracepoint_create_sals_from_location, tracepoint_decode_location)
+	(tracepoint_probe_create_sals_from_location)
+	(tracepoint_probe_decode_location): Use struct event_location
+	instead of address string.
+	(dprintf_print_recreate): Use event_location_to_string to recreate
+	the dprintf.
+	(dprintf_re_set): Remove check for valid/missing format string.
+	(strace_marker_create_sals_from_location)
+	(strace_marker_create_breakpoints_sal, strace_marker_decode_location)
+	(update_static_tracepoint): Use struct event_location instead of
+	address string.
+	(location_to_sals): Likewise.
+	Pass `extra_string' to find_condition_and_thread.
+	For newly resolved pending breakpoint locations, clear the location's
+	string representation.
+	Assert that the breakpoint's condition string is NULL when
+	condition_not_parsed.
+	(breakpoint_re_set_default, create_sals_from_location_default)
+	(decode_location_default, trace_command, ftrace_command)
+	(strace_command, create_tracepoint_from_upload): Use locations
+	instead of address strings.
+	* breakpoint.h (struct breakpoint_ops) <create_sals_from_location>:
+	Use struct event_location instead of address string.
+	Update all uses.
+	<decode_location>: Likewise.
+	(struct breakpoint) <addr_string>: Change to struct event_location
+	and rename `location'.
+	<addr_string_range_end>: Change to struct event_location and rename
+	`location_range_end'.
+	(create_breakpoint): Use struct event_location instead of address
+	string.
+	* cli/cli-cmds.c: Include location.h.
+	(edit_command, list_command): Use locations instead of address strings.
+	* elfread.c: Include location.h.
+	(elf_gnu_ifunc_resolver_return_stop): Use event_location_to_string.
+	* guile/scm-breakpoint.c: Include location.h.
+	(bpscm_print_breakpoint_smob): Use event_location_to_string.
+	(gdbscm_register_breakpoint): Use locations instead of address
+	strings.
+	* linespec.c: Include location.h.
+	(struct ls_parser) <stream>: Change to const char *.
+	(PARSER_STREAM): Update.
+	(lionespec_lexer_lex_keyword): According to find_condition_and_thread,
+	keywords must be followed by whitespace.
+	(canonicalize_linespec): Save a linespec location into `canonical'.
+	Save a canonical linespec into `canonical'.
+	(parse_linespec): Change `argptr' to const char * and rename `arg'.
+	All uses updated.
+	Update function description.
+	(linespec_parser_new): Initialize `parser'.
+	Update initialization of  parsing stream.
+	(event_location_to_sals): New function.
+	(decode_line_full): Change `argptr' to a struct event_location and
+	rename it `location'.
+	Use locations instead of address strings.
+	Call event_location_to_sals instead of parse_linespec.
+	(decode_line_1): Likewise.
+	(decode_line_with_current_source, decode_line_with_last_displayed)
+	Use locations instead of address strings.
+	(decode_objc): Likewise.
+	Change `argptr' to const char * and rename `arg'.
+	(destroy_linespec_result): Delete the linespec result's location
+	instead of freeing the address string.
+	* linespec.h (struct linespec_result) <addr_string>: Change to
+	struct event_location and rename to ...
+	<location>: ... this.
+	(decode_line_1, decode_line_full): Change `argptr' to struct
+	event_location.  All callers updated.
+	* mi/mi-cmd-break.c: Include language.h, location.h, and linespec.h.
+	(mi_cmd_break_insert_1): Use locations instead of address strings.
+	Throw an error if there was "garbage" at the end of the specified
+	linespec.
+	* probe.c: Include location.h.
+	(parse_probes): Change `argptr' to struct event_location.
+	Use event locations instead of address strings.
+	* probe.h (parse_probes): Change `argptr' to struct event_location.
+	* python/py-breakpoint.c: Include location.h.
+	(bppy_get_location): Constify local variable `str'.
+	Use event_location_to_string.
+	(bppy_init): Use locations instead of address strings.
+	* python/py-finishbreakpoint.c: Include location.h.
+	(bpfinishpy_init): Remove local variable `addr_str'.
+	Use locations instead of address strings.
+	* python/python.c: Include location.h.
+	(gdbpy_decode_line): Use locations instead of address strings.
+	* remote.c: Include location.h.
+	(remote_download_tracepoint): Use locations instead of address
+	strings.
+	* spu-tdep.c: Include location.h.
+	(spu_catch_start): Remove local variable `buf'.
+	Use locations instead of address strings.
+	* tracepoint.c: Include location.h.
+	(scope_info): Use locations instead of address strings.
+	(encode_source_string): Constify parameter `src'.
+	* tracepoint.h (encode_source_string): Likewise.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* Makefile.in (SFILES): Add location.c.
 	(HFILES_NO_SRCDIR): Add location.h.
 	(COMMON_OBS): Add location.o.
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 38f2c55..817fa53 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -40,6 +40,7 @@ 
 #include "arch-utils.h"
 #include "cli/cli-utils.h"
 #include "linespec.h"
+#include "location.h"
 #include "objfiles.h"
 
 #include "valprint.h"
@@ -2642,13 +2643,16 @@  agent_command_1 (char *exp, int eval)
       int ix;
       struct linespec_sals *iter;
       struct cleanup *old_chain;
+      struct event_location *location;
 
       exp = skip_spaces (exp);
       init_linespec_result (&canonical);
-      decode_line_full (&exp, DECODE_LINE_FUNFIRSTLINE,
+      location = new_linespec_location (&exp);
+      old_chain = make_cleanup_delete_event_location (location);
+      decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
 			(struct symtab *) NULL, 0, &canonical,
 			NULL, NULL);
-      old_chain = make_cleanup_destroy_linespec_result (&canonical);
+      make_cleanup_destroy_linespec_result (&canonical);
       exp = skip_spaces (exp);
       if (exp[0] == ',')
         {
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 927176f..9449aa5 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -35,6 +35,7 @@ 
 #include "cp-abi.h"
 #include "gdb_regex.h"
 #include "cp-support.h"
+#include "location.h"
 
 /* Enums for exception-handling support.  */
 enum exception_event_kind
@@ -210,25 +211,31 @@  re_set_exception_catchpoint (struct breakpoint *self)
   struct symtabs_and_lines sals_end = {0};
   struct cleanup *cleanup;
   enum exception_event_kind kind = classify_exception_breakpoint (self);
+  struct event_location *location;
 
   /* We first try to use the probe interface.  */
   TRY
     {
       char *spec = ASTRDUP (exception_functions[kind].probe);
 
-      sals = parse_probes (&spec, NULL);
+      location = new_linespec_location (&spec);
+      cleanup = make_cleanup_delete_event_location (location);
+      sals = parse_probes (location, NULL);
+      do_cleanups (cleanup);
     }
 
   CATCH (e, RETURN_MASK_ERROR)
     {
-
       /* Using the probe interface failed.  Let's fallback to the normal
 	 catchpoint mode.  */
       TRY
 	{
 	  char *spec = ASTRDUP (exception_functions[kind].function);
 
-	  self->ops->decode_location (self, &spec, &sals);
+	  location = new_linespec_location (&spec);
+	  cleanup = make_cleanup_delete_event_location (location);
+	  self->ops->decode_location (self, location, &sals);
+	  do_cleanups (cleanup);
 	}
       CATCH (ex, RETURN_MASK_ERROR)
 	{
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1d1cb03..395da1f 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -67,6 +67,7 @@ 
 #include "dummy-frame.h"
 #include "interps.h"
 #include "format.h"
+#include "location.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -108,10 +109,10 @@  static int breakpoint_re_set_one (void *);
 
 static void breakpoint_re_set_default (struct breakpoint *);
 
-static void create_sals_from_location_default (char **,
-					       struct linespec_result *,
-					       enum bptype, char *,
-					       char **);
+static void
+  create_sals_from_location_default (const struct event_location *location,
+				     struct linespec_result *canonical,
+				     enum bptype type_wanted);
 
 static void create_breakpoints_sal_default (struct gdbarch *,
 					    struct linespec_result *,
@@ -121,8 +122,9 @@  static void create_breakpoints_sal_default (struct gdbarch *,
 					    const struct breakpoint_ops *,
 					    int, int, int, unsigned);
 
-static void decode_location_default (struct breakpoint *, char **,
-				     struct symtabs_and_lines *);
+static void decode_location_default (struct breakpoint *b,
+				     const struct event_location *location,
+				     struct symtabs_and_lines *sals);
 
 static void clear_command (char *, int);
 
@@ -3422,6 +3424,7 @@  create_overlay_event_breakpoint (void)
       struct breakpoint *b;
       struct breakpoint_objfile_data *bp_objfile_data;
       CORE_ADDR addr;
+      char *p;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3446,7 +3449,8 @@  create_overlay_event_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_overlay_event,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      p = ASTRDUP (func_name);
+      b->location = new_linespec_location (&p);
 
       if (overlay_debugging == ovly_auto)
         {
@@ -3513,6 +3517,7 @@  create_longjmp_master_breakpoint (void)
 	  int i;
 	  struct probe *probe;
 	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
+	  char *p;
 
 	  for (i = 0;
 	       VEC_iterate (probe_p,
@@ -3527,7 +3532,8 @@  create_longjmp_master_breakpoint (void)
 								 objfile),
 					      bp_longjmp_master,
 					      &internal_breakpoint_ops);
-	      b->addr_string = xstrdup ("-probe-stap libc:longjmp");
+	      p = ASTRDUP ("-probe-stap libc:longjmp");
+	      b->location = new_linespec_location (&p);
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -3542,6 +3548,7 @@  create_longjmp_master_breakpoint (void)
 	  struct breakpoint *b;
 	  const char *func_name;
 	  CORE_ADDR addr;
+	  char *p;
 
 	  if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
 	    continue;
@@ -3564,7 +3571,8 @@  create_longjmp_master_breakpoint (void)
 	  addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
 	  b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
 					  &internal_breakpoint_ops);
-	  b->addr_string = xstrdup (func_name);
+	  p = ASTRDUP (func_name);
+	  b->location = new_linespec_location (&p);
 	  b->enable_state = bp_disabled;
 	}
     }
@@ -3595,6 +3603,7 @@  create_std_terminate_master_breakpoint (void)
     {
       struct breakpoint *b;
       struct breakpoint_objfile_data *bp_objfile_data;
+      char *p;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3620,7 +3629,8 @@  create_std_terminate_master_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_std_terminate_master,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      p = ASTRDUP (func_name);
+      b->location = new_linespec_location (&p);
       b->enable_state = bp_disabled;
     }
   }
@@ -3644,6 +3654,7 @@  create_exception_master_breakpoint (void)
       struct gdbarch *gdbarch;
       struct breakpoint_objfile_data *bp_objfile_data;
       CORE_ADDR addr;
+      char *p;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3684,13 +3695,15 @@  create_exception_master_breakpoint (void)
 	       ++i)
 	    {
 	      struct breakpoint *b;
+	      char *p;
 
 	      b = create_internal_breakpoint (gdbarch,
 					      get_probe_address (probe,
 								 objfile),
 					      bp_exception_master,
 					      &internal_breakpoint_ops);
-	      b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
+	      p = ASTRDUP ("-probe-stap libgcc:unwind");
+	      b->location = new_linespec_location (&p);
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -3723,7 +3736,8 @@  create_exception_master_breakpoint (void)
 						 &current_target);
       b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      p = ASTRDUP (func_name);
+      b->location = new_linespec_location (&p);
       b->enable_state = bp_disabled;
     }
 
@@ -3844,7 +3858,7 @@  update_breakpoints_after_exec (void)
     /* Without a symbolic address, we have little hope of the
        pre-exec() address meaning the same thing in the post-exec()
        a.out.  */
-    if (b->addr_string == NULL)
+    if (event_location_empty_p (b->location))
       {
 	delete_breakpoint (b);
 	continue;
@@ -6032,7 +6046,8 @@  print_breakpoint_location (struct breakpoint *b,
     set_current_program_space (loc->pspace);
 
   if (b->display_canonical)
-    ui_out_field_string (uiout, "what", b->addr_string);
+    ui_out_field_string (uiout, "what",
+			 event_location_to_string (b->location));
   else if (loc && loc->symtab)
     {
       struct symbol *sym 
@@ -6068,7 +6083,21 @@  print_breakpoint_location (struct breakpoint *b,
       do_cleanups (stb_chain);
     }
   else
-    ui_out_field_string (uiout, "pending", b->addr_string);
+    {
+      ui_out_field_string (uiout, "pending",
+			   event_location_to_string (b->location));
+      /* If extra_string is available, it could be holding a condition
+	 or dprintf arguments.  In either case, make sure it is printed,
+	 too, but only for non-MI streams.  */
+      if (!ui_out_is_mi_like_p (uiout) && b->extra_string != NULL)
+	{
+	  if (b->type == bp_dprintf)
+	    ui_out_text (uiout, ",");
+	  else
+	    ui_out_text (uiout, " ");
+	  ui_out_text (uiout, b->extra_string);
+	}
+    }
 
   if (loc && is_breakpoint (b)
       && breakpoint_condition_evaluation_mode () == condition_evaluation_target
@@ -6537,8 +6566,10 @@  print_one_breakpoint_location (struct breakpoint *b,
 
 	  ui_out_field_string (uiout, "original-location", w->exp_string);
 	}
-      else if (b->addr_string)
-	ui_out_field_string (uiout, "original-location", b->addr_string);
+      else if (b->location != NULL
+	       && event_location_to_string (b->location) != NULL)
+	ui_out_field_string (uiout, "original-location",
+			     event_location_to_string (b->location));
     }
 }
 
@@ -7308,6 +7339,7 @@  init_raw_breakpoint_without_location (struct breakpoint *b,
   b->condition_not_parsed = 0;
   b->py_bp_object = NULL;
   b->related_breakpoint = b;
+  b->location = NULL;
 }
 
 /* Helper to set_raw_breakpoint below.  Creates a breakpoint
@@ -7628,15 +7660,19 @@  delete_std_terminate_breakpoint (void)
 struct breakpoint *
 create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 {
+  char *tmp;
   struct breakpoint *b;
+  struct cleanup *cleanup;
 
   b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
 				  &internal_breakpoint_ops);
 
   b->enable_state = bp_enabled;
-  /* addr_string has to be used or breakpoint_re_set will delete me.  */
-  b->addr_string
-    = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+  /* location has to be used or breakpoint_re_set will delete me.  */
+  tmp = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+  cleanup = make_cleanup (xfree, tmp);
+  b->location = new_linespec_location (&tmp);
+  do_cleanups (cleanup);
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
@@ -9070,13 +9106,14 @@  update_dprintf_commands (char *args, int from_tty,
     }
 }
 
-/* Create a breakpoint with SAL as location.  Use ADDR_STRING
-   as textual description of the location, and COND_STRING
+/* Create a breakpoint with SAL as location.  Use LOCATION
+   as a description of the location, and COND_STRING
    as condition expression.  */
 
 static void
 init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
-		     struct symtabs_and_lines sals, char *addr_string,
+		     struct symtabs_and_lines sals,
+		     struct event_location *location,
 		     char *filter, char *cond_string,
 		     char *extra_string,
 		     enum bptype type, enum bpdisp disposition,
@@ -9142,13 +9179,13 @@  init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
 		{
 		  /* We already know the marker exists, otherwise, we
 		     wouldn't see a sal for it.  */
-		  char *p = &addr_string[3];
-		  char *endp;
+		  const char *p = &event_location_to_string (b->location)[3];
+		  const char *endp;
 		  char *marker_str;
 
-		  p = skip_spaces (p);
+		  p = skip_spaces_const (p);
 
-		  endp = skip_to_space (p);
+		  endp = skip_to_space_const (p);
 
 		  marker_str = savestring (p, endp - p);
 		  t->static_trace_marker_id = marker_str;
@@ -9204,19 +9241,26 @@  init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
     }
 
   b->display_canonical = display_canonical;
-  if (addr_string)
-    b->addr_string = addr_string;
+  if (location != NULL)
+    b->location = location;
   else
-    /* addr_string has to be used or breakpoint_re_set will delete
-       me.  */
-    b->addr_string
-      = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+    {
+      char *tmp;
+      struct cleanup *cleanup;
+
+      tmp = xstrprintf ("*%s",
+			    paddress (b->loc->gdbarch, b->loc->address));
+      cleanup = make_cleanup (xfree, tmp);
+      b->location = new_linespec_location (&tmp);
+      do_cleanups (cleanup);
+   }
   b->filter = filter;
 }
 
 static void
 create_breakpoint_sal (struct gdbarch *gdbarch,
-		       struct symtabs_and_lines sals, char *addr_string,
+		       struct symtabs_and_lines sals,
+		       struct event_location *location,
 		       char *filter, char *cond_string,
 		       char *extra_string,
 		       enum bptype type, enum bpdisp disposition,
@@ -9241,7 +9285,7 @@  create_breakpoint_sal (struct gdbarch *gdbarch,
   old_chain = make_cleanup (xfree, b);
 
   init_breakpoint_sal (b, gdbarch,
-		       sals, addr_string,
+		       sals, location,
 		       filter, cond_string, extra_string,
 		       type, disposition,
 		       thread, task, ignore_count,
@@ -9285,17 +9329,17 @@  create_breakpoints_sal (struct gdbarch *gdbarch,
 
   for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i)
     {
-      /* Note that 'addr_string' can be NULL in the case of a plain
+      /* Note that 'location' can be NULL in the case of a plain
 	 'break', without arguments.  */
-      char *addr_string = (canonical->addr_string
-			   ? xstrdup (canonical->addr_string)
-			   : NULL);
+      struct event_location *location
+	= (canonical->location != NULL
+	   ? copy_event_location (canonical->location) : NULL);
       char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
-      struct cleanup *inner = make_cleanup (xfree, addr_string);
+      struct cleanup *inner = make_cleanup_delete_event_location (location);
 
       make_cleanup (xfree, filter_string);
       create_breakpoint_sal (gdbarch, lsal->sals,
-			     addr_string,
+			     location,
 			     filter_string,
 			     cond_string, extra_string,
 			     type, disposition,
@@ -9306,83 +9350,97 @@  create_breakpoints_sal (struct gdbarch *gdbarch,
     }
 }
 
-/* Parse ADDRESS which is assumed to be a SAL specification possibly
+/* Parse LOCATION which is assumed to be a SAL specification possibly
    followed by conditionals.  On return, SALS contains an array of SAL
-   addresses found.  ADDR_STRING contains a vector of (canonical)
-   address strings.  ADDRESS points to the end of the SAL.
+   addresses found.  LOCATION points to the end of the SAL (for
+   linespec locations).
 
    The array and the line spec strings are allocated on the heap, it is
    the caller's responsibility to free them.  */
 
 static void
-parse_breakpoint_sals (char **address,
+parse_breakpoint_sals (const struct event_location *location,
 		       struct linespec_result *canonical)
 {
-  /* If no arg given, or if first arg is 'if ', use the default
-     breakpoint.  */
-  if ((*address) == NULL || linespec_lexer_lex_keyword (*address))
-    {
-      /* The last displayed codepoint, if it's valid, is our default breakpoint
-         address.  */
-      if (last_displayed_sal_is_valid ())
-	{
-	  struct linespec_sals lsal;
-	  struct symtab_and_line sal;
-	  CORE_ADDR pc;
-
-	  init_sal (&sal);		/* Initialize to zeroes.  */
-	  lsal.sals.sals = (struct symtab_and_line *)
-	    xmalloc (sizeof (struct symtab_and_line));
-
-	  /* Set sal's pspace, pc, symtab, and line to the values
-	     corresponding to the last call to print_frame_info.
-	     Be sure to reinitialize LINE with NOTCURRENT == 0
-	     as the breakpoint line number is inappropriate otherwise.
-	     find_pc_line would adjust PC, re-set it back.  */
-	  get_last_displayed_sal (&sal);
-	  pc = sal.pc;
-	  sal = find_pc_line (pc, 0);
-
-	  /* "break" without arguments is equivalent to "break *PC"
-	     where PC is the last displayed codepoint's address.  So
-	     make sure to set sal.explicit_pc to prevent GDB from
-	     trying to expand the list of sals to include all other
-	     instances with the same symtab and line.  */
-	  sal.pc = pc;
-	  sal.explicit_pc = 1;
-
-	  lsal.sals.sals[0] = sal;
-	  lsal.sals.nelts = 1;
-	  lsal.canonical = NULL;
-
-	  VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+  struct symtab_and_line cursal;
+
+  if (event_location_type (location) == LINESPEC_LOCATION)
+    {
+      const char *address = get_linespec_location (location);
+
+      if (address == NULL)
+	{
+	  /* The last displayed codepoint, if it's valid, is our default
+	     breakpoint address.  */
+	  if (last_displayed_sal_is_valid ())
+	    {
+	      struct linespec_sals lsal;
+	      struct symtab_and_line sal;
+	      CORE_ADDR pc;
+
+	      init_sal (&sal);		/* Initialize to zeroes.  */
+	      lsal.sals.sals = (struct symtab_and_line *)
+		xmalloc (sizeof (struct symtab_and_line));
+
+	      /* Set sal's pspace, pc, symtab, and line to the values
+		 corresponding to the last call to print_frame_info.
+		 Be sure to reinitialize LINE with NOTCURRENT == 0
+		 as the breakpoint line number is inappropriate otherwise.
+		 find_pc_line would adjust PC, re-set it back.  */
+	      get_last_displayed_sal (&sal);
+	      pc = sal.pc;
+	      sal = find_pc_line (pc, 0);
+
+	      /* "break" without arguments is equivalent to "break *PC"
+		 where PC is the last displayed codepoint's address.  So
+		 make sure to set sal.explicit_pc to prevent GDB from
+		 trying to expand the list of sals to include all other
+		 instances with the same symtab and line.  */
+	      sal.pc = pc;
+	      sal.explicit_pc = 1;
+
+	      lsal.sals.sals[0] = sal;
+	      lsal.sals.nelts = 1;
+	      lsal.canonical = NULL;
+
+	      VEC_safe_push (linespec_sals, canonical->sals, &lsal);
+	      return;
+	    }
+	  else
+	    error (_("No default breakpoint address now."));
 	}
-      else
-	error (_("No default breakpoint address now."));
     }
-  else
+
+  /* Force almost all breakpoints to be in terms of the
+     current_source_symtab (which is decode_line_1's default).
+     This should produce the results we want almost all of the
+     time while leaving default_breakpoint_* alone.
+
+     ObjC: However, don't match an Objective-C method name which
+     may have a '+' or '-' succeeded by a '['.  */
+  cursal = get_current_source_symtab_and_line ();
+  if (last_displayed_sal_is_valid ())
     {
-      struct symtab_and_line cursal = get_current_source_symtab_and_line ();
+      const char *address = NULL;
 
-      /* Force almost all breakpoints to be in terms of the
-         current_source_symtab (which is decode_line_1's default).
-         This should produce the results we want almost all of the
-         time while leaving default_breakpoint_* alone.
+      if (event_location_type (location) == LINESPEC_LOCATION)
+	address = get_linespec_location (location);
 
-	 ObjC: However, don't match an Objective-C method name which
-	 may have a '+' or '-' succeeded by a '['.  */
-      if (last_displayed_sal_is_valid ()
-	  && (!cursal.symtab
-	      || ((strchr ("+-", (*address)[0]) != NULL)
-		  && ((*address)[1] != '['))))
-	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
-			  get_last_displayed_symtab (),
-			  get_last_displayed_line (),
-			  canonical, NULL, NULL);
-      else
-	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
-			  cursal.symtab, cursal.line, canonical, NULL, NULL);
+      if (!cursal.symtab
+	  || (address != NULL
+	      && strchr ("+-", address[0]) != NULL
+	      && address[1] != '['))
+	{
+	  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
+			    get_last_displayed_symtab (),
+			    get_last_displayed_line (),
+			    canonical, NULL, NULL);
+	  return;
+	}
     }
+
+  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
+		    cursal.symtab, cursal.line, canonical, NULL, NULL);
 }
 
 
@@ -9527,19 +9585,19 @@  find_condition_and_thread (const char *tok, CORE_ADDR pc,
 /* Decode a static tracepoint marker spec.  */
 
 static struct symtabs_and_lines
-decode_static_tracepoint_spec (char **arg_p)
+decode_static_tracepoint_spec (const char **arg_p)
 {
   VEC(static_tracepoint_marker_p) *markers = NULL;
   struct symtabs_and_lines sals;
   struct cleanup *old_chain;
-  char *p = &(*arg_p)[3];
-  char *endp;
+  const char *p = &(*arg_p)[3];
+  const char *endp;
   char *marker_str;
   int i;
 
-  p = skip_spaces (p);
+  p = skip_spaces_const (p);
 
-  endp = skip_to_space (p);
+  endp = skip_to_space_const (p);
 
   marker_str = savestring (p, endp - p);
   old_chain = make_cleanup (xfree, marker_str);
@@ -9571,22 +9629,13 @@  decode_static_tracepoint_spec (char **arg_p)
   return sals;
 }
 
-/* Set a breakpoint.  This function is shared between CLI and MI
-   functions for setting a breakpoint.  This function has two major
-   modes of operations, selected by the PARSE_ARG parameter.  If
-   non-zero, the function will parse ARG, extracting location,
-   condition, thread and extra string.  Otherwise, ARG is just the
-   breakpoint's location, with condition, thread, and extra string
-   specified by the COND_STRING, THREAD and EXTRA_STRING parameters.
-   If INTERNAL is non-zero, the breakpoint number will be allocated
-   from the internal breakpoint count.  Returns true if any breakpoint
-   was created; false otherwise.  */
+/* See breakpoint.h.  */
 
 int
 create_breakpoint (struct gdbarch *gdbarch,
-		   char *arg, char *cond_string,
+		   const struct event_location *location, char *cond_string,
 		   int thread, char *extra_string,
-		   int parse_arg,
+		   int parse_extra,
 		   int tempflag, enum bptype type_wanted,
 		   int ignore_count,
 		   enum auto_boolean pending_break_support,
@@ -9594,8 +9643,6 @@  create_breakpoint (struct gdbarch *gdbarch,
 		   int from_tty, int enabled, int internal,
 		   unsigned flags)
 {
-  char *copy_arg = NULL;
-  char *addr_start = arg;
   struct linespec_result canonical;
   struct cleanup *old_chain;
   struct cleanup *bkpt_chain = NULL;
@@ -9605,12 +9652,15 @@  create_breakpoint (struct gdbarch *gdbarch,
 
   gdb_assert (ops != NULL);
 
+  /* If extra_string isn't useful, set it to NULL.  */
+  if (extra_string != NULL && *extra_string == '\0')
+    extra_string = NULL;
+
   init_linespec_result (&canonical);
 
   TRY
     {
-      ops->create_sals_from_location (&arg, &canonical, type_wanted,
-				      addr_start, &copy_arg);
+      ops->create_sals_from_location (location, &canonical, type_wanted);
     }
   CATCH (e, RETURN_MASK_ERROR)
     {
@@ -9637,24 +9687,14 @@  create_breakpoint (struct gdbarch *gdbarch,
 	     a pending breakpoint and selected yes, or pending
 	     breakpoint behavior is on and thus a pending breakpoint
 	     is defaulted on behalf of the user.  */
-	  {
-	    struct linespec_sals lsal;
-
-	    copy_arg = xstrdup (addr_start);
-	    lsal.canonical = xstrdup (copy_arg);
-	    lsal.sals.nelts = 1;
-	    lsal.sals.sals = XNEW (struct symtab_and_line);
-	    init_sal (&lsal.sals.sals[0]);
-	    pending = 1;
-	    VEC_safe_push (linespec_sals, canonical.sals, &lsal);
-	  }
+	  pending = 1;
 	}
       else
 	throw_exception (e);
     }
   END_CATCH
 
-  if (VEC_empty (linespec_sals, canonical.sals))
+  if (!pending && VEC_empty (linespec_sals, canonical.sals))
     return 0;
 
   /* Create a chain of things that always need to be cleaned up.  */
@@ -9692,7 +9732,7 @@  create_breakpoint (struct gdbarch *gdbarch,
      breakpoint.  */
   if (!pending)
     {
-      if (parse_arg)
+      if (parse_extra)
         {
 	  char *rest;
 	  struct linespec_sals *lsal;
@@ -9704,19 +9744,22 @@  create_breakpoint (struct gdbarch *gdbarch,
 	     sal is OK.  When setting the breakpoint we'll
 	     re-parse it in context of each sal.  */
 
-	  find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
-				     &thread, &task, &rest);
+	  find_condition_and_thread (extra_string, lsal->sals.sals[0].pc,
+				     &cond_string, &thread, &task, &rest);
 	  if (cond_string)
 	    make_cleanup (xfree, cond_string);
 	  if (rest)
 	    make_cleanup (xfree, rest);
 	  if (rest)
 	    extra_string = rest;
+	  else
+	    extra_string = NULL;
         }
       else
         {
-	  if (*arg != '\0')
-	    error (_("Garbage '%s' at end of location"), arg);
+	  if (type_wanted != bp_dprintf
+	      && extra_string != NULL && *extra_string != '\0')
+		error (_("Garbage '%s' at end of location"), extra_string);
 
 	  /* Create a private copy of condition string.  */
 	  if (cond_string)
@@ -9742,8 +9785,6 @@  create_breakpoint (struct gdbarch *gdbarch,
     {
       struct breakpoint *b;
 
-      make_cleanup (xfree, copy_arg);
-
       if (is_tracepoint_type (type_wanted))
 	{
 	  struct tracepoint *t;
@@ -9755,13 +9796,10 @@  create_breakpoint (struct gdbarch *gdbarch,
 	b = XNEW (struct breakpoint);
 
       init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
+      b->location = copy_event_location (location);
 
-      b->addr_string = copy_arg;
-      if (parse_arg)
-	{
-	  b->cond_string = NULL;
-	  b->extra_string = NULL;
-	}
+      if (parse_extra)
+	b->cond_string = NULL;
       else
 	{
 	  /* Create a private copy of condition string.  */
@@ -9770,16 +9808,17 @@  create_breakpoint (struct gdbarch *gdbarch,
 	      cond_string = xstrdup (cond_string);
 	      make_cleanup (xfree, cond_string);
 	    }
-	  /* Create a private copy of any extra string.  */
-	  if (extra_string != NULL)
-	    {
-	      extra_string = xstrdup (extra_string);
-	      make_cleanup (xfree, extra_string);
-	    }
 	  b->cond_string = cond_string;
-	  b->extra_string = extra_string;
 	  b->thread = thread;
 	}
+
+      /* Create a private copy of any extra string.  */
+      if (extra_string != NULL)
+	{
+	  extra_string = xstrdup (extra_string);
+	  make_cleanup (xfree, extra_string);
+	}
+      b->extra_string = extra_string;
       b->ignore_count = ignore_count;
       b->disposition = tempflag ? disp_del : disp_donttouch;
       b->condition_not_parsed = 1;
@@ -9826,16 +9865,21 @@  break_command_1 (char *arg, int flag, int from_tty)
 			     : bp_breakpoint);
   struct breakpoint_ops *ops;
   const char *arg_cp = arg;
+  struct event_location *location;
+  struct cleanup *cleanup;
+
+  location = string_to_event_location (&arg, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
 
   /* Matching breakpoints on probes.  */
-  if (arg && probe_linespec_to_ops (&arg_cp) != NULL)
+  if (arg_cp != NULL && probe_linespec_to_ops (&arg_cp) != NULL)
     ops = &bkpt_probe_breakpoint_ops;
   else
     ops = &bkpt_breakpoint_ops;
 
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     tempflag, type_wanted,
 		     0 /* Ignore count */,
 		     pending_break_support,
@@ -9844,6 +9888,7 @@  break_command_1 (char *arg, int flag, int from_tty)
 		     1 /* enabled */,
 		     0 /* internal */,
 		     0);
+  do_cleanups (cleanup);
 }
 
 /* Helper function for break_command_1 and disassemble_command.  */
@@ -10010,9 +10055,28 @@  stopat_command (char *arg, int from_tty)
 static void
 dprintf_command (char *arg, int from_tty)
 {
+  struct event_location *location;
+  struct cleanup *cleanup;
+
+  location = string_to_event_location (&arg, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
+
+  /* If non-NULL, ARG should have been advanced past the location;
+     the next character must be ','.  */
+  if (arg != NULL)
+    {
+      if (arg[0] != ',' || arg[1] == '\0')
+	error (_("Format string required"));
+      else
+	{
+	  /* Skip the comma.  */
+	  ++arg;
+	}
+    }
+
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0, bp_dprintf,
 		     0 /* Ignore count */,
 		     pending_break_support,
@@ -10021,6 +10085,7 @@  dprintf_command (char *arg, int from_tty)
 		     1 /* enabled */,
 		     0 /* internal */,
 		     0);
+  do_cleanups (cleanup);
 }
 
 static void
@@ -10165,8 +10230,9 @@  print_mention_ranged_breakpoint (struct breakpoint *b)
 static void
 print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
 {
-  fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string,
-		      b->addr_string_range_end);
+  fprintf_unfiltered (fp, "break-range %s, %s",
+		      event_location_to_string (b->location),
+		      event_location_to_string (b->location_range_end));
   print_recreate_thread (b, fp);
 }
 
@@ -10217,6 +10283,7 @@  break_range_command (char *arg, int from_tty)
   struct symtab_and_line sal_start, sal_end;
   struct cleanup *cleanup_bkpt;
   struct linespec_sals *lsal_start, *lsal_end;
+  struct event_location *start_location, *end_location;
 
   /* We don't support software ranged breakpoints.  */
   if (target_ranged_break_num_registers () < 0)
@@ -10236,9 +10303,10 @@  break_range_command (char *arg, int from_tty)
   init_linespec_result (&canonical_start);
 
   arg_start = arg;
-  parse_breakpoint_sals (&arg, &canonical_start);
-
-  cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start);
+  start_location = string_to_event_location (&arg, current_language);
+  cleanup_bkpt = make_cleanup_delete_event_location (start_location);
+  parse_breakpoint_sals (start_location, &canonical_start);
+  make_cleanup_destroy_linespec_result (&canonical_start);
 
   if (arg[0] != ',')
     error (_("Too few arguments."));
@@ -10268,7 +10336,9 @@  break_range_command (char *arg, int from_tty)
      symtab and line as the default symtab and line for the end of the
      range.  This makes it possible to have ranges like "foo.c:27, +14",
      where +14 means 14 lines from the start location.  */
-  decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE,
+  end_location = string_to_event_location (&arg, current_language);
+  make_cleanup_delete_event_location (end_location);
+  decode_line_full (end_location, DECODE_LINE_FUNFIRSTLINE,
 		    sal_start.symtab, sal_start.line,
 		    &canonical_end, NULL, NULL);
 
@@ -10283,8 +10353,6 @@  break_range_command (char *arg, int from_tty)
     error (_("Cannot create a ranged breakpoint with multiple locations."));
 
   sal_end = lsal_end->sals.sals[0];
-  addr_string_end = savestring (arg_start, arg - arg_start);
-  make_cleanup (xfree, addr_string_end);
 
   end = find_breakpoint_range_end (sal_end);
   if (sal_start.pc > end)
@@ -10311,8 +10379,8 @@  break_range_command (char *arg, int from_tty)
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
   b->disposition = disp_donttouch;
-  b->addr_string = xstrdup (addr_string_start);
-  b->addr_string_range_end = xstrdup (addr_string_end);
+  b->location = copy_event_location (start_location);
+  b->location_range_end = copy_event_location (end_location);
   b->loc->length = length;
 
   do_cleanups (cleanup_bkpt);
@@ -11439,21 +11507,25 @@  until_break_command (char *arg, int from_tty, int anywhere)
   struct frame_id caller_frame_id;
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2 = NULL;
-  struct cleanup *old_chain;
+  struct cleanup *old_chain, *cleanup;
   int thread;
   struct thread_info *tp;
+  struct event_location *location;
 
   clear_proceed_status (0);
 
   /* Set a breakpoint where the user wants it and at return from
      this function.  */
 
+  location = string_to_event_location (&arg, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
+
   if (last_displayed_sal_is_valid ())
-    sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+    sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
 			  get_last_displayed_symtab (),
 			  get_last_displayed_line ());
   else
-    sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+    sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE,
 			  (struct symtab *) NULL, 0);
 
   if (sals.nelts != 1)
@@ -11539,6 +11611,8 @@  until_break_command (char *arg, int from_tty, int anywhere)
     }
   else
     do_cleanups (old_chain);
+
+  do_cleanups (cleanup);
 }
 
 /* This function attempts to parse an optional "if <cond>" clause
@@ -11694,7 +11768,8 @@  init_ada_exception_breakpoint (struct breakpoint *b,
 
   b->enable_state = enabled ? bp_enabled : bp_disabled;
   b->disposition = tempflag ? disp_del : disp_donttouch;
-  b->addr_string = addr_string;
+  b->location = string_to_event_location (&addr_string,
+					  language_def (language_ada));
   b->language = language_ada;
 }
 
@@ -12552,7 +12627,26 @@  say_where (struct breakpoint *b)
      single string.  */
   if (b->loc == NULL)
     {
-      printf_filtered (_(" (%s) pending."), b->addr_string);
+      /* For pending locations, the output differs slightly based
+	 on b->extra_string.  If this is non-NULL, it contains either
+	 a condition or dprintf arguments.  */
+      if (b->extra_string == NULL)
+	{
+	  printf_filtered (_(" (%s) pending."),
+			   event_location_to_string (b->location));
+	}
+      else if (b->type == bp_dprintf)
+	{
+	  printf_filtered (_(" (%s,%s) pending."),
+			   event_location_to_string (b->location),
+			   b->extra_string);
+	}
+      else
+	{
+	  printf_filtered (_(" (%s %s) pending."),
+			   event_location_to_string (b->location),
+			   b->extra_string);
+	}
     }
   else
     {
@@ -12574,7 +12668,8 @@  say_where (struct breakpoint *b)
 	    /* This is not ideal, but each location may have a
 	       different file name, and this at least reflects the
 	       real situation somewhat.  */
-	    printf_filtered (": %s.", b->addr_string);
+	    printf_filtered (": %s.",
+			     event_location_to_string (b->location));
 	}
 
       if (b->loc->next)
@@ -12616,9 +12711,9 @@  base_breakpoint_dtor (struct breakpoint *self)
   decref_counted_command_line (&self->commands);
   xfree (self->cond_string);
   xfree (self->extra_string);
-  xfree (self->addr_string);
   xfree (self->filter);
-  xfree (self->addr_string_range_end);
+  delete_event_location (self->location);
+  delete_event_location (self->location_range_end);
 }
 
 static struct bp_location *
@@ -12711,11 +12806,10 @@  base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
 }
 
 static void
-base_breakpoint_create_sals_from_location (char **arg,
-					   struct linespec_result *canonical,
-					   enum bptype type_wanted,
-					   char *addr_start,
-					   char **copy_arg)
+base_breakpoint_create_sals_from_location
+  (const struct event_location *location,
+   struct linespec_result *canonical,
+   enum bptype type_wanted)
 {
   internal_error_pure_virtual_called ();
 }
@@ -12737,7 +12831,8 @@  base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-base_breakpoint_decode_location (struct breakpoint *b, char **s,
+base_breakpoint_decode_location (struct breakpoint *b,
+				 const struct event_location *location,
 				 struct symtabs_and_lines *sals)
 {
   internal_error_pure_virtual_called ();
@@ -12788,9 +12883,9 @@  static void
 bkpt_re_set (struct breakpoint *b)
 {
   /* FIXME: is this still reachable?  */
-  if (b->addr_string == NULL)
+  if (event_location_empty_p (b->location))
     {
-      /* Anything without a string can't be re-set.  */
+      /* Anything without a location can't be re-set.  */
       delete_breakpoint (b);
       return;
     }
@@ -12942,18 +13037,23 @@  bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
     internal_error (__FILE__, __LINE__,
 		    _("unhandled breakpoint type %d"), (int) tp->type);
 
-  fprintf_unfiltered (fp, " %s", tp->addr_string);
+  fprintf_unfiltered (fp, " %s",
+		      event_location_to_string (tp->location));
+
+  /* Print out extra_string if this breakpoint is pending.  It might
+     contain, for example, conditions that were set by the user.  */
+  if (tp->loc == NULL && tp->extra_string != NULL)
+    fprintf_unfiltered (fp, " %s", tp->extra_string);
+
   print_recreate_thread (tp, fp);
 }
 
 static void
-bkpt_create_sals_from_location (char **arg,
-			       struct linespec_result *canonical,
-			       enum bptype type_wanted,
-			       char *addr_start, char **copy_arg)
+bkpt_create_sals_from_location (const struct event_location *location,
+				struct linespec_result *canonical,
+				enum bptype type_wanted)
 {
-  create_sals_from_location_default (arg, canonical, type_wanted,
-				    addr_start, copy_arg);
+  create_sals_from_location_default (location, canonical, type_wanted);
 }
 
 static void
@@ -12978,10 +13078,11 @@  bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-bkpt_decode_location (struct breakpoint *b, char **s,
+bkpt_decode_location (struct breakpoint *b,
+		      const struct event_location *location,
 		      struct symtabs_and_lines *sals)
 {
-  decode_location_default (b, s, sals);
+  decode_location_default (b, location, sals);
 }
 
 /* Virtual table for internal breakpoints.  */
@@ -13181,26 +13282,23 @@  bkpt_probe_remove_location (struct bp_location *bl)
 }
 
 static void
-bkpt_probe_create_sals_from_location (char **arg,
+bkpt_probe_create_sals_from_location (const struct event_location *location,
 				      struct linespec_result *canonical,
-				      enum bptype type_wanted,
-				      char *addr_start, char **copy_arg)
+				      enum bptype type_wanted)
 {
   struct linespec_sals lsal;
 
-  lsal.sals = parse_probes (arg, canonical);
-
-  *copy_arg = xstrdup (canonical->addr_string);
-  lsal.canonical = xstrdup (*copy_arg);
-
+  lsal.sals = parse_probes (location, canonical);
+  lsal.canonical = xstrdup (event_location_to_string (canonical->location));
   VEC_safe_push (linespec_sals, canonical->sals, &lsal);
 }
 
 static void
-bkpt_probe_decode_location (struct breakpoint *b, char **s,
+bkpt_probe_decode_location (struct breakpoint *b,
+			    const struct event_location *location,
 			    struct symtabs_and_lines *sals)
 {
-  *sals = parse_probes (s, NULL);
+  *sals = parse_probes (location, NULL);
   if (!sals->sals)
     error (_("probe not found"));
 }
@@ -13282,7 +13380,8 @@  tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
     internal_error (__FILE__, __LINE__,
 		    _("unhandled tracepoint type %d"), (int) self->type);
 
-  fprintf_unfiltered (fp, " %s", self->addr_string);
+  fprintf_unfiltered (fp, " %s",
+		      event_location_to_string (self->location));
   print_recreate_thread (self, fp);
 
   if (tp->pass_count)
@@ -13290,13 +13389,11 @@  tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
 }
 
 static void
-tracepoint_create_sals_from_location (char **arg,
-				     struct linespec_result *canonical,
-				     enum bptype type_wanted,
-				     char *addr_start, char **copy_arg)
+tracepoint_create_sals_from_location (const struct event_location *location,
+				      struct linespec_result *canonical,
+				      enum bptype type_wanted)
 {
-  create_sals_from_location_default (arg, canonical, type_wanted,
-				    addr_start, copy_arg);
+  create_sals_from_location_default (location, canonical, type_wanted);
 }
 
 static void
@@ -13321,10 +13418,11 @@  tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-tracepoint_decode_location (struct breakpoint *b, char **s,
+tracepoint_decode_location (struct breakpoint *b,
+			    const struct event_location *location,
 			    struct symtabs_and_lines *sals)
 {
-  decode_location_default (b, s, sals);
+  decode_location_default (b, location, sals);
 }
 
 struct breakpoint_ops tracepoint_breakpoint_ops;
@@ -13333,22 +13431,22 @@  struct breakpoint_ops tracepoint_breakpoint_ops;
    static probe.  */
 
 static void
-tracepoint_probe_create_sals_from_location (char **arg,
-					    struct linespec_result *canonical,
-					    enum bptype type_wanted,
-					    char *addr_start, char **copy_arg)
+tracepoint_probe_create_sals_from_location
+  (const struct event_location *location,
+   struct linespec_result *canonical,
+   enum bptype type_wanted)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_create_sals_from_location (arg, canonical, type_wanted,
-					addr_start, copy_arg);
+  bkpt_probe_create_sals_from_location (location, canonical, type_wanted);
 }
 
 static void
-tracepoint_probe_decode_location (struct breakpoint *b, char **s,
+tracepoint_probe_decode_location (struct breakpoint *b,
+				  const struct event_location *location,
 				  struct symtabs_and_lines *sals)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_decode_location (b, s, sals);
+  bkpt_probe_decode_location (b, location, sals);
 }
 
 static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
@@ -13360,13 +13458,8 @@  dprintf_re_set (struct breakpoint *b)
 {
   breakpoint_re_set_default (b);
 
-  /* This breakpoint could have been pending, and be resolved now, and
-     if so, we should now have the extra string.  If we don't, the
-     dprintf was malformed when created, but we couldn't tell because
-     we can't extract the extra string until the location is
-     resolved.  */
-  if (b->loc != NULL && b->extra_string == NULL)
-    error (_("Format string required"));
+  /* extra_string should never be non-NULL for dprintf.  */
+  gdb_assert (b->extra_string != NULL);
 
   /* 1 - connect to target 1, that can run breakpoint commands.
      2 - create a dprintf, which resolves fine.
@@ -13387,7 +13480,8 @@  dprintf_re_set (struct breakpoint *b)
 static void
 dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
 {
-  fprintf_unfiltered (fp, "dprintf %s%s", tp->addr_string,
+  fprintf_unfiltered (fp, "dprintf %s,%s",
+		      event_location_to_string (tp->location),
 		      tp->extra_string);
   print_recreate_thread (tp, fp);
 }
@@ -13434,19 +13528,24 @@  dprintf_after_condition_true (struct bpstats *bs)
    markers (`-m').  */
 
 static void
-strace_marker_create_sals_from_location (char **arg,
+strace_marker_create_sals_from_location (const struct event_location *location,
 					 struct linespec_result *canonical,
-					 enum bptype type_wanted,
-					 char *addr_start, char **copy_arg)
+					 enum bptype type_wanted)
 {
   struct linespec_sals lsal;
+  const char *arg_start, *arg;
+  char *str;
+  struct cleanup *cleanup;
 
-  lsal.sals = decode_static_tracepoint_spec (arg);
+  arg = arg_start = get_linespec_location (location);
+  lsal.sals = decode_static_tracepoint_spec (&arg);
 
-  *copy_arg = savestring (addr_start, *arg - addr_start);
+  str = savestring (arg_start, arg - arg_start);
+  cleanup = make_cleanup (xfree, str);
+  canonical->location = new_linespec_location (&str);
+  do_cleanups (cleanup);
 
-  canonical->addr_string = xstrdup (*copy_arg);
-  lsal.canonical = xstrdup (*copy_arg);
+  lsal.canonical = xstrdup (event_location_to_string (canonical->location));
   VEC_safe_push (linespec_sals, canonical->sals, &lsal);
 }
 
@@ -13479,17 +13578,17 @@  strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
       struct symtabs_and_lines expanded;
       struct tracepoint *tp;
       struct cleanup *old_chain;
-      char *addr_string;
+      struct event_location *location;
 
       expanded.nelts = 1;
       expanded.sals = &lsal->sals.sals[i];
 
-      addr_string = xstrdup (canonical->addr_string);
-      old_chain = make_cleanup (xfree, addr_string);
+      location = copy_event_location (canonical->location);
+      old_chain = make_cleanup_delete_event_location (location);
 
       tp = XCNEW (struct tracepoint);
       init_breakpoint_sal (&tp->base, gdbarch, expanded,
-			   addr_string, NULL,
+			   location, NULL,
 			   cond_string, extra_string,
 			   type_wanted, disposition,
 			   thread, task, ignore_count, ops,
@@ -13510,12 +13609,14 @@  strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-strace_marker_decode_location (struct breakpoint *b, char **s,
+strace_marker_decode_location (struct breakpoint *b,
+			       const struct event_location *location,
 			       struct symtabs_and_lines *sals)
 {
   struct tracepoint *tp = (struct tracepoint *) b;
+  const char *s = get_linespec_location (location);
 
-  *sals = decode_static_tracepoint_spec (s);
+  *sals = decode_static_tracepoint_spec (&s);
   if (sals->nelts > tp->static_trace_marker_id_idx)
     {
       sals->sals[0] = sals->sals[tp->static_trace_marker_id_idx];
@@ -13847,10 +13948,12 @@  update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 
       if (!VEC_empty(static_tracepoint_marker_p, markers))
 	{
+	  char *p, *tmp;
 	  struct symtab_and_line sal2;
 	  struct symbol *sym;
 	  struct static_tracepoint_marker *tpmarker;
 	  struct ui_out *uiout = current_uiout;
+	  struct cleanup *cleanup;
 
 	  tpmarker = VEC_index (static_tracepoint_marker_p, markers, 0);
 
@@ -13891,10 +13994,13 @@  update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 	  b->loc->line_number = sal2.line;
 	  b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
 
-	  xfree (b->addr_string);
-	  b->addr_string = xstrprintf ("%s:%d",
-				   symtab_to_filename_for_display (sal2.symtab),
-				       b->loc->line_number);
+	  delete_event_location (b->location);
+	  p = tmp = xstrprintf ("%s:%d",
+				symtab_to_filename_for_display (sal2.symtab),
+				b->loc->line_number);
+	  cleanup = make_cleanup (xfree, tmp);
+	  b->location = new_linespec_location (&tmp);
+	  do_cleanups (cleanup);
 
 	  /* Might be nice to check if function changed, and warn if
 	     so.  */
@@ -14051,22 +14157,21 @@  update_breakpoint_locations (struct breakpoint *b,
   update_global_location_list (UGLL_MAY_INSERT);
 }
 
-/* Find the SaL locations corresponding to the given ADDR_STRING.
+/* Find the SaL locations corresponding to the given LOCATION.
    On return, FOUND will be 1 if any SaL was found, zero otherwise.  */
 
 static struct symtabs_and_lines
-location_to_sals (struct breakpoint *b, char *addr_string, int *found)
+location_to_sals (struct breakpoint *b, struct event_location *location,
+		  int *found)
 {
-  char *s;
   struct symtabs_and_lines sals = {0};
   struct gdb_exception exception = exception_none;
 
   gdb_assert (b->ops != NULL);
-  s = addr_string;
 
   TRY
     {
-      b->ops->decode_location (b, &s, &sals);
+      b->ops->decode_location (b, location, &sals);
     }
   CATCH (e, RETURN_MASK_ERROR)
     {
@@ -14108,20 +14213,24 @@  location_to_sals (struct breakpoint *b, char *addr_string, int *found)
 
       for (i = 0; i < sals.nelts; ++i)
 	resolve_sal_pc (&sals.sals[i]);
-      if (b->condition_not_parsed && s && s[0])
+      if (b->condition_not_parsed && b->extra_string != NULL)
 	{
 	  char *cond_string, *extra_string;
 	  int thread, task;
 
-	  find_condition_and_thread (s, sals.sals[0].pc,
+	  find_condition_and_thread (b->extra_string, sals.sals[0].pc,
 				     &cond_string, &thread, &task,
 				     &extra_string);
+	  gdb_assert (b->cond_string == NULL);
 	  if (cond_string)
 	    b->cond_string = cond_string;
 	  b->thread = thread;
 	  b->task = task;
 	  if (extra_string)
-	    b->extra_string = extra_string;
+	    {
+	      xfree (b->extra_string);
+	      b->extra_string = extra_string;
+	    }
 	  b->condition_not_parsed = 0;
 	}
 
@@ -14148,16 +14257,16 @@  breakpoint_re_set_default (struct breakpoint *b)
   struct symtabs_and_lines expanded = {0};
   struct symtabs_and_lines expanded_end = {0};
 
-  sals = location_to_sals (b, b->addr_string, &found);
+  sals = location_to_sals (b, b->location, &found);
   if (found)
     {
       make_cleanup (xfree, sals.sals);
       expanded = sals;
     }
 
-  if (b->addr_string_range_end)
+  if (b->location_range_end != NULL)
     {
-      sals_end = location_to_sals (b, b->addr_string_range_end, &found);
+      sals_end = location_to_sals (b, b->location_range_end, &found);
       if (found)
 	{
 	  make_cleanup (xfree, sals_end.sals);
@@ -14172,12 +14281,11 @@  breakpoint_re_set_default (struct breakpoint *b)
    calls parse_breakpoint_sals.  Return 1 for success, zero for failure.  */
 
 static void
-create_sals_from_location_default (char **arg,
-				  struct linespec_result *canonical,
-				  enum bptype type_wanted,
-				  char *addr_start, char **copy_arg)
+create_sals_from_location_default (const struct event_location *location,
+				   struct linespec_result *canonical,
+				   enum bptype type_wanted)
 {
-  parse_breakpoint_sals (arg, canonical);
+  parse_breakpoint_sals (location, canonical);
 }
 
 /* Call create_breakpoints_sal for the given arguments.  This is the default
@@ -14208,13 +14316,14 @@  create_breakpoints_sal_default (struct gdbarch *gdbarch,
    default function for the `decode_location' method of breakpoint_ops.  */
 
 static void
-decode_location_default (struct breakpoint *b, char **s,
+decode_location_default (struct breakpoint *b,
+			 const struct event_location *location,
 			 struct symtabs_and_lines *sals)
 {
   struct linespec_result canonical;
 
   init_linespec_result (&canonical);
-  decode_line_full (s, DECODE_LINE_FUNFIRSTLINE,
+  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
 		    (struct symtab *) NULL, 0,
 		    &canonical, multiple_symbols_all,
 		    b->filter);
@@ -14886,16 +14995,20 @@  static void
 trace_command (char *arg, int from_tty)
 {
   struct breakpoint_ops *ops;
+  struct event_location *location;
+  struct cleanup *back_to;
   const char *arg_cp = arg;
 
-  if (arg && probe_linespec_to_ops (&arg_cp))
+  location = string_to_event_location (&arg, current_language);
+  back_to = make_cleanup_delete_event_location (location);
+  if (arg_cp != NULL && probe_linespec_to_ops (&arg_cp) != NULL)
     ops = &tracepoint_probe_breakpoint_ops;
   else
     ops = &tracepoint_breakpoint_ops;
 
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -14904,14 +15017,20 @@  trace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 static void
 ftrace_command (char *arg, int from_tty)
 {
+  struct event_location *location;
+  struct cleanup *back_to;
+
+  location = string_to_event_location (&arg, current_language);
+  back_to = make_cleanup_delete_event_location (location);
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_fast_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -14920,6 +15039,7 @@  ftrace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 /* strace command implementation.  Creates a static tracepoint.  */
@@ -14928,17 +15048,26 @@  static void
 strace_command (char *arg, int from_tty)
 {
   struct breakpoint_ops *ops;
+  struct event_location *location;
+  struct cleanup *back_to;
 
   /* Decide if we are dealing with a static tracepoint marker (`-m'),
      or with a normal static tracepoint.  */
   if (arg && startswith (arg, "-m") && isspace (arg[2]))
-    ops = &strace_marker_breakpoint_ops;
+    {
+      ops = &strace_marker_breakpoint_ops;
+      location = new_linespec_location (&arg);
+    }
   else
-    ops = &tracepoint_breakpoint_ops;
+    {
+      ops = &tracepoint_breakpoint_ops;
+      location = string_to_event_location (&arg, current_language);
+    }
 
+  back_to = make_cleanup_delete_event_location (location);
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_static_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -14947,6 +15076,7 @@  strace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 /* Set up a fake reader function that gets command lines from a linked
@@ -14978,6 +15108,8 @@  create_tracepoint_from_upload (struct uploaded_tp *utp)
 {
   char *addr_str, small_buf[100];
   struct tracepoint *tp;
+  struct event_location *location;
+  struct cleanup *cleanup;
 
   if (utp->at_string)
     addr_str = utp->at_string;
@@ -15000,9 +15132,11 @@  create_tracepoint_from_upload (struct uploaded_tp *utp)
 	       "has no source form, ignoring it"),
 	     utp->number);
 
+  location = string_to_event_location (&addr_str, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
   if (!create_breakpoint (get_current_arch (),
-			  addr_str,
-			  utp->cond_string, -1, NULL,
+			  location,
+			  utp->cond_string, -1, addr_str,
 			  0 /* parse cond/thread */,
 			  0 /* tempflag */,
 			  utp->type /* type_wanted */,
@@ -15013,7 +15147,12 @@  create_tracepoint_from_upload (struct uploaded_tp *utp)
 			  utp->enabled /* enabled */,
 			  0 /* internal */,
 			  CREATE_BREAKPOINT_FLAGS_INSERTED))
-    return NULL;
+    {
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  do_cleanups (cleanup);
 
   /* Get the tracepoint we just created.  */
   tp = get_tracepoint (tracepoint_count);
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 4406260..877766a 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -37,6 +37,7 @@  struct bpstats;
 struct bp_location;
 struct linespec_result;
 struct linespec_sals;
+struct event_location;
 
 /* This is the maximum number of bytes a breakpoint instruction can
    take.  Feel free to increase it.  It's just used in a few places to
@@ -580,8 +581,9 @@  struct breakpoint_ops
      `create_sals_from_location_default'.
 
      This function is called inside `create_breakpoint'.  */
-  void (*create_sals_from_location) (char **, struct linespec_result *,
-				     enum bptype, char *, char **);
+  void (*create_sals_from_location) (const struct event_location *location,
+				     struct linespec_result *canonical,
+				     enum bptype type_wanted);
 
   /* This method will be responsible for creating a breakpoint given its SALs.
      Usually, it just calls `create_breakpoints_sal' (for ordinary
@@ -602,8 +604,9 @@  struct breakpoint_ops
      it calls `decode_line_full'.
 
      This function is called inside `location_to_sals'.  */
-  void (*decode_location) (struct breakpoint *, char **,
-			   struct symtabs_and_lines *);
+  void (*decode_location) (struct breakpoint *b,
+			   const struct event_location *location,
+			   struct symtabs_and_lines *sals);
 
   /* Return true if this breakpoint explains a signal.  See
      bpstat_explains_signal.  */
@@ -702,17 +705,17 @@  struct breakpoint
        non-thread-specific ordinary breakpoints this is NULL.  */
     struct program_space *pspace;
 
-    /* String we used to set the breakpoint (malloc'd).  */
-    char *addr_string;
+    /* Location we used to set the breakpoint (malloc'd).  */
+    struct event_location *location;
 
     /* The filter that should be passed to decode_line_full when
        re-setting this breakpoint.  This may be NULL, but otherwise is
        allocated with xmalloc.  */
     char *filter;
 
-    /* For a ranged breakpoint, the string we used to find
+    /* For a ranged breakpoint, the location we used to find
        the end of the range (malloc'd).  */
-    char *addr_string_range_end;
+    struct event_location *location_range_end;
 
     /* Architecture we used to set the breakpoint.  */
     struct gdbarch *gdbarch;
@@ -1293,10 +1296,30 @@  enum breakpoint_create_flags
     CREATE_BREAKPOINT_FLAGS_INSERTED = 1 << 0
   };
 
-extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
+/* Set a breakpoint.  This function is shared between CLI and MI functions
+   for setting a breakpoint at LOCATION.
+
+   This function has two major modes of operations, selected by the
+   PARSE_EXTRA parameter.
+
+   If PARSE_EXTRA is zero, LOCATION is just the breakpoint's location,
+   with condition, thread, and extra string specified by the COND_STRING,
+   THREAD, and EXTRA_STRING parameters.
+
+   If PARSE_EXTRA is non-zero, this function will attempt to extract
+   the condition, thread, and extra string from EXTRA_STRING, ignoring
+   the similarly named parameters.
+
+   If INTERNAL is non-zero, the breakpoint number will be allocated
+   from the internal breakpoint count.
+
+   Returns true if any breakpoint was created; false otherwise.  */
+
+extern int create_breakpoint (struct gdbarch *gdbarch,
+			      const struct event_location *location,
 			      char *cond_string, int thread,
 			      char *extra_string,
-			      int parse_arg,
+			      int parse_extra,
 			      int tempflag, enum bptype wanted_type,
 			      int ignore_count,
 			      enum auto_boolean pending_break_support,
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 2ec2dd3..e9664c9 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -38,6 +38,7 @@ 
 #include "disasm.h"
 #include "tracepoint.h"
 #include "filestuff.h"
+#include "location.h"
 
 #include "ui-out.h"
 
@@ -782,7 +783,6 @@  edit_command (char *arg, int from_tty)
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
   struct symbol *sym;
-  char *arg1;
   char *editor;
   char *p;
   const char *fn;
@@ -804,21 +804,28 @@  edit_command (char *arg, int from_tty)
     }
   else
     {
-      /* Now should only be one argument -- decode it in SAL.  */
+      struct cleanup *cleanup;
+      struct event_location *location;
+      char *arg1;
 
+      /* Now should only be one argument -- decode it in SAL.  */
       arg1 = arg;
-      sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+      location = string_to_event_location (&arg1, current_language);
+      cleanup = make_cleanup_delete_event_location (location);
+      sals = decode_line_1 (location, DECODE_LINE_LIST_MODE, 0, 0);
 
       filter_sals (&sals);
       if (! sals.nelts)
 	{
 	  /*  C++  */
+	  do_cleanups (cleanup);
 	  return;
 	}
       if (sals.nelts > 1)
 	{
 	  ambiguous_line_spec (&sals);
 	  xfree (sals.sals);
+	  do_cleanups (cleanup);
 	  return;
 	}
 
@@ -860,6 +867,7 @@  edit_command (char *arg, int from_tty)
 
       if (sal.symtab == 0)
         error (_("No line number known for %s."), arg);
+      do_cleanups (cleanup);
     }
 
   if ((editor = (char *) getenv ("EDITOR")) == NULL)
@@ -888,6 +896,9 @@  list_command (char *arg, int from_tty)
   int dummy_beg = 0;
   int linenum_beg = 0;
   char *p;
+  struct cleanup *cleanup;
+
+  cleanup = make_cleanup (null_cleanup, NULL);
 
   /* Pull in the current default source line if necessary.  */
   if (arg == 0 || arg[0] == '+' || arg[0] == '-')
@@ -951,15 +962,24 @@  list_command (char *arg, int from_tty)
     dummy_beg = 1;
   else
     {
-      sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+      struct event_location *location;
+
+      location = string_to_event_location (&arg1, current_language);
+      make_cleanup_delete_event_location (location);
+      sals = decode_line_1 (location, DECODE_LINE_LIST_MODE, 0, 0);
 
       filter_sals (&sals);
       if (!sals.nelts)
-	return;			/*  C++  */
+	{
+	  /*  C++  */
+	  do_cleanups (cleanup);
+	  return;
+	}
       if (sals.nelts > 1)
 	{
 	  ambiguous_line_spec (&sals);
 	  xfree (sals.sals);
+	  do_cleanups (cleanup);
 	  return;
 	}
 
@@ -984,18 +1004,28 @@  list_command (char *arg, int from_tty)
 	dummy_end = 1;
       else
 	{
+	  struct event_location *location;
+
+	  location = string_to_event_location (&arg1, current_language);
+	  make_cleanup_delete_event_location (location);
 	  if (dummy_beg)
-	    sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+	    sals_end = decode_line_1 (location,
+				      DECODE_LINE_LIST_MODE, 0, 0);
 	  else
-	    sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE,
+	    sals_end = decode_line_1 (location, DECODE_LINE_LIST_MODE,
 				      sal.symtab, sal.line);
+
 	  filter_sals (&sals_end);
 	  if (sals_end.nelts == 0)
-	    return;
+	    {
+	      do_cleanups (cleanup);
+	      return;
+	    }
 	  if (sals_end.nelts > 1)
 	    {
 	      ambiguous_line_spec (&sals_end);
 	      xfree (sals_end.sals);
+	      do_cleanups (cleanup);
 	      return;
 	    }
 	  sal_end = sals_end.sals[0];
@@ -1076,6 +1106,7 @@  list_command (char *arg, int from_tty)
 			 ? sal.line + get_lines_to_list ()
 			 : sal_end.line + 1),
 			0);
+  do_cleanups (cleanup);
 }
 
 /* Subroutine of disassemble_command to simplify it.
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 0e169c7..1e52515 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -45,6 +45,7 @@ 
 #include "bcache.h"
 #include "gdb_bfd.h"
 #include "build-id.h"
+#include "location.h"
 
 extern void _initialize_elfread (void);
 
@@ -989,7 +990,8 @@  elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
   resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc);
 
   gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
-  elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc);
+  elf_gnu_ifunc_record_cache (event_location_to_string (b->location),
+			      resolved_pc);
 
   sal = find_pc_line (resolved_pc, 0);
   sals.nelts = 1;
diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
index eef8a4b..a7e0fe0 100644
--- a/gdb/guile/scm-breakpoint.c
+++ b/gdb/guile/scm-breakpoint.c
@@ -31,6 +31,7 @@ 
 #include "arch-utils.h"
 #include "language.h"
 #include "guile-internal.h"
+#include "location.h"
 
 /* The <gdb:breakpoint> smob.
    N.B.: The name of this struct is known to breakpoint.h.
@@ -173,6 +174,8 @@  bpscm_print_breakpoint_smob (SCM self, SCM port, scm_print_state *pstate)
   /* Careful, the breakpoint may be invalid.  */
   if (b != NULL)
     {
+      const char *str;
+
       gdbscm_printf (port, " %s %s %s",
 		     bpscm_type_to_string (b->type),
 		     bpscm_enable_state_to_string (b->enable_state),
@@ -181,8 +184,9 @@  bpscm_print_breakpoint_smob (SCM self, SCM port, scm_print_state *pstate)
       gdbscm_printf (port, " hit:%d", b->hit_count);
       gdbscm_printf (port, " ignore:%d", b->ignore_count);
 
-      if (b->addr_string != NULL)
-	gdbscm_printf (port, " @%s", b->addr_string);
+      str = event_location_to_string (b->location);
+      if (str != NULL)
+	gdbscm_printf (port, " @%s", str);
     }
 
   scm_puts (">", port);
@@ -408,6 +412,9 @@  gdbscm_register_breakpoint_x (SCM self)
   breakpoint_smob *bp_smob
     = bpscm_get_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   struct gdb_exception except = exception_none;
+  char *location, *copy;
+  struct event_location *eloc;
+  struct cleanup *cleanup;
 
   /* We only support registering breakpoints created with make-breakpoint.  */
   if (!bp_smob->is_scheme_bkpt)
@@ -417,10 +424,13 @@  gdbscm_register_breakpoint_x (SCM self)
     scm_misc_error (FUNC_NAME, _("breakpoint is already registered"), SCM_EOL);
 
   pending_breakpoint_scm = self;
+  location = bp_smob->spec.location;
+  copy = location;
+  eloc = new_linespec_location (&copy);
+  cleanup = make_cleanup_delete_event_location (eloc);
 
   TRY
     {
-      char *location = bp_smob->spec.location;
       int internal = bp_smob->spec.is_internal;
 
       switch (bp_smob->spec.type)
@@ -428,7 +438,7 @@  gdbscm_register_breakpoint_x (SCM self)
 	case bp_breakpoint:
 	  {
 	    create_breakpoint (get_current_arch (),
-			       location, NULL, -1, NULL,
+			       eloc, NULL, -1, NULL,
 			       0,
 			       0, bp_breakpoint,
 			       0,
@@ -464,6 +474,7 @@  gdbscm_register_breakpoint_x (SCM self)
   /* Ensure this gets reset, even if there's an error.  */
   pending_breakpoint_scm = SCM_BOOL_F;
   GDBSCM_HANDLE_GDB_EXCEPTION (except);
+  do_cleanups (cleanup);
 
   return SCM_UNSPECIFIED;
 }
@@ -819,12 +830,12 @@  gdbscm_breakpoint_location (SCM self)
 {
   breakpoint_smob *bp_smob
     = bpscm_get_valid_breakpoint_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
-  char *str;
+  const char *str;
 
   if (bp_smob->bp->type != bp_breakpoint)
     return SCM_BOOL_F;
 
-  str = bp_smob->bp->addr_string;
+  str = event_location_to_string (bp_smob->bp->location);
   if (! str)
     str = "";
 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 5c4ed3f..7cebe39 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -43,6 +43,7 @@ 
 #include "filenames.h"
 #include "ada-lang.h"
 #include "stack.h"
+#include "location.h"
 
 typedef struct symbol *symbolp;
 DEF_VEC_P (symbolp);
@@ -281,8 +282,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;
@@ -315,7 +316,7 @@  static 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 *);
 
@@ -1785,21 +1786,29 @@  linespec_parse_basic (linespec_parser *parser)
    STATE->canonical.  */
 
 static void
-canonicalize_linespec (struct linespec_state *state, linespec_p ls)
+canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
 {
+  char *tmp;
+
   /* 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);
+    {
+      tmp = ASTRDUP (ls->expression);
+      state->canonical->location = new_linespec_location (&tmp);
+    }
   else
     {
       struct ui_file *buf;
       int need_colon = 0;
+      struct cleanup *cleanup;
 
       buf = mem_fileopen ();
+      cleanup = make_cleanup_ui_file_delete (buf);
+
       if (ls->source_filename)
 	{
 	  fputs_unfiltered (ls->source_filename, buf);
@@ -1848,8 +1857,10 @@  canonicalize_linespec (struct linespec_state *state, linespec_p ls)
 			    ls->line_offset.offset);
 	}
 
-      state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
-      ui_file_delete (buf);
+      tmp = ui_file_xstrdup (buf, NULL);
+      make_cleanup (xfree, tmp);
+      state->canonical->location = new_linespec_location (&tmp);
+      do_cleanups (cleanup);
     }
 }
 
@@ -2117,8 +2128,6 @@  convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 }
 
 /* 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:
 
@@ -2167,10 +2176,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 +2190,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;
 
@@ -2390,6 +2399,7 @@  linespec_parser_new (linespec_parser *parser,
 		     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;
@@ -2443,7 +2453,6 @@  linespec_lex_to_end (char **stringp)
   linespec_parser parser;
   struct cleanup *cleanup;
   linespec_token token;
-  volatile struct gdb_exception e;
   const char *orig;
 
   if (stringp == NULL || *stringp == NULL)
@@ -2483,10 +2492,42 @@  linespec_lex_to_end (char **stringp)
   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:
+      {
+	TRY
+	  {
+	    result = parse_linespec (parser, get_linespec_location (location));
+	  }
+	CATCH (except, RETURN_MASK_ERROR)
+	  {
+	    throw_exception (except);
+	  }
+	END_CATCH
+      }
+      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 symtab *default_symtab,
 		  int default_line, struct linespec_result *canonical,
 		  const char *select_mode,
@@ -2497,7 +2538,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'.  */
@@ -2513,13 +2553,10 @@  decode_line_full (char **argptr, int flags,
   cleanups = make_cleanup (linespec_parser_delete, &parser);
   save_current_program_space ();
 
-  orig = copy = *argptr;
-  result = parse_linespec (&parser, &copy);
-  *argptr += copy - orig;
+  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.  */
@@ -2563,23 +2600,20 @@  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 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,
 		       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;
+  result = event_location_to_sals (&parser, location);
 
   do_cleanups (cleanups);
   return result;
@@ -2592,6 +2626,8 @@  decode_line_with_current_source (char *string, int flags)
 {
   struct symtabs_and_lines sals;
   struct symtab_and_line cursal;
+  struct event_location *location;
+  struct cleanup *cleanup;
 
   if (string == 0)
     error (_("Empty line specification."));
@@ -2600,11 +2636,15 @@  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,
+  location = string_to_event_location (&string, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
+  sals = decode_line_1 (location, flags,
 			cursal.symtab, cursal.line);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
+  do_cleanups (cleanup);
   return sals;
 }
 
@@ -2614,19 +2654,25 @@  struct symtabs_and_lines
 decode_line_with_last_displayed (char *string, int flags)
 {
   struct symtabs_and_lines sals;
+  struct event_location *location;
+  struct cleanup *cleanup;
 
   if (string == 0)
     error (_("Empty line specification."));
 
+  location = string_to_event_location (&string, current_language);
+  cleanup = make_cleanup_delete_event_location (location);
   if (last_displayed_sal_is_valid ())
-    sals = decode_line_1 (&string, flags,
+    sals = decode_line_1 (location, flags,
 			  get_last_displayed_symtab (),
 			  get_last_displayed_line ());
   else
-    sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
+    sals = decode_line_1 (location, flags, (struct symtab *) NULL, 0);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
+  do_cleanups (cleanup);
   return sals;
 }
 
@@ -2679,7 +2725,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;
@@ -2697,7 +2743,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);
@@ -2711,9 +2757,9 @@  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 = 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->function_symbols = info.result.symbols;
@@ -2722,17 +2768,23 @@  decode_objc (struct linespec_state *self, linespec_p ls, const char **argptr)
 
       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);
+	    {
+	      str = xstrprintf ("%s:%s",
+				ls->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;
@@ -3830,7 +3882,7 @@  destroy_linespec_result (struct linespec_result *ls)
   int i;
   struct linespec_sals *lsal;
 
-  xfree (ls->addr_string);
+  delete_event_location (ls->location);
   for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
     {
       xfree (lsal->canonical);
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 77ec46d..840bae5 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -39,7 +39,7 @@  enum decode_line_flags
 
 struct linespec_sals
 {
-  /* This is the linespec corresponding to the sals contained in this
+  /* This is the location corresponding to the sals contained in this
      object.  It can be passed as the FILTER argument to future calls
      to decode_line_full.  This is freed by
      destroy_linespec_result.  */
@@ -71,9 +71,9 @@  struct linespec_result
      object.  */
   int pre_expanded;
 
-  /* If PRE_EXPANDED is non-zero, this is set to the linespec entered
+  /* If PRE_EXPANDED is non-zero, this is set to the location entered
      by the user.  This will be freed by destroy_linespec_result.  */
-  char *addr_string;
+  struct event_location *location;
 
   /* The sals.  The vector will be freed by
      destroy_linespec_result.  */
@@ -96,10 +96,10 @@  extern struct cleanup *
 /* Decode a linespec using the provided default symtab and line.  */
 
 extern struct symtabs_and_lines
-	decode_line_1 (char **argptr, int flags,
+	decode_line_1 (const struct event_location *location, int flags,
 		       struct symtab *default_symtab, int default_line);
 
-/* Parse *ARGPTR as a linespec and return results.  This is the "full"
+/* Parse LOCATION and return results.  This is the "full"
    interface to this module, which handles multiple results
    properly.
 
@@ -135,7 +135,7 @@  extern struct symtabs_and_lines
    strcmp sense) to FILTER will be returned; all others will be
    filtered out.  */
 
-extern void decode_line_full (char **argptr, int flags,
+extern void decode_line_full (const struct event_location *location, int flags,
 			      struct symtab *default_symtab, int default_line,
 			      struct linespec_result *canonical,
 			      const char *select_mode,
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index 186f807..c8c988d 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -28,6 +28,9 @@ 
 #include "observer.h"
 #include "mi-main.h"
 #include "mi-cmd-break.h"
+#include "language.h"
+#include "location.h"
+#include "linespec.h"
 #include "gdb_obstack.h"
 #include <ctype.h>
 
@@ -177,6 +180,7 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   int tracepoint = 0;
   struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
   enum bptype type_wanted;
+  struct event_location *location;
   struct breakpoint_ops *ops;
   char *extra_string = NULL;
 
@@ -287,7 +291,13 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       ops = &bkpt_breakpoint_ops;
     }
 
-  create_breakpoint (get_current_arch (), address, condition, thread,
+  location = string_to_event_location (&address, current_language);
+  make_cleanup_delete_event_location (location);
+
+  if (*address)
+    error (_("Garbage '%s' at end of location"), address);
+
+  create_breakpoint (get_current_arch (), location, condition, thread,
 		     extra_string,
 		     0 /* condition and thread are valid.  */,
 		     temp_p, type_wanted,
diff --git a/gdb/probe.c b/gdb/probe.c
index dce2b25..8366220 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -33,6 +33,7 @@ 
 #include "value.h"
 #include "ax.h"
 #include "ax-gdb.h"
+#include "location.h"
 #include <ctype.h>
 
 typedef struct bound_probe bound_probe_s;
@@ -43,23 +44,24 @@  DEF_VEC_O (bound_probe_s);
 /* See definition in probe.h.  */
 
 struct symtabs_and_lines
-parse_probes (char **argptr, struct linespec_result *canonical)
+parse_probes (const struct event_location *location,
+	      struct linespec_result *canonical)
 {
-  char *arg_start, *arg_end, *arg;
+  char *arg_end, *arg;
   char *objfile_namestr = NULL, *provider = NULL, *name, *p;
   struct cleanup *cleanup;
   struct symtabs_and_lines result;
   struct objfile *objfile;
   struct program_space *pspace;
   const struct probe_ops *probe_ops;
-  const char *cs;
+  const char *arg_start, *cs;
 
   result.sals = NULL;
   result.nelts = 0;
 
-  arg_start = *argptr;
+  arg_start = get_linespec_location (location);
 
-  cs = *argptr;
+  cs = arg_start;
   probe_ops = probe_linespec_to_ops (&cs);
   if (probe_ops == NULL)
     error (_("'%s' is not a probe linespec"), arg_start);
@@ -170,12 +172,15 @@  parse_probes (char **argptr, struct linespec_result *canonical)
 
   if (canonical)
     {
+      char *canon;
+
+      canon = savestring (arg_start, arg_end - arg_start);
+      make_cleanup (xfree, canon);
       canonical->special_display = 1;
       canonical->pre_expanded = 1;
-      canonical->addr_string = savestring (*argptr, arg_end - *argptr);
+      canonical->location = new_linespec_location (&canon);
     }
 
-  *argptr = arg_end;
   do_cleanups (cleanup);
 
   return result;
diff --git a/gdb/probe.h b/gdb/probe.h
index e8d5dfe..c058a38 100644
--- a/gdb/probe.h
+++ b/gdb/probe.h
@@ -20,6 +20,8 @@ 
 #if !defined (PROBE_H)
 #define PROBE_H 1
 
+struct event_location;
+
 #include "gdb_vecs.h"
 
 /* Definition of a vector of probes.  */
@@ -219,9 +221,9 @@  struct bound_probe
   };
 
 /* A helper for linespec that decodes a probe specification.  It returns a
-   symtabs_and_lines object and updates *ARGPTR or throws an error.  */
+   symtabs_and_lines object and updates LOC or throws an error.  */
 
-extern struct symtabs_and_lines parse_probes (char **argptr,
+extern struct symtabs_and_lines parse_probes (const struct event_location *loc,
 					      struct linespec_result *canon);
 
 /* Helper function to register the proper probe_ops to a newly created probe.
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 42a8596..30619dc 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -30,6 +30,7 @@ 
 #include "ada-lang.h"
 #include "arch-utils.h"
 #include "language.h"
+#include "location.h"
 
 /* Number of live breakpoints.  */
 static int bppy_live;
@@ -380,7 +381,7 @@  bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure)
 static PyObject *
 bppy_get_location (PyObject *self, void *closure)
 {
-  char *str;
+  const char *str;
   gdbpy_breakpoint_object *obj = (gdbpy_breakpoint_object *) self;
 
   BPPY_REQUIRE_VALID (obj);
@@ -388,8 +389,7 @@  bppy_get_location (PyObject *self, void *closure)
   if (obj->bp->type != bp_breakpoint)
     Py_RETURN_NONE;
 
-  str = obj->bp->addr_string;
-
+  str = event_location_to_string (obj->bp->location);
   if (! str)
     str = "";
   return PyString_Decode (str, strlen (str), host_charset (), NULL);
@@ -670,8 +670,12 @@  bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 	{
 	case bp_breakpoint:
 	  {
+	    struct event_location *location;
+
+	    location = new_linespec_location (&copy);
+	    make_cleanup_delete_event_location (location);
 	    create_breakpoint (python_gdbarch,
-			       copy, NULL, -1, NULL,
+			       location, NULL, -1, NULL,
 			       0,
 			       temporary_bp, bp_breakpoint,
 			       0,
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index e3d4867..671fd23 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -29,6 +29,7 @@ 
 #include "observer.h"
 #include "inferior.h"
 #include "block.h"
+#include "location.h"
 
 /* Function that is called when a Python finish bp is found out of scope.  */
 static char * const outofscope_func = "out_of_scope";
@@ -169,7 +170,7 @@  bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
   PyObject *internal = NULL;
   int internal_bp = 0;
   CORE_ADDR finish_pc, pc;
-  char *addr_str, small_buf[100];
+  char small_buf[100], *p;
   struct symbol *function;
 
   if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
@@ -296,13 +297,17 @@  bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 
   TRY
     {
+      struct event_location *location;
+      struct cleanup *back_to;
+
       /* Set a breakpoint on the return address.  */
       finish_pc = get_frame_pc (prev_frame);
       xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc));
-      addr_str = small_buf;
-
+      p = small_buf;
+      location = new_linespec_location (&p);
+      back_to = make_cleanup_delete_event_location (location);
       create_breakpoint (python_gdbarch,
-                         addr_str, NULL, thread, NULL,
+                         location, NULL, thread, NULL,
                          0,
                          1 /*temp_flag*/,
                          bp_breakpoint,
@@ -310,6 +315,7 @@  bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
                          AUTO_BOOLEAN_TRUE,
                          &bkpt_breakpoint_ops,
                          0, 1, internal_bp, 0);
+      do_cleanups (back_to);
     }
   CATCH (except, RETURN_MASK_ALL)
     {
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 4f88b0e..c28f98b 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -34,6 +34,7 @@ 
 #include "extension-priv.h"
 #include "cli/cli-utils.h"
 #include <ctype.h>
+#include "location.h"
 
 /* Declared constants and enum for python stack printing.  */
 static const char python_excp_none[] = "none";
@@ -724,12 +725,12 @@  gdbpy_decode_line (PyObject *self, PyObject *args)
   struct symtabs_and_lines sals = { NULL, 0 }; /* Initialize to
 						  appease gcc.  */
   struct symtab_and_line sal;
-  const char *arg = NULL;
-  char *copy_to_free = NULL, *copy = NULL;
+  char *arg = NULL;
   struct cleanup *cleanups;
   PyObject *result = NULL;
   PyObject *return_result = NULL;
   PyObject *unparsed = NULL;
+  struct event_location *location;
 
   if (! PyArg_ParseTuple (args, "|s", &arg))
     return NULL;
@@ -738,14 +739,16 @@  gdbpy_decode_line (PyObject *self, PyObject *args)
 
   sals.sals = NULL;
 
+  if (arg != NULL)
+    {
+      location = new_linespec_location (&arg);
+      make_cleanup_delete_event_location (location);
+    }
+
   TRY
     {
       if (arg)
-	{
-	  copy = xstrdup (arg);
-	  copy_to_free = copy;
-	  sals = decode_line_1 (&copy, 0, 0, 0);
-	}
+	sals = decode_line_1 (location, 0, 0, 0);
       else
 	{
 	  set_default_source_symtab_and_line ();
@@ -761,10 +764,7 @@  gdbpy_decode_line (PyObject *self, PyObject *args)
   END_CATCH
 
   if (sals.sals != NULL && sals.sals != &sal)
-    {
-      make_cleanup (xfree, copy_to_free);
-      make_cleanup (xfree, sals.sals);
-    }
+    make_cleanup (xfree, sals.sals);
 
   if (except.reason < 0)
     {
@@ -808,9 +808,9 @@  gdbpy_decode_line (PyObject *self, PyObject *args)
       goto error;
     }
 
-  if (copy && strlen (copy) > 0)
+  if (arg != NULL && strlen (arg) > 0)
     {
-      unparsed = PyString_FromString (copy);
+      unparsed = PyString_FromString (arg);
       if (unparsed == NULL)
 	{
 	  Py_DECREF (result);
diff --git a/gdb/remote.c b/gdb/remote.c
index 6d577d8..ca1f0df 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -45,6 +45,7 @@ 
 #include "filestuff.h"
 #include "rsp-low.h"
 #include "disasm.h"
+#include "location.h"
 
 #include <sys/time.h>
 
@@ -11242,13 +11243,12 @@  remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
 
   if (packet_support (PACKET_TracepointSource) == PACKET_ENABLE)
     {
-      if (b->addr_string)
+      if (b->location != NULL)
 	{
 	  strcpy (buf, "QTDPsrc:");
-	  encode_source_string (b->number, loc->address,
-				"at", b->addr_string, buf + strlen (buf),
-				2048 - strlen (buf));
-
+	  encode_source_string (b->number, loc->address, "at",
+				event_location_to_string (b->location),
+				buf + strlen (buf), 2048 - strlen (buf));
 	  putpkt (buf);
 	  remote_get_noisy_reply (&target_buf, &target_buf_size);
 	  if (strcmp (target_buf, "OK"))
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index e2cd91f..58d6671 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -45,7 +45,7 @@ 
 #include "dwarf2-frame.h"
 #include "ax.h"
 #include "spu-tdep.h"
-
+#include "location.h"
 
 /* The list of available "set spu " and "show spu " commands.  */
 static struct cmd_list_element *setspucmdlist = NULL;
@@ -1953,8 +1953,10 @@  spu_catch_start (struct objfile *objfile)
 {
   struct bound_minimal_symbol minsym;
   struct compunit_symtab *cust;
+  char buf[32], *p;
   CORE_ADDR pc;
-  char buf[32];
+  struct event_location *location;
+  struct cleanup *back_to;
 
   /* Do this only if requested by "set spu stop-on-load on".  */
   if (!spu_stop_on_load_p)
@@ -1999,7 +2001,10 @@  spu_catch_start (struct objfile *objfile)
   /* Use a numerical address for the set_breakpoint command to avoid having
      the breakpoint re-set incorrectly.  */
   xsnprintf (buf, sizeof buf, "*%s", core_addr_to_string (pc));
-  create_breakpoint (get_objfile_arch (objfile), buf /* arg */,
+  p = buf;
+  location = new_linespec_location (&p);
+  back_to = make_cleanup_delete_event_location (location);
+  create_breakpoint (get_objfile_arch (objfile), location,
 		     NULL /* cond_string */, -1 /* thread */,
 		     NULL /* extra_string */,
 		     0 /* parse_condition_and_thread */, 1 /* tempflag */,
@@ -2008,6 +2013,7 @@  spu_catch_start (struct objfile *objfile)
 		     AUTO_BOOLEAN_FALSE /* pending_break_support */,
 		     &bkpt_breakpoint_ops /* ops */, 0 /* from_tty */,
 		     1 /* enabled */, 0 /* internal  */, 0);
+  do_cleanups (back_to);
 }
 
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 294fbce..5fa6cdd 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,9 @@ 
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+	* gdb.base/dprintf-pending.exp: Update dprintf "without format"
+	test.
+	Add tests for missing ",FMT" and ",".
+
 2015-08-10  Doug Evans  <dje@google.com>
 	    Keith Seitz  <keiths@redhat.com>
 
diff --git a/gdb/testsuite/gdb.base/dprintf-pending.exp b/gdb/testsuite/gdb.base/dprintf-pending.exp
index ad0aa53..953998f 100644
--- a/gdb/testsuite/gdb.base/dprintf-pending.exp
+++ b/gdb/testsuite/gdb.base/dprintf-pending.exp
@@ -41,14 +41,8 @@  with_test_prefix "without format" {
     gdb_start
     gdb_reinitialize_dir $srcdir/$subdir
 
-    gdb_test \
-	"dprintf pendfunc" \
-	"Dprintf.*pendfunc.*pending." \
-	"set pending dprintf" \
-	".*Make dprintf pending.*y or \\\[n\\\]. $" \
-	"y"
-
-    gdb_test "file ${binfile}" ".*Error in re-setting breakpoint.*" "resolved dprintf fails to be re-set"
+    gdb_test "dprintf pendfunc" "Format string required" "missing ,FMT"
+    gdb_test "dprintf pendfunc," "Format string required" "missing FMT"
 }
 
 with_test_prefix "without symbols" {
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 7c04ecb..af553a3 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -55,6 +55,7 @@ 
 #include "filestuff.h"
 #include "rsp-low.h"
 #include "tracefile.h"
+#include "location.h"
 
 /* readline include files */
 #include "readline/readline.h"
@@ -2712,14 +2713,22 @@  scope_info (char *args, int from_tty)
   int j, count = 0;
   struct gdbarch *gdbarch;
   int regno;
+  struct event_location *location;
+  struct cleanup *back_to;
 
   if (args == 0 || *args == 0)
     error (_("requires an argument (function, "
 	     "line or *addr) to define a scope"));
 
-  sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
+  location = string_to_event_location (&args, current_language);
+  back_to = make_cleanup_delete_event_location (location);
+  sals = decode_line_1 (location, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
   if (sals.nelts == 0)
-    return;		/* Presumably decode_line_1 has already warned.  */
+    {
+      /* Presumably decode_line_1 has already warned.  */
+      do_cleanups (back_to);
+      return;
+    }
 
   /* Resolve line numbers to PC.  */
   resolve_sal_pc (&sals.sals[0]);
@@ -2856,6 +2865,7 @@  scope_info (char *args, int from_tty)
   if (count <= 0)
     printf_filtered ("Scope for %s contains no locals or arguments.\n",
 		     save_args);
+  do_cleanups (back_to);
 }
 
 /* Helper for trace_dump_command.  Dump the action list starting at
@@ -3078,7 +3088,7 @@  trace_dump_command (char *args, int from_tty)
 
 extern int
 encode_source_string (int tpnum, ULONGEST addr,
-		      char *srctype, char *src, char *buf, int buf_size)
+		      char *srctype, const char *src, char *buf, int buf_size)
 {
   if (80 + strlen (srctype) > buf_size)
     error (_("Buffer too small for source encoding"));
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index f34be15..549cf61 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -298,7 +298,7 @@  extern struct trace_state_variable *
 extern struct trace_state_variable *create_trace_state_variable (const char *name);
 
 extern int encode_source_string (int num, ULONGEST addr,
-				 char *srctype, char *src,
+				 char *srctype, const char *src,
 				 char *buf, int buf_size);
 
 extern void parse_trace_status (char *line, struct trace_status *ts);



commit a06efdd6effd149a1d392df8d62824e44872003a
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: introduce address locations
    
    This patch adds support for address locations, of the form "*ADDR".
    [Support for address linespecs has been removed/replaced by this "new"
    location type.] This patch also converts any existing address locations
    from its previous linespec type.
    
    gdb/ChangeLog:
    
    	* breakpoint.c (create_thread_event_breakpoint, init_breakpoint_sal):
    	Convert linespec to address location.
    	* linespec.c (canonicalize_linespec): Do not handle address
    	locations here.
    	(convert_address_location_to_sals): New function; contents moved
    	from ...
    	(convert_linespc_to_sals): ... here.
    	(parse_linespec): Remove address locations from linespec grammar.
    	Remove handling of address locations.
    	(linespec_lex_to_end): Remove handling of address linespecs.
    	(event_location_to_sals): Handle ADDRESS_LOCATION.
    	(linespec_expression_to_pc): Export.
    	* linespec.h (linespec_expression_to_pc): Add declaration.
    	* location.c (struct event_location.u) <address>: New member.
    	(new_address_location, get_address_location): New functions.
    	(copy_event_location, delete_event_location, event_location_to_string)
    	(string_to_event_location, event_location_empty_p): Handle address
    	locations.
    	* location.h (enum event_location_type): Add ADDRESS_LOCATION.
    	(new_address_location, get_address_location): Declare.
    	* python/py-finishbreakpoint.c (bpfinishpy_init): Convert linespec
    	to address location.
    	* spu-tdep.c (spu_catch_start): Likewise.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index f6dc1b6..97da8c5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,31 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* breakpoint.c (create_thread_event_breakpoint, init_breakpoint_sal):
+	Convert linespec to address location.
+	* linespec.c (canonicalize_linespec): Do not handle address
+	locations here.
+	(convert_address_location_to_sals): New function; contents moved
+	from ...
+	(convert_linespc_to_sals): ... here.
+	(parse_linespec): Remove address locations from linespec grammar.
+	Remove handling of address locations.
+	(linespec_lex_to_end): Remove handling of address linespecs.
+	(event_location_to_sals): Handle ADDRESS_LOCATION.
+	(linespec_expression_to_pc): Export.
+	* linespec.h (linespec_expression_to_pc): Add declaration.
+	* location.c (struct event_location.u) <address>: New member.
+	(new_address_location, get_address_location): New functions.
+	(copy_event_location, delete_event_location, event_location_to_string)
+	(string_to_event_location, event_location_empty_p): Handle address
+	locations.
+	* location.h (enum event_location_type): Add ADDRESS_LOCATION.
+	(new_address_location, get_address_location): Declare.
+	* python/py-finishbreakpoint.c (bpfinishpy_init): Convert linespec
+	to address location.
+	* spu-tdep.c (spu_catch_start): Likewise.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* ax-gdb.c: Include location.h.
 	(agent_command_1) Use linespec location instead of address
 	string.
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 395da1f..b05c93a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -7660,19 +7660,14 @@  delete_std_terminate_breakpoint (void)
 struct breakpoint *
 create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 {
-  char *tmp;
   struct breakpoint *b;
-  struct cleanup *cleanup;
 
   b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
 				  &internal_breakpoint_ops);
 
   b->enable_state = bp_enabled;
   /* location has to be used or breakpoint_re_set will delete me.  */
-  tmp = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
-  cleanup = make_cleanup (xfree, tmp);
-  b->location = new_linespec_location (&tmp);
-  do_cleanups (cleanup);
+  b->location = new_address_location (b->loc->address);
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
@@ -9244,16 +9239,7 @@  init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
   if (location != NULL)
     b->location = location;
   else
-    {
-      char *tmp;
-      struct cleanup *cleanup;
-
-      tmp = xstrprintf ("*%s",
-			    paddress (b->loc->gdbarch, b->loc->address));
-      cleanup = make_cleanup (xfree, tmp);
-      b->location = new_linespec_location (&tmp);
-      do_cleanups (cleanup);
-   }
+    b->location = new_address_location (b->loc->address);
   b->filter = filter;
 }
 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7cebe39..65c55df 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -312,7 +312,7 @@  static void iterate_over_file_blocks (struct symtab *symtab,
 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,
@@ -1789,79 +1789,69 @@  static void
 canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
 {
   char *tmp;
+  struct ui_file *buf;
+  int need_colon = 0;
+  struct cleanup *cleanup;
 
   /* 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)
+  buf = mem_fileopen ();
+  cleanup = make_cleanup_ui_file_delete (buf);
+
+  if (ls->source_filename)
     {
-      tmp = ASTRDUP (ls->expression);
-      state->canonical->location = new_linespec_location (&tmp);
+      fputs_unfiltered (ls->source_filename, buf);
+      need_colon = 1;
     }
-  else
-    {
-      struct ui_file *buf;
-      int need_colon = 0;
-      struct cleanup *cleanup;
 
-      buf = mem_fileopen ();
-      cleanup = make_cleanup_ui_file_delete (buf);
+  if (ls->function_name)
+    {
+      if (need_colon)
+	fputc_unfiltered (':', buf);
+      fputs_unfiltered (ls->function_name, buf);
+      need_colon = 1;
+    }
 
-      if (ls->source_filename)
-	{
-	  fputs_unfiltered (ls->source_filename, buf);
-	  need_colon = 1;
-	}
+  if (ls->label_name)
+    {
+      if (need_colon)
+	fputc_unfiltered (':', buf);
 
-      if (ls->function_name)
+      if (ls->function_name == NULL)
 	{
-	  if (need_colon)
-	    fputc_unfiltered (':', buf);
-	  fputs_unfiltered (ls->function_name, buf);
-	  need_colon = 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);
+	  fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
+	  fputc_unfiltered (':', buf);
 	}
 
-      if (ls->label_name)
-	{
-	  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;
-	}
-
-      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);
-	}
+      fputs_unfiltered (ls->label_name, buf);
+      need_colon = 1;
+      state->canonical->special_display = 1;
+    }
 
-      tmp = ui_file_xstrdup (buf, NULL);
-      make_cleanup (xfree, tmp);
-      state->canonical->location = new_linespec_location (&tmp);
-      do_cleanups (cleanup);
+  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);
     }
+
+  tmp = ui_file_xstrdup (buf, NULL);
+  make_cleanup (xfree, tmp);
+  state->canonical->location = new_linespec_location (&tmp);
+  do_cleanups (cleanup);
 }
 
 /* Given a line offset in LS, construct the relevant SALs.  */
@@ -2015,6 +2005,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
@@ -2022,18 +2030,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;
@@ -2131,8 +2128,7 @@  convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
    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
@@ -2223,33 +2219,7 @@  parse_linespec (linespec_parser *parser, const char *arg)
   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;
 
@@ -2470,20 +2440,6 @@  linespec_lex_to_end (char **stringp)
       token = linespec_lexer_peek_token (&parser);
       if (token.type == LSTOKEN_COMMA)
 	break;
-
-      /* For addresses advance the parser stream past
-	 any parsed input and stop lexing.  */
-      if (token.type == LSTOKEN_STRING
-	  && *LS_TOKEN_STOKEN (token).ptr == '*')
-	{
-	  const char *arg;
-
-	  arg = *stringp;
-	  (void) linespec_expression_to_pc (&arg);
-	  PARSER_STREAM (&parser) = arg;
-	  break;
-	}
-
       token = linespec_lexer_consume_token (&parser);
     }
   while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
@@ -2517,6 +2473,12 @@  event_location_to_sals (linespec_parser *parser,
       }
       break;
 
+    case ADDRESS_LOCATION:
+      result
+	= convert_address_location_to_sals (PARSER_STATE (parser),
+					    get_address_location (location));
+      break;
+
     default:
       gdb_assert_not_reached ("unhandled event location type");
     }
@@ -2702,7 +2664,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)
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 840bae5..391ed26 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -161,4 +161,9 @@  extern const char *linespec_lexer_lex_keyword (const char *p);
    STRINGP will be advanced to this point.  */
 
 extern void linespec_lex_to_end (char **stringp);
+
+/* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR,
+   advancing EXP_PTR past any parsed text.  */
+
+extern CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
 #endif /* defined (LINESPEC_H) */
diff --git a/gdb/location.c b/gdb/location.c
index 44f3dc6..eea88fa 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -45,6 +45,10 @@  struct event_location
        probes.  */
     char *addr_string;
 #define EL_LINESPEC(PTR) ((PTR)->u.addr_string)
+
+    /* An address in the inferior.  */
+    CORE_ADDR address;
+#define EL_ADDRESS(PTR) (PTR)->u.address
   } u;
 
   /* Cached string representation of this location.  This is used, e.g., to
@@ -95,6 +99,28 @@  get_linespec_location (const struct event_location *location)
 /* See description in location.h.  */
 
 struct event_location *
+new_address_location (CORE_ADDR addr)
+{
+  struct event_location *location;
+
+  location = XCNEW (struct event_location);
+  EL_TYPE (location) = ADDRESS_LOCATION;
+  EL_ADDRESS (location) = addr;
+  return location;
+}
+
+/* See description in location.h.  */
+
+CORE_ADDR
+get_address_location (const struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == ADDRESS_LOCATION);
+  return EL_ADDRESS (location);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
 copy_event_location (const struct event_location *src)
 {
   struct event_location *dst;
@@ -111,6 +137,10 @@  copy_event_location (const struct event_location *src)
 	EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src));
       break;
 
+    case ADDRESS_LOCATION:
+      EL_ADDRESS (dst) = EL_ADDRESS (src);
+      break;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
@@ -151,6 +181,10 @@  delete_event_location (struct event_location *location)
 	  xfree (EL_LINESPEC (location));
 	  break;
 
+	case ADDRESS_LOCATION:
+	  /* Nothing to do.  */
+	  break;
+
 	default:
 	  gdb_assert_not_reached ("unknown event location type");
 	}
@@ -173,6 +207,12 @@  event_location_to_string (struct event_location *location)
 	    EL_STRING (location) = xstrdup (EL_LINESPEC (location));
 	  break;
 
+	case ADDRESS_LOCATION:
+	  EL_STRING (location)
+	    = xstrprintf ("*%s",
+			  core_addr_to_string (EL_ADDRESS (location)));
+	  break;
+
 	default:
 	  gdb_assert_not_reached ("unknown event location type");
 	}
@@ -189,7 +229,23 @@  string_to_event_location (char **stringp,
 {
   struct event_location *location;
 
-  location = new_linespec_location (stringp);
+  /* First, check if the string is an address location.  */
+  if (*stringp != NULL && **stringp == '*')
+    {
+      const char *arg, *orig;
+      CORE_ADDR addr;
+
+      orig = arg = *stringp;
+      addr = linespec_expression_to_pc (&arg);
+      location = new_address_location (addr);
+      *stringp += arg - orig;
+    }
+  else
+    {
+      /* Everything else is a linespec.  */
+      location = new_linespec_location (stringp);
+    }
+
   return location;
 }
 
@@ -204,6 +260,9 @@  event_location_empty_p (const struct event_location *location)
       /* Linespecs are never "empty."  (NULL is a valid linespec)  */
       return 0;
 
+    case ADDRESS_LOCATION:
+      return 0;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
diff --git a/gdb/location.h b/gdb/location.h
index d35fecb..7b9741b 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -28,7 +28,10 @@  struct event_location;
 enum event_location_type
 {
   /* A traditional linespec.  */
-  LINESPEC_LOCATION
+  LINESPEC_LOCATION,
+
+  /* An address in the inferior.  */
+  ADDRESS_LOCATION
 };
 
 /* Return the type of the given event location.  */
@@ -57,6 +60,18 @@  extern struct event_location *
 extern const char *
   get_linespec_location (const struct event_location *location);
 
+/* Create a new address location.  The return result is malloc'd
+   and should be freed with delete_event_location.  */
+
+extern struct event_location *
+  new_address_location (CORE_ADDR addr);
+
+/* Return the address location (a CORE_ADDR) of the given event_location
+   (which must be of type ADDRESS_LOCATION).  */
+
+extern CORE_ADDR
+  get_address_location (const struct event_location *location);
+
 /* Free an event location and any associated data.  */
 
 extern void delete_event_location (struct event_location *location);
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 671fd23..e543bb3 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -169,8 +169,7 @@  bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
   struct frame_id frame_id;
   PyObject *internal = NULL;
   int internal_bp = 0;
-  CORE_ADDR finish_pc, pc;
-  char small_buf[100], *p;
+  CORE_ADDR pc;
   struct symbol *function;
 
   if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
@@ -301,10 +300,7 @@  bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
       struct cleanup *back_to;
 
       /* Set a breakpoint on the return address.  */
-      finish_pc = get_frame_pc (prev_frame);
-      xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc));
-      p = small_buf;
-      location = new_linespec_location (&p);
+      location = new_address_location (get_frame_pc (prev_frame));
       back_to = make_cleanup_delete_event_location (location);
       create_breakpoint (python_gdbarch,
                          location, NULL, thread, NULL,
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 58d6671..75372df 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -1953,7 +1953,6 @@  spu_catch_start (struct objfile *objfile)
 {
   struct bound_minimal_symbol minsym;
   struct compunit_symtab *cust;
-  char buf[32], *p;
   CORE_ADDR pc;
   struct event_location *location;
   struct cleanup *back_to;
@@ -2000,9 +1999,7 @@  spu_catch_start (struct objfile *objfile)
 
   /* Use a numerical address for the set_breakpoint command to avoid having
      the breakpoint re-set incorrectly.  */
-  xsnprintf (buf, sizeof buf, "*%s", core_addr_to_string (pc));
-  p = buf;
-  location = new_linespec_location (&p);
+  location = new_address_location (pc);
   back_to = make_cleanup_delete_event_location (location);
   create_breakpoint (get_objfile_arch (objfile), location,
 		     NULL /* cond_string */, -1 /* thread */,



commit 5b56227bdc000d129d393772f1e4544b5ea0fd46
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: introduce probe locations
    
    This patch adds support for probe locations and converts existing
    probe linespec locations to the new location type.
    
    gdb/ChangeLog:
    
    	* break-catch-throw.c (re_set_exception_catchpoint): Convert
    	linespec for stap probe to probe location.
    	* breakpoint.c (create_longjmp_master_breakpoint)
    	(create_exception_master_breakpoint): Likewise.
    	(break_command_1): Remove local variable `arg_cp'.
    	Check location type to set appropriate breakpoint ops methods.
    	(trace_command): Likewise.
    	* linespec.c (event_location_to_sals): Assert on probe locations.
    	* location.c (EL_PROBE): Add macro definition.
    	(new_probe_location, get_probe_location): New functions.
    	(copy_event_location, delete_event_location, event_location_to_string)
    	(string_to_event_location, event_location_empty_p): Handle probe
    	locations.
    	* location.h (enum event_location_type): Add PROBE_LOCATION.
    	(new_probe_location, get_probe_location): Declare.
    	* probe.c (parse_probes): Assert that LOCATION is a probe location.
    	Convert linespec into probe location.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 97da8c5..efb0587 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,25 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* break-catch-throw.c (re_set_exception_catchpoint): Convert
+	linespec for stap probe to probe location.
+	* breakpoint.c (create_longjmp_master_breakpoint)
+	(create_exception_master_breakpoint): Likewise.
+	(break_command_1): Remove local variable `arg_cp'.
+	Check location type to set appropriate breakpoint ops methods.
+	(trace_command): Likewise.
+	* linespec.c (event_location_to_sals): Assert on probe locations.
+	* location.c (EL_PROBE): Add macro definition.
+	(new_probe_location, get_probe_location): New functions.
+	(copy_event_location, delete_event_location, event_location_to_string)
+	(string_to_event_location, event_location_empty_p): Handle probe
+	locations.
+	* location.h (enum event_location_type): Add PROBE_LOCATION.
+	(new_probe_location, get_probe_location): Declare.
+	* probe.c (parse_probes): Assert that LOCATION is a probe location.
+	Convert linespec into probe location.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* breakpoint.c (create_thread_event_breakpoint, init_breakpoint_sal):
 	Convert linespec to address location.
 	* linespec.c (canonicalize_linespec): Do not handle address
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 9449aa5..07a8f05 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -216,9 +216,8 @@  re_set_exception_catchpoint (struct breakpoint *self)
   /* We first try to use the probe interface.  */
   TRY
     {
-      char *spec = ASTRDUP (exception_functions[kind].probe);
-
-      location = new_linespec_location (&spec);
+      location
+	= new_probe_location (exception_functions[kind].probe);
       cleanup = make_cleanup_delete_event_location (location);
       sals = parse_probes (location, NULL);
       do_cleanups (cleanup);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b05c93a..0597688 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3517,7 +3517,6 @@  create_longjmp_master_breakpoint (void)
 	  int i;
 	  struct probe *probe;
 	  struct gdbarch *gdbarch = get_objfile_arch (objfile);
-	  char *p;
 
 	  for (i = 0;
 	       VEC_iterate (probe_p,
@@ -3532,8 +3531,8 @@  create_longjmp_master_breakpoint (void)
 								 objfile),
 					      bp_longjmp_master,
 					      &internal_breakpoint_ops);
-	      p = ASTRDUP ("-probe-stap libc:longjmp");
-	      b->location = new_linespec_location (&p);
+	      b->location
+		= new_probe_location ("-probe-stap libc:longjmp");
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -3695,15 +3694,14 @@  create_exception_master_breakpoint (void)
 	       ++i)
 	    {
 	      struct breakpoint *b;
-	      char *p;
 
 	      b = create_internal_breakpoint (gdbarch,
 					      get_probe_address (probe,
 								 objfile),
 					      bp_exception_master,
 					      &internal_breakpoint_ops);
-	      p = ASTRDUP ("-probe-stap libgcc:unwind");
-	      b->location = new_linespec_location (&p);
+	      b->location
+		= new_probe_location ("-probe-stap libgcc:unwind");
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -9850,7 +9848,6 @@  break_command_1 (char *arg, int flag, int from_tty)
 			     ? bp_hardware_breakpoint
 			     : bp_breakpoint);
   struct breakpoint_ops *ops;
-  const char *arg_cp = arg;
   struct event_location *location;
   struct cleanup *cleanup;
 
@@ -9858,7 +9855,8 @@  break_command_1 (char *arg, int flag, int from_tty)
   cleanup = make_cleanup_delete_event_location (location);
 
   /* Matching breakpoints on probes.  */
-  if (arg_cp != NULL && probe_linespec_to_ops (&arg_cp) != NULL)
+  if (location != NULL
+      && event_location_type (location) == PROBE_LOCATION)
     ops = &bkpt_probe_breakpoint_ops;
   else
     ops = &bkpt_breakpoint_ops;
@@ -14983,11 +14981,11 @@  trace_command (char *arg, int from_tty)
   struct breakpoint_ops *ops;
   struct event_location *location;
   struct cleanup *back_to;
-  const char *arg_cp = arg;
 
   location = string_to_event_location (&arg, current_language);
   back_to = make_cleanup_delete_event_location (location);
-  if (arg_cp != NULL && probe_linespec_to_ops (&arg_cp) != NULL)
+  if (location != NULL
+      && event_location_type (location) == PROBE_LOCATION)
     ops = &tracepoint_probe_breakpoint_ops;
   else
     ops = &tracepoint_breakpoint_ops;
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 65c55df..8a7640b 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2479,6 +2479,11 @@  event_location_to_sals (linespec_parser *parser,
 					    get_address_location (location));
       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");
     }
diff --git a/gdb/location.c b/gdb/location.c
index eea88fa..fd35c48 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -45,6 +45,7 @@  struct event_location
        probes.  */
     char *addr_string;
 #define EL_LINESPEC(PTR) ((PTR)->u.addr_string)
+#define EL_PROBE(PTR) ((PTR)->u.addr_string)
 
     /* An address in the inferior.  */
     CORE_ADDR address;
@@ -121,6 +122,29 @@  get_address_location (const struct event_location *location)
 /* See description in location.h.  */
 
 struct event_location *
+new_probe_location (const char *probe)
+{
+  struct event_location *location;
+
+  location = XCNEW (struct event_location);
+  EL_TYPE (location) = PROBE_LOCATION;
+  if (probe != NULL)
+    EL_PROBE (location) = xstrdup (probe);
+  return location;
+}
+
+/* See description in location.h.  */
+
+const char *
+get_probe_location (const struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == PROBE_LOCATION);
+  return EL_PROBE (location);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
 copy_event_location (const struct event_location *src)
 {
   struct event_location *dst;
@@ -141,6 +165,11 @@  copy_event_location (const struct event_location *src)
       EL_ADDRESS (dst) = EL_ADDRESS (src);
       break;
 
+    case PROBE_LOCATION:
+      if (EL_PROBE (src) != NULL)
+	EL_PROBE (dst) = xstrdup (EL_PROBE (src));
+      break;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
@@ -185,6 +214,10 @@  delete_event_location (struct event_location *location)
 	  /* Nothing to do.  */
 	  break;
 
+	case PROBE_LOCATION:
+	  xfree (EL_PROBE (location));
+	  break;
+
 	default:
 	  gdb_assert_not_reached ("unknown event location type");
 	}
@@ -213,6 +246,10 @@  event_location_to_string (struct event_location *location)
 			  core_addr_to_string (EL_ADDRESS (location)));
 	  break;
 
+	case PROBE_LOCATION:
+	  EL_STRING (location) = xstrdup (EL_PROBE (location));
+	  break;
+
 	default:
 	  gdb_assert_not_reached ("unknown event location type");
 	}
@@ -242,8 +279,20 @@  string_to_event_location (char **stringp,
     }
   else
     {
-      /* Everything else is a linespec.  */
-      location = new_linespec_location (stringp);
+      const char *cs;
+
+      /* Next, try the input as a probe spec.  */
+      cs = *stringp;
+      if (cs != NULL && probe_linespec_to_ops (&cs) != NULL)
+	{
+	  location = new_probe_location (*stringp);
+	  *stringp += strlen (*stringp);
+	}
+      else
+	{
+	  /* Everything else is a linespec.  */
+	  location = new_linespec_location (stringp);
+	}
     }
 
   return location;
@@ -263,6 +312,9 @@  event_location_empty_p (const struct event_location *location)
     case ADDRESS_LOCATION:
       return 0;
 
+    case PROBE_LOCATION:
+      return EL_PROBE (location) == NULL;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
diff --git a/gdb/location.h b/gdb/location.h
index 7b9741b..63318ba 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -31,7 +31,10 @@  enum event_location_type
   LINESPEC_LOCATION,
 
   /* An address in the inferior.  */
-  ADDRESS_LOCATION
+  ADDRESS_LOCATION,
+
+  /* A probe location.  */
+  PROBE_LOCATION
 };
 
 /* Return the type of the given event location.  */
@@ -72,6 +75,18 @@  extern struct event_location *
 extern CORE_ADDR
   get_address_location (const struct event_location *location);
 
+/* Create a new probe location.  The return result is malloc'd
+   and should be freed with delete_event_location.  */
+
+extern struct event_location *
+  new_probe_location (const char *probe);
+
+/* Return the probe location (a string) of the given event_location
+   (which must be of type PROBE_LOCATION).  */
+
+extern const char *
+  get_probe_location (const struct event_location *location);
+
 /* Free an event location and any associated data.  */
 
 extern void delete_event_location (struct event_location *location);
diff --git a/gdb/probe.c b/gdb/probe.c
index 8366220..a3cfefe 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -59,7 +59,8 @@  parse_probes (const struct event_location *location,
   result.sals = NULL;
   result.nelts = 0;
 
-  arg_start = get_linespec_location (location);
+  gdb_assert (event_location_type (location) == PROBE_LOCATION);
+  arg_start = get_probe_location (location);
 
   cs = arg_start;
   probe_ops = probe_linespec_to_ops (&cs);
@@ -178,7 +179,7 @@  parse_probes (const struct event_location *location,
       make_cleanup (xfree, canon);
       canonical->special_display = 1;
       canonical->pre_expanded = 1;
-      canonical->location = new_linespec_location (&canon);
+      canonical->location = new_probe_location (canon);
     }
 
   do_cleanups (cleanup);



commit 00e52e5376c7ec604a739e6242e6be36221162d7
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:35 2015 -0700

    Explicit locations: introduce explicit locations
    
    This patch add support for explicit locations and switches many linespec
    locations to this new location type.  This patch also converts all
    linespec locations entered by the user to an explicit representation
    internally (thus bypassing the linespec parser when resetting the
    breakpoint).
    
    This patch does not introduce any user-visible changes.
    
    
    gdb/ChangeLog:
    
    	* break-catch-throw.c (re_set_exception_catchpoint): Convert
    	linespec into explicit location.
    	* breakpoint.c (create_overlay_breakpoint)
    	(create_longjmp_master_breakpoint)
    	(create_std_terminate_master_breakpoint)
    	(create_exception_master_breakpoint): Convert linespec into explicit
    	location.
    	(update_static_tracepoint): Convert linespec into explicit location.
    	* linespec.c (enum offset_relative_sign, struct line_offset): Move
    	location.h.
    	(struct linespec) <expression, expr_pc, source_filename>
    	<function_name, label_name, line_offset>: Replace with ...
    	<explicit>: ... this.
    	<is_linespec>: New member.
    	(PARSER_EXPLICIT): New accessor macro.
    	(undefined_label_error): New function.
    	(source_file_not_found_error): New function.
    	(linespec_parse_basic): The parser result is now an explicit location.
    	Use PARSER_EXPLICIT to access it.
    	Use undefined_label_error.
    	(canonicalize_linespec): Convert canonical linespec into explicit
    	location.
    	Move string representation of location to explicit_location_to_linespec
    	and use it and explicit_location_to_string to save string
    	representations of the canonical location.
    	(create_sals_line_offset, convert_linespec_to_sals): `ls' contains an
    	explicit location.  Update all references.
    	(convert_explicit_location_to_sals): New function.
    	(parse_linespec): Use PARSER_EXPLICIT to access the parser
    	result's explicit location.
    	(linespec_state_constructor): Initialize is_linespec.
    	Use PARSER_EXPLICIT.
    	(linespec_parser_delete): Use PARSER_EXPLICIT to access the parser's
    	result.
    	(event_location_to_sals): For linespec locations, set is_linespec.
    	Handle explicit locations.
    	(decode_objc): 'ls' contains an explicit location now. Update all
    	references.
    	(symtabs_from_filename): Use source_file_not_found_error.
    	* location.c (struct event_location.u) <explicit>: New member.
    	(initialize_explicit_location): New function.
    	(initialize_event_location): Initialize explicit locations.
    	(new_explicit_location, get_explicit_location)
    	(get_explicit_location_const): New functions.
    	(explicit_to_string_internal): New function; most of contents moved
    	from canonicalize_linespec.
    	(explicit_location_to_string): New function.
    	(explicit_location_to_linespec): New function.
    	(copy_event_location, delete_event_location)
    	(event_location_to_string_const, event_location_empty_p): Handle
    	explicit locations.
    	* location.h (enum offset_relative_sign, struct line_offset): Move
    	here from linespec.h.
    	(enum event_location_type): Add EXPLICIT_LOCATION.
    	(struct explicit_location): New structure.
    	(explicit_location_to_string): Declare.
    	(explicit_location_to_linespec): Declare.
    	(new_explicit_location, get_explicit_locationp
    	(get_explicit_location_const, initialize_explicit_location): Declare.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index efb0587..13d31a6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,68 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
 	* break-catch-throw.c (re_set_exception_catchpoint): Convert
+	linespec into explicit location.
+	* breakpoint.c (create_overlay_breakpoint)
+	(create_longjmp_master_breakpoint)
+	(create_std_terminate_master_breakpoint)
+	(create_exception_master_breakpoint): Convert linespec into explicit
+	location.
+	(update_static_tracepoint): Convert linespec into explicit location.
+	* linespec.c (enum offset_relative_sign, struct line_offset): Move
+	location.h.
+	(struct linespec) <expression, expr_pc, source_filename>
+	<function_name, label_name, line_offset>: Replace with ...
+	<explicit>: ... this.
+	<is_linespec>: New member.
+	(PARSER_EXPLICIT): New accessor macro.
+	(undefined_label_error): New function.
+	(source_file_not_found_error): New function.
+	(linespec_parse_basic): The parser result is now an explicit location.
+	Use PARSER_EXPLICIT to access it.
+	Use undefined_label_error.
+	(canonicalize_linespec): Convert canonical linespec into explicit
+	location.
+	Move string representation of location to explicit_location_to_linespec
+	and use it and explicit_location_to_string to save string
+	representations of the canonical location.
+	(create_sals_line_offset, convert_linespec_to_sals): `ls' contains an
+	explicit location.  Update all references.
+	(convert_explicit_location_to_sals): New function.
+	(parse_linespec): Use PARSER_EXPLICIT to access the parser
+	result's explicit location.
+	(linespec_state_constructor): Initialize is_linespec.
+	Use PARSER_EXPLICIT.
+	(linespec_parser_delete): Use PARSER_EXPLICIT to access the parser's
+	result.
+	(event_location_to_sals): For linespec locations, set is_linespec.
+	Handle explicit locations.
+	(decode_objc): 'ls' contains an explicit location now. Update all
+	references.
+	(symtabs_from_filename): Use source_file_not_found_error.
+	* location.c (struct event_location.u) <explicit>: New member.
+	(initialize_explicit_location): New function.
+	(initialize_event_location): Initialize explicit locations.
+	(new_explicit_location, get_explicit_location)
+	(get_explicit_location_const): New functions.
+	(explicit_to_string_internal): New function; most of contents moved
+	from canonicalize_linespec.
+	(explicit_location_to_string): New function.
+	(explicit_location_to_linespec): New function.
+	(copy_event_location, delete_event_location)
+	(event_location_to_string_const, event_location_empty_p): Handle
+	explicit locations.
+	* location.h (enum offset_relative_sign, struct line_offset): Move
+	here from linespec.h.
+	(enum event_location_type): Add EXPLICIT_LOCATION.
+	(struct explicit_location): New structure.
+	(explicit_location_to_string): Declare.
+	(explicit_location_to_linespec): Declare.
+	(new_explicit_location, get_explicit_locationp
+	(get_explicit_location_const, initialize_explicit_location): Declare.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+	* break-catch-throw.c (re_set_exception_catchpoint): Convert
 	linespec for stap probe to probe location.
 	* breakpoint.c (create_longjmp_master_breakpoint)
 	(create_exception_master_breakpoint): Likewise.
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 07a8f05..209c3e3 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -229,9 +229,12 @@  re_set_exception_catchpoint (struct breakpoint *self)
 	 catchpoint mode.  */
       TRY
 	{
-	  char *spec = ASTRDUP (exception_functions[kind].function);
+	  struct explicit_location explicit;
 
-	  location = new_linespec_location (&spec);
+	  initialize_explicit_location (&explicit);
+	  explicit.function_name
+	    = ASTRDUP (exception_functions[kind].function);
+	  location = new_explicit_location (&explicit);
 	  cleanup = make_cleanup_delete_event_location (location);
 	  self->ops->decode_location (self, location, &sals);
 	  do_cleanups (cleanup);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0597688..e6bee3d 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3424,7 +3424,7 @@  create_overlay_event_breakpoint (void)
       struct breakpoint *b;
       struct breakpoint_objfile_data *bp_objfile_data;
       CORE_ADDR addr;
-      char *p;
+      struct explicit_location explicit;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3449,8 +3449,9 @@  create_overlay_event_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_overlay_event,
 				      &internal_breakpoint_ops);
-      p = ASTRDUP (func_name);
-      b->location = new_linespec_location (&p);
+      initialize_explicit_location (&explicit);
+      explicit.function_name = ASTRDUP (func_name);
+      b->location = new_explicit_location (&explicit);
 
       if (overlay_debugging == ovly_auto)
         {
@@ -3547,7 +3548,7 @@  create_longjmp_master_breakpoint (void)
 	  struct breakpoint *b;
 	  const char *func_name;
 	  CORE_ADDR addr;
-	  char *p;
+	  struct explicit_location explicit;
 
 	  if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
 	    continue;
@@ -3570,8 +3571,9 @@  create_longjmp_master_breakpoint (void)
 	  addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
 	  b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
 					  &internal_breakpoint_ops);
-	  p = ASTRDUP (func_name);
-	  b->location = new_linespec_location (&p);
+	  initialize_explicit_location (&explicit);
+	  explicit.function_name = ASTRDUP (func_name);
+	  b->location = new_explicit_location (&explicit);
 	  b->enable_state = bp_disabled;
 	}
     }
@@ -3602,7 +3604,7 @@  create_std_terminate_master_breakpoint (void)
     {
       struct breakpoint *b;
       struct breakpoint_objfile_data *bp_objfile_data;
-      char *p;
+      struct explicit_location explicit;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3628,8 +3630,9 @@  create_std_terminate_master_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_std_terminate_master,
 				      &internal_breakpoint_ops);
-      p = ASTRDUP (func_name);
-      b->location = new_linespec_location (&p);
+      initialize_explicit_location (&explicit);
+      explicit.function_name = ASTRDUP (func_name);
+      b->location = new_explicit_location (&explicit);
       b->enable_state = bp_disabled;
     }
   }
@@ -3653,7 +3656,7 @@  create_exception_master_breakpoint (void)
       struct gdbarch *gdbarch;
       struct breakpoint_objfile_data *bp_objfile_data;
       CORE_ADDR addr;
-      char *p;
+      struct explicit_location explicit;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3734,8 +3737,9 @@  create_exception_master_breakpoint (void)
 						 &current_target);
       b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
 				      &internal_breakpoint_ops);
-      p = ASTRDUP (func_name);
-      b->location = new_linespec_location (&p);
+      initialize_explicit_location (&explicit);
+      explicit.function_name = ASTRDUP (func_name);
+      b->location = new_explicit_location (&explicit);
       b->enable_state = bp_disabled;
     }
 
@@ -13932,12 +13936,11 @@  update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 
       if (!VEC_empty(static_tracepoint_marker_p, markers))
 	{
-	  char *p, *tmp;
 	  struct symtab_and_line sal2;
 	  struct symbol *sym;
 	  struct static_tracepoint_marker *tpmarker;
 	  struct ui_out *uiout = current_uiout;
-	  struct cleanup *cleanup;
+	  struct explicit_location explicit;
 
 	  tpmarker = VEC_index (static_tracepoint_marker_p, markers, 0);
 
@@ -13979,12 +13982,12 @@  update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 	  b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
 
 	  delete_event_location (b->location);
-	  p = tmp = xstrprintf ("%s:%d",
-				symtab_to_filename_for_display (sal2.symtab),
-				b->loc->line_number);
-	  cleanup = make_cleanup (xfree, tmp);
-	  b->location = new_linespec_location (&tmp);
-	  do_cleanups (cleanup);
+	  initialize_explicit_location (&explicit);
+	  explicit.source_filename
+	    = ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
+	  explicit.line_offset.offset = b->loc->line_number;
+	  explicit.line_offset.sign = LINE_OFFSET_NONE;
+	  b->location = new_explicit_location (&explicit);
 
 	  /* Might be nice to check if function changed, and warn if
 	     so.  */
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 8a7640b..84e518f 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -65,73 +65,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;
 
   /* 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.  */
@@ -140,10 +93,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;
 
@@ -196,6 +145,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
@@ -302,6 +254,10 @@  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)
+
 /* Prototypes for local functions.  */
 
 static void iterate_over_file_blocks (struct symtab *symtab,
@@ -1572,6 +1528,29 @@  unexpected_linespec_error (linespec_parser *parser)
 		 token_type_strings[token.type]);
 }
 
+/* Throw an undefined label error.  */
+
+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);
+}
+
 /* Parse and return a line offset in STRING.  */
 
 static struct line_offset
@@ -1618,7 +1597,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.  */
@@ -1655,7 +1634,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);
     }
@@ -1669,7 +1648,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);
 	}
@@ -1677,14 +1656,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;
 	    }
@@ -1699,7 +1678,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;
 	}
@@ -1719,7 +1698,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);
 
@@ -1739,16 +1718,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.  */
@@ -1766,7 +1744,7 @@  linespec_parse_basic (linespec_parser *parser)
 	      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);
 
@@ -1783,43 +1761,28 @@  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, const linespec_p ls)
 {
-  char *tmp;
-  struct ui_file *buf;
-  int need_colon = 0;
-  struct cleanup *cleanup;
+  struct event_location *canon;
+  struct explicit_location *explicit;
 
   /* If canonicalization was not requested, no need to do anything.  */
   if (!state->canonical)
     return;
 
-  buf = mem_fileopen ();
-  cleanup = make_cleanup_ui_file_delete (buf);
-
-  if (ls->source_filename)
-    {
-      fputs_unfiltered (ls->source_filename, buf);
-      need_colon = 1;
-    }
-
-  if (ls->function_name)
-    {
-      if (need_colon)
-	fputc_unfiltered (':', buf);
-      fputs_unfiltered (ls->function_name, buf);
-      need_colon = 1;
-    }
+  /* Save everything as an explicit location.  */
+  canon = state->canonical->location = new_explicit_location (&ls->explicit);
+  explicit = get_explicit_location (canon);
 
-  if (ls->label_name)
+  if (explicit->label_name != NULL)
     {
-      if (need_colon)
-	fputc_unfiltered (':', buf);
+      state->canonical->special_display = 1;
 
-      if (ls->function_name == NULL)
+      if (explicit->function_name == NULL)
 	{
 	  struct symbol *s;
 
@@ -1828,30 +1791,19 @@  canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
 		      && (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);
+	  explicit->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
 	}
-
-      fputs_unfiltered (ls->label_name, buf);
-      need_colon = 1;
-      state->canonical->special_display = 1;
     }
 
-  if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+  /* If this location originally came from a linespec, save a string
+     representation of it for display and saving to file.  */
+  if (state->is_linespec)
     {
-      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);
-    }
+      char *linespec = explicit_location_to_linespec (explicit);
 
-  tmp = ui_file_xstrdup (buf, NULL);
-  make_cleanup (xfree, tmp);
-  state->canonical->location = new_linespec_location (&tmp);
-  do_cleanups (cleanup);
+      set_event_location_string (canon, linespec);
+      xfree (linespec);
+    }
 }
 
 /* Given a line offset in LS, construct the relevant SALs.  */
@@ -1891,18 +1843,18 @@  create_sals_line_offset (struct linespec_state *self,
       use_default = 1;
     }
 
-  val.line = ls->line_offset.offset;
-  switch (ls->line_offset.sign)
+  val.line = ls->explicit.line_offset.offset;
+  switch (ls->explicit.line_offset.sign)
     {
     case LINE_OFFSET_PLUS:
-      if (ls->line_offset.offset == 0)
+      if (ls->explicit.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.line_offset.offset == 0)
 	val.line = 15;
       if (use_default)
 	val.line = self->default_line - val.line;
@@ -1994,9 +1946,9 @@  create_sals_line_offset (struct linespec_state *self,
 
   if (values.nelts == 0)
     {
-      if (ls->source_filename)
+      if (ls->explicit.source_filename)
 	throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
-		     val.line, ls->source_filename);
+		     val.line, ls->explicit.source_filename);
       else
 	throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
 		     val.line);
@@ -2093,13 +2045,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.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.source_filename == NULL)
 	  {
 	    const char *fullname = symtab_to_fullname (state->default_symtab);
 
@@ -2107,7 +2059,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.source_filename = xstrdup (fullname);
 	  }
     }
   else
@@ -2124,6 +2076,72 @@  convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
   return sals;
 }
 
+/* Convert the explicit location EXPLICIT into SaLs.  */
+
+static struct symtabs_and_lines
+convert_explicit_location_to_sals (struct linespec_state *self,
+				   linespec_p result,
+				   const struct explicit_location *explicit)
+{
+  VEC (symbolp) *symbols, *labels;
+  VEC (bound_minimal_symbol_d) *minimal_symbols;
+
+  if (explicit->source_filename != NULL)
+    {
+      TRY
+	{
+	  result->file_symtabs
+	    = symtabs_from_filename (explicit->source_filename);
+	}
+      CATCH (except, RETURN_MASK_ERROR)
+	{
+	  source_file_not_found_error (explicit->source_filename);
+	}
+      END_CATCH
+      result->explicit.source_filename = xstrdup (explicit->source_filename);
+    }
+  else
+    {
+      /* A NULL entry means to use the default symtab.  */
+      VEC_safe_push (symtab_ptr, result->file_symtabs, NULL);
+    }
+
+  if (explicit->function_name != NULL)
+    {
+      find_linespec_symbols (self, result->file_symtabs,
+			     explicit->function_name, &symbols,
+			     &minimal_symbols);
+
+      if (symbols == NULL && minimal_symbols == NULL)
+	symbol_not_found_error (explicit->function_name,
+				result->explicit.source_filename);
+
+      result->explicit.function_name = xstrdup (explicit->function_name);
+      result->function_symbols = symbols;
+      result->minimal_symbols = minimal_symbols;
+    }
+
+  if (explicit->label_name != NULL)
+    {
+      symbols = NULL;
+      labels = find_label_symbols (self, result->function_symbols,
+				   &symbols, explicit->label_name);
+
+      if (labels == NULL)
+	undefined_label_error (result->explicit.function_name,
+			       explicit->label_name);
+
+      result->explicit.label_name = xstrdup (explicit->label_name);
+      result->labels.label_symbols = labels;
+      result->labels.function_symbols = symbols;
+    }
+
+  if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+    result->explicit.line_offset = explicit->line_offset;
+
+   return convert_linespec_to_sals (self, result);
+}
+
 /* Parse a string that specifies a linespec.
 
    The basic grammar of linespecs:
@@ -2229,13 +2247,13 @@  parse_linespec (linespec_parser *parser, const char *arg)
       /* 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);
@@ -2273,7 +2291,7 @@  parse_linespec (linespec_parser *parser, const char *arg)
       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);
@@ -2310,7 +2328,7 @@  parse_linespec (linespec_parser *parser, const char *arg)
 
   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
@@ -2319,8 +2337,8 @@  parse_linespec (linespec_parser *parser, const char *arg)
 	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:
@@ -2358,6 +2376,7 @@  linespec_state_constructor (struct linespec_state *self,
   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.  */
@@ -2372,7 +2391,7 @@  linespec_parser_new (linespec_parser *parser,
   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,
 			      default_symtab, default_line, canonical);
 }
@@ -2392,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);
@@ -2461,6 +2479,7 @@  event_location_to_sals (linespec_parser *parser,
     {
     case LINESPEC_LOCATION:
       {
+	PARSER_STATE (parser)->is_linespec = 1;
 	TRY
 	  {
 	    result = parse_linespec (parser, get_linespec_location (location));
@@ -2479,6 +2498,17 @@  event_location_to_sals (linespec_parser *parser,
 					    get_address_location (location));
       break;
 
+    case EXPLICIT_LOCATION:
+      {
+	const struct explicit_location *explicit;
+
+	explicit = get_explicit_location_const (location);
+	result = convert_explicit_location_to_sals (PARSER_STATE (parser),
+						    PARSER_RESULT (parser),
+						    explicit);
+      }
+      break;
+
     case PROBE_LOCATION:
       /* Probes are handled by their own decoders.  */
       gdb_assert_not_reached ("attempt to decode probe location");
@@ -2728,7 +2758,7 @@  decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
       memcpy (saved_arg, arg, new_argptr - arg);
       saved_arg[new_argptr - arg] = '\0';
 
-      ls->function_name = xstrdup (saved_arg);
+      ls->explicit.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);
@@ -2739,10 +2769,10 @@  decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
 
 	  self->canonical->pre_expanded = 1;
 
-	  if (ls->source_filename)
+	  if (ls->explicit.source_filename)
 	    {
 	      str = xstrprintf ("%s:%s",
-				ls->source_filename, saved_arg);
+				ls->explicit.source_filename, saved_arg);
 	    }
 	  else
 	    str = xstrdup (saved_arg);
@@ -3122,7 +3152,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;
diff --git a/gdb/location.c b/gdb/location.c
index fd35c48..3985e5a 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -50,6 +50,10 @@  struct event_location
     /* An address in the inferior.  */
     CORE_ADDR address;
 #define EL_ADDRESS(PTR) (PTR)->u.address
+
+    /* An explicit location.  */
+    struct explicit_location explicit;
+#define EL_EXPLICIT(PTR) (&((PTR)->u.explicit))
   } u;
 
   /* Cached string representation of this location.  This is used, e.g., to
@@ -68,6 +72,15 @@  event_location_type (const struct event_location *location)
 
 /* See description in location.h.  */
 
+void
+initialize_explicit_location (struct explicit_location *explicit)
+{
+  memset (explicit, 0, sizeof (struct explicit_location));
+  explicit->line_offset.sign = LINE_OFFSET_UNKNOWN;
+}
+
+/* See description in location.h.  */
+
 struct event_location *
 new_linespec_location (char **linespec)
 {
@@ -145,6 +158,137 @@  get_probe_location (const struct event_location *location)
 /* See description in location.h.  */
 
 struct event_location *
+new_explicit_location (const struct explicit_location *explicit)
+{
+  struct event_location tmp;
+
+  memset (&tmp, 0, sizeof (struct event_location));
+  EL_TYPE (&tmp) = EXPLICIT_LOCATION;
+  initialize_explicit_location (EL_EXPLICIT (&tmp));
+  if (explicit != NULL)
+    {
+      if (explicit->source_filename != NULL)
+	{
+	  EL_EXPLICIT (&tmp)->source_filename
+	    = explicit->source_filename;
+	}
+
+      if (explicit->function_name != NULL)
+	EL_EXPLICIT (&tmp)->function_name
+	  = explicit->function_name;
+
+      if (explicit->label_name != NULL)
+	EL_EXPLICIT (&tmp)->label_name = explicit->label_name;
+
+      if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+	EL_EXPLICIT (&tmp)->line_offset = explicit->line_offset;
+    }
+
+  return copy_event_location (&tmp);
+}
+
+/* See description in location.h.  */
+
+struct explicit_location *
+get_explicit_location (struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION);
+  return EL_EXPLICIT (location);
+}
+
+/* See description in location.h.  */
+
+const struct explicit_location *
+get_explicit_location_const (const struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION);
+  return EL_EXPLICIT (location);
+}
+
+/* This convenience function returns a malloc'd string which
+   represents the location in EXPLICIT.
+
+   AS_LINESPEC is non-zero if this string should be a linespec.
+   Otherwise it will be output in explicit form.  */
+
+static char *
+explicit_to_string_internal (int as_linespec,
+			     const struct explicit_location *explicit)
+{
+  struct ui_file *buf;
+  char space, *result;
+  int need_space = 0;
+  struct cleanup *cleanup;
+
+  space = as_linespec ? ':' : ' ';
+  buf = mem_fileopen ();
+  cleanup = make_cleanup_ui_file_delete (buf);
+
+  if (explicit->source_filename != NULL)
+    {
+      if (!as_linespec)
+	fputs_unfiltered ("-source ", buf);
+      fputs_unfiltered (explicit->source_filename, buf);
+      need_space = 1;
+    }
+
+  if (explicit->function_name != NULL)
+    {
+      if (need_space)
+	fputc_unfiltered (space, buf);
+      if (!as_linespec)
+	fputs_unfiltered ("-function ", buf);
+      fputs_unfiltered (explicit->function_name, buf);
+      need_space = 1;
+    }
+
+  if (explicit->label_name != NULL)
+    {
+      if (need_space)
+	fputc_unfiltered (space, buf);
+      if (!as_linespec)
+	fputs_unfiltered ("-label ", buf);
+      fputs_unfiltered (explicit->label_name, buf);
+      need_space = 1;
+    }
+
+  if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+    {
+      if (need_space)
+	fputc_unfiltered (space, buf);
+      if (!as_linespec)
+	fputs_unfiltered ("-line ", buf);
+      fprintf_filtered (buf, "%s%d",
+			(explicit->line_offset.sign == LINE_OFFSET_NONE ? ""
+			 : (explicit->line_offset.sign
+			    == LINE_OFFSET_PLUS ? "+" : "-")),
+			explicit->line_offset.offset);
+    }
+
+  result = ui_file_xstrdup (buf, NULL);
+  do_cleanups (cleanup);
+  return result;
+}
+
+/* See description in location.h.  */
+
+char *
+explicit_location_to_string (const struct explicit_location *explicit)
+{
+  return explicit_to_string_internal (0, explicit);
+}
+
+/* See description in location.h.  */
+
+char *
+explicit_location_to_linespec (const struct explicit_location *explicit)
+{
+  return explicit_to_string_internal (1, explicit);
+}
+
+/* See description in location.h.  */
+
+struct event_location *
 copy_event_location (const struct event_location *src)
 {
   struct event_location *dst;
@@ -165,6 +309,22 @@  copy_event_location (const struct event_location *src)
       EL_ADDRESS (dst) = EL_ADDRESS (src);
       break;
 
+    case EXPLICIT_LOCATION:
+      if (EL_EXPLICIT (src)->source_filename != NULL)
+	EL_EXPLICIT (dst)->source_filename
+	  = xstrdup (EL_EXPLICIT (src)->source_filename);
+
+      if (EL_EXPLICIT (src)->function_name != NULL)
+	EL_EXPLICIT (dst)->function_name
+	  = xstrdup (EL_EXPLICIT (src)->function_name);
+
+      if (EL_EXPLICIT (src)->label_name != NULL)
+	EL_EXPLICIT (dst)->label_name = xstrdup (EL_EXPLICIT (src)->label_name);
+
+      EL_EXPLICIT (dst)->line_offset = EL_EXPLICIT (src)->line_offset;
+      break;
+
+
     case PROBE_LOCATION:
       if (EL_PROBE (src) != NULL)
 	EL_PROBE (dst) = xstrdup (EL_PROBE (src));
@@ -214,6 +374,12 @@  delete_event_location (struct event_location *location)
 	  /* Nothing to do.  */
 	  break;
 
+	case EXPLICIT_LOCATION:
+	  xfree (EL_EXPLICIT (location)->source_filename);
+	  xfree (EL_EXPLICIT (location)->function_name);
+	  xfree (EL_EXPLICIT (location)->label_name);
+	  break;
+
 	case PROBE_LOCATION:
 	  xfree (EL_PROBE (location));
 	  break;
@@ -246,6 +412,11 @@  event_location_to_string (struct event_location *location)
 			  core_addr_to_string (EL_ADDRESS (location)));
 	  break;
 
+	case EXPLICIT_LOCATION:
+	  EL_STRING (location)
+	    = explicit_location_to_string (EL_EXPLICIT (location));
+	  break;
+
 	case PROBE_LOCATION:
 	  EL_STRING (location) = xstrdup (EL_PROBE (location));
 	  break;
@@ -312,6 +483,14 @@  event_location_empty_p (const struct event_location *location)
     case ADDRESS_LOCATION:
       return 0;
 
+    case EXPLICIT_LOCATION:
+      return (EL_EXPLICIT (location) == NULL
+	      || (EL_EXPLICIT (location)->source_filename == NULL
+		  && EL_EXPLICIT (location)->function_name == NULL
+		  && EL_EXPLICIT (location)->label_name == NULL
+		  && (EL_EXPLICIT (location)->line_offset.sign
+		      == LINE_OFFSET_UNKNOWN)));
+
     case PROBE_LOCATION:
       return EL_PROBE (location) == NULL;
 
diff --git a/gdb/location.h b/gdb/location.h
index 63318ba..3082d9e 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -22,6 +22,32 @@ 
 struct language_defn;
 struct event_location;
 
+/* 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 location.  */
+
+struct line_offset
+{
+  /* Line offset and any specified sign.  */
+  int offset;
+  enum offset_relative_sign sign;
+};
+
 /* An enumeration of the various ways to specify a stop event
    location (used with create_breakpoint).  */
 
@@ -33,15 +59,52 @@  enum event_location_type
   /* An address in the inferior.  */
   ADDRESS_LOCATION,
 
+  /* An explicit location.  */
+  EXPLICIT_LOCATION,
+
   /* A probe location.  */
   PROBE_LOCATION
 };
 
+/* An explicit location.  This structure is used to bypass the
+   parsing done on linespecs.  It still has the same requirements
+   as linespecs, though.  For example, source_filename requires
+   at least one other field.  */
+
+struct explicit_location
+{
+  /* The source filename. Malloc'd.  */
+  char *source_filename;
+
+  /* The function name.  Malloc'd.  */
+  char *function_name;
+
+  /* The name of a label.  Malloc'd.  */
+  char *label_name;
+
+  /* A line offset relative to the start of the symbol
+     identified by the above fields or the current symtab
+     if the other fields are NULL.  */
+  struct line_offset line_offset;
+};
+
 /* Return the type of the given event location.  */
 
 extern enum event_location_type
   event_location_type (const struct event_location *);
 
+/* Return a malloc'd explicit string representation of the given
+   explicit location.  The location must already be canonicalized/valid.  */
+
+extern char *
+  explicit_location_to_string (const struct explicit_location *explicit);
+
+/* Return a malloc'd linespec string representation of the given
+   explicit location.  The location must already be canonicalized/valid.  */
+
+extern char *
+  explicit_location_to_linespec (const struct explicit_location *explicit);
+
 /* Return a string representation of the LOCATION.
    This function may return NULL for unspecified linespecs,
    e.g, LOCATION_LINESPEC and addr_string is NULL.
@@ -87,6 +150,30 @@  extern struct event_location *
 extern const char *
   get_probe_location (const struct event_location *location);
 
+/* Initialize the given explicit location.  */
+
+extern void initialize_explicit_location (struct explicit_location *explicit);
+
+/* Create a new explicit location.  If not NULL, EXPLICIT is checked for
+   validity.  If invalid, an exception is thrown.
+
+   The return result is malloc'd and should be freed with
+   delete_event_location.  */
+
+extern struct event_location *
+  new_explicit_location (const struct explicit_location *explicit);
+
+/* Return the explicit location of the given event_location
+   (which must be of type EXPLICIT_LOCATION).  */
+
+extern struct explicit_location *
+  get_explicit_location (struct event_location *location);
+
+/* A const version of the above.  */
+
+extern const struct explicit_location *
+  get_explicit_location_const (const struct event_location *location);
+
 /* Free an event location and any associated data.  */
 
 extern void delete_event_location (struct event_location *location);



commit 87f0e7204722a986f79f245eee716f0870832d47
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:36 2015 -0700

    Explicit locations: add UI features for CLI
    
    This patch exposes explicit locations to the CLI user.  This enables
    users to "explicitly" specify attributes of the breakpoint location
    to avoid any ambiguity that might otherwise exist with linespecs.
    
    The general syntax of explicit locations is:
    -source SOURCE_FILENAME -line {+-}LINE -function FUNCTION_NAME
    -label LABEL_NAME
    
    Option names may be abbreviated, e.g., "-s SOURCE_FILENAME -li 3" and users
    may use the completer with either options or values.
    
    gdb/ChangeLog:
    
    	* completer.c: Include location.h.
    	(enum match_type): New enum.
    	(location_completer): Rename to ...
    	(linespec_completer): ... this.
    	(collect_explicit_location_matches, backup_text_ptr)
    	(explicit_location_completer): New functions.
    	(location_completer): "New" function; handle linespec
    	and explicit location completions.
    	(complete_line_internal): Remove all location completer-specific
    	handling.
    	* linespec.c (linespec_lexer_lex_keyword, is_ada_operator)
    	(find_toplevel_char): Export.
    	(linespec_parse_line_offset): Export.
    	Issue error if STRING is not numerical.
    	(gdb_get_linespec_parser_quote_characters): New function.
    	* linespec.h (linespec_parse_line_offset): Declare.
    	(get_gdb_linespec_parser_quote_characters): Declare.
    	(is_ada_operator): Declare.
    	(find_toplevel_char): Declare.
    	(linespec_lexer_lex_keyword): Declare.
    	* location.c (explicit_to_event_location): New function.
    	(explicit_location_lex_one): New function.
    	(string_to_explicit_location): New function.
    	(string_to_event_location): Handle explicit locations.
    	* location.h (explicit_to_event_location): Declare.
    	(string_to_explicit_location): Declare.
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.linespec/3explicit.c: New file.
    	* gdb.linespec/cpexplicit.cc: New file.
    	* gdb.linespec/cpexplicit.exp: New file.
    	* gdb.linespec/explicit.c: New file.
    	* gdb.linespec/explicit.exp: New file.
    	* gdb.linespec/explicit2.c: New file.
    	* gdb.linespec/ls-errs.exp: Add explicit location tests.
    	* lib/gdb.exp (capture_command_output): Regexp-escape `command'
    	before using in the matching pattern.
    	Clarify that `prefix' is a regular expression.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 13d31a6..57717bd 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,34 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* completer.c: Include location.h.
+	(enum match_type): New enum.
+	(location_completer): Rename to ...
+	(linespec_completer): ... this.
+	(collect_explicit_location_matches, backup_text_ptr)
+	(explicit_location_completer): New functions.
+	(location_completer): "New" function; handle linespec
+	and explicit location completions.
+	(complete_line_internal): Remove all location completer-specific
+	handling.
+	* linespec.c (linespec_lexer_lex_keyword, is_ada_operator)
+	(find_toplevel_char): Export.
+	(linespec_parse_line_offset): Export.
+	Issue error if STRING is not numerical.
+	(gdb_get_linespec_parser_quote_characters): New function.
+	* linespec.h (linespec_parse_line_offset): Declare.
+	(get_gdb_linespec_parser_quote_characters): Declare.
+	(is_ada_operator): Declare.
+	(find_toplevel_char): Declare.
+	(linespec_lexer_lex_keyword): Declare.
+	* location.c (explicit_to_event_location): New function.
+	(explicit_location_lex_one): New function.
+	(string_to_explicit_location): New function.
+	(string_to_event_location): Handle explicit locations.
+	* location.h (explicit_to_event_location): Declare.
+	(string_to_explicit_location): Declare.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* break-catch-throw.c (re_set_exception_catchpoint): Convert
 	linespec into explicit location.
 	* breakpoint.c (create_overlay_breakpoint)
diff --git a/gdb/completer.c b/gdb/completer.c
index d1ebf67..7fc27b1 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -27,6 +27,7 @@ 
 #include "reggroups.h"
 #include "user-regs.h"
 #include "arch-utils.h"
+#include "location.h"
 
 #include "cli/cli-decode.h"
 
@@ -43,6 +44,21 @@ 
 
 #include "completer.h"
 
+/* An enumeration of the various things a user might
+   attempt to complete for a location.  */
+
+enum explicit_location_match_type
+{
+    /* The filename of a source file.  */
+    MATCH_SOURCE,
+
+    /* The name of a function or method.  */
+    MATCH_FUNCTION,
+
+    /* The name of a label.  */
+    MATCH_LABEL
+};
+
 /* Prototypes for local functions.  */
 static
 char *line_completion_function (const char *text, int matches, 
@@ -175,7 +191,7 @@  filename_completer (struct cmd_list_element *ignore,
   return return_val;
 }
 
-/* Complete on locations, which might be of two possible forms:
+/* Complete on linespecs, which might be of two possible forms:
 
        file:line
    or
@@ -184,9 +200,9 @@  filename_completer (struct cmd_list_element *ignore,
    This is intended to be used in commands that set breakpoints
    etc.  */
 
-VEC (char_ptr) *
-location_completer (struct cmd_list_element *ignore, 
-		    const char *text, const char *word)
+static VEC (char_ptr) *
+linespec_location_completer (struct cmd_list_element *ignore,
+			     const char *text, const char *word)
 {
   int n_syms, n_files, ix;
   VEC (char_ptr) *fn_list = NULL;
@@ -333,6 +349,182 @@  location_completer (struct cmd_list_element *ignore,
   return list;
 }
 
+/* A helper function to collect explicit location matches for the given
+   LOCATION, which is attempting to match on WORD.  */
+
+static VEC (char_ptr) *
+collect_explicit_location_matches (struct event_location *location,
+				   enum explicit_location_match_type what,
+				   const char *word)
+{
+  VEC (char_ptr) *matches = NULL;
+  const struct explicit_location *explicit = get_explicit_location (location);
+
+  switch (what)
+    {
+    case MATCH_SOURCE:
+      {
+	const char *text = (explicit->source_filename == NULL
+			    ? "" : explicit->source_filename);
+
+	matches = make_source_files_completion_list (text, word);
+      }
+      break;
+
+    case MATCH_FUNCTION:
+      {
+	const char *text = (explicit->function_name == NULL
+			    ? "" : explicit->function_name);
+
+	if (explicit->source_filename != NULL)
+	  {
+	    matches
+	      = make_file_symbol_completion_list (text, word,
+						  explicit->source_filename);
+	  }
+	else
+	  matches = make_symbol_completion_list (text, word);
+      }
+      break;
+
+    case MATCH_LABEL:
+      /* Not supported.  */
+      break;
+
+    default:
+      gdb_assert_not_reached ("unhandled explicit_location_match_type");
+    }
+
+  return matches;
+}
+
+/* A convenience macro to (safely) back up P to the previous word.  */
+
+static const char *
+backup_text_ptr (const char *p, const char *text)
+{
+  while (p > text && isspace (*p))
+    --p;
+  for (; p > text && !isspace (p[-1]); --p)
+    ;
+
+  return p;
+}
+
+/* A completer function for explicit locations.  This function
+   completes both options ("-source", "-line", etc) and values.  */
+
+static VEC (char_ptr) *
+explicit_location_completer (struct cmd_list_element *ignore,
+			     struct event_location *location,
+			     const char *text, const char *word)
+{
+  const char *p;
+  VEC (char_ptr) *matches = NULL;
+
+  /* Find the beginning of the word.  This is necessary because
+     we need to know if we are completing an option name or value.  We
+     don't get the leading '-' from the completer.  */
+  p = backup_text_ptr (word, text);
+
+  if (*p == '-')
+    {
+      /* Completing on option name.  */
+      static const char *const keywords[] =
+	{
+	  "source",
+	  "function",
+	  "line",
+	  "label",
+	  NULL
+	};
+
+      /* Skip over the '-'.  */
+      ++p;
+
+      return complete_on_enum (keywords, p, p);
+    }
+  else
+    {
+      /* Completing on value (or unknown).  Get the previous word to see what
+	 the user is completing on.  */
+      size_t len, offset;
+      const char *new_word, *end;
+      enum explicit_location_match_type what;
+      struct explicit_location *explicit = get_explicit_location (location);
+
+      /* Backup P to the previous word, which should be the option
+	 the user is attempting to complete.  */
+      offset = word - p;
+      end = --p;
+      p = backup_text_ptr (p, text);
+      len = end - p;
+
+      if (strncmp (p, "-source", len) == 0)
+	{
+	  what = MATCH_SOURCE;
+	  new_word = explicit->source_filename + offset;
+	}
+      else if (strncmp (p, "-function", len) == 0)
+	{
+	  what = MATCH_FUNCTION;
+	  new_word = explicit->function_name + offset;
+	}
+      else if (strncmp (p, "-label", len) == 0)
+	{
+	  what = MATCH_LABEL;
+	  new_word = explicit->label_name + offset;
+	}
+      else
+	{
+	  /* The user isn't completing on any valid option name,
+	     e.g., "break -source foo.c [tab]".  */
+	  return NULL;
+	}
+
+      /* If the user hasn't entered a search expression, e.g.,
+	 "break -function <TAB><TAB>", new_word will be NULL, but
+	 search routines require non-NULL search words.  */
+      if (new_word == NULL)
+	new_word = "";
+
+      /* Now gather matches  */
+      matches = collect_explicit_location_matches (location, what, new_word);
+    }
+
+  return matches;
+}
+
+/* A completer for locations.  */
+
+VEC (char_ptr) *
+location_completer (struct cmd_list_element *ignore,
+		    const char *text, const char *word)
+{
+  VEC (char_ptr) *matches = NULL;
+  const char *copy = text;
+  struct event_location *location;
+
+  location = string_to_explicit_location (&copy, current_language, 1);
+  if (location != NULL)
+    {
+      struct cleanup *cleanup;
+
+      cleanup = make_cleanup_delete_event_location (location);
+      matches = explicit_location_completer (ignore, location, text, word);
+      do_cleanups (cleanup);
+    }
+  else
+    {
+      /* This is an address or linespec location.
+	 Right now both of these are handled by the (old) linespec
+	 completer.  */
+      matches = linespec_location_completer (ignore, text, word);
+    }
+
+  return matches;
+}
+
 /* Helper for expression_completer which recursively adds field and
    method names from TYPE, a struct or union type, to the array
    OUTPUT.  */
@@ -688,16 +880,6 @@  complete_line_internal (const char *text,
 		      rl_completer_word_break_characters =
 			gdb_completer_file_name_break_characters;
 		    }
-		  else if (c->completer == location_completer)
-		    {
-		      /* Commands which complete on locations want to
-			 see the entire argument.  */
-		      for (p = word;
-			   p > tmp_command
-			     && p[-1] != ' ' && p[-1] != '\t';
-			   p--)
-			;
-		    }
 		  if (reason == handle_brkchars
 		      && c->completer_handle_brkchars != NULL)
 		    (*c->completer_handle_brkchars) (c, p, word);
@@ -766,14 +948,6 @@  complete_line_internal (const char *text,
 		  rl_completer_word_break_characters =
 		    gdb_completer_file_name_break_characters;
 		}
-	      else if (c->completer == location_completer)
-		{
-		  for (p = word;
-		       p > tmp_command
-			 && p[-1] != ' ' && p[-1] != '\t';
-		       p--)
-		    ;
-		}
 	      if (reason == handle_brkchars
 		  && c->completer_handle_brkchars != NULL)
 		(*c->completer_handle_brkchars) (c, p, word);
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 84e518f..ff8ae05 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -323,8 +323,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.  */
@@ -419,10 +417,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;
@@ -1140,7 +1137,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;
@@ -1551,11 +1548,12 @@  source_file_not_found_error (const char *name)
   throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
 }
 
-/* Parse and return a line offset in STRING.  */
+/* See description in linespec.h.  */
 
-static struct line_offset
+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 == '+')
@@ -1569,6 +1567,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;
@@ -3903,3 +3904,11 @@  make_cleanup_destroy_linespec_result (struct linespec_result *ls)
 {
   return make_cleanup (cleanup_linespec_result, ls);
 }
+
+/* Return the quote characters permitted by the linespec parser.  */
+
+const char *
+get_gdb_linespec_parser_quote_characters (void)
+{
+  return linespec_quote_characters;
+}
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 391ed26..2a76283 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -157,6 +157,26 @@  extern struct symtabs_and_lines decode_line_with_last_displayed (char *, int);
 
 extern const char *linespec_lexer_lex_keyword (const char *p);
 
+/* Parse a line offset from STRING.  */
+
+extern struct line_offset linespec_parse_line_offset (const char *string);
+
+/* Return the quote characters permitted by the linespec parser.  */
+
+extern const char *get_gdb_linespec_parser_quote_characters (void);
+
+/* Does STRING represent an Ada operator?  If so, return the length
+   of the decoded operator name.  If not, return 0.  */
+
+extern int is_ada_operator (const char *string);
+
+/* Find an instance of the character C in the string S that is outside
+   of all parenthesis pairs, single-quoted strings, and double-quoted
+   strings.  Also, ignore the char within a template name, like a ','
+   within foo<int, int>.  */
+
+extern const char *find_toplevel_char (const char *s, char c);
+
 /* Find the end of the (first) linespec pointed to by *STRINGP.
    STRINGP will be advanced to this point.  */
 
diff --git a/gdb/location.c b/gdb/location.c
index 3985e5a..675c8d9 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -429,6 +429,196 @@  event_location_to_string (struct event_location *location)
   return EL_STRING (location);
 }
 
+/* A lexer for explicit locations.  This function will advance INP
+   past any strings that it lexes.  Returns a malloc'd copy of the
+   lexed string or NULL if no lexing was done.  */
+
+static char *
+explicit_location_lex_one (const char **inp,
+			   const struct language_defn *language)
+{
+  const char *start = *inp;
+
+  if (*start == '\0')
+    return NULL;
+
+  /* If quoted, skip to the ending quote.  */
+  if (strchr (get_gdb_linespec_parser_quote_characters (), *start))
+    {
+      char quote_char = *start;
+
+      /* If the input is not an Ada operator, skip to the matching
+	 closing quote and return the string.  */
+      if (!(language->la_language == language_ada
+	    && quote_char == '\"' && is_ada_operator (start)))
+	{
+	  const char *end = find_toplevel_char (start + 1, quote_char);
+
+	  if (end == NULL)
+	    error (_("Unmatched quote, %s."), start);
+	  *inp = end + 1;
+	  return savestring (start + 1, *inp - start - 2);
+	}
+    }
+
+  /* If the input starts with '-' or '+', the string ends with the next
+     whitespace or comma.  */
+  if (*start == '-' || *start == '+')
+    {
+      while (*inp[0] != '\0' && *inp[0] != ',' && !isspace (*inp[0]))
+	++(*inp);
+    }
+  else
+    {
+      /* Handle numbers first, stopping at the next whitespace or ','.  */
+      while (isdigit (*inp[0]))
+	++(*inp);
+      if (*inp[0] == '\0' || isspace (*inp[0]) || *inp[0] == ',')
+	return savestring (start, *inp - start);
+
+      /* Otherwise stop at the next occurrence of whitespace, '\0',
+	 keyword, or ','.  */
+      *inp = start;
+      while ((*inp)[0]
+	     && (*inp)[0] != ','
+	     && !(isspace ((*inp)[0])
+		  || linespec_lexer_lex_keyword (&(*inp)[1])))
+	{
+	  /* Special case: C++ operator,.  */
+	  if (language->la_language == language_cplus
+	      && strncmp (*inp, "operator", 8)
+	      && (*inp)[9] == ',')
+	    (*inp) += 9;
+	  ++(*inp);
+	}
+    }
+
+  if (*inp - start > 0)
+    return savestring (start, *inp - start);
+
+  return NULL;
+}
+
+/* See description in location.h.  */
+
+struct event_location *
+string_to_explicit_location (const char **argp,
+			     const struct language_defn *language,
+			     int dont_throw)
+{
+  struct cleanup *cleanup;
+  struct event_location *location;
+
+  /* It is assumed that input beginning with '-' and a non-digit
+     character is an explicit location.  */
+  if (argp == NULL
+      || *argp == '\0'
+      || *argp[0] != '-'
+      || !isalpha ((*argp)[1]))
+    return NULL;
+
+  location = new_explicit_location (NULL);
+  cleanup = make_cleanup_delete_event_location (location);
+
+  /* Process option/argument pairs.  dprintf_command
+     requires that processing stop on ','.  */
+  while ((*argp)[0] != '\0' && (*argp)[0] != ',')
+    {
+      int len;
+      char *opt, *oarg;
+      const char *start;
+      struct cleanup *opt_cleanup, *oarg_cleanup;
+
+      /* If *ARGP starts with a keyword, stop processing
+	 options.  */
+      if (linespec_lexer_lex_keyword (*argp) != NULL)
+	break;
+
+      /* Mark the start of the string in case we need to rewind.  */
+      start = *argp;
+
+      /* Get the option string.  */
+      opt = explicit_location_lex_one (argp, language);
+      opt_cleanup = make_cleanup (xfree, opt);
+
+      *argp = skip_spaces_const (*argp);
+
+      /* Get the argument string.  */
+      oarg = explicit_location_lex_one (argp, language);
+      oarg_cleanup = make_cleanup (xfree, oarg);
+      *argp = skip_spaces_const (*argp);
+
+      /* Use the length of the option to allow abbreviations.  */
+      len = strlen (opt);
+
+      /* All options have a required argument.  Checking for this required
+	 argument is deferred until later.  */
+      if (strncmp (opt, "-source", len) == 0)
+	EL_EXPLICIT (location)->source_filename = oarg;
+      else if (strncmp (opt, "-function", len) == 0)
+	EL_EXPLICIT (location)->function_name = oarg;
+      else if (strncmp (opt, "-line", len) == 0)
+	{
+	  if (oarg != NULL)
+	    {
+	      EL_EXPLICIT (location)->line_offset
+		= linespec_parse_line_offset (oarg);
+	      do_cleanups (oarg_cleanup);
+	      do_cleanups (opt_cleanup);
+	      continue;
+	    }
+	}
+      else if (strncmp (opt, "-label", len) == 0)
+	EL_EXPLICIT (location)->label_name = oarg;
+      /* Only emit an "invalid argument" error for options
+	 that look like option strings.  */
+      else if (opt[0] == '-' && !isdigit (opt[1]))
+	{
+	  if (!dont_throw)
+	    error (_("invalid explicit location argument, \"%s\""), opt);
+	}
+      else
+	{
+	  /* End of the explicit location specification.
+	     Stop parsing and return whatever explicit location was
+	     parsed.  */
+	  *argp = start;
+	  discard_cleanups (oarg_cleanup);
+	  do_cleanups (opt_cleanup);
+	  discard_cleanups (cleanup);
+	  return location;
+	}
+
+      /* It's a little lame to error after the fact, but in this
+	 case, it provides a much better user experience to issue
+	 the "invalid argument" error before any missing
+	 argument error.  */
+      if (oarg == NULL && !dont_throw)
+	error (_("missing argument for \"%s\""), opt);
+
+      /* The option/argument pair was successfully processed;
+	 oarg belongs to the explicit location, and opt should
+	 be freed.  */
+      discard_cleanups (oarg_cleanup);
+      do_cleanups (opt_cleanup);
+    }
+
+  /* One special error check:  If a source filename was given
+     without offset, function, or label, issue an error.  */
+  if (EL_EXPLICIT (location)->source_filename != NULL
+      && EL_EXPLICIT (location)->function_name == NULL
+      && EL_EXPLICIT (location)->label_name == NULL
+      && (EL_EXPLICIT (location)->line_offset.sign == LINE_OFFSET_UNKNOWN)
+      && !dont_throw)
+    {
+      error (_("Source filename requires function, label, or "
+	       "line offset."));
+    }
+
+  discard_cleanups (cleanup);
+  return location;
+}
+
 /* See description in location.h.  */
 
 struct event_location *
@@ -461,8 +651,22 @@  string_to_event_location (char **stringp,
 	}
       else
 	{
-	  /* Everything else is a linespec.  */
-	  location = new_linespec_location (stringp);
+	  const char *arg, *orig;
+
+	  /* Next, try an explicit location.  */
+	  orig = arg = *stringp;
+	  location = string_to_explicit_location (&arg, language, 0);
+	  if (location != NULL)
+	    {
+	      /* It was a valid explicit location.  Advance STRINGP to
+		 the end of input.  */
+	      *stringp += arg - orig;
+	    }
+	  else
+	    {
+	      /* Everything else is a linespec.  */
+	      location = new_linespec_location (stringp);
+	    }
 	}
     }
 
diff --git a/gdb/location.h b/gdb/location.h
index 3082d9e..31ae59a 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -203,6 +203,21 @@  extern struct event_location *
   string_to_event_location (char **argp,
 			    const struct language_defn *langauge);
 
+/* Attempt to convert the input string in *ARGP into an explicit location.
+   ARGP is advanced past any processed input.  Returns an event_location
+   (malloc'd) if an explicit location was successfully found in *ARGP,
+   NULL otherwise.
+
+   IF !DONT_THROW, this function may call error() if *ARGP looks like
+   properly formed input, e.g., if it is called with missing argument
+   parameters or invalid options.  If DONT_THROW is non-zero, this function
+   will not throw any exceptions.  */
+
+extern struct event_location *
+  string_to_explicit_location (const char **argp,
+			       const struct language_defn *langauge,
+			       int dont_throw);
+
 /* A convenience function for testing for unset locations.  */
 
 extern int event_location_empty_p (const struct event_location *location);
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 5fa6cdd..ae3a275 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,18 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* gdb.linespec/3explicit.c: New file.
+	* gdb.linespec/cpexplicit.cc: New file.
+	* gdb.linespec/cpexplicit.exp: New file.
+	* gdb.linespec/explicit.c: New file.
+	* gdb.linespec/explicit.exp: New file.
+	* gdb.linespec/explicit2.c: New file.
+	* gdb.linespec/ls-errs.exp: Add explicit location tests.
+	* lib/gdb.exp (capture_command_output): Regexp-escape `command'
+	before using in the matching pattern.
+	Clarify that `prefix' is a regular expression.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* gdb.base/dprintf-pending.exp: Update dprintf "without format"
 	test.
 	Add tests for missing ",FMT" and ",".
diff --git a/gdb/testsuite/gdb.linespec/3explicit.c b/gdb/testsuite/gdb.linespec/3explicit.c
new file mode 100644
index 0000000..12bf277
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/3explicit.c
@@ -0,0 +1,28 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+static int
+myfunction4 (int arg)
+{
+  return arg + 2;
+}
+
+int
+myfunction3 (int arg)
+{
+  return myfunction4 (arg);
+}
diff --git a/gdb/testsuite/gdb.linespec/cpexplicit.cc b/gdb/testsuite/gdb.linespec/cpexplicit.cc
new file mode 100644
index 0000000..42d50c7
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/cpexplicit.cc
@@ -0,0 +1,63 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+class myclass
+{
+public:
+  static int myfunction (int arg)  /* entry location */
+  {
+    int i, j, r;
+
+    j = 0; /* myfunction location */
+    r = arg;
+
+  top:
+    ++j;  /* top location */
+
+    if (j == 10)
+      goto done;
+
+    for (i = 0; i < 10; ++i)
+      {
+	r += i;
+	if (j % 2)
+	  goto top;
+      }
+
+  done:
+    return r;
+  }
+
+  int operator, (const myclass& c) { return 0; } /* operator location */
+};
+
+int
+main (void)
+{
+  int i, j;
+
+  /* Call the test function repeatedly, enough times for all our tests
+     without running forever if something goes wrong.  */
+  myclass c, d;
+  for (i = 0, j = 0; i < 1000; ++i)
+    {
+      j += myclass::myfunction (0);
+      j += (c,d);
+    }
+
+  return j;
+}
diff --git a/gdb/testsuite/gdb.linespec/cpexplicit.exp b/gdb/testsuite/gdb.linespec/cpexplicit.exp
new file mode 100644
index 0000000..90c8ce8
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/cpexplicit.exp
@@ -0,0 +1,112 @@ 
+# Copyright 2012-2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Tests for explicit linespecs
+
+if {[skip_cplus_tests]} {
+    unsupported "skipping C++ tests"
+    return
+}
+
+standard_testfile .cc
+set exefile $testfile
+
+if {[prepare_for_testing $testfile $exefile $srcfile \
+	 {c++ debug nowarnings}]} {
+    return -1
+}
+
+# Wrap this whole test in a namespace to avoid contaminating other tests.
+namespace eval $testfile {
+    # Test the given (explicit) LINESPEC which should cause gdb to break
+    # at LOCATION.
+    proc test_breakpoint {linespec location} {
+
+	# Delete all breakpoints, set a new breakpoint at LINESPEC,
+	# and attempt to run to it.
+	delete_breakpoints
+	gdb_breakpoint $linespec
+	gdb_continue_to_breakpoint $linespec $location
+    }
+
+    # Add the given LINESPEC to the array named in THEARRAY.  GDB is expected
+    # to stop at LOCATION.
+    proc add {thearray linespec location} {
+	upvar $thearray ar
+
+	lappend ar(linespecs) $linespec
+	lappend ar(locations) $location
+    }
+
+    # Some locations used in this test
+    variable lineno
+    variable location
+    set lineno(normal) [gdb_get_line_number "myfunction location" $srcfile]
+    set lineno(entry) [gdb_get_line_number "entry location" $srcfile]
+    set lineno(top) [gdb_get_line_number "top location" $srcfile]
+    set lineno(operator) [gdb_get_line_number "operator location" $srcfile]
+    foreach v [array names lineno] {
+	set location($v) ".*[string_to_regexp "$srcfile:$lineno($v)"].*"
+    }
+
+    # A list of explicit linespecs and the corresponding location
+    variable linespecs
+    set linespecs(linespecs) {}
+    set linespecs(location) {}
+
+    add linespecs "-source $srcfile -function myclass::myfunction" \
+	$location(normal)
+    add linespecs "-source $srcfile -function myclass::myfunction -label top" \
+	$location(top)
+
+    # This isn't implemented yet; -line is silently ignored.
+    add linespecs \
+	"-source $srcfile -function myclass::myfunction -label top -line 3" \
+	$location(top)
+    add linespecs "-source $srcfile -line $lineno(top)" $location(top)
+    add linespecs "-function myclass::myfunction" $location(normal)
+    add linespecs "-function myclass::myfunction -label top" $location(top)
+
+    # These are also not yet supported; -line is silently ignored.
+    add linespecs "-function myclass::myfunction -line 3" $location(normal)
+    add linespecs "-function myclass::myfunction -label top -line 3" \
+	$location(top)
+    add linespecs "-line 3" $location(normal)
+    add linespecs "-function myclass::operator," $location(operator)
+    add linespecs "-function 'myclass::operator,'" $location(operator)
+    add linespecs "-function \"myclass::operator,\"" $location(operator)
+
+    # Fire up gdb.
+    if {![runto_main]} {
+	namespace delete $testfile
+	return -1
+    }
+
+    # Test explicit linespecs, with and without conditions.
+    foreach linespec $linespecs(linespecs) loc_pattern $linespecs(locations) {
+	# Test the linespec
+	test_breakpoint $linespec $loc_pattern
+    }
+
+    # Special (orphaned) dprintf cases.
+    gdb_test "dprintf -function myclass::operator,,\"hello\"" \
+	"Dprintf .*$srcfile, line $lineno(operator)\\."
+    gdb_test "dprintf -function 'myclass::operator,',\"hello\"" \
+	"Dprintf .*$srcfile, line $lineno(operator)\\."
+    gdb_test "dprintf -function \"myclass::operator,\",\"hello\"" \
+	"Dprintf .*$srcfile, line $lineno(operator)\\."
+}
+
+namespace delete $testfile
diff --git a/gdb/testsuite/gdb.linespec/explicit.c b/gdb/testsuite/gdb.linespec/explicit.c
new file mode 100644
index 0000000..4e1c635
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/explicit.c
@@ -0,0 +1,56 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012-2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int myfunction2 (int arg);
+
+static int
+myfunction (int arg)
+{
+  int i, j, r;
+
+  j = 0; /* myfunction location */
+  r = arg;
+
+ top:
+  ++j;  /* top location */
+
+  if (j == 10)
+    goto done;
+
+  for (i = 0; i < 10; ++i)
+    {
+      r += i;
+      if (j % 2)
+	goto top;
+    }
+
+ done:
+  return r;
+}
+
+int
+main (void)
+{
+  int i, j;
+
+  /* Call the test function repeatedly, enough times for all our tests
+     without running forever if something goes wrong.  */
+  for (i = 0, j = 0; i < 1000; ++i)
+    j += myfunction (0);
+
+  return myfunction2 (j);
+}
diff --git a/gdb/testsuite/gdb.linespec/explicit.exp b/gdb/testsuite/gdb.linespec/explicit.exp
new file mode 100644
index 0000000..344f1b0
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/explicit.exp
@@ -0,0 +1,406 @@ 
+# Copyright 2012-2015 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Tests for explicit locations
+
+standard_testfile explicit.c explicit2.c 3explicit.c
+set exefile $testfile
+
+if {[prepare_for_testing $testfile $exefile \
+	 [list $srcfile $srcfile2 $srcfile3] {debug nowarnings}]} {
+    return -1
+}
+
+# Wrap the entire test in a namespace to avoid contaminating other tests.
+namespace eval $testfile {
+
+    # Test the given (explicit) LINESPEC which should cause gdb to break
+    # at LOCATION.
+    proc test_breakpoint {linespec location} {
+
+	set testname "set breakpoint at \"$linespec\""
+	# Delete all breakpoints, set a new breakpoint at LINESPEC,
+	# and attempt to run to it.
+	delete_breakpoints
+	if {[gdb_breakpoint $linespec]} {
+	    pass $testname
+	    send_log "\nexpecting locpattern \"$location\"\n"
+	    gdb_continue_to_breakpoint $linespec $location
+	} else {
+	    fail $testname
+	}
+    }
+
+    # Add the given LINESPEC to the array named in THEARRAY.  GDB is expected
+    # to stop at LOCATION.
+    proc add {thearray linespec location} {
+	upvar $thearray ar
+
+	lappend ar(linespecs) $linespec
+	lappend ar(locations) $location
+    }
+
+    # A list of all explicit linespec arguments.
+    variable all_arguments
+    set all_arguments {"source" "function" "label" "line"}
+
+    # Some locations used in this test
+    variable lineno
+    variable location
+    set lineno(normal) [gdb_get_line_number "myfunction location" $srcfile]
+    set lineno(top) [gdb_get_line_number "top location" $srcfile]
+    foreach v [array names lineno] {
+	set location($v) ".*[string_to_regexp "$srcfile:$lineno($v)"].*"
+    }
+
+    # A list of explicit locations and the corresponding location.
+    variable linespecs
+    set linespecs(linespecs) {}
+    set linespecs(location) {}
+
+    add linespecs "-source $srcfile -function myfunction" $location(normal)
+    add linespecs "-source $srcfile -function myfunction -label top" \
+	$location(top)
+
+    # This isn't implemented yet; -line is silently ignored.
+    add linespecs "-source $srcfile -function myfunction -label top -line 3" \
+	$location(top)
+    add linespecs "-source $srcfile -line $lineno(top)" $location(top)
+    add linespecs "-function myfunction" $location(normal)
+    add linespecs "-function myfunction -label top" $location(top)
+
+    # These are also not yet supported; -line is silently ignored.
+    add linespecs "-function myfunction -line 3" $location(normal)
+    add linespecs "-function myfunction -label top -line 3" $location(top)
+    add linespecs "-line 3" $location(normal)
+
+    # Test that static tracepoints on marker ID are not interpreted
+    # as an erroneous explicit option.
+    gdb_test "strace -m gdbfoobarbaz" "You can't do that.*"
+
+    # Fire up gdb.
+    if {![runto_main]} {
+	return -1
+    }
+
+    # Turn off queries
+    gdb_test_no_output "set confirm off"
+
+    # Simple error tests (many more are tested in ls-err.exp)
+    foreach arg $all_arguments {
+	# Test missing argument
+	gdb_test "break -$arg" \
+	    [string_to_regexp "missing argument for \"-$arg\""]
+
+	# Test abbreviations
+	set short [string range $arg 0 3]
+	gdb_test "break -$short" \
+	    [string_to_regexp "missing argument for \"-$short\""]
+    }
+
+    # Test invalid arguments
+    foreach arg {"-foo" "-foo bar" "-function myfunction -foo" \
+		     "-function -myfunction -foo bar"} {
+	gdb_test "break $arg" \
+	    [string_to_regexp "invalid explicit location argument, \"-foo\""]
+    }
+
+    # Test explicit locations, with and without conditions.
+    # For these tests, it is easiest to turn of pending breakpoint.
+    gdb_test_no_output "set breakpoint pending off" \
+	"turn off pending breakpoints"
+
+    foreach linespec $linespecs(linespecs) loc_pattern $linespecs(locations) {
+
+	# Test the linespec
+	test_breakpoint $linespec $loc_pattern
+
+	# Test with a valid condition
+	delete_breakpoints
+	set tst "set breakpoint at \"$linespec\" with valid condition"
+	if {[gdb_breakpoint "$linespec if arg == 0"]} {
+	    pass $tst
+
+	    gdb_test "info break" ".*stop only if arg == 0.*" \
+		"info break of conditional breakpoint at \"$linespec\""
+	} else {
+	    fail $tst
+	}
+
+	# Test with invalid condition
+	gdb_test "break $linespec if foofoofoo == 1" \
+	    ".*No symbol \"foofoofoo\" in current context.*" \
+	    "set breakpoint at \"$linespec\" with invalid condition"
+
+	# Test with thread
+	delete_breakpoints
+	gdb_test "break $linespec thread 123" "Unknown thread 123."
+    }
+
+    # Test the explicit location completer
+    foreach abbrev {"fun" "so" "lab" "li"}  full {"function" "source" "label" "line"} {
+	set tst "complete 'break -$abbrev'"
+	send_gdb "break -${abbrev}\t"
+	gdb_test_multiple "" $tst {
+	    "break -$full " {
+		send_gdb "\n"
+		gdb_test_multiple "" $tst {
+		    -re "missing argument for \"-$full\".*$gdb_prompt " {
+			pass $tst
+		    }
+		}
+	    }
+	}
+	set tst "complete -$full with no value"
+	send_gdb "break -$full \t"
+	gdb_test_multiple "" $tst {
+	    -re ".*break -$full " {
+		send_gdb "\n"
+		gdb_test_multiple "" $tst {
+		    -re ".*Source filename requires function, label, or line offset\..*$gdb_prompt " {
+			if {[string equal $full "source"]} {
+			    pass $tst
+			} else {
+			    faill $tst
+			}
+		    }
+		    -re "missing argument for \"-$full\".*$gdb_prompt " {
+			pass $tst
+		    }
+		}
+	    }
+	}
+    }
+
+    set tst "complete unique function name"
+    send_gdb "break -function mai\t"
+    gdb_test_multiple "" $tst {
+	"break -function mai\\\x07n" {
+	    send_gdb "\n"
+	    gdb_test "" ".*Breakpoint \[0-9\]+.*" $tst
+	    gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
+	}
+    }
+
+    set tst "complete non-unique function name"
+    send_gdb "break -function myfunc\t"
+    gdb_test_multiple "" $tst {
+	"break -function myfunc\\\x07tion" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		-re "\\\x07\r\nmyfunction\[ \t\]+myfunction2\[ \t\]+myfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
+		    gdb_test "2" ".*Breakpoint \[0-9\]+.*" $tst
+		    gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
+		}
+	    }
+	}
+    }
+
+    set tst "complete non-existant function name"
+    send_gdb "break -function foo\t"
+    gdb_test_multiple "" $tst {
+	"break -function foo\\\x07" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		-re "\\\x07\\\x07" {
+		    send_gdb "\n"
+		    gdb_test "" {Function "foo" not defined.} $tst
+		}
+	    }
+	}
+    }
+
+    set tst "complete unique file name"
+    send_gdb "break -source 3ex\t"
+    gdb_test_multiple "" $tst {
+	"break -source 3explicit.c " {
+	    send_gdb "\n"
+	    gdb_test "" \
+		{Source filename requires function, label, or line offset.} $tst
+	}
+    }
+
+    set tst "complete non-unique file name"
+    send_gdb "break -source exp\t"
+    gdb_test_multiple "" $tst {
+	"break -source exp\\\x07licit" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		-re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+\r\n$gdb_prompt" {
+		    send_gdb "\n"
+		    gdb_test "" \
+			{Source filename requires function, label, or line offset.} \
+			$tst
+		}
+	    }
+	}
+
+	"break -source exp\\\x07l" {
+	    # This pattern may occur when glibc debuginfo is installed.
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		-re "\\\x07\r\nexplicit.c\[ \t\]+explicit2.c\[ \t\]+expl.*\r\n$gdb_prompt" {
+		    send_gdb "\n"
+		    gdb_test "" \
+			{Source filename requires function, label, or line offset.} \
+			$tst
+		}
+	    }
+	}
+    }
+
+    set tst "complete non-existant file name"
+    send_gdb "break -source foo\t"
+    gdb_test_multiple "" $tst {
+	"break -source foo" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		"\\\x07\\\x07" {
+		    send_gdb "\n"
+		    gdb_test "" \
+			{Source filename requires function, label, or line offset.} \
+			$tst
+		}
+	    }
+	}
+    }
+
+    set tst "complete filename and unique function name"
+    send_gdb "break -source explicit.c -function ma\t"
+    gdb_test_multiple "" $tst {
+	"break -source explicit.c -function main " {
+	    send_gdb "\n"
+	    gdb_test "" ".*Breakpoint .*" $tst
+	    gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
+	}
+    }
+
+    set tst "complete filename and non-unique function name"
+    send_gdb "break -so 3explicit.c -func myfunc\t"
+    gdb_test_multiple "" $tst {
+	"break -so 3explicit.c -func myfunc\\\x07tion" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		-re "\\\x07\r\nmyfunction3\[ \t\]+myfunction4\[ \t\]+\r\n$gdb_prompt " {
+		    gdb_test "3" ".*Breakpoint \[0-9\]+.*" $tst
+		    gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
+		}
+	    }
+	}
+    }
+
+    set tst "complete filename and non-existant function name"
+    send_gdb "break -sou 3explicit.c -fun foo\t"
+    gdb_test_multiple "" $tst {
+	"break -sou 3explicit.c -fun foo\\\x07" {
+	    send_gdb "\t\t"
+	    gdb_test_multiple "" $tst {
+		"\\\x07\\\x07" {
+		    send_gdb "\n"
+		    gdb_test "" \
+			{Function "foo" not defined in "3explicit.c".} $tst
+		}
+	    }
+	}
+    }
+
+    set tst "complete filename and function reversed"
+    send_gdb "break -func myfunction4 -source 3ex\t"
+    gdb_test_multiple "" $tst {
+	"break -func myfunction4 -source 3explicit.c " {
+	    send_gdb "\n"
+	    gdb_test "" "Breakpoint \[0-9\]+.*" $tst
+	    gdb_test_no_output "delete \$bpnum" "delete $tst breakpoint"
+	}
+    }
+
+    # NOTE: We don't bother testing more elaborate combinations of options,
+    # such as "-func main -sour 3ex\t" (main is defined in explicit.c).  The
+    # completer cannot handle these yet.
+
+    # Test pending explicit breakpoints
+    gdb_exit
+    gdb_start
+
+    set tst "pending invalid conditional explicit breakpoint"
+    if {![gdb_breakpoint "-func myfunction if foofoofoo == 1" \
+	      allow-pending]} {
+	fail "set $tst"
+    } else {
+	gdb_test "info break" ".*PENDING.*myfunction if foofoofoo == 1.*" $tst
+    }
+
+    gdb_exit
+    gdb_start
+
+    set tst "pending valid conditional explicit breakpoint"
+    if {![gdb_breakpoint "-func myfunction if arg == 0" \
+	      allow-pending]} {
+	fail "set $tst"
+    } else {
+	gdb_test "info break" ".*PENDING.*myfunction if arg == 0" $tst
+
+	gdb_load [standard_output_file $exefile]
+	gdb_test "info break" \
+	    ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" \
+	    "$tst resolved"
+    }
+
+    # Test interaction of condition command and explicit linespec conditons.
+    gdb_exit
+    gdb_start
+    gdb_load [standard_output_file $exefile]
+
+    set tst "condition_command overrides explicit linespec condition"
+    if {![runto main]} {
+	fail $tst
+    } else {
+	if {![gdb_breakpoint "-func myfunction if arg == 1"]} {
+	    fail "set breakpoint with condition 'arg == 1'"
+	} else {
+	    gdb_test_no_output "cond 2 arg == 0" \
+		"set new breakpoint condition for explicit linespec"
+
+	    gdb_continue_to_breakpoint $tst $location(normal)
+	}
+    }
+
+    gdb_test "cond 2" [string_to_regexp "Breakpoint 2 now unconditional."] \
+	"clear condition for explicit breakpoint"
+    set tst "info break of cleared condition of explicit breakpoint"
+    gdb_test_multiple "info break" $tst {
+	-re ".*in myfunction at .*$srcfile:.*stop only if arg == 0.*" {
+	    fail $tst
+	}
+	-re ".*in myfunction at .*$srcfile:.*$gdb_prompt $" {
+	    pass $tst
+	}
+    }
+
+    # Test explicit "ranges."  Make sure that using explicit
+    # locations doesn't alter the expected outcome.
+    gdb_test "list main" ".*" "list main 1"
+    set list_result [capture_command_output "list -,+" ""]
+    gdb_test "list main" ".*" "list main 2"
+    gdb_test "list -line -,-line +" [string_to_regexp $list_result]
+
+    # Ditto for the reverse (except that no output is expected).
+    gdb_test "list myfunction" ".*" "list myfunction 1"
+    gdb_test_no_output "list +,-"
+    gdb_test "list myfunction" ".*" "list myfunction 2"
+    gdb_test_no_output "list -line +, -line -"
+}
+
+namespace delete $testfile
diff --git a/gdb/testsuite/gdb.linespec/explicit2.c b/gdb/testsuite/gdb.linespec/explicit2.c
new file mode 100644
index 0000000..218cccb
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/explicit2.c
@@ -0,0 +1,24 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2013 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+extern int myfunction3 (int arg);
+
+int
+myfunction2 (int arg)
+{
+  return myfunction3 (arg);
+}
diff --git a/gdb/testsuite/gdb.linespec/ls-errs.exp b/gdb/testsuite/gdb.linespec/ls-errs.exp
index 019312c..9b30720 100644
--- a/gdb/testsuite/gdb.linespec/ls-errs.exp
+++ b/gdb/testsuite/gdb.linespec/ls-errs.exp
@@ -49,11 +49,16 @@  array set error_messages {
     invalid_var_or_func_f \
 	"Undefined convenience variable or function \"%s\" not defined in \"%s\"."
     invalid_label "No label \"%s\" defined in function \"%s\"."
+    invalid_parm "invalid linespec argument, \"%s\""
     invalid_offset "No line %d in the current file."
     invalid_offset_f "No line %d in file \"%s\"."
+    malformed_line_offset "malformed line offset: \"%s\""
+    source_incomplete \
+	"Source filename requires function, label, or line offset."
     unexpected "malformed linespec error: unexpected %s"
     unexpected_opt "malformed linespec error: unexpected %s, \"%s\""
     unmatched_quote "unmatched quote"
+    garbage "Garbage '%s' at end of command"
 }
 
 # Some commonly used whitespace tests around ':'.
@@ -80,6 +85,7 @@  foreach x $invalid_offsets {
 	incr offset 16
     }
     test_break $x invalid_offset $offset
+    test_break "-line $x" invalid_offset $offset
 }
 
 # Test offsets with trailing tokens w/ and w/o spaces.
@@ -91,13 +97,17 @@  foreach x $spaces {
 
 foreach x {1 +1 +100 -10} {
     test_break "3 $x" unexpected_opt "number" $x
+    test_break "-line 3 $x" garbage $x
     test_break "+10 $x" unexpected_opt "number" $x
+    test_break "-line +10 $x" garbage $x
     test_break "-10 $x" unexpected_opt "number" $x
+    test_break "-line -10 $x" garbage $x
 }
 
-test_break "3 foo" unexpected_opt "string" "foo"
-test_break "+10 foo" unexpected_opt "string" "foo"
-test_break "-10 foo" unexpected_opt "string" "foo"
+foreach x {3 +10 -10} {
+    test_break "$x foo" unexpected_opt "string" "foo"
+    test_break "-line $x foo" garbage "foo"
+}
 
 # Test invalid linespecs starting with filename.
 foreach x [list "this_file_doesn't_exist.c" \
@@ -113,6 +123,25 @@  foreach x [list "this_file_doesn't_exist.c" \
     # Remove any quoting from FILENAME for the error message.
     test_break "$x:3" invalid_file [string trim $x \"']
 }
+foreach x [list "this_file_doesn't_exist.c" \
+	       "file::colons.c" \
+	       "'file::colons.c'"] {
+    test_break "-source $x -line 3" \
+	invalid_file [string trim $x \"']
+}
+
+# Test that option lexing stops at whitespace boundaries
+test_break "-source this file has spaces.c -line 3" \
+    invalid_file "this"
+
+test_break "-function function whitespace" \
+    invalid_function "function"
+
+test_break "-source $srcfile -function function whitespace" \
+    invalid_function_f "function" $srcfile
+
+test_break "-function main -label label whitespace" \
+    invalid_label "label" "main"
 
 # Test unmatched quotes.
 foreach x {"\"src-file.c'" "'src-file.c"} {
@@ -123,7 +152,11 @@  test_break $srcfile invalid_function $srcfile
 foreach x {"foo" " foo" " foo "} {
     # Trim any leading/trailing whitespace for error messages.
     test_break "$srcfile:$x" invalid_function_f [string trim $x] $srcfile
+    test_break "-source $srcfile -function $x" \
+	invalid_function_f [string trim $x] $srcfile
     test_break "$srcfile:main:$x" invalid_label [string trim $x] "main"
+    test_break "-source $srcfile -function main -label $x" \
+	invalid_label [string trim $x] "main"
 }
 
 foreach x $spaces {
@@ -133,20 +166,26 @@  foreach x $spaces {
 
 test_break "${srcfile}::" invalid_function "${srcfile}::"
 test_break "$srcfile:3 1" unexpected_opt "number" "1"
+test_break "-source $srcfile -line 3 1" garbage "1"
 test_break "$srcfile:3 +100" unexpected_opt "number" "+100"
+test_break "-source $srcfile -line 3 +100" garbage "+100"
 test_break "$srcfile:3 -100" unexpected_opt "number" "-100"
 test_break "$srcfile:3 foo" unexpected_opt "string" "foo"
+test_break "-source $srcfile -line 3 foo" garbage "foo"
 
 foreach x $invalid_offsets {
     test_break "$srcfile:$x" invalid_offset_f $x $srcfile
     test_break "\"$srcfile:$x\"" invalid_offset_f $x $srcfile
     test_break "'$srcfile:$x'" invalid_offset_f $x $srcfile
+    test_break "-source $srcfile -line $x" invalid_offset_f $x $srcfile
 }
+test_break "-source $srcfile -line -x" malformed_line_offset "-x"
 
 # Test invalid filespecs starting with function.
 foreach x {"foobar" "foo::bar" "foo.bar" "foo ." "foo bar" "foo 1" \
 	       "foo 0" "foo +10" "foo -10" "foo +100" "foo -100"} {
     test_break $x invalid_function $x
+    test_break "-function \"$x\"" invalid_function $x
 }
 
 foreach x $spaces {
@@ -155,13 +194,12 @@  foreach x $spaces {
     test_break "main:here${x}" unexpected "end of input"
 }
 
-test_break "main 3" invalid_function "main 3"
-test_break "main +100" invalid_function "main +100"
-test_break "main -100" invalid_function "main -100"
-test_break "main foo" invalid_function "main foo"
-
 foreach x {"3" "+100" "-100" "foo"} {
+    test_break "main 3" invalid_function "main 3"
+    test_break "-function \"main $x\"" invalid_function "main $x"
     test_break "main:here $x" invalid_label "here $x" "main"
+    test_break "-function main -label \"here $x\"" \
+	invalid_label "here $x" "main"
 }
 
 foreach x {"if" "task" "thread"} {
@@ -178,3 +216,6 @@  test_break "'main.c'+3" unexpected_opt "number" "+3"
 set x {$zippo}
 test_break $x invalid_var_or_func $x
 test_break "$srcfile:$x" invalid_var_or_func_f $x $srcfile
+
+# Explicit linespec-specific tests
+test_break "-source $srcfile" source_incomplete
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index ad2ad6e..5ecef1a 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5552,14 +5552,16 @@  proc parse_args { argset } {
     # number of items expected to be passed into the procedure...
 }
 
-# Capture the output of COMMAND in a string ignoring PREFIX; return that string.
+# Capture the output of COMMAND in a string ignoring PREFIX (a regexp);
+# return that string.
+
 proc capture_command_output { command prefix } {
     global gdb_prompt
     global expect_out
 
     set output_string ""
     gdb_test_multiple "$command" "capture_command_output for $command" {
-	-re "${command}\[\r\n\]+${prefix}(.*)\[\r\n\]+$gdb_prompt $" {
+	-re "[string_to_regexp ${command}]\[\r\n\]+${prefix}(.*)\[\r\n\]+$gdb_prompt $" {
 	    set output_string $expect_out(1,string)
 	}
     }



commit eb8c4e2e66329dc7bf2024d55991efe8587075c0
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:36 2015 -0700

    Explicit locations: MI support for explicit locations
    
    This patch adds support for explicit locations to MI's -break-insert
    command. The new options, documented in the User Manual, are
    --source, --line, --function, and --label.
    
    gdb/ChangeLog:
    
    	* mi/mi-cmd-break.c (mi_cmd_break_insert_1): Add support for
    	explicit locations, options "--source", "--function",
    	"--label", and "--line".
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.mi/mi-break.exp (test_explicit_breakpoints): New proc.
    	(at toplevel): Call test_explicit_breakpoints.
    	* gdb.mi/mi-dprintf.exp: Add tests for explicit dprintf
    	breakpoints.
    	* lib/mi-support.exp (mi_make_breakpoint): Add support for
    	breakpoint conditions, "-cond".

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 57717bd..b8d089f 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,11 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* mi/mi-cmd-break.c (mi_cmd_break_insert_1): Add support for
+	explicit locations, options "--source", "--function",
+	"--label", and "--line".
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* completer.c: Include location.h.
 	(enum match_type): New enum.
 	(location_completer): Rename to ...
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index c8c988d..4aded13 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -182,6 +182,8 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   enum bptype type_wanted;
   struct event_location *location;
   struct breakpoint_ops *ops;
+  int is_explicit = 0;
+  struct explicit_location explicit;
   char *extra_string = NULL;
 
   enum opt
@@ -189,6 +191,8 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       HARDWARE_OPT, TEMP_OPT, CONDITION_OPT,
       IGNORE_COUNT_OPT, THREAD_OPT, PENDING_OPT, DISABLE_OPT,
       TRACEPOINT_OPT,
+      EXPLICIT_SOURCE_OPT, EXPLICIT_FUNC_OPT,
+      EXPLICIT_LABEL_OPT, EXPLICIT_LINE_OPT
     };
   static const struct mi_opt opts[] =
   {
@@ -200,6 +204,10 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
     {"f", PENDING_OPT, 0},
     {"d", DISABLE_OPT, 0},
     {"a", TRACEPOINT_OPT, 0},
+    {"-source" , EXPLICIT_SOURCE_OPT, 1},
+    {"-function", EXPLICIT_FUNC_OPT, 1},
+    {"-label", EXPLICIT_LABEL_OPT, 1},
+    {"-line", EXPLICIT_LINE_OPT, 1},
     { 0, 0, 0 }
   };
 
@@ -208,6 +216,8 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
   int oind = 0;
   char *oarg;
 
+  initialize_explicit_location (&explicit);
+
   while (1)
     {
       int opt = mi_getopt ("-break-insert", argc, argv,
@@ -240,16 +250,31 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
 	case TRACEPOINT_OPT:
 	  tracepoint = 1;
 	  break;
+	case EXPLICIT_SOURCE_OPT:
+	  is_explicit = 1;
+	  explicit.source_filename = oarg;
+	  break;
+	case EXPLICIT_FUNC_OPT:
+	  is_explicit = 1;
+	  explicit.function_name = oarg;
+	  break;
+	case EXPLICIT_LABEL_OPT:
+	  is_explicit = 1;
+	  explicit.label_name = oarg;
+	  break;
+	case EXPLICIT_LINE_OPT:
+	  is_explicit = 1;
+	  explicit.line_offset = linespec_parse_line_offset (oarg);
+	  break;
 	}
     }
 
-  if (oind >= argc)
+  if (oind >= argc && !is_explicit)
     error (_("-%s-insert: Missing <location>"),
 	   dprintf ? "dprintf" : "break");
-  address = argv[oind];
   if (dprintf)
     {
-      int format_num = oind + 1;
+      int format_num = is_explicit ? oind : oind + 1;
 
       if (hardware || tracepoint)
 	error (_("-dprintf-insert: does not support -h or -a"));
@@ -258,11 +283,21 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
 
       extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
       make_cleanup (xfree, extra_string);
+      address = argv[oind];
     }
   else
     {
-      if (oind < argc - 1)
-	error (_("-break-insert: Garbage following <location>"));
+      if (is_explicit)
+	{
+	  if (oind < argc)
+	    error (_("-break-insert: Garbage following explicit location"));
+	}
+      else
+	{
+	  if (oind < argc - 1)
+	    error (_("-break-insert: Garbage following <location>"));
+	  address = argv[oind];
+	}
     }
 
   /* Now we have what we need, let's insert the breakpoint!  */
@@ -291,11 +326,30 @@  mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
       ops = &bkpt_breakpoint_ops;
     }
 
-  location = string_to_event_location (&address, current_language);
-  make_cleanup_delete_event_location (location);
+  if (is_explicit)
+    {
+      /* Error check -- we must have one of the other
+	 parameters specified.  */
+      if (explicit.source_filename != NULL
+	  && explicit.function_name == NULL
+	  && explicit.label_name == NULL
+	  && explicit.line_offset.sign == LINE_OFFSET_UNKNOWN)
+	error (_("-%s-insert: --source option requires --function, --label,"
+		 " or --line"), dprintf ? "dprintf" : "break");
+
+      location = new_explicit_location (&explicit);
+    }
+  else
+    {
+      location = string_to_event_location (&address, current_language);
+      if (*address)
+	{
+	  delete_event_location (location);
+	  error (_("Garbage '%s' at end of location"), address);
+	}
+    }
 
-  if (*address)
-    error (_("Garbage '%s' at end of location"), address);
+  make_cleanup_delete_event_location (location);
 
   create_breakpoint (get_current_arch (), location, condition, thread,
 		     extra_string,
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index ae3a275..de66155 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,14 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* gdb.mi/mi-break.exp (test_explicit_breakpoints): New proc.
+	(at toplevel): Call test_explicit_breakpoints.
+	* gdb.mi/mi-dprintf.exp: Add tests for explicit dprintf
+	breakpoints.
+	* lib/mi-support.exp (mi_make_breakpoint): Add support for
+	breakpoint conditions, "-cond".
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* gdb.linespec/3explicit.c: New file.
 	* gdb.linespec/cpexplicit.cc: New file.
 	* gdb.linespec/cpexplicit.exp: New file.
diff --git a/gdb/testsuite/gdb.mi/mi-break.exp b/gdb/testsuite/gdb.mi/mi-break.exp
index a86ba8c..60bab0e 100644
--- a/gdb/testsuite/gdb.mi/mi-break.exp
+++ b/gdb/testsuite/gdb.mi/mi-break.exp
@@ -305,6 +305,86 @@  proc test_breakpoint_commands {} {
     mi_expect_stop "exited-normally" "" "" "" "" "" "test hitting breakpoint with commands"
 }
 
+# Test explicit breakpoints.  These tests only test the MI portion of the
+# code.  In-depth testing of explicit breakpoints is accomplished in
+# gdb.linespec tests.
+
+proc test_explicit_breakpoints {} {
+    global srcfile
+    global line_callee3_head line_callee4_head
+    global line_callee2_body line_main_body
+
+    mi_delete_breakpoints
+
+    # First check mixed explicit/parsed linespecs.
+    mi_gdb_test "-break-insert --function main $srcfile:$line_callee3_head" \
+	".*Garbage following explicit linespec"
+
+    # Insert some breakpoints and list them
+    # Also, disable some so they do not interfere with other tests
+    # Tests:
+    # -break-insert -t --function main
+    # -break-insert -t --source basics.c --function callee2
+    # -break-insert -t --source basics.c --line $line_callee3_head
+    # -break-insert -t --source srcfile --line $line_callee4_head
+    # -break-list
+
+    set bps {}
+    lappend bps [mi_create_breakpoint "-t --function main" \
+		     "insert temp explicit breakpoint in main" \
+		     -func main -file ".*$srcfile" -line $line_main_body]
+
+    lappend bps \
+	[mi_create_breakpoint "-t --source $srcfile --function callee2" \
+	     "insert temp explicit breakpoint at $srcfile:callee2" \
+	     -func callee2 -file ".*$srcfile" -line $line_callee2_body]
+
+    lappend bps \
+	[mi_create_breakpoint "-t --source $srcfile --line $line_callee3_head" \
+	     "insert temp explicit breakpoint at $srcfile:$line_callee3_head" \
+	     -func callee3 -file ".*$srcfile" -line $line_callee3_head]
+
+    lappend bps \
+	[mi_create_breakpoint \
+	     "-t --source \"$srcfile\" --line  $line_callee4_head" \
+	     "insert temp explicit breakpoint at \"$srcfile\":$line_callee4_head" \
+	     -func callee4 -file ".*$srcfile" -line $line_callee4_head]
+
+    mi_gdb_test "-break-list" "\\^done,[mi_make_breakpoint_table $bps]" \
+	"list of explicit breakpoints"
+
+    mi_gdb_test "-break-delete" \
+	    "\\^done" \
+	    "delete temp breakpoints"
+
+    mi_create_breakpoint "-c \"intarg == 3\" --function callee2" \
+	"insert explicit conditional breakpoint in callee2" \
+	-func callee2 ".*$srcfile" -line $line_callee2_body \
+	-cond "intarg == 3"
+
+    # mi_create_breakpoint cannot deal with displaying canonical
+    # linespecs.
+    mi_gdb_test \
+	"-break-insert -c \"foo == 3\" --source $srcfile --function main --label label" \
+	".*No symbol \"foo\" in current context.*"
+
+    mi_gdb_test \
+	"-break-insert --source foobar.c --line 3" \
+	".*No source file named foobar.c.*"
+
+    mi_gdb_test \
+	"-break-insert --source $srcfile --function foobar" \
+	".*Function \"foobar\" not defined in \"$srcfile\".*"
+
+    mi_gdb_test \
+	"-break-insert --source $srcfile --function main --label foobar" \
+	".*No label \"foobar\" defined in function \"main\".*"
+
+    mi_gdb_test \
+	"-break-insert --source $srcfile" \
+	".*Source filename requires function, label, or line offset.*"
+}
+
 test_tbreak_creation_and_listing
 test_rbreak_creation_and_listing
 
@@ -318,5 +398,7 @@  test_breakpoint_commands
 
 test_abreak_creation
 
+test_explicit_breakpoints
+
 mi_gdb_exit
 return 0
diff --git a/gdb/testsuite/gdb.mi/mi-dprintf.exp b/gdb/testsuite/gdb.mi/mi-dprintf.exp
index c205724..08885e9 100644
--- a/gdb/testsuite/gdb.mi/mi-dprintf.exp
+++ b/gdb/testsuite/gdb.mi/mi-dprintf.exp
@@ -47,6 +47,16 @@  mi_gdb_test "[incr i]-dprintf-insert 29" \
     "$i\\^error,msg=\"-dprintf-insert: Missing <format>\"" "mi insert second breakpoint without format string"
 
 mi_gdb_test "-break-insert main" ".*" "mi insert breakpoint main"
+
+mi_gdb_test "-dprintf-insert --function main \"hello\"" \
+    "\\^done,bkpt={.*}" "explicit dprintf at main"
+
+mi_gdb_test "-dprintf-insert --source $srcfile --line $dp_location1 \"hello\"" \
+    "\\^done,bkpt={.*}" "explicit breakpoint at $srcfile:$dp_location1"
+
+mi_gdb_test "-dprintf-insert --source $srcfile \"hello\"" \
+    "\\^error,msg=\"-dprintf-insert: --source option requires --function, --label, or --line\"" "invalid explicit dprintf"
+
 mi_delete_breakpoints
 
 set bps [mi_make_breakpoint -type dprintf -func foo -file ".*mi-dprintf.c" \
@@ -61,7 +71,7 @@  mi_gdb_test "[incr i]-dprintf-insert $dp_location1 \"arg=%d, g=%d\\n\" arg g" \
 		   "$i\\^done,$bps" "mi insert dprintf dp_location1"
 
 set bps {}
-lappend bps [mi_make_breakpoint -number 3 -type dprintf -func foo \
+lappend bps [mi_make_breakpoint -type dprintf -func foo \
 		 -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c"]
 lappend bps [mi_make_breakpoint -type dprintf -func foo \
 		 -file ".*mi-dprintf.c" -fullname ".*mi-dprintf.c" \
diff --git a/gdb/testsuite/lib/mi-support.exp b/gdb/testsuite/lib/mi-support.exp
index 27b2ebc..74e893d 100644
--- a/gdb/testsuite/lib/mi-support.exp
+++ b/gdb/testsuite/lib/mi-support.exp
@@ -2395,7 +2395,7 @@  proc mi_build_kv_pairs {attr_list {joiner ,}} {
 #
 # All arguments for the breakpoint may be specified using the options
 # number, type, disp, enabled, addr, func, file, fullanme, line,
-# thread-groups, times, ignore, script, and original-location.
+# thread-groups, cond, times, ignore, script, and original-location.
 #
 # Only if -script and -ignore are given will they appear in the output.
 # Otherwise, this procedure will skip them using ".*".
@@ -2410,17 +2410,27 @@  proc mi_make_breakpoint {args} {
     parse_args {{number .*} {type .*} {disp .*} {enabled .*} {addr .*}
 	{func .*} {file .*} {fullname .*} {line .*}
 	{thread-groups \\\[.*\\\]} {times .*} {ignore 0}
-	{script ""} {original-location .*}}
+	{script ""} {original-location .*} {cond ""}}
 
     set attr_list {}
     foreach attr [list number type disp enabled addr func file \
-		      fullname line thread-groups times] {
+		      fullname line thread-groups] {
 	lappend attr_list $attr [set $attr]
     }
 
     set result "bkpt={[mi_build_kv_pairs $attr_list]"
 
     # There are always exceptions.
+
+    # If COND is not preset, do not output it.
+    if {[string length $cond] > 0} {
+	append result ","
+	append result [mi_build_kv_pairs [list "cond" $cond]]
+    }
+
+    append result ","
+    append result [mi_build_kv_pairs [list "times" $times]]
+
     # If SCRIPT and IGNORE are not present, do not output them.
     if {$ignore != 0} {
 	append result ","



commit 629500fae69737a6230a564e8fef1f42c3ef1116
Author: Keith Seitz <keiths@redhat.com>
Date:   Tue Aug 11 17:09:36 2015 -0700

    Explicit locations: documentation updates
    
    This patch adds documentation for explicit locations to both the
    User Manual and gdb's online help system.
    
    gdb/ChangeLog:
    
    	* NEWS: Mention explicit locations.
    	* breakpoint.c [LOCATION_HELP_STRING]: New macro.
    	[BREAK_ARGS_HELP]: Use LOCATION_HELP_STRING.
    	(_initialize_breakpoint): Update documentation for
    	"clear", "break", "trace", "strace", "ftrace", and "dprintf".
    
    gdb/doc/ChangeLog:
    
    	* gdb.texinfo (Thread-Specific Breakpoints, Printing Source Lines):
    	Use "location(s)"instead of "linespec(s)".
    	(Specifying a Location): Rewrite.
    	Add subsections describing linespec, address, and explicit locations.
    	Add node/menu for each subsection.
    	(Source and Machine Code, C Preprocessor Macros)
    	(Create and Delete Trace points)
    	(Extensions for Ada Tasks): Use "location(s)" instead of "linespec(s)".
    	(Continuing at a Different Address): Remove "linespec" examples.
    	Add reference to "Specify a Location"
    	(The -break-insert Command): Rewrite.  Add anchor.
    	Add reference to appropriate manual section discussing locations.
    	(The -dprintf-insert Command): Refer to -break-insert for
    	specification of 'location'.
    
    gdb/testsuite/ChangeLog:
    
    	* gdb.base/help.exp: Update help_breakpoint_text.

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index b8d089f..01e9938 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* NEWS: Mention explicit locations.
+	* breakpoint.c [LOCATION_HELP_STRING]: New macro.
+	[BREAK_ARGS_HELP]: Use LOCATION_HELP_STRING.
+	(_initialize_breakpoint): Update documentation for
+	"clear", "break", "trace", "strace", "ftrace", and "dprintf".
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* mi/mi-cmd-break.c (mi_cmd_break_insert_1): Add support for
 	explicit locations, options "--source", "--function",
 	"--label", and "--line".
diff --git a/gdb/NEWS b/gdb/NEWS
index 3fe6036..950a866 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -8,6 +8,10 @@ 
 * The 'record instruction-history' command now indicates speculative execution
   when using the Intel(R) Processor Trace recording format.
 
+* GDB now allows users to specify explicit locations, bypassing
+  the linespec parser.  This feature is also available to GDB/MI
+  clients.
+
 * New commands
 
 maint set target-non-stop (on|off|auto)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e6bee3d..bffff23 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -15566,26 +15566,46 @@  all_tracepoints (void)
 }
 
 
+/* This help string is used to consolidate all the help string for specifying
+   locations used by several commands.  */
+
+#define LOCATION_HELP_STRING \
+"Linespecs are colon-separated lists of location parameters, such as\n\
+source filename, function name, label name, and line number.\n\
+Example: To specify the start of a label named \"the_top\" in the\n\
+function \"fact\" in the file \"factorial.c\", use\n\
+\"factorial.c:fact:the_top\".\n\
+\n\
+Address locations begin with \"*\" and specify an exact address in the\n\
+program.  Example: To specify the fourth byte past the start function\n\
+\"main\", use \"*main + 4\".\n\
+\n\
+Explicit locations are similar to linespecs but use an option/argument\n\
+syntax to specify location parameters.\n\
+Example: To specify the start of the label named \"the_top\" in the\n\
+function \"fact\" in the file \"factorial.c\", use \"-source factorial.c\n\
+-function fact -label the_top\".\n"
+
 /* This help string is used for the break, hbreak, tbreak and thbreak
    commands.  It is defined as a macro to prevent duplication.
    COMMAND should be a string constant containing the name of the
    command.  */
+
 #define BREAK_ARGS_HELP(command) \
 command" [PROBE_MODIFIER] [LOCATION] [thread THREADNUM] [if CONDITION]\n\
 PROBE_MODIFIER shall be present if the command is to be placed in a\n\
 probe point.  Accepted values are `-probe' (for a generic, automatically\n\
 guessed probe type), `-probe-stap' (for a SystemTap probe) or \n\
 `-probe-dtrace' (for a DTrace probe).\n\
-LOCATION may be a line number, function name, or \"*\" and an address.\n\
-If a line number is specified, break at start of code for that line.\n\
-If a function is specified, break at start of code for that function.\n\
-If an address is specified, break at that exact address.\n\
+LOCATION may be a linespec, address, or explicit location as described\n\
+below.\n\
+\n\
 With no LOCATION, uses current execution address of the selected\n\
 stack frame.  This is useful for breaking on return to a stack frame.\n\
 \n\
 THREADNUM is the number from \"info threads\".\n\
 CONDITION is a boolean expression.\n\
-\n\
+\n" LOCATION_HELP_STRING "\n\
 Multiple breakpoints at one place are permitted, and useful if their\n\
 conditions are different.\n\
 \n\
@@ -16032,20 +16052,17 @@  This command may be abbreviated \"delete\"."),
 	   &deletelist);
 
   add_com ("clear", class_breakpoint, clear_command, _("\
-Clear breakpoint at specified line or function.\n\
-Argument may be line number, function name, or \"*\" and an address.\n\
-If line number is specified, all breakpoints in that line are cleared.\n\
-If function is specified, breakpoints at beginning of function are cleared.\n\
-If an address is specified, breakpoints at that address are cleared.\n\
+Clear breakpoint at specified location.\n\
+Argument may be a linespec, explicit, or address location as described below.\n\
 \n\
 With no argument, clears all breakpoints in the line that the selected frame\n\
-is executing in.\n\
-\n\
+is executing in.\n"
+"\n" LOCATION_HELP_STRING "\n\
 See also the \"delete\" command which clears breakpoints by number."));
   add_com_alias ("cl", "clear", class_breakpoint, 1);
 
   c = add_com ("break", class_breakpoint, break_command, _("\
-Set breakpoint at specified line or function.\n"
+Set breakpoint at specified location.\n"
 BREAK_ARGS_HELP ("break")));
   set_cmd_completer (c, location_completer);
 
@@ -16208,7 +16225,7 @@  hardware.)"),
   /* Tracepoint manipulation commands.  */
 
   c = add_com ("trace", class_breakpoint, trace_command, _("\
-Set a tracepoint at specified line or function.\n\
+Set a tracepoint at specified location.\n\
 \n"
 BREAK_ARGS_HELP ("trace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
@@ -16220,31 +16237,27 @@  Do \"help tracepoints\" for info on other tracepoint commands."));
   add_com_alias ("trac", "trace", class_alias, 1);
 
   c = add_com ("ftrace", class_breakpoint, ftrace_command, _("\
-Set a fast tracepoint at specified line or function.\n\
+Set a fast tracepoint at specified location.\n\
 \n"
 BREAK_ARGS_HELP ("ftrace") "\n\
 Do \"help tracepoints\" for info on other tracepoint commands."));
   set_cmd_completer (c, location_completer);
 
   c = add_com ("strace", class_breakpoint, strace_command, _("\
-Set a static tracepoint at specified line, function or marker.\n\
+Set a static tracepoint at location or marker.\n\
 \n\
 strace [LOCATION] [if CONDITION]\n\
-LOCATION may be a line number, function name, \"*\" and an address,\n\
-or -m MARKER_ID.\n\
-If a line number is specified, probe the marker at start of code\n\
-for that line.  If a function is specified, probe the marker at start\n\
-of code for that function.  If an address is specified, probe the marker\n\
-at that exact address.  If a marker id is specified, probe the marker\n\
-with that name.  With no LOCATION, uses current execution address of\n\
-the selected stack frame.\n\
+LOCATION may be a linespec, explicit, or address location (described below) \n\
+or -m MARKER_ID.\n\n\
+If a marker id is specified, probe the marker with that name.  With\n\
+no LOCATION, uses current execution address of the selected stack frame.\n\
 Static tracepoints accept an extra collect action -- ``collect $_sdata''.\n\
 This collects arbitrary user data passed in the probe point call to the\n\
 tracing library.  You can inspect it when analyzing the trace buffer,\n\
 by printing the $_sdata variable like any other convenience variable.\n\
 \n\
 CONDITION is a boolean expression.\n\
-\n\
+\n" LOCATION_HELP_STRING "\n\
 Multiple tracepoints at one place are permitted, and useful if their\n\
 conditions are different.\n\
 \n\
@@ -16396,11 +16409,10 @@  an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
 range (including START-LOCATION and END-LOCATION)."));
 
   c = add_com ("dprintf", class_breakpoint, dprintf_command, _("\
-Set a dynamic printf at specified line or function.\n\
+Set a dynamic printf at specified location.\n\
 dprintf location,format string,arg1,arg2,...\n\
-location may be a line number, function name, or \"*\" and an address.\n\
-If a line number is specified, break at start of code for that line.\n\
-If a function is specified, break at start of code for that function."));
+location may be a linespec, explicit, or address location.\n"
+"\n" LOCATION_HELP_STRING));
   set_cmd_completer (c, location_completer);
 
   add_setshow_enum_cmd ("dprintf-style", class_support,
diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog
index 846ac24..5b3d9a1 100644
--- a/gdb/doc/ChangeLog
+++ b/gdb/doc/ChangeLog
@@ -1,3 +1,20 @@ 
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+	* gdb.texinfo (Thread-Specific Breakpoints, Printing Source Lines):
+	Use "location(s)"instead of "linespec(s)".
+	(Specifying a Location): Rewrite.
+	Add subsections describing linespec, address, and explicit locations.
+	Add node/menu for each subsection.
+	(Source and Machine Code, C Preprocessor Macros)
+	(Create and Delete Trace points)
+	(Extensions for Ada Tasks): Use "location(s)" instead of "linespec(s)".
+	(Continuing at a Different Address): Remove "linespec" examples.
+	Add reference to "Specify a Location"
+	(The -break-insert Command): Rewrite.  Add anchor.
+	Add reference to appropriate manual section discussing locations.
+	(The -dprintf-insert Command): Refer to -break-insert for
+	specification of 'location'.
+
 2015-08-07  Pedro Alves  <palves@redhat.com>
 
 	* gdb.texinfo (Maintenance Commands): Document "maint set/show
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 900970b..c64c7a1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6060,9 +6060,9 @@  breakpoints on all threads, or on a particular thread.
 @cindex breakpoints and threads
 @cindex thread breakpoints
 @kindex break @dots{} thread @var{threadno}
-@item break @var{linespec} thread @var{threadno}
-@itemx break @var{linespec} thread @var{threadno} if @dots{}
-@var{linespec} specifies source lines; there are several ways of
+@item break @var{location} thread @var{threadno}
+@itemx break @var{location} thread @var{threadno} if @dots{}
+@var{location} specifies source lines; there are several ways of
 writing them (@pxref{Specify Location}), but the effect is always to
 specify some source line.
 
@@ -7531,21 +7531,21 @@  argument of @samp{-}; that argument is preserved in repetition so that
 each repetition moves up in the source file.
 
 In general, the @code{list} command expects you to supply zero, one or two
-@dfn{linespecs}.  Linespecs specify source lines; there are several ways
+@dfn{locations}.  Locations specify source lines; there are several ways
 of writing them (@pxref{Specify Location}), but the effect is always
 to specify some source line.
 
 Here is a complete description of the possible arguments for @code{list}:
 
 @table @code
-@item list @var{linespec}
-Print lines centered around the line specified by @var{linespec}.
+@item list @var{location}
+Print lines centered around the line specified by @var{location}.
 
 @item list @var{first},@var{last}
 Print lines from @var{first} to @var{last}.  Both arguments are
-linespecs.  When a @code{list} command has two linespecs, and the
-source file of the second linespec is omitted, this refers to
-the same source file as the first linespec.
+locations.  When a @code{list} command has two locations, and the
+source file of the second location is omitted, this refers to
+the same source file as the first location.
 
 @item list ,@var{last}
 Print lines ending with @var{last}.
@@ -7566,15 +7566,28 @@  As described in the preceding table.
 @node Specify Location
 @section Specifying a Location
 @cindex specifying location
-@cindex linespec
+@cindex location
+@cindex source location
+
+@menu
+* Linespec Locations::                Linespec locations
+* Explicit Locations::                Explicit locations
+* Address Locations::                 Address locations
+@end menu
 
 Several @value{GDBN} commands accept arguments that specify a location
 of your program's code.  Since @value{GDBN} is a source-level
-debugger, a location usually specifies some line in the source code;
-for that reason, locations are also known as @dfn{linespecs}.
+debugger, a location usually specifies some line in the source code.
+Locations may be specified using three different formats:
+linespec locations, explicit locations, or address locations.
 
-Here are all the different ways of specifying a code location that
-@value{GDBN} understands:
+@node Linespec Locations
+@subsection Linespec Locations
+@cindex linespec locations
+
+A @dfn{linespec} is a colon-separated list of source location parameters such
+as file name, function name, etc.  Here are all the different ways of
+specifying a linespec:
 
 @table @code
 @item @var{linenum}
@@ -7613,25 +7626,93 @@  function name to avoid ambiguity when there are identically named
 functions in different source files.
 
 @item @var{label}
-Specifies the line at which the label named @var{label} appears.
-@value{GDBN} searches for the label in the function corresponding to
-the currently selected stack frame.  If there is no current selected
-stack frame (for instance, if the inferior is not running), then
-@value{GDBN} will not search for a label.
-
-@item *@var{address}
-Specifies the program address @var{address}.  For line-oriented
-commands, such as @code{list} and @code{edit}, this specifies a source
-line that contains @var{address}.  For @code{break} and other
-breakpoint oriented commands, this can be used to set breakpoints in
+Specifies the line at which the label named @var{label} appears
+in the function corresponding to the currently selected stack frame.
+If there is no current selected stack frame (for instance, if the inferior
+is not running), then @value{GDBN} will not search for a label.
+
+@cindex breakpoint at static probe point
+@item -pstap|-probe-stap @r{[}@var{objfile}:@r{[}@var{provider}:@r{]}@r{]}@var{name}
+The @sc{gnu}/Linux tool @code{SystemTap} provides a way for
+applications to embed static probes.  @xref{Static Probe Points}, for more
+information on finding and using static probes.  This form of linespec
+specifies the location of such a static probe.
+
+If @var{objfile} is given, only probes coming from that shared library
+or executable matching @var{objfile} as a regular expression are considered.
+If @var{provider} is given, then only probes from that provider are considered.
+If several probes match the spec, @value{GDBN} will insert a breakpoint at
+each one of those probes.
+@end table
+
+@node Explicit Locations
+@subsection Explicit Locations
+@cindex explicit locations
+
+@dfn{Explicit locations} allow the user to directly specify the source
+location's parameters using option-value pairs.
+
+Explicit locations are useful when several functions, labels, or
+file names have the same name (base name for files) in the program's
+sources.  In these cases, explicit locations point to the source
+line you meant more accurately and unambiguously.  Also, using
+explicit locations might be faster in large programs.
+
+For example, the linespec @samp{foo:bar} may refer to a function @code{bar}
+defined in the file named @file{foo} or the label @code{bar} in a function
+named @code{foo}.  @value{GDBN} must search either the file system or
+the symbol table to know.
+
+The list of valid explicit location options is summarized in the
+following table:
+
+@table @code
+@item -source @var{filename}
+The value specifies the source file name.  To differentiate between
+files with the same base name, prepend as many directories as is necessary
+to uniquely identify the desired file, e.g., @file{foo/bar/baz.c}.  Otherwise
+@value{GDBN} will use the first file it finds with the given base
+name.   This option requires the use of either @code{-function} or @code{-line}.
+
+@item -function @var{function}
+The value specifies the name of a function.  Operations
+on function locations unmodified by other options (such as @code{-label}
+or @code{-line}) refer to the line that begins the body of the function.
+In C, for example, this is the line with the open brace.
+
+@item -label @var{label}
+The value specifies the name of a label.  When the function
+name is not specified, the label is searched in the function of the currently
+selected stack frame.
+
+@item -line @var{number}
+The value specifies a line offset for the location.  The offset may either
+be absolute (@code{-line 3}) or relative (@code{-line +3}), depending on
+the command.  When specified without any other options, the line offset is
+relative to the current line.
+@end table
+
+Explicit location options may be abbreviated by omitting any non-unique
+trailing characters from the option name, e.g., @code{break -s main.c -li 3}.
+
+@node Address Locations
+@subsection Address Locations
+@cindex address locations
+
+@dfn{Address locations} indicate a specific program address.  They have
+the generalized form *@var{address}.
+
+For line-oriented commands, such as @code{list} and @code{edit}, this
+specifies a source line that contains @var{address}.  For @code{break} and
+other breakpoint-oriented commands, this can be used to set breakpoints in
 parts of your program which do not have debugging information or
 source files.
 
 Here @var{address} may be any expression valid in the current working
 language (@pxref{Languages, working language}) that specifies a code
 address.  In addition, as a convenience, @value{GDBN} extends the
-semantics of expressions used in locations to cover the situations
-that frequently happen during debugging.  Here are the various forms
+semantics of expressions used in locations to cover several situations
+that frequently occur during debugging.  Here are the various forms
 of @var{address}:
 
 @table @code
@@ -7656,22 +7737,6 @@  specify the function unambiguously, e.g., if there are several
 functions with identical names in different source files.
 @end table
 
-@cindex breakpoint at static probe point
-@item -pstap|-probe-stap @r{[}@var{objfile}:@r{[}@var{provider}:@r{]}@r{]}@var{name}
-The @sc{gnu}/Linux tool @code{SystemTap} provides a way for
-applications to embed static probes.  @xref{Static Probe Points}, for more
-information on finding and using static probes.  This form of linespec
-specifies the location of such a static probe.
-
-If @var{objfile} is given, only probes coming from that shared library
-or executable matching @var{objfile} as a regular expression are considered.
-If @var{provider} is given, then only probes from that provider are considered.
-If several probes match the spec, @value{GDBN} will insert a breakpoint at
-each one of those probes.
-
-@end table
-
-
 @node Edit
 @section Editing Source Files
 @cindex editing source files
@@ -7989,9 +8054,9 @@  well as hex.
 
 @table @code
 @kindex info line
-@item info line @var{linespec}
+@item info line @var{location}
 Print the starting and ending addresses of the compiled code for
-source line @var{linespec}.  You can specify source lines in any of
+source line @var{location}.  You can specify source lines in any of
 the ways documented in @ref{Specify Location}.
 @end table
 
@@ -8009,7 +8074,7 @@  Line 895 of "builtin.c" starts at pc 0x634c and ends at 0x6350.
 @noindent
 @cindex code address and its source line
 We can also inquire (using @code{*@var{addr}} as the form for
-@var{linespec}) what source line covers a particular address:
+@var{location}) what source line covers a particular address:
 @smallexample
 (@value{GDBP}) info line *0x63ff
 Line 926 of "builtin.c" starts at pc 0x63e4 and ends at 0x6404.
@@ -8119,7 +8184,7 @@  Dump of assembler code from 0x400281 to 0x40028b:
 End of assembler dump.
 @end smallexample
 
-Addresses cannot be specified as a linespec (@pxref{Specify Location}).
+Addresses cannot be specified as a location (@pxref{Specify Location}).
 So, for example, if you want to disassemble function @code{bar}
 in file @file{foo.c}, you must type @samp{disassemble 'foo.c'::bar}
 and not @samp{disassemble foo.c:bar}.
@@ -11772,9 +11837,9 @@  argument processing and the beginning of @var{macro} for non C-like macros where
 the macro may begin with a hyphen.
 
 @kindex info macros
-@item info macros @var{linespec}
+@item info macros @var{location}
 Show all macro definitions that are in effect at the location specified
-by @var{linespec},  and describe the source location or compiler
+by @var{location},  and describe the source location or compiler
 command-line where those definitions were established.
 
 @kindex macro define
@@ -12079,12 +12144,11 @@  conditions and actions.
 @kindex trace
 @item trace @var{location}
 The @code{trace} command is very similar to the @code{break} command.
-Its argument @var{location} can be a source line, a function name, or
-an address in the target program.  @xref{Specify Location}.  The
-@code{trace} command defines a tracepoint, which is a point in the
-target program where the debugger will briefly stop, collect some
-data, and then allow the program to continue.  Setting a tracepoint or
-changing its actions takes effect immediately if the remote stub
+Its argument @var{location} can be any valid location.
+@xref{Specify Location}.  The @code{trace} command defines a tracepoint,
+which is a point in the target program where the debugger will briefly stop,
+collect some data, and then allow the program to continue.  Setting a tracepoint
+or changing its actions takes effect immediately if the remote stub
 supports the @samp{InstallInTrace} feature (@pxref{install tracepoint
 in tracing}).
 If remote stub doesn't support the @samp{InstallInTrace} feature, all
@@ -15964,14 +16028,14 @@  from the current task to the given task.
 #4  0x804aacc in un () at un.adb:5
 @end smallexample
 
-@item break @var{linespec} task @var{taskno}
-@itemx break @var{linespec} task @var{taskno} if @dots{}
+@item break @var{location} task @var{taskno}
+@itemx break @var{location} task @var{taskno} if @dots{}
 @cindex breakpoints and tasks, in Ada
 @cindex task breakpoints, in Ada
 @kindex break @dots{} task @var{taskno}@r{ (Ada)}
 These commands are like the @code{break @dots{} thread @dots{}}
 command (@pxref{Thread Stops}).  The
-@var{linespec} argument specifies source lines, as described
+@var{location} argument specifies source lines, as described
 in @ref{Specify Location}.
 
 Use the qualifier @samp{task @var{taskno}} with a breakpoint command
@@ -16899,20 +16963,17 @@  an address of your own choosing, with the following commands:
 @table @code
 @kindex jump
 @kindex j @r{(@code{jump})}
-@item jump @var{linespec}
-@itemx j @var{linespec}
-@itemx jump @var{location}
+@item jump @var{location}
 @itemx j @var{location}
-Resume execution at line @var{linespec} or at address given by
-@var{location}.  Execution stops again immediately if there is a
-breakpoint there.  @xref{Specify Location}, for a description of the
-different forms of @var{linespec} and @var{location}.  It is common
+Resume execution at @var{location}.  Execution stops again immediately
+if there is a breakpoint there.  @xref{Specify Location}, for a description
+of the different forms of @var{location}.  It is common
 practice to use the @code{tbreak} command in conjunction with
 @code{jump}.  @xref{Set Breaks, ,Setting Breakpoints}.
 
 The @code{jump} command does not change the current stack frame, or
 the stack pointer, or the contents of any memory location or any
-register other than the program counter.  If line @var{linespec} is in
+register other than the program counter.  If @var{location} is in
 a different function from the one currently executing, the results may
 be bizarre if the two functions expect different patterns of arguments or
 of local variables.  For this reason, the @code{jump} command requests
@@ -26851,6 +26912,7 @@  N.A.
 
 @subheading The @code{-break-insert} Command
 @findex -break-insert
+@anchor{-break-insert}
 
 @subsubheading Synopsis
 
@@ -26863,16 +26925,35 @@  N.A.
 @noindent
 If specified, @var{location}, can be one of:
 
-@itemize @bullet
-@item function
-@c @item +offset
-@c @item -offset
-@c @item linenum
-@item filename:linenum
-@item filename:function
-@item *address
-@end itemize
+@table @var
+@item linespec location
+A linespec location.  @xref{Linespec Locations}.
+
+@item explicit location
+An explicit location.  @sc{gdb/mi} explicit locations are
+analogous to the CLI's explicit locations using the option names
+listed below.  @xref{Explicit Locations}.
+
+@table @samp
+@item --source @var{filename}
+The source file name of the location.  This option requires the use
+of either @samp{--function} or @samp{--line}.
+
+@item --function @var{function}
+The name of a function or method.
 
+@item --label @var{label}
+The name of a label.
+
+@item --line @var{lineoffset}
+An absolute or relative line offset from the start of the location.
+@end table
+
+@item address location
+An address location, *@var{address}.  @xref{Address Locations}.
+@end table
+
+@noindent
 The possible optional parameters of this command are:
 
 @table @samp
@@ -26964,17 +27045,8 @@  times="0"@}]@}
 @end smallexample
 
 @noindent
-If specified, @var{location}, can be one of:
-
-@itemize @bullet
-@item @var{function}
-@c @item +offset
-@c @item -offset
-@c @item @var{linenum}
-@item @var{filename}:@var{linenum}
-@item @var{filename}:function
-@item *@var{address}
-@end itemize
+If supplied, @var{location} may be specified the same way as for
+the @code{-break-insert} command.  @xref{-break-insert}.
 
 The possible optional parameters of this command are:
 
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index de66155..7af0868 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,5 +1,9 @@ 
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
+	* gdb.base/help.exp: Update help_breakpoint_text.
+
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
 	* gdb.mi/mi-break.exp (test_explicit_breakpoints): New proc.
 	(at toplevel): Call test_explicit_breakpoints.
 	* gdb.mi/mi-dprintf.exp: Add tests for explicit dprintf
diff --git a/gdb/testsuite/gdb.base/help.exp b/gdb/testsuite/gdb.base/help.exp
index 565e339..22e6aa3 100644
--- a/gdb/testsuite/gdb.base/help.exp
+++ b/gdb/testsuite/gdb.base/help.exp
@@ -58,7 +58,7 @@  test_class_help "user-defined" {
 }
 
 # Test help of an abbreviated command.  "break" is picked at random.
-set help_breakpoint_text "Set breakpoint at specified line or function\..*"
+set help_breakpoint_text "Set breakpoint at specified location\..*"
 # test help breakpoint "b" abbreviation
 gdb_test "help b" $help_breakpoint_text "help breakpoint \"b\" abbreviation"
 # test help breakpoint "br" abbreviation