public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] Eliminate the two-level data structures behind location_specs
@ 2022-06-17  9:23 Pedro Alves
  0 siblings, 0 replies; only message in thread
From: Pedro Alves @ 2022-06-17  9:23 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=40d97ee21fc3e39db73ee8f84b847a22f9d251cc

commit 40d97ee21fc3e39db73ee8f84b847a22f9d251cc
Author: Pedro Alves <pedro@palves.net>
Date:   Fri May 27 13:13:41 2022 +0100

    Eliminate the two-level data structures behind location_specs
    
    Currently, there's the location_spec hierarchy, and then some
    location_spec subclasses have their own struct type holding all their
    data fields.
    
    I.e., there is this:
    
     location_spec
       explicit_location_spec
       linespec_location_spec
       address_location_spec
       probe_location_spec
    
    and then these separate types:
    
      explicit_location
      linespec_location
    
    where:
    
      explicit_location_spec
         has-a explicit_location
      linespec_location_spec
         has-a linespec_location
    
    This patch eliminates explicit_location and linespec_location,
    inlining their members in the corresponding location_spec type.
    
    The location_spec subclasses were the ones currently defined in
    location.c, so they are moved to the header.  Since the definitions of
    the classes are now visible, we no longer need location_spec_deleter.
    
    Some constructors that are used for cloning location_specs, like:
    
      explicit explicit_location_spec (const struct explicit_location *loc)
    
    ... were converted to proper copy ctors.
    
    In the process, initialize_explicit_location is eliminated, and some
    functions that returned the "data type behind a locspec", like
    get_linespec_location are converted to downcast functions, like
    as_linespec_location_spec.
    
    Change-Id: Ia31ccef9382b25a52b00fa878c8df9b8cf2a6c5a

Diff:
---
 gdb/break-catch-throw.c    |   9 +-
 gdb/breakpoint.c           |  44 ++--
 gdb/completer.c            |   6 +-
 gdb/linespec.c             | 106 +++++-----
 gdb/location.c             | 512 +++++++++++++++++----------------------------
 gdb/location.h             | 233 +++++++++++++++------
 gdb/mi/mi-cmd-break.c      |  25 ++-
 gdb/probe.c                |   2 +-
 gdb/python/py-breakpoint.c |  21 +-
 9 files changed, 452 insertions(+), 506 deletions(-)

diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 3ef4b972d4f..2eb24f3b76c 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -225,12 +225,9 @@ exception_catchpoint::re_set ()
 	 catchpoint mode.  */
       try
 	{
-	  struct explicit_location explicit_loc;
-
-	  initialize_explicit_location (&explicit_loc);
-	  explicit_loc.function_name
-	    = ASTRDUP (exception_functions[kind].function);
-	  location_spec_up locspec = new_explicit_location_spec (&explicit_loc);
+	  location_spec_up locspec
+	    = (new_explicit_location_spec_function
+	       (exception_functions[kind].function));
 	  sals = this->decode_location_spec (locspec.get (), filter_pspace);
 	}
       catch (const gdb_exception_error &ex)
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index ab88a38e0a3..82937a3b78a 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3364,7 +3364,6 @@ create_overlay_event_breakpoint (void)
       struct breakpoint *b;
       struct breakpoint_objfile_data *bp_objfile_data;
       CORE_ADDR addr;
-      struct explicit_location explicit_loc;
 
       bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3388,9 +3387,7 @@ create_overlay_event_breakpoint (void)
       addr = bp_objfile_data->overlay_msym.value_address ();
       b = create_internal_breakpoint (objfile->arch (), addr,
 				      bp_overlay_event);
-      initialize_explicit_location (&explicit_loc);
-      explicit_loc.function_name = ASTRDUP (func_name);
-      b->locspec = new_explicit_location_spec (&explicit_loc);
+      b->locspec = new_explicit_location_spec_function (func_name);
 
       if (overlay_debugging == ovly_auto)
 	{
@@ -3473,7 +3470,6 @@ create_longjmp_master_breakpoint_names (objfile *objfile)
       struct breakpoint *b;
       const char *func_name;
       CORE_ADDR addr;
-      struct explicit_location explicit_loc;
 
       if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
 	continue;
@@ -3495,9 +3491,7 @@ create_longjmp_master_breakpoint_names (objfile *objfile)
 
       addr = bp_objfile_data->longjmp_msym[i].value_address ();
       b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master);
-      initialize_explicit_location (&explicit_loc);
-      explicit_loc.function_name = ASTRDUP (func_name);
-      b->locspec = new_explicit_location_spec (&explicit_loc);
+      b->locspec = new_explicit_location_spec_function (func_name);
       b->enable_state = bp_disabled;
       installed_bp++;
     }
@@ -3553,7 +3547,6 @@ create_std_terminate_master_breakpoint (void)
 	{
 	  struct breakpoint *b;
 	  struct breakpoint_objfile_data *bp_objfile_data;
-	  struct explicit_location explicit_loc;
 
 	  bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3578,9 +3571,7 @@ create_std_terminate_master_breakpoint (void)
 	  addr = bp_objfile_data->terminate_msym.value_address ();
 	  b = create_internal_breakpoint (objfile->arch (), addr,
 					  bp_std_terminate_master);
-	  initialize_explicit_location (&explicit_loc);
-	  explicit_loc.function_name = ASTRDUP (func_name);
-	  b->locspec = new_explicit_location_spec (&explicit_loc);
+	  b->locspec = new_explicit_location_spec_function (func_name);
 	  b->enable_state = bp_disabled;
 	}
     }
@@ -3648,7 +3639,6 @@ create_exception_master_breakpoint_hook (objfile *objfile)
   struct gdbarch *gdbarch;
   struct breakpoint_objfile_data *bp_objfile_data;
   CORE_ADDR addr;
-  struct explicit_location explicit_loc;
 
   bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3675,9 +3665,7 @@ create_exception_master_breakpoint_hook (objfile *objfile)
   addr = gdbarch_convert_from_func_ptr_addr
     (gdbarch, addr, current_inferior ()->top_target ());
   b = create_internal_breakpoint (gdbarch, addr, bp_exception_master);
-  initialize_explicit_location (&explicit_loc);
-  explicit_loc.function_name = ASTRDUP (func_name);
-  b->locspec = new_explicit_location_spec (&explicit_loc);
+  b->locspec = new_explicit_location_spec_function (func_name);
   b->enable_state = bp_disabled;
 
   return true;
@@ -8467,7 +8455,7 @@ parse_breakpoint_sals (location_spec *locspec,
 
   if (location_spec_type (locspec) == LINESPEC_LOCATION_SPEC)
     {
-      const char *spec = get_linespec_location (locspec)->spec_string;
+      const char *spec = as_linespec_location_spec (locspec)->spec_string;
 
       if (spec == NULL)
 	{
@@ -8518,7 +8506,7 @@ parse_breakpoint_sals (location_spec *locspec,
       const char *spec = NULL;
 
       if (location_spec_type (locspec) == LINESPEC_LOCATION_SPEC)
-	spec = get_linespec_location (locspec)->spec_string;
+	spec = as_linespec_location_spec (locspec)->spec_string;
 
       if (!cursal.symtab
 	  || (spec != NULL
@@ -12005,7 +11993,7 @@ strace_marker_create_sals_from_location_spec (location_spec *locspec,
   struct linespec_sals lsal;
   const char *arg_start, *arg;
 
-  arg = arg_start = get_linespec_location (locspec)->spec_string;
+  arg = arg_start = as_linespec_location_spec (locspec)->spec_string;
   lsal.sals = decode_static_tracepoint_spec (&arg);
 
   std::string str (arg_start, arg - arg_start);
@@ -12073,7 +12061,7 @@ std::vector<symtab_and_line>
 static_marker_tracepoint::decode_location_spec (location_spec *locspec,
 						program_space *search_pspace)
 {
-  const char *s = get_linespec_location (locspec)->spec_string;
+  const char *s = as_linespec_location_spec (locspec)->spec_string;
 
   std::vector<symtab_and_line> sals = decode_static_tracepoint_spec (&s);
   if (sals.size () > static_trace_marker_id_idx)
@@ -12381,7 +12369,6 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 	  struct symbol *sym;
 	  struct static_tracepoint_marker *tpmarker;
 	  struct ui_out *uiout = current_uiout;
-	  struct explicit_location explicit_loc;
 
 	  tpmarker = &markers[0];
 
@@ -12418,13 +12405,14 @@ 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;
 
-	  b->locspec.reset (nullptr);
-	  initialize_explicit_location (&explicit_loc);
-	  explicit_loc.source_filename
-	    = ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
-	  explicit_loc.line_offset.offset = b->loc->line_number;
-	  explicit_loc.line_offset.sign = LINE_OFFSET_NONE;
-	  b->locspec = new_explicit_location_spec (&explicit_loc);
+	  std::unique_ptr<explicit_location_spec> els
+	    (new explicit_location_spec ());
+	  els->source_filename
+	    = xstrdup (symtab_to_filename_for_display (sal2.symtab));
+	  els->line_offset.offset = b->loc->line_number;
+	  els->line_offset.sign = LINE_OFFSET_NONE;
+
+	  b->locspec = std::move (els);
 
 	  /* Might be nice to check if function changed, and warn if
 	     so.  */
diff --git a/gdb/completer.c b/gdb/completer.c
index 2ec8d2eb594..b68b6de2057 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -712,8 +712,8 @@ collect_explicit_location_matches (completion_tracker &tracker,
 				   const char *word,
 				   const struct language_defn *language)
 {
-  const struct explicit_location *explicit_loc
-    = get_explicit_location (locspec);
+  const explicit_location_spec *explicit_loc
+    = as_explicit_location_spec (locspec);
 
   /* True if the option expects an argument.  */
   bool needs_arg = true;
@@ -1008,7 +1008,7 @@ location_completer (struct cmd_list_element *ignore,
 	  text = copy;
 
 	  symbol_name_match_type match_type
-	    = get_explicit_location (locspec.get ())->func_name_match_type;
+	    = as_explicit_location_spec (locspec.get ())->func_name_match_type;
 	  complete_address_and_linespec_locations (tracker, text, match_type);
 	}
     }
diff --git a/gdb/linespec.c b/gdb/linespec.c
index b12f5c87733..063944bb9a1 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -94,8 +94,8 @@ struct address_entry
 
 struct linespec
 {
-  /* An explicit location describing the SaLs.  */
-  struct explicit_location explicit_loc {};
+  /* An explicit location spec describing the SaLs.  */
+  explicit_location_spec explicit_loc;
 
   /* The list of symtabs to search to which to limit the search.
 
@@ -342,8 +342,8 @@ struct linespec_parser
   struct completion_tracker *completion_tracker = nullptr;
 };
 
-/* A convenience macro for accessing the explicit location result of
-   the parser.  */
+/* A convenience macro for accessing the explicit location spec result
+   of the parser.  */
 #define PARSER_EXPLICIT(PPTR) (&PARSER_RESULT ((PPTR))->explicit_loc)
 
 /* Prototypes for local functions.  */
@@ -1990,18 +1990,14 @@ linespec_parse_basic (linespec_parser *parser)
 static void
 canonicalize_linespec (struct linespec_state *state, const linespec *ls)
 {
-  location_spec *canon;
-  struct explicit_location *explicit_loc;
-
   /* If canonicalization was not requested, no need to do anything.  */
   if (!state->canonical)
     return;
 
   /* Save everything as an explicit location.  */
-  state->canonical->locspec
-    = new_explicit_location_spec (&ls->explicit_loc);
-  canon = state->canonical->locspec.get ();
-  explicit_loc = get_explicit_location (canon);
+  state->canonical->locspec = ls->explicit_loc.clone ();
+  explicit_location_spec *explicit_loc
+    = as_explicit_location_spec (state->canonical->locspec.get ());
 
   if (explicit_loc->label_name != NULL)
     {
@@ -2019,8 +2015,7 @@ canonicalize_linespec (struct linespec_state *state, const linespec *ls)
   /* If this location originally came from a linespec, save a string
      representation of it for display and saving to file.  */
   if (state->is_linespec)
-    set_location_spec_string (canon,
-			      explicit_location_to_linespec (explicit_loc));
+    set_location_spec_string (explicit_loc, explicit_loc->to_linespec ());
 }
 
 /* Given a line offset in LS, construct the relevant SALs.  */
@@ -2307,17 +2302,18 @@ convert_linespec_to_sals (struct linespec_state *state, linespec *ls)
   return sals;
 }
 
-/* Build RESULT from the explicit location components SOURCE_FILENAME,
-   FUNCTION_NAME, LABEL_NAME and LINE_OFFSET.  */
+/* Build RESULT from the explicit location spec components
+   SOURCE_FILENAME, FUNCTION_NAME, LABEL_NAME and LINE_OFFSET.  */
 
 static void
-convert_explicit_location_to_linespec (struct linespec_state *self,
-				       linespec *result,
-				       const char *source_filename,
-				       const char *function_name,
-				       symbol_name_match_type fname_match_type,
-				       const char *label_name,
-				       struct line_offset line_offset)
+convert_explicit_location_spec_to_linespec
+  (struct linespec_state *self,
+   linespec *result,
+   const char *source_filename,
+   const char *function_name,
+   symbol_name_match_type fname_match_type,
+   const char *label_name,
+   struct line_offset line_offset)
 {
   std::vector<bound_minimal_symbol> minimal_symbols;
 
@@ -2382,16 +2378,17 @@ convert_explicit_location_to_linespec (struct linespec_state *self,
 /* Convert the explicit location EXPLICIT_LOC into SaLs.  */
 
 static std::vector<symtab_and_line>
-convert_explicit_location_to_sals (struct linespec_state *self,
-				   linespec *result,
-				   const struct explicit_location *explicit_loc)
+convert_explicit_location_spec_to_sals
+  (struct linespec_state *self,
+   linespec *result,
+   const explicit_location_spec *explicit_spec)
 {
-  convert_explicit_location_to_linespec (self, result,
-					 explicit_loc->source_filename,
-					 explicit_loc->function_name,
-					 explicit_loc->func_name_match_type,
-					 explicit_loc->label_name,
-					 explicit_loc->line_offset);
+  convert_explicit_location_spec_to_linespec (self, result,
+					      explicit_spec->source_filename,
+					      explicit_spec->function_name,
+					      explicit_spec->func_name_match_type,
+					      explicit_spec->label_name,
+					      explicit_spec->line_offset);
   return convert_linespec_to_sals (self, result);
 }
 
@@ -2694,10 +2691,6 @@ linespec_state_destructor (struct linespec_state *self)
 
 linespec_parser::~linespec_parser ()
 {
-  xfree (PARSER_EXPLICIT (this)->source_filename);
-  xfree (PARSER_EXPLICIT (this)->label_name);
-  xfree (PARSER_EXPLICIT (this)->function_name);
-
   linespec_state_destructor (PARSER_STATE (this));
 }
 
@@ -2855,12 +2848,12 @@ linespec_complete_label (completion_tracker &tracker,
 
   try
     {
-      convert_explicit_location_to_linespec (PARSER_STATE (&parser),
-					     PARSER_RESULT (&parser),
-					     source_filename,
-					     function_name,
-					     func_name_match_type,
-					     NULL, unknown_offset);
+      convert_explicit_location_spec_to_linespec (PARSER_STATE (&parser),
+						  PARSER_RESULT (&parser),
+						  source_filename,
+						  function_name,
+						  func_name_match_type,
+						  NULL, unknown_offset);
     }
   catch (const gdb_exception_error &ex)
     {
@@ -3073,24 +3066,18 @@ location_spec_to_sals (linespec_parser *parser,
     {
     case LINESPEC_LOCATION_SPEC:
       {
+	const linespec_location_spec *ls = as_linespec_location_spec (locspec);
 	PARSER_STATE (parser)->is_linespec = 1;
-	try
-	  {
-	    const linespec_location *ls = get_linespec_location (locspec);
-	    result = parse_linespec (parser,
-				     ls->spec_string, ls->match_type);
-	  }
-	catch (const gdb_exception_error &except)
-	  {
-	    throw;
-	  }
+	result = parse_linespec (parser, ls->spec_string, ls->match_type);
       }
       break;
 
     case ADDRESS_LOCATION_SPEC:
       {
-	const char *addr_string = get_address_string_location (locspec);
-	CORE_ADDR addr = get_address_location (locspec);
+	const address_location_spec *addr_spec
+	  = as_address_location_spec (locspec);
+	const char *addr_string = addr_spec->to_string ();
+	CORE_ADDR addr;
 
 	if (addr_string != NULL)
 	  {
@@ -3099,6 +3086,8 @@ location_spec_to_sals (linespec_parser *parser,
 	      PARSER_STATE (parser)->canonical->locspec
 		= copy_location_spec (locspec);
 	  }
+	else
+	  addr = addr_spec->address;
 
 	result = convert_address_location_to_sals (PARSER_STATE (parser),
 						   addr);
@@ -3107,12 +3096,11 @@ location_spec_to_sals (linespec_parser *parser,
 
     case EXPLICIT_LOCATION_SPEC:
       {
-	const struct explicit_location *explicit_loc;
-
-	explicit_loc = get_explicit_location_const (locspec);
-	result = convert_explicit_location_to_sals (PARSER_STATE (parser),
-						    PARSER_RESULT (parser),
-						    explicit_loc);
+	const explicit_location_spec *explicit_locspec
+	  = as_explicit_location_spec (locspec);
+	result = convert_explicit_location_spec_to_sals (PARSER_STATE (parser),
+							 PARSER_RESULT (parser),
+							 explicit_locspec);
       }
       break;
 
diff --git a/gdb/location.c b/gdb/location.c
index 14a5aebff17..4d0b60ff9c7 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -29,280 +29,187 @@
 #include <ctype.h>
 #include <string.h>
 
-static std::string explicit_location_to_string
-     (const struct explicit_location *explicit_loc);
+static std::string
+  explicit_to_string_internal (bool as_linespec,
+			       const explicit_location_spec *explicit_loc);
+
+/* Return a xstrdup of STR if not NULL, otherwise return NULL.  */
 
-/* The base class for all location specs used to match actual
-   locations in the inferior.  */
+static char *
+maybe_xstrdup (const char *str)
+{
+  return (str != nullptr ? xstrdup (str) : nullptr);
+}
+
+probe_location_spec::probe_location_spec (std::string &&probe)
+  : location_spec (PROBE_LOCATION_SPEC, std::move (probe))
+{
+}
 
-struct location_spec
+location_spec_up
+probe_location_spec::clone () const
 {
-  virtual ~location_spec () = default;
-
-  /* Clone this object.  */
-  virtual location_spec_up clone () const = 0;
-
-  /* Return true if this location spec is empty, false otherwise.  */
-  virtual bool empty_p () const = 0;
-
-  /* Return a string representation of this location.  */
-  const char *to_string () const
-  {
-    if (as_string.empty ())
-      as_string = compute_string ();
-    if (as_string.empty ())
-      return nullptr;
-    return as_string.c_str ();
-  }
-
-  DISABLE_COPY_AND_ASSIGN (location_spec);
-
-  /* The type of this location specification.  */
-  enum location_spec_type type;
-
-  /* Cached string representation of this location spec.  This is
-     used, e.g., to save location specs to file.  */
-  mutable std::string as_string;
-
-protected:
-
-  explicit location_spec (enum location_spec_type t)
-    : type (t)
-  {
-  }
-
-  location_spec (enum location_spec_type t, std::string &&str)
-    : type (t),
-      as_string (std::move (str))
-  {
-  }
-
-  explicit location_spec (const location_spec *to_clone)
-    : type (to_clone->type),
-      as_string (to_clone->as_string)
-  {
-  }
-
-  /* Compute the string representation of this object.  This is called
-     by to_string when needed.  */
-  virtual std::string compute_string () const = 0;
-};
-
-/* A probe.  */
-struct probe_location_spec : public location_spec
+  return location_spec_up (new probe_location_spec (*this));
+}
+
+bool
+probe_location_spec::empty_p () const
 {
-  explicit probe_location_spec (std::string &&probe)
-    : location_spec (PROBE_LOCATION_SPEC, std::move (probe))
-  {
-  }
-
-  location_spec_up clone () const override
-  {
-    return location_spec_up (new probe_location_spec (this));
-  }
-
-  bool empty_p () const override
-  {
-    return false;
-  }
-
-protected:
-
-  explicit probe_location_spec (const probe_location_spec *to_clone)
-    : location_spec (to_clone)
-  {
-  }
-
-  std::string compute_string () const override
-  {
-    return std::move (as_string);
-  }
-};
+  return false;
+}
+
+std::string probe_location_spec::compute_string () const
+{
+  return std::move (as_string);
+}
 
 /* A "normal" linespec.  */
-struct linespec_location_spec : public location_spec
+linespec_location_spec::linespec_location_spec
+  (const char **linespec, symbol_name_match_type match_type_)
+  : location_spec (LINESPEC_LOCATION_SPEC),
+    match_type (match_type_)
 {
-  linespec_location_spec (const char **linespec,
-			  symbol_name_match_type match_type)
-    : location_spec (LINESPEC_LOCATION_SPEC)
-  {
-    linespec_location.match_type = match_type;
-    if (*linespec != NULL)
-      {
-	const char *p;
-	const char *orig = *linespec;
-
-	linespec_lex_to_end (linespec);
-	p = remove_trailing_whitespace (orig, *linespec);
-
-	/* If there is no valid linespec then this will leave the
-	   spec_string as nullptr.  This behaviour is relied on in the
-	   breakpoint setting code, where spec_string being nullptr means
-	   to use the default breakpoint location.  */
-	if ((p - orig) > 0)
-	  linespec_location.spec_string = savestring (orig, p - orig);
-      }
-  }
-
-  ~linespec_location_spec ()
-  {
-    xfree (linespec_location.spec_string);
-  }
-
-  location_spec_up clone () const override
-  {
-    return location_spec_up (new linespec_location_spec (this));
-  }
-
-  bool empty_p () const override
-  {
-    return false;
-  }
-
-  struct linespec_location linespec_location {};
-
-protected:
-
-  explicit linespec_location_spec (const linespec_location_spec *to_clone)
-    : location_spec (to_clone),
-      linespec_location (to_clone->linespec_location)
-  {
-    if (linespec_location.spec_string != nullptr)
-      linespec_location.spec_string = xstrdup (linespec_location.spec_string);
-  }
-
-  std::string compute_string () const override
-  {
-    if (linespec_location.spec_string != nullptr)
-      {
-	const struct linespec_location *ls = &linespec_location;
-	if (ls->match_type == symbol_name_match_type::FULL)
-	  return std::string ("-qualified ") + ls->spec_string;
-	else
-	  return ls->spec_string;
-      }
-    return {};
-  }
-};
-
-/* An address in the inferior.  */
-struct address_location_spec : public location_spec
+  if (*linespec != NULL)
+    {
+      const char *p;
+      const char *orig = *linespec;
+
+      linespec_lex_to_end (linespec);
+      p = remove_trailing_whitespace (orig, *linespec);
+
+      /* If there is no valid linespec then this will leave the
+	 spec_string as nullptr.  This behaviour is relied on in the
+	 breakpoint setting code, where spec_string being nullptr means
+	 to use the default breakpoint location.  */
+      if ((p - orig) > 0)
+	spec_string = savestring (orig, p - orig);
+    }
+}
+
+linespec_location_spec::~linespec_location_spec ()
 {
-  address_location_spec (CORE_ADDR addr, const char *addr_string,
-			 int addr_string_len)
-    : location_spec (ADDRESS_LOCATION_SPEC),
-      address (addr)
-  {
-    if (addr_string != nullptr)
-      as_string = std::string (addr_string, addr_string_len);
-  }
-
-  location_spec_up clone () const override
-  {
-    return location_spec_up (new address_location_spec (this));
-  }
-
-  bool empty_p () const override
-  {
-    return false;
-  }
-
-  CORE_ADDR address;
-
-protected:
-
-  address_location_spec (const address_location_spec *to_clone)
-    : location_spec (to_clone),
-      address (to_clone->address)
-  {
-  }
-
-  std::string compute_string () const override
-  {
-    const char *addr_string = core_addr_to_string (address);
-    return std::string ("*") + addr_string;
-  }
-};
-
-/* An explicit location spec.  */
-struct explicit_location_spec : public location_spec
+  xfree (spec_string);
+}
+
+location_spec_up
+linespec_location_spec::clone () const
 {
-  explicit explicit_location_spec (const struct explicit_location *loc)
-    : location_spec (EXPLICIT_LOCATION_SPEC)
-  {
-    copy_loc (loc);
-  }
-
-  ~explicit_location_spec ()
-  {
-    xfree (explicit_loc.source_filename);
-    xfree (explicit_loc.function_name);
-    xfree (explicit_loc.label_name);
-  }
-
-  location_spec_up clone () const override
-  {
-    return location_spec_up (new explicit_location_spec (this));
-  }
-
-  bool empty_p () const override
-  {
-    return (explicit_loc.source_filename == nullptr
-	    && explicit_loc.function_name == nullptr
-	    && explicit_loc.label_name == nullptr
-	    && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN);
-  }
-
-  struct explicit_location explicit_loc;
-
-protected:
-
-  explicit explicit_location_spec (const explicit_location_spec *to_clone)
-    : location_spec (to_clone)
-  {
-    copy_loc (&to_clone->explicit_loc);
-  }
-
-  std::string compute_string () const override
-  {
-    return explicit_location_to_string (&explicit_loc);
-  }
-
-private:
-
-  void copy_loc (const struct explicit_location *loc)
-  {
-    initialize_explicit_location (&explicit_loc);
-    if (loc != nullptr)
-      {
-	explicit_loc.func_name_match_type = loc->func_name_match_type;
-	if (loc->source_filename != nullptr)
-	  explicit_loc.source_filename = xstrdup (loc->source_filename);
-	if (loc->function_name != nullptr)
-	  explicit_loc.function_name = xstrdup (loc->function_name);
-	if (loc->label_name != nullptr)
-	  explicit_loc.label_name = xstrdup (loc->label_name);
-	explicit_loc.line_offset = loc->line_offset;
-      }
-  }
-};
+  return location_spec_up (new linespec_location_spec (*this));
+}
 
-/* See description in location.h.  */
+bool
+linespec_location_spec::empty_p () const
+{
+  return false;
+}
 
-enum location_spec_type
-location_spec_type (const location_spec *locspec)
+linespec_location_spec::linespec_location_spec
+  (const linespec_location_spec &other)
+  : location_spec (other),
+    match_type (other.match_type),
+    spec_string (maybe_xstrdup (other.spec_string))
 {
-  return locspec->type;
+}
+
+std::string
+linespec_location_spec::compute_string () const
+{
+  if (spec_string != nullptr)
+    {
+      if (match_type == symbol_name_match_type::FULL)
+	return std::string ("-qualified ") + spec_string;
+      else
+	return spec_string;
+    }
+  return {};
+}
+
+address_location_spec::address_location_spec (CORE_ADDR addr,
+					      const char *addr_string,
+					      int addr_string_len)
+  : location_spec (ADDRESS_LOCATION_SPEC),
+    address (addr)
+{
+  if (addr_string != nullptr)
+    as_string = std::string (addr_string, addr_string_len);
+}
+
+location_spec_up
+address_location_spec::clone () const
+{
+  return location_spec_up (new address_location_spec (*this));
+}
+
+bool
+address_location_spec::empty_p () const
+{
+  return false;
+}
+
+address_location_spec::address_location_spec
+  (const address_location_spec &other)
+  : location_spec (other),
+    address (other.address)
+{
+}
+
+std::string
+address_location_spec::compute_string () const
+{
+  const char *addr_string = core_addr_to_string (address);
+  return std::string ("*") + addr_string;
+}
+
+explicit_location_spec::explicit_location_spec ()
+  : location_spec (EXPLICIT_LOCATION_SPEC)
+{
+}
+
+explicit_location_spec::~explicit_location_spec ()
+{
+  xfree (source_filename);
+  xfree (function_name);
+  xfree (label_name);
+}
+
+explicit_location_spec::explicit_location_spec
+  (const explicit_location_spec &other)
+  : location_spec (other),
+    source_filename (maybe_xstrdup (other.source_filename)),
+    function_name (maybe_xstrdup (other.function_name)),
+    func_name_match_type (other.func_name_match_type),
+    label_name (maybe_xstrdup (other.label_name)),
+    line_offset (other.line_offset)
+{
+}
+
+location_spec_up
+explicit_location_spec::clone () const
+{
+  return location_spec_up (new explicit_location_spec (*this));
+}
+
+bool
+explicit_location_spec::empty_p () const
+{
+  return (source_filename == nullptr
+	  && function_name == nullptr
+	  && label_name == nullptr
+	  && line_offset.sign == LINE_OFFSET_UNKNOWN);
+}
+
+std::string
+explicit_location_spec::compute_string () const
+{
+  return explicit_to_string_internal (false, this);
 }
 
 /* See description in location.h.  */
 
-void
-initialize_explicit_location (struct explicit_location *explicit_loc)
+enum location_spec_type
+location_spec_type (const location_spec *locspec)
 {
-  memset (explicit_loc, 0, sizeof (struct explicit_location));
-  explicit_loc->line_offset.sign = LINE_OFFSET_UNKNOWN;
-  explicit_loc->func_name_match_type = symbol_name_match_type::WILD;
+  return locspec->type;
 }
 
 /* See description in location.h.  */
@@ -317,11 +224,11 @@ new_linespec_location_spec (const char **linespec,
 
 /* See description in location.h.  */
 
-const linespec_location *
-get_linespec_location (const location_spec *locspec)
+const linespec_location_spec *
+as_linespec_location_spec (const location_spec *locspec)
 {
   gdb_assert (locspec->type == LINESPEC_LOCATION_SPEC);
-  return &((linespec_location_spec *) locspec)->linespec_location;
+  return static_cast<const linespec_location_spec *> (locspec);
 }
 
 /* See description in location.h.  */
@@ -336,20 +243,11 @@ new_address_location_spec (CORE_ADDR addr, const char *addr_string,
 
 /* See description in location.h.  */
 
-CORE_ADDR
-get_address_location (const location_spec *locspec)
+const address_location_spec *
+as_address_location_spec (const location_spec *locspec)
 {
   gdb_assert (locspec->type == ADDRESS_LOCATION_SPEC);
-  return ((address_location_spec *) locspec)->address;
-}
-
-/* See description in location.h.  */
-
-const char *
-get_address_string_location (const location_spec *locspec)
-{
-  gdb_assert (locspec->type == ADDRESS_LOCATION_SPEC);
-  return locspec->to_string ();
+  return static_cast<const address_location_spec *> (locspec);
 }
 
 /* See description in location.h.  */
@@ -362,37 +260,29 @@ new_probe_location_spec (std::string &&probe)
 
 /* See description in location.h.  */
 
-const char *
-get_probe_location_spec_string (const location_spec *locspec)
+const probe_location_spec *
+as_probe_location_spec (const location_spec *locspec)
 {
   gdb_assert (locspec->type == PROBE_LOCATION_SPEC);
-  return locspec->to_string ();
-}
-
-/* See description in location.h.  */
-
-location_spec_up
-new_explicit_location_spec (const explicit_location *explicit_loc)
-{
-  return location_spec_up (new explicit_location_spec (explicit_loc));
+  return static_cast<const probe_location_spec *> (locspec);
 }
 
 /* See description in location.h.  */
 
-struct explicit_location *
-get_explicit_location (location_spec *locspec)
+const explicit_location_spec *
+as_explicit_location_spec (const location_spec *locspec)
 {
   gdb_assert (locspec->type == EXPLICIT_LOCATION_SPEC);
-  return &((explicit_location_spec *) locspec)->explicit_loc;
+  return static_cast<const explicit_location_spec *> (locspec);
 }
 
 /* See description in location.h.  */
 
-const struct explicit_location *
-get_explicit_location_const (const location_spec *locspec)
+explicit_location_spec *
+as_explicit_location_spec (location_spec *locspec)
 {
   gdb_assert (locspec->type == EXPLICIT_LOCATION_SPEC);
-  return &((explicit_location_spec *) locspec)->explicit_loc;
+  return static_cast<explicit_location_spec *> (locspec);
 }
 
 /* Return a string representation of the explicit location spec in
@@ -403,7 +293,7 @@ get_explicit_location_const (const location_spec *locspec)
 
 static std::string
 explicit_to_string_internal (bool as_linespec,
-			     const struct explicit_location *explicit_loc)
+			     const explicit_location_spec *explicit_loc)
 {
   bool need_space = false;
   char space = as_linespec ? ':' : ' ';
@@ -457,18 +347,10 @@ explicit_to_string_internal (bool as_linespec,
 
 /* See description in location.h.  */
 
-static std::string
-explicit_location_to_string (const struct explicit_location *explicit_loc)
-{
-  return explicit_to_string_internal (false, explicit_loc);
-}
-
-/* See description in location.h.  */
-
 std::string
-explicit_location_to_linespec (const struct explicit_location *explicit_loc)
+explicit_location_spec::to_linespec () const
 {
-  return explicit_to_string_internal (true, explicit_loc);
+  return explicit_to_string_internal (true, this);
 }
 
 /* See description in location.h.  */
@@ -479,12 +361,6 @@ copy_location_spec (const location_spec *src)
   return src->clone ();
 }
 
-void
-location_spec_deleter::operator() (location_spec *locspec) const
-{
-  delete locspec;
-}
-
 /* See description in location.h.  */
 
 const char *
@@ -788,7 +664,7 @@ string_to_explicit_location_spec (const char **argp,
     return NULL;
 
   std::unique_ptr<explicit_location_spec> locspec
-    (new explicit_location_spec ((const explicit_location *) nullptr));
+    (new explicit_location_spec ());
 
   /* Process option/argument pairs.  dprintf_command
      requires that processing stop on ','.  */
@@ -857,18 +733,17 @@ string_to_explicit_location_spec (const char **argp,
 	{
 	  set_oarg (explicit_location_spec_lex_one (argp, language,
 						    completion_info));
-	  locspec->explicit_loc.source_filename = oarg.release ();
+	  locspec->source_filename = oarg.release ();
 	}
       else if (strncmp (opt.get (), "-function", len) == 0)
 	{
 	  set_oarg (explicit_location_spec_lex_one_function (argp, language,
 							     completion_info));
-	  locspec->explicit_loc.function_name = oarg.release ();
+	  locspec->function_name = oarg.release ();
 	}
       else if (strncmp (opt.get (), "-qualified", len) == 0)
 	{
-	  locspec->explicit_loc.func_name_match_type
-	    = symbol_name_match_type::FULL;
+	  locspec->func_name_match_type = symbol_name_match_type::FULL;
 	}
       else if (strncmp (opt.get (), "-line", len) == 0)
 	{
@@ -876,8 +751,7 @@ string_to_explicit_location_spec (const char **argp,
 	  *argp = skip_spaces (*argp);
 	  if (have_oarg)
 	    {
-	      locspec->explicit_loc.line_offset
-		= linespec_parse_line_offset (oarg.get ());
+	      locspec->line_offset = linespec_parse_line_offset (oarg.get ());
 	      continue;
 	    }
 	}
@@ -885,7 +759,7 @@ string_to_explicit_location_spec (const char **argp,
 	{
 	  set_oarg (explicit_location_spec_lex_one (argp, language,
 						    completion_info));
-	  locspec->explicit_loc.label_name = oarg.release ();
+	  locspec->label_name = oarg.release ();
 	}
       /* Only emit an "invalid argument" error for options
 	 that look like option strings.  */
@@ -915,10 +789,10 @@ string_to_explicit_location_spec (const char **argp,
 
   /* One special error check:  If a source filename was given
      without offset, function, or label, issue an error.  */
-  if (locspec->explicit_loc.source_filename != NULL
-      && locspec->explicit_loc.function_name == NULL
-      && locspec->explicit_loc.label_name == NULL
-      && (locspec->explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
+  if (locspec->source_filename != NULL
+      && locspec->function_name == NULL
+      && locspec->label_name == NULL
+      && (locspec->line_offset.sign == LINE_OFFSET_UNKNOWN)
       && completion_info == NULL)
     {
       error (_("Source filename requires function, label, or "
@@ -1000,7 +874,7 @@ string_to_location_spec (const char **stringp,
       explicit_location_spec *xloc
 	= dynamic_cast<explicit_location_spec *> (locspec.get ());
       gdb_assert (xloc != nullptr);
-      match_type = xloc->explicit_loc.func_name_match_type;
+      match_type = xloc->func_name_match_type;
     }
 
   /* Everything else is a "basic" linespec, address, or probe location
diff --git a/gdb/location.h b/gdb/location.h
index 602998de298..0a2f1799bc4 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -46,8 +46,8 @@ enum offset_relative_sign
 struct line_offset
 {
   /* Line offset and any specified sign.  */
-  int offset;
-  enum offset_relative_sign sign;
+  int offset = 0;
+  enum offset_relative_sign sign = LINE_OFFSET_UNKNOWN;
 };
 
 /* An enumeration of the various ways to specify a location spec.  */
@@ -67,15 +67,104 @@ enum location_spec_type
   PROBE_LOCATION_SPEC
 };
 
-/* A traditional linespec.  */
+/* A unique pointer for location_spec.  */
+typedef std::unique_ptr<location_spec> location_spec_up;
+
+/* The base class for all location specs used to resolve actual
+   locations in the inferior.  */
 
-struct linespec_location
+struct location_spec
 {
+  virtual ~location_spec () = default;
+
+  /* Clone this object.  */
+  virtual location_spec_up clone () const = 0;
+
+  /* Return true if this location spec is empty, false otherwise.  */
+  virtual bool empty_p () const = 0;
+
+  /* Return a string representation of this location.  */
+  const char *to_string () const
+  {
+    if (as_string.empty ())
+      as_string = compute_string ();
+    if (as_string.empty ())
+      return nullptr;
+    return as_string.c_str ();
+  }
+
+  /* The type of this location specification.  */
+  enum location_spec_type type;
+
+  /* Cached string representation of this location spec.  This is
+     used, e.g., to save location specs to file.  */
+  mutable std::string as_string;
+
+protected:
+
+  explicit location_spec (enum location_spec_type t)
+    : type (t)
+  {
+  }
+
+  location_spec (enum location_spec_type t, std::string &&str)
+    : type (t),
+      as_string (std::move (str))
+  {
+  }
+
+  location_spec (const location_spec &other)
+    : type (other.type),
+      as_string (other.as_string)
+  {
+  }
+
+  /* Compute the string representation of this object.  This is called
+     by to_string when needed.  */
+  virtual std::string compute_string () const = 0;
+};
+
+/* A "normal" linespec.  */
+
+struct linespec_location_spec : public location_spec
+{
+  linespec_location_spec (const char **linespec,
+			  symbol_name_match_type match_type);
+
+  ~linespec_location_spec ();
+
+  location_spec_up clone () const override;
+
+  bool empty_p () const override;
+
   /* Whether the function name is fully-qualified or not.  */
   symbol_name_match_type match_type;
 
   /* The linespec.  */
-  char *spec_string;
+  char *spec_string = nullptr;
+
+protected:
+  linespec_location_spec (const linespec_location_spec &other);
+
+  std::string compute_string () const override;
+};
+
+/* An address in the inferior.  */
+struct address_location_spec : public location_spec
+{
+  address_location_spec (CORE_ADDR addr, const char *addr_string,
+			 int addr_string_len);
+
+  location_spec_up clone () const override;
+
+  bool empty_p () const override;
+
+  CORE_ADDR address;
+
+protected:
+  address_location_spec (const address_location_spec &other);
+
+  std::string compute_string () const override;
 };
 
 /* An explicit location spec.  This structure is used to bypass the
@@ -83,24 +172,58 @@ struct linespec_location
    as linespecs, though.  For example, source_filename requires
    at least one other field.  */
 
-struct explicit_location
+struct explicit_location_spec : public location_spec
 {
+  explicit_location_spec ();
+
+  ~explicit_location_spec ();
+
+  location_spec_up clone () const override;
+
+  bool empty_p () const override;
+
+  /* Return a linespec string representation of this explicit location
+     spec.  The explicit location spec must already be
+     canonicalized/valid.  */
+  std::string to_linespec () const;
+
   /* The source filename. Malloc'd.  */
-  char *source_filename;
+  char *source_filename = nullptr;
 
   /* The function name.  Malloc'd.  */
-  char *function_name;
+  char *function_name = nullptr;
 
   /* Whether the function name is fully-qualified or not.  */
-  symbol_name_match_type func_name_match_type;
+  symbol_name_match_type func_name_match_type
+    = symbol_name_match_type::WILD;
 
   /* The name of a label.  Malloc'd.  */
-  char *label_name;
+  char *label_name = nullptr;
 
   /* 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;
+  struct line_offset line_offset = {0, LINE_OFFSET_UNKNOWN};
+
+protected:
+  explicit_location_spec (const explicit_location_spec &other);
+
+  std::string compute_string () const override;
+};
+
+/* A probe.  */
+struct probe_location_spec : public location_spec
+{
+  explicit probe_location_spec (std::string &&probe);
+
+  location_spec_up clone () const override;
+
+  bool empty_p () const override;
+
+protected:
+  probe_location_spec (const probe_location_spec &other) = default;
+
+  std::string compute_string () const override;
 };
 
 /* Return the type of the given location spec.  */
@@ -108,13 +231,6 @@ struct explicit_location
 extern enum location_spec_type
   location_spec_type (const location_spec *);
 
-/* Return a linespec string representation of the given explicit
-   location spec.  The location spec must already be
-   canonicalized/valid.  */
-
-extern std::string explicit_location_to_linespec
-  (const explicit_location *explicit_locspec);
-
 /* Return a string representation of LOCSPEC.
    This function may return NULL for unspecified linespecs,
    e.g, LINESPEC_LOCATION_SPEC and spec_string is NULL.
@@ -124,27 +240,16 @@ extern std::string explicit_location_to_linespec
 extern const char *
   location_spec_to_string (location_spec *locspec);
 
-/* A deleter for a struct location_spec.  */
-
-struct location_spec_deleter
-{
-  void operator() (location_spec *locspec) const;
-};
-
-/* A unique pointer for location_spec.  */
-typedef std::unique_ptr<location_spec, location_spec_deleter>
-     location_spec_up;
-
 /* Create a new linespec location spec.  */
 
 extern location_spec_up new_linespec_location_spec
   (const char **linespec, symbol_name_match_type match_type);
 
-/* Return the linespec location spec of the given location_spec (which
-   must be of type LINESPEC_LOCATION_SPEC).  */
+/* Return the given location_spec as a linespec_location_spec.
+   LOCSPEC must be of type LINESPEC_LOCATION_SPEC.  */
 
-extern const linespec_location *
-  get_linespec_location (const location_spec *locspec);
+extern const linespec_location_spec *
+  as_linespec_location_spec (const location_spec *locspec);
 
 /* Create a new address location spec.
    ADDR is the address corresponding to this location_spec.
@@ -155,50 +260,42 @@ extern location_spec_up new_address_location_spec (CORE_ADDR addr,
 						   const char *addr_string,
 						   int addr_string_len);
 
-/* Return the address (a CORE_ADDR) of the given location_spec, which
-   must be of type ADDRESS_LOCATION_SPEC.  */
-
-extern CORE_ADDR
-  get_address_location (const location_spec *locspec);
+/* Return the given location_spec as an address_location_spec.
+   LOCSPEC must be of type ADDRESS_LOCATION_SPEC.  */
 
-/* Return the expression (a string) that was used to compute the
-   address of the given location_spec, which must be of type
-   ADDRESS_LOCATION_SPEC.  */
-
-extern const char *
-  get_address_string_location (const location_spec *locspec);
+const address_location_spec *
+  as_address_location_spec (const location_spec *locspec);
 
 /* Create a new probe location.  */
 
 extern location_spec_up new_probe_location_spec (std::string &&probe);
 
-/* Return the probe location spec string of the given location_spec,
-   which must be of type PROBE_LOCATION_SPEC.  */
-
-extern const char *
-  get_probe_location_spec_string (const location_spec *locspec);
-
-/* Initialize the given explicit location.  */
+/* Assuming LOCSPEC is of type PROBE_LOCATION_SPEC, return LOCSPEC
+   cast to probe_location_spec.  */
 
-extern void
-  initialize_explicit_location (explicit_location *locspec);
+const probe_location_spec *
+  as_probe_location_spec (const location_spec *locspec);
 
-/* Create a new explicit location.  If not NULL, EXPLICIT is checked for
-   validity.  If invalid, an exception is thrown.  */
+/* Create a new explicit location with explicit FUNCTION_NAME.  All
+   other fields are defaulted.  */
 
-extern location_spec_up
-  new_explicit_location_spec (const explicit_location *locspec);
-
-/* Return the explicit location spec of the given location_spec, which
-   must be of type EXPLICIT_LOCATION.  */
-
-extern struct explicit_location *
-  get_explicit_location (location_spec *locspec);
-
-/* A const version of the above.  */
-
-extern const explicit_location *
-  get_explicit_location_const (const location_spec *locspec);
+static inline location_spec_up
+new_explicit_location_spec_function (const char *function_name)
+{
+  explicit_location_spec *spec
+    = new explicit_location_spec ();
+  spec->function_name
+    = (function_name != nullptr ? xstrdup (function_name) : nullptr);
+  return location_spec_up (spec);
+}
+
+/* Assuming LOCSPEC is of type EXPLICIT_LOCATION_SPEC, return LOCSPEC
+   cast to explicit_location_spec.  */
+
+const explicit_location_spec *
+  as_explicit_location_spec (const location_spec *locspec);
+explicit_location_spec *
+  as_explicit_location_spec (location_spec *locspec);
 
 /* Return a copy of the given SRC location spec.  */
 
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index dab0a471abc..408f582ebc5 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -182,7 +182,8 @@ mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
   location_spec_up locspec;
   const struct breakpoint_ops *ops;
   int is_explicit = 0;
-  struct explicit_location explicit_loc;
+  std::unique_ptr<explicit_location_spec> explicit_loc
+    (new explicit_location_spec ());
   std::string extra_string;
   bool force_condition = false;
 
@@ -220,8 +221,6 @@ mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
   int oind = 0;
   char *oarg;
 
-  initialize_explicit_location (&explicit_loc);
-
   while (1)
     {
       int opt = mi_getopt ("-break-insert", argc, argv,
@@ -259,19 +258,19 @@ mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
 	  break;
 	case EXPLICIT_SOURCE_OPT:
 	  is_explicit = 1;
-	  explicit_loc.source_filename = oarg;
+	  explicit_loc->source_filename = xstrdup (oarg);
 	  break;
 	case EXPLICIT_FUNC_OPT:
 	  is_explicit = 1;
-	  explicit_loc.function_name = oarg;
+	  explicit_loc->function_name = xstrdup (oarg);
 	  break;
 	case EXPLICIT_LABEL_OPT:
 	  is_explicit = 1;
-	  explicit_loc.label_name = oarg;
+	  explicit_loc->label_name = xstrdup (oarg);
 	  break;
 	case EXPLICIT_LINE_OPT:
 	  is_explicit = 1;
-	  explicit_loc.line_offset = linespec_parse_line_offset (oarg);
+	  explicit_loc->line_offset = linespec_parse_line_offset (oarg);
 	  break;
 	case FORCE_CONDITION_OPT:
 	  force_condition = true;
@@ -339,16 +338,16 @@ mi_cmd_break_insert_1 (int dprintf, const char *command, char **argv, int argc)
     {
       /* Error check -- we must have one of the other
 	 parameters specified.  */
-      if (explicit_loc.source_filename != NULL
-	  && explicit_loc.function_name == NULL
-	  && explicit_loc.label_name == NULL
-	  && explicit_loc.line_offset.sign == LINE_OFFSET_UNKNOWN)
+      if (explicit_loc->source_filename != NULL
+	  && explicit_loc->function_name == NULL
+	  && explicit_loc->label_name == NULL
+	  && explicit_loc->line_offset.sign == LINE_OFFSET_UNKNOWN)
 	error (_("-%s-insert: --source option requires --function, --label,"
 		 " or --line"), dprintf ? "dprintf" : "break");
 
-      explicit_loc.func_name_match_type = match_type;
+      explicit_loc->func_name_match_type = match_type;
 
-      locspec = new_explicit_location_spec (&explicit_loc);
+      locspec = std::move (explicit_loc);
     }
   else
     {
diff --git a/gdb/probe.c b/gdb/probe.c
index 0b056eb88db..5371b7eca46 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -123,7 +123,7 @@ parse_probes (const location_spec *locspec,
   const char *arg_start, *cs;
 
   gdb_assert (location_spec_type (locspec) == PROBE_LOCATION_SPEC);
-  arg_start = get_probe_location_spec_string (locspec);
+  arg_start = locspec->to_string ();
 
   cs = arg_start;
   const static_probe_ops *spops = probe_linespec_to_static_ops (&cs);
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 029ced74136..bab1c60a43e 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -839,20 +839,23 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 	      }
 	    else
 	      {
-		struct explicit_location explicit_loc;
+		std::unique_ptr<explicit_location_spec> explicit_loc
+		  (new explicit_location_spec ());
 
-		initialize_explicit_location (&explicit_loc);
-		explicit_loc.source_filename = source;
-		explicit_loc.function_name = function;
-		explicit_loc.label_name = label;
+		explicit_loc->source_filename
+		  = source != nullptr ? xstrdup (source) : nullptr;
+		explicit_loc->function_name
+		  = function != nullptr ? xstrdup (function) : nullptr;
+		explicit_loc->label_name
+		  = label != nullptr ? xstrdup (label) : nullptr;
 
 		if (line != NULL)
-		  explicit_loc.line_offset =
-		    linespec_parse_line_offset (line.get ());
+		  explicit_loc->line_offset
+		    = linespec_parse_line_offset (line.get ());
 
-		explicit_loc.func_name_match_type = func_name_match_type;
+		explicit_loc->func_name_match_type = func_name_match_type;
 
-		locspec = new_explicit_location_spec (&explicit_loc);
+		locspec.reset (explicit_loc.release ());
 	      }
 
 	    const struct breakpoint_ops *ops


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-17  9:23 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-17  9:23 [binutils-gdb] Eliminate the two-level data structures behind location_specs Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).