gdb: add inferior-specific breakpoints
[binutils-gdb.git] / gdb / breakpoint.c
index ede8b43dcabffb3b45f61439220992f18974fde6..f88ca1c9b65202a665da1f3ac819f0ab4c16921a 100644 (file)
@@ -1,6 +1,6 @@
 /* Everything about breakpoints, for GDB.
 
-   Copyright (C) 1986-2022 Free Software Foundation, Inc.
+   Copyright (C) 1986-2023 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
@@ -53,6 +53,7 @@
 #include "memattr.h"
 #include "ada-lang.h"
 #include "top.h"
+#include "ui.h"
 #include "valprint.h"
 #include "jit.h"
 #include "parser-defs.h"
@@ -68,6 +69,7 @@
 #include "tid-parse.h"
 #include "cli/cli-style.h"
 #include "cli/cli-decode.h"
+#include <unordered_set>
 
 /* readline include files */
 #include "readline/tilde.h"
 #include "progspace-and-thread.h"
 #include "gdbsupport/array-view.h"
 #include "gdbsupport/gdb_optional.h"
+#include "gdbsupport/common-utils.h"
 
 /* Prototypes for local functions.  */
 
 static void map_breakpoint_numbers (const char *,
                                    gdb::function_view<void (breakpoint *)>);
 
-static void breakpoint_re_set_default (struct breakpoint *);
-
 static void
-  create_sals_from_location_default (struct event_location *location,
-                                    struct linespec_result *canonical,
-                                    enum bptype type_wanted);
-
-static void create_breakpoints_sal_default (struct gdbarch *,
-                                           struct linespec_result *,
-                                           gdb::unique_xmalloc_ptr<char>,
-                                           gdb::unique_xmalloc_ptr<char>,
-                                           enum bptype,
-                                           enum bpdisp, int, int,
-                                           int,
-                                           const struct breakpoint_ops *,
-                                           int, int, int, unsigned);
-
-static std::vector<symtab_and_line> decode_location_default
-  (struct breakpoint *b, struct event_location *location,
-   struct program_space *search_pspace);
+  create_sals_from_location_spec_default (location_spec *locspec,
+                                         linespec_result *canonical);
+
+static void create_breakpoints_sal (struct gdbarch *,
+                                   struct linespec_result *,
+                                   gdb::unique_xmalloc_ptr<char>,
+                                   gdb::unique_xmalloc_ptr<char>,
+                                   enum bptype,
+                                   enum bpdisp, int, int, int,
+                                   int,
+                                   int, int, int, unsigned);
 
 static int can_use_hardware_watchpoint
     (const std::vector<value_ref_ptr> &vals);
 
-static void mention (struct breakpoint *);
+static void mention (const breakpoint *);
 
-static struct breakpoint *set_raw_breakpoint_without_location (struct gdbarch *,
-                                                              enum bptype,
-                                                              const struct breakpoint_ops *);
-static struct bp_location *add_location_to_breakpoint (struct breakpoint *,
-                                                      const struct symtab_and_line *);
+static breakpoint *add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b);
 
-/* This function is used in gdbtk sources and thus can not be made
-   static.  */
-static struct breakpoint *set_raw_breakpoint (struct gdbarch *gdbarch,
-                                             struct symtab_and_line,
-                                             enum bptype,
-                                             const struct breakpoint_ops *);
+static breakpoint *add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b);
 
 static struct breakpoint *
   momentary_breakpoint_from_master (struct breakpoint *orig,
                                    enum bptype type,
-                                   const struct breakpoint_ops *ops,
-                                   int loc_enabled);
+                                   int loc_enabled, int thread);
 
-static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, int);
+static void breakpoint_adjustment_warning (CORE_ADDR, CORE_ADDR, int, bool);
 
 static CORE_ADDR adjust_breakpoint_address (struct gdbarch *gdbarch,
                                            CORE_ADDR bpaddr,
-                                           enum bptype bptype);
+                                           enum bptype bptype,
+                                           struct program_space *pspace);
 
-static void describe_other_breakpoints (struct gdbarch *,
-                                       struct program_space *, CORE_ADDR,
-                                       struct obj_section *, int);
+static bool watchpoint_locations_match (const struct bp_location *loc1,
+                                       const struct bp_location *loc2);
 
-static int watchpoint_locations_match (struct bp_location *loc1,
-                                      struct bp_location *loc2);
+static bool breakpoint_locations_match (const struct bp_location *loc1,
+                                       const struct bp_location *loc2,
+                                       bool sw_hw_bps_match = false);
 
-static int breakpoint_locations_match (struct bp_location *loc1,
-                                      struct bp_location *loc2,
-                                      bool sw_hw_bps_match = false);
+static bool breakpoint_location_address_match (struct bp_location *bl,
+                                              const struct address_space *aspace,
+                                              CORE_ADDR addr);
 
-static int breakpoint_location_address_match (struct bp_location *bl,
-                                             const struct address_space *aspace,
-                                             CORE_ADDR addr);
-
-static int breakpoint_location_address_range_overlap (struct bp_location *,
-                                                     const address_space *,
-                                                     CORE_ADDR, int);
+static bool breakpoint_location_address_range_overlap (struct bp_location *,
+                                                      const address_space *,
+                                                      CORE_ADDR, int);
 
 static int remove_breakpoint (struct bp_location *);
 static int remove_breakpoint_1 (struct bp_location *, enum remove_bp_reason);
@@ -175,7 +157,14 @@ static void enable_breakpoint_disp (struct breakpoint *, enum bpdisp,
 
 static void decref_bp_location (struct bp_location **loc);
 
-static struct bp_location *allocate_bp_location (struct breakpoint *bpt);
+static std::vector<symtab_and_line> bkpt_probe_decode_location_spec
+     (struct breakpoint *b,
+      location_spec *locspec,
+      struct program_space *search_pspace);
+
+static bool bl_address_is_meaningful (bp_location *loc);
+
+static int find_loc_num_by_location (const bp_location *loc);
 
 /* update_global_location_list's modes of operation wrt to whether to
    insert locations now.  */
@@ -212,6 +201,68 @@ enum ugll_insert_mode
   UGLL_INSERT
 };
 
+/* Return a textual version of INSERT_MODE.  */
+
+static const char *
+ugll_insert_mode_text (ugll_insert_mode insert_mode)
+{
+/* Make sure the compiler warns if a new ugll_insert_mode enumerator is added
+   but not handled here.  */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+  switch (insert_mode)
+    {
+    case UGLL_DONT_INSERT:
+      return "UGLL_DONT_INSERT";
+    case UGLL_MAY_INSERT:
+      return "UGLL_MAY_INSERT";
+    case UGLL_INSERT:
+      return "UGLL_INSERT";
+    }
+DIAGNOSTIC_POP
+
+  gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of REASON.  */
+
+static const char *
+remove_bp_reason_str (remove_bp_reason reason)
+{
+/* Make sure the compiler warns if a new remove_bp_reason enumerator is added
+   but not handled here.  */
+DIAGNOSTIC_PUSH
+DIAGNOSTIC_ERROR_SWITCH
+  switch (reason)
+    {
+    case REMOVE_BREAKPOINT:
+      return "regular remove";
+    case DETACH_BREAKPOINT:
+      return "detach";
+    }
+DIAGNOSTIC_POP
+
+  gdb_assert_not_reached ("must handle all enum values");
+}
+
+/* Return a textual version of breakpoint location BL describing number,
+   location and address.  */
+
+static std::string
+breakpoint_location_address_str (const bp_location *bl)
+{
+  std::string str = string_printf ("Breakpoint %d (%s) at address %s",
+                                  bl->owner->number,
+                                  host_address_to_string (bl),
+                                  paddress (bl->gdbarch, bl->address));
+
+  std::string loc_string = bl->to_string ();
+  if (!loc_string.empty ())
+    str += string_printf (" %s", loc_string.c_str ());
+
+  return str;
+}
+
 static void update_global_location_list (enum ugll_insert_mode);
 
 static void update_global_location_list_nothrow (enum ugll_insert_mode);
@@ -224,34 +275,181 @@ static void set_tracepoint_count (int num);
 
 static bool is_masked_watchpoint (const struct breakpoint *b);
 
-/* Return 1 if B refers to a static tracepoint set by marker ("-m"), zero
-   otherwise.  */
-
-static int strace_marker_p (struct breakpoint *b);
-
-/* The breakpoint_ops structure to be inherited by all breakpoint_ops
-   that are implemented on top of software or hardware breakpoints
-   (user breakpoints, internal and momentary breakpoints, etc.).  */
-static struct breakpoint_ops bkpt_base_breakpoint_ops;
+/* Return true if B refers to a static tracepoint set by marker ("-m"),
+   zero otherwise.  */
 
-/* Internal breakpoints class type.  */
-static struct breakpoint_ops internal_breakpoint_ops;
+static bool strace_marker_p (struct breakpoint *b);
 
-/* Momentary breakpoints class type.  */
-static struct breakpoint_ops momentary_breakpoint_ops;
+static void bkpt_probe_create_sals_from_location_spec
+     (location_spec *locspec,
+      struct linespec_result *canonical);
+static void tracepoint_probe_create_sals_from_location_spec
+     (location_spec *locspec,
+      struct linespec_result *canonical);
 
-/* The breakpoint_ops structure to be used in regular user created
-   breakpoints.  */
-struct breakpoint_ops bkpt_breakpoint_ops;
+const struct breakpoint_ops code_breakpoint_ops =
+{
+  create_sals_from_location_spec_default,
+  create_breakpoints_sal,
+};
 
 /* Breakpoints set on probes.  */
-static struct breakpoint_ops bkpt_probe_breakpoint_ops;
+static const struct breakpoint_ops bkpt_probe_breakpoint_ops =
+{
+  bkpt_probe_create_sals_from_location_spec,
+  create_breakpoints_sal,
+};
 
 /* Tracepoints set on probes.  */
-static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
+static const struct breakpoint_ops tracepoint_probe_breakpoint_ops =
+{
+  tracepoint_probe_create_sals_from_location_spec,
+  create_breakpoints_sal,
+};
+
+/* Implementation of abstract dtors.  These must exist to satisfy the
+   linker.  */
+
+breakpoint::~breakpoint ()
+{
+}
+
+code_breakpoint::~code_breakpoint ()
+{
+}
+
+catchpoint::~catchpoint ()
+{
+}
+
+/* The structure to be used in regular breakpoints.  */
+struct ordinary_breakpoint : public code_breakpoint
+{
+  using code_breakpoint::code_breakpoint;
+
+  int resources_needed (const struct bp_location *) override;
+  enum print_stop_action print_it (const bpstat *bs) const override;
+  void print_mention () const override;
+  void print_recreate (struct ui_file *fp) const override;
+};
+
+/* Internal breakpoints.  These typically have a lifetime the same as
+   the program, and they end up installed on the breakpoint chain with
+   a negative breakpoint number.  They're visible in "maint info
+   breakpoints", but not "info breakpoints".  */
+struct internal_breakpoint : public code_breakpoint
+{
+  internal_breakpoint (struct gdbarch *gdbarch,
+                      enum bptype type, CORE_ADDR address)
+    : code_breakpoint (gdbarch, type)
+  {
+    symtab_and_line sal;
+    sal.pc = address;
+    sal.section = find_pc_overlay (sal.pc);
+    sal.pspace = current_program_space;
+    add_location (sal);
+
+    pspace = current_program_space;
+    disposition = disp_donttouch;
+  }
+
+  void re_set () override;
+  void check_status (struct bpstat *bs) override;
+  enum print_stop_action print_it (const bpstat *bs) const override;
+  void print_mention () const override;
+};
+
+/* Momentary breakpoints.  These typically have a lifetime of some run
+   control command only, are always thread-specific, and have 0 for
+   breakpoint number.  I.e., there can be many momentary breakpoints
+   on the breakpoint chain and they all same the same number (zero).
+   They're visible in "maint info breakpoints", but not "info
+   breakpoints".  */
+struct momentary_breakpoint : public code_breakpoint
+{
+  momentary_breakpoint (struct gdbarch *gdbarch_, enum bptype bptype,
+                       program_space *pspace_,
+                       const struct frame_id &frame_id_,
+                       int thread_)
+    : code_breakpoint (gdbarch_, bptype)
+  {
+    /* If FRAME_ID is valid, it should be a real frame, not an inlined
+       or tail-called one.  */
+    gdb_assert (!frame_id_artificial_p (frame_id));
+
+    /* Momentary breakpoints are always thread-specific.  */
+    gdb_assert (thread_ > 0);
+
+    pspace = pspace_;
+    enable_state = bp_enabled;
+    disposition = disp_donttouch;
+    frame_id = frame_id_;
+    thread = thread_;
+
+    /* The inferior should have been set by the parent constructor.  */
+    gdb_assert (inferior == -1);
+  }
+
+  void re_set () override;
+  void check_status (struct bpstat *bs) override;
+  enum print_stop_action print_it (const bpstat *bs) const override;
+  void print_mention () const override;
+};
+
+/* DPrintf breakpoints.  */
+struct dprintf_breakpoint : public ordinary_breakpoint
+{
+  using ordinary_breakpoint::ordinary_breakpoint;
+
+  void re_set () override;
+  int breakpoint_hit (const struct bp_location *bl,
+                     const address_space *aspace,
+                     CORE_ADDR bp_addr,
+                     const target_waitstatus &ws) override;
+  void print_recreate (struct ui_file *fp) const override;
+  void after_condition_true (struct bpstat *bs) override;
+};
+
+/* Ranged breakpoints.  */
+struct ranged_breakpoint : public ordinary_breakpoint
+{
+  explicit ranged_breakpoint (struct gdbarch *gdbarch,
+                             const symtab_and_line &sal_start,
+                             int length,
+                             location_spec_up start_locspec,
+                             location_spec_up end_locspec)
+    : ordinary_breakpoint (gdbarch, bp_hardware_breakpoint)
+  {
+    bp_location *bl = add_location (sal_start);
+    bl->length = length;
 
-/* Dynamic printf class type.  */
-struct breakpoint_ops dprintf_breakpoint_ops;
+    disposition = disp_donttouch;
+
+    locspec = std::move (start_locspec);
+    locspec_range_end = std::move (end_locspec);
+  }
+
+  int breakpoint_hit (const struct bp_location *bl,
+                     const address_space *aspace,
+                     CORE_ADDR bp_addr,
+                     const target_waitstatus &ws) override;
+  int resources_needed (const struct bp_location *) override;
+  enum print_stop_action print_it (const bpstat *bs) const override;
+  bool print_one (const bp_location **) const override;
+  void print_one_detail (struct ui_out *) const override;
+  void print_mention () const override;
+  void print_recreate (struct ui_file *fp) const override;
+};
+
+/* Static tracepoints with marker (`-m').  */
+struct static_marker_tracepoint : public tracepoint
+{
+  using tracepoint::tracepoint;
+
+  std::vector<symtab_and_line> decode_location_spec
+       (struct location_spec *locspec,
+       struct program_space *search_pspace) override;
+};
 
 /* The style in which to perform a dynamic printf.  This is a user
    option because different output options have different tradeoffs;
@@ -324,10 +522,10 @@ show_can_use_hw_watchpoints (struct ui_file *file, int from_tty,
                             struct cmd_list_element *c,
                             const char *value)
 {
-  fprintf_filtered (file,
-                   _("Debugger's willingness to use "
-                     "watchpoint hardware is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Debugger's willingness to use "
+               "watchpoint hardware is %s.\n"),
+             value);
 }
 
 /* If AUTO_BOOLEAN_FALSE, gdb will not attempt to create pending breakpoints.
@@ -340,10 +538,10 @@ show_pending_break_support (struct ui_file *file, int from_tty,
                            struct cmd_list_element *c,
                            const char *value)
 {
-  fprintf_filtered (file,
-                   _("Debugger's behavior regarding "
-                     "pending breakpoints is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Debugger's behavior regarding "
+               "pending breakpoints is %s.\n"),
+             value);
 }
 
 /* If true, gdb will automatically use hardware breakpoints for breakpoints
@@ -356,9 +554,9 @@ show_automatic_hardware_breakpoints (struct ui_file *file, int from_tty,
                                     struct cmd_list_element *c,
                                     const char *value)
 {
-  fprintf_filtered (file,
-                   _("Automatic usage of hardware breakpoints is %s.\n"),
-                   value);
+  gdb_printf (file,
+             _("Automatic usage of hardware breakpoints is %s.\n"),
+             value);
 }
 
 /* If on, GDB keeps breakpoints inserted even if the inferior is
@@ -374,8 +572,24 @@ static void
 show_always_inserted_mode (struct ui_file *file, int from_tty,
                     struct cmd_list_element *c, const char *value)
 {
-  fprintf_filtered (file, _("Always inserted breakpoint mode is %s.\n"),
-                   value);
+  gdb_printf (file, _("Always inserted breakpoint mode is %s.\n"),
+             value);
+}
+
+/* True if breakpoint debug output is enabled.  */
+static bool debug_breakpoint = false;
+
+/* Print a "breakpoint" debug statement.  */
+#define breakpoint_debug_printf(fmt, ...) \
+  debug_prefixed_printf_cond (debug_breakpoint, "breakpoint", fmt, \
+                             ##__VA_ARGS__)
+
+/* "show debug breakpoint" implementation.  */
+static void
+show_debug_breakpoint (struct ui_file *file, int from_tty,
+                      struct cmd_list_element *c, const char *value)
+{
+  gdb_printf (file, _("Breakpoint location debugging is %s.\n"), value);
 }
 
 /* See breakpoint.h.  */
@@ -463,7 +677,7 @@ breakpoint_condition_evaluation_mode (void)
 /* Return true if GDB should evaluate breakpoint conditions or false
    otherwise.  */
 
-static int
+static bool
 gdb_evaluates_breakpoint_condition_p (void)
 {
   const char *mode = breakpoint_condition_evaluation_mode ();
@@ -480,25 +694,16 @@ static int overlay_events_enabled;
 /* See description in breakpoint.h. */
 bool target_exact_watchpoints = false;
 
-/* Walk the following statement or block through all breakpoints.
-   ALL_BREAKPOINTS_SAFE does so even if the statement deletes the
-   current breakpoint.  */
-
-#define ALL_BREAKPOINTS_SAFE(B,TMP)    \
-       for (B = breakpoint_chain;      \
-            B ? (TMP=B->next, 1): 0;   \
-            B = TMP)
-
 /* Chains of all breakpoints defined.  */
 
-static struct breakpoint *breakpoint_chain;
+static intrusive_list<breakpoint> breakpoint_chain;
 
 /* See breakpoint.h.  */
 
 breakpoint_range
 all_breakpoints ()
 {
-  return breakpoint_range (breakpoint_chain);
+  return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
 }
 
 /* See breakpoint.h.  */
@@ -514,7 +719,8 @@ all_breakpoints_safe ()
 tracepoint_range
 all_tracepoints ()
 {
-  return tracepoint_range (breakpoint_chain);
+  return tracepoint_range (tracepoint_iterator (breakpoint_chain.begin ()),
+                          tracepoint_iterator (breakpoint_chain.end ()));
 }
 
 /* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS.  */
@@ -628,7 +834,7 @@ static struct cmd_list_element *breakpoint_show_cmdlist;
 struct cmd_list_element *save_cmdlist;
 
 /* Return whether a breakpoint is an active enabled breakpoint.  */
-static int
+static bool
 breakpoint_enabled (struct breakpoint *b)
 {
   return (b->enable_state == bp_enabled);
@@ -669,8 +875,8 @@ scoped_rbreak_breakpoints::~scoped_rbreak_breakpoints ()
 void
 clear_breakpoint_hit_counts (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    b->hit_count = 0;
+  for (breakpoint &b : all_breakpoints ())
+    b.hit_count = 0;
 }
 
 \f
@@ -680,13 +886,26 @@ clear_breakpoint_hit_counts (void)
 struct breakpoint *
 get_breakpoint (int num)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == num)
-      return b;
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == num)
+      return &b;
   
   return nullptr;
 }
 
+/* Return TRUE if NUM refer to an existing breakpoint that has
+   multiple code locations.  */
+
+static bool
+has_multiple_locations (int num)
+{
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == num)
+      return b.has_multiple_locations ();
+
+  return false;
+}
+
 \f
 
 /* Mark locations as "conditions have changed" in case the target supports
@@ -706,8 +925,8 @@ mark_breakpoint_modified (struct breakpoint *b)
   if (!is_breakpoint (b))
     return;
 
-  for (bp_location *loc : b->locations ())
-    loc->condition_changed = condition_modified;
+  for (bp_location &loc : b->locations ())
+    loc.condition_changed = condition_modified;
 }
 
 /* Mark location as "conditions have changed" in case the target supports
@@ -798,14 +1017,14 @@ show_condition_evaluation_mode (struct ui_file *file, int from_tty,
                                struct cmd_list_element *c, const char *value)
 {
   if (condition_evaluation_mode == condition_evaluation_auto)
-    fprintf_filtered (file,
-                     _("Breakpoint condition evaluation "
-                       "mode is %s (currently %s).\n"),
-                     value,
-                     breakpoint_condition_evaluation_mode ());
+    gdb_printf (file,
+               _("Breakpoint condition evaluation "
+                 "mode is %s (currently %s).\n"),
+               value,
+               breakpoint_condition_evaluation_mode ());
   else
-    fprintf_filtered (file, _("Breakpoint condition evaluation mode is %s.\n"),
-                     value);
+    gdb_printf (file, _("Breakpoint condition evaluation mode is %s.\n"),
+               value);
 }
 
 /* Parse COND_STRING in the context of LOC and set as the condition
@@ -828,9 +1047,9 @@ set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
        {
          loc->cond = std::move (new_exp);
          if (loc->disabled_by_cond && loc->enabled)
-           printf_filtered (_("Breakpoint %d's condition is now valid at "
-                              "location %d, enabling.\n"),
-                            bp_num, loc_num);
+           gdb_printf (_("Breakpoint %d's condition is now valid at "
+                         "location %d, enabling.\n"),
+                       bp_num, loc_num);
 
          loc->disabled_by_cond = false;
        }
@@ -858,6 +1077,15 @@ set_breakpoint_location_condition (const char *cond_string, bp_location *loc,
     error (_("Garbage '%s' follows condition"), cond_string);
 }
 
+/* See breakpoint.h.  */
+
+void
+notify_breakpoint_modified (breakpoint *b)
+{
+  interps_notify_breakpoint_modified (b);
+  gdb::observers::breakpoint_modified.notify (b);
+}
+
 void
 set_breakpoint_condition (struct breakpoint *b, const char *exp,
                          int from_tty, bool force)
@@ -867,18 +1095,18 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
       b->cond_string.reset ();
 
       if (is_watchpoint (b))
-       static_cast<watchpoint *> (b)->cond_exp.reset ();
+       gdb::checked_static_cast<watchpoint *> (b)->cond_exp.reset ();
       else
        {
          int loc_num = 1;
-         for (bp_location *loc : b->locations ())
+         for (bp_location &loc : b->locations ())
            {
-             loc->cond.reset ();
-             if (loc->disabled_by_cond && loc->enabled)
-               printf_filtered (_("Breakpoint %d's condition is now valid at "
-                                  "location %d, enabling.\n"),
-                                b->number, loc_num);
-             loc->disabled_by_cond = false;
+             loc.cond.reset ();
+             if (loc.disabled_by_cond && loc.enabled)
+               gdb_printf (_("Breakpoint %d's condition is now valid at "
+                             "location %d, enabling.\n"),
+                           b->number, loc_num);
+             loc.disabled_by_cond = false;
              loc_num++;
 
              /* No need to free the condition agent expression
@@ -888,7 +1116,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
        }
 
       if (from_tty)
-       printf_filtered (_("Breakpoint %d now unconditional.\n"), b->number);
+       gdb_printf (_("Breakpoint %d now unconditional.\n"), b->number);
     }
   else
     {
@@ -899,7 +1127,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
          expression_up new_exp = parse_exp_1 (&arg, 0, 0, 0, &tracker);
          if (*arg != 0)
            error (_("Junk at end of expression"));
-         watchpoint *w = static_cast<watchpoint *> (b);
+         watchpoint *w = gdb::checked_static_cast<watchpoint *> (b);
          w->cond_exp = std::move (new_exp);
          w->cond_exp_valid_block = tracker.block ();
        }
@@ -913,13 +1141,13 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
             the error and the condition string will be rejected.
             This two-pass approach is taken to avoid setting the
             state of locations in case of a reject.  */
-         for (bp_location *loc : b->locations ())
+         for (const bp_location &loc : b->locations ())
            {
              try
                {
                  const char *arg = exp;
-                 parse_exp_1 (&arg, loc->address,
-                              block_for_pc (loc->address), 0);
+                 parse_exp_1 (&arg, loc.address,
+                              block_for_pc (loc.address), 0);
                  if (*arg != 0)
                    error (_("Junk at end of expression"));
                  break;
@@ -929,16 +1157,16 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
                  /* Condition string is invalid.  If this happens to
                     be the last loc, abandon (if not forced) or continue
                     (if forced).  */
-                 if (loc->next == nullptr && !force)
+                 if (&loc == &b->last_loc () && !force)
                    throw;
                }
            }
 
          /* If we reach here, the condition is valid at some locations.  */
          int loc_num = 1;
-         for (bp_location *loc : b->locations ())
+         for (bp_location &loc : b->locations ())
            {
-             set_breakpoint_location_condition (exp, loc, b->number, loc_num);
+             set_breakpoint_location_condition (exp, &loc, b->number, loc_num);
              loc_num++;
            }
        }
@@ -950,7 +1178,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
     }
   mark_breakpoint_modified (b);
 
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* See breakpoint.h.  */
@@ -959,14 +1187,14 @@ void
 set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
                          bool force)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == bpnum)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == bpnum)
       {
        /* Check if this breakpoint has a "stop" method implemented in an
           extension language.  This method and conditions entered into GDB
           from the CLI are mutually exclusive.  */
        const struct extension_language_defn *extlang
-         = get_breakpoint_cond_ext_lang (b, EXT_LANG_NONE);
+         = get_breakpoint_cond_ext_lang (&b, EXT_LANG_NONE);
 
        if (extlang != NULL)
          {
@@ -974,9 +1202,9 @@ set_breakpoint_condition (int bpnum, const char *exp, int from_tty,
                     " a %s stop condition defined for this breakpoint."),
                   ext_lang_capitalized_name (extlang));
          }
-       set_breakpoint_condition (b, exp, from_tty, force);
+       set_breakpoint_condition (&b, exp, from_tty, force);
 
-       if (is_breakpoint (b))
+       if (is_breakpoint (&b))
          update_global_location_list (UGLL_MAY_INSERT);
 
        return;
@@ -1051,11 +1279,11 @@ condition_completer (struct cmd_list_element *cmd,
       /* We're completing the breakpoint number.  */
       len = strlen (text);
 
-      for (breakpoint *b : all_breakpoints ())
+      for (breakpoint &b : all_breakpoints ())
        {
          char number[50];
 
-         xsnprintf (number, sizeof (number), "%d", b->number);
+         xsnprintf (number, sizeof (number), "%d", b.number);
 
          if (strncmp (number, text, len) == 0)
            tracker.add_completion (make_unique_xstrdup (number));
@@ -1127,8 +1355,10 @@ check_no_tracepoint_commands (struct command_line *commands)
     }
 }
 
-struct longjmp_breakpoint : public breakpoint
+struct longjmp_breakpoint : public momentary_breakpoint
 {
+  using momentary_breakpoint::momentary_breakpoint;
+
   ~longjmp_breakpoint () override;
 };
 
@@ -1139,13 +1369,8 @@ is_tracepoint_type (bptype type)
 {
   return (type == bp_tracepoint
          || type == bp_fast_tracepoint
-         || type == bp_static_tracepoint);
-}
-
-static bool
-is_longjmp_type (bptype type)
-{
-  return type == bp_longjmp || type == bp_exception;
+         || type == bp_static_tracepoint
+         || type == bp_static_marker_tracepoint);
 }
 
 /* See breakpoint.h.  */
@@ -1159,19 +1384,43 @@ is_tracepoint (const struct breakpoint *b)
 /* Factory function to create an appropriate instance of breakpoint given
    TYPE.  */
 
-static std::unique_ptr<breakpoint>
-new_breakpoint_from_type (bptype type)
+template<typename... Arg>
+static std::unique_ptr<code_breakpoint>
+new_breakpoint_from_type (struct gdbarch *gdbarch, bptype type,
+                         Arg&&... args)
 {
-  breakpoint *b;
+  code_breakpoint *b;
 
-  if (is_tracepoint_type (type))
-    b = new tracepoint ();
-  else if (is_longjmp_type (type))
-    b = new longjmp_breakpoint ();
-  else
-    b = new breakpoint ();
+  switch (type)
+    {
+    case bp_breakpoint:
+    case bp_hardware_breakpoint:
+      b = new ordinary_breakpoint (gdbarch, type,
+                                  std::forward<Arg> (args)...);
+      break;
+
+    case bp_fast_tracepoint:
+    case bp_static_tracepoint:
+    case bp_tracepoint:
+      b = new tracepoint (gdbarch, type,
+                         std::forward<Arg> (args)...);
+      break;
+
+    case bp_static_marker_tracepoint:
+      b = new static_marker_tracepoint (gdbarch, type,
+                                       std::forward<Arg> (args)...);
+      break;
+
+    case bp_dprintf:
+      b = new dprintf_breakpoint (gdbarch, type,
+                                 std::forward<Arg> (args)...);
+      break;
+
+    default:
+      gdb_assert_not_reached ("invalid type");
+    }
 
-  return std::unique_ptr<breakpoint> (b);
+  return std::unique_ptr<code_breakpoint> (b);
 }
 
 /* A helper function that validates that COMMANDS are valid for a
@@ -1210,7 +1459,8 @@ validate_commands_for_breakpoint (struct breakpoint *b,
              if (b->type == bp_fast_tracepoint)
                error (_("The 'while-stepping' command "
                         "cannot be used for fast tracepoint"));
-             else if (b->type == bp_static_tracepoint)
+             else if (b->type == bp_static_tracepoint
+                      || b->type == bp_static_marker_tracepoint)
                error (_("The 'while-stepping' command "
                         "cannot be used for static tracepoint"));
 
@@ -1250,12 +1500,13 @@ static_tracepoints_here (CORE_ADDR addr)
 {
   std::vector<breakpoint *> found;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_static_tracepoint)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_static_tracepoint
+       || b.type == bp_static_marker_tracepoint)
       {
-       for (bp_location *loc : b->locations ())
-         if (loc->address == addr)
-           found.push_back (b);
+       for (bp_location &loc : b.locations ())
+         if (loc.address == addr)
+           found.push_back (&b);
       }
 
   return found;
@@ -1271,7 +1522,7 @@ breakpoint_set_commands (struct breakpoint *b,
   validate_commands_for_breakpoint (b, commands.get ());
 
   b->commands = std::move (commands);
-  gdb::observers::breakpoint_modified.notify (b);
+  notify_breakpoint_modified (b);
 }
 
 /* Set the internal `silent' flag on the breakpoint.  Note that this
@@ -1285,33 +1536,64 @@ breakpoint_set_silent (struct breakpoint *b, int silent)
 
   b->silent = silent;
   if (old_silent != silent)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
-/* Set the thread for this breakpoint.  If THREAD is -1, make the
-   breakpoint work for any thread.  */
+/* See breakpoint.h.  */
 
 void
 breakpoint_set_thread (struct breakpoint *b, int thread)
 {
-  int old_thread = b->thread;
+  /* THREAD should be -1, meaning no thread restriction, or it should be a
+     valid global thread-id, which are greater than zero.  */
+  gdb_assert (thread == -1 || thread > 0);
 
+  /* It is not valid to set a thread restriction for a breakpoint that
+     already has task or inferior restriction.  */
+  gdb_assert (thread == -1 || (b->task == -1 && b->inferior == -1));
+
+  int old_thread = b->thread;
   b->thread = thread;
   if (old_thread != thread)
+    notify_breakpoint_modified (b);
+}
+
+/* See breakpoint.h.  */
+
+void
+breakpoint_set_inferior (struct breakpoint *b, int inferior)
+{
+  /* INFERIOR should be -1, meaning no inferior restriction, or it should
+     be a valid inferior number, which are greater than zero.  */
+  gdb_assert (inferior == -1 || inferior > 0);
+
+  /* It is not valid to set an inferior restriction for a breakpoint that
+     already has a task or thread restriction.  */
+  gdb_assert (inferior == -1 || (b->task == -1 && b->thread == -1));
+
+  int old_inferior = b->inferior;
+  b->inferior = inferior;
+  if (old_inferior != inferior)
     gdb::observers::breakpoint_modified.notify (b);
 }
 
-/* Set the task for this breakpoint.  If TASK is 0, make the
-   breakpoint work for any task.  */
+/* See breakpoint.h.  */
 
 void
 breakpoint_set_task (struct breakpoint *b, int task)
 {
-  int old_task = b->task;
+  /* TASK should be -1, meaning no task restriction, or it should be a
+     valid task-id, which are greater than zero.  */
+  gdb_assert (task == -1 || task > 0);
 
+  /* It is not valid to set a task restriction for a breakpoint that
+     already has a thread or inferior restriction.  */
+  gdb_assert (task == -1 || (b->thread == -1 && b->inferior == -1));
+
+  int old_task = b->task;
   b->task = task;
   if (old_task != task)
-    gdb::observers::breakpoint_modified.notify (b);
+    notify_breakpoint_modified (b);
 }
 
 static void
@@ -1380,7 +1662,7 @@ commands_command_1 (const char *arg, int from_tty,
         {
           validate_commands_for_breakpoint (b, cmd.get ());
           b->commands = cmd;
-          gdb::observers::breakpoint_modified.notify (b);
+          notify_breakpoint_modified (b);
         }
      });
 }
@@ -1403,19 +1685,19 @@ commands_from_control_command (const char *arg, struct command_line *cmd)
   return simple_control;
 }
 
-/* Return non-zero if BL->TARGET_INFO contains valid information.  */
+/* Return true if BL->TARGET_INFO contains valid information.  */
 
-static int
+static bool
 bp_location_has_shadow (struct bp_location *bl)
 {
   if (bl->loc_type != bp_loc_software_breakpoint)
-    return 0;
+    return false;
   if (!bl->inserted)
-    return 0;
+    return false;
   if (bl->target_info.shadow_len == 0)
     /* BL isn't valid, or doesn't shadow memory.  */
-    return 0;
-  return 1;
+    return false;
+  return true;
 }
 
 /* Update BUF, which is LEN bytes read from the target address
@@ -1653,7 +1935,7 @@ is_watchpoint (const struct breakpoint *bpt)
    and in any state.  It is presently left to the target allowing
    memory accesses when threads are running.  */
 
-static int
+static bool
 watchpoint_in_thread_scope (struct watchpoint *b)
 {
   return (b->pspace == current_program_space
@@ -1677,6 +1959,7 @@ watchpoint_del_at_next_stop (struct watchpoint *w)
       w->related_breakpoint = w;
     }
   w->disposition = disp_del_at_next_stop;
+  disable_breakpoint (w);
 }
 
 /* Extract a bitfield value from value VAL using the bit parameters contained in
@@ -1690,50 +1973,34 @@ extract_bitfield_from_watchpoint_value (struct watchpoint *w, struct value *val)
   if (val == NULL)
     return NULL;
 
-  bit_val = allocate_value (value_type (val));
+  bit_val = value::allocate (val->type ());
 
-  unpack_value_bitfield (bit_val,
-                        w->val_bitpos,
-                        w->val_bitsize,
-                        value_contents_for_printing (val).data (),
-                        value_offset (val),
-                        val);
+  val->unpack_bitfield (bit_val,
+                       w->val_bitpos,
+                       w->val_bitsize,
+                       val->contents_for_printing ().data (),
+                       val->offset ());
 
   return bit_val;
 }
 
-/* Allocate a dummy location and add it to B, which must be a software
-   watchpoint.  This is required because even if a software watchpoint
-   is not watching any memory, bpstat_stop_status requires a location
-   to be able to report stops.  */
+/* Allocate a dummy location and add it to B.  This is required
+   because bpstat_stop_status requires a location to be able to report
+   stops.  */
 
 static void
-software_watchpoint_add_no_memory_location (struct breakpoint *b,
-                                           struct program_space *pspace)
+add_dummy_location (struct breakpoint *b,
+                   struct program_space *pspace)
 {
-  gdb_assert (b->type == bp_watchpoint && b->loc == NULL);
-
-  b->loc = allocate_bp_location (b);
-  b->loc->pspace = pspace;
-  b->loc->address = -1;
-  b->loc->length = -1;
-}
-
-/* Returns true if B is a software watchpoint that is not watching any
-   memory (e.g., "watch $pc").  */
+  gdb_assert (!b->has_locations ());
 
-static bool
-is_no_memory_software_watchpoint (struct breakpoint *b)
-{
-  return (b->type == bp_watchpoint
-         && b->loc != NULL
-         && b->loc->next == NULL
-         && b->loc->address == -1
-         && b->loc->length == -1);
+  bp_location *loc = new bp_location (b, bp_loc_other);
+  loc->pspace = pspace;
+  b->add_location (*loc);
 }
 
 /* Assuming that B is a watchpoint:
-   - Reparse watchpoint expression, if REPARSE is non-zero
+   - Reparse watchpoint expression, if REPARSE is true
    - Evaluate expression and store the result in B->val
    - Evaluate the condition if there is one, and store the result
      in b->loc->cond.
@@ -1785,11 +2052,9 @@ is_no_memory_software_watchpoint (struct breakpoint *b)
    watchpoint removal from inferior.  */
 
 static void
-update_watchpoint (struct watchpoint *b, int reparse)
+update_watchpoint (struct watchpoint *b, bool reparse)
 {
-  int within_current_scope;
-  struct frame_id saved_frame_id;
-  int frame_saved;
+  bool within_current_scope;
 
   /* If this is a local watchpoint, we only want to check if the
      watchpoint frame is in scope if the current thread is the thread
@@ -1799,15 +2064,15 @@ update_watchpoint (struct watchpoint *b, int reparse)
 
   if (b->disposition == disp_del_at_next_stop)
     return;
-  frame_saved = 0;
+
+  gdb::optional<scoped_restore_selected_frame> restore_frame;
 
   /* Determine if the watchpoint is within scope.  */
   if (b->exp_valid_block == NULL)
-    within_current_scope = 1;
+    within_current_scope = true;
   else
     {
-      struct frame_info *fi = get_current_frame ();
+      frame_info_ptr fi = get_current_frame ();
       struct gdbarch *frame_arch = get_frame_arch (fi);
       CORE_ADDR frame_pc = get_frame_pc (fi);
 
@@ -1823,8 +2088,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
       /* FIXME drow/2003-09-09: It would be nice if evaluate_expression
         took a frame parameter, so that we didn't have to change the
         selected frame.  */
-      frame_saved = 1;
-      saved_frame_id = get_frame_id (get_selected_frame (NULL));
+      restore_frame.emplace ();
 
       fi = frame_find_by_id (b->watchpoint_frame);
       within_current_scope = (fi != NULL);
@@ -1835,7 +2099,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
   /* We don't free locations.  They are stored in the bp_location array
      and update_global_location_list will eventually delete them and
      remove breakpoints if needed.  */
-  b->loc = NULL;
+  b->clear_locations ();
 
   if (within_current_scope && reparse)
     {
@@ -1877,7 +2141,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
         the target gains execution, through breakpoint_re_set.  */
       if (!can_use_hw_watchpoints)
        {
-         if (b->ops->works_in_software_mode (b))
+         if (b->works_in_software_mode ())
            b->type = bp_watchpoint;
          else
            error (_("Can't set read/access watchpoint when "
@@ -1920,10 +2184,10 @@ update_watchpoint (struct watchpoint *b, int reparse)
             must watch it.  If the first value returned is
             still lazy, that means an error occurred reading it;
             watch it anyway in case it becomes readable.  */
-         if (VALUE_LVAL (v) == lval_memory
-             && (v == val_chain[0] || ! value_lazy (v)))
+         if (v->lval () == lval_memory
+             && (v == val_chain[0] || ! v->lazy ()))
            {
-             struct type *vtype = check_typedef (value_type (v));
+             struct type *vtype = check_typedef (v->type ());
 
              /* We only watch structs and arrays if user asked
                 for it explicitly, never if they just happen to
@@ -1934,15 +2198,14 @@ update_watchpoint (struct watchpoint *b, int reparse)
                {
                  CORE_ADDR addr;
                  enum target_hw_bp_type type;
-                 struct bp_location *loc, **tmp;
                  int bitpos = 0, bitsize = 0;
 
-                 if (value_bitsize (v) != 0)
+                 if (v->bitsize () != 0)
                    {
                      /* Extract the bit parameters out from the bitfield
                         sub-expression.  */
-                     bitpos = value_bitpos (v);
-                     bitsize = value_bitsize (v);
+                     bitpos = v->bitpos ();
+                     bitsize = v->bitsize ();
                    }
                  else if (v == result && b->val_bitsize != 0)
                    {
@@ -1953,7 +2216,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
                      bitsize = b->val_bitsize;
                    }
 
-                 addr = value_address (v);
+                 addr = v->address ();
                  if (bitsize != 0)
                    {
                      /* Skip the bytes that don't contain the bitfield.  */
@@ -1966,14 +2229,12 @@ update_watchpoint (struct watchpoint *b, int reparse)
                  else if (b->type == bp_access_watchpoint)
                    type = hw_access;
 
-                 loc = allocate_bp_location (b);
-                 for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
-                   ;
-                 *tmp = loc;
-                 loc->gdbarch = value_type (v)->arch ();
-
+                 bp_location *loc = b->allocate_location ();
+                 loc->gdbarch = v->type ()->arch ();
                  loc->pspace = frame_pspace;
-                 loc->address = address_significant (loc->gdbarch, addr);
+                 loc->address
+                   = gdbarch_remove_non_address_bits (loc->gdbarch, addr);
+                 b->add_location (*loc);
 
                  if (bitsize != 0)
                    {
@@ -1981,18 +2242,32 @@ update_watchpoint (struct watchpoint *b, int reparse)
                      loc->length = ((bitpos % 8) + bitsize + 7) / 8;
                    }
                  else
-                   loc->length = TYPE_LENGTH (value_type (v));
+                   loc->length = v->type ()->length ();
 
                  loc->watchpoint_type = type;
                }
            }
        }
 
+      /* Helper function to bundle possibly emitting a warning along with
+        changing the type of B to bp_watchpoint.  */
+      auto change_type_to_bp_watchpoint = [] (breakpoint *bp)
+      {
+       /* Only warn for breakpoints that have been assigned a +ve number,
+          anything else is either an internal watchpoint (which we don't
+          currently create) or has not yet been finalized, in which case
+          this change of type will be occurring before the user is told
+          the type of this watchpoint.  */
+       if (bp->type == bp_hardware_watchpoint && bp->number > 0)
+         warning (_("watchpoint %d downgraded to software watchpoint"),
+                  bp->number);
+       bp->type = bp_watchpoint;
+      };
+
       /* Change the type of breakpoint between hardware assisted or
-        an ordinary watchpoint depending on the hardware support
-        and free hardware slots.  REPARSE is set when the inferior
-        is started.  */
-      if (reparse)
+        an ordinary watchpoint depending on the hardware support and
+        free hardware slots.  Recheck the number of free hardware slots
+        as the value chain may have changed.  */
        {
          int reg_cnt;
          enum bp_loc_type loc_type;
@@ -2036,7 +2311,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
                = target_can_use_hardware_watchpoint (type, i, other_type_used);
              if (target_resources_ok <= 0)
                {
-                 int sw_mode = b->ops->works_in_software_mode (b);
+                 bool sw_mode = b->works_in_software_mode ();
 
                  if (target_resources_ok == 0 && !sw_mode)
                    error (_("Target does not support this type of "
@@ -2046,7 +2321,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
                             "resources for this watchpoint."));
 
                  /* Downgrade to software watchpoint.  */
-                 b->type = bp_watchpoint;
+                 change_type_to_bp_watchpoint (b);
                }
              else
                {
@@ -2057,7 +2332,7 @@ update_watchpoint (struct watchpoint *b, int reparse)
                  b->type = type;
                }
            }
-         else if (!b->ops->works_in_software_mode (b))
+         else if (!b->works_in_software_mode ())
            {
              if (!can_use_hw_watchpoints)
                error (_("Can't set read/access watchpoint when "
@@ -2067,56 +2342,53 @@ update_watchpoint (struct watchpoint *b, int reparse)
                         "read/access watchpoint."));
            }
          else
-           b->type = bp_watchpoint;
+           change_type_to_bp_watchpoint (b);
 
-         loc_type = (b->type == bp_watchpoint? bp_loc_other
+         loc_type = (b->type == bp_watchpoint? bp_loc_software_watchpoint
                      : bp_loc_hardware_watchpoint);
-         for (bp_location *bl : b->locations ())
-           bl->loc_type = loc_type;
+
+         for (bp_location &bl : b->locations ())
+           bl.loc_type = loc_type;
        }
 
       /* If a software watchpoint is not watching any memory, then the
         above left it without any location set up.  But,
         bpstat_stop_status requires a location to be able to report
         stops, so make sure there's at least a dummy one.  */
-      if (b->type == bp_watchpoint && b->loc == NULL)
-       software_watchpoint_add_no_memory_location (b, frame_pspace);
+      if (b->type == bp_watchpoint && !b->has_locations ())
+       add_dummy_location (b, frame_pspace);
     }
   else if (!within_current_scope)
     {
-      printf_filtered (_("\
+      gdb_printf (_("\
 Watchpoint %d deleted because the program has left the block\n\
 in which its expression is valid.\n"),
-                      b->number);
+                 b->number);
       watchpoint_del_at_next_stop (b);
     }
-
-  /* Restore the selected frame.  */
-  if (frame_saved)
-    select_frame (frame_find_by_id (saved_frame_id));
 }
 
-
-/* Returns 1 iff breakpoint location should be
+/* Returns true iff breakpoint location should be
    inserted in the inferior.  We don't differentiate the type of BL's owner
    (breakpoint vs. tracepoint), although insert_location in tracepoint's
    breakpoint_ops is not defined, because in insert_bp_location,
    tracepoint's insert_location will not be called.  */
-static int
+
+static bool
 should_be_inserted (struct bp_location *bl)
 {
   if (bl->owner == NULL || !breakpoint_enabled (bl->owner))
-    return 0;
+    return false;
 
   if (bl->owner->disposition == disp_del_at_next_stop)
-    return 0;
+    return false;
 
   if (!bl->enabled || bl->disabled_by_cond
       || bl->shlib_disabled || bl->duplicate)
-    return 0;
+    return false;
 
   if (user_breakpoint_p (bl->owner) && bl->pspace->executing_startup)
-    return 0;
+    return false;
 
   /* This is set for example, when we're attached to the parent of a
      vfork, and have detached from the child.  The child is running
@@ -2127,7 +2399,7 @@ should_be_inserted (struct bp_location *bl)
      the child could still trip on the parent's breakpoints.  Since
      the parent is blocked anyway, it won't miss any breakpoint.  */
   if (bl->pspace->breakpoints_not_allowed)
-    return 0;
+    return false;
 
   /* Don't insert a breakpoint if we're trying to step past its
      location, except if the breakpoint is a single-step breakpoint,
@@ -2149,7 +2421,7 @@ should_be_inserted (struct bp_location *bl)
     {
       infrun_debug_printf ("skipping breakpoint: stepping past insn at: %s",
                           paddress (bl->gdbarch, bl->address));
-      return 0;
+      return false;
     }
 
   /* Don't insert watchpoints if we're trying to step past the
@@ -2160,25 +2432,22 @@ should_be_inserted (struct bp_location *bl)
       infrun_debug_printf ("stepping past non-steppable watchpoint. "
                           "skipping watchpoint at %s:%d",
                           paddress (bl->gdbarch, bl->address), bl->length);
-      return 0;
+      return false;
     }
 
-  return 1;
+  return true;
 }
 
 /* Same as should_be_inserted but does the check assuming
    that the location is not duplicated.  */
 
-static int
+static bool
 unduplicated_should_be_inserted (struct bp_location *bl)
 {
-  int result;
-  const int save_duplicate = bl->duplicate;
+  scoped_restore restore_bl_duplicate
+    = make_scoped_restore (&bl->duplicate, 0);
 
-  bl->duplicate = 0;
-  result = should_be_inserted (bl);
-  bl->duplicate = save_duplicate;
-  return result;
+  return should_be_inserted (bl);
 }
 
 /* Parses a conditional described by an expression COND into an
@@ -2221,7 +2490,7 @@ parse_cond_to_aexpr (CORE_ADDR scope, struct expression *cond)
 static void
 build_target_condition_list (struct bp_location *bl)
 {
-  int null_condition_or_parse_error = 0;
+  bool null_condition_or_parse_error = false;
   int modified = bl->needs_update;
 
   /* Release conditions left over from a previous insert.  */
@@ -2264,7 +2533,7 @@ build_target_condition_list (struct bp_location *bl)
             went wrong or we have a null condition expression.  */
          if (!loc->cond_bytecode)
            {
-             null_condition_or_parse_error = 1;
+             null_condition_or_parse_error = true;
              break;
            }
        }
@@ -2295,7 +2564,7 @@ build_target_condition_list (struct bp_location *bl)
   /* No NULL conditions or failed bytecode generation.  Build a
      condition list for this location's address.  If we have software
      and hardware locations at the same address, they aren't
-     considered duplicates, but we still marge all the conditions
+     considered duplicates, but we still merge all the conditions
      anyway, as it's simpler, and doesn't really make a practical
      difference.  */
   for (bp_location *loc : loc_range)
@@ -2363,7 +2632,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
       const char *cmd1;
 
       cmd1 = cmdrest;
-      expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1);
+      expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope),
+                                       PARSER_COMMA_TERMINATES);
       argvec.push_back (expr.release ());
       cmdrest = cmd1;
       if (*cmdrest == ',')
@@ -2398,7 +2668,7 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd)
 static void
 build_target_command_list (struct bp_location *bl)
 {
-  int null_command_or_parse_error = 0;
+  bool null_command_or_parse_error = false;
   int modified = bl->needs_update;
 
   /* Clear commands left over from a previous insert.  */
@@ -2447,7 +2717,7 @@ build_target_command_list (struct bp_location *bl)
             went wrong or we have a null command expression.  */
          if (!loc->cmd_bytecode)
            {
-             null_command_or_parse_error = 1;
+             null_command_or_parse_error = true;
              break;
            }
        }
@@ -2504,7 +2774,7 @@ build_target_command_list (struct bp_location *bl)
    registers state.  */
 
 static int
-breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
+breakpoint_kind (const struct bp_location *bl, CORE_ADDR *addr)
 {
   if (bl->owner->type == bp_single_step)
     {
@@ -2520,6 +2790,29 @@ breakpoint_kind (struct bp_location *bl, CORE_ADDR *addr)
     return gdbarch_breakpoint_kind_from_pc (bl->gdbarch, addr);
 }
 
+/* Rethrow the currently handled exception, if it's a TARGET_CLOSE_ERROR.
+   E is either the currently handled exception, or a copy, or a sliced copy,
+   so we can't rethrow that one, but we can use it to inspect the properties
+   of the currently handled exception.  */
+
+static void
+rethrow_on_target_close_error (const gdb_exception &e)
+{
+  if (e.reason == 0)
+    return;
+  /* Can't set the breakpoint.  */
+
+  if (e.error != TARGET_CLOSE_ERROR)
+    return;
+
+  /* If the target has closed then it will have deleted any breakpoints
+     inserted within the target inferior, as a result any further attempts
+     to interact with the breakpoint objects is not possible.  Just rethrow
+     the error.  Don't use e to rethrow, to prevent object slicing of the
+     exception.  */
+  throw;
+}
+
 /* Insert a low-level "breakpoint" of some type.  BL is the breakpoint
    location.  Any error messages are printed to TMP_ERROR_STREAM; and
    DISABLED_BREAKS, and HW_BREAKPOINT_ERROR are used to report problems.
@@ -2540,6 +2833,8 @@ insert_bp_location (struct bp_location *bl,
   if (!should_be_inserted (bl) || (bl->inserted && !bl->needs_update))
     return 0;
 
+  breakpoint_debug_printf ("%s", breakpoint_location_address_str (bl).c_str ());
+
   /* Note we don't initialize bl->target_info, as that wipes out
      the breakpoint location's shadow_contents if the breakpoint
      is still inserted at that location.  This in turn breaks
@@ -2578,12 +2873,12 @@ insert_bp_location (struct bp_location *bl,
 
       if (mr != nullptr && mr->attrib.mode != MEM_RW)
        {
-         fprintf_unfiltered (tmp_error_stream,
-                             _("Cannot insert breakpoint %d.\n"
-                               "Cannot set software breakpoint "
-                               "at read-only address %s\n"),
-                             bl->owner->number,
-                             paddress (bl->gdbarch, bl->address));
+         gdb_printf (tmp_error_stream,
+                     _("Cannot insert breakpoint %d.\n"
+                       "Cannot set software breakpoint "
+                       "at read-only address %s\n"),
+                     bl->owner->number,
+                     paddress (bl->gdbarch, bl->address));
          return 1;
        }
     }
@@ -2601,12 +2896,13 @@ insert_bp_location (struct bp_location *bl,
            {
              int val;
 
-             val = bl->owner->ops->insert_location (bl);
+             val = bl->owner->insert_location (bl);
              if (val)
                bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
            }
          catch (gdb_exception &e)
            {
+             rethrow_on_target_close_error (e);
              bp_excpt = std::move (e);
            }
        }
@@ -2646,14 +2942,15 @@ insert_bp_location (struct bp_location *bl,
                    }
                  catch (gdb_exception &e)
                    {
+                     rethrow_on_target_close_error (e);
                      bp_excpt = std::move (e);
                    }
 
                  if (bp_excpt.reason != 0)
-                   fprintf_unfiltered (tmp_error_stream,
-                                       "Overlay breakpoint %d "
-                                       "failed: in ROM?\n",
-                                       bl->owner->number);
+                   gdb_printf (tmp_error_stream,
+                               "Overlay breakpoint %d "
+                               "failed: in ROM?\n",
+                               bl->owner->number);
                }
            }
          /* Shall we set a breakpoint at the VMA? */
@@ -2664,12 +2961,13 @@ insert_bp_location (struct bp_location *bl,
                {
                  int val;
 
-                 val = bl->owner->ops->insert_location (bl);
+                 val = bl->owner->insert_location (bl);
                  if (val)
                    bp_excpt = gdb_exception {RETURN_ERROR, GENERIC_ERROR};
                }
-             catch (gdb_exception &e)
+             catch (gdb_exception_error &e)
                {
+                 rethrow_on_target_close_error (e);
                  bp_excpt = std::move (e);
                }
            }
@@ -2684,13 +2982,6 @@ insert_bp_location (struct bp_location *bl,
       if (bp_excpt.reason != 0)
        {
          /* Can't set the breakpoint.  */
-
-         /* If the target has closed then it will have deleted any
-            breakpoints inserted within the target inferior, as a result
-            any further attempts to interact with the breakpoint objects
-            is not possible.  Just rethrow the error.  */
-         if (bp_excpt.error == TARGET_CLOSE_ERROR)
-           throw bp_excpt;
          gdb_assert (bl->owner != nullptr);
 
          /* In some cases, we might not be able to insert a
@@ -2711,19 +3002,19 @@ insert_bp_location (struct bp_location *bl,
            {
              /* See also: disable_breakpoints_in_shlibs.  */
              bl->shlib_disabled = 1;
-             gdb::observers::breakpoint_modified.notify (bl->owner);
+             notify_breakpoint_modified (bl->owner);
              if (!*disabled_breaks)
                {
-                 fprintf_unfiltered (tmp_error_stream, 
-                                     "Cannot insert breakpoint %d.\n", 
-                                     bl->owner->number);
-                 fprintf_unfiltered (tmp_error_stream, 
-                                     "Temporarily disabling shared "
-                                     "library breakpoints:\n");
+                 gdb_printf (tmp_error_stream, 
+                             "Cannot insert breakpoint %d.\n", 
+                             bl->owner->number);
+                 gdb_printf (tmp_error_stream, 
+                             "Temporarily disabling shared "
+                             "library breakpoints:\n");
                }
              *disabled_breaks = 1;
-             fprintf_unfiltered (tmp_error_stream,
-                                 "breakpoint #%d\n", bl->owner->number);
+             gdb_printf (tmp_error_stream,
+                         "breakpoint #%d\n", bl->owner->number);
              return 0;
            }
          else
@@ -2732,13 +3023,13 @@ insert_bp_location (struct bp_location *bl,
                {
                  *hw_breakpoint_error = 1;
                  *hw_bp_error_explained_already = bp_excpt.message != NULL;
-                 fprintf_unfiltered (tmp_error_stream,
-                                     "Cannot insert hardware breakpoint %d%s",
-                                     bl->owner->number,
-                                     bp_excpt.message ? ":" : ".\n");
+                 gdb_printf (tmp_error_stream,
+                             "Cannot insert hardware breakpoint %d%s",
+                             bl->owner->number,
+                             bp_excpt.message ? ":" : ".\n");
                  if (bp_excpt.message != NULL)
-                   fprintf_unfiltered (tmp_error_stream, "%s.\n",
-                                       bp_excpt.what ());
+                   gdb_printf (tmp_error_stream, "%s.\n",
+                               bp_excpt.what ());
                }
              else
                {
@@ -2748,17 +3039,17 @@ insert_bp_location (struct bp_location *bl,
                        = memory_error_message (TARGET_XFER_E_IO,
                                                bl->gdbarch, bl->address);
 
-                     fprintf_unfiltered (tmp_error_stream,
-                                         "Cannot insert breakpoint %d.\n"
-                                         "%s\n",
-                                         bl->owner->number, message.c_str ());
+                     gdb_printf (tmp_error_stream,
+                                 "Cannot insert breakpoint %d.\n"
+                                 "%s\n",
+                                 bl->owner->number, message.c_str ());
                    }
                  else
                    {
-                     fprintf_unfiltered (tmp_error_stream,
-                                         "Cannot insert breakpoint %d: %s\n",
-                                         bl->owner->number,
-                                         bp_excpt.what ());
+                     gdb_printf (tmp_error_stream,
+                                 "Cannot insert breakpoint %d: %s\n",
+                                 bl->owner->number,
+                                 bp_excpt.what ());
                    }
                }
              return 1;
@@ -2772,16 +3063,11 @@ insert_bp_location (struct bp_location *bl,
     }
 
   else if (bl->loc_type == bp_loc_hardware_watchpoint
-          /* NOTE drow/2003-09-08: This state only exists for removing
-             watchpoints.  It's not clear that it's necessary...  */
           && bl->owner->disposition != disp_del_at_next_stop)
     {
       int val;
 
-      gdb_assert (bl->owner->ops != NULL
-                 && bl->owner->ops->insert_location != NULL);
-
-      val = bl->owner->ops->insert_location (bl);
+      val = bl->owner->insert_location (bl);
 
       /* If trying to set a read-watchpoint, and it turns out it's not
         supported, try emulating one with an access watchpoint.  */
@@ -2806,7 +3092,7 @@ insert_bp_location (struct bp_location *bl,
          if (val == 1)
            {
              bl->watchpoint_type = hw_access;
-             val = bl->owner->ops->insert_location (bl);
+             val = bl->owner->insert_location (bl);
 
              if (val)
                /* Back to the original value.  */
@@ -2821,10 +3107,7 @@ insert_bp_location (struct bp_location *bl,
     {
       int val;
 
-      gdb_assert (bl->owner->ops != NULL
-                 && bl->owner->ops->insert_location != NULL);
-
-      val = bl->owner->ops->insert_location (bl);
+      val = bl->owner->insert_location (bl);
       if (val)
        {
          bl->owner->enable_state = bp_disabled;
@@ -2856,30 +3139,18 @@ void
 breakpoint_program_space_exit (struct program_space *pspace)
 {
   /* Remove any breakpoint that was set through this program space.  */
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == pspace)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == pspace)
+      delete_breakpoint (&b);
 
   /* Breakpoints set through other program spaces could have locations
      bound to PSPACE as well.  Remove those.  */
   for (bp_location *loc : all_bp_locations ())
-    {
-      struct bp_location *tmp;
-
-      if (loc->pspace == pspace)
-       {
-         /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
-         if (loc->owner->loc == loc)
-           loc->owner->loc = loc->next;
-         else
-           for (tmp = loc->owner->loc; tmp->next != NULL; tmp = tmp->next)
-             if (tmp->next == loc)
-               {
-                 tmp->next = loc->next;
-                 break;
-               }
-       }
-    }
+    if (loc->pspace == pspace)
+      {
+       /* ALL_BP_LOCATIONS bp_location has LOC->OWNER always non-NULL.  */
+       loc->owner->unadd_location (*loc);
+      }
 
   /* Now update the global location list to permanently delete the
      removed locations above.  */
@@ -2893,12 +3164,12 @@ breakpoint_program_space_exit (struct program_space *pspace)
 void
 insert_breakpoints (void)
 {
-  for (breakpoint *bpt : all_breakpoints ())
-    if (is_hardware_watchpoint (bpt))
+  for (breakpoint &bpt : all_breakpoints ())
+    if (is_hardware_watchpoint (&bpt))
       {
-       struct watchpoint *w = (struct watchpoint *) bpt;
+       watchpoint &w = gdb::checked_static_cast<watchpoint &> (bpt);
 
-       update_watchpoint (w, 0 /* don't reparse.  */);
+       update_watchpoint (&w, false /* don't reparse.  */);
       }
 
   /* Updating watchpoints creates new locations, so update the global
@@ -2964,7 +3235,7 @@ update_inserted_breakpoint_locations (void)
   if (error_flag)
     {
       target_terminal::ours_for_output ();
-      error_stream (tmp_error_stream);
+      error (("%s"), tmp_error_stream.c_str ());
     }
 }
 
@@ -2999,6 +3270,12 @@ insert_breakpoint_locations (void)
          && !valid_global_thread_id (bl->owner->thread))
        continue;
 
+      /* Or inferior specific breakpoints if the inferior no longer
+        exists.  */
+      if (bl->owner->inferior != -1
+         && !valid_global_inferior_id (bl->owner->inferior))
+       continue;
+
       switch_to_program_space_and_thread (bl->pspace);
 
       /* For targets that support global breakpoints, there's no need
@@ -3017,36 +3294,36 @@ insert_breakpoint_locations (void)
 
   /* If we failed to insert all locations of a watchpoint, remove
      them, as half-inserted watchpoint is of limited use.  */
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
-      int some_failed = 0;
+      bool some_failed = false;
 
-      if (!is_hardware_watchpoint (bpt))
+      if (!is_hardware_watchpoint (&bpt))
        continue;
 
-      if (!breakpoint_enabled (bpt))
+      if (!breakpoint_enabled (&bpt))
        continue;
 
-      if (bpt->disposition == disp_del_at_next_stop)
+      if (bpt.disposition == disp_del_at_next_stop)
        continue;
-      
-      for (bp_location *loc : bpt->locations ())
-       if (!loc->inserted && should_be_inserted (loc))
+
+      for (bp_location &loc : bpt.locations ())
+       if (!loc.inserted && should_be_inserted (&loc))
          {
-           some_failed = 1;
+           some_failed = true;
            break;
          }
 
       if (some_failed)
        {
-         for (bp_location *loc : bpt->locations ())
-           if (loc->inserted)
-             remove_breakpoint (loc);
+         for (bp_location &loc : bpt.locations ())
+           if (loc.inserted)
+             remove_breakpoint (&loc);
 
          hw_breakpoint_error = 1;
          tmp_error_stream.printf ("Could not insert "
                                   "hardware watchpoint %d.\n",
-                                  bpt->number);
+                                  bpt.number);
          error_flag = -1;
        }
     }
@@ -3061,7 +3338,7 @@ insert_breakpoint_locations (void)
 You may have requested too many hardware breakpoints/watchpoints.\n");
        }
       target_terminal::ours_for_output ();
-      error_stream (tmp_error_stream);
+      error (("%s"), tmp_error_stream.c_str ());
     }
 }
 
@@ -3087,18 +3364,37 @@ remove_breakpoints (void)
 static void
 remove_threaded_breakpoints (struct thread_info *tp, int silent)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->thread == tp->global_num && user_breakpoint_p (b))
+      if (b.thread == tp->global_num && user_breakpoint_p (&b))
        {
-         b->disposition = disp_del_at_next_stop;
-
-         printf_filtered (_("\
+         gdb_printf (_("\
 Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
-                          b->number, print_thread_id (tp));
+                     b.number, print_thread_id (tp));
+         delete_breakpoint (&b);
+       }
+    }
+}
 
-         /* Hide it from the user.  */
-         b->number = 0;
+/* Called when inferior INF has been removed from GDB.  Remove associated
+   per-inferior breakpoints.  */
+
+static void
+remove_inferior_breakpoints (struct inferior *inf)
+{
+  for (breakpoint &b : all_breakpoints_safe ())
+    {
+      if (b.inferior == inf->num && user_breakpoint_p (&b))
+       {
+         /* Tell the user the breakpoint has been deleted.  But only for
+            breakpoints that would not normally have been deleted at the
+            next stop anyway.  */
+         if (b.disposition != disp_del
+             && b.disposition != disp_del_at_next_stop)
+           gdb_printf (_("\
+Inferior-specific breakpoint %d deleted - inferior %d has been removed.\n"),
+                       b.number, inf->num);
+         delete_breakpoint (&b);
        }
     }
 }
@@ -3110,6 +3406,8 @@ remove_breakpoints_inf (inferior *inf)
 {
   int val;
 
+  breakpoint_debug_printf ("inf->num = %d", inf->num);
+
   for (bp_location *bl : all_bp_locations ())
     {
       if (bl->pspace != inf->pspace)
@@ -3144,21 +3442,45 @@ set_breakpoint_number (int internal, struct breakpoint *b)
     }
 }
 
+/* Create a TYPE breakpoint on ADDRESS from an object file with GDBARCH.  */
+
 static struct breakpoint *
 create_internal_breakpoint (struct gdbarch *gdbarch,
-                           CORE_ADDR address, enum bptype type,
-                           const struct breakpoint_ops *ops)
+                           CORE_ADDR address, enum bptype type)
 {
-  symtab_and_line sal;
-  sal.pc = address;
-  sal.section = find_pc_overlay (sal.pc);
-  sal.pspace = current_program_space;
+  std::unique_ptr<internal_breakpoint> b
+    (new internal_breakpoint (gdbarch, type, address));
 
-  breakpoint *b = set_raw_breakpoint (gdbarch, sal, type, ops);
   b->number = internal_breakpoint_number--;
-  b->disposition = disp_donttouch;
 
-  return b;
+  return add_to_breakpoint_chain (std::move (b));
+}
+
+/* Create a TYPE breakpoint on minimal symbol MSYM from an object file with
+   GDBARCH.  */
+
+static struct breakpoint *
+create_internal_breakpoint (struct gdbarch *gdbarch,
+                           struct bound_minimal_symbol &msym, enum bptype type)
+{
+  CORE_ADDR address;
+
+  address = msym.value_address ();
+
+  address = gdbarch_convert_from_func_ptr_addr
+    (gdbarch, address, current_inferior ()->top_target ());
+
+  /* Note that we're not using gdbarch_addr_bits_remove here, because that's
+     related to addresses in $pc.  We're getting the address from the
+     minimal symbol table.  */
+
+  /* Is gdbarch_deprecated_function_start_offset needed here?  Or is that dealt
+     with elsewhere?  Needs testing on vax.  */
+
+  if (gdbarch_skip_entrypoint_p (gdbarch))
+    address = gdbarch_skip_entrypoint (gdbarch, address);
+
+  return create_internal_breakpoint (gdbarch, address, type);
 }
 
 static const char *const longjmp_names[] =
@@ -3171,10 +3493,10 @@ static const char *const longjmp_names[] =
 struct breakpoint_objfile_data
 {
   /* Minimal symbol for "_ovly_debug_event" (if any).  */
-  struct bound_minimal_symbol overlay_msym {};
+  struct bound_minimal_symbol overlay_msym;
 
   /* Minimal symbol(s) for "longjmp", "siglongjmp", etc. (if any).  */
-  struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES] {};
+  struct bound_minimal_symbol longjmp_msym[NUM_LONGJMP_NAMES];
 
   /* True if we have looked for longjmp probes.  */
   int longjmp_searched = 0;
@@ -3184,10 +3506,10 @@ struct breakpoint_objfile_data
   std::vector<probe *> longjmp_probes;
 
   /* Minimal symbol for "std::terminate()" (if any).  */
-  struct bound_minimal_symbol terminate_msym {};
+  struct bound_minimal_symbol terminate_msym;
 
   /* Minimal symbol for "_Unwind_DebugHook" (if any).  */
-  struct bound_minimal_symbol exception_msym {};
+  struct bound_minimal_symbol exception_msym;
 
   /* True if we have looked for exception probes.  */
   int exception_searched = 0;
@@ -3197,7 +3519,7 @@ struct breakpoint_objfile_data
   std::vector<probe *> exception_probes;
 };
 
-static const struct objfile_key<breakpoint_objfile_data>
+static const registry<objfile>::key<breakpoint_objfile_data>
   breakpoint_objfile_key;
 
 /* Minimal symbol not found sentinel.  */
@@ -3205,7 +3527,7 @@ static struct minimal_symbol msym_not_found;
 
 /* Returns TRUE if MSYM point to the "not found" sentinel.  */
 
-static int
+static bool
 msym_not_found_p (const struct minimal_symbol *msym)
 {
   return msym == &msym_not_found;
@@ -3235,7 +3557,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);
 
@@ -3256,13 +3577,10 @@ create_overlay_event_breakpoint (void)
          bp_objfile_data->overlay_msym = m;
        }
 
-      addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->overlay_msym);
+      addr = bp_objfile_data->overlay_msym.value_address ();
       b = create_internal_breakpoint (objfile->arch (), addr,
-                                     bp_overlay_event,
-                                     &internal_breakpoint_ops);
-      initialize_explicit_location (&explicit_loc);
-      explicit_loc.function_name = ASTRDUP (func_name);
-      b->location = new_explicit_location (&explicit_loc);
+                                     bp_overlay_event);
+      b->locspec = new_explicit_location_spec_function (func_name);
 
       if (overlay_debugging == ovly_auto)
        {
@@ -3318,9 +3636,8 @@ create_longjmp_master_breakpoint_probe (objfile *objfile)
 
       b = create_internal_breakpoint (gdbarch,
                                      p->get_relocated_address (objfile),
-                                     bp_longjmp_master,
-                                     &internal_breakpoint_ops);
-      b->location = new_probe_location ("-probe-stap libc:longjmp");
+                                     bp_longjmp_master);
+      b->locspec = new_probe_location_spec ("-probe-stap libc:longjmp");
       b->enable_state = bp_disabled;
     }
 
@@ -3346,7 +3663,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;
@@ -3366,12 +3682,9 @@ create_longjmp_master_breakpoint_names (objfile *objfile)
          bp_objfile_data->longjmp_msym[i] = m;
        }
 
-      addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
-      b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
-                                     &internal_breakpoint_ops);
-      initialize_explicit_location (&explicit_loc);
-      explicit_loc.function_name = ASTRDUP (func_name);
-      b->location = new_explicit_location (&explicit_loc);
+      addr = bp_objfile_data->longjmp_msym[i].value_address ();
+      b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master);
+      b->locspec = new_explicit_location_spec_function (func_name);
       b->enable_state = bp_disabled;
       installed_bp++;
     }
@@ -3419,15 +3732,12 @@ create_std_terminate_master_breakpoint (void)
 
   for (struct program_space *pspace : program_spaces)
     {
-      CORE_ADDR addr;
-
       set_current_program_space (pspace);
 
       for (objfile *objfile : current_program_space->objfiles ())
        {
          struct breakpoint *b;
          struct breakpoint_objfile_data *bp_objfile_data;
-         struct explicit_location explicit_loc;
 
          bp_objfile_data = get_breakpoint_objfile_data (objfile);
 
@@ -3439,8 +3749,8 @@ create_std_terminate_master_breakpoint (void)
              struct bound_minimal_symbol m;
 
              m = lookup_minimal_symbol (func_name, NULL, objfile);
-             if (m.minsym == NULL || (MSYMBOL_TYPE (m.minsym) != mst_text
-                                      && MSYMBOL_TYPE (m.minsym) != mst_file_text))
+             if (m.minsym == NULL || (m.minsym->type () != mst_text
+                                      && m.minsym->type () != mst_file_text))
                {
                  /* Prevent future lookups in this objfile.  */
                  bp_objfile_data->terminate_msym.minsym = &msym_not_found;
@@ -3449,13 +3759,10 @@ create_std_terminate_master_breakpoint (void)
              bp_objfile_data->terminate_msym = m;
            }
 
-         addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->terminate_msym);
-         b = create_internal_breakpoint (objfile->arch (), addr,
-                                         bp_std_terminate_master,
-                                         &internal_breakpoint_ops);
-         initialize_explicit_location (&explicit_loc);
-         explicit_loc.function_name = ASTRDUP (func_name);
-         b->location = new_explicit_location (&explicit_loc);
+         b = create_internal_breakpoint (objfile->arch (),
+                                         bp_objfile_data->terminate_msym,
+                                         bp_std_terminate_master);
+         b->locspec = new_explicit_location_spec_function (func_name);
          b->enable_state = bp_disabled;
        }
     }
@@ -3504,9 +3811,8 @@ create_exception_master_breakpoint_probe (objfile *objfile)
     {
       b = create_internal_breakpoint (gdbarch,
                                      p->get_relocated_address (objfile),
-                                     bp_exception_master,
-                                     &internal_breakpoint_ops);
-      b->location = new_probe_location ("-probe-stap libgcc:unwind");
+                                     bp_exception_master);
+      b->locspec = new_probe_location_spec ("-probe-stap libgcc:unwind");
       b->enable_state = bp_disabled;
     }
 
@@ -3523,8 +3829,6 @@ create_exception_master_breakpoint_hook (objfile *objfile)
   struct breakpoint *b;
   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);
 
@@ -3547,14 +3851,9 @@ create_exception_master_breakpoint_hook (objfile *objfile)
       bp_objfile_data->exception_msym = debug_hook;
     }
 
-  addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
-  addr = gdbarch_convert_from_func_ptr_addr
-    (gdbarch, addr, current_inferior ()->top_target ());
-  b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
-                                 &internal_breakpoint_ops);
-  initialize_explicit_location (&explicit_loc);
-  explicit_loc.function_name = ASTRDUP (func_name);
-  b->location = new_explicit_location (&explicit_loc);
+  b = create_internal_breakpoint (gdbarch, bp_objfile_data->exception_msym,
+                                 bp_exception_master);
+  b->locspec = new_explicit_location_spec_function (func_name);
   b->enable_state = bp_disabled;
 
   return true;
@@ -3585,10 +3884,10 @@ create_exception_master_breakpoint (void)
 
 /* Does B have a location spec?  */
 
-static int
-breakpoint_event_location_empty_p (const struct breakpoint *b)
+static bool
+breakpoint_location_spec_empty_p (const struct breakpoint *b)
 {
-  return b->location != NULL && event_location_empty_p (b->location.get ());
+  return (b->locspec != nullptr && b->locspec->empty_p ());
 }
 
 void
@@ -3606,60 +3905,60 @@ update_breakpoints_after_exec (void)
     if (bploc->pspace == current_program_space)
       gdb_assert (!bploc->inserted);
 
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->pspace != current_program_space)
+      if (b.pspace != current_program_space)
        continue;
 
       /* Solib breakpoints must be explicitly reset after an exec().  */
-      if (b->type == bp_shlib_event)
+      if (b.type == bp_shlib_event)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* JIT breakpoints must be explicitly reset after an exec().  */
-      if (b->type == bp_jit_event)
+      if (b.type == bp_jit_event)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Thread event breakpoints must be set anew after an exec(),
         as must overlay event and longjmp master breakpoints.  */
-      if (b->type == bp_thread_event || b->type == bp_overlay_event
-         || b->type == bp_longjmp_master || b->type == bp_std_terminate_master
-         || b->type == bp_exception_master)
+      if (b.type == bp_thread_event || b.type == bp_overlay_event
+         || b.type == bp_longjmp_master || b.type == bp_std_terminate_master
+         || b.type == bp_exception_master)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Step-resume breakpoints are meaningless after an exec().  */
-      if (b->type == bp_step_resume || b->type == bp_hp_step_resume)
+      if (b.type == bp_step_resume || b.type == bp_hp_step_resume)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Just like single-step breakpoints.  */
-      if (b->type == bp_single_step)
+      if (b.type == bp_single_step)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
       /* Longjmp and longjmp-resume breakpoints are also meaningless
         after an exec.  */
-      if (b->type == bp_longjmp || b->type == bp_longjmp_resume
-         || b->type == bp_longjmp_call_dummy
-         || b->type == bp_exception || b->type == bp_exception_resume)
+      if (b.type == bp_longjmp || b.type == bp_longjmp_resume
+         || b.type == bp_longjmp_call_dummy
+         || b.type == bp_exception || b.type == bp_exception_resume)
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
 
-      if (b->type == bp_catchpoint)
+      if (b.type == bp_catchpoint)
        {
          /* For now, none of the bp_catchpoint breakpoints need to
             do anything at this point.  In the future, if some of
@@ -3694,7 +3993,7 @@ update_breakpoints_after_exec (void)
         address is probably bogus in the new a.out, unlike e.g., the
         solib breakpoints.)  */
 
-      if (b->type == bp_finish)
+      if (b.type == bp_finish)
        {
          continue;
        }
@@ -3702,9 +4001,9 @@ 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 (breakpoint_event_location_empty_p (b))
+      if (breakpoint_location_spec_empty_p (&b))
        {
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          continue;
        }
     }
@@ -3729,11 +4028,12 @@ detach_breakpoints (ptid_t ptid)
 
       /* This function must physically remove breakpoints locations
         from the specified ptid, without modifying the breakpoint
-        package's state.  Locations of type bp_loc_other are only
-        maintained at GDB side.  So, there is no need to remove
-        these bp_loc_other locations.  Moreover, removing these
+        package's state.  Locations of type bp_loc_other and
+        bp_loc_software_watchpoint are only maintained at GDB side,
+        so there is no need to remove them.  Moreover, removing these
         would modify the breakpoint package's state.  */
-      if (bl->loc_type == bp_loc_other)
+      if (bl->loc_type == bp_loc_other
+         || bl->loc_type == bp_loc_software_watchpoint)
        continue;
 
       if (bl->inserted)
@@ -3752,6 +4052,10 @@ detach_breakpoints (ptid_t ptid)
 static int
 remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
 {
+  breakpoint_debug_printf ("%s due to %s",
+                          breakpoint_location_address_str (bl).c_str (),
+                          remove_bp_reason_str (reason));
+
   int val;
 
   /* BL is never in moribund_locations by our callers.  */
@@ -3798,7 +4102,7 @@ remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
              && !memory_validate_breakpoint (bl->gdbarch, &bl->target_info))
            val = 0;
          else
-           val = bl->owner->ops->remove_location (bl, reason);
+           val = bl->owner->remove_location (bl, reason);
        }
       else
        {
@@ -3833,7 +4137,7 @@ remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
                 wrong code with the saved shadow contents.  */
              if (bl->loc_type == bp_loc_hardware_breakpoint
                  || section_is_mapped (bl->section))
-               val = bl->owner->ops->remove_location (bl, reason);
+               val = bl->owner->remove_location (bl, reason);
              else
                val = 0;
            }
@@ -3867,11 +4171,8 @@ remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
     }
   else if (bl->loc_type == bp_loc_hardware_watchpoint)
     {
-      gdb_assert (bl->owner->ops != NULL
-                 && bl->owner->ops->remove_location != NULL);
-
       bl->inserted = (reason == DETACH_BREAKPOINT);
-      bl->owner->ops->remove_location (bl, reason);
+      bl->owner->remove_location (bl, reason);
 
       /* Failure to remove any of the hardware watchpoints comes here.  */
       if (reason == REMOVE_BREAKPOINT && bl->inserted)
@@ -3882,10 +4183,7 @@ remove_breakpoint_1 (struct bp_location *bl, enum remove_bp_reason reason)
           && breakpoint_enabled (bl->owner)
           && !bl->duplicate)
     {
-      gdb_assert (bl->owner->ops != NULL
-                 && bl->owner->ops->remove_location != NULL);
-
-      val = bl->owner->ops->remove_location (bl, reason);
+      val = bl->owner->remove_location (bl, reason);
       if (val)
        return val;
 
@@ -3946,12 +4244,12 @@ breakpoint_init_inferior (enum inf_context context)
 
   mark_breakpoints_out ();
 
-  for (breakpoint *b : all_breakpoints_safe ())
+  for (breakpoint &b : all_breakpoints_safe ())
     {
-      if (b->loc && b->loc->pspace != pspace)
+      if (b.has_locations () && b.first_loc ().pspace != pspace)
        continue;
 
-      switch (b->type)
+      switch (b.type)
        {
        case bp_call_dummy:
        case bp_longjmp_call_dummy:
@@ -3988,7 +4286,7 @@ breakpoint_init_inferior (enum inf_context context)
 
          /* Also remove single-step breakpoints.  */
 
-         delete_breakpoint (b);
+         delete_breakpoint (&b);
          break;
 
        case bp_watchpoint:
@@ -3996,11 +4294,11 @@ breakpoint_init_inferior (enum inf_context context)
        case bp_read_watchpoint:
        case bp_access_watchpoint:
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
            /* Likewise for watchpoints on local expressions.  */
-           if (w->exp_valid_block != NULL)
-             delete_breakpoint (b);
+           if (w.exp_valid_block != NULL)
+             delete_breakpoint (&b);
            else
              {
                /* Get rid of existing locations, which are no longer
@@ -4008,14 +4306,14 @@ breakpoint_init_inferior (enum inf_context context)
                   update_watchpoint, when the inferior is restarted.
                   The next update_global_location_list call will
                   garbage collect them.  */
-               b->loc = NULL;
+               b.clear_locations ();
 
                if (context == inf_starting)
                  {
                    /* Reset val field to force reread of starting value in
                       insert_breakpoints.  */
-                   w->val.reset (nullptr);
-                   w->val_valid = false;
+                   w.val.reset (nullptr);
+                   w.val_valid = false;
                  }
              }
          }
@@ -4049,7 +4347,7 @@ breakpoint_init_inferior (enum inf_context context)
 enum breakpoint_here
 breakpoint_here_p (const address_space *aspace, CORE_ADDR pc)
 {
-  int any_breakpoint_here = 0;
+  bool any_breakpoint_here = false;
 
   for (bp_location *bl : all_bp_locations ())
     {
@@ -4069,7 +4367,7 @@ breakpoint_here_p (const address_space *aspace, CORE_ADDR pc)
          else if (bl->permanent)
            return permanent_breakpoint_here;
          else
-           any_breakpoint_here = 1;
+           any_breakpoint_here = true;
        }
     }
 
@@ -4120,25 +4418,22 @@ moribund_breakpoint_here_p (const address_space *aspace, CORE_ADDR pc)
   return 0;
 }
 
-/* Returns non-zero iff BL is inserted at PC, in address space
-   ASPACE.  */
+/* Returns true iff BL is inserted at PC, in address space ASPACE.  */
 
-static int
-bp_location_inserted_here_p (struct bp_location *bl,
+static bool
+bp_location_inserted_here_p (const struct bp_location *bl,
                             const address_space *aspace, CORE_ADDR pc)
 {
   if (bl->inserted
       && breakpoint_address_match (bl->pspace->aspace, bl->address,
                                   aspace, pc))
     {
-      if (overlay_debugging
-         && section_is_overlay (bl->section)
-         && !section_is_mapped (bl->section))
-       return 0;               /* unmapped overlay -- can't be a match */
-      else
-       return 1;
+      /* An unmapped overlay can't be a match.  */
+      return !(overlay_debugging
+              && section_is_overlay (bl->section)
+              && !section_is_mapped (bl->section));
     }
-  return 0;
+  return false;
 }
 
 /* Returns non-zero iff there's a breakpoint inserted at PC.  */
@@ -4199,23 +4494,23 @@ int
 hardware_watchpoint_inserted_in_range (const address_space *aspace,
                                       CORE_ADDR addr, ULONGEST len)
 {
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
-      if (bpt->type != bp_hardware_watchpoint
-         && bpt->type != bp_access_watchpoint)
+      if (bpt.type != bp_hardware_watchpoint
+         && bpt.type != bp_access_watchpoint)
        continue;
 
-      if (!breakpoint_enabled (bpt))
+      if (!breakpoint_enabled (&bpt))
        continue;
 
-      for (bp_location *loc : bpt->locations ())
-       if (loc->pspace->aspace == aspace && loc->inserted)
+      for (bp_location &loc : bpt.locations ())
+       if (loc.pspace->aspace == aspace && loc.inserted)
          {
            CORE_ADDR l, h;
 
            /* Check for intersection.  */
-           l = std::max<CORE_ADDR> (loc->address, addr);
-           h = std::min<CORE_ADDR> (loc->address + loc->length, addr + len);
+           l = std::max<CORE_ADDR> (loc.address, addr);
+           h = std::min<CORE_ADDR> (loc.address + loc.length, addr + len);
            if (l < h)
              return 1;
          }
@@ -4262,7 +4557,7 @@ bpstat::bpstat (const bpstat &other)
     print_it (other.print_it)
 {
   if (other.old_val != NULL)
-    old_val = release_value (value_copy (other.old_val.get ()));
+    old_val = release_value (other.old_val->copy ());
 }
 
 /* Return a copy of a bpstat.  Like "bs1 = bs2" but all storage that
@@ -4325,8 +4620,7 @@ bpstat_explains_signal (bpstat *bsp, enum gdb_signal sig)
        }
       else
        {
-         if (bsp->breakpoint_at->ops->explains_signal (bsp->breakpoint_at,
-                                                       sig))
+         if (bsp->breakpoint_at->explains_signal (sig))
            return true;
        }
     }
@@ -4334,15 +4628,7 @@ bpstat_explains_signal (bpstat *bsp, enum gdb_signal sig)
   return false;
 }
 
-/* Put in *NUM the breakpoint number of the first breakpoint we are
-   stopped at.  *BSP upon return is a bpstat which points to the
-   remaining breakpoints stopped at (but which is not guaranteed to be
-   good for anything but further calls to bpstat_num).
-
-   Return 0 if passed a bpstat which does not indicate any breakpoints.
-   Return -1 if stopped at a breakpoint that has been deleted since
-   we set it.
-   Return 1 otherwise.  */
+/* See breakpoint.h.  */
 
 int
 bpstat_num (bpstat **bsp, int *num)
@@ -4364,6 +4650,52 @@ bpstat_num (bpstat **bsp, int *num)
   return 1;
 }
 
+/* See breakpoint.h  */
+
+int
+bpstat_locno (const bpstat *bs)
+{
+  const struct breakpoint *b = bs->breakpoint_at;
+  const struct bp_location *bl = bs->bp_location_at.get ();
+
+  if (b != nullptr && b->has_multiple_locations ())
+    {
+      int locno = 1;
+
+      for (bp_location &loc : b->locations ())
+       {
+         if (bl == &loc)
+           return locno;
+
+         ++locno;
+       }
+
+      warning (_("location number not found for breakpoint %d address %s."),
+              b->number, paddress (bl->gdbarch, bl->address));
+    }
+
+  return 0;
+}
+
+/* See breakpoint.h.  */
+
+void
+print_num_locno (const bpstat *bs, struct ui_out *uiout)
+{
+  struct breakpoint *b = bs->breakpoint_at;
+
+  if (b == nullptr)
+    uiout->text (_("deleted breakpoint"));
+  else
+    {
+      uiout->field_signed ("bkptno", b->number);
+
+      int locno = bpstat_locno (bs);
+      if (locno != 0)
+       uiout->message (".%pF", signed_field ("locno", locno));
+    }
+}
+
 /* See breakpoint.h.  */
 
 void
@@ -4402,15 +4734,28 @@ breakpoint_about_to_proceed (void)
   breakpoint_proceeded = 1;
 }
 
-/* Return non-zero iff CMD as the first line of a command sequence is `silent'
+/* Return true iff CMD as the first line of a command sequence is `silent'
    or its equivalent.  */
 
-static int
+static bool
 command_line_is_silent (struct command_line *cmd)
 {
   return cmd && (strcmp ("silent", cmd->line) == 0);
 }
 
+/* Sets the $_hit_bpnum and $_hit_locno to bpnum and locno.
+   A locno 0 is changed to 1 to e.g. let the user do
+     (gdb) disable $_hit_bpnum.$_hit_locno
+   for a single location breakpoint.  */
+
+static void
+set_hit_convenience_vars (int bpnum, int locno)
+{
+  set_internalvar_integer (lookup_internalvar ("_hit_bpnum"), bpnum);
+  set_internalvar_integer (lookup_internalvar ("_hit_locno"),
+                          (locno > 0 ? locno : 1));
+}
+
 /* Execute all the commands associated with all the breakpoints at
    this location.  Any of these commands could cause the process to
    proceed beyond this point, etc.  We look out for such changes by
@@ -4420,16 +4765,16 @@ command_line_is_silent (struct command_line *cmd)
    case, it is the caller's responsibility to recall it again with the
    bpstat of the current thread.  */
 
-static int
+static bool
 bpstat_do_actions_1 (bpstat **bsp)
 {
   bpstat *bs;
-  int again = 0;
+  bool again = false;
 
   /* Avoid endless recursion if a `source' command is contained
      in bs->commands.  */
   if (executing_breakpoint_commands)
-    return 0;
+    return false;
 
   scoped_restore save_executing
     = make_scoped_restore (&executing_breakpoint_commands, 1);
@@ -4439,16 +4784,40 @@ bpstat_do_actions_1 (bpstat **bsp)
   /* This pointer will iterate over the list of bpstat's.  */
   bs = *bsp;
 
+  /* The $_hit_* convenience variables are set before running the
+     commands of BS.  In case we have several bs, after the loop,
+     we set again the variables to the first printed bpnum and locno.
+     For multiple breakpoints, this ensures the variables are set to the
+     breakpoint printed for the user. */
+  int printed_hit_bpnum = -1;
+  int printed_hit_locno = -1;
+
   breakpoint_proceeded = 0;
   for (; bs != NULL; bs = bs->next)
     {
       struct command_line *cmd = NULL;
 
+      /* Set the _hit_* convenience variables before running BS's commands.  */
+      {
+       const struct breakpoint *b = bs->breakpoint_at;
+       if (b != nullptr)
+         {
+           int locno = bpstat_locno (bs);
+
+           set_hit_convenience_vars (b->number, locno);
+           if (printed_hit_locno == -1 && bs->print)
+             {
+               printed_hit_bpnum = b->number;
+               printed_hit_locno = locno;
+             }
+         }
+      }
+
       /* Take ownership of the BSP's command tree, if it has one.
 
         The command tree could legitimately contain commands like
         'step' and 'next', which call clear_proceed_status, which
-        frees stop_bpstat's command tree.  To make sure this doesn't
+        frees the bpstat BS and its command tree.  To make sure this doesn't
         free the tree we're executing out from under us, we need to
         take ownership of the tree ourselves.  Since a given bpstat's
         commands are only executed once, we don't need to copy it; we
@@ -4467,6 +4836,8 @@ bpstat_do_actions_1 (bpstat **bsp)
       while (cmd != NULL)
        {
          execute_control_command (cmd);
+         /* After execute_control_command, if breakpoint_proceeded is true,
+            BS has been freed and cannot be accessed anymore.  */
 
          if (breakpoint_proceeded)
            break;
@@ -4495,10 +4866,16 @@ bpstat_do_actions_1 (bpstat **bsp)
               command, and can easily blow up GDB stack.  Instead, we
               return true, which will trigger the caller to recall us
               with the new stop_bpstat.  */
-           again = 1;
+           again = true;
          break;
        }
     }
+
+  /* Now that we have executed the commands of all bs, set the _hit_*
+     convenience variables to the printed values.  */
+  if (printed_hit_locno != -1)
+    set_hit_convenience_vars (printed_hit_bpnum, printed_hit_locno);
+
   return again;
 }
 
@@ -4614,21 +4991,20 @@ print_bp_stop_message (bpstat *bs)
          return PRINT_UNKNOWN;
 
        /* Normal case.  Call the breakpoint's print_it method.  */
-       return b->ops->print_it (bs);
+       return b->print_it (bs);
       }
       break;
 
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("print_bp_stop_message: unrecognized enum value"));
+      internal_error (_("print_bp_stop_message: unrecognized enum value"));
       break;
     }
 }
 
-/* A helper function that prints a shared library stopped event.  */
+/* See breakpoint.h.  */
 
-static void
-print_solib_event (int is_catchpoint)
+void
+print_solib_event (bool is_catchpoint)
 {
   bool any_deleted = !current_program_space->deleted_solibs.empty ();
   bool any_added = !current_program_space->added_solibs.empty ();
@@ -4699,7 +5075,7 @@ print_solib_event (int is_catchpoint)
    further info to be printed.  */
 
 enum print_stop_action
-bpstat_print (bpstat *bs, int kind)
+bpstat_print (bpstat *bs, target_waitkind kind)
 {
   enum print_stop_action val;
 
@@ -4711,7 +5087,7 @@ bpstat_print (bpstat *bs, int kind)
     {
       val = print_bp_stop_message (bs);
       if (val == PRINT_SRC_ONLY 
-         || val == PRINT_SRC_AND_LOC 
+         || val == PRINT_SRC_AND_LOC
          || val == PRINT_NOTHING)
        return val;
     }
@@ -4721,7 +5097,7 @@ bpstat_print (bpstat *bs, int kind)
      OS-level shared library event, do the same thing.  */
   if (kind == TARGET_WAITKIND_LOADED)
     {
-      print_solib_event (0);
+      print_solib_event (false);
       return PRINT_NOTHING;
     }
 
@@ -4735,11 +5111,8 @@ bpstat_print (bpstat *bs, int kind)
 static bool
 breakpoint_cond_eval (expression *exp)
 {
-  struct value *mark = value_mark ();
-  bool res = value_true (evaluate_expression (exp));
-
-  value_free_to_mark (mark);
-  return res;
+  scoped_value_mark mark;
+  return value_true (exp->evaluate ());
 }
 
 /* Allocate a new bpstat.  Link it to the FIFO list by BS_LINK_POINTER.  */
@@ -4780,12 +5153,12 @@ watchpoints_triggered (const target_waitstatus &ws)
     {
       /* We were not stopped by a watchpoint.  Mark all watchpoints
         as not triggered.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (is_hardware_watchpoint (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (is_hardware_watchpoint (&b))
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-           w->watchpoint_triggered = watch_triggered_no;
+           w.watchpoint_triggered = watch_triggered_no;
          }
 
       return 0;
@@ -4795,12 +5168,12 @@ watchpoints_triggered (const target_waitstatus &ws)
     {
       /* We were stopped by a watchpoint, but we don't know where.
         Mark all watchpoints as unknown.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (is_hardware_watchpoint (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (is_hardware_watchpoint (&b))
          {
-           struct watchpoint *w = (struct watchpoint *) b;
+           watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-           w->watchpoint_triggered = watch_triggered_unknown;
+           w.watchpoint_triggered = watch_triggered_unknown;
          }
 
       return 1;
@@ -4810,31 +5183,31 @@ watchpoints_triggered (const target_waitstatus &ws)
      affected by this data address as triggered, and all others as not
      triggered.  */
 
-  for (breakpoint *b : all_breakpoints ())
-    if (is_hardware_watchpoint (b))
+  for (breakpoint &b : all_breakpoints ())
+    if (is_hardware_watchpoint (&b))
       {
-       struct watchpoint *w = (struct watchpoint *) b;
+       watchpoint &w = gdb::checked_static_cast<watchpoint &> (b);
 
-       w->watchpoint_triggered = watch_triggered_no;
-       for (bp_location *loc : b->locations ())
+       w.watchpoint_triggered = watch_triggered_no;
+       for (bp_location &loc : b.locations ())
          {
-           if (is_masked_watchpoint (b))
+           if (is_masked_watchpoint (&b))
              {
-               CORE_ADDR newaddr = addr & w->hw_wp_mask;
-               CORE_ADDR start = loc->address & w->hw_wp_mask;
+               CORE_ADDR newaddr = addr & w.hw_wp_mask;
+               CORE_ADDR start = loc.address & w.hw_wp_mask;
 
                if (newaddr == start)
                  {
-                   w->watchpoint_triggered = watch_triggered_yes;
+                   w.watchpoint_triggered = watch_triggered_yes;
                    break;
                  }
              }
            /* Exact match not required.  Within range is sufficient.  */
            else if (target_watchpoint_addr_within_range
-                      (current_inferior ()->top_target (), addr, loc->address,
-                       loc->length))
+                      (current_inferior ()->top_target (), addr, loc.address,
+                       loc.length))
              {
-               w->watchpoint_triggered = watch_triggered_yes;
+               w.watchpoint_triggered = watch_triggered_yes;
                break;
              }
          }
@@ -4869,8 +5242,8 @@ static wp_check_result
 watchpoint_check (bpstat *bs)
 {
   struct watchpoint *b;
-  struct frame_info *fr;
-  int within_current_scope;
+  frame_info_ptr fr;
+  bool within_current_scope;
 
   /* BS is built from an existing struct breakpoint.  */
   gdb_assert (bs->breakpoint_at != NULL);
@@ -4883,10 +5256,10 @@ watchpoint_check (bpstat *bs)
     return WP_IGNORE;
 
   if (b->exp_valid_block == NULL)
-    within_current_scope = 1;
+    within_current_scope = true;
   else
     {
-      struct frame_info *frame = get_current_frame ();
+      frame_info_ptr frame = get_current_frame ();
       struct gdbarch *frame_arch = get_frame_arch (frame);
       CORE_ADDR frame_pc = get_frame_pc (frame);
 
@@ -4913,9 +5286,8 @@ watchpoint_check (bpstat *bs)
 
          function = get_frame_function (fr);
          if (function == NULL
-             || !contained_in (b->exp_valid_block,
-                               SYMBOL_BLOCK_VALUE (function)))
-           within_current_scope = 0;
+             || !function->value_block ()->contains (b->exp_valid_block))
+           within_current_scope = false;
        }
 
       if (within_current_scope)
@@ -4981,8 +5353,8 @@ watchpoint_check (bpstat *bs)
         watch after that (since the garbage may or may not equal
         the first value assigned).  */
       /* We print all the stop information in
-        breakpoint_ops->print_it, but in this case, by the time we
-        call breakpoint_ops->print_it this bp will be deleted
+        breakpointprint_it, but in this case, by the time we
+        call breakpoint->print_it this bp will be deleted
         already.  So we have no choice but print the information
         here.  */
 
@@ -5011,7 +5383,7 @@ watchpoint_check (bpstat *bs)
    breakpoint location BL.  This function does not check if we should
    stop, only if BL explains the stop.  */
 
-static int
+static bool
 bpstat_check_location (const struct bp_location *bl,
                       const address_space *aspace, CORE_ADDR bp_addr,
                       const target_waitstatus &ws)
@@ -5021,11 +5393,11 @@ bpstat_check_location (const struct bp_location *bl,
   /* BL is from an existing breakpoint.  */
   gdb_assert (b != NULL);
 
-  return b->ops->breakpoint_hit (bl, aspace, bp_addr, ws);
+  return b->breakpoint_hit (bl, aspace, bp_addr, ws);
 }
 
 /* Determine if the watched values have actually changed, and we
-   should stop.  If not, set BS->stop to 0.  */
+   should stop.  If not, set BS->stop to false.  */
 
 static void
 bpstat_check_watchpoint (bpstat *bs)
@@ -5040,24 +5412,24 @@ bpstat_check_watchpoint (bpstat *bs)
   gdb_assert (b != NULL);
 
     {
-      int must_check_value = 0;
-      
+      bool must_check_value = false;
+
       if (b->type == bp_watchpoint)
        /* For a software watchpoint, we must always check the
           watched value.  */
-       must_check_value = 1;
+       must_check_value = true;
       else if (b->watchpoint_triggered == watch_triggered_yes)
        /* We have a hardware watchpoint (read, write, or access)
           and the target earlier reported an address watched by
           this watchpoint.  */
-       must_check_value = 1;
+       must_check_value = true;
       else if (b->watchpoint_triggered == watch_triggered_unknown
               && b->type == bp_hardware_watchpoint)
        /* We were stopped by a hardware watchpoint, but the target could
           not report the data address.  We must check the watchpoint's
           value.  Access and read watchpoints are out of luck; without
           a data address, we can't figure it out.  */
-       must_check_value = 1;
+       must_check_value = true;
 
       if (must_check_value)
        {
@@ -5067,7 +5439,7 @@ bpstat_check_watchpoint (bpstat *bs)
            {
              e = watchpoint_check (bs);
            }
-         catch (const gdb_exception &ex)
+         catch (const gdb_exception_error &ex)
            {
              exception_fprintf (gdb_stderr, ex,
                                 "Error evaluating expression "
@@ -5076,8 +5448,8 @@ bpstat_check_watchpoint (bpstat *bs)
 
              SWITCH_THRU_ALL_UIS ()
                {
-                 printf_filtered (_("Watchpoint %d deleted.\n"),
-                                  b->number);
+                 gdb_printf (_("Watchpoint %d deleted.\n"),
+                             b->number);
                }
              watchpoint_del_at_next_stop (b);
              e = WP_DELETED;
@@ -5092,7 +5464,7 @@ bpstat_check_watchpoint (bpstat *bs)
              break;
            case WP_IGNORE:
              bs->print_it = print_it_noop;
-             bs->stop = 0;
+             bs->stop = false;
              break;
            case WP_VALUE_CHANGED:
              if (b->type == bp_read_watchpoint)
@@ -5135,14 +5507,14 @@ bpstat_check_watchpoint (bpstat *bs)
 
                  if (bl->watchpoint_type == hw_read)
                    {
-                     for (breakpoint *other_b : all_breakpoints ())
-                       if (other_b->type == bp_hardware_watchpoint
-                           || other_b->type == bp_access_watchpoint)
+                     for (breakpoint &other_b : all_breakpoints ())
+                       if (other_b.type == bp_hardware_watchpoint
+                           || other_b.type == bp_access_watchpoint)
                          {
-                           struct watchpoint *other_w =
-                             (struct watchpoint *) other_b;
+                           watchpoint &other_w =
+                             gdb::checked_static_cast<watchpoint &> (other_b);
 
-                           if (other_w->watchpoint_triggered
+                           if (other_w.watchpoint_triggered
                                == watch_triggered_yes)
                              {
                                other_write_watchpoint = 1;
@@ -5159,7 +5531,7 @@ bpstat_check_watchpoint (bpstat *bs)
                         updated it, so this trap must be for a write.
                         Ignore it.  */
                      bs->print_it = print_it_noop;
-                     bs->stop = 0;
+                     bs->stop = false;
                    }
                }
              break;
@@ -5170,7 +5542,7 @@ bpstat_check_watchpoint (bpstat *bs)
                  /* Don't stop: write watchpoints shouldn't fire if
                     the value hasn't changed.  */
                  bs->print_it = print_it_noop;
-                 bs->stop = 0;
+                 bs->stop = false;
                }
              /* Stop.  */
              break;
@@ -5179,14 +5551,14 @@ bpstat_check_watchpoint (bpstat *bs)
              break;
            }
        }
-      else     /* must_check_value == 0 */
+      else     /* !must_check_value */
        {
          /* This is a case where some watchpoint(s) triggered, but
             not at the address of this watchpoint, or else no
             watchpoint triggered after all.  So don't print
             anything for this watchpoint.  */
          bs->print_it = print_it_noop;
-         bs->stop = 0;
+         bs->stop = false;
        }
     }
 }
@@ -5199,6 +5571,8 @@ bpstat_check_watchpoint (bpstat *bs)
 static void
 bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
 {
+  INFRUN_SCOPED_DEBUG_ENTER_EXIT;
+
   const struct bp_location *bl;
   struct breakpoint *b;
   /* Assume stop.  */
@@ -5213,14 +5587,21 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
   b = bs->breakpoint_at;
   gdb_assert (b != NULL);
 
+  infrun_debug_printf ("thread = %s, breakpoint %d.%d",
+                      thread->ptid.to_string ().c_str (),
+                      b->number, find_loc_num_by_location (bl));
+
   /* Even if the target evaluated the condition on its end and notified GDB, we
      need to do so again since GDB does not know if we stopped due to a
      breakpoint or a single step breakpoint.  */
 
   if (frame_id_p (b->frame_id)
-      && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ())))
+      && b->frame_id != get_stack_frame_id (get_current_frame ()))
     {
-      bs->stop = 0;
+      infrun_debug_printf ("incorrect frame %s not %s, not stopping",
+                          get_stack_frame_id (get_current_frame ()).to_string ().c_str (),
+                          b->frame_id.to_string ().c_str ());
+      bs->stop = false;
       return;
     }
 
@@ -5228,9 +5609,11 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
      evaluating the condition if this isn't the specified
      thread/task.  */
   if ((b->thread != -1 && b->thread != thread->global_num)
-      || (b->task != 0 && b->task != ada_get_task_number (thread)))
+      || (b->inferior != -1 && b->inferior != thread->inf->num)
+      || (b->task != -1 && b->task != ada_get_task_number (thread)))
     {
-      bs->stop = 0;
+      infrun_debug_printf ("incorrect thread or task, not stopping");
+      bs->stop = false;
       return;
     }
 
@@ -5247,17 +5630,16 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
   else
     cond = bl->cond.get ();
 
-  if (cond && b->disposition != disp_del_at_next_stop)
+  if (cond != nullptr && b->disposition != disp_del_at_next_stop)
     {
-      int within_current_scope = 1;
+      bool within_current_scope = true;
       struct watchpoint * w;
 
-      /* We use value_mark and value_free_to_mark because it could
-        be a long time before we return to the command level and
-        call free_all_values.  We can't call free_all_values
-        because we might be in the middle of evaluating a
-        function call.  */
-      struct value *mark = value_mark ();
+      /* We use scoped_value_mark because it could be a long time
+        before we return to the command level and call
+        free_all_values.  We can't call free_all_values because we
+        might be in the middle of evaluating a function call.  */
+      scoped_value_mark mark;
 
       if (is_watchpoint (b))
        w = (struct watchpoint *) b;
@@ -5274,7 +5656,7 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
        select_frame (get_current_frame ());
       else
        {
-         struct frame_info *frame;
+         frame_info_ptr frame;
 
          /* For local watchpoint expressions, which particular
             instance of a local is being watched matters, so we
@@ -5294,7 +5676,7 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
          if (frame != NULL)
            select_frame (frame);
          else
-           within_current_scope = 0;
+           within_current_scope = false;
        }
       if (within_current_scope)
        {
@@ -5302,10 +5684,19 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
            {
              condition_result = breakpoint_cond_eval (cond);
            }
-         catch (const gdb_exception &ex)
+         catch (const gdb_exception_error &ex)
            {
-             exception_fprintf (gdb_stderr, ex,
-                                "Error in testing breakpoint condition:\n");
+             int locno = bpstat_locno (bs);
+             if (locno != 0)
+               exception_fprintf
+                 (gdb_stderr, ex,
+                  "Error in testing condition for breakpoint %d.%d:\n",
+                  b->number, locno);
+             else
+               exception_fprintf
+                 (gdb_stderr, ex,
+                  "Error in testing condition for breakpoint %d:\n",
+                  b->number);
            }
        }
       else
@@ -5316,28 +5707,37 @@ bpstat_check_breakpoint_conditions (bpstat *bs, thread_info *thread)
             watchpoint, unconditionally report it.  */
        }
       /* FIXME-someday, should give breakpoint #.  */
-      value_free_to_mark (mark);
     }
 
-  if (cond && !condition_result)
+  if (cond != nullptr && !condition_result)
     {
-      bs->stop = 0;
+      infrun_debug_printf ("condition_result = false, not stopping");
+      bs->stop = false;
+      return;
     }
   else if (b->ignore_count > 0)
     {
+      infrun_debug_printf ("ignore count %d, not stopping",
+                          b->ignore_count);
       b->ignore_count--;
-      bs->stop = 0;
+      bs->stop = false;
       /* Increase the hit count even though we don't stop.  */
       ++(b->hit_count);
-      gdb::observers::breakpoint_modified.notify (b);
-    }  
+      notify_breakpoint_modified (b);
+      return;
+    }
+
+  if (bs->stop)
+    infrun_debug_printf ("stopping at this breakpoint");
+  else
+    infrun_debug_printf ("not stopping at this breakpoint");
 }
 
 /* Returns true if we need to track moribund locations of LOC's type
    on the current target.  */
 
-static int
-need_moribund_for_location_type (struct bp_location *loc)
+static bool
+need_moribund_for_location_type (const struct bp_location *loc)
 {
   return ((loc->loc_type == bp_loc_software_breakpoint
           && !target_supports_stopped_by_sw_breakpoint ())
@@ -5353,46 +5753,46 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
 {
   bpstat *bs_head = nullptr, **bs_link = &bs_head;
 
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (!breakpoint_enabled (b))
+      if (!breakpoint_enabled (&b))
        continue;
 
-      for (bp_location *bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
          /* For hardware watchpoints, we look only at the first
             location.  The watchpoint_check function will work on the
             entire expression, not the individual locations.  For
             read watchpoints, the watchpoints_triggered function has
             checked all locations already.  */
-         if (b->type == bp_hardware_watchpoint && bl != b->loc)
+         if (b.type == bp_hardware_watchpoint && &bl != &b.first_loc ())
            break;
 
-         if (!bl->enabled || bl->disabled_by_cond || bl->shlib_disabled)
+         if (!bl.enabled || bl.disabled_by_cond || bl.shlib_disabled)
            continue;
 
-         if (!bpstat_check_location (bl, aspace, bp_addr, ws))
+         if (!bpstat_check_location (&bl, aspace, bp_addr, ws))
            continue;
 
          /* Come here if it's a watchpoint, or if the break address
             matches.  */
 
-         bpstat *bs = new bpstat (bl, &bs_link);       /* Alloc a bpstat to
+         bpstat *bs = new bpstat (&bl, &bs_link);      /* Alloc a bpstat to
                                                           explain stop.  */
 
          /* Assume we stop.  Should we find a watchpoint that is not
             actually triggered, or if the condition of the breakpoint
             evaluates as false, we'll reset 'stop' to 0.  */
-         bs->stop = 1;
-         bs->print = 1;
+         bs->stop = true;
+         bs->print = true;
 
          /* If this is a scope breakpoint, mark the associated
             watchpoint as triggered so that we will handle the
             out-of-scope event.  We'll get to the watchpoint next
             iteration.  */
-         if (b->type == bp_watchpoint_scope && b->related_breakpoint != b)
+         if (b.type == bp_watchpoint_scope && b.related_breakpoint != &b)
            {
-             struct watchpoint *w = (struct watchpoint *) b->related_breakpoint;
+             struct watchpoint *w = (struct watchpoint *) b.related_breakpoint;
 
              w->watchpoint_triggered = watch_triggered_yes;
            }
@@ -5410,8 +5810,8 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
            {
              bpstat *bs = new bpstat (loc, &bs_link);
              /* For hits of moribund locations, we should just proceed.  */
-             bs->stop = 0;
-             bs->print = 0;
+             bs->stop = false;
+             bs->print = false;
              bs->print_it = print_it_noop;
            }
        }
@@ -5469,7 +5869,7 @@ bpstat_stop_status (const address_space *aspace,
        continue;
 
       b = bs->breakpoint_at;
-      b->ops->check_status (bs);
+      b->check_status (bs);
       if (bs->stop)
        {
          bpstat_check_breakpoint_conditions (bs, thread);
@@ -5486,15 +5886,15 @@ bpstat_stop_status (const address_space *aspace,
                    b->enable_state = bp_disabled;
                  removed_any = 1;
                }
-             gdb::observers::breakpoint_modified.notify (b);
+             notify_breakpoint_modified (b);
              if (b->silent)
-               bs->print = 0;
+               bs->print = false;
              bs->commands = b->commands;
              if (command_line_is_silent (bs->commands
                                          ? bs->commands.get () : NULL))
-               bs->print = 0;
+               bs->print = false;
 
-             b->ops->after_condition_true (bs);
+             b->after_condition_true (bs);
            }
 
        }
@@ -5518,7 +5918,7 @@ bpstat_stop_status (const address_space *aspace,
        {
          struct watchpoint *w = (struct watchpoint *) bs->breakpoint_at;
 
-         update_watchpoint (w, 0 /* don't reparse.  */);
+         update_watchpoint (w, false /* don't reparse.  */);
          need_remove_insert = 1;
        }
 
@@ -5530,6 +5930,21 @@ bpstat_stop_status (const address_space *aspace,
   return bs_head;
 }
 
+/* See breakpoint.h.  */
+
+bpstat *
+bpstat_stop_status_nowatch (const address_space *aspace, CORE_ADDR bp_addr,
+                           thread_info *thread, const target_waitstatus &ws)
+{
+  gdb_assert (!target_stopped_by_watchpoint ());
+
+  /* Clear all watchpoints' 'watchpoint_triggered' value from a
+     previous stop to avoid confusing bpstat_stop_status.  */
+  watchpoints_triggered (ws);
+
+  return bpstat_stop_status (aspace, bp_addr, thread, ws);
+}
+
 static void
 handle_jit_event (CORE_ADDR address)
 {
@@ -5549,7 +5964,10 @@ handle_jit_event (CORE_ADDR address)
      function needs to be updated too.  */
   bound_minimal_symbol jit_bp_sym = lookup_minimal_symbol_by_pc (address);
   gdb_assert (jit_bp_sym.objfile != nullptr);
-  jit_event_handler (gdbarch, jit_bp_sym.objfile);
+  objfile *objfile = jit_bp_sym.objfile;
+  if (objfile->separate_debug_objfile_backlink)
+    objfile = objfile->separate_debug_objfile_backlink;
+  jit_event_handler (gdbarch, objfile);
 
   target_terminal::inferior ();
 }
@@ -5680,7 +6098,8 @@ bpstat_what (bpstat *bs_head)
            {
              /* Some catchpoints are implemented with breakpoints.
                 For those, we need to step over the breakpoint.  */
-             if (bs->bp_location_at->loc_type != bp_loc_other)
+             if (bs->bp_location_at->loc_type == bp_loc_software_breakpoint
+                 || bs->bp_location_at->loc_type == bp_loc_hardware_breakpoint)
                this_action = BPSTAT_WHAT_SINGLE;
            }
          break;
@@ -5702,11 +6121,11 @@ bpstat_what (bpstat *bs_head)
        case bp_tracepoint:
        case bp_fast_tracepoint:
        case bp_static_tracepoint:
+       case bp_static_marker_tracepoint:
          /* Tracepoint hits should not be reported back to GDB, and
             if one got through somehow, it should have been filtered
             out already.  */
-         internal_error (__FILE__, __LINE__,
-                         _("bpstat_what: tracepoint encountered"));
+         internal_error (_("bpstat_what: tracepoint encountered"));
          break;
        case bp_gnu_ifunc_resolver:
          /* Step over it (and insert bp_gnu_ifunc_resolver_return).  */
@@ -5726,8 +6145,7 @@ bpstat_what (bpstat *bs_head)
          break;
 
        default:
-         internal_error (__FILE__, __LINE__,
-                         _("bpstat_what: unhandled bptype %d"), (int) bptype);
+         internal_error (_("bpstat_what: unhandled bptype %d"), (int) bptype);
        }
 
       retval.main_action = std::max (retval.main_action, this_action);
@@ -5753,10 +6171,10 @@ bpstat_run_callbacks (bpstat *bs_head)
          handle_jit_event (bs->bp_location_at->address);
          break;
        case bp_gnu_ifunc_resolver:
-         gnu_ifunc_resolver_stop (b);
+         gnu_ifunc_resolver_stop ((code_breakpoint *) b);
          break;
        case bp_gnu_ifunc_resolver_return:
-         gnu_ifunc_resolver_return_stop (b);
+         gnu_ifunc_resolver_return_stop ((code_breakpoint *) b);
          break;
        }
     }
@@ -5767,8 +6185,10 @@ bpstat_run_callbacks (bpstat *bs_head)
 bool
 bpstat_should_step ()
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
+  for (breakpoint &b : all_breakpoints ())
+    if (breakpoint_enabled (&b)
+       && b.type == bp_watchpoint
+       && b.has_locations ())
       return true;
 
   return false;
@@ -5788,14 +6208,13 @@ bpstat_causes_stop (bpstat *bs)
 
 \f
 
-/* Compute a string of spaces suitable to indent the next line
+/* Compute a number of spaces suitable to indent the next line
    so it starts at the position corresponding to the table column
    named COL_NAME in the currently active table of UIOUT.  */
 
-static char *
+static int
 wrap_indent_at_field (struct ui_out *uiout, const char *col_name)
 {
-  static char wrap_indent[80];
   int i, total_width, width, align;
   const char *text;
 
@@ -5803,18 +6222,12 @@ wrap_indent_at_field (struct ui_out *uiout, const char *col_name)
   for (i = 1; uiout->query_table_field (i, &width, &align, &text); i++)
     {
       if (strcmp (text, col_name) == 0)
-       {
-         gdb_assert (total_width < sizeof wrap_indent);
-         memset (wrap_indent, ' ', total_width);
-         wrap_indent[total_width] = 0;
-
-         return wrap_indent;
-       }
+       return total_width;
 
       total_width += width + 1;
     }
 
-  return NULL;
+  return 0;
 }
 
 /* Determine if the locations of this breakpoint will have their conditions
@@ -5826,7 +6239,7 @@ wrap_indent_at_field (struct ui_out *uiout, const char *col_name)
 */
 
 static const char *
-bp_condition_evaluator (struct breakpoint *b)
+bp_condition_evaluator (const breakpoint *b)
 {
   char host_evals = 0;
   char target_evals = 0;
@@ -5841,9 +6254,9 @@ bp_condition_evaluator (struct breakpoint *b)
       || !target_supports_evaluation_of_breakpoint_conditions ())
     return condition_evaluation_host;
 
-  for (bp_location *bl : b->locations ())
+  for (bp_location &bl : b->locations ())
     {
-      if (bl->cond_bytecode)
+      if (bl.cond_bytecode)
        target_evals++;
       else
        host_evals++;
@@ -5861,7 +6274,7 @@ bp_condition_evaluator (struct breakpoint *b)
    similar to bp_condition_evaluator, but for locations.  */
 
 static const char *
-bp_location_condition_evaluator (struct bp_location *bl)
+bp_location_condition_evaluator (const struct bp_location *bl)
 {
   if (bl && !is_breakpoint (bl->owner))
     return NULL;
@@ -5879,8 +6292,7 @@ bp_location_condition_evaluator (struct bp_location *bl)
 /* Print the LOC location out of the list of B->LOC locations.  */
 
 static void
-print_breakpoint_location (struct breakpoint *b,
-                          struct bp_location *loc)
+print_breakpoint_location (const breakpoint *b, const bp_location *loc)
 {
   struct ui_out *uiout = current_uiout;
 
@@ -5893,7 +6305,7 @@ print_breakpoint_location (struct breakpoint *b,
     set_current_program_space (loc->pspace);
 
   if (b->display_canonical)
-    uiout->field_string ("what", event_location_to_string (b->location.get ()));
+    uiout->field_string ("what", b->locspec->to_string ());
   else if (loc && loc->symtab)
     {
       const struct symbol *sym = loc->symbol;
@@ -5927,8 +6339,7 @@ print_breakpoint_location (struct breakpoint *b,
     }
   else
     {
-      uiout->field_string ("pending",
-                          event_location_to_string (b->location.get ()));
+      uiout->field_string ("pending", b->locspec->to_string ());
       /* 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.  */
@@ -5993,6 +6404,7 @@ bptype_string (enum bptype type)
     {bp_tracepoint, "tracepoint"},
     {bp_fast_tracepoint, "fast tracepoint"},
     {bp_static_tracepoint, "static tracepoint"},
+    {bp_static_marker_tracepoint, "static marker tracepoint"},
     {bp_dprintf, "dprintf"},
     {bp_jit_event, "jit events"},
     {bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
@@ -6001,8 +6413,7 @@ bptype_string (enum bptype type)
 
   if (((int) type >= (sizeof (bptypes) / sizeof (bptypes[0])))
       || ((int) type != bptypes[(int) type].type))
-    internal_error (__FILE__, __LINE__,
-                   _("bptypes table does not describe type #%d."),
+    internal_error (_("bptypes table does not describe type #%d."),
                    (int) type);
 
   return bptypes[(int) type].description;
@@ -6047,25 +6458,30 @@ output_thread_groups (struct ui_out *uiout,
     }
 }
 
+/* See breakpoint.h. */
+
+bool fix_breakpoint_script_output_globally = false;
+
 /* Print B to gdb_stdout.  If RAW_LOC, print raw breakpoint locations
    instead of going via breakpoint_ops::print_one.  This makes "maint
    info breakpoints" show the software breakpoint locations of
    catchpoints, which are considered internal implementation
-   detail.  */
+   detail.  Returns true if RAW_LOC is false and if the breakpoint's
+   print_one method did something; false otherwise.  */
 
-static void
+static bool
 print_one_breakpoint_location (struct breakpoint *b,
                               struct bp_location *loc,
                               int loc_number,
-                              struct bp_location **last_loc,
+                              const bp_location **last_loc,
                               int allflag, bool raw_loc)
 {
   struct command_line *l;
   static char bpenables[] = "nynny";
 
   struct ui_out *uiout = current_uiout;
-  int header_of_multiple = 0;
-  int part_of_multiple = (loc != NULL);
+  bool header_of_multiple = false;
+  bool part_of_multiple = (loc != NULL);
   struct value_print_options opts;
 
   get_user_print_options (&opts);
@@ -6074,12 +6490,13 @@ print_one_breakpoint_location (struct breakpoint *b,
   /* See comment in print_one_breakpoint concerning treatment of
      breakpoints with single disabled location.  */
   if (loc == NULL 
-      && (b->loc != NULL 
-         && (b->loc->next != NULL
-             || !b->loc->enabled || b->loc->disabled_by_cond)))
-    header_of_multiple = 1;
-  if (loc == NULL)
-    loc = b->loc;
+      && (b->has_locations ()
+         && (b->has_multiple_locations ()
+             || !b->first_loc ().enabled || b->first_loc ().disabled_by_cond)))
+    header_of_multiple = true;
+
+  if (loc == NULL && b->has_locations ())
+    loc = &b->first_loc ();
 
   annotate_record ();
 
@@ -6106,19 +6523,45 @@ print_one_breakpoint_location (struct breakpoint *b,
 
   /* 4 */
   annotate_field (3);
-  /* For locations that are disabled because of an invalid condition,
-     display "N*" on CLI, where "*" refers to a footnote below the
-     table.  For MI, simply display a "N" without a footnote.  */
-  const char *N = (uiout->is_mi_like_p ()) ? "N" : "N*";
   if (part_of_multiple)
-    uiout->field_string ("enabled", (loc->disabled_by_cond ? N
-                                    : (loc->enabled ? "y" : "n")));
+    {
+      /* For locations that are disabled because of an invalid
+        condition, display "N*" on the CLI, where "*" refers to a
+        footnote below the table.  For MI, simply display a "N"
+        without a footnote.  On the CLI, for enabled locations whose
+        breakpoint is disabled, display "y-".  */
+      auto get_enable_state = [uiout, loc] () -> const char *
+       {
+         if (uiout->is_mi_like_p ())
+           {
+             if (loc->disabled_by_cond)
+               return "N";
+             else if (!loc->enabled)
+               return "n";
+             else
+               return "y";
+           }
+         else
+           {
+             if (loc->disabled_by_cond)
+               return "N*";
+             else if (!loc->enabled)
+               return "n";
+             else if (!breakpoint_enabled (loc->owner))
+               return "y-";
+             else
+               return "y";
+           }
+       };
+      uiout->field_string ("enabled", get_enable_state ());
+    }
   else
     uiout->field_fmt ("enabled", "%c", bpenables[(int) b->enable_state]);
 
   /* 5 and 6 */
-  if (!raw_loc && b->ops != NULL && b->ops->print_one != NULL)
-    b->ops->print_one (b, last_loc);
+  bool result = false;
+  if (!raw_loc && b->print_one (last_loc))
+    result = true;
   else
     {
       if (is_watchpoint (b))
@@ -6142,7 +6585,7 @@ print_one_breakpoint_location (struct breakpoint *b,
              if (header_of_multiple)
                uiout->field_string ("addr", "<MULTIPLE>",
                                     metadata_style.style ());
-             else if (b->loc == NULL || loc->shlib_disabled)
+             else if (!b->has_locations () || loc->shlib_disabled)
                uiout->field_string ("addr", "<PENDING>",
                                     metadata_style.style ());
              else
@@ -6152,8 +6595,8 @@ print_one_breakpoint_location (struct breakpoint *b,
          annotate_field (5);
          if (!header_of_multiple)
            print_breakpoint_location (b, loc);
-         if (b->loc)
-           *last_loc = b->loc;
+         if (b->has_locations ())
+           *last_loc = &b->first_loc ();
        }
     }
 
@@ -6168,39 +6611,40 @@ print_one_breakpoint_location (struct breakpoint *b,
            inf_nums.push_back (inf->num);
        }
 
-       /* For backward compatibility, don't display inferiors in CLI unless
-          there are several.  Always display for MI. */
-       if (allflag
-           || (!gdbarch_has_global_breakpoints (target_gdbarch ())
-               && (program_spaces.size () > 1
-                   || number_of_inferiors () > 1)
-               /* LOC is for existing B, it cannot be in
-                  moribund_locations and thus having NULL OWNER.  */
-               && loc->owner->type != bp_catchpoint))
+      /* For backward compatibility, don't display inferiors in CLI unless
+        there are several.  Always display for MI. */
+      if (allflag
+         || (!gdbarch_has_global_breakpoints (target_gdbarch ())
+             && (program_spaces.size () > 1
+                 || number_of_inferiors () > 1)
+             /* LOC is for existing B, it cannot be in
+                moribund_locations and thus having NULL OWNER.  */
+             && loc->owner->type != bp_catchpoint))
        mi_only = 0;
       output_thread_groups (uiout, "thread-groups", inf_nums, mi_only);
     }
 
-  if (!part_of_multiple)
+  /* In the MI output, each location of a thread or task specific
+     breakpoint includes the relevant thread or task ID.  This is done for
+     backwards compatibility reasons.
+
+     For the CLI output, the thread/task information is printed on a
+     separate line, see the 'stop only in thread' and 'stop only in task'
+     output below.  */
+  if (part_of_multiple && uiout->is_mi_like_p ())
     {
       if (b->thread != -1)
-       {
-         /* FIXME: This seems to be redundant and lost here; see the
-            "stop only in" line a little further down.  */
-         uiout->text (" thread ");
-         uiout->field_signed ("thread", b->thread);
-       }
-      else if (b->task != 0)
-       {
-         uiout->text (" task ");
-         uiout->field_signed ("task", b->task);
-       }
+       uiout->field_signed ("thread", b->thread);
+      else if (b->task != -1)
+       uiout->field_signed ("task", b->task);
+      else if (b->inferior != -1)
+       uiout->field_signed ("inferior", b->inferior);
     }
 
   uiout->text ("\n");
 
   if (!part_of_multiple)
-    b->ops->print_one_detail (b, uiout);
+    b->print_one_detail (uiout);
 
   if (part_of_multiple && frame_id_p (b->frame_id))
     {
@@ -6249,7 +6693,21 @@ print_one_breakpoint_location (struct breakpoint *b,
        }
       uiout->text ("\n");
     }
-  
+
+  if (!part_of_multiple && b->task != -1)
+    {
+      uiout->text ("\tstop only in task ");
+      uiout->field_signed ("task", b->task);
+      uiout->text ("\n");
+    }
+
+  if (!part_of_multiple && b->inferior != -1)
+    {
+      uiout->text ("\tstop only in inferior ");
+      uiout->field_signed ("inferior", b->inferior);
+      uiout->text ("\n");
+    }
+
   if (!part_of_multiple)
     {
       if (b->hit_count)
@@ -6316,7 +6774,19 @@ print_one_breakpoint_location (struct breakpoint *b,
   if (!part_of_multiple && l)
     {
       annotate_field (9);
-      ui_out_emit_tuple tuple_emitter (uiout, "script");
+
+      bool use_fixed_output =
+       (uiout->test_flags (fix_breakpoint_script_output)
+        || fix_breakpoint_script_output_globally);
+
+      gdb::optional<ui_out_emit_tuple> tuple_emitter;
+      gdb::optional<ui_out_emit_list> list_emitter;
+
+      if (use_fixed_output)
+       list_emitter.emplace (uiout, "script");
+      else
+       tuple_emitter.emplace (uiout, "script");
+
       print_command_lines (uiout, l, 4);
     }
 
@@ -6360,11 +6830,15 @@ print_one_breakpoint_location (struct breakpoint *b,
 
          uiout->field_string ("original-location", w->exp_string.get ());
        }
-      else if (b->location != NULL
-              && event_location_to_string (b->location.get ()) != NULL)
-       uiout->field_string ("original-location",
-                            event_location_to_string (b->location.get ()));
+      else if (b->locspec != nullptr)
+       {
+         const char *str = b->locspec->to_string ();
+         if (str != nullptr)
+           uiout->field_string ("original-location", str);
+       }
     }
+
+  return result;
 }
 
 /* See breakpoint.h. */
@@ -6372,9 +6846,7 @@ print_one_breakpoint_location (struct breakpoint *b,
 bool fix_multi_location_breakpoint_output_globally = false;
 
 static void
-print_one_breakpoint (struct breakpoint *b,
-                     struct bp_location **last_loc, 
-                     int allflag)
+print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
 {
   struct ui_out *uiout = current_uiout;
   bool use_fixed_output
@@ -6382,7 +6854,8 @@ print_one_breakpoint (struct breakpoint *b,
        || fix_multi_location_breakpoint_output_globally);
 
   gdb::optional<ui_out_emit_tuple> bkpt_tuple_emitter (gdb::in_place, uiout, "bkpt");
-  print_one_breakpoint_location (b, NULL, 0, last_loc, allflag, false);
+  bool printed = print_one_breakpoint_location (b, NULL, 0, last_loc,
+                                               allflag, false);
 
   /* The mi2 broken format: the main breakpoint tuple ends here, the locations
      are outside.  */
@@ -6392,9 +6865,7 @@ print_one_breakpoint (struct breakpoint *b,
   /* If this breakpoint has custom print function,
      it's already printed.  Otherwise, print individual
      locations, if any.  */
-  if (b->ops == NULL
-      || b->ops->print_one == NULL
-      || allflag)
+  if (!printed || allflag)
     {
       /* If breakpoint has a single location that is disabled, we
         print it as if it had several locations, since otherwise it's
@@ -6412,9 +6883,10 @@ print_one_breakpoint (struct breakpoint *b,
          && (!is_catchpoint (b) || is_exception_catchpoint (b)
              || is_ada_exception_catchpoint (b))
          && (allflag
-             || (b->loc && (b->loc->next
-                            || !b->loc->enabled
-                            || b->loc->disabled_by_cond))))
+             || (b->has_locations ()
+                 && (b->has_multiple_locations ()
+                     || !b->first_loc ().enabled
+                     || b->first_loc ().disabled_by_cond))))
        {
          gdb::optional<ui_out_emit_list> locations_list;
 
@@ -6425,10 +6897,10 @@ print_one_breakpoint (struct breakpoint *b,
            locations_list.emplace (uiout, "locations");
 
          int n = 1;
-         for (bp_location *loc : b->locations ())
+         for (bp_location &loc : b->locations ())
            {
              ui_out_emit_tuple loc_tuple_emitter (uiout, NULL);
-             print_one_breakpoint_location (b, loc, n, last_loc,
+             print_one_breakpoint_location (b, &loc, n, last_loc,
                                             allflag, allflag);
              n++;
            }
@@ -6441,16 +6913,12 @@ breakpoint_address_bits (struct breakpoint *b)
 {
   int print_address_bits = 0;
 
-  /* Software watchpoints that aren't watching memory don't have an
-     address to print.  */
-  if (is_no_memory_software_watchpoint (b))
-    return 0;
-
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     {
-      int addr_bit;
+      if (!bl_address_is_meaningful (&loc))
+       continue;
 
-      addr_bit = gdbarch_addr_bit (loc->gdbarch);
+      int addr_bit = gdbarch_addr_bit (loc.gdbarch);
       if (addr_bit > print_address_bits)
        print_address_bits = addr_bit;
     }
@@ -6463,7 +6931,7 @@ breakpoint_address_bits (struct breakpoint *b)
 void
 print_breakpoint (breakpoint *b)
 {
-  struct bp_location *dummy_loc = NULL;
+  const bp_location *dummy_loc = nullptr;
   print_one_breakpoint (b, &dummy_loc, 0);
 }
 
@@ -6481,7 +6949,7 @@ user_breakpoint_p (struct breakpoint *b)
 int
 pending_breakpoint_p (struct breakpoint *b)
 {
-  return b->loc == NULL;
+  return !b->has_locations ();
 }
 
 /* Print information on breakpoints (including watchpoints and tracepoints).
@@ -6501,7 +6969,7 @@ static int
 breakpoint_1 (const char *bp_num_list, bool show_internal,
              bool (*filter) (const struct breakpoint *))
 {
-  struct bp_location *last_loc = NULL;
+  const bp_location *last_loc = nullptr;
   int nr_printable_breakpoints;
   struct value_print_options opts;
   int print_address_bits = 0;
@@ -6514,31 +6982,31 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
   /* Compute the number of rows in the table, as well as the size
      required for address fields.  */
   nr_printable_breakpoints = 0;
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
       /* If we have a filter, only list the breakpoints it accepts.  */
-      if (filter && !filter (b))
+      if (filter && !filter (&b))
        continue;
 
       /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
         accept.  Skip the others.  */
       if (bp_num_list != NULL && *bp_num_list != '\0')
        {
-         if (show_internal && parse_and_eval_long (bp_num_list) != b->number)
+         if (show_internal && parse_and_eval_long (bp_num_list) != b.number)
            continue;
-         if (!show_internal && !number_is_in_list (bp_num_list, b->number))
+         if (!show_internal && !number_is_in_list (bp_num_list, b.number))
            continue;
        }
 
-      if (show_internal || user_breakpoint_p (b))
+      if (show_internal || user_breakpoint_p (&b))
        {
          int addr_bit, type_len;
 
-         addr_bit = breakpoint_address_bits (b);
+         addr_bit = breakpoint_address_bits (&b);
          if (addr_bit > print_address_bits)
            print_address_bits = addr_bit;
 
-         type_len = strlen (bptype_string (b->type));
+         type_len = strlen (bptype_string (b.type));
          if (type_len > print_type_col_width)
            print_type_col_width = type_len;
 
@@ -6582,11 +7050,11 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
     if (nr_printable_breakpoints > 0)
       annotate_breakpoints_table ();
 
-    for (breakpoint *b : all_breakpoints ())
+    for (breakpoint &b : all_breakpoints ())
       {
        QUIT;
        /* If we have a filter, only list the breakpoints it accepts.  */
-       if (filter && !filter (b))
+       if (filter && !filter (&b))
          continue;
 
        /* If we have a BP_NUM_LIST string, it is a list of breakpoints to
@@ -6596,22 +7064,22 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
          {
            if (show_internal)  /* maintenance info breakpoint */
              {
-               if (parse_and_eval_long (bp_num_list) != b->number)
+               if (parse_and_eval_long (bp_num_list) != b.number)
                  continue;
              }
            else                /* all others */
              {
-               if (!number_is_in_list (bp_num_list, b->number))
+               if (!number_is_in_list (bp_num_list, b.number))
                  continue;
              }
          }
        /* We only print out user settable breakpoints unless the
           show_internal is set.  */
-       if (show_internal || user_breakpoint_p (b))
+       if (show_internal || user_breakpoint_p (&b))
          {
-           print_one_breakpoint (b, &last_loc, show_internal);
-           for (bp_location *loc : b->locations ())
-             if (loc->disabled_by_cond)
+           print_one_breakpoint (&b, &last_loc, show_internal);
+           for (bp_location &loc : b.locations ())
+             if (loc.disabled_by_cond)
                has_disabled_by_cond_location = true;
          }
       }
@@ -6699,58 +7167,62 @@ maintenance_info_breakpoints (const char *args, int from_tty)
   default_collect_info ();
 }
 
-static int
+static bool
 breakpoint_has_pc (struct breakpoint *b,
                   struct program_space *pspace,
                   CORE_ADDR pc, struct obj_section *section)
 {
-  for (bp_location *bl : b->locations ())
+  for (bp_location &bl : b->locations ())
     {
-      if (bl->pspace == pspace
-         && bl->address == pc
-         && (!overlay_debugging || bl->section == section))
-       return 1;         
+      if (bl.pspace == pspace
+         && bl.address == pc
+         && (!overlay_debugging || bl.section == section))
+       return true;
     }
-  return 0;
+  return false;
 }
 
-/* Print a message describing any user-breakpoints set at PC.  This
-   concerns with logical breakpoints, so we match program spaces, not
-   address spaces.  */
+/* See breakpoint.h.  */
 
-static void
+void
 describe_other_breakpoints (struct gdbarch *gdbarch,
                            struct program_space *pspace, CORE_ADDR pc,
                            struct obj_section *section, int thread)
 {
   int others = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    others += (user_breakpoint_p (b)
-              && breakpoint_has_pc (b, pspace, pc, section));
+  for (breakpoint &b : all_breakpoints ())
+    others += (user_breakpoint_p (&b)
+              && breakpoint_has_pc (&b, pspace, pc, section));
 
   if (others > 0)
     {
       if (others == 1)
-       printf_filtered (_("Note: breakpoint "));
+       gdb_printf (_("Note: breakpoint "));
       else /* if (others == ???) */
-       printf_filtered (_("Note: breakpoints "));
-      for (breakpoint *b : all_breakpoints ())
-       if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
+       gdb_printf (_("Note: breakpoints "));
+      for (breakpoint &b : all_breakpoints ())
+       if (user_breakpoint_p (&b)
+           && breakpoint_has_pc (&b, pspace, pc, section))
          {
            others--;
-           printf_filtered ("%d", b->number);
-           if (b->thread == -1 && thread != -1)
-             printf_filtered (" (all threads)");
-           else if (b->thread != -1)
-             printf_filtered (" (thread %d)", b->thread);
-           printf_filtered ("%s%s ",
-                            ((b->enable_state == bp_disabled
-                              || b->enable_state == bp_call_disabled)
-                             ? " (disabled)"
-                             : ""),
-                            (others > 1) ? "," 
-                            : ((others == 1) ? " and" : ""));
+           gdb_printf ("%d", b.number);
+           if (b.thread == -1 && thread != -1)
+             gdb_printf (" (all threads)");
+           else if (b.thread != -1)
+             {
+               struct thread_info *thr = find_thread_global_id (b.thread);
+               gdb_printf (" (thread %s)", print_thread_id (thr));
+             }
+           else if (b.task != -1)
+             gdb_printf (" (task %d)", b.task);
+           gdb_printf ("%s%s ",
+                       ((b.enable_state == bp_disabled
+                         || b.enable_state == bp_call_disabled)
+                        ? " (disabled)"
+                        : ""),
+                       (others > 1) ? "," 
+                       : ((others == 1) ? " and" : ""));
          }
       current_uiout->message (_("also set at pc %ps.\n"),
                              styled_string (address_style.style (),
@@ -6779,9 +7251,9 @@ bl_address_is_meaningful (bp_location *loc)
 /* Assuming LOC1 and LOC2's owners are hardware watchpoints, returns
    true if LOC1 and LOC2 represent the same watchpoint location.  */
 
-static int
-watchpoint_locations_match (struct bp_location *loc1, 
-                           struct bp_location *loc2)
+static bool
+watchpoint_locations_match (const struct bp_location *loc1,
+                           const struct bp_location *loc2)
 {
   struct watchpoint *w1 = (struct watchpoint *) loc1->owner;
   struct watchpoint *w2 = (struct watchpoint *) loc2->owner;
@@ -6806,7 +7278,7 @@ watchpoint_locations_match (struct bp_location *loc1,
                                                    loc2->length,
                                                    loc2->watchpoint_type,
                                                    w2->cond_exp.get ())))
-    return 0;
+    return false;
 
   /* Note that this checks the owner's type, not the location's.  In
      case the target does not support read watchpoints, but does
@@ -6836,7 +7308,7 @@ breakpoint_address_match (const address_space *aspace1, CORE_ADDR addr1,
    matches ASPACE2.  On targets that have global breakpoints, the address
    space doesn't really matter.  */
 
-static int
+static bool
 breakpoint_address_match_range (const address_space *aspace1,
                                CORE_ADDR addr1,
                                int len1, const address_space *aspace2,
@@ -6852,7 +7324,7 @@ breakpoint_address_match_range (const address_space *aspace1,
    matches the breakpoint's address space.  On targets that have global
    breakpoints, the address space doesn't really matter.  */
 
-static int
+static bool
 breakpoint_location_address_match (struct bp_location *bl,
                                   const address_space *aspace,
                                   CORE_ADDR addr)
@@ -6871,7 +7343,7 @@ breakpoint_location_address_match (struct bp_location *bl,
    space.  On targets that have global breakpoints, the address space
    doesn't really matter.  */
 
-static int
+static bool
 breakpoint_location_address_range_overlap (struct bp_location *bl,
                                           const address_space *aspace,
                                           CORE_ADDR addr, int len)
@@ -6891,9 +7363,9 @@ breakpoint_location_address_range_overlap (struct bp_location *bl,
    Then, if LOC1 and LOC2 represent the same tracepoint location, returns
    true, otherwise returns false.  */
 
-static int
-tracepoint_locations_match (struct bp_location *loc1,
-                           struct bp_location *loc2)
+static bool
+tracepoint_locations_match (const struct bp_location *loc1,
+                           const struct bp_location *loc2)
 {
   if (is_tracepoint (loc1->owner) && is_tracepoint (loc2->owner))
     /* Since tracepoint locations are never duplicated with others', tracepoint
@@ -6901,7 +7373,7 @@ tracepoint_locations_match (struct bp_location *loc1,
        different locations.  */
     return (loc1->address == loc2->address && loc1->owner == loc2->owner);
   else
-    return 0;
+    return false;
 }
 
 /* Assuming LOC1 and LOC2's types' have meaningful target addresses
@@ -6910,9 +7382,9 @@ tracepoint_locations_match (struct bp_location *loc1,
    breakpoint locations and hardware breakpoint locations match,
    otherwise they don't.  */
 
-static int
-breakpoint_locations_match (struct bp_location *loc1,
-                           struct bp_location *loc2,
+static bool
+breakpoint_locations_match (const struct bp_location *loc1,
+                           const struct bp_location *loc2,
                            bool sw_hw_bps_match)
 {
   int hw_point1, hw_point2;
@@ -6925,7 +7397,7 @@ breakpoint_locations_match (struct bp_location *loc1,
   hw_point2 = is_hardware_watchpoint (loc2->owner);
 
   if (hw_point1 != hw_point2)
-    return 0;
+    return false;
   else if (hw_point1)
     return watchpoint_locations_match (loc1, loc2);
   else if (is_tracepoint (loc1->owner) || is_tracepoint (loc2->owner))
@@ -6942,7 +7414,7 @@ breakpoint_locations_match (struct bp_location *loc1,
 
 static void
 breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
-                              int bnum, int have_bnum)
+                              int bnum, bool have_bnum)
 {
   /* The longest string possibly returned by hex_string_custom
      is 50 chars.  These must be at least that big for safety.  */
@@ -6965,8 +7437,11 @@ breakpoint_adjustment_warning (CORE_ADDR from_addr, CORE_ADDR to_addr,
 
 static CORE_ADDR
 adjust_breakpoint_address (struct gdbarch *gdbarch,
-                          CORE_ADDR bpaddr, enum bptype bptype)
+                          CORE_ADDR bpaddr, enum bptype bptype,
+                          struct program_space *pspace)
 {
+  gdb_assert (pspace != nullptr);
+
   if (bptype == bp_watchpoint
       || bptype == bp_hardware_watchpoint
       || bptype == bp_read_watchpoint
@@ -6991,20 +7466,28 @@ adjust_breakpoint_address (struct gdbarch *gdbarch,
     {
       CORE_ADDR adjusted_bpaddr = bpaddr;
 
+      /* Some targets have architectural constraints on the placement
+        of breakpoint instructions.  Obtain the adjusted address.  */
       if (gdbarch_adjust_breakpoint_address_p (gdbarch))
        {
-         /* Some targets have architectural constraints on the placement
-            of breakpoint instructions.  Obtain the adjusted address.  */
-         adjusted_bpaddr = gdbarch_adjust_breakpoint_address (gdbarch, bpaddr);
+         /* Targets that implement this adjustment function will likely
+            inspect either the symbol table, target memory at BPADDR, or
+            even state registers, so ensure a suitable thread (and its
+            associated program space) are currently selected.  */
+         scoped_restore_current_pspace_and_thread restore_pspace_thread;
+         switch_to_program_space_and_thread (pspace);
+         adjusted_bpaddr
+           = gdbarch_adjust_breakpoint_address (gdbarch, bpaddr);
        }
 
-      adjusted_bpaddr = address_significant (gdbarch, adjusted_bpaddr);
+      adjusted_bpaddr
+       = gdbarch_remove_non_address_bits (gdbarch, adjusted_bpaddr);
 
       /* An adjusted breakpoint address can significantly alter
         a user's expectations.  Print a warning if an adjustment
         is required.  */
       if (adjusted_bpaddr != bpaddr)
-       breakpoint_adjustment_warning (bpaddr, adjusted_bpaddr, 0, 0);
+       breakpoint_adjustment_warning (bpaddr, adjusted_bpaddr, 0, false);
 
       return adjusted_bpaddr;
     }
@@ -7040,20 +7523,29 @@ bp_location_from_bp_type (bptype type)
     case bp_gnu_ifunc_resolver_return:
     case bp_dprintf:
       return bp_loc_software_breakpoint;
+
     case bp_hardware_breakpoint:
       return bp_loc_hardware_breakpoint;
+
     case bp_hardware_watchpoint:
     case bp_read_watchpoint:
     case bp_access_watchpoint:
       return bp_loc_hardware_watchpoint;
+
     case bp_watchpoint:
-    case bp_catchpoint:
+      return bp_loc_software_watchpoint;
+
     case bp_tracepoint:
     case bp_fast_tracepoint:
     case bp_static_tracepoint:
+    case bp_static_marker_tracepoint:
+      return bp_loc_tracepoint;
+
+    case bp_catchpoint:
       return bp_loc_other;
+
     default:
-      internal_error (__FILE__, __LINE__, _("unknown breakpoint type"));
+      internal_error (_("unknown breakpoint type"));
     }
 }
 
@@ -7080,12 +7572,15 @@ bp_location::bp_location (breakpoint *owner)
 {
 }
 
-/* Allocate a struct bp_location.  */
+/* See breakpoint.h.  */
 
-static struct bp_location *
-allocate_bp_location (struct breakpoint *bpt)
+std::string
+bp_location::to_string () const
 {
-  return bpt->ops->allocate_location (bpt);
+  string_file stb;
+  ui_out_redirect_pop redir (current_uiout, &stb);
+  print_breakpoint_location (this->owner, this);
+  return stb.string ();
 }
 
 /* Decrement reference count.  If the reference count reaches 0,
@@ -7103,55 +7598,12 @@ decref_bp_location (struct bp_location **blp)
 static breakpoint *
 add_to_breakpoint_chain (std::unique_ptr<breakpoint> &&b)
 {
-  struct breakpoint *b1;
-  struct breakpoint *result = b.get ();
-
   /* Add this breakpoint to the end of the chain so that a list of
      breakpoints will come out in order of increasing numbers.  */
 
-  b1 = breakpoint_chain;
-  if (b1 == 0)
-    breakpoint_chain = b.release ();
-  else
-    {
-      while (b1->next)
-       b1 = b1->next;
-      b1->next = b.release ();
-    }
-
-  return result;
-}
-
-/* Initializes breakpoint B with type BPTYPE and no locations yet.  */
-
-static void
-init_raw_breakpoint_without_location (struct breakpoint *b,
-                                     struct gdbarch *gdbarch,
-                                     enum bptype bptype,
-                                     const struct breakpoint_ops *ops)
-{
-  gdb_assert (ops != NULL);
-
-  b->ops = ops;
-  b->type = bptype;
-  b->gdbarch = gdbarch;
-  b->language = current_language->la_language;
-  b->input_radix = input_radix;
-  b->related_breakpoint = b;
-}
-
-/* Helper to set_raw_breakpoint below.  Creates a breakpoint
-   that has type BPTYPE and has no locations as yet.  */
-
-static struct breakpoint *
-set_raw_breakpoint_without_location (struct gdbarch *gdbarch,
-                                    enum bptype bptype,
-                                    const struct breakpoint_ops *ops)
-{
-  std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
+  breakpoint_chain.push_back (*b.release ());
 
-  init_raw_breakpoint_without_location (b.get (), gdbarch, bptype, ops);
-  return add_to_breakpoint_chain (std::move (b));
+  return &breakpoint_chain.back ();
 }
 
 /* Initialize loc->function_name.  */
@@ -7168,15 +7620,16 @@ set_breakpoint_location_function (struct bp_location *loc)
       const char *function_name;
 
       if (loc->msymbol != NULL
-         && (MSYMBOL_TYPE (loc->msymbol) == mst_text_gnu_ifunc
-             || MSYMBOL_TYPE (loc->msymbol) == mst_data_gnu_ifunc))
+         && (loc->msymbol->type () == mst_text_gnu_ifunc
+             || loc->msymbol->type () == mst_data_gnu_ifunc))
        {
          struct breakpoint *b = loc->owner;
 
          function_name = loc->msymbol->linkage_name ();
 
-         if (b->type == bp_breakpoint && b->loc == loc
-             && loc->next == NULL && b->related_breakpoint == b)
+         if (b->type == bp_breakpoint
+             && b->has_single_location ()
+             && b->related_breakpoint == b)
            {
              /* Create only the whole new breakpoint of this type but do not
                 mess more complicated breakpoints with multiple locations.  */
@@ -7201,64 +7654,11 @@ get_sal_arch (struct symtab_and_line sal)
   if (sal.section)
     return sal.section->objfile->arch ();
   if (sal.symtab)
-    return SYMTAB_OBJFILE (sal.symtab)->arch ();
+    return sal.symtab->compunit ()->objfile ()->arch ();
 
   return NULL;
 }
 
-/* Low level routine for partially initializing a breakpoint of type
-   BPTYPE.  The newly created breakpoint's address, section, source
-   file name, and line number are provided by SAL.
-
-   It is expected that the caller will complete the initialization of
-   the newly created breakpoint struct as well as output any status
-   information regarding the creation of a new breakpoint.  */
-
-static void
-init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
-                    struct symtab_and_line sal, enum bptype bptype,
-                    const struct breakpoint_ops *ops)
-{
-  init_raw_breakpoint_without_location (b, gdbarch, bptype, ops);
-
-  add_location_to_breakpoint (b, &sal);
-
-  if (bptype != bp_catchpoint)
-    gdb_assert (sal.pspace != NULL);
-
-  /* Store the program space that was used to set the breakpoint,
-     except for ordinary breakpoints, which are independent of the
-     program space.  */
-  if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
-    b->pspace = sal.pspace;
-}
-
-/* set_raw_breakpoint is a low level routine for allocating and
-   partially initializing a breakpoint of type BPTYPE.  The newly
-   created breakpoint's address, section, source file name, and line
-   number are provided by SAL.  The newly created and partially
-   initialized breakpoint is added to the breakpoint chain and
-   is also returned as the value of this function.
-
-   It is expected that the caller will complete the initialization of
-   the newly created breakpoint struct as well as output any status
-   information regarding the creation of a new breakpoint.  In
-   particular, set_raw_breakpoint does NOT set the breakpoint
-   number!  Care should be taken to not allow an error to occur
-   prior to completing the initialization of the breakpoint.  If this
-   should happen, a bogus breakpoint will be left on the chain.  */
-
-static struct breakpoint *
-set_raw_breakpoint (struct gdbarch *gdbarch,
-                   struct symtab_and_line sal, enum bptype bptype,
-                   const struct breakpoint_ops *ops)
-{
-  std::unique_ptr<breakpoint> b = new_breakpoint_from_type (bptype);
-
-  init_raw_breakpoint (b.get (), gdbarch, sal, bptype, ops);
-  return add_to_breakpoint_chain (std::move (b));
-}
-
 /* Call this routine when stepping and nexting to enable a breakpoint
    if we do a longjmp() or 'throw' in TP.  FRAME is the frame which
    initiated the operation.  */
@@ -7272,19 +7672,15 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
      we maintain a list of continually-inserted but always disabled
      longjmp "master" breakpoints.  Here, we simply create momentary
      clones of those and enable them for the requested thread.  */
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == current_program_space
-       && (b->type == bp_longjmp_master
-           || b->type == bp_exception_master))
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == current_program_space
+       && (b.type == bp_longjmp_master
+           || b.type == bp_exception_master))
       {
-       enum bptype type = b->type == bp_longjmp_master ? bp_longjmp : bp_exception;
-       struct breakpoint *clone;
-
+       bptype type = b.type == bp_longjmp_master ? bp_longjmp : bp_exception;
        /* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
           after their removal.  */
-       clone = momentary_breakpoint_from_master (b, type,
-                                                 &momentary_breakpoint_ops, 1);
-       clone->thread = thread;
+       momentary_breakpoint_from_master (&b, type, 1, thread);
       }
 
   tp->initiating_frame = frame;
@@ -7294,22 +7690,28 @@ set_longjmp_breakpoint (struct thread_info *tp, struct frame_id frame)
 void
 delete_longjmp_breakpoint (int thread)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_longjmp || b->type == bp_exception)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_longjmp || b.type == bp_exception)
       {
-       if (b->thread == thread)
-         delete_breakpoint (b);
+       if (b.thread == thread)
+         {
+           gdb_assert (b.inferior == -1);
+           delete_breakpoint (&b);
+         }
       }
 }
 
 void
 delete_longjmp_breakpoint_at_next_stop (int thread)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_longjmp || b->type == bp_exception)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_longjmp || b.type == bp_exception)
       {
-       if (b->thread == thread)
-         b->disposition = disp_del_at_next_stop;
+       if (b.thread == thread)
+         {
+           gdb_assert (b.inferior == -1);
+           b.disposition = disp_del_at_next_stop;
+         }
       }
 }
 
@@ -7323,15 +7725,13 @@ set_longjmp_breakpoint_for_call_dummy (void)
 {
   breakpoint *retval = nullptr;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->pspace == current_program_space && b->type == bp_longjmp_master)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.pspace == current_program_space && b.type == bp_longjmp_master)
       {
-       struct breakpoint *new_b;
-
-       new_b = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
-                                                 &momentary_breakpoint_ops,
-                                                 1);
-       new_b->thread = inferior_thread ()->global_num;
+       int thread = inferior_thread ()->global_num;
+       breakpoint *new_b
+         = momentary_breakpoint_from_master (&b, bp_longjmp_call_dummy,
+                                             1, thread);
 
        /* Link NEW_B into the chain of RETVAL breakpoints.  */
 
@@ -7359,81 +7759,89 @@ set_longjmp_breakpoint_for_call_dummy (void)
 void
 check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
 {
-  struct breakpoint *b, *b_tmp;
+  /* We would need to delete breakpoints other than the current one while
+     iterating, so all_breakpoints_safe is not sufficient to make that safe.
+     Save all breakpoints to delete in that set and delete them at the end.  */
+  std::unordered_set<breakpoint *> to_delete;
 
-  ALL_BREAKPOINTS_SAFE (b, b_tmp)
-    if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
-      {
-       struct breakpoint *dummy_b = b->related_breakpoint;
-
-       /* Find the bp_call_dummy breakpoint in the list of breakpoints
-          chained off b->related_breakpoint.  */
-       while (dummy_b != b && dummy_b->type != bp_call_dummy)
-         dummy_b = dummy_b->related_breakpoint;
-
-       /* If there was no bp_call_dummy breakpoint then there's nothing
-          more to do.  Or, if the dummy frame associated with the
-          bp_call_dummy is still on the stack then we need to leave this
-          bp_call_dummy in place.  */
-       if (dummy_b->type != bp_call_dummy
-           || frame_find_by_id (dummy_b->frame_id) != NULL)
-         continue;
+  for (struct breakpoint &b : all_breakpoints ())
+    {
+      if (b.type == bp_longjmp_call_dummy && b.thread == tp->global_num)
+       {
+         gdb_assert (b.inferior == -1);
+         struct breakpoint *dummy_b = b.related_breakpoint;
 
-       /* We didn't find the dummy frame on the stack, this could be
-          because we have longjmp'd to a stack frame that is previous to
-          the dummy frame, or it could be because the stack unwind is
-          broken at some point between the longjmp frame and the dummy
-          frame.
-
-          Next we figure out why the stack unwind stopped.  If it looks
-          like the unwind is complete then we assume the dummy frame has
-          been jumped over, however, if the unwind stopped for an
-          unexpected reason then we assume the stack unwind is currently
-          broken, and that we will (eventually) return to the dummy
-          frame.
-
-          It might be tempting to consider using frame_id_inner here, but
-          that is not safe.   There is no guarantee that the stack frames
-          we are looking at here are even on the same stack as the
-          original dummy frame, hence frame_id_inner can't be used.  See
-          the comments on frame_id_inner for more details.  */
-       bool unwind_finished_unexpectedly = false;
-       for (struct frame_info *fi = get_current_frame (); fi != nullptr; )
-         {
-           struct frame_info *prev = get_prev_frame (fi);
-           if (prev == nullptr)
-             {
-               /* FI is the last stack frame.  Why did this frame not
-                  unwind further?  */
-               auto stop_reason = get_frame_unwind_stop_reason (fi);
-               if (stop_reason != UNWIND_NO_REASON
-                   && stop_reason != UNWIND_OUTERMOST)
-                 unwind_finished_unexpectedly = true;
-             }
-           fi = prev;
-         }
-       if (unwind_finished_unexpectedly)
-         continue;
+         /* Find the bp_call_dummy breakpoint in the list of breakpoints
+            chained off b->related_breakpoint.  */
+         while (dummy_b != &b && dummy_b->type != bp_call_dummy)
+           dummy_b = dummy_b->related_breakpoint;
 
-       dummy_frame_discard (dummy_b->frame_id, tp);
+         /* If there was no bp_call_dummy breakpoint then there's nothing
+            more to do.  Or, if the dummy frame associated with the
+            bp_call_dummy is still on the stack then we need to leave this
+            bp_call_dummy in place.  */
+         if (dummy_b->type != bp_call_dummy
+             || frame_find_by_id (dummy_b->frame_id) != NULL)
+           continue;
 
-       while (b->related_breakpoint != b)
-         {
-           if (b_tmp == b->related_breakpoint)
-             b_tmp = b->related_breakpoint->next;
-           delete_breakpoint (b->related_breakpoint);
-         }
-       delete_breakpoint (b);
-      }
+         /* We didn't find the dummy frame on the stack, this could be
+            because we have longjmp'd to a stack frame that is previous to
+            the dummy frame, or it could be because the stack unwind is
+            broken at some point between the longjmp frame and the dummy
+            frame.
+
+            Next we figure out why the stack unwind stopped.  If it looks
+            like the unwind is complete then we assume the dummy frame has
+            been jumped over, however, if the unwind stopped for an
+            unexpected reason then we assume the stack unwind is currently
+            broken, and that we will (eventually) return to the dummy
+            frame.
+
+            It might be tempting to consider using frame_id_inner here, but
+            that is not safe.   There is no guarantee that the stack frames
+            we are looking at here are even on the same stack as the
+            original dummy frame, hence frame_id_inner can't be used.  See
+            the comments on frame_id_inner for more details.  */
+         bool unwind_finished_unexpectedly = false;
+         for (frame_info_ptr fi = get_current_frame (); fi != nullptr; )
+           {
+             frame_info_ptr prev = get_prev_frame (fi);
+             if (prev == nullptr)
+               {
+                 /* FI is the last stack frame.  Why did this frame not
+                    unwind further?  */
+                 auto stop_reason = get_frame_unwind_stop_reason (fi);
+                 if (stop_reason != UNWIND_NO_REASON
+                     && stop_reason != UNWIND_OUTERMOST)
+                   unwind_finished_unexpectedly = true;
+               }
+             fi = prev;
+           }
+         if (unwind_finished_unexpectedly)
+           continue;
+
+         dummy_frame_discard (dummy_b->frame_id, tp);
+
+         for (breakpoint *related_breakpoint = b.related_breakpoint;
+              related_breakpoint != &b;
+              related_breakpoint = related_breakpoint->related_breakpoint)
+           to_delete.insert (b.related_breakpoint);
+
+         to_delete.insert (&b);
+       }
+    }
+
+  for (breakpoint *b : to_delete)
+    delete_breakpoint (b);
 }
 
 void
 enable_overlay_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_overlay_event)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_overlay_event)
       {
-       b->enable_state = bp_enabled;
+       b.enable_state = bp_enabled;
        update_global_location_list (UGLL_MAY_INSERT);
        overlay_events_enabled = 1;
       }
@@ -7442,10 +7850,10 @@ enable_overlay_breakpoints (void)
 void
 disable_overlay_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_overlay_event)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_overlay_event)
       {
-       b->enable_state = bp_disabled;
+       b.enable_state = bp_disabled;
        update_global_location_list (UGLL_DONT_INSERT);
        overlay_events_enabled = 0;
       }
@@ -7456,12 +7864,12 @@ disable_overlay_breakpoints (void)
 void
 set_std_terminate_breakpoint (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->pspace == current_program_space
-       && b->type == bp_std_terminate_master)
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.pspace == current_program_space
+       && b.type == bp_std_terminate_master)
       {
-       momentary_breakpoint_from_master (b, bp_std_terminate,
-                                         &momentary_breakpoint_ops, 1);
+       momentary_breakpoint_from_master (&b, bp_std_terminate, 1,
+                                         inferior_thread ()->global_num);
       }
 }
 
@@ -7469,9 +7877,9 @@ set_std_terminate_breakpoint (void)
 void
 delete_std_terminate_breakpoint (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_std_terminate)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_std_terminate)
+      delete_breakpoint (&b);
 }
 
 struct breakpoint *
@@ -7479,12 +7887,11 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 {
   struct breakpoint *b;
 
-  b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
-                                 &internal_breakpoint_ops);
+  b = create_internal_breakpoint (gdbarch, address, bp_thread_event);
 
   b->enable_state = bp_enabled;
-  /* location has to be used or breakpoint_re_set will delete me.  */
-  b->location = new_address_location (b->loc->address, NULL, 0);
+  /* locspec has to be used or breakpoint_re_set will delete me.  */
+  b->locspec = new_address_location_spec (b->first_loc ().address, NULL, 0);
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
@@ -7502,8 +7909,7 @@ struct lang_and_radix
 struct breakpoint *
 create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 {
-  return create_internal_breakpoint (gdbarch, address, bp_jit_event,
-                                    &internal_breakpoint_ops);
+  return create_internal_breakpoint (gdbarch, address, bp_jit_event);
 }
 
 /* Remove JIT code registration and unregistration breakpoint(s).  */
@@ -7511,19 +7917,19 @@ create_jit_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 void
 remove_jit_event_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_jit_event
-       && b->loc->pspace == current_program_space)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_jit_event
+       && b.first_loc ().pspace == current_program_space)
+      delete_breakpoint (&b);
 }
 
 void
 remove_solib_event_breakpoints (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_shlib_event
-       && b->loc->pspace == current_program_space)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_shlib_event
+       && b.first_loc ().pspace == current_program_space)
+      delete_breakpoint (&b);
 }
 
 /* See breakpoint.h.  */
@@ -7531,10 +7937,10 @@ remove_solib_event_breakpoints (void)
 void
 remove_solib_event_breakpoints_at_next_stop (void)
 {
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->type == bp_shlib_event
-       && b->loc->pspace == current_program_space)
-      b->disposition = disp_del_at_next_stop;
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.type == bp_shlib_event
+       && b.first_loc ().pspace == current_program_space)
+      b.disposition = disp_del_at_next_stop;
 }
 
 /* Helper for create_solib_event_breakpoint /
@@ -7547,8 +7953,7 @@ create_solib_event_breakpoint_1 (struct gdbarch *gdbarch, CORE_ADDR address,
 {
   struct breakpoint *b;
 
-  b = create_internal_breakpoint (gdbarch, address, bp_shlib_event,
-                                 &internal_breakpoint_ops);
+  b = create_internal_breakpoint (gdbarch, address, bp_shlib_event);
   update_global_location_list_nothrow (insert_mode);
   return b;
 }
@@ -7569,7 +7974,7 @@ create_and_insert_solib_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR add
   /* Explicitly tell update_global_location_list to insert
      locations.  */
   b = create_solib_event_breakpoint_1 (gdbarch, address, UGLL_INSERT);
-  if (!b->loc->inserted)
+  if (!b->first_loc ().inserted)
     {
       delete_breakpoint (b);
       return NULL;
@@ -7614,7 +8019,7 @@ disable_breakpoints_in_shlibs (void)
 static void
 disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
 {
-  int disabled_shlib_breaks = 0;
+  bool disabled_shlib_breaks = false;
 
   for (bp_location *loc : all_bp_locations ())
     {
@@ -7638,7 +8043,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
          loc->inserted = 0;
 
          /* This may cause duplicate notifications for the same breakpoint.  */
-         gdb::observers::breakpoint_modified.notify (b);
+         notify_breakpoint_modified (b);
 
          if (!disabled_shlib_breaks)
            {
@@ -7647,7 +8052,7 @@ disable_breakpoints_in_unloaded_shlib (struct so_list *solib)
                         "for unloaded shared library \"%s\""),
                       solib->so_name);
            }
-         disabled_shlib_breaks = 1;
+         disabled_shlib_breaks = true;
        }
     }
 }
@@ -7677,457 +8082,88 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
       || (objfile->flags & OBJF_USERLOADED) == 0)
     return;
 
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      int bp_modified = 0;
+      bool bp_modified = false;
 
-      if (!is_breakpoint (b) && !is_tracepoint (b))
+      if (!is_breakpoint (&b) && !is_tracepoint (&b))
        continue;
 
-      for (bp_location *loc : b->locations ())
+      for (bp_location &loc : b.locations ())
        {
-         CORE_ADDR loc_addr = loc->address;
+         CORE_ADDR loc_addr = loc.address;
 
-         if (loc->loc_type != bp_loc_hardware_breakpoint
-             && loc->loc_type != bp_loc_software_breakpoint)
+         if (loc.loc_type != bp_loc_hardware_breakpoint
+             && loc.loc_type != bp_loc_software_breakpoint)
            continue;
 
-         if (loc->shlib_disabled != 0)
+         if (loc.shlib_disabled != 0)
            continue;
 
-         if (objfile->pspace != loc->pspace)
+         if (objfile->pspace != loc.pspace)
            continue;
 
-         if (loc->loc_type != bp_loc_hardware_breakpoint
-             && loc->loc_type != bp_loc_software_breakpoint)
+         if (loc.loc_type != bp_loc_hardware_breakpoint
+             && loc.loc_type != bp_loc_software_breakpoint)
            continue;
 
          if (is_addr_in_objfile (loc_addr, objfile))
            {
-             loc->shlib_disabled = 1;
+             loc.shlib_disabled = 1;
              /* At this point, we don't know whether the object was
                 unmapped from the inferior or not, so leave the
                 inserted flag alone.  We'll handle failure to
                 uninsert quietly, in case the object was indeed
                 unmapped.  */
 
-             mark_breakpoint_location_modified (loc);
+             mark_breakpoint_location_modified (&loc);
 
-             bp_modified = 1;
+             bp_modified = true;
            }
        }
 
       if (bp_modified)
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
     }
 }
 
-/* FORK & VFORK catchpoints.  */
-
-/* An instance of this type is used to represent a fork or vfork
-   catchpoint.  A breakpoint is really of this type iff its ops pointer points
-   to CATCH_FORK_BREAKPOINT_OPS.  */
-
-struct fork_catchpoint : public breakpoint
-{
-  /* True if the breakpoint is for vfork, false for fork.  */
-  bool is_vfork;
-
-  /* Process id of a child process whose forking triggered this
-     catchpoint.  This field is only valid immediately after this
-     catchpoint has triggered.  */
-  ptid_t forked_inferior_pid;
-};
-
-/* Implement the "insert" breakpoint_ops method for fork
-   catchpoints.  */
-
-static int
-insert_catch_fork (struct bp_location *bl)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) bl->owner;
-
-  if (c->is_vfork)
-    return target_insert_vfork_catchpoint (inferior_ptid.pid ());
-  else
-    return target_insert_fork_catchpoint (inferior_ptid.pid ());
-}
-
-/* Implement the "remove" breakpoint_ops method for fork
-   catchpoints.  */
-
-static int
-remove_catch_fork (struct bp_location *bl, enum remove_bp_reason reason)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) bl->owner;
-
-  if (c->is_vfork)
-    return target_remove_vfork_catchpoint (inferior_ptid.pid ());
-  else
-    return target_remove_fork_catchpoint (inferior_ptid.pid ());
-}
-
-/* Implement the "breakpoint_hit" breakpoint_ops method for fork
-   catchpoints.  */
-
-static int
-breakpoint_hit_catch_fork (const struct bp_location *bl,
-                          const address_space *aspace, CORE_ADDR bp_addr,
-                          const target_waitstatus &ws)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) bl->owner;
-
-  if (ws.kind () != (c->is_vfork
-                    ? TARGET_WAITKIND_VFORKED
-                    : TARGET_WAITKIND_FORKED))
-    return 0;
-
-  c->forked_inferior_pid = ws.child_ptid ();
-  return 1;
-}
-
-/* Implement the "print_it" breakpoint_ops method for fork
-   catchpoints.  */
-
-static enum print_stop_action
-print_it_catch_fork (bpstat *bs)
-{
-  struct ui_out *uiout = current_uiout;
-  struct breakpoint *b = bs->breakpoint_at;
-  struct fork_catchpoint *c = (struct fork_catchpoint *) bs->breakpoint_at;
-
-  annotate_catchpoint (b->number);
-  maybe_print_thread_hit_breakpoint (uiout);
-  if (b->disposition == disp_del)
-    uiout->text ("Temporary catchpoint ");
-  else
-    uiout->text ("Catchpoint ");
-  if (uiout->is_mi_like_p ())
-    {
-      uiout->field_string ("reason",
-                          async_reason_lookup (c->is_vfork
-                                               ? EXEC_ASYNC_VFORK
-                                               : EXEC_ASYNC_FORK));
-      uiout->field_string ("disp", bpdisp_text (b->disposition));
-    }
-  uiout->field_signed ("bkptno", b->number);
-  if (c->is_vfork)
-    uiout->text (" (vforked process ");
-  else
-    uiout->text (" (forked process ");
-  uiout->field_signed ("newpid", c->forked_inferior_pid.pid ());
-  uiout->text ("), ");
-  return PRINT_SRC_AND_LOC;
-}
-
-/* Implement the "print_one" breakpoint_ops method for fork
-   catchpoints.  */
-
-static void
-print_one_catch_fork (struct breakpoint *b, struct bp_location **last_loc)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) b;
-  struct value_print_options opts;
-  struct ui_out *uiout = current_uiout;
-
-  get_user_print_options (&opts);
-
-  /* Field 4, the address, is omitted (which makes the columns not
-     line up too nicely with the headers, but the effect is relatively
-     readable).  */
-  if (opts.addressprint)
-    uiout->field_skip ("addr");
-  annotate_field (5);
-  const char *name = c->is_vfork ? "vfork" : "fork";
-  uiout->text (name);
-  if (c->forked_inferior_pid != null_ptid)
-    {
-      uiout->text (", process ");
-      uiout->field_signed ("what", c->forked_inferior_pid.pid ());
-      uiout->spaces (1);
-    }
-
-  if (uiout->is_mi_like_p ())
-    uiout->field_string ("catch-type", name);
-}
-
-/* Implement the "print_mention" breakpoint_ops method for fork
-   catchpoints.  */
-
-static void
-print_mention_catch_fork (struct breakpoint *b)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) b;
-  printf_filtered (_("Catchpoint %d (%s)"), c->number,
-                  c->is_vfork ? "vfork" : "fork");
-}
-
-/* Implement the "print_recreate" breakpoint_ops method for fork
-   catchpoints.  */
-
-static void
-print_recreate_catch_fork (struct breakpoint *b, struct ui_file *fp)
-{
-  struct fork_catchpoint *c = (struct fork_catchpoint *) b;
-  fprintf_unfiltered (fp, "catch %s",
-                     c->is_vfork ? "vfork" : "fork");
-  print_recreate_thread (b, fp);
-}
-
-/* The breakpoint_ops structure to be used in fork catchpoints.  */
-
-static struct breakpoint_ops catch_fork_breakpoint_ops;
-
-/* An instance of this type is used to represent an solib catchpoint.
-   A breakpoint is really of this type iff its ops pointer points to
-   CATCH_SOLIB_BREAKPOINT_OPS.  */
-
-struct solib_catchpoint : public breakpoint
-{
-  /* True for "catch load", false for "catch unload".  */
-  bool is_load;
-
-  /* Regular expression to match, if any.  COMPILED is only valid when
-     REGEX is non-NULL.  */
-  gdb::unique_xmalloc_ptr<char> regex;
-  std::unique_ptr<compiled_regex> compiled;
-};
-
-static int
-insert_catch_solib (struct bp_location *ignore)
-{
-  return 0;
-}
-
-static int
-remove_catch_solib (struct bp_location *ignore, enum remove_bp_reason reason)
-{
-  return 0;
-}
-
-static int
-breakpoint_hit_catch_solib (const struct bp_location *bl,
-                           const address_space *aspace,
-                           CORE_ADDR bp_addr,
-                           const target_waitstatus &ws)
-{
-  struct solib_catchpoint *self = (struct solib_catchpoint *) bl->owner;
-
-  if (ws.kind () == TARGET_WAITKIND_LOADED)
-    return 1;
-
-  for (breakpoint *other : all_breakpoints ())
-    {
-      if (other == bl->owner)
-       continue;
-
-      if (other->type != bp_shlib_event)
-       continue;
-
-      if (self->pspace != NULL && other->pspace != self->pspace)
-       continue;
-
-      for (bp_location *other_bl : other->locations ())
-       {
-         if (other->ops->breakpoint_hit (other_bl, aspace, bp_addr, ws))
-           return 1;
-       }
-    }
-
-  return 0;
-}
-
-static void
-check_status_catch_solib (struct bpstat *bs)
-{
-  struct solib_catchpoint *self
-    = (struct solib_catchpoint *) bs->breakpoint_at;
-
-  if (self->is_load)
-    {
-      for (so_list *iter : current_program_space->added_solibs)
-       {
-         if (!self->regex
-             || self->compiled->exec (iter->so_name, 0, NULL, 0) == 0)
-           return;
-       }
-    }
-  else
-    {
-      for (const std::string &iter : current_program_space->deleted_solibs)
-       {
-         if (!self->regex
-             || self->compiled->exec (iter.c_str (), 0, NULL, 0) == 0)
-           return;
-       }
-    }
-
-  bs->stop = 0;
-  bs->print_it = print_it_noop;
-}
-
-static enum print_stop_action
-print_it_catch_solib (bpstat *bs)
-{
-  struct breakpoint *b = bs->breakpoint_at;
-  struct ui_out *uiout = current_uiout;
-
-  annotate_catchpoint (b->number);
-  maybe_print_thread_hit_breakpoint (uiout);
-  if (b->disposition == disp_del)
-    uiout->text ("Temporary catchpoint ");
-  else
-    uiout->text ("Catchpoint ");
-  uiout->field_signed ("bkptno", b->number);
-  uiout->text ("\n");
-  if (uiout->is_mi_like_p ())
-    uiout->field_string ("disp", bpdisp_text (b->disposition));
-  print_solib_event (1);
-  return PRINT_SRC_AND_LOC;
-}
-
-static void
-print_one_catch_solib (struct breakpoint *b, struct bp_location **locs)
-{
-  struct solib_catchpoint *self = (struct solib_catchpoint *) b;
-  struct value_print_options opts;
-  struct ui_out *uiout = current_uiout;
-
-  get_user_print_options (&opts);
-  /* Field 4, the address, is omitted (which makes the columns not
-     line up too nicely with the headers, but the effect is relatively
-     readable).  */
-  if (opts.addressprint)
-    {
-      annotate_field (4);
-      uiout->field_skip ("addr");
-    }
-
-  std::string msg;
-  annotate_field (5);
-  if (self->is_load)
-    {
-      if (self->regex)
-       msg = string_printf (_("load of library matching %s"),
-                            self->regex.get ());
-      else
-       msg = _("load of library");
-    }
-  else
-    {
-      if (self->regex)
-       msg = string_printf (_("unload of library matching %s"),
-                            self->regex.get ());
-      else
-       msg = _("unload of library");
-    }
-  uiout->field_string ("what", msg);
-
-  if (uiout->is_mi_like_p ())
-    uiout->field_string ("catch-type", self->is_load ? "load" : "unload");
-}
-
-static void
-print_mention_catch_solib (struct breakpoint *b)
-{
-  struct solib_catchpoint *self = (struct solib_catchpoint *) b;
-
-  printf_filtered (_("Catchpoint %d (%s)"), b->number,
-                  self->is_load ? "load" : "unload");
-}
-
-static void
-print_recreate_catch_solib (struct breakpoint *b, struct ui_file *fp)
-{
-  struct solib_catchpoint *self = (struct solib_catchpoint *) b;
-
-  fprintf_unfiltered (fp, "%s %s",
-                     b->disposition == disp_del ? "tcatch" : "catch",
-                     self->is_load ? "load" : "unload");
-  if (self->regex)
-    fprintf_unfiltered (fp, " %s", self->regex.get ());
-  fprintf_unfiltered (fp, "\n");
-}
-
-static struct breakpoint_ops catch_solib_breakpoint_ops;
-
 /* See breakpoint.h.  */
 
-void
-add_solib_catchpoint (const char *arg, bool is_load, bool is_temp, bool enabled)
+breakpoint::breakpoint (struct gdbarch *gdbarch_, enum bptype bptype,
+                       bool temp, const char *cond_string_)
+  : type (bptype),
+    disposition (temp ? disp_del : disp_donttouch),
+    gdbarch (gdbarch_),
+    language (current_language->la_language),
+    input_radix (::input_radix),
+    cond_string (cond_string_ != nullptr
+                ? make_unique_xstrdup (cond_string_)
+                : nullptr),
+    related_breakpoint (this)
 {
-  struct gdbarch *gdbarch = get_current_arch ();
-
-  if (!arg)
-    arg = "";
-  arg = skip_spaces (arg);
-
-  std::unique_ptr<solib_catchpoint> c (new solib_catchpoint ());
-
-  if (*arg != '\0')
-    {
-      c->compiled.reset (new compiled_regex (arg, REG_NOSUB,
-                                            _("Invalid regexp")));
-      c->regex = make_unique_xstrdup (arg);
-    }
-
-  c->is_load = is_load;
-  init_catchpoint (c.get (), gdbarch, is_temp, NULL,
-                  &catch_solib_breakpoint_ops);
-
-  c->enable_state = enabled ? bp_enabled : bp_disabled;
-
-  install_breakpoint (0, std::move (c), 1);
 }
 
-/* A helper function that does all the work for "catch load" and
-   "catch unload".  */
+/* See breakpoint.h.  */
 
-static void
-catch_load_or_unload (const char *arg, int from_tty, int is_load,
-                     struct cmd_list_element *command)
+catchpoint::catchpoint (struct gdbarch *gdbarch, bool temp,
+                       const char *cond_string)
+  : breakpoint (gdbarch, bp_catchpoint, temp, cond_string)
 {
-  const int enabled = 1;
-  bool temp = command->context () == CATCH_TEMPORARY;
+  add_dummy_location (this, current_program_space);
 
-  add_solib_catchpoint (arg, is_load, temp, enabled);
+  pspace = current_program_space;
 }
 
-static void
-catch_load_command_1 (const char *arg, int from_tty,
-                     struct cmd_list_element *command)
-{
-  catch_load_or_unload (arg, from_tty, 1, command);
-}
+/* Notify interpreters and observers that breakpoint B was created.  */
 
 static void
-catch_unload_command_1 (const char *arg, int from_tty,
-                       struct cmd_list_element *command)
-{
-  catch_load_or_unload (arg, from_tty, 0, command);
-}
-
-/* See breakpoint.h.  */
-
-void
-init_catchpoint (struct breakpoint *b,
-                struct gdbarch *gdbarch, bool temp,
-                const char *cond_string,
-                const struct breakpoint_ops *ops)
+notify_breakpoint_created (breakpoint *b)
 {
-  symtab_and_line sal;
-  sal.pspace = current_program_space;
-
-  init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
-
-  if (cond_string == nullptr)
-    b->cond_string.reset ();
-  else
-    b->cond_string = make_unique_xstrdup (cond_string);
-  b->disposition = temp ? disp_del : disp_donttouch;
+  interps_notify_breakpoint_created (b);
+  gdb::observers::breakpoint_created.notify (b);
 }
 
-void
+breakpoint *
 install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_gll)
 {
   breakpoint *b = add_to_breakpoint_chain (std::move (arg));
@@ -8136,150 +8172,27 @@ install_breakpoint (int internal, std::unique_ptr<breakpoint> &&arg, int update_
     set_tracepoint_count (breakpoint_count);
   if (!internal)
     mention (b);
-  gdb::observers::breakpoint_created.notify (b);
+
+  notify_breakpoint_created (b);
 
   if (update_gll)
     update_global_location_list (UGLL_MAY_INSERT);
-}
-
-static void
-create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch,
-                                   bool temp, const char *cond_string,
-                                   bool is_vfork)
-{
-  std::unique_ptr<fork_catchpoint> c (new fork_catchpoint ());
-
-  init_catchpoint (c.get (), gdbarch, temp, cond_string,
-                  &catch_fork_breakpoint_ops);
-  c->is_vfork = is_vfork;
-  c->forked_inferior_pid = null_ptid;
-
-  install_breakpoint (0, std::move (c), 1);
-}
-
-/* Exec catchpoints.  */
-
-/* An instance of this type is used to represent an exec catchpoint.
-   A breakpoint is really of this type iff its ops pointer points to
-   CATCH_EXEC_BREAKPOINT_OPS.  */
-
-struct exec_catchpoint : public breakpoint
-{
-  /* Filename of a program whose exec triggered this catchpoint.
-     This field is only valid immediately after this catchpoint has
-     triggered.  */
-  gdb::unique_xmalloc_ptr<char> exec_pathname;
-};
-
-static int
-insert_catch_exec (struct bp_location *bl)
-{
-  return target_insert_exec_catchpoint (inferior_ptid.pid ());
-}
-
-static int
-remove_catch_exec (struct bp_location *bl, enum remove_bp_reason reason)
-{
-  return target_remove_exec_catchpoint (inferior_ptid.pid ());
-}
-
-static int
-breakpoint_hit_catch_exec (const struct bp_location *bl,
-                          const address_space *aspace, CORE_ADDR bp_addr,
-                          const target_waitstatus &ws)
-{
-  struct exec_catchpoint *c = (struct exec_catchpoint *) bl->owner;
-
-  if (ws.kind () != TARGET_WAITKIND_EXECD)
-    return 0;
-
-  c->exec_pathname = make_unique_xstrdup (ws.execd_pathname ());
-  return 1;
-}
-
-static enum print_stop_action
-print_it_catch_exec (bpstat *bs)
-{
-  struct ui_out *uiout = current_uiout;
-  struct breakpoint *b = bs->breakpoint_at;
-  struct exec_catchpoint *c = (struct exec_catchpoint *) b;
-
-  annotate_catchpoint (b->number);
-  maybe_print_thread_hit_breakpoint (uiout);
-  if (b->disposition == disp_del)
-    uiout->text ("Temporary catchpoint ");
-  else
-    uiout->text ("Catchpoint ");
-  if (uiout->is_mi_like_p ())
-    {
-      uiout->field_string ("reason", async_reason_lookup (EXEC_ASYNC_EXEC));
-      uiout->field_string ("disp", bpdisp_text (b->disposition));
-    }
-  uiout->field_signed ("bkptno", b->number);
-  uiout->text (" (exec'd ");
-  uiout->field_string ("new-exec", c->exec_pathname.get ());
-  uiout->text ("), ");
-
-  return PRINT_SRC_AND_LOC;
-}
-
-static void
-print_one_catch_exec (struct breakpoint *b, struct bp_location **last_loc)
-{
-  struct exec_catchpoint *c = (struct exec_catchpoint *) b;
-  struct value_print_options opts;
-  struct ui_out *uiout = current_uiout;
 
-  get_user_print_options (&opts);
-
-  /* Field 4, the address, is omitted (which makes the columns
-     not line up too nicely with the headers, but the effect
-     is relatively readable).  */
-  if (opts.addressprint)
-    uiout->field_skip ("addr");
-  annotate_field (5);
-  uiout->text ("exec");
-  if (c->exec_pathname != NULL)
-    {
-      uiout->text (", program \"");
-      uiout->field_string ("what", c->exec_pathname.get ());
-      uiout->text ("\" ");
-    }
-
-  if (uiout->is_mi_like_p ())
-    uiout->field_string ("catch-type", "exec");
-}
-
-static void
-print_mention_catch_exec (struct breakpoint *b)
-{
-  printf_filtered (_("Catchpoint %d (exec)"), b->number);
-}
-
-/* Implement the "print_recreate" breakpoint_ops method for exec
-   catchpoints.  */
-
-static void
-print_recreate_catch_exec (struct breakpoint *b, struct ui_file *fp)
-{
-  fprintf_unfiltered (fp, "catch exec");
-  print_recreate_thread (b, fp);
+  return b;
 }
 
-static struct breakpoint_ops catch_exec_breakpoint_ops;
-
 static int
 hw_breakpoint_used_count (void)
 {
   int i = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
-      for (bp_location *bl : b->locations ())
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_hardware_breakpoint && breakpoint_enabled (&b))
+      for (bp_location &bl : b.locations ())
        {
          /* Special types of hardware breakpoints may use more than
             one register.  */
-         i += b->ops->resources_needed (bl);
+         i += b.resources_needed (&bl);
        }
 
   return i;
@@ -8296,11 +8209,11 @@ hw_watchpoint_use_count (struct breakpoint *b)
   if (!breakpoint_enabled (b))
     return 0;
 
-  for (bp_location *bl : b->locations ())
+  for (bp_location &bl : b->locations ())
     {
       /* Special types of hardware watchpoints may use more than
         one register.  */
-      i += b->ops->resources_needed (bl);
+      i += b->resources_needed (&bl);
     }
 
   return i;
@@ -8318,16 +8231,16 @@ hw_watchpoint_used_count_others (struct breakpoint *except,
   int i = 0;
 
   *other_type_used = 0;
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (b == except)
+      if (&b == except)
        continue;
-      if (!breakpoint_enabled (b))
+      if (!breakpoint_enabled (&b))
        continue;
 
-      if (b->type == type)
-       i += hw_watchpoint_use_count (b);
-      else if (is_hardware_watchpoint (b))
+      if (b.type == type)
+       i += hw_watchpoint_use_count (&b);
+      else if (is_hardware_watchpoint (&b))
        *other_type_used = 1;
     }
 
@@ -8337,10 +8250,10 @@ hw_watchpoint_used_count_others (struct breakpoint *except,
 void
 disable_watchpoints_before_interactive_call_start (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (is_watchpoint (b) && breakpoint_enabled (b))
+  for (breakpoint &b : all_breakpoints ())
+    if (is_watchpoint (&b) && breakpoint_enabled (&b))
       {
-       b->enable_state = bp_call_disabled;
+       b.enable_state = bp_call_disabled;
        update_global_location_list (UGLL_DONT_INSERT);
       }
 }
@@ -8348,10 +8261,10 @@ disable_watchpoints_before_interactive_call_start (void)
 void
 enable_watchpoints_after_interactive_call_stop (void)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (is_watchpoint (b) && b->enable_state == bp_call_disabled)
+  for (breakpoint &b : all_breakpoints ())
+    if (is_watchpoint (&b) && b.enable_state == bp_call_disabled)
       {
-       b->enable_state = bp_enabled;
+       b.enable_state = bp_enabled;
        update_global_location_list (UGLL_MAY_INSERT);
       }
 }
@@ -8370,24 +8283,19 @@ enable_breakpoints_after_startup (void)
   breakpoint_re_set ();
 }
 
-/* Create a new single-step breakpoint for thread THREAD, with no
-   locations.  */
+/* Allocate a new momentary breakpoint.  */
 
-static struct breakpoint *
-new_single_step_breakpoint (int thread, struct gdbarch *gdbarch)
+template<typename... Arg>
+static momentary_breakpoint *
+new_momentary_breakpoint (struct gdbarch *gdbarch, enum bptype type,
+                         Arg&&... args)
 {
-  std::unique_ptr<breakpoint> b (new breakpoint ());
-
-  init_raw_breakpoint_without_location (b.get (), gdbarch, bp_single_step,
-                                       &momentary_breakpoint_ops);
-
-  b->disposition = disp_donttouch;
-  b->frame_id = null_frame_id;
-
-  b->thread = thread;
-  gdb_assert (b->thread != 0);
-
-  return add_to_breakpoint_chain (std::move (b));
+  if (type == bp_longjmp || type == bp_exception)
+    return new longjmp_breakpoint (gdbarch, type,
+                                  std::forward<Arg> (args)...);
+  else
+    return new momentary_breakpoint (gdbarch, type,
+                                    std::forward<Arg> (args)...);
 }
 
 /* Set a momentary breakpoint of type TYPE at address specified by
@@ -8398,22 +8306,21 @@ breakpoint_up
 set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
                          struct frame_id frame_id, enum bptype type)
 {
-  struct breakpoint *b;
-
   /* If FRAME_ID is valid, it should be a real frame, not an inlined or
      tail-called one.  */
   gdb_assert (!frame_id_artificial_p (frame_id));
 
-  b = set_raw_breakpoint (gdbarch, sal, type, &momentary_breakpoint_ops);
-  b->enable_state = bp_enabled;
-  b->disposition = disp_donttouch;
-  b->frame_id = frame_id;
+  std::unique_ptr<momentary_breakpoint> b
+    (new_momentary_breakpoint (gdbarch, type, sal.pspace, frame_id,
+                              inferior_thread ()->global_num));
+
+  b->add_location (sal);
 
-  b->thread = inferior_thread ()->global_num;
+  breakpoint_up bp (add_to_breakpoint_chain (std::move (b)));
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
-  return breakpoint_up (b);
+  return bp;
 }
 
 /* Make a momentary breakpoint based on the master breakpoint ORIG.
@@ -8423,34 +8330,30 @@ set_momentary_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal,
 static struct breakpoint *
 momentary_breakpoint_from_master (struct breakpoint *orig,
                                  enum bptype type,
-                                 const struct breakpoint_ops *ops,
-                                 int loc_enabled)
-{
-  struct breakpoint *copy;
-
-  copy = set_raw_breakpoint_without_location (orig->gdbarch, type, ops);
-  copy->loc = allocate_bp_location (copy);
-  set_breakpoint_location_function (copy->loc);
-
-  copy->loc->gdbarch = orig->loc->gdbarch;
-  copy->loc->requested_address = orig->loc->requested_address;
-  copy->loc->address = orig->loc->address;
-  copy->loc->section = orig->loc->section;
-  copy->loc->pspace = orig->loc->pspace;
-  copy->loc->probe = orig->loc->probe;
-  copy->loc->line_number = orig->loc->line_number;
-  copy->loc->symtab = orig->loc->symtab;
-  copy->loc->enabled = loc_enabled;
-  copy->frame_id = orig->frame_id;
-  copy->thread = orig->thread;
-  copy->pspace = orig->pspace;
-
-  copy->enable_state = bp_enabled;
-  copy->disposition = disp_donttouch;
-  copy->number = internal_breakpoint_number--;
-
+                                 int loc_enabled,
+                                 int thread)
+{
+  std::unique_ptr<breakpoint> copy
+    (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
+                              orig->frame_id, thread));
+  const bp_location &orig_loc = orig->first_loc ();
+  bp_location *copy_loc = copy->allocate_location ();
+  copy->add_location (*copy_loc);
+  set_breakpoint_location_function (copy_loc);
+
+  copy_loc->gdbarch = orig_loc.gdbarch;
+  copy_loc->requested_address = orig_loc.requested_address;
+  copy_loc->address = orig_loc.address;
+  copy_loc->section = orig_loc.section;
+  copy_loc->pspace = orig_loc.pspace;
+  copy_loc->probe = orig_loc.probe;
+  copy_loc->line_number = orig_loc.line_number;
+  copy_loc->symtab = orig_loc.symtab;
+  copy_loc->enabled = loc_enabled;
+
+  breakpoint *b = add_to_breakpoint_chain (std::move (copy));
   update_global_location_list_nothrow (UGLL_DONT_INSERT);
-  return copy;
+  return b;
 }
 
 /* Make a deep copy of momentary breakpoint ORIG.  Returns NULL if
@@ -8463,7 +8366,8 @@ clone_momentary_breakpoint (struct breakpoint *orig)
   if (orig == NULL)
     return NULL;
 
-  return momentary_breakpoint_from_master (orig, orig->type, orig->ops, 0);
+  return momentary_breakpoint_from_master (orig, orig->type, 0,
+                                          orig->thread);
 }
 
 breakpoint_up
@@ -8484,9 +8388,9 @@ set_momentary_breakpoint_at_pc (struct gdbarch *gdbarch, CORE_ADDR pc,
 /* Tell the user we have just set a breakpoint B.  */
 
 static void
-mention (struct breakpoint *b)
+mention (const breakpoint *b)
 {
-  b->ops->print_mention (b);
+  b->print_mention ();
   current_uiout->text ("\n");
 }
 \f
@@ -8537,10 +8441,9 @@ handle_automatic_hardware_breakpoints (bp_location *bl)
              bl->loc_type = new_type;
              if (!said)
                {
-                 fprintf_filtered (gdb_stdout,
-                                   _("Note: automatically using "
-                                     "hardware breakpoints for "
-                                     "read-only addresses.\n"));
+                 gdb_printf (_("Note: automatically using "
+                               "hardware breakpoints for "
+                               "read-only addresses.\n"));
                  said = true;
                }
            }
@@ -8548,49 +8451,45 @@ handle_automatic_hardware_breakpoints (bp_location *bl)
     }
 }
 
-static struct bp_location *
-add_location_to_breakpoint (struct breakpoint *b,
-                           const struct symtab_and_line *sal)
+bp_location *
+code_breakpoint::add_location (const symtab_and_line &sal)
 {
-  struct bp_location *loc, **tmp;
   CORE_ADDR adjusted_address;
-  struct gdbarch *loc_gdbarch = get_sal_arch (*sal);
+  struct gdbarch *loc_gdbarch = get_sal_arch (sal);
 
   if (loc_gdbarch == NULL)
-    loc_gdbarch = b->gdbarch;
+    loc_gdbarch = gdbarch;
 
   /* Adjust the breakpoint's address prior to allocating a location.
-     Once we call allocate_bp_location(), that mostly uninitialized
+     Once we call allocate_location(), that mostly uninitialized
      location will be placed on the location chain.  Adjustment of the
      breakpoint may cause target_read_memory() to be called and we do
      not want its scan of the location chain to find a breakpoint and
      location that's only been partially initialized.  */
   adjusted_address = adjust_breakpoint_address (loc_gdbarch,
-                                               sal->pc, b->type);
+                                               sal.pc, type,
+                                               sal.pspace);
 
   /* Sort the locations by their ADDRESS.  */
-  loc = allocate_bp_location (b);
-  for (tmp = &(b->loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
-       tmp = &((*tmp)->next))
-    ;
-  loc->next = *tmp;
-  *tmp = loc;
-
-  loc->requested_address = sal->pc;
-  loc->address = adjusted_address;
-  loc->pspace = sal->pspace;
-  loc->probe.prob = sal->prob;
-  loc->probe.objfile = sal->objfile;
-  gdb_assert (loc->pspace != NULL);
-  loc->section = sal->section;
-  loc->gdbarch = loc_gdbarch;
-  loc->line_number = sal->line;
-  loc->symtab = sal->symtab;
-  loc->symbol = sal->symbol;
-  loc->msymbol = sal->msymbol;
-  loc->objfile = sal->objfile;
-
-  set_breakpoint_location_function (loc);
+  bp_location *new_loc = this->allocate_location ();
+
+  new_loc->requested_address = sal.pc;
+  new_loc->address = adjusted_address;
+  new_loc->pspace = sal.pspace;
+  new_loc->probe.prob = sal.prob;
+  new_loc->probe.objfile = sal.objfile;
+  gdb_assert (new_loc->pspace != NULL);
+  new_loc->section = sal.section;
+  new_loc->gdbarch = loc_gdbarch;
+  new_loc->line_number = sal.line;
+  new_loc->symtab = sal.symtab;
+  new_loc->symbol = sal.symbol;
+  new_loc->msymbol = sal.msymbol;
+  new_loc->objfile = sal.objfile;
+
+  breakpoint::add_location (*new_loc);
+
+  set_breakpoint_location_function (new_loc);
 
   /* While by definition, permanent breakpoints are already present in the
      code, we don't mark the location as inserted.  Normally one would expect
@@ -8605,10 +8504,10 @@ add_location_to_breakpoint (struct breakpoint *b,
      (If GDB later needs to continue execution past the permanent breakpoint,
      it manually increments the PC, thus avoiding executing the breakpoint
      instruction.)  */
-  if (bp_loc_is_permanent (loc))
-    loc->permanent = 1;
+  if (bp_loc_is_permanent (new_loc))
+    new_loc->permanent = 1;
 
-  return loc;
+  return new_loc;
 }
 \f
 
@@ -8684,8 +8583,7 @@ update_dprintf_command_list (struct breakpoint *b)
        }
     }
   else
-    internal_error (__FILE__, __LINE__,
-                   _("Invalid dprintf style."));
+    internal_error (_("Invalid dprintf style."));
 
   gdb_assert (printf_line != NULL);
 
@@ -8703,28 +8601,25 @@ static void
 update_dprintf_commands (const char *args, int from_tty,
                         struct cmd_list_element *c)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_dprintf)
-       update_dprintf_command_list (b);
-}
-
-/* Create a breakpoint with SAL as location.  Use LOCATION
-   as a description of the location, and COND_STRING
-   as condition expression.  If LOCATION is NULL then create an
-   "address location" from the address in the SAL.  */
-
-static void
-init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
-                    gdb::array_view<const symtab_and_line> sals,
-                    event_location_up &&location,
-                    gdb::unique_xmalloc_ptr<char> filter,
-                    gdb::unique_xmalloc_ptr<char> cond_string,
-                    gdb::unique_xmalloc_ptr<char> extra_string,
-                    enum bptype type, enum bpdisp disposition,
-                    int thread, int task, int ignore_count,
-                    const struct breakpoint_ops *ops, int from_tty,
-                    int enabled, int internal, unsigned flags,
-                    int display_canonical)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_dprintf)
+       update_dprintf_command_list (&b);
+}
+
+code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
+                                 enum bptype type_,
+                                 gdb::array_view<const symtab_and_line> sals,
+                                 location_spec_up &&locspec_,
+                                 gdb::unique_xmalloc_ptr<char> filter_,
+                                 gdb::unique_xmalloc_ptr<char> cond_string_,
+                                 gdb::unique_xmalloc_ptr<char> extra_string_,
+                                 enum bpdisp disposition_,
+                                 int thread_, int task_, int inferior_,
+                                 int ignore_count_,
+                                 int from_tty,
+                                 int enabled_, unsigned flags,
+                                 int display_canonical_)
+  : breakpoint (gdbarch_, type_)
 {
   int i;
 
@@ -8744,80 +8639,70 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
 
   gdb_assert (!sals.empty ());
 
-  for (const auto &sal : sals)
-    {
-      struct bp_location *loc;
+  /* At most one of thread, task, or inferior can be set on any breakpoint.  */
+  gdb_assert (((thread == -1 ? 0 : 1)
+              + (task == -1 ? 0 : 1)
+              + (inferior == -1 ? 0 : 1)) <= 1);
 
-      if (from_tty)
-       {
-         struct gdbarch *loc_gdbarch = get_sal_arch (sal);
-         if (!loc_gdbarch)
-           loc_gdbarch = gdbarch;
+  thread = thread_;
+  task = task_;
+  inferior = inferior_;
 
-         describe_other_breakpoints (loc_gdbarch,
-                                     sal.pspace, sal.pc, sal.section, thread);
-       }
+  cond_string = std::move (cond_string_);
+  extra_string = std::move (extra_string_);
+  ignore_count = ignore_count_;
+  enable_state = enabled_ ? bp_enabled : bp_disabled;
+  disposition = disposition_;
 
-      if (&sal == &sals[0])
-       {
-         init_raw_breakpoint (b, gdbarch, sal, type, ops);
-         b->thread = thread;
-         b->task = task;
-
-         b->cond_string = std::move (cond_string);
-         b->extra_string = std::move (extra_string);
-         b->ignore_count = ignore_count;
-         b->enable_state = enabled ? bp_enabled : bp_disabled;
-         b->disposition = disposition;
-
-         if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
-           b->loc->inserted = 1;
-
-         if (type == bp_static_tracepoint)
-           {
-             struct tracepoint *t = (struct tracepoint *) b;
-             struct static_tracepoint_marker marker;
-
-             if (strace_marker_p (b))
-               {
-                 /* We already know the marker exists, otherwise, we
-                    wouldn't see a sal for it.  */
-                 const char *p
-                   = &event_location_to_string (b->location.get ())[3];
-                 const char *endp;
+  if (type == bp_static_tracepoint
+      || type == bp_static_marker_tracepoint)
+    {
+      auto *t = gdb::checked_static_cast<struct tracepoint *> (this);
+      struct static_tracepoint_marker marker;
 
-                 p = skip_spaces (p);
+      if (strace_marker_p (this))
+       {
+         /* We already know the marker exists, otherwise, we wouldn't
+            see a sal for it.  */
+         const char *p = &locspec_->to_string ()[3];
+         const char *endp;
 
-                 endp = skip_to_space (p);
+         p = skip_spaces (p);
 
-                 t->static_trace_marker_id.assign (p, endp - p);
+         endp = skip_to_space (p);
 
-                 printf_filtered (_("Probed static tracepoint "
-                                    "marker \"%s\"\n"),
-                                  t->static_trace_marker_id.c_str ());
-               }
-             else if (target_static_tracepoint_marker_at (sal.pc, &marker))
-               {
-                 t->static_trace_marker_id = std::move (marker.str_id);
+         t->static_trace_marker_id.assign (p, endp - p);
 
-                 printf_filtered (_("Probed static tracepoint "
-                                    "marker \"%s\"\n"),
-                                  t->static_trace_marker_id.c_str ());
-               }
-             else
-               warning (_("Couldn't determine the static "
-                          "tracepoint marker to probe"));
-           }
+         gdb_printf (_("Probed static tracepoint marker \"%s\"\n"),
+                     t->static_trace_marker_id.c_str ());
+       }
+      else if (target_static_tracepoint_marker_at (sals[0].pc, &marker))
+       {
+         t->static_trace_marker_id = std::move (marker.str_id);
 
-         loc = b->loc;
+         gdb_printf (_("Probed static tracepoint marker \"%s\"\n"),
+                     t->static_trace_marker_id.c_str ());
        }
       else
+       warning (_("Couldn't determine the static tracepoint marker to probe"));
+    }
+
+  for (const auto &sal : sals)
+    {
+      if (from_tty)
        {
-         loc = add_location_to_breakpoint (b, &sal);
-         if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
-           loc->inserted = 1;
+         struct gdbarch *loc_gdbarch = get_sal_arch (sal);
+         if (loc_gdbarch == nullptr)
+           loc_gdbarch = gdbarch;
+
+         describe_other_breakpoints (loc_gdbarch,
+                                     sal.pspace, sal.pc, sal.section, thread);
        }
 
+      bp_location *new_loc = add_location (sal);
+      if ((flags & CREATE_BREAKPOINT_FLAGS_INSERTED) != 0)
+       new_loc->inserted = 1;
+
       /* Do not set breakpoint locations conditions yet.  As locations
         are inserted, they get sorted based on their addresses.  Let
         the list stabilize to have reliable location numbers.  */
@@ -8826,61 +8711,61 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
         command line, otherwise it's an error.  */
       if (type == bp_dprintf)
        {
-         if (b->extra_string)
-           update_dprintf_command_list (b);
+         if (extra_string != nullptr)
+           update_dprintf_command_list (this);
          else
            error (_("Format string required"));
        }
-      else if (b->extra_string)
-       error (_("Garbage '%s' at end of command"), b->extra_string.get ());
+      else if (extra_string != nullptr)
+       error (_("Garbage '%s' at end of command"), extra_string.get ());
     }
 
-
   /* The order of the locations is now stable.  Set the location
      condition using the location's number.  */
   int loc_num = 1;
-  for (bp_location *loc : b->locations ())
+  for (bp_location &bl : locations ())
     {
-      if (b->cond_string != nullptr)
-       set_breakpoint_location_condition (b->cond_string.get (), loc,
-                                          b->number, loc_num);
+      if (cond_string != nullptr)
+       set_breakpoint_location_condition (cond_string.get (), &bl,
+                                          number, loc_num);
 
       ++loc_num;
     }
 
-  b->display_canonical = display_canonical;
-  if (location != NULL)
-    b->location = std::move (location);
+  display_canonical = display_canonical_;
+  if (locspec_ != nullptr)
+    locspec = std::move (locspec_);
   else
-    b->location = new_address_location (b->loc->address, NULL, 0);
-  b->filter = std::move (filter);
+    locspec = new_address_location_spec (this->first_loc ().address, NULL, 0);
+  filter = std::move (filter_);
 }
 
 static void
 create_breakpoint_sal (struct gdbarch *gdbarch,
                       gdb::array_view<const symtab_and_line> sals,
-                      event_location_up &&location,
+                      location_spec_up &&locspec,
                       gdb::unique_xmalloc_ptr<char> filter,
                       gdb::unique_xmalloc_ptr<char> cond_string,
                       gdb::unique_xmalloc_ptr<char> extra_string,
                       enum bptype type, enum bpdisp disposition,
-                      int thread, int task, int ignore_count,
-                      const struct breakpoint_ops *ops, int from_tty,
+                      int thread, int task, int inferior, int ignore_count,
+                      int from_tty,
                       int enabled, int internal, unsigned flags,
                       int display_canonical)
 {
-  std::unique_ptr<breakpoint> b = new_breakpoint_from_type (type);
-
-  init_breakpoint_sal (b.get (), gdbarch,
-                      sals, std::move (location),
-                      std::move (filter),
-                      std::move (cond_string),
-                      std::move (extra_string),
-                      type, disposition,
-                      thread, task, ignore_count,
-                      ops, from_tty,
-                      enabled, internal, flags,
-                      display_canonical);
+  std::unique_ptr<code_breakpoint> b
+    = new_breakpoint_from_type (gdbarch,
+                               type,
+                               sals,
+                               std::move (locspec),
+                               std::move (filter),
+                               std::move (cond_string),
+                               std::move (extra_string),
+                               disposition,
+                               thread, task, inferior, ignore_count,
+                               from_tty,
+                               enabled, flags,
+                               display_canonical);
 
   install_breakpoint (internal, std::move (b), 0);
 }
@@ -8906,8 +8791,9 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
                        gdb::unique_xmalloc_ptr<char> cond_string,
                        gdb::unique_xmalloc_ptr<char> extra_string,
                        enum bptype type, enum bpdisp disposition,
-                       int thread, int task, int ignore_count,
-                       const struct breakpoint_ops *ops, int from_tty,
+                       int thread, int task, int inferior,
+                       int ignore_count,
+                       int from_tty,
                        int enabled, int internal, unsigned flags)
 {
   if (canonical->pre_expanded)
@@ -8917,41 +8803,42 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
     {
       /* Note that 'location' can be NULL in the case of a plain
         'break', without arguments.  */
-      event_location_up location
-       = (canonical->location != NULL
-          ? copy_event_location (canonical->location.get ()) : NULL);
+      location_spec_up locspec
+       = (canonical->locspec != nullptr
+          ? canonical->locspec->clone ()
+          : nullptr);
       gdb::unique_xmalloc_ptr<char> filter_string
        (lsal.canonical != NULL ? xstrdup (lsal.canonical) : NULL);
 
       create_breakpoint_sal (gdbarch, lsal.sals,
-                            std::move (location),
+                            std::move (locspec),
                             std::move (filter_string),
                             std::move (cond_string),
                             std::move (extra_string),
                             type, disposition,
-                            thread, task, ignore_count, ops,
+                            thread, task, inferior, ignore_count,
                             from_tty, enabled, internal, flags,
                             canonical->special_display);
     }
 }
 
-/* Parse LOCATION which is assumed to be a SAL specification possibly
+/* Parse LOCSPEC which is assumed to be a SAL specification possibly
    followed by conditionals.  On return, SALS contains an array of SAL
-   addresses found.  LOCATION points to the end of the SAL (for
-   linespec locations).
+   addresses found.  LOCSPEC points to the end of the SAL (for
+   linespec locspecs).
 
    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 (struct event_location *location,
+parse_breakpoint_sals (location_spec *locspec,
                       struct linespec_result *canonical)
 {
   struct symtab_and_line cursal;
 
-  if (event_location_type (location) == LINESPEC_LOCATION)
+  if (locspec->type () == LINESPEC_LOCATION_SPEC)
     {
-      const char *spec = get_linespec_location (location)->spec_string;
+      const char *spec = as_linespec_location_spec (locspec)->spec_string;
 
       if (spec == NULL)
        {
@@ -9001,15 +8888,15 @@ parse_breakpoint_sals (struct event_location *location,
     {
       const char *spec = NULL;
 
-      if (event_location_type (location) == LINESPEC_LOCATION)
-       spec = get_linespec_location (location)->spec_string;
+      if (locspec->type () == LINESPEC_LOCATION_SPEC)
+       spec = as_linespec_location_spec (locspec)->spec_string;
 
       if (!cursal.symtab
          || (spec != NULL
              && strchr ("+-", spec[0]) != NULL
              && spec[1] != '['))
        {
-         decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
+         decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, NULL,
                            get_last_displayed_symtab (),
                            get_last_displayed_line (),
                            canonical, NULL, NULL);
@@ -9017,7 +8904,7 @@ parse_breakpoint_sals (struct event_location *location,
        }
     }
 
-  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, NULL,
+  decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, NULL,
                    cursal.symtab, cursal.line, canonical, NULL, NULL);
 }
 
@@ -9059,22 +8946,27 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
     }
 }
 
-/* Given TOK, a string specification of condition and thread, as
-   accepted by the 'break' command, extract the condition
-   string and thread number and set *COND_STRING and *THREAD.
-   PC identifies the context at which the condition should be parsed.
-   If no condition is found, *COND_STRING is set to NULL.
-   If no thread is found, *THREAD is set to -1.  */
+/* Given TOK, a string specification of condition and thread, as accepted
+   by the 'break' command, extract the condition string into *COND_STRING.
+   If no condition string is found then *COND_STRING is set to nullptr.
+
+   If the breakpoint specification has an associated thread, task, or
+   inferior, these are extracted into *THREAD, *TASK, and *INFERIOR
+   respectively, otherwise these arguments are set to -1 (for THREAD and
+   INFERIOR) or 0 (for TASK).
+
+   PC identifies the context at which the condition should be parsed.  */
 
 static void
 find_condition_and_thread (const char *tok, CORE_ADDR pc,
                           gdb::unique_xmalloc_ptr<char> *cond_string,
-                          int *thread, int *task,
+                          int *thread, int *inferior, int *task,
                           gdb::unique_xmalloc_ptr<char> *rest)
 {
   cond_string->reset ();
   *thread = -1;
-  *task = 0;
+  *inferior = -1;
+  *task = -1;
   rest->reset ();
   bool force = false;
 
@@ -9090,7 +8982,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
       if ((*tok == '"' || *tok == ',') && rest)
        {
          rest->reset (savestring (tok, strlen (tok)));
-         return;
+         break;
        }
 
       end_tok = skip_to_space (tok);
@@ -9124,6 +9016,15 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
          const char *tmptok;
          struct thread_info *thr;
 
+         if (*thread != -1)
+           error(_("You can specify only one thread."));
+
+         if (*task != -1)
+           error (_("You can specify only one of thread or task."));
+
+         if (*inferior != -1)
+           error (_("You can specify only one of inferior or thread."));
+
          tok = end_tok + 1;
          thr = parse_thread_id (tok, &tmptok);
          if (tok == tmptok)
@@ -9131,10 +9032,39 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
          *thread = thr->global_num;
          tok = tmptok;
        }
+      else if (toklen >= 1 && strncmp (tok, "inferior", toklen) == 0)
+       {
+         if (*inferior != -1)
+           error(_("You can specify only one inferior."));
+
+         if (*task != -1)
+           error (_("You can specify only one of inferior or task."));
+
+         if (*thread != -1)
+           error (_("You can specify only one of inferior or thread."));
+
+         char *tmptok;
+         tok = end_tok + 1;
+         *inferior = strtol (tok, &tmptok, 0);
+         if (tok == tmptok)
+           error (_("Junk after inferior keyword."));
+         if (!valid_global_inferior_id (*inferior))
+           error (_("Unknown inferior number %d."), *inferior);
+         tok = tmptok;
+       }
       else if (toklen >= 1 && strncmp (tok, "task", toklen) == 0)
        {
          char *tmptok;
 
+         if (*task != -1)
+           error(_("You can specify only one task."));
+
+         if (*thread != -1)
+           error (_("You can specify only one of thread or task."));
+
+         if (*inferior != -1)
+           error (_("You can specify only one of inferior or task."));
+
          tok = end_tok + 1;
          *task = strtol (tok, &tmptok, 0);
          if (tok == tmptok)
@@ -9146,7 +9076,7 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc,
       else if (rest)
        {
          rest->reset (savestring (tok, strlen (tok)));
-         return;
+         break;
        }
       else
        error (_("Junk at end of arguments."));
@@ -9162,15 +9092,16 @@ static void
 find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
                                    const char *input,
                                    gdb::unique_xmalloc_ptr<char> *cond_string,
-                                   int *thread, int *task,
+                                   int *thread, int *inferior, int *task,
                                    gdb::unique_xmalloc_ptr<char> *rest)
 {
   int num_failures = 0;
   for (auto &sal : sals)
     {
       gdb::unique_xmalloc_ptr<char> cond;
-      int thread_id = 0;
-      int task_id = 0;
+      int thread_id = -1;
+      int inferior_id = -1;
+      int task_id = -1;
       gdb::unique_xmalloc_ptr<char> remaining;
 
       /* Here we want to parse 'arg' to separate condition from thread
@@ -9182,9 +9113,16 @@ find_condition_and_thread_for_sals (const std::vector<symtab_and_line> &sals,
       try
        {
          find_condition_and_thread (input, sal.pc, &cond, &thread_id,
-                                    &task_id, &remaining);
+                                    &inferior_id, &task_id, &remaining);
          *cond_string = std::move (cond);
+         /* A value of -1 indicates that these fields are unset.  At most
+            one of these fields should be set (to a value other than -1)
+            at this point.  */
+         gdb_assert (((thread_id == -1 ? 1 : 0)
+                      + (task_id == -1 ? 1 : 0)
+                      + (inferior_id == -1 ? 1 : 0)) >= 2);
          *thread = thread_id;
+         *inferior = inferior_id;
          *task = task_id;
          *rest = std::move (remaining);
          break;
@@ -9237,44 +9175,45 @@ decode_static_tracepoint_spec (const char **arg_p)
    according to IS_TRACEPOINT.  */
 
 static const struct breakpoint_ops *
-breakpoint_ops_for_event_location_type (enum event_location_type location_type,
-                                       bool is_tracepoint)
+breakpoint_ops_for_location_spec_type (enum location_spec_type locspec_type,
+                                      bool is_tracepoint)
 {
   if (is_tracepoint)
     {
-      if (location_type == PROBE_LOCATION)
+      if (locspec_type == PROBE_LOCATION_SPEC)
        return &tracepoint_probe_breakpoint_ops;
       else
-       return &tracepoint_breakpoint_ops;
+       return &code_breakpoint_ops;
     }
   else
     {
-      if (location_type == PROBE_LOCATION)
+      if (locspec_type == PROBE_LOCATION_SPEC)
        return &bkpt_probe_breakpoint_ops;
       else
-       return &bkpt_breakpoint_ops;
+       return &code_breakpoint_ops;
     }
 }
 
 /* See breakpoint.h.  */
 
 const struct breakpoint_ops *
-breakpoint_ops_for_event_location (const struct event_location *location,
-                                  bool is_tracepoint)
+breakpoint_ops_for_location_spec (const location_spec *locspec,
+                                 bool is_tracepoint)
 {
-  if (location != nullptr)
-    return breakpoint_ops_for_event_location_type
-      (event_location_type (location), is_tracepoint);
-  return is_tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
+  if (locspec != nullptr)
+    return (breakpoint_ops_for_location_spec_type
+           (locspec->type (), is_tracepoint));
+  return &code_breakpoint_ops;
 }
 
 /* See breakpoint.h.  */
 
 int
 create_breakpoint (struct gdbarch *gdbarch,
-                  struct event_location *location,
+                  location_spec *locspec,
                   const char *cond_string,
-                  int thread, const char *extra_string,
+                  int thread, int inferior,
+                  const char *extra_string,
                   bool force_condition, int parse_extra,
                   int tempflag, enum bptype type_wanted,
                   int ignore_count,
@@ -9284,10 +9223,14 @@ create_breakpoint (struct gdbarch *gdbarch,
                   unsigned flags)
 {
   struct linespec_result canonical;
-  int pending = 0;
-  int task = 0;
+  bool pending = false;
+  int task = -1;
   int prev_bkpt_count = breakpoint_count;
 
+  gdb_assert (thread == -1 || thread > 0);
+  gdb_assert (inferior == -1 || inferior > 0);
+  gdb_assert (thread == -1 || inferior == -1);
+
   gdb_assert (ops != NULL);
 
   /* If extra_string isn't useful, set it to NULL.  */
@@ -9296,7 +9239,7 @@ create_breakpoint (struct gdbarch *gdbarch,
 
   try
     {
-      ops->create_sals_from_location (location, &canonical, type_wanted);
+      ops->create_sals_from_location_spec (locspec, &canonical);
     }
   catch (const gdb_exception_error &e)
     {
@@ -9323,7 +9266,7 @@ 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.  */
-         pending = 1;
+         pending = true;
        }
       else
        throw;
@@ -9363,7 +9306,8 @@ create_breakpoint (struct gdbarch *gdbarch,
          const linespec_sals &lsal = canonical.lsals[0];
 
          find_condition_and_thread_for_sals (lsal.sals, extra_string,
-                                             &cond, &thread, &task, &rest);
+                                             &cond, &thread, &inferior,
+                                             &task, &rest);
          cond_string_copy = std::move (cond);
          extra_string_copy = std::move (rest);
        }
@@ -9413,15 +9357,14 @@ create_breakpoint (struct gdbarch *gdbarch,
                                   std::move (extra_string_copy),
                                   type_wanted,
                                   tempflag ? disp_del : disp_donttouch,
-                                  thread, task, ignore_count, ops,
+                                  thread, task, inferior, ignore_count,
                                   from_tty, enabled, internal, flags);
     }
   else
     {
-      std::unique_ptr <breakpoint> b = new_breakpoint_from_type (type_wanted);
-
-      init_raw_breakpoint_without_location (b.get (), gdbarch, type_wanted, ops);
-      b->location = copy_event_location (location);
+      std::unique_ptr <breakpoint> b = new_breakpoint_from_type (gdbarch,
+                                                                type_wanted);
+      b->locspec = locspec->clone ();
 
       if (parse_extra)
        b->cond_string = NULL;
@@ -9476,13 +9419,16 @@ break_command_1 (const char *arg, int flag, int from_tty)
                             ? bp_hardware_breakpoint
                             : bp_breakpoint);
 
-  event_location_up location = string_to_event_location (&arg, current_language);
-  const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
-    (location.get (), false /* is_tracepoint */);
+  location_spec_up locspec = string_to_location_spec (&arg, current_language);
+  const struct breakpoint_ops *ops
+    = breakpoint_ops_for_location_spec (locspec.get (),
+                                       false /* is_tracepoint */);
 
   create_breakpoint (get_current_arch (),
-                    location.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    locspec.get (),
+                    NULL,
+                    -1 /* thread */, -1 /* inferior */,
+                    arg, false, 1 /* parse arg */,
                     tempflag, type_wanted,
                     0 /* Ignore count */,
                     pending_break_support,
@@ -9520,15 +9466,13 @@ resolve_sal_pc (struct symtab_and_line *sal)
       struct symbol *sym;
 
       bv = blockvector_for_pc_sect (sal->pc, 0, &b,
-                                   SYMTAB_COMPUNIT (sal->symtab));
+                                   sal->symtab->compunit ());
       if (bv != NULL)
        {
-         sym = block_linkage_function (b);
+         sym = b->linkage_function ();
          if (sym != NULL)
-           {
-             fixup_symbol_section (sym, SYMTAB_OBJFILE (sal->symtab));
-             sal->section = sym->obj_section (SYMTAB_OBJFILE (sal->symtab));
-           }
+           sal->section
+             = sym->obj_section (sal->symtab->compunit ()->objfile ());
          else
            {
              /* It really is worthwhile to have the section, so we'll
@@ -9571,79 +9515,6 @@ thbreak_command (const char *arg, int from_tty)
   break_command_1 (arg, (BP_TEMPFLAG | BP_HARDWAREFLAG), from_tty);
 }
 
-static void
-stop_command (const char *arg, int from_tty)
-{
-  printf_filtered (_("Specify the type of breakpoint to set.\n\
-Usage: stop in <function | address>\n\
-       stop at <line>\n"));
-}
-
-static void
-stopin_command (const char *arg, int from_tty)
-{
-  int badInput = 0;
-
-  if (arg == NULL)
-    badInput = 1;
-  else if (*arg != '*')
-    {
-      const char *argptr = arg;
-      int hasColon = 0;
-
-      /* Look for a ':'.  If this is a line number specification, then
-        say it is bad, otherwise, it should be an address or
-        function/method name.  */
-      while (*argptr && !hasColon)
-       {
-         hasColon = (*argptr == ':');
-         argptr++;
-       }
-
-      if (hasColon)
-       badInput = (*argptr != ':');    /* Not a class::method */
-      else
-       badInput = isdigit (*arg);      /* a simple line number */
-    }
-
-  if (badInput)
-    printf_filtered (_("Usage: stop in <function | address>\n"));
-  else
-    break_command_1 (arg, 0, from_tty);
-}
-
-static void
-stopat_command (const char *arg, int from_tty)
-{
-  int badInput = 0;
-
-  if (arg == NULL || *arg == '*')      /* no line number */
-    badInput = 1;
-  else
-    {
-      const char *argptr = arg;
-      int hasColon = 0;
-
-      /* Look for a ':'.  If there is a '::' then get out, otherwise
-        it is probably a line number.  */
-      while (*argptr && !hasColon)
-       {
-         hasColon = (*argptr == ':');
-         argptr++;
-       }
-
-      if (hasColon)
-       badInput = (*argptr == ':');    /* we have class::method */
-      else
-       badInput = !isdigit (*arg);     /* not a line number */
-    }
-
-  if (badInput)
-    printf_filtered (_("Usage: stop at LINE\n"));
-  else
-    break_command_1 (arg, 0, from_tty);
-}
-
 /* The dynamic printf command is mostly like a regular breakpoint, but
    with a prewired command list consisting of a single output command,
    built from extra arguments supplied on the dprintf command
@@ -9652,7 +9523,7 @@ stopat_command (const char *arg, int from_tty)
 static void
 dprintf_command (const char *arg, int from_tty)
 {
-  event_location_up location = string_to_event_location (&arg, current_language);
+  location_spec_up locspec = string_to_location_spec (&arg, current_language);
 
   /* If non-NULL, ARG should have been advanced past the location;
      the next character must be ','.  */
@@ -9668,12 +9539,13 @@ dprintf_command (const char *arg, int from_tty)
     }
 
   create_breakpoint (get_current_arch (),
-                    location.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    locspec.get (),
+                    NULL, -1, -1,
+                    arg, false, 1 /* parse arg */,
                     0, bp_dprintf,
                     0 /* Ignore count */,
                     pending_break_support,
-                    &dprintf_breakpoint_ops,
+                    &code_breakpoint_ops,
                     from_tty,
                     1 /* enabled */,
                     0 /* internal */,
@@ -9686,14 +9558,13 @@ agent_printf_command (const char *arg, int from_tty)
   error (_("May only run agent-printf on the target"));
 }
 
-/* Implement the "breakpoint_hit" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "breakpoint_hit" method for ranged breakpoints.  */
 
-static int
-breakpoint_hit_ranged_breakpoint (const struct bp_location *bl,
-                                 const address_space *aspace,
-                                 CORE_ADDR bp_addr,
-                                 const target_waitstatus &ws)
+int
+ranged_breakpoint::breakpoint_hit (const struct bp_location *bl,
+                                  const address_space *aspace,
+                                  CORE_ADDR bp_addr,
+                                  const target_waitstatus &ws)
 {
   if (ws.kind () != TARGET_WAITKIND_STOPPED
       || ws.sig () != GDB_SIGNAL_TRAP)
@@ -9703,35 +9574,31 @@ breakpoint_hit_ranged_breakpoint (const struct bp_location *bl,
                                         bl->length, aspace, bp_addr);
 }
 
-/* Implement the "resources_needed" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "resources_needed" method for ranged breakpoints.  */
 
-static int
-resources_needed_ranged_breakpoint (const struct bp_location *bl)
+int
+ranged_breakpoint::resources_needed (const struct bp_location *bl)
 {
   return target_ranged_break_num_registers ();
 }
 
-/* Implement the "print_it" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "print_it" method for ranged breakpoints.  */
 
-static enum print_stop_action
-print_it_ranged_breakpoint (bpstat *bs)
+enum print_stop_action
+ranged_breakpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b = bs->breakpoint_at;
-  struct bp_location *bl = b->loc;
   struct ui_out *uiout = current_uiout;
 
-  gdb_assert (b->type == bp_hardware_breakpoint);
+  gdb_assert (type == bp_hardware_breakpoint);
 
   /* Ranged breakpoints have only one location.  */
-  gdb_assert (bl && bl->next == NULL);
+  gdb_assert (this->has_single_location ());
 
-  annotate_breakpoint (b->number);
+  annotate_breakpoint (number);
 
   maybe_print_thread_hit_breakpoint (uiout);
 
-  if (b->disposition == disp_del)
+  if (disposition == disp_del)
     uiout->text ("Temporary ranged breakpoint ");
   else
     uiout->text ("Ranged breakpoint ");
@@ -9739,96 +9606,84 @@ print_it_ranged_breakpoint (bpstat *bs)
     {
       uiout->field_string ("reason",
                      async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
-      uiout->field_string ("disp", bpdisp_text (b->disposition));
+      uiout->field_string ("disp", bpdisp_text (disposition));
     }
-  uiout->field_signed ("bkptno", b->number);
+  print_num_locno (bs, uiout);
   uiout->text (", ");
 
   return PRINT_SRC_AND_LOC;
 }
 
-/* Implement the "print_one" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "print_one" method for ranged breakpoints.  */
 
-static void
-print_one_ranged_breakpoint (struct breakpoint *b,
-                            struct bp_location **last_loc)
+bool
+ranged_breakpoint::print_one (const bp_location **last_loc) const
 {
-  struct bp_location *bl = b->loc;
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
 
   /* Ranged breakpoints have only one location.  */
-  gdb_assert (bl && bl->next == NULL);
+  gdb_assert (this->has_single_location ());
 
   get_user_print_options (&opts);
 
   if (opts.addressprint)
     /* We don't print the address range here, it will be printed later
-       by print_one_detail_ranged_breakpoint.  */
+       by ranged_breakpoint::print_one_detail.  */
     uiout->field_skip ("addr");
   annotate_field (5);
-  print_breakpoint_location (b, bl);
-  *last_loc = bl;
+  print_breakpoint_location (this, &this->first_loc ());
+  *last_loc = &this->first_loc ();
+
+  return true;
 }
 
-/* Implement the "print_one_detail" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "print_one_detail" method for ranged breakpoints.  */
 
-static void
-print_one_detail_ranged_breakpoint (const struct breakpoint *b,
-                                   struct ui_out *uiout)
+void
+ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
 {
   CORE_ADDR address_start, address_end;
-  struct bp_location *bl = b->loc;
+  const bp_location &bl = this->first_loc ();
   string_file stb;
 
-  gdb_assert (bl);
-
-  address_start = bl->address;
-  address_end = address_start + bl->length - 1;
+  address_start = bl.address;
+  address_end = address_start + bl.length - 1;
 
   uiout->text ("\taddress range: ");
   stb.printf ("[%s, %s]",
-             print_core_address (bl->gdbarch, address_start),
-             print_core_address (bl->gdbarch, address_end));
+             print_core_address (bl.gdbarch, address_start),
+             print_core_address (bl.gdbarch, address_end));
   uiout->field_stream ("addr", stb);
   uiout->text ("\n");
 }
 
-/* Implement the "print_mention" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "print_mention" method for ranged breakpoints.  */
 
-static void
-print_mention_ranged_breakpoint (struct breakpoint *b)
+void
+ranged_breakpoint::print_mention () const
 {
-  struct bp_location *bl = b->loc;
+  const bp_location &bl = this->first_loc ();
   struct ui_out *uiout = current_uiout;
 
-  gdb_assert (bl);
-  gdb_assert (b->type == bp_hardware_breakpoint);
+  gdb_assert (type == bp_hardware_breakpoint);
 
   uiout->message (_("Hardware assisted ranged breakpoint %d from %s to %s."),
-                 b->number, paddress (bl->gdbarch, bl->address),
-                 paddress (bl->gdbarch, bl->address + bl->length - 1));
+                 number, paddress (bl.gdbarch, bl.address),
+                 paddress (bl.gdbarch, bl.address + bl.length - 1));
 }
 
-/* Implement the "print_recreate" breakpoint_ops method for
-   ranged breakpoints.  */
+/* Implement the "print_recreate" method for ranged breakpoints.  */
 
-static void
-print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
+void
+ranged_breakpoint::print_recreate (struct ui_file *fp) const
 {
-  fprintf_unfiltered (fp, "break-range %s, %s",
-                     event_location_to_string (b->location.get ()),
-                     event_location_to_string (b->location_range_end.get ()));
-  print_recreate_thread (b, fp);
+  gdb_printf (fp, "break-range %s, %s",
+             locspec->to_string (),
+             locspec_range_end->to_string ());
+  print_recreate_thread (fp);
 }
 
-/* The breakpoint_ops structure to be used in ranged breakpoints.  */
-
-static struct breakpoint_ops ranged_breakpoint_ops;
-
 /* Find the address where the end of the breakpoint range should be
    placed, given the SAL of the end of the range.  This is so that if
    the user provides a line number, the end of the range is set to the
@@ -9868,7 +9723,6 @@ break_range_command (const char *arg, int from_tty)
   struct linespec_result canonical_start, canonical_end;
   int bp_count, can_use_bp, length;
   CORE_ADDR end;
-  struct breakpoint *b;
 
   /* We don't support software ranged breakpoints.  */
   if (target_ranged_break_num_registers () < 0)
@@ -9886,9 +9740,9 @@ break_range_command (const char *arg, int from_tty)
     error(_("No address range specified."));
 
   arg_start = arg;
-  event_location_up start_location = string_to_event_location (&arg,
-                                                              current_language);
-  parse_breakpoint_sals (start_location.get (), &canonical_start);
+  location_spec_up start_locspec
+    = string_to_location_spec (&arg, current_language);
+  parse_breakpoint_sals (start_locspec.get (), &canonical_start);
 
   if (arg[0] != ',')
     error (_("Too few arguments."));
@@ -9907,18 +9761,19 @@ break_range_command (const char *arg, int from_tty)
   arg++;       /* Skip the comma.  */
   arg = skip_spaces (arg);
 
-  /* Parse the end location.  */
+  /* Parse the end location specification.  */
 
   arg_start = arg;
 
   /* We call decode_line_full directly here instead of using
-     parse_breakpoint_sals because we need to specify the start location's
-     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.  */
-  event_location_up end_location = string_to_event_location (&arg,
-                                                            current_language);
-  decode_line_full (end_location.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
+     parse_breakpoint_sals because we need to specify the start
+     location spec's 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 spec.  */
+  location_spec_up end_locspec
+    = string_to_location_spec (&arg, current_language);
+  decode_line_full (end_locspec.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
                    sal_start.symtab, sal_start.line,
                    &canonical_end, NULL, NULL);
 
@@ -9949,19 +9804,15 @@ break_range_command (const char *arg, int from_tty)
       return;
     }
 
-  /* Now set up the breakpoint.  */
-  b = set_raw_breakpoint (get_current_arch (), sal_start,
-                         bp_hardware_breakpoint, &ranged_breakpoint_ops);
-  set_breakpoint_count (breakpoint_count + 1);
-  b->number = breakpoint_count;
-  b->disposition = disp_donttouch;
-  b->location = std::move (start_location);
-  b->location_range_end = std::move (end_location);
-  b->loc->length = length;
+  /* Now set up the breakpoint and install it.  */
 
-  mention (b);
-  gdb::observers::breakpoint_created.notify (b);
-  update_global_location_list (UGLL_MAY_INSERT);
+  std::unique_ptr<breakpoint> br
+    (new ranged_breakpoint (get_current_arch (),
+                           sal_start, length,
+                           std::move (start_locspec),
+                           std::move (end_locspec)));
+
+  install_breakpoint (false, std::move (br), true);
 }
 
 /*  Return non-zero if EXP is verified as constant.  Returned zero
@@ -9975,13 +9826,11 @@ watchpoint_exp_is_const (const struct expression *exp)
   return exp->op->constant_p ();
 }
 
-/* Implement the "re_set" breakpoint_ops method for watchpoints.  */
+/* Implement the "re_set" method for watchpoints.  */
 
-static void
-re_set_watchpoint (struct breakpoint *b)
+void
+watchpoint::re_set ()
 {
-  struct watchpoint *w = (struct watchpoint *) b;
-
   /* Watchpoint can be either on expression using entirely global
      variables, or it can be on local variables.
 
@@ -10003,44 +9852,42 @@ re_set_watchpoint (struct breakpoint *b)
      I'm not sure we'll ever be called in this case.
 
      If a local watchpoint's frame id is still valid, then
-     w->exp_valid_block is likewise valid, and we can safely use it.
+     exp_valid_block is likewise valid, and we can safely use it.
 
      Don't do anything about disabled watchpoints, since they will be
      reevaluated again when enabled.  */
-  update_watchpoint (w, 1 /* reparse */);
+  update_watchpoint (this, true /* reparse */);
 }
 
-/* Implement the "insert" breakpoint_ops method for hardware watchpoints.  */
+/* Implement the "insert" method for hardware watchpoints.  */
 
-static int
-insert_watchpoint (struct bp_location *bl)
+int
+watchpoint::insert_location (struct bp_location *bl)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-  int length = w->exact ? 1 : bl->length;
+  int length = exact ? 1 : bl->length;
 
   return target_insert_watchpoint (bl->address, length, bl->watchpoint_type,
-                                  w->cond_exp.get ());
+                                  cond_exp.get ());
 }
 
-/* Implement the "remove" breakpoint_ops method for hardware watchpoints.  */
+/* Implement the "remove" method for hardware watchpoints.  */
 
-static int
-remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
+int
+watchpoint::remove_location (struct bp_location *bl,
+                            enum remove_bp_reason reason)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-  int length = w->exact ? 1 : bl->length;
+  int length = exact ? 1 : bl->length;
 
   return target_remove_watchpoint (bl->address, length, bl->watchpoint_type,
-                                  w->cond_exp.get ());
+                                  cond_exp.get ());
 }
 
-static int
-breakpoint_hit_watchpoint (const struct bp_location *bl,
-                          const address_space *aspace, CORE_ADDR bp_addr,
-                          const target_waitstatus &ws)
+int
+watchpoint::breakpoint_hit (const struct bp_location *bl,
+                           const address_space *aspace, CORE_ADDR bp_addr,
+                           const target_waitstatus &ws)
 {
   struct breakpoint *b = bl->owner;
-  struct watchpoint *w = (struct watchpoint *) b;
 
   /* Continuable hardware watchpoints are treated as non-existent if the
      reason we stopped wasn't a hardware watchpoint (we didn't stop on
@@ -10049,75 +9896,67 @@ breakpoint_hit_watchpoint (const struct bp_location *bl,
      been defined.  Also skip watchpoints which we know did not trigger
      (did not match the data address).  */
   if (is_hardware_watchpoint (b)
-      && w->watchpoint_triggered == watch_triggered_no)
+      && watchpoint_triggered == watch_triggered_no)
     return 0;
 
   return 1;
 }
 
-static void
-check_status_watchpoint (bpstat *bs)
+void
+watchpoint::check_status (bpstat *bs)
 {
-  gdb_assert (is_watchpoint (bs->breakpoint_at));
-
   bpstat_check_watchpoint (bs);
 }
 
-/* Implement the "resources_needed" breakpoint_ops method for
-   hardware watchpoints.  */
+/* Implement the "resources_needed" method for hardware
+   watchpoints.  */
 
-static int
-resources_needed_watchpoint (const struct bp_location *bl)
+int
+watchpoint::resources_needed (const struct bp_location *bl)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-  int length = w->exact? 1 : bl->length;
+  int length = exact? 1 : bl->length;
 
   return target_region_ok_for_hw_watchpoint (bl->address, length);
 }
 
-/* Implement the "works_in_software_mode" breakpoint_ops method for
-   hardware watchpoints.  */
+/* Implement the "works_in_software_mode" method for hardware
+   watchpoints.  */
 
-static int
-works_in_software_mode_watchpoint (const struct breakpoint *b)
+bool
+watchpoint::works_in_software_mode () const
 {
   /* Read and access watchpoints only work with hardware support.  */
-  return b->type == bp_watchpoint || b->type == bp_hardware_watchpoint;
+  return type == bp_watchpoint || type == bp_hardware_watchpoint;
 }
 
-static enum print_stop_action
-print_it_watchpoint (bpstat *bs)
+enum print_stop_action
+watchpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b;
   enum print_stop_action result;
-  struct watchpoint *w;
   struct ui_out *uiout = current_uiout;
 
   gdb_assert (bs->bp_location_at != NULL);
 
-  b = bs->breakpoint_at;
-  w = (struct watchpoint *) b;
-
-  annotate_watchpoint (b->number);
+  annotate_watchpoint (this->number);
   maybe_print_thread_hit_breakpoint (uiout);
 
   string_file stb;
 
   gdb::optional<ui_out_emit_tuple> tuple_emitter;
-  switch (b->type)
+  switch (this->type)
     {
     case bp_watchpoint:
     case bp_hardware_watchpoint:
       if (uiout->is_mi_like_p ())
        uiout->field_string
          ("reason", async_reason_lookup (EXEC_ASYNC_WATCHPOINT_TRIGGER));
-      mention (b);
+      mention (this);
       tuple_emitter.emplace (uiout, "value");
       uiout->text ("\nOld value = ");
       watchpoint_value_print (bs->old_val.get (), &stb);
       uiout->field_stream ("old", stb);
       uiout->text ("\nNew value = ");
-      watchpoint_value_print (w->val.get (), &stb);
+      watchpoint_value_print (val.get (), &stb);
       uiout->field_stream ("new", stb);
       uiout->text ("\n");
       /* More than one watchpoint may have been triggered.  */
@@ -10128,10 +9967,10 @@ print_it_watchpoint (bpstat *bs)
       if (uiout->is_mi_like_p ())
        uiout->field_string
          ("reason", async_reason_lookup (EXEC_ASYNC_READ_WATCHPOINT_TRIGGER));
-      mention (b);
+      mention (this);
       tuple_emitter.emplace (uiout, "value");
       uiout->text ("\nValue = ");
-      watchpoint_value_print (w->val.get (), &stb);
+      watchpoint_value_print (val.get (), &stb);
       uiout->field_stream ("value", stb);
       uiout->text ("\n");
       result = PRINT_UNKNOWN;
@@ -10144,7 +9983,7 @@ print_it_watchpoint (bpstat *bs)
            uiout->field_string
              ("reason",
               async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
-         mention (b);
+         mention (this);
          tuple_emitter.emplace (uiout, "value");
          uiout->text ("\nOld value = ");
          watchpoint_value_print (bs->old_val.get (), &stb);
@@ -10153,7 +9992,7 @@ print_it_watchpoint (bpstat *bs)
        }
       else
        {
-         mention (b);
+         mention (this);
          if (uiout->is_mi_like_p ())
            uiout->field_string
              ("reason",
@@ -10161,7 +10000,7 @@ print_it_watchpoint (bpstat *bs)
          tuple_emitter.emplace (uiout, "value");
          uiout->text ("\nValue = ");
        }
-      watchpoint_value_print (w->val.get (), &stb);
+      watchpoint_value_print (val.get (), &stb);
       uiout->field_stream ("new", stb);
       uiout->text ("\n");
       result = PRINT_UNKNOWN;
@@ -10173,17 +10012,15 @@ print_it_watchpoint (bpstat *bs)
   return result;
 }
 
-/* Implement the "print_mention" breakpoint_ops method for hardware
-   watchpoints.  */
+/* Implement the "print_mention" method for hardware watchpoints.  */
 
-static void
-print_mention_watchpoint (struct breakpoint *b)
+void
+watchpoint::print_mention () const
 {
-  struct watchpoint *w = (struct watchpoint *) b;
   struct ui_out *uiout = current_uiout;
   const char *tuple_name;
 
-  switch (b->type)
+  switch (type)
     {
     case bp_watchpoint:
       uiout->text ("Watchpoint ");
@@ -10202,123 +10039,120 @@ print_mention_watchpoint (struct breakpoint *b)
       tuple_name = "hw-awpt";
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("Invalid hardware watchpoint type."));
+      internal_error (_("Invalid hardware watchpoint type."));
     }
 
   ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
-  uiout->field_signed ("number", b->number);
+  uiout->field_signed ("number", number);
   uiout->text (": ");
-  uiout->field_string ("exp", w->exp_string.get ());
+  uiout->field_string ("exp", exp_string.get ());
 }
 
-/* Implement the "print_recreate" breakpoint_ops method for
-   watchpoints.  */
+/* Implement the "print_recreate" method for watchpoints.  */
 
-static void
-print_recreate_watchpoint (struct breakpoint *b, struct ui_file *fp)
+void
+watchpoint::print_recreate (struct ui_file *fp) const
 {
-  struct watchpoint *w = (struct watchpoint *) b;
-
-  switch (b->type)
+  switch (type)
     {
     case bp_watchpoint:
     case bp_hardware_watchpoint:
-      fprintf_unfiltered (fp, "watch");
+      gdb_printf (fp, "watch");
       break;
     case bp_read_watchpoint:
-      fprintf_unfiltered (fp, "rwatch");
+      gdb_printf (fp, "rwatch");
       break;
     case bp_access_watchpoint:
-      fprintf_unfiltered (fp, "awatch");
+      gdb_printf (fp, "awatch");
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("Invalid watchpoint type."));
+      internal_error (_("Invalid watchpoint type."));
     }
 
-  fprintf_unfiltered (fp, " %s", w->exp_string.get ());
-  print_recreate_thread (b, fp);
+  gdb_printf (fp, " %s", exp_string.get ());
+  print_recreate_thread (fp);
 }
 
-/* Implement the "explains_signal" breakpoint_ops method for
-   watchpoints.  */
+/* Implement the "explains_signal" method for watchpoints.  */
 
-static int
-explains_signal_watchpoint (struct breakpoint *b, enum gdb_signal sig)
+bool
+watchpoint::explains_signal (enum gdb_signal sig)
 {
   /* A software watchpoint cannot cause a signal other than
      GDB_SIGNAL_TRAP.  */
-  if (b->type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
-    return 0;
+  if (type == bp_watchpoint && sig != GDB_SIGNAL_TRAP)
+    return false;
 
-  return 1;
+  return true;
 }
 
-/* The breakpoint_ops structure to be used in hardware watchpoints.  */
+struct masked_watchpoint : public watchpoint
+{
+  using watchpoint::watchpoint;
 
-static struct breakpoint_ops watchpoint_breakpoint_ops;
+  int insert_location (struct bp_location *) override;
+  int remove_location (struct bp_location *,
+                      enum remove_bp_reason reason) override;
+  int resources_needed (const struct bp_location *) override;
+  bool works_in_software_mode () const override;
+  enum print_stop_action print_it (const bpstat *bs) const override;
+  void print_one_detail (struct ui_out *) const override;
+  void print_mention () const override;
+  void print_recreate (struct ui_file *fp) const override;
+};
 
-/* Implement the "insert" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "insert" method for masked hardware watchpoints.  */
 
-static int
-insert_masked_watchpoint (struct bp_location *bl)
+int
+masked_watchpoint::insert_location (struct bp_location *bl)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-
-  return target_insert_mask_watchpoint (bl->address, w->hw_wp_mask,
+  return target_insert_mask_watchpoint (bl->address, hw_wp_mask,
                                        bl->watchpoint_type);
 }
 
-/* Implement the "remove" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "remove" method for masked hardware watchpoints.  */
 
-static int
-remove_masked_watchpoint (struct bp_location *bl, enum remove_bp_reason reason)
+int
+masked_watchpoint::remove_location (struct bp_location *bl,
+                                   enum remove_bp_reason reason)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-
-  return target_remove_mask_watchpoint (bl->address, w->hw_wp_mask,
+  return target_remove_mask_watchpoint (bl->address, hw_wp_mask,
                                        bl->watchpoint_type);
 }
 
-/* Implement the "resources_needed" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "resources_needed" method for masked hardware
+   watchpoints.  */
 
-static int
-resources_needed_masked_watchpoint (const struct bp_location *bl)
+int
+masked_watchpoint::resources_needed (const struct bp_location *bl)
 {
-  struct watchpoint *w = (struct watchpoint *) bl->owner;
-
-  return target_masked_watch_num_registers (bl->address, w->hw_wp_mask);
+  return target_masked_watch_num_registers (bl->address, hw_wp_mask);
 }
 
-/* Implement the "works_in_software_mode" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "works_in_software_mode" method for masked hardware
+   watchpoints.  */
 
-static int
-works_in_software_mode_masked_watchpoint (const struct breakpoint *b)
+bool
+masked_watchpoint::works_in_software_mode () const
 {
-  return 0;
+  return false;
 }
 
-/* Implement the "print_it" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "print_it" method for masked hardware
+   watchpoints.  */
 
-static enum print_stop_action
-print_it_masked_watchpoint (bpstat *bs)
+enum print_stop_action
+masked_watchpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b = bs->breakpoint_at;
   struct ui_out *uiout = current_uiout;
 
   /* Masked watchpoints have only one location.  */
-  gdb_assert (b->loc && b->loc->next == NULL);
+  gdb_assert (this->has_single_location ());
 
-  annotate_watchpoint (b->number);
+  annotate_watchpoint (this->number);
   maybe_print_thread_hit_breakpoint (uiout);
 
-  switch (b->type)
+  switch (this->type)
     {
     case bp_hardware_watchpoint:
       if (uiout->is_mi_like_p ())
@@ -10339,11 +10173,10 @@ print_it_masked_watchpoint (bpstat *bs)
           async_reason_lookup (EXEC_ASYNC_ACCESS_WATCHPOINT_TRIGGER));
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("Invalid hardware watchpoint type."));
+      internal_error (_("Invalid hardware watchpoint type."));
     }
 
-  mention (b);
+  mention (this);
   uiout->text (_("\n\
 Check the underlying instruction at PC for the memory\n\
 address and value which triggered this watchpoint.\n"));
@@ -10353,34 +10186,30 @@ address and value which triggered this watchpoint.\n"));
   return PRINT_UNKNOWN;
 }
 
-/* Implement the "print_one_detail" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "print_one_detail" method for masked hardware
+   watchpoints.  */
 
-static void
-print_one_detail_masked_watchpoint (const struct breakpoint *b,
-                                   struct ui_out *uiout)
+void
+masked_watchpoint::print_one_detail (struct ui_out *uiout) const
 {
-  struct watchpoint *w = (struct watchpoint *) b;
-
   /* Masked watchpoints have only one location.  */
-  gdb_assert (b->loc && b->loc->next == NULL);
+  gdb_assert (this->has_single_location ());
 
   uiout->text ("\tmask ");
-  uiout->field_core_addr ("mask", b->loc->gdbarch, w->hw_wp_mask);
+  uiout->field_core_addr ("mask", this->first_loc ().gdbarch, hw_wp_mask);
   uiout->text ("\n");
 }
 
-/* Implement the "print_mention" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "print_mention" method for masked hardware
+   watchpoints.  */
 
-static void
-print_mention_masked_watchpoint (struct breakpoint *b)
+void
+masked_watchpoint::print_mention () const
 {
-  struct watchpoint *w = (struct watchpoint *) b;
   struct ui_out *uiout = current_uiout;
   const char *tuple_name;
 
-  switch (b->type)
+  switch (type)
     {
     case bp_hardware_watchpoint:
       uiout->text ("Masked hardware watchpoint ");
@@ -10395,55 +10224,47 @@ print_mention_masked_watchpoint (struct breakpoint *b)
       tuple_name = "hw-awpt";
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("Invalid hardware watchpoint type."));
+      internal_error (_("Invalid hardware watchpoint type."));
     }
 
   ui_out_emit_tuple tuple_emitter (uiout, tuple_name);
-  uiout->field_signed ("number", b->number);
+  uiout->field_signed ("number", number);
   uiout->text (": ");
-  uiout->field_string ("exp", w->exp_string.get ());
+  uiout->field_string ("exp", exp_string.get ());
 }
 
-/* Implement the "print_recreate" breakpoint_ops method for
-   masked hardware watchpoints.  */
+/* Implement the "print_recreate" method for masked hardware
+   watchpoints.  */
 
-static void
-print_recreate_masked_watchpoint (struct breakpoint *b, struct ui_file *fp)
+void
+masked_watchpoint::print_recreate (struct ui_file *fp) const
 {
-  struct watchpoint *w = (struct watchpoint *) b;
-
-  switch (b->type)
+  switch (type)
     {
     case bp_hardware_watchpoint:
-      fprintf_unfiltered (fp, "watch");
+      gdb_printf (fp, "watch");
       break;
     case bp_read_watchpoint:
-      fprintf_unfiltered (fp, "rwatch");
+      gdb_printf (fp, "rwatch");
       break;
     case bp_access_watchpoint:
-      fprintf_unfiltered (fp, "awatch");
+      gdb_printf (fp, "awatch");
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("Invalid hardware watchpoint type."));
+      internal_error (_("Invalid hardware watchpoint type."));
     }
 
-  fprintf_unfiltered (fp, " %s mask 0x%s", w->exp_string.get (),
-                     phex (w->hw_wp_mask, sizeof (CORE_ADDR)));
-  print_recreate_thread (b, fp);
+  gdb_printf (fp, " %s mask 0x%s", exp_string.get (),
+             phex (hw_wp_mask, sizeof (CORE_ADDR)));
+  print_recreate_thread (fp);
 }
 
-/* The breakpoint_ops structure to be used in masked hardware watchpoints.  */
-
-static struct breakpoint_ops masked_watchpoint_breakpoint_ops;
-
 /* Tell whether the given watchpoint is a masked hardware watchpoint.  */
 
 static bool
 is_masked_watchpoint (const struct breakpoint *b)
 {
-  return b->ops == &masked_watchpoint_breakpoint_ops;
+  return dynamic_cast<const masked_watchpoint *> (b) != nullptr;
 }
 
 /* accessflag:  hw_write:  watch write, 
@@ -10465,11 +10286,12 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   const char *cond_end = NULL;
   enum bptype bp_type;
   int thread = -1;
+  int inferior = -1;
   /* Flag to indicate whether we are going to use masks for
      the hardware watchpoint.  */
   bool use_mask = false;
   CORE_ADDR mask = 0;
-  int task = 0;
+  int task = -1;
 
   /* Make sure that we actually have parameters to parse.  */
   if (arg != NULL && arg[0] != '\0')
@@ -10516,12 +10338,16 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
              if (thread != -1)
                error(_("You can specify only one thread."));
 
+             if (task != -1)
+               error (_("You can specify only one of thread or task."));
+
+             if (inferior != -1)
+               error (_("You can specify only one of inferior or thread."));
+
              /* Extract the thread ID from the next token.  */
              thr = parse_thread_id (value_start, &endp);
-
-             /* Check if the user provided a valid thread ID.  */
-             if (*endp != ' ' && *endp != '\t' && *endp != '\0')
-               invalid_thread_id_error (value_start);
+             if (value_start == endp)
+               error (_("Junk after thread keyword."));
 
              thread = thr->global_num;
            }
@@ -10529,28 +10355,41 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
            {
              char *tmp;
 
+             if (task != -1)
+               error(_("You can specify only one task."));
+
+             if (thread != -1)
+               error (_("You can specify only one of thread or task."));
+
+             if (inferior != -1)
+               error (_("You can specify only one of inferior or task."));
+
              task = strtol (value_start, &tmp, 0);
              if (tmp == value_start)
                error (_("Junk after task keyword."));
              if (!valid_task_id (task))
                error (_("Unknown task %d."), task);
            }
+         else if (toklen == 8 && startswith (tok, "inferior"))
+           {
+             /* Support for watchpoints will be added in a later commit.  */
+             error (_("Cannot use 'inferior' keyword with watchpoints"));
+           }
          else if (toklen == 4 && startswith (tok, "mask"))
            {
              /* We've found a "mask" token, which means the user wants to
                 create a hardware watchpoint that is going to have the mask
                 facility.  */
-             struct value *mask_value, *mark;
+             struct value *mask_value;
 
              if (use_mask)
                error(_("You can specify only one mask."));
 
              use_mask = just_location = true;
 
-             mark = value_mark ();
+             scoped_value_mark mark;
              mask_value = parse_to_comma_and_eval (&value_start);
              mask = value_as_address (mask_value);
-             value_free_to_mark (mark);
            }
          else
            /* We didn't recognize what we found.  We should stop here.  */
@@ -10597,8 +10436,8 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
 
   if (val_as_value != NULL && just_location)
     {
-      saved_bitpos = value_bitpos (val_as_value);
-      saved_bitsize = value_bitsize (val_as_value);
+      saved_bitpos = val_as_value->bitpos ();
+      saved_bitsize = val_as_value->bitsize ();
     }
 
   value_ref_ptr val;
@@ -10642,7 +10481,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   if (*tok)
     error (_("Junk at end of command."));
 
-  frame_info *wp_frame = block_innermost_frame (exp_valid_block);
+  frame_info_ptr wp_frame = block_innermost_frame (exp_valid_block);
 
   /* Save this because create_internal_breakpoint below invalidates
      'wp_frame'.  */
@@ -10663,8 +10502,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
 
          scope_breakpoint
            = create_internal_breakpoint (caller_arch, caller_pc,
-                                         bp_watchpoint_scope,
-                                         &momentary_breakpoint_ops);
+                                         bp_watchpoint_scope);
 
          /* create_internal_breakpoint could invalidate WP_FRAME.  */
          wp_frame = NULL;
@@ -10678,12 +10516,13 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
          scope_breakpoint->frame_id = caller_frame_id;
 
          /* Set the address at which we will stop.  */
-         scope_breakpoint->loc->gdbarch = caller_arch;
-         scope_breakpoint->loc->requested_address = caller_pc;
-         scope_breakpoint->loc->address
-           = adjust_breakpoint_address (scope_breakpoint->loc->gdbarch,
-                                        scope_breakpoint->loc->requested_address,
-                                        scope_breakpoint->type);
+         bp_location &loc = scope_breakpoint->first_loc ();
+         loc.gdbarch = caller_arch;
+         loc.requested_address = caller_pc;
+         loc.address
+           = adjust_breakpoint_address (loc.gdbarch, loc.requested_address,
+                                        scope_breakpoint->type,
+                                        current_program_space);
        }
     }
 
@@ -10699,15 +10538,16 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   else
     bp_type = bp_hardware_watchpoint;
 
-  std::unique_ptr<watchpoint> w (new watchpoint ());
-
+  std::unique_ptr<watchpoint> w;
   if (use_mask)
-    init_raw_breakpoint_without_location (w.get (), NULL, bp_type,
-                                         &masked_watchpoint_breakpoint_ops);
+    w.reset (new masked_watchpoint (nullptr, bp_type));
   else
-    init_raw_breakpoint_without_location (w.get (), NULL, bp_type,
-                                         &watchpoint_breakpoint_ops);
+    w.reset (new watchpoint (nullptr, bp_type));
+
+  /* At most one of thread or task can be set on a watchpoint.  */
+  gdb_assert (thread == -1 || task == -1);
   w->thread = thread;
+  w->inferior = inferior;
   w->task = task;
   w->disposition = disp_donttouch;
   w->pspace = current_program_space;
@@ -10716,7 +10556,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
   w->cond_exp_valid_block = cond_exp_valid_block;
   if (just_location)
     {
-      struct type *t = value_type (val.get ());
+      struct type *t = val->type ();
       CORE_ADDR addr = value_as_address (val.get ());
 
       w->exp_string_reparse
@@ -10769,7 +10609,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty,
 
   /* Finally update the new watchpoint.  This creates the locations
      that should be inserted.  */
-  update_watchpoint (w.get (), 1);
+  update_watchpoint (w.get (), true /* reparse */);
 
   install_breakpoint (internal, std::move (w), 1);
 }
@@ -10812,9 +10652,9 @@ can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
     {
       struct value *v = iter.get ();
 
-      if (VALUE_LVAL (v) == lval_memory)
+      if (v->lval () == lval_memory)
        {
-         if (v != head && value_lazy (v))
+         if (v != head && v->lazy ())
            /* A lazy memory lvalue in the chain is one that GDB never
               needed to fetch; we either just used its address (e.g.,
               `a' in `a.b') or we never needed it at all (e.g., `a'
@@ -10825,7 +10665,7 @@ can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
            {
              /* Ahh, memory we actually used!  Check if we can cover
                 it with hardware watchpoints.  */
-             struct type *vtype = check_typedef (value_type (v));
+             struct type *vtype = check_typedef (v->type ());
 
              /* We only watch structs and arrays if user asked for it
                 explicitly, never if they just happen to appear in a
@@ -10834,13 +10674,13 @@ can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
                  || (vtype->code () != TYPE_CODE_STRUCT
                      && vtype->code () != TYPE_CODE_ARRAY))
                {
-                 CORE_ADDR vaddr = value_address (v);
+                 CORE_ADDR vaddr = v->address ();
                  int len;
                  int num_regs;
 
                  len = (target_exact_watchpoints
                         && is_scalar_type_recursive (vtype))?
-                   1 : TYPE_LENGTH (value_type (v));
+                   1 : v->type ()->length ();
 
                  num_regs = target_region_ok_for_hw_watchpoint (vaddr, len);
                  if (!num_regs)
@@ -10850,10 +10690,9 @@ can_use_hardware_watchpoint (const std::vector<value_ref_ptr> &vals)
                }
            }
        }
-      else if (VALUE_LVAL (v) != not_lval
-              && deprecated_value_modifiable (v) == 0)
+      else if (v->lval () != not_lval && !v->deprecated_modifiable ())
        return 0;       /* These are values from the history (e.g., $1).  */
-      else if (VALUE_LVAL (v) == lval_register)
+      else if (v->lval () == lval_register)
        return 0;       /* Cannot watch a register with a HW watchpoint.  */
     }
 
@@ -11035,7 +10874,7 @@ until_break_fsm::do_async_reply_reason ()
 void
 until_break_command (const char *arg, int from_tty, int anywhere)
 {
-  struct frame_info *frame;
+  frame_info_ptr frame;
   struct gdbarch *frame_gdbarch;
   struct frame_id stack_frame_id;
   struct frame_id caller_frame_id;
@@ -11047,14 +10886,14 @@ until_break_command (const char *arg, int from_tty, int anywhere)
   /* Set a breakpoint where the user wants it and at return from
      this function.  */
 
-  event_location_up location = string_to_event_location (&arg, current_language);
+  location_spec_up locspec = string_to_location_spec (&arg, current_language);
 
   std::vector<symtab_and_line> sals
     = (last_displayed_sal_is_valid ()
-       ? decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
+       ? decode_line_1 (locspec.get (), DECODE_LINE_FUNFIRSTLINE, NULL,
                        get_last_displayed_symtab (),
                        get_last_displayed_line ())
-       : decode_line_1 (location.get (), DECODE_LINE_FUNFIRSTLINE,
+       : decode_line_1 (locspec.get (), DECODE_LINE_FUNFIRSTLINE,
                        NULL, NULL, 0));
 
   if (sals.empty ())
@@ -11097,7 +10936,7 @@ until_break_command (const char *arg, int from_tty, int anywhere)
                                    caller_frame_id, bp_until);
       breakpoints.emplace_back (std::move (caller_breakpoint));
 
-      set_longjmp_breakpoint (tp, caller_frame_id);
+      set_longjmp_breakpoint (tp, stack_frame_id);
       lj_deleter.emplace (thread);
     }
 
@@ -11120,8 +10959,10 @@ until_break_command (const char *arg, int from_tty, int anywhere)
       breakpoints.emplace_back (std::move (location_breakpoint));
     }
 
-  tp->thread_fsm = new until_break_fsm (command_interp (), tp->global_num,
-                                       std::move (breakpoints));
+  tp->set_thread_fsm
+    (std::unique_ptr<thread_fsm>
+     (new until_break_fsm (command_interp (), tp->global_num,
+                          std::move (breakpoints))));
 
   if (lj_deleter)
     lj_deleter->release ();
@@ -11129,158 +10970,6 @@ until_break_command (const char *arg, int from_tty, int anywhere)
   proceed (-1, GDB_SIGNAL_DEFAULT);
 }
 
-/* This function attempts to parse an optional "if <cond>" clause
-   from the arg string.  If one is not found, it returns NULL.
-
-   Else, it returns a pointer to the condition string.  (It does not
-   attempt to evaluate the string against a particular block.)  And,
-   it updates arg to point to the first character following the parsed
-   if clause in the arg string.  */
-
-const char *
-ep_parse_optional_if_clause (const char **arg)
-{
-  const char *cond_string;
-
-  if (((*arg)[0] != 'i') || ((*arg)[1] != 'f') || !isspace ((*arg)[2]))
-    return NULL;
-
-  /* Skip the "if" keyword.  */
-  (*arg) += 2;
-
-  /* Skip any extra leading whitespace, and record the start of the
-     condition string.  */
-  *arg = skip_spaces (*arg);
-  cond_string = *arg;
-
-  /* Assume that the condition occupies the remainder of the arg
-     string.  */
-  (*arg) += strlen (cond_string);
-
-  return cond_string;
-}
-
-/* Commands to deal with catching events, such as signals, exceptions,
-   process start/exit, etc.  */
-
-typedef enum
-{
-  catch_fork_temporary, catch_vfork_temporary,
-  catch_fork_permanent, catch_vfork_permanent
-}
-catch_fork_kind;
-
-static void
-catch_fork_command_1 (const char *arg, int from_tty,
-                     struct cmd_list_element *command)
-{
-  struct gdbarch *gdbarch = get_current_arch ();
-  const char *cond_string = NULL;
-  catch_fork_kind fork_kind;
-
-  fork_kind = (catch_fork_kind) (uintptr_t) command->context ();
-  bool temp = (fork_kind == catch_fork_temporary
-              || fork_kind == catch_vfork_temporary);
-
-  if (!arg)
-    arg = "";
-  arg = skip_spaces (arg);
-
-  /* The allowed syntax is:
-     catch [v]fork
-     catch [v]fork if <cond>
-
-     First, check if there's an if clause.  */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  /* If this target supports it, create a fork or vfork catchpoint
-     and enable reporting of such events.  */
-  switch (fork_kind)
-    {
-    case catch_fork_temporary:
-    case catch_fork_permanent:
-      create_fork_vfork_event_catchpoint (gdbarch, temp, cond_string, false);
-      break;
-    case catch_vfork_temporary:
-    case catch_vfork_permanent:
-      create_fork_vfork_event_catchpoint (gdbarch, temp, cond_string, true);
-      break;
-    default:
-      error (_("unsupported or unknown fork kind; cannot catch it"));
-      break;
-    }
-}
-
-static void
-catch_exec_command_1 (const char *arg, int from_tty,
-                     struct cmd_list_element *command)
-{
-  struct gdbarch *gdbarch = get_current_arch ();
-  const char *cond_string = NULL;
-  bool temp = command->context () == CATCH_TEMPORARY;
-
-  if (!arg)
-    arg = "";
-  arg = skip_spaces (arg);
-
-  /* The allowed syntax is:
-     catch exec
-     catch exec if <cond>
-
-     First, check if there's an if clause.  */
-  cond_string = ep_parse_optional_if_clause (&arg);
-
-  if ((*arg != '\0') && !isspace (*arg))
-    error (_("Junk at end of arguments."));
-
-  std::unique_ptr<exec_catchpoint> c (new exec_catchpoint ());
-  init_catchpoint (c.get (), gdbarch, temp, cond_string,
-                  &catch_exec_breakpoint_ops);
-  c->exec_pathname.reset ();
-
-  install_breakpoint (0, std::move (c), 1);
-}
-
-void
-init_ada_exception_breakpoint (struct breakpoint *b,
-                              struct gdbarch *gdbarch,
-                              struct symtab_and_line sal,
-                              const char *addr_string,
-                              const struct breakpoint_ops *ops,
-                              int tempflag,
-                              int enabled,
-                              int from_tty)
-{
-  if (from_tty)
-    {
-      struct gdbarch *loc_gdbarch = get_sal_arch (sal);
-      if (!loc_gdbarch)
-       loc_gdbarch = gdbarch;
-
-      describe_other_breakpoints (loc_gdbarch,
-                                 sal.pspace, sal.pc, sal.section, -1);
-      /* FIXME: brobecker/2006-12-28: Actually, re-implement a special
-        version for exception catchpoints, because two catchpoints
-        used for different exception names will use the same address.
-        In this case, a "breakpoint ... also set at..." warning is
-        unproductive.  Besides, the warning phrasing is also a bit
-        inappropriate, we should use the word catchpoint, and tell
-        the user what type of catchpoint it is.  The above is good
-        enough for now, though.  */
-    }
-
-  init_raw_breakpoint (b, gdbarch, sal, bp_catchpoint, ops);
-
-  b->enable_state = enabled ? bp_enabled : bp_disabled;
-  b->disposition = tempflag ? disp_del : disp_donttouch;
-  b->location = string_to_event_location (&addr_string,
-                                         language_def (language_ada));
-  b->language = language_ada;
-}
-
 \f
 
 /* Compare two breakpoints and return a strcmp-like result.  */
@@ -11378,30 +11067,31 @@ clear_command (const char *arg, int from_tty)
                      ? NULL : symtab_to_fullname (sal.symtab));
 
       /* Find all matching breakpoints and add them to 'found'.  */
-      for (breakpoint *b : all_breakpoints ())
+      for (breakpoint &b : all_breakpoints ())
        {
          int match = 0;
          /* Are we going to delete b?  */
-         if (b->type != bp_none && !is_watchpoint (b))
+         if (b.type != bp_none && !is_watchpoint (&b)
+             && user_breakpoint_p (&b))
            {
-             for (bp_location *loc : b->locations ())
+             for (bp_location &loc : b.locations ())
                {
                  /* If the user specified file:line, don't allow a PC
                     match.  This matches historical gdb behavior.  */
                  int pc_match = (!sal.explicit_line
                                  && sal.pc
-                                 && (loc->pspace == sal.pspace)
-                                 && (loc->address == sal.pc)
-                                 && (!section_is_overlay (loc->section)
-                                     || loc->section == sal.section));
+                                 && (loc.pspace == sal.pspace)
+                                 && (loc.address == sal.pc)
+                                 && (!section_is_overlay (loc.section)
+                                     || loc.section == sal.section));
                  int line_match = 0;
 
                  if ((default_match || sal.explicit_line)
-                     && loc->symtab != NULL
+                     && loc.symtab != NULL
                      && sal_fullname != NULL
-                     && sal.pspace == loc->pspace
-                     && loc->line_number == sal.line
-                     && filename_cmp (symtab_to_fullname (loc->symtab),
+                     && sal.pspace == loc.pspace
+                     && loc.line_number == sal.line
+                     && filename_cmp (symtab_to_fullname (loc.symtab),
                                       sal_fullname) == 0)
                    line_match = 1;
 
@@ -11414,7 +11104,7 @@ clear_command (const char *arg, int from_tty)
            }
 
          if (match)
-           found.push_back (b);
+           found.push_back (&b);
        }
     }
 
@@ -11445,19 +11135,19 @@ clear_command (const char *arg, int from_tty)
   if (from_tty)
     {
       if (found.size () == 1)
-       printf_filtered (_("Deleted breakpoint "));
+       gdb_printf (_("Deleted breakpoint "));
       else
-       printf_filtered (_("Deleted breakpoints "));
+       gdb_printf (_("Deleted breakpoints "));
     }
 
   for (breakpoint *iter : found)
     {
       if (from_tty)
-       printf_filtered ("%d ", iter->number);
+       gdb_printf ("%d ", iter->number);
       delete_breakpoint (iter);
     }
   if (from_tty)
-    putchar_filtered ('\n');
+    gdb_putc ('\n');
 }
 \f
 /* Delete breakpoint in BS if they are `delete' breakpoints and
@@ -11473,15 +11163,15 @@ breakpoint_auto_delete (bpstat *bs)
        && bs->stop)
       delete_breakpoint (bs->breakpoint_at);
 
-  for (breakpoint *b : all_breakpoints_safe ())
-    if (b->disposition == disp_del_at_next_stop)
-      delete_breakpoint (b);
+  for (breakpoint &b : all_breakpoints_safe ())
+    if (b.disposition == disp_del_at_next_stop)
+      delete_breakpoint (&b);
 }
 
 /* A comparison function for bp_location AP and BP being interfaced to
    std::sort.  Sort elements primarily by their ADDRESS (no matter what
    bl_address_is_meaningful says), secondarily by ordering first
-   permanent elements and terciarily just ensuring the array is sorted
+   permanent elements and tertiarily just ensuring the array is sorted
    stable way despite std::sort being an unstable algorithm.  */
 
 static int
@@ -11566,12 +11256,11 @@ download_tracepoint_locations (void)
 
   scoped_restore_current_pspace_and_thread restore_pspace_thread;
 
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      struct tracepoint *t;
-      int bp_location_downloaded = 0;
+      bool bp_location_downloaded = false;
 
-      if ((b->type == bp_fast_tracepoint
+      if ((b.type == bp_fast_tracepoint
           ? !may_insert_fast_tracepoints
           : !may_insert_tracepoints))
        continue;
@@ -11587,25 +11276,26 @@ download_tracepoint_locations (void)
       if (can_download_tracepoint == TRIBOOL_FALSE)
        break;
 
-      for (bp_location *bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
          /* In tracepoint, locations are _never_ duplicated, so
             should_be_inserted is equivalent to
             unduplicated_should_be_inserted.  */
-         if (!should_be_inserted (bl) || bl->inserted)
+         if (!should_be_inserted (&bl) || bl.inserted)
            continue;
 
-         switch_to_program_space_and_thread (bl->pspace);
+         switch_to_program_space_and_thread (bl.pspace);
 
-         target_download_tracepoint (bl);
+         target_download_tracepoint (&bl);
 
-         bl->inserted = 1;
-         bp_location_downloaded = 1;
+         bl.inserted = 1;
+         bp_location_downloaded = true;
        }
-      t = (struct tracepoint *) b;
-      t->number_on_target = b->number;
+
+      tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
+      t.number_on_target = b.number;
       if (bp_location_downloaded)
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
     }
 }
 
@@ -11696,6 +11386,9 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   /* Last breakpoint location program space that was marked for update.  */
   int last_pspace_num = -1;
 
+  breakpoint_debug_printf ("insert_mode = %s",
+                          ugll_insert_mode_text (insert_mode));
+
   /* Used in the duplicates detection below.  When iterating over all
      bp_locations, points to the first bp_location of a given address.
      Breakpoints and watchpoints of different types are never
@@ -11712,9 +11405,9 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   std::vector<bp_location *> old_locations = std::move (bp_locations);
   bp_locations.clear ();
 
-  for (breakpoint *b : all_breakpoints ())
-    for (bp_location *loc : b->locations ())
-      bp_locations.push_back (loc);
+  for (breakpoint &b : all_breakpoints ())
+    for (bp_location &loc : b.locations ())
+      bp_locations.push_back (&loc);
 
   /* See if we need to "upgrade" a software breakpoint to a hardware
      breakpoint.  Do this before deciding whether locations are
@@ -11744,10 +11437,10 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
     {
       /* Tells if 'old_loc' is found among the new locations.  If
         not, we have to free it.  */
-      int found_object = 0;
+      bool found_object = false;
       /* Tells if the location should remain inserted in the target.  */
-      int keep_in_target = 0;
-      int removed = 0;
+      bool keep_in_target = false;
+      bool removed = false;
 
       /* Skip LOCP entries which will definitely never be needed.
         Stop either at or being the one matching OLD_LOC.  */
@@ -11773,7 +11466,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
            }
 
          if (bp_locations[loc2_i] == old_loc)
-           found_object = 1;
+           found_object = true;
        }
 
       /* We have already handled this address, update it so that we don't
@@ -11799,7 +11492,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
            {
              /* The location is still present in the location list,
                 and still should be inserted.  Don't do anything.  */
-             keep_in_target = 1;
+             keep_in_target = true;
            }
          else
            {
@@ -11842,7 +11535,7 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
                          if (unduplicated_should_be_inserted (loc2))
                            {
                              swap_insertion (old_loc, loc2);
-                             keep_in_target = 1;
+                             keep_in_target = true;
                              break;
                            }
                        }
@@ -11862,11 +11555,11 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
                     Note that at this point, old_loc->owner is still
                     valid, as delete_breakpoint frees the breakpoint
                     only after calling us.  */
-                 printf_filtered (_("warning: Error removing "
-                                    "breakpoint %d\n"), 
-                                  old_loc->owner->number);
+                 warning (_("error removing breakpoint %d at %s"),
+                          old_loc->owner->number,
+                          paddress (old_loc->gdbarch, old_loc->address));
                }
-             removed = 1;
+             removed = true;
            }
        }
 
@@ -12089,11 +11782,10 @@ bpstat_remove_breakpoint_callback (struct thread_info *th, void *data)
   return 0;
 }
 
-/* Helper for breakpoint and tracepoint breakpoint_ops->mention
-   callbacks.  */
+/* See breakpoint.h.  */
 
-static void
-say_where (struct breakpoint *b)
+void
+code_breakpoint::say_where () const
 {
   struct value_print_options opts;
 
@@ -12101,275 +11793,214 @@ say_where (struct breakpoint *b)
 
   /* i18n: cagney/2005-02-11: Below needs to be merged into a
      single string.  */
-  if (b->loc == NULL)
+  if (!this->has_locations ())
     {
       /* For pending locations, the output differs slightly based
-        on b->extra_string.  If this is non-NULL, it contains either
+        on extra_string.  If this is non-NULL, it contains either
         a condition or dprintf arguments.  */
-      if (b->extra_string == NULL)
+      if (extra_string == NULL)
        {
-         printf_filtered (_(" (%s) pending."),
-                          event_location_to_string (b->location.get ()));
+         gdb_printf (_(" (%s) pending."), locspec->to_string ());
        }
-      else if (b->type == bp_dprintf)
+      else if (type == bp_dprintf)
        {
-         printf_filtered (_(" (%s,%s) pending."),
-                          event_location_to_string (b->location.get ()),
-                          b->extra_string.get ());
+         gdb_printf (_(" (%s,%s) pending."),
+                     locspec->to_string (),
+                     extra_string.get ());
        }
       else
        {
-         printf_filtered (_(" (%s %s) pending."),
-                          event_location_to_string (b->location.get ()),
-                          b->extra_string.get ());
+         gdb_printf (_(" (%s %s) pending."),
+                     locspec->to_string (),
+                     extra_string.get ());
        }
     }
   else
     {
-      if (opts.addressprint || b->loc->symtab == NULL)
-       printf_filtered (" at %ps",
-                        styled_string (address_style.style (),
-                                       paddress (b->loc->gdbarch,
-                                                 b->loc->address)));
-      if (b->loc->symtab != NULL)
+      const bp_location &bl = this->first_loc ();
+      if (opts.addressprint || bl.symtab == nullptr)
+       gdb_printf (" at %ps",
+                   styled_string (address_style.style (),
+                                  paddress (bl.gdbarch,
+                                            bl.address)));
+      if (bl.symtab != NULL)
        {
          /* If there is a single location, we can print the location
             more nicely.  */
-         if (b->loc->next == NULL)
+         if (!this->has_multiple_locations ())
            {
              const char *filename
-               = symtab_to_filename_for_display (b->loc->symtab);
-             printf_filtered (": file %ps, line %d.",
-                              styled_string (file_name_style.style (),
-                                             filename),
-                              b->loc->line_number);
+               = symtab_to_filename_for_display (bl.symtab);
+             gdb_printf (": file %ps, line %d.",
+                         styled_string (file_name_style.style (),
+                                        filename),
+                         bl.line_number);
            }
          else
            /* 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.",
-                            event_location_to_string (b->location.get ()));
+           gdb_printf (": %s.", locspec->to_string ());
        }
 
-      if (b->loc->next)
+      if (this->has_multiple_locations ())
        {
-         struct bp_location *loc = b->loc;
-         int n = 0;
-         for (; loc; loc = loc->next)
-           ++n;
-         printf_filtered (" (%d locations)", n);
+         int n = std::distance (m_locations.begin (), m_locations.end ());
+         gdb_printf (" (%d locations)", n);
        }
     }
 }
 
 /* See breakpoint.h.  */
 
-bp_location_range breakpoint::locations ()
-{
-  return bp_location_range (this->loc);
-}
-
-static struct bp_location *
-base_breakpoint_allocate_location (struct breakpoint *self)
+bp_location_range breakpoint::locations () const
 {
-  return new bp_location (self);
+  return bp_location_range (m_locations.begin (), m_locations.end ());
 }
 
-static void
-base_breakpoint_re_set (struct breakpoint *b)
+struct bp_location *
+breakpoint::allocate_location ()
 {
-  /* Nothing to re-set. */
+  return new bp_location (this);
 }
 
-#define internal_error_pure_virtual_called() \
-  gdb_assert_not_reached ("pure virtual function called")
+/* See breakpoint.h.  */
 
-static int
-base_breakpoint_insert_location (struct bp_location *bl)
+void
+breakpoint::add_location (bp_location &loc)
 {
-  internal_error_pure_virtual_called ();
-}
+  gdb_assert (loc.owner == this);
+  gdb_assert (!loc.is_linked ());
 
-static int
-base_breakpoint_remove_location (struct bp_location *bl,
-                                enum remove_bp_reason reason)
-{
-  internal_error_pure_virtual_called ();
+  auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
+                             loc,
+                             [] (const bp_location &left,
+                                 const bp_location &right)
+                               { return left.address < right.address; });
+  m_locations.insert (ub, loc);
 }
 
-static int
-base_breakpoint_breakpoint_hit (const struct bp_location *bl,
-                               const address_space *aspace,
-                               CORE_ADDR bp_addr,
-                               const target_waitstatus &ws)
-{
-  internal_error_pure_virtual_called ();
-}
+/* See breakpoint.h.  */
 
-static void
-base_breakpoint_check_status (bpstat *bs)
+void
+breakpoint::unadd_location (bp_location &loc)
 {
-  /* Always stop.   */
-}
-
-/* A "works_in_software_mode" breakpoint_ops method that just internal
-   errors.  */
+  gdb_assert (loc.owner == this);
+  gdb_assert (loc.is_linked ());
 
-static int
-base_breakpoint_works_in_software_mode (const struct breakpoint *b)
-{
-  internal_error_pure_virtual_called ();
+  m_locations.erase (m_locations.iterator_to (loc));
 }
 
-/* A "resources_needed" breakpoint_ops method that just internal
-   errors.  */
+#define internal_error_pure_virtual_called() \
+  gdb_assert_not_reached ("pure virtual function called")
 
-static int
-base_breakpoint_resources_needed (const struct bp_location *bl)
+int
+breakpoint::insert_location (struct bp_location *bl)
 {
   internal_error_pure_virtual_called ();
 }
 
-static enum print_stop_action
-base_breakpoint_print_it (bpstat *bs)
+int
+breakpoint::remove_location (struct bp_location *bl,
+                            enum remove_bp_reason reason)
 {
   internal_error_pure_virtual_called ();
 }
 
-static void
-base_breakpoint_print_one_detail (const struct breakpoint *self,
-                                 struct ui_out *uiout)
-{
-  /* nothing */
-}
-
-static void
-base_breakpoint_print_mention (struct breakpoint *b)
+int
+breakpoint::breakpoint_hit (const struct bp_location *bl,
+                           const address_space *aspace,
+                           CORE_ADDR bp_addr,
+                           const target_waitstatus &ws)
 {
   internal_error_pure_virtual_called ();
 }
 
-static void
-base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
+int
+breakpoint::resources_needed (const struct bp_location *bl)
 {
   internal_error_pure_virtual_called ();
 }
 
-static void
-base_breakpoint_create_sals_from_location
-  (struct event_location *location,
-   struct linespec_result *canonical,
-   enum bptype type_wanted)
+enum print_stop_action
+breakpoint::print_it (const bpstat *bs) const
 {
   internal_error_pure_virtual_called ();
 }
 
-static void
-base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
-                                       struct linespec_result *c,
-                                       gdb::unique_xmalloc_ptr<char> cond_string,
-                                       gdb::unique_xmalloc_ptr<char> extra_string,
-                                       enum bptype type_wanted,
-                                       enum bpdisp disposition,
-                                       int thread,
-                                       int task, int ignore_count,
-                                       const struct breakpoint_ops *o,
-                                       int from_tty, int enabled,
-                                       int internal, unsigned flags)
+void
+breakpoint::print_mention () const
 {
   internal_error_pure_virtual_called ();
 }
 
-static std::vector<symtab_and_line>
-base_breakpoint_decode_location (struct breakpoint *b,
-                                struct event_location *location,
-                                struct program_space *search_pspace)
+void
+breakpoint::print_recreate (struct ui_file *fp) const
 {
   internal_error_pure_virtual_called ();
 }
 
-/* The default 'explains_signal' method.  */
-
-static int
-base_breakpoint_explains_signal (struct breakpoint *b, enum gdb_signal sig)
-{
-  return 1;
-}
-
-/* The default "after_condition_true" method.  */
-
-static void
-base_breakpoint_after_condition_true (struct bpstat *bs)
-{
-  /* Nothing to do.   */
-}
-
-struct breakpoint_ops base_breakpoint_ops =
-{
-  base_breakpoint_allocate_location,
-  base_breakpoint_re_set,
-  base_breakpoint_insert_location,
-  base_breakpoint_remove_location,
-  base_breakpoint_breakpoint_hit,
-  base_breakpoint_check_status,
-  base_breakpoint_resources_needed,
-  base_breakpoint_works_in_software_mode,
-  base_breakpoint_print_it,
-  NULL,
-  base_breakpoint_print_one_detail,
-  base_breakpoint_print_mention,
-  base_breakpoint_print_recreate,
-  base_breakpoint_create_sals_from_location,
-  base_breakpoint_create_breakpoints_sal,
-  base_breakpoint_decode_location,
-  base_breakpoint_explains_signal,
-  base_breakpoint_after_condition_true,
-};
-
 /* Default breakpoint_ops methods.  */
 
-static void
-bkpt_re_set (struct breakpoint *b)
+void
+code_breakpoint::re_set ()
 {
   /* FIXME: is this still reachable?  */
-  if (breakpoint_event_location_empty_p (b))
+  if (breakpoint_location_spec_empty_p (this))
     {
       /* Anything without a location can't be re-set.  */
-      delete_breakpoint (b);
+      delete_breakpoint (this);
       return;
     }
 
-  breakpoint_re_set_default (b);
+  re_set_default ();
 }
 
-static int
-bkpt_insert_location (struct bp_location *bl)
+int
+code_breakpoint::insert_location (struct bp_location *bl)
 {
   CORE_ADDR addr = bl->target_info.reqstd_address;
 
   bl->target_info.kind = breakpoint_kind (bl, &addr);
   bl->target_info.placed_address = addr;
 
+  int result;
   if (bl->loc_type == bp_loc_hardware_breakpoint)
-    return target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
+    result = target_insert_hw_breakpoint (bl->gdbarch, &bl->target_info);
   else
-    return target_insert_breakpoint (bl->gdbarch, &bl->target_info);
+    result = target_insert_breakpoint (bl->gdbarch, &bl->target_info);
+
+  if (result == 0 && bl->probe.prob != nullptr)
+    {
+      /* The insertion was successful, now let's set the probe's semaphore
+        if needed.  */
+      bl->probe.prob->set_semaphore (bl->probe.objfile, bl->gdbarch);
+    }
+
+  return result;
 }
 
-static int
-bkpt_remove_location (struct bp_location *bl, enum remove_bp_reason reason)
+int
+code_breakpoint::remove_location (struct bp_location *bl,
+                                 enum remove_bp_reason reason)
 {
+  if (bl->probe.prob != nullptr)
+    {
+      /* Let's clear the semaphore before removing the location.  */
+      bl->probe.prob->clear_semaphore (bl->probe.objfile, bl->gdbarch);
+    }
+
   if (bl->loc_type == bp_loc_hardware_breakpoint)
     return target_remove_hw_breakpoint (bl->gdbarch, &bl->target_info);
   else
     return target_remove_breakpoint (bl->gdbarch, &bl->target_info, reason);
 }
 
-static int
-bkpt_breakpoint_hit (const struct bp_location *bl,
-                    const address_space *aspace, CORE_ADDR bp_addr,
-                    const target_waitstatus &ws)
+int
+code_breakpoint::breakpoint_hit (const struct bp_location *bl,
+                                const address_space *aspace,
+                                CORE_ADDR bp_addr,
+                                const target_waitstatus &ws)
 {
   if (ws.kind () != TARGET_WAITKIND_STOPPED
       || ws.sig () != GDB_SIGNAL_TRAP)
@@ -12387,10 +12018,11 @@ bkpt_breakpoint_hit (const struct bp_location *bl,
   return 1;
 }
 
-static int
-dprintf_breakpoint_hit (const struct bp_location *bl,
-                       const address_space *aspace, CORE_ADDR bp_addr,
-                       const target_waitstatus &ws)
+int
+dprintf_breakpoint::breakpoint_hit (const struct bp_location *bl,
+                                   const address_space *aspace,
+                                   CORE_ADDR bp_addr,
+                                   const target_waitstatus &ws)
 {
   if (dprintf_style == dprintf_style_agent
       && target_can_run_breakpoint_commands ())
@@ -12401,154 +12033,135 @@ dprintf_breakpoint_hit (const struct bp_location *bl,
       return 0;
     }
 
-  return bkpt_breakpoint_hit (bl, aspace, bp_addr, ws);
+  return this->ordinary_breakpoint::breakpoint_hit (bl, aspace, bp_addr, ws);
 }
 
-static int
-bkpt_resources_needed (const struct bp_location *bl)
+int
+ordinary_breakpoint::resources_needed (const struct bp_location *bl)
 {
-  gdb_assert (bl->owner->type == bp_hardware_breakpoint);
+  gdb_assert (type == bp_hardware_breakpoint);
 
   return 1;
 }
 
-static enum print_stop_action
-bkpt_print_it (bpstat *bs)
+enum print_stop_action
+ordinary_breakpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b;
   const struct bp_location *bl;
   int bp_temp;
   struct ui_out *uiout = current_uiout;
 
-  gdb_assert (bs->bp_location_at != NULL);
-
   bl = bs->bp_location_at.get ();
-  b = bs->breakpoint_at;
 
-  bp_temp = b->disposition == disp_del;
+  bp_temp = disposition == disp_del;
   if (bl->address != bl->requested_address)
     breakpoint_adjustment_warning (bl->requested_address,
                                   bl->address,
-                                  b->number, 1);
-  annotate_breakpoint (b->number);
+                                  number, true);
+  annotate_breakpoint (number);
   maybe_print_thread_hit_breakpoint (uiout);
 
   if (uiout->is_mi_like_p ())
     {
       uiout->field_string ("reason",
                           async_reason_lookup (EXEC_ASYNC_BREAKPOINT_HIT));
-      uiout->field_string ("disp", bpdisp_text (b->disposition));
+      uiout->field_string ("disp", bpdisp_text (disposition));
     }
+
   if (bp_temp)
-    uiout->message ("Temporary breakpoint %pF, ",
-                   signed_field ("bkptno", b->number));
+    uiout->text ("Temporary breakpoint ");
   else
-    uiout->message ("Breakpoint %pF, ",
-                   signed_field ("bkptno", b->number));
+    uiout->text ("Breakpoint ");
+  print_num_locno (bs, uiout);
+  uiout->text (", ");
 
   return PRINT_SRC_AND_LOC;
 }
 
-static void
-bkpt_print_mention (struct breakpoint *b)
+void
+ordinary_breakpoint::print_mention () const
 {
   if (current_uiout->is_mi_like_p ())
     return;
 
-  switch (b->type)
+  switch (type)
     {
     case bp_breakpoint:
     case bp_gnu_ifunc_resolver:
-      if (b->disposition == disp_del)
-       printf_filtered (_("Temporary breakpoint"));
+      if (disposition == disp_del)
+       gdb_printf (_("Temporary breakpoint"));
       else
-       printf_filtered (_("Breakpoint"));
-      printf_filtered (_(" %d"), b->number);
-      if (b->type == bp_gnu_ifunc_resolver)
-       printf_filtered (_(" at gnu-indirect-function resolver"));
+       gdb_printf (_("Breakpoint"));
+      gdb_printf (_(" %d"), number);
+      if (type == bp_gnu_ifunc_resolver)
+       gdb_printf (_(" at gnu-indirect-function resolver"));
       break;
     case bp_hardware_breakpoint:
-      printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
+      gdb_printf (_("Hardware assisted breakpoint %d"), number);
       break;
     case bp_dprintf:
-      printf_filtered (_("Dprintf %d"), b->number);
+      gdb_printf (_("Dprintf %d"), number);
       break;
     }
 
-  say_where (b);
+  say_where ();
 }
 
-static void
-bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
-{
-  if (tp->type == bp_breakpoint && tp->disposition == disp_del)
-    fprintf_unfiltered (fp, "tbreak");
-  else if (tp->type == bp_breakpoint)
-    fprintf_unfiltered (fp, "break");
-  else if (tp->type == bp_hardware_breakpoint
-          && tp->disposition == disp_del)
-    fprintf_unfiltered (fp, "thbreak");
-  else if (tp->type == bp_hardware_breakpoint)
-    fprintf_unfiltered (fp, "hbreak");
+void
+ordinary_breakpoint::print_recreate (struct ui_file *fp) const
+{
+  if (type == bp_breakpoint && disposition == disp_del)
+    gdb_printf (fp, "tbreak");
+  else if (type == bp_breakpoint)
+    gdb_printf (fp, "break");
+  else if (type == bp_hardware_breakpoint
+          && disposition == disp_del)
+    gdb_printf (fp, "thbreak");
+  else if (type == bp_hardware_breakpoint)
+    gdb_printf (fp, "hbreak");
   else
-    internal_error (__FILE__, __LINE__,
-                   _("unhandled breakpoint type %d"), (int) tp->type);
+    internal_error (_("unhandled breakpoint type %d"), (int) type);
 
-  fprintf_unfiltered (fp, " %s",
-                     event_location_to_string (tp->location.get ()));
+  gdb_printf (fp, " %s", locspec->to_string ());
 
   /* 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.get ());
+  if (!this->has_locations () && extra_string != NULL)
+    gdb_printf (fp, " %s", extra_string.get ());
 
-  print_recreate_thread (tp, fp);
+  print_recreate_thread (fp);
 }
 
-static void
-bkpt_create_sals_from_location (struct event_location *location,
-                               struct linespec_result *canonical,
-                               enum bptype type_wanted)
+std::vector<symtab_and_line>
+code_breakpoint::decode_location_spec (location_spec *locspec,
+                                      program_space *search_pspace)
 {
-  create_sals_from_location_default (location, canonical, type_wanted);
-}
+  if (locspec->type () == PROBE_LOCATION_SPEC)
+    return bkpt_probe_decode_location_spec (this, locspec, search_pspace);
 
-static void
-bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
-                            struct linespec_result *canonical,
-                            gdb::unique_xmalloc_ptr<char> cond_string,
-                            gdb::unique_xmalloc_ptr<char> extra_string,
-                            enum bptype type_wanted,
-                            enum bpdisp disposition,
-                            int thread,
-                            int task, int ignore_count,
-                            const struct breakpoint_ops *ops,
-                            int from_tty, int enabled,
-                            int internal, unsigned flags)
-{
-  create_breakpoints_sal_default (gdbarch, canonical,
-                                 std::move (cond_string),
-                                 std::move (extra_string),
-                                 type_wanted,
-                                 disposition, thread, task,
-                                 ignore_count, ops, from_tty,
-                                 enabled, internal, flags);
-}
+  struct linespec_result canonical;
 
-static std::vector<symtab_and_line>
-bkpt_decode_location (struct breakpoint *b,
-                     struct event_location *location,
-                     struct program_space *search_pspace)
-{
-  return decode_location_default (b, location, search_pspace);
+  decode_line_full (locspec, DECODE_LINE_FUNFIRSTLINE, search_pspace,
+                   NULL, 0, &canonical, multiple_symbols_all,
+                   filter.get ());
+
+  /* We should get 0 or 1 resulting SALs.  */
+  gdb_assert (canonical.lsals.size () < 2);
+
+  if (!canonical.lsals.empty ())
+    {
+      const linespec_sals &lsal = canonical.lsals[0];
+      return std::move (lsal.sals);
+    }
+  return {};
 }
 
 /* Virtual table for internal breakpoints.  */
 
-static void
-internal_bkpt_re_set (struct breakpoint *b)
+void
+internal_breakpoint::re_set ()
 {
-  switch (b->type)
+  switch (type)
     {
       /* Delete overlay event and longjmp master breakpoints; they
         will be reset later by breakpoint_re_set.  */
@@ -12556,7 +12169,7 @@ internal_bkpt_re_set (struct breakpoint *b)
     case bp_longjmp_master:
     case bp_std_terminate_master:
     case bp_exception_master:
-      delete_breakpoint (b);
+      delete_breakpoint (this);
       break;
 
       /* This breakpoint is special, it's set up when the inferior
@@ -12570,80 +12183,76 @@ internal_bkpt_re_set (struct breakpoint *b)
     }
 }
 
-static void
-internal_bkpt_check_status (bpstat *bs)
+void
+internal_breakpoint::check_status (bpstat *bs)
 {
-  if (bs->breakpoint_at->type == bp_shlib_event)
+  if (type == bp_shlib_event)
     {
       /* If requested, stop when the dynamic linker notifies GDB of
         events.  This allows the user to get control and place
         breakpoints in initializer routines for dynamically loaded
         objects (among other things).  */
-      bs->stop = stop_on_solib_events;
-      bs->print = stop_on_solib_events;
+      bs->stop = stop_on_solib_events != 0;
+      bs->print = stop_on_solib_events != 0;
     }
   else
-    bs->stop = 0;
+    bs->stop = false;
 }
 
-static enum print_stop_action
-internal_bkpt_print_it (bpstat *bs)
+enum print_stop_action
+internal_breakpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b;
-
-  b = bs->breakpoint_at;
-
-  switch (b->type)
+  switch (type)
     {
     case bp_shlib_event:
       /* Did we stop because the user set the stop_on_solib_events
         variable?  (If so, we report this as a generic, "Stopped due
         to shlib event" message.) */
-      print_solib_event (0);
+      print_solib_event (false);
       break;
 
     case bp_thread_event:
       /* Not sure how we will get here.
         GDB should not stop for these breakpoints.  */
-      printf_filtered (_("Thread Event Breakpoint: gdb should not stop!\n"));
+      gdb_printf (_("Thread Event Breakpoint: gdb should not stop!\n"));
       break;
 
     case bp_overlay_event:
       /* By analogy with the thread event, GDB should not stop for these.  */
-      printf_filtered (_("Overlay Event Breakpoint: gdb should not stop!\n"));
+      gdb_printf (_("Overlay Event Breakpoint: gdb should not stop!\n"));
       break;
 
     case bp_longjmp_master:
       /* These should never be enabled.  */
-      printf_filtered (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
+      gdb_printf (_("Longjmp Master Breakpoint: gdb should not stop!\n"));
       break;
 
     case bp_std_terminate_master:
       /* These should never be enabled.  */
-      printf_filtered (_("std::terminate Master Breakpoint: "
-                        "gdb should not stop!\n"));
+      gdb_printf (_("std::terminate Master Breakpoint: "
+                   "gdb should not stop!\n"));
       break;
 
     case bp_exception_master:
       /* These should never be enabled.  */
-      printf_filtered (_("Exception Master Breakpoint: "
-                        "gdb should not stop!\n"));
+      gdb_printf (_("Exception Master Breakpoint: "
+                   "gdb should not stop!\n"));
       break;
     }
 
   return PRINT_NOTHING;
 }
 
-static void
-internal_bkpt_print_mention (struct breakpoint *b)
+void
+internal_breakpoint::print_mention () const
 {
   /* Nothing to mention.  These breakpoints are internal.  */
 }
 
 /* Virtual table for momentary breakpoints  */
 
-static void
-momentary_bkpt_re_set (struct breakpoint *b)
+void
+momentary_breakpoint::re_set ()
 {
   /* Keep temporary breakpoints, which can be encountered when we step
      over a dlopen call and solib_add is resetting the breakpoints.
@@ -12651,20 +12260,20 @@ momentary_bkpt_re_set (struct breakpoint *b)
      or by breakpoint_init_inferior when we rerun the executable.  */
 }
 
-static void
-momentary_bkpt_check_status (bpstat *bs)
+void
+momentary_breakpoint::check_status (bpstat *bs)
 {
   /* Nothing.  The point of these breakpoints is causing a stop.  */
 }
 
-static enum print_stop_action
-momentary_bkpt_print_it (bpstat *bs)
+enum print_stop_action
+momentary_breakpoint::print_it (const bpstat *bs) const
 {
   return PRINT_UNKNOWN;
 }
 
-static void
-momentary_bkpt_print_mention (struct breakpoint *b)
+void
+momentary_breakpoint::print_mention () const
 {
   /* Nothing to mention.  These breakpoints are internal.  */
 }
@@ -12682,211 +12291,120 @@ longjmp_breakpoint::~longjmp_breakpoint ()
     tp->initiating_frame = null_frame_id;
 }
 
-/* Specific methods for probe breakpoints.  */
-
-static int
-bkpt_probe_insert_location (struct bp_location *bl)
-{
-  int v = bkpt_insert_location (bl);
-
-  if (v == 0)
-    {
-      /* The insertion was successful, now let's set the probe's semaphore
-        if needed.  */
-      bl->probe.prob->set_semaphore (bl->probe.objfile, bl->gdbarch);
-    }
-
-  return v;
-}
-
-static int
-bkpt_probe_remove_location (struct bp_location *bl,
-                           enum remove_bp_reason reason)
-{
-  /* Let's clear the semaphore before removing the location.  */
-  bl->probe.prob->clear_semaphore (bl->probe.objfile, bl->gdbarch);
-
-  return bkpt_remove_location (bl, reason);
-}
-
 static void
-bkpt_probe_create_sals_from_location (struct event_location *location,
-                                     struct linespec_result *canonical,
-                                     enum bptype type_wanted)
+bkpt_probe_create_sals_from_location_spec (location_spec *locspec,
+                                          struct linespec_result *canonical)
+
 {
   struct linespec_sals lsal;
 
-  lsal.sals = parse_probes (location, NULL, canonical);
-  lsal.canonical
-    = xstrdup (event_location_to_string (canonical->location.get ()));
+  lsal.sals = parse_probes (locspec, NULL, canonical);
+  lsal.canonical = xstrdup (canonical->locspec->to_string ());
   canonical->lsals.push_back (std::move (lsal));
 }
 
 static std::vector<symtab_and_line>
-bkpt_probe_decode_location (struct breakpoint *b,
-                           struct event_location *location,
-                           struct program_space *search_pspace)
+bkpt_probe_decode_location_spec (struct breakpoint *b,
+                                location_spec *locspec,
+                                program_space *search_pspace)
 {
-  std::vector<symtab_and_line> sals = parse_probes (location, search_pspace, NULL);
+  std::vector<symtab_and_line> sals
+    = parse_probes (locspec, search_pspace, NULL);
   if (sals.empty ())
     error (_("probe not found"));
   return sals;
 }
 
-/* The breakpoint_ops structure to be used in tracepoints.  */
-
-static void
-tracepoint_re_set (struct breakpoint *b)
-{
-  breakpoint_re_set_default (b);
-}
-
-static int
-tracepoint_breakpoint_hit (const struct bp_location *bl,
-                          const address_space *aspace, CORE_ADDR bp_addr,
-                          const target_waitstatus &ws)
+int
+tracepoint::breakpoint_hit (const struct bp_location *bl,
+                           const address_space *aspace, CORE_ADDR bp_addr,
+                           const target_waitstatus &ws)
 {
   /* By definition, the inferior does not report stops at
      tracepoints.  */
   return 0;
 }
 
-static void
-tracepoint_print_one_detail (const struct breakpoint *self,
-                            struct ui_out *uiout)
+void
+tracepoint::print_one_detail (struct ui_out *uiout) const
 {
-  struct tracepoint *tp = (struct tracepoint *) self;
-  if (!tp->static_trace_marker_id.empty ())
+  if (!static_trace_marker_id.empty ())
     {
-      gdb_assert (self->type == bp_static_tracepoint);
+      gdb_assert (type == bp_static_tracepoint
+                 || type == bp_static_marker_tracepoint);
 
       uiout->message ("\tmarker id is %pF\n",
                      string_field ("static-tracepoint-marker-string-id",
-                                   tp->static_trace_marker_id.c_str ()));
+                                   static_trace_marker_id.c_str ()));
     }
 }
 
-static void
-tracepoint_print_mention (struct breakpoint *b)
+void
+tracepoint::print_mention () const
 {
   if (current_uiout->is_mi_like_p ())
     return;
 
-  switch (b->type)
+  switch (type)
     {
     case bp_tracepoint:
-      printf_filtered (_("Tracepoint"));
-      printf_filtered (_(" %d"), b->number);
+      gdb_printf (_("Tracepoint"));
+      gdb_printf (_(" %d"), number);
       break;
     case bp_fast_tracepoint:
-      printf_filtered (_("Fast tracepoint"));
-      printf_filtered (_(" %d"), b->number);
+      gdb_printf (_("Fast tracepoint"));
+      gdb_printf (_(" %d"), number);
       break;
     case bp_static_tracepoint:
-      printf_filtered (_("Static tracepoint"));
-      printf_filtered (_(" %d"), b->number);
+    case bp_static_marker_tracepoint:
+      gdb_printf (_("Static tracepoint"));
+      gdb_printf (_(" %d"), number);
       break;
     default:
-      internal_error (__FILE__, __LINE__,
-                     _("unhandled tracepoint type %d"), (int) b->type);
+      internal_error (_("unhandled tracepoint type %d"), (int) type);
     }
 
-  say_where (b);
+  say_where ();
 }
 
-static void
-tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
-{
-  struct tracepoint *tp = (struct tracepoint *) self;
-
-  if (self->type == bp_fast_tracepoint)
-    fprintf_unfiltered (fp, "ftrace");
-  else if (self->type == bp_static_tracepoint)
-    fprintf_unfiltered (fp, "strace");
-  else if (self->type == bp_tracepoint)
-    fprintf_unfiltered (fp, "trace");
+void
+tracepoint::print_recreate (struct ui_file *fp) const
+{
+  if (type == bp_fast_tracepoint)
+    gdb_printf (fp, "ftrace");
+  else if (type == bp_static_tracepoint
+          || type == bp_static_marker_tracepoint)
+    gdb_printf (fp, "strace");
+  else if (type == bp_tracepoint)
+    gdb_printf (fp, "trace");
   else
-    internal_error (__FILE__, __LINE__,
-                   _("unhandled tracepoint type %d"), (int) self->type);
-
-  fprintf_unfiltered (fp, " %s",
-                     event_location_to_string (self->location.get ()));
-  print_recreate_thread (self, fp);
-
-  if (tp->pass_count)
-    fprintf_unfiltered (fp, "  passcount %d\n", tp->pass_count);
-}
-
-static void
-tracepoint_create_sals_from_location (struct event_location *location,
-                                     struct linespec_result *canonical,
-                                     enum bptype type_wanted)
-{
-  create_sals_from_location_default (location, canonical, type_wanted);
-}
+    internal_error (_("unhandled tracepoint type %d"), (int) type);
 
-static void
-tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
-                                  struct linespec_result *canonical,
-                                  gdb::unique_xmalloc_ptr<char> cond_string,
-                                  gdb::unique_xmalloc_ptr<char> extra_string,
-                                  enum bptype type_wanted,
-                                  enum bpdisp disposition,
-                                  int thread,
-                                  int task, int ignore_count,
-                                  const struct breakpoint_ops *ops,
-                                  int from_tty, int enabled,
-                                  int internal, unsigned flags)
-{
-  create_breakpoints_sal_default (gdbarch, canonical,
-                                 std::move (cond_string),
-                                 std::move (extra_string),
-                                 type_wanted,
-                                 disposition, thread, task,
-                                 ignore_count, ops, from_tty,
-                                 enabled, internal, flags);
-}
+  gdb_printf (fp, " %s", locspec->to_string ());
+  print_recreate_thread (fp);
 
-static std::vector<symtab_and_line>
-tracepoint_decode_location (struct breakpoint *b,
-                           struct event_location *location,
-                           struct program_space *search_pspace)
-{
-  return decode_location_default (b, location, search_pspace);
+  if (pass_count)
+    gdb_printf (fp, "  passcount %d\n", pass_count);
 }
 
-struct breakpoint_ops tracepoint_breakpoint_ops;
-
 /* Virtual table for tracepoints on static probes.  */
 
 static void
-tracepoint_probe_create_sals_from_location
-  (struct event_location *location,
-   struct linespec_result *canonical,
-   enum bptype type_wanted)
+tracepoint_probe_create_sals_from_location_spec
+  (location_spec *locspec,
+   struct linespec_result *canonical)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_create_sals_from_location (location, canonical, type_wanted);
+  bkpt_probe_create_sals_from_location_spec (locspec, canonical);
 }
 
-static std::vector<symtab_and_line>
-tracepoint_probe_decode_location (struct breakpoint *b,
-                                 struct event_location *location,
-                                 struct program_space *search_pspace)
-{
-  /* We use the same method for breakpoint on probes.  */
-  return bkpt_probe_decode_location (b, location, search_pspace);
-}
-
-/* Dprintf breakpoint_ops methods.  */
-
-static void
-dprintf_re_set (struct breakpoint *b)
+void
+dprintf_breakpoint::re_set ()
 {
-  breakpoint_re_set_default (b);
+  re_set_default ();
 
   /* extra_string should never be non-NULL for dprintf.  */
-  gdb_assert (b->extra_string != NULL);
+  gdb_assert (extra_string != NULL);
 
   /* 1 - connect to target 1, that can run breakpoint commands.
      2 - create a dprintf, which resolves fine.
@@ -12898,23 +12416,20 @@ dprintf_re_set (struct breakpoint *b)
      answers for target_can_run_breakpoint_commands().
      Given absence of finer grained resetting, we get to do
      it all the time.  */
-  if (b->extra_string != NULL)
-    update_dprintf_command_list (b);
+  if (extra_string != NULL)
+    update_dprintf_command_list (this);
 }
 
-/* Implement the "print_recreate" breakpoint_ops method for dprintf.  */
+/* Implement the "print_recreate" method for dprintf.  */
 
-static void
-dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
+void
+dprintf_breakpoint::print_recreate (struct ui_file *fp) const
 {
-  fprintf_unfiltered (fp, "dprintf %s,%s",
-                     event_location_to_string (tp->location.get ()),
-                     tp->extra_string.get ());
-  print_recreate_thread (tp, fp);
+  gdb_printf (fp, "dprintf %s,%s", locspec->to_string (), extra_string.get ());
+  print_recreate_thread (fp);
 }
 
-/* Implement the "after_condition_true" breakpoint_ops method for
-   dprintf.
+/* Implement the "after_condition_true" method for dprintf.
 
    dprintf's are implemented with regular commands in their command
    list, but we run the commands here instead of before presenting the
@@ -12922,13 +12437,13 @@ dprintf_print_recreate (struct breakpoint *tp, struct ui_file *fp)
    also makes it so that the commands of multiple dprintfs at the same
    address are all handled.  */
 
-static void
-dprintf_after_condition_true (struct bpstat *bs)
+void
+dprintf_breakpoint::after_condition_true (struct bpstat *bs)
 {
   /* dprintf's never cause a stop.  This wasn't set in the
      check_status hook instead because that would make the dprintf's
      condition not be evaluated.  */
-  bs->stop = 0;
+  bs->stop = false;
 
   /* Run the command list here.  Take ownership of it instead of
      copying.  We never want these commands to run later in
@@ -12944,23 +12459,21 @@ dprintf_after_condition_true (struct bpstat *bs)
    markers (`-m').  */
 
 static void
-strace_marker_create_sals_from_location (struct event_location *location,
-                                        struct linespec_result *canonical,
-                                        enum bptype type_wanted)
+strace_marker_create_sals_from_location_spec (location_spec *locspec,
+                                             struct linespec_result *canonical)
 {
   struct linespec_sals lsal;
   const char *arg_start, *arg;
 
-  arg = arg_start = get_linespec_location (location)->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);
   const char *ptr = str.c_str ();
-  canonical->location
-    = new_linespec_location (&ptr, symbol_name_match_type::FULL);
+  canonical->locspec
+    = new_linespec_location_spec (&ptr, symbol_name_match_type::FULL);
 
-  lsal.canonical
-    = xstrdup (event_location_to_string (canonical->location.get ()));
+  lsal.canonical = xstrdup (canonical->locspec->to_string ());
   canonical->lsals.push_back (std::move (lsal));
 }
 
@@ -12972,8 +12485,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
                                      enum bptype type_wanted,
                                      enum bpdisp disposition,
                                      int thread,
-                                     int task, int ignore_count,
-                                     const struct breakpoint_ops *ops,
+                                     int task, int inferior,
+                                     int ignore_count,
                                      int from_tty, int enabled,
                                      int internal, unsigned flags)
 {
@@ -12988,18 +12501,21 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
 
   for (size_t i = 0; i < lsal.sals.size (); i++)
     {
-      event_location_up location
-       = copy_event_location (canonical->location.get ());
-
-      std::unique_ptr<tracepoint> tp (new tracepoint ());
-      init_breakpoint_sal (tp.get (), gdbarch, lsal.sals[i],
-                          std::move (location), NULL,
-                          std::move (cond_string),
-                          std::move (extra_string),
-                          type_wanted, disposition,
-                          thread, task, ignore_count, ops,
-                          from_tty, enabled, internal, flags,
-                          canonical->special_display);
+      location_spec_up locspec = canonical->locspec->clone ();
+
+      std::unique_ptr<tracepoint> tp
+       (new tracepoint (gdbarch,
+                        type_wanted,
+                        lsal.sals[i],
+                        std::move (locspec),
+                        NULL,
+                        std::move (cond_string),
+                        std::move (extra_string),
+                        disposition,
+                        thread, task, inferior, ignore_count,
+                        from_tty, enabled, flags,
+                        canonical->special_display));
+
       /* Given that its possible to have multiple markers with
         the same string id, if the user is creating a static
         tracepoint by marker id ("strace -m MARKER_ID"), then
@@ -13012,31 +12528,43 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
     }
 }
 
-static std::vector<symtab_and_line>
-strace_marker_decode_location (struct breakpoint *b,
-                              struct event_location *location,
-                              struct program_space *search_pspace)
+std::vector<symtab_and_line>
+static_marker_tracepoint::decode_location_spec (location_spec *locspec,
+                                               program_space *search_pspace)
 {
-  struct tracepoint *tp = (struct tracepoint *) b;
-  const char *s = get_linespec_location (location)->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 () > tp->static_trace_marker_id_idx)
+  if (sals.size () > static_trace_marker_id_idx)
     {
-      sals[0] = sals[tp->static_trace_marker_id_idx];
+      sals[0] = sals[static_trace_marker_id_idx];
       sals.resize (1);
       return sals;
     }
   else
-    error (_("marker %s not found"), tp->static_trace_marker_id.c_str ());
+    error (_("marker %s not found"), static_trace_marker_id.c_str ());
 }
 
-static struct breakpoint_ops strace_marker_breakpoint_ops;
+/* Static tracepoints with marker (`-m').  */
+static struct breakpoint_ops strace_marker_breakpoint_ops =
+{
+  strace_marker_create_sals_from_location_spec,
+  strace_marker_create_breakpoints_sal,
+};
 
-static int
+static bool
 strace_marker_p (struct breakpoint *b)
 {
-  return b->ops == &strace_marker_breakpoint_ops;
+  return b->type == bp_static_marker_tracepoint;
+}
+
+/* Notify interpreters and observers that breakpoint B was deleted.  */
+
+static void
+notify_breakpoint_deleted (breakpoint *b)
+{
+  interps_notify_breakpoint_deleted (b);
+  gdb::observers::breakpoint_deleted.notify (b);
 }
 
 /* Delete a breakpoint and clean up all traces of it in the data
@@ -13094,17 +12622,9 @@ delete_breakpoint (struct breakpoint *bpt)
      a problem in that process, we'll be asked to delete the half-created
      watchpoint.  In that case, don't announce the deletion.  */
   if (bpt->number)
-    gdb::observers::breakpoint_deleted.notify (bpt);
+    notify_breakpoint_deleted (bpt);
 
-  if (breakpoint_chain == bpt)
-    breakpoint_chain = bpt->next;
-
-  for (breakpoint *b : all_breakpoints ())
-    if (b->next == bpt)
-      {
-       b->next = bpt->next;
-       break;
-      }
+  breakpoint_chain.erase (breakpoint_chain.iterator_to (*bpt));
 
   /* Be sure no bpstat's are pointing at the breakpoint after it's
      been freed.  */
@@ -13123,7 +12643,11 @@ delete_breakpoint (struct breakpoint *bpt)
      belong to this breakpoint.  Do this before freeing the breakpoint
      itself, since remove_breakpoint looks at location's owner.  It
      might be better design to have location completely
-     self-contained, but it's not the case now.  */
+     self-contained, but it's not the case now.
+
+     Clear the location linked list first, otherwise, the intrusive_list
+     destructor accesses the locations after they are freed.  */
+  bpt->clear_locations ();
   update_global_location_list (UGLL_DONT_INSERT);
 
   /* On the chance that someone will soon try again to delete this
@@ -13179,8 +12703,8 @@ delete_command (const char *arg, int from_tty)
       /* Delete all breakpoints if no argument.  Do not delete
         internal breakpoints, these have to be deleted with an
         explicit breakpoint number argument.  */
-      for (breakpoint *b : all_breakpoints ())
-       if (user_breakpoint_p (b))
+      for (breakpoint &b : all_breakpoints ())
+       if (user_breakpoint_p (&b))
          {
            breaks_to_delete = 1;
            break;
@@ -13189,9 +12713,9 @@ delete_command (const char *arg, int from_tty)
       /* Ask user only if there are some breakpoints to delete.  */
       if (!from_tty
          || (breaks_to_delete && query (_("Delete all breakpoints? "))))
-       for (breakpoint *b : all_breakpoints_safe ())
-         if (user_breakpoint_p (b))
-           delete_breakpoint (b);
+       for (breakpoint &b : all_breakpoints_safe ())
+         if (user_breakpoint_p (&b))
+           delete_breakpoint (&b);
     }
   else
     map_breakpoint_numbers
@@ -13205,33 +12729,32 @@ delete_command (const char *arg, int from_tty)
    PSPACE is NULL, all locations of all program spaces are
    considered.  */
 
-static int
+static bool
 all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
 {
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     if ((pspace == NULL
-        || loc->pspace == pspace)
-       && !loc->shlib_disabled
-       && !loc->pspace->executing_startup)
-      return 0;
-  return 1;
+        || loc.pspace == pspace)
+       && !loc.shlib_disabled
+       && !loc.pspace->executing_startup)
+      return false;
+  return true;
 }
 
 /* Subroutine of update_breakpoint_locations to simplify it.
-   Return non-zero if multiple fns in list LOC have the same name.
+   Return true if multiple fns in list LOCS have the same name.
    Null names are ignored.  */
 
-static int
-ambiguous_names_p (struct bp_location *loc)
+static bool
+ambiguous_names_p (const bp_location_range &locs)
 {
-  struct bp_location *l;
   htab_up htab (htab_create_alloc (13, htab_hash_string, htab_eq_string, NULL,
                                   xcalloc, xfree));
 
-  for (l = loc; l != NULL; l = l->next)
+  for (const bp_location &l : locs)
     {
       const char **slot;
-      const char *name = l->function_name.get ();
+      const char *name = l.function_name.get ();
 
       /* Allow for some names to be NULL, ignore them.  */
       if (name == NULL)
@@ -13242,11 +12765,11 @@ ambiguous_names_p (struct bp_location *loc)
       /* NOTE: We can assume slot != NULL here because xcalloc never
         returns NULL.  */
       if (*slot != NULL)
-       return 1;
+       return true;
       *slot = name;
     }
 
-  return 0;
+  return false;
 }
 
 /* When symbols change, it probably means the sources changed as well,
@@ -13321,7 +12844,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];
 
@@ -13355,16 +12877,17 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
          uiout->field_signed ("line", sal2.line);
          uiout->text ("\n");
 
-         b->loc->line_number = sal2.line;
-         b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
+         b->first_loc ().line_number = sal2.line;
+         b->first_loc ().symtab = sym != NULL ? sal2.symtab : NULL;
+
+         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->first_loc ().line_number;
+         els->line_offset.sign = LINE_OFFSET_NONE;
 
-         b->location.reset (NULL);
-         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->location = new_explicit_location (&explicit_loc);
+         b->locspec = std::move (els);
 
          /* Might be nice to check if function changed, and warn if
             so.  */
@@ -13373,72 +12896,56 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
   return sal;
 }
 
-/* Returns 1 iff locations A and B are sufficiently same that
+/* Returns true iff location lists A and B are sufficiently same that
    we don't need to report breakpoint as changed.  */
 
-static int
-locations_are_equal (struct bp_location *a, struct bp_location *b)
+static bool
+locations_are_equal (const bp_location_list &a, const bp_location_range &b)
 {
-  while (a && b)
-    {
-      if (a->address != b->address)
-       return 0;
+  auto a_iter = a.begin ();
+  auto b_iter = b.begin ();
 
-      if (a->shlib_disabled != b->shlib_disabled)
-       return 0;
+  for (; a_iter != a.end () && b_iter != b.end (); ++a_iter, ++b_iter)
+    {
+      if (a_iter->address != b_iter->address)
+       return false;
 
-      if (a->enabled != b->enabled)
-       return 0;
+      if (a_iter->shlib_disabled != b_iter->shlib_disabled)
+       return false;
 
-      if (a->disabled_by_cond != b->disabled_by_cond)
-       return 0;
+      if (a_iter->enabled != b_iter->enabled)
+       return false;
 
-      a = a->next;
-      b = b->next;
+      if (a_iter->disabled_by_cond != b_iter->disabled_by_cond)
+       return false;
     }
 
-  if ((a == NULL) != (b == NULL))
-    return 0;
-
-  return 1;
+  return (a_iter == a.end ()) == (b_iter == b.end ());
 }
 
-/* Split all locations of B that are bound to PSPACE out of B's
-   location list to a separate list and return that list's head.  If
-   PSPACE is NULL, hoist out all locations of B.  */
+/* See breakpoint.h.  */
 
-static struct bp_location *
-hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
+bp_location_list
+breakpoint::steal_locations (program_space *pspace)
 {
-  struct bp_location head;
-  struct bp_location *i = b->loc;
-  struct bp_location **i_link = &b->loc;
-  struct bp_location *hoisted = &head;
-
   if (pspace == NULL)
-    {
-      i = b->loc;
-      b->loc = NULL;
-      return i;
-    }
+    return std::move (m_locations);
 
-  head.next = NULL;
+  bp_location_list ret;
 
-  while (i != NULL)
+  for (auto it = m_locations.begin (); it != m_locations.end (); )
     {
-      if (i->pspace == pspace)
+      if (it->pspace == pspace)
        {
-         *i_link = i->next;
-         i->next = NULL;
-         hoisted->next = i;
-         hoisted = i;
+         bp_location &loc = *it;
+         it = m_locations.erase (it);
+         ret.push_back (loc);
        }
       else
-       i_link = &i->next;
-      i = *i_link;
+       ++it;
     }
 
-  return head.next;
+  return ret;
 }
 
 /* Create new breakpoint locations for B (a hardware or software
@@ -13448,21 +12955,20 @@ hoist_existing_locations (struct breakpoint *b, struct program_space *pspace)
    untouched.  */
 
 void
-update_breakpoint_locations (struct breakpoint *b,
+update_breakpoint_locations (code_breakpoint *b,
                             struct program_space *filter_pspace,
                             gdb::array_view<const symtab_and_line> sals,
                             gdb::array_view<const symtab_and_line> sals_end)
 {
-  struct bp_location *existing_locations;
-
   if (!sals_end.empty () && (sals.size () != 1 || sals_end.size () != 1))
     {
       /* Ranged breakpoints have only one start location and one end
         location.  */
       b->enable_state = bp_disabled;
-      printf_unfiltered (_("Could not reset ranged breakpoint %d: "
-                          "multiple locations found\n"),
-                        b->number);
+      gdb_printf (gdb_stderr,
+                 _("Could not reset ranged breakpoint %d: "
+                   "multiple locations found\n"),
+                 b->number);
       return;
     }
 
@@ -13475,7 +12981,7 @@ update_breakpoint_locations (struct breakpoint *b,
   if (all_locations_are_pending (b, filter_pspace) && sals.empty ())
     return;
 
-  existing_locations = hoist_existing_locations (b, filter_pspace);
+  bp_location_list existing_locations = b->steal_locations (filter_pspace);
 
   for (const auto &sal : sals)
     {
@@ -13483,7 +12989,7 @@ update_breakpoint_locations (struct breakpoint *b,
 
       switch_to_program_space_and_thread (sal.pspace);
 
-      new_loc = add_location_to_breakpoint (b, &sal);
+      new_loc = b->add_location (sal);
 
       /* Reparse conditions, they might contain references to the
         old symtab.  */
@@ -13515,21 +13021,20 @@ update_breakpoint_locations (struct breakpoint *b,
   /* If possible, carry over 'disable' status from existing
      breakpoints.  */
   {
-    struct bp_location *e = existing_locations;
     /* If there are multiple breakpoints with the same function name,
        e.g. for inline functions, comparing function names won't work.
        Instead compare pc addresses; this is just a heuristic as things
        may have moved, but in practice it gives the correct answer
        often enough until a better solution is found.  */
-    int have_ambiguous_names = ambiguous_names_p (b->loc);
+    int have_ambiguous_names = ambiguous_names_p (b->locations ());
 
-    for (; e; e = e->next)
+    for (const bp_location &e : existing_locations)
       {
-       if ((!e->enabled || e->disabled_by_cond) && e->function_name)
+       if ((!e.enabled || e.disabled_by_cond) && e.function_name)
          {
            if (have_ambiguous_names)
              {
-               for (bp_location *l : b->locations ())
+               for (bp_location &l : b->locations ())
                  {
                    /* Ignore software vs hardware location type at
                       this point, because with "set breakpoint
@@ -13538,23 +13043,23 @@ update_breakpoint_locations (struct breakpoint *b,
                       As mentioned above, this is an heuristic and in
                       practice should give the correct answer often
                       enough.  */
-                   if (breakpoint_locations_match (e, l, true))
+                   if (breakpoint_locations_match (&e, &l, true))
                      {
-                       l->enabled = e->enabled;
-                       l->disabled_by_cond = e->disabled_by_cond;
+                       l.enabled = e.enabled;
+                       l.disabled_by_cond = e.disabled_by_cond;
                        break;
                      }
                  }
              }
            else
              {
-               for (bp_location *l : b->locations ())
-                 if (l->function_name
-                     && strcmp (e->function_name.get (),
-                                l->function_name.get ()) == 0)
+               for (bp_location &l : b->locations ())
+                 if (l.function_name
+                     && strcmp (e.function_name.get (),
+                                l.function_name.get ()) == 0)
                    {
-                     l->enabled = e->enabled;
-                     l->disabled_by_cond = e->disabled_by_cond;
+                     l.enabled = e.enabled;
+                     l.disabled_by_cond = e.disabled_by_cond;
                      break;
                    }
              }
@@ -13562,30 +13067,29 @@ update_breakpoint_locations (struct breakpoint *b,
       }
   }
 
-  if (!locations_are_equal (existing_locations, b->loc))
-    gdb::observers::breakpoint_modified.notify (b);
+  if (!locations_are_equal (existing_locations, b->locations ()))
+    notify_breakpoint_modified (b);
 }
 
-/* Find the SaL locations corresponding to the given LOCATION.
+/* Find the SaL locations corresponding to the given LOCSPEC.
    On return, FOUND will be 1 if any SaL was found, zero otherwise.  */
 
-static std::vector<symtab_and_line>
-location_to_sals (struct breakpoint *b, struct event_location *location,
-                 struct program_space *search_pspace, int *found)
+std::vector<symtab_and_line>
+code_breakpoint::location_spec_to_sals (location_spec *locspec,
+                                       struct program_space *search_pspace,
+                                       int *found)
 {
   struct gdb_exception exception;
 
-  gdb_assert (b->ops != NULL);
-
   std::vector<symtab_and_line> sals;
 
   try
     {
-      sals = b->ops->decode_location (b, location, search_pspace);
+      sals = decode_location_spec (locspec, search_pspace);
     }
   catch (gdb_exception_error &e)
     {
-      int not_found_and_ok = 0;
+      int not_found_and_ok = false;
 
       /* For pending breakpoints, it's expected that parsing will
         fail until the right shared library is loaded.  User has
@@ -13595,14 +13099,15 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
         breakpoint being disabled, and don't want to see more
         errors.  */
       if (e.error == NOT_FOUND_ERROR
-         && (b->condition_not_parsed
-             || (b->loc != NULL
+         && (condition_not_parsed
+             || (this->has_locations ()
                  && search_pspace != NULL
-                 && b->loc->pspace != search_pspace)
-             || (b->loc && b->loc->shlib_disabled)
-             || (b->loc && b->loc->pspace->executing_startup)
-             || b->enable_state == bp_disabled))
-       not_found_and_ok = 1;
+                 && this->first_loc ().pspace != search_pspace)
+             || (this->has_locations () && this->first_loc ().shlib_disabled)
+             || (this->has_locations ()
+                 && this->first_loc ().pspace->executing_startup)
+             || enable_state == bp_disabled))
+       not_found_and_ok = true;
 
       if (!not_found_and_ok)
        {
@@ -13612,7 +13117,7 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
             have separate 'warning emitted' flag.  Since this
             happens only when a binary has changed, I don't know
             which approach is better.  */
-         b->enable_state = bp_disabled;
+         enable_state = bp_disabled;
          throw;
        }
 
@@ -13623,26 +13128,27 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
     {
       for (auto &sal : sals)
        resolve_sal_pc (&sal);
-      if (b->condition_not_parsed && b->extra_string != NULL)
+      if (condition_not_parsed && extra_string != NULL)
        {
-         gdb::unique_xmalloc_ptr<char> cond_string, extra_string;
-         int thread, task;
+         gdb::unique_xmalloc_ptr<char> local_cond, local_extra;
+         int local_thread, local_task, local_inferior;
 
-         find_condition_and_thread_for_sals (sals, b->extra_string.get (),
-                                             &cond_string, &thread,
-                                             &task, &extra_string);
-         gdb_assert (b->cond_string == NULL);
-         if (cond_string)
-           b->cond_string = std::move (cond_string);
-         b->thread = thread;
-         b->task = task;
-         if (extra_string)
-           b->extra_string = std::move (extra_string);
-         b->condition_not_parsed = 0;
+         find_condition_and_thread_for_sals (sals, extra_string.get (),
+                                             &local_cond, &local_thread,
+                                             &local_inferior,
+                                             &local_task, &local_extra);
+         gdb_assert (cond_string == nullptr);
+         if (local_cond != nullptr)
+           cond_string = std::move (local_cond);
+         thread = local_thread;
+         task = local_task;
+         if (local_extra != nullptr)
+           extra_string = std::move (local_extra);
+         condition_not_parsed = 0;
        }
 
-      if (b->type == bp_static_tracepoint && !strace_marker_p (b))
-       sals[0] = update_static_tracepoint (b, sals[0]);
+      if (type == bp_static_tracepoint)
+       sals[0] = update_static_tracepoint (this, sals[0]);
 
       *found = 1;
     }
@@ -13656,89 +13162,39 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
    breakpoints.  Reevaluate the breakpoint and recreate its
    locations.  */
 
-static void
-breakpoint_re_set_default (struct breakpoint *b)
+void
+code_breakpoint::re_set_default ()
 {
   struct program_space *filter_pspace = current_program_space;
   std::vector<symtab_and_line> expanded, expanded_end;
 
   int found;
-  std::vector<symtab_and_line> sals = location_to_sals (b, b->location.get (),
-                                                       filter_pspace, &found);
+  std::vector<symtab_and_line> sals = location_spec_to_sals (locspec.get (),
+                                                            filter_pspace,
+                                                            &found);
   if (found)
     expanded = std::move (sals);
 
-  if (b->location_range_end != NULL)
+  if (locspec_range_end != nullptr)
     {
       std::vector<symtab_and_line> sals_end
-       = location_to_sals (b, b->location_range_end.get (),
-                           filter_pspace, &found);
+       = location_spec_to_sals (locspec_range_end.get (),
+                                filter_pspace, &found);
       if (found)
        expanded_end = std::move (sals_end);
     }
 
-  update_breakpoint_locations (b, filter_pspace, expanded, expanded_end);
+  update_breakpoint_locations (this, filter_pspace, expanded, expanded_end);
 }
 
 /* Default method for creating SALs from an address string.  It basically
    calls parse_breakpoint_sals.  Return 1 for success, zero for failure.  */
 
 static void
-create_sals_from_location_default (struct event_location *location,
-                                  struct linespec_result *canonical,
-                                  enum bptype type_wanted)
-{
-  parse_breakpoint_sals (location, canonical);
-}
-
-/* Call create_breakpoints_sal for the given arguments.  This is the default
-   function for the `create_breakpoints_sal' method of
-   breakpoint_ops.  */
-
-static void
-create_breakpoints_sal_default (struct gdbarch *gdbarch,
-                               struct linespec_result *canonical,
-                               gdb::unique_xmalloc_ptr<char> cond_string,
-                               gdb::unique_xmalloc_ptr<char> extra_string,
-                               enum bptype type_wanted,
-                               enum bpdisp disposition,
-                               int thread,
-                               int task, int ignore_count,
-                               const struct breakpoint_ops *ops,
-                               int from_tty, int enabled,
-                               int internal, unsigned flags)
-{
-  create_breakpoints_sal (gdbarch, canonical,
-                         std::move (cond_string),
-                         std::move (extra_string),
-                         type_wanted, disposition,
-                         thread, task, ignore_count, ops, from_tty,
-                         enabled, internal, flags);
-}
-
-/* Decode the line represented by S by calling decode_line_full.  This is the
-   default function for the `decode_location' method of breakpoint_ops.  */
-
-static std::vector<symtab_and_line>
-decode_location_default (struct breakpoint *b,
-                        struct event_location *location,
-                        struct program_space *search_pspace)
+create_sals_from_location_spec_default (location_spec *locspec,
+                                       struct linespec_result *canonical)
 {
-  struct linespec_result canonical;
-
-  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE, search_pspace,
-                   NULL, 0, &canonical, multiple_symbols_all,
-                   b->filter.get ());
-
-  /* We should get 0 or 1 resulting SALs.  */
-  gdb_assert (canonical.lsals.size () < 2);
-
-  if (!canonical.lsals.empty ())
-    {
-      const linespec_sals &lsal = canonical.lsals[0];
-      return std::move (lsal.sals);
-    }
-  return {};
+  parse_breakpoint_sals (locspec, canonical);
 }
 
 /* Reset a breakpoint.  */
@@ -13749,7 +13205,7 @@ breakpoint_re_set_one (breakpoint *b)
   input_radix = b->input_radix;
   set_language (b->language);
 
-  b->ops->re_set (b);
+  b->re_set ();
 }
 
 /* Re-set breakpoint locations for the current program space.
@@ -13781,17 +13237,17 @@ breakpoint_re_set (void)
        breakpoint 1, we'd insert the locations of breakpoint 2, which
        hadn't been re-set yet, and thus may have stale locations.  */
 
-    for (breakpoint *b : all_breakpoints_safe ())
+    for (breakpoint &b : all_breakpoints_safe ())
       {
        try
          {
-           breakpoint_re_set_one (b);
+           breakpoint_re_set_one (&b);
          }
        catch (const gdb_exception &ex)
          {
            exception_fprintf (gdb_stderr, ex,
                               "Error in re-setting breakpoint %d: ",
-                              b->number);
+                              b.number);
          }
       }
 
@@ -13822,7 +13278,7 @@ breakpoint_re_set_thread (struct breakpoint *b)
         selected as current, and unless this was a vfork will have a
         different program space from the original thread.  Reset that
         as well.  */
-      b->loc->pspace = current_program_space;
+      b->first_loc ().pspace = current_program_space;
     }
 }
 
@@ -13836,33 +13292,33 @@ set_ignore_count (int bptnum, int count, int from_tty)
   if (count < 0)
     count = 0;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == bptnum)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == bptnum)
       {
-       if (is_tracepoint (b))
+       if (is_tracepoint (&b))
          {
            if (from_tty && count != 0)
-             printf_filtered (_("Ignore count ignored for tracepoint %d."),
-                              bptnum);
+             gdb_printf (_("Ignore count ignored for tracepoint %d."),
+                         bptnum);
            return;
          }
 
-       b->ignore_count = count;
+       b.ignore_count = count;
        if (from_tty)
          {
            if (count == 0)
-             printf_filtered (_("Will stop next time "
-                                "breakpoint %d is reached."),
-                              bptnum);
+             gdb_printf (_("Will stop next time "
+                           "breakpoint %d is reached."),
+                         bptnum);
            else if (count == 1)
-             printf_filtered (_("Will ignore next crossing of breakpoint %d."),
-                              bptnum);
+             gdb_printf (_("Will ignore next crossing of breakpoint %d."),
+                         bptnum);
            else
-             printf_filtered (_("Will ignore next %d "
-                                "crossings of breakpoint %d."),
-                              count, bptnum);
+             gdb_printf (_("Will ignore next %d "
+                           "crossings of breakpoint %d."),
+                         count, bptnum);
          }
-       gdb::observers::breakpoint_modified.notify (b);
+       notify_breakpoint_modified (&b);
        return;
       }
 
@@ -13890,7 +13346,7 @@ ignore_command (const char *args, int from_tty)
                    longest_to_int (value_as_long (parse_and_eval (p))),
                    from_tty);
   if (from_tty)
-    printf_filtered ("\n");
+    gdb_printf ("\n");
 }
 \f
 
@@ -13912,15 +13368,15 @@ map_breakpoint_number_range (std::pair<int, int> bp_num_range,
        {
          bool match = false;
 
-         for (breakpoint *b : all_breakpoints_safe ())
-           if (b->number == i)
+         for (breakpoint &b : all_breakpoints_safe ())
+           if (b.number == i)
              {
                match = true;
-               function (b);
+               function (&b);
                break;
              }
          if (!match)
-           printf_filtered (_("No breakpoint number %d.\n"), i);
+           gdb_printf (_("No breakpoint number %d.\n"), i);
        }
     }
 }
@@ -13959,9 +13415,9 @@ find_location_by_number (int bp_num, int loc_num)
     error (_("Bad breakpoint location number '%d'"), loc_num);
 
   int n = 0;
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     if (++n == loc_num)
-      return loc;
+      return &loc;
 
   error (_("Bad breakpoint location number '%d'"), loc_num);
 }
@@ -14116,7 +13572,64 @@ enable_disable_bp_num_loc (int bp_num, int loc_num, bool enable)
     }
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (loc->owner);
+  notify_breakpoint_modified (loc->owner);
+}
+
+/* Calculates LOC_NUM for LOC by traversing the bp_location chain of LOC's
+   owner.  1-based indexing.  -1 signals NOT FOUND.  */
+
+static int
+find_loc_num_by_location (const bp_location *loc)
+{
+  if (loc != nullptr && loc->owner != nullptr)
+    {
+      /* Locations use 1-based indexing.  */
+      int loc_num = 1;
+      for (bp_location &it : loc->owner->locations ())
+       {
+         if (&it == loc)
+           return loc_num;
+         loc_num++;
+       }
+    }
+  return -1;
+}
+
+/* Enable or disable a breakpoint location LOC.  ENABLE
+   specifies whether to enable or disable.  */
+
+void
+enable_disable_bp_location (bp_location *loc, bool enable)
+{
+  if (loc == nullptr)
+    error (_("Breakpoint location is invalid."));
+
+  if (loc->owner == nullptr)
+    error (_("Breakpoint location does not have an owner breakpoint."));
+
+  if (loc->disabled_by_cond && enable)
+    {
+      int loc_num = find_loc_num_by_location (loc);
+      if (loc_num == -1)
+       error (_("Breakpoint location LOC_NUM could not be found."));
+      else
+       error (_("Breakpoint %d's condition is invalid at location %d, "
+                "cannot enable."), loc->owner->number, loc_num);
+    }
+
+  if (loc->enabled != enable)
+    {
+      loc->enabled = enable;
+      mark_breakpoint_location_modified (loc);
+    }
+
+  if (target_supports_enable_disable_tracepoint ()
+      && current_trace_status ()->running && loc->owner
+      && is_tracepoint (loc->owner))
+    target_disable_tracepoint (loc);
+
+  update_global_location_list (UGLL_DONT_INSERT);
+  notify_breakpoint_modified (loc->owner);
 }
 
 /* Enable or disable a range of breakpoint locations.  BP_NUM is the
@@ -14155,13 +13668,13 @@ disable_breakpoint (struct breakpoint *bpt)
   if (target_supports_enable_disable_tracepoint ()
       && current_trace_status ()->running && is_tracepoint (bpt))
     {
-      for (bp_location *location : bpt->locations ())
-       target_disable_tracepoint (location);
+      for (bp_location &location : bpt->locations ())
+       target_disable_tracepoint (&location);
     }
 
   update_global_location_list (UGLL_DONT_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 /* Enable or disable the breakpoint(s) or breakpoint location(s)
@@ -14174,13 +13687,13 @@ enable_disable_command (const char *args, int from_tty, bool enable)
 {
   if (args == 0)
     {
-      for (breakpoint *bpt : all_breakpoints ())
-       if (user_breakpoint_p (bpt))
+      for (breakpoint &bpt : all_breakpoints ())
+       if (user_breakpoint_p (&bpt))
          {
            if (enable)
-             enable_breakpoint (bpt);
+             enable_breakpoint (&bpt);
            else
-             disable_breakpoint (bpt);
+             disable_breakpoint (&bpt);
          }
     }
   else
@@ -14194,9 +13707,13 @@ enable_disable_command (const char *args, int from_tty, bool enable)
          extract_bp_number_and_location (num, bp_num_range, bp_loc_range);
 
          if (bp_loc_range.first == bp_loc_range.second
-             && bp_loc_range.first == 0)
+             && (bp_loc_range.first == 0
+                 || (bp_loc_range.first == 1
+                     && bp_num_range.first == bp_num_range.second
+                     && !has_multiple_locations (bp_num_range.first))))
            {
-             /* Handle breakpoint ids with formats 'x' or 'x-z'.  */
+             /* Handle breakpoint ids with formats 'x' or 'x-z'
+                or 'y.1' where y has only one code location.  */
              map_breakpoint_number_range (bp_num_range,
                                           enable
                                           ? enable_breakpoint
@@ -14255,9 +13772,9 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
 
          orig_enable_state = bpt->enable_state;
          bpt->enable_state = bp_enabled;
-         update_watchpoint (w, 1 /* reparse */);
+         update_watchpoint (w, true /* reparse */);
        }
-      catch (const gdb_exception &e)
+      catch (const gdb_exception_error &e)
        {
          bpt->enable_state = orig_enable_state;
          exception_fprintf (gdb_stderr, e, _("Cannot enable watchpoint %d: "),
@@ -14274,15 +13791,15 @@ enable_breakpoint_disp (struct breakpoint *bpt, enum bpdisp disposition,
   if (target_supports_enable_disable_tracepoint ()
       && current_trace_status ()->running && is_tracepoint (bpt))
     {
-      for (bp_location *location : bpt->locations ())
-       target_enable_tracepoint (location);
+      for (bp_location &location : bpt->locations ())
+       target_enable_tracepoint (&location);
     }
 
   bpt->disposition = disposition;
   bpt->enable_count = count;
   update_global_location_list (UGLL_MAY_INSERT);
 
-  gdb::observers::breakpoint_modified.notify (bpt);
+  notify_breakpoint_modified (bpt);
 }
 
 
@@ -14361,21 +13878,21 @@ invalidate_bp_value_on_memory_change (struct inferior *inferior,
                                      CORE_ADDR addr, ssize_t len,
                                      const bfd_byte *data)
 {
-  for (breakpoint *bp : all_breakpoints ())
-    if (bp->enable_state == bp_enabled
-       && bp->type == bp_hardware_watchpoint)
+  for (breakpoint &bp : all_breakpoints ())
+    if (bp.enable_state == bp_enabled
+       && bp.type == bp_hardware_watchpoint)
       {
-       struct watchpoint *wp = (struct watchpoint *) bp;
+       watchpoint &wp = gdb::checked_static_cast<watchpoint &> (bp);
 
-       if (wp->val_valid && wp->val != nullptr)
+       if (wp.val_valid && wp.val != nullptr)
          {
-           for (bp_location *loc : bp->locations ())
-             if (loc->loc_type == bp_loc_hardware_watchpoint
-                 && loc->address + loc->length > addr
-                 && addr + len > loc->address)
+           for (bp_location &loc : bp.locations ())
+             if (loc.loc_type == bp_loc_hardware_watchpoint
+                 && loc.address + loc.length > addr
+                 && addr + len > loc.address)
                {
-                 wp->val = NULL;
-                 wp->val_valid = false;
+                 wp.val = NULL;
+                 wp.val_valid = false;
                }
          }
       }
@@ -14394,15 +13911,25 @@ insert_single_step_breakpoint (struct gdbarch *gdbarch,
 
   if (tp->control.single_step_breakpoints == NULL)
     {
+      std::unique_ptr<breakpoint> b
+       (new momentary_breakpoint (gdbarch, bp_single_step,
+                                  current_program_space,
+                                  null_frame_id,
+                                  tp->global_num));
+
       tp->control.single_step_breakpoints
-       = new_single_step_breakpoint (tp->global_num, gdbarch);
+       = add_to_breakpoint_chain (std::move (b));
     }
 
   sal = find_pc_line (pc, 0);
   sal.pc = pc;
   sal.section = find_pc_overlay (pc);
   sal.explicit_pc = 1;
-  add_location_to_breakpoint (tp->control.single_step_breakpoints, &sal);
+
+  auto *ss_bp
+    = (gdb::checked_static_cast<momentary_breakpoint *>
+       (tp->control.single_step_breakpoints));
+  ss_bp->add_location (sal);
 
   update_global_location_list (UGLL_INSERT);
 }
@@ -14419,7 +13946,7 @@ insert_single_step_breakpoints (struct gdbarch *gdbarch)
 
   if (!next_pcs.empty ())
     {
-      struct frame_info *frame = get_current_frame ();
+      frame_info_ptr frame = get_current_frame ();
       const address_space *aspace = get_frame_address_space (frame);
 
       for (CORE_ADDR pc : next_pcs)
@@ -14438,9 +13965,9 @@ breakpoint_has_location_inserted_here (struct breakpoint *bp,
                                       const address_space *aspace,
                                       CORE_ADDR pc)
 {
-  for (bp_location *loc : bp->locations ())
-    if (loc->inserted
-       && breakpoint_location_address_match (loc, aspace, pc))
+  for (bp_location &loc : bp->locations ())
+    if (loc.inserted
+       && breakpoint_location_address_match (&loc, aspace, pc))
       return 1;
 
   return 0;
@@ -14453,10 +13980,10 @@ int
 single_step_breakpoint_inserted_here_p (const address_space *aspace,
                                        CORE_ADDR pc)
 {
-  for (breakpoint *bpt : all_breakpoints ())
+  for (breakpoint &bpt : all_breakpoints ())
     {
-      if (bpt->type == bp_single_step
-         && breakpoint_has_location_inserted_here (bpt, aspace, pc))
+      if (bpt.type == bp_single_step
+         && breakpoint_has_location_inserted_here (&bpt, aspace, pc))
        return 1;
     }
   return 0;
@@ -14475,14 +14002,14 @@ set_tracepoint_count (int num)
 static void
 trace_command (const char *arg, int from_tty)
 {
-  event_location_up location = string_to_event_location (&arg,
-                                                        current_language);
-  const struct breakpoint_ops *ops = breakpoint_ops_for_event_location
-    (location.get (), true /* is_tracepoint */);
+  location_spec_up locspec = string_to_location_spec (&arg,
+                                                     current_language);
+  const struct breakpoint_ops *ops = breakpoint_ops_for_location_spec
+    (locspec.get (), true /* is_tracepoint */);
 
   create_breakpoint (get_current_arch (),
-                    location.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    locspec.get (),
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
                     bp_tracepoint /* type_wanted */,
                     0 /* Ignore count */,
@@ -14496,16 +14023,16 @@ trace_command (const char *arg, int from_tty)
 static void
 ftrace_command (const char *arg, int from_tty)
 {
-  event_location_up location = string_to_event_location (&arg,
-                                                        current_language);
+  location_spec_up locspec = string_to_location_spec (&arg,
+                                                     current_language);
   create_breakpoint (get_current_arch (),
-                    location.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    locspec.get (),
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
                     bp_fast_tracepoint /* type_wanted */,
                     0 /* Ignore count */,
                     pending_break_support,
-                    &tracepoint_breakpoint_ops,
+                    &code_breakpoint_ops,
                     from_tty,
                     1 /* enabled */,
                     0 /* internal */, 0);
@@ -14516,27 +14043,31 @@ ftrace_command (const char *arg, int from_tty)
 static void
 strace_command (const char *arg, int from_tty)
 {
-  struct breakpoint_ops *ops;
-  event_location_up location;
+  const struct breakpoint_ops *ops;
+  location_spec_up locspec;
+  enum bptype type;
 
   /* 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;
-      location = new_linespec_location (&arg, symbol_name_match_type::FULL);
+      locspec = new_linespec_location_spec (&arg,
+                                           symbol_name_match_type::FULL);
+      type = bp_static_marker_tracepoint;
     }
   else
     {
-      ops = &tracepoint_breakpoint_ops;
-      location = string_to_event_location (&arg, current_language);
+      ops = &code_breakpoint_ops;
+      locspec = string_to_location_spec (&arg, current_language);
+      type = bp_static_tracepoint;
     }
 
   create_breakpoint (get_current_arch (),
-                    location.get (),
-                    NULL, 0, arg, false, 1 /* parse arg */,
+                    locspec.get (),
+                    NULL, -1, -1, arg, false, 1 /* parse arg */,
                     0 /* tempflag */,
-                    bp_static_tracepoint /* type_wanted */,
+                    type /* type_wanted */,
                     0 /* Ignore count */,
                     pending_break_support,
                     ops,
@@ -14551,8 +14082,8 @@ strace_command (const char *arg, int from_tty)
 static struct uploaded_tp *this_utp;
 static int next_cmd;
 
-static char *
-read_uploaded_action (void)
+static const char *
+read_uploaded_action (std::string &buffer)
 {
   char *rslt = nullptr;
 
@@ -14599,18 +14130,18 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
               "has no source form, ignoring it"),
             utp->number);
 
-  event_location_up location = string_to_event_location (&addr_str,
-                                                        current_language);
+  location_spec_up locspec = string_to_location_spec (&addr_str,
+                                                     current_language);
   if (!create_breakpoint (get_current_arch (),
-                         location.get (),
-                         utp->cond_string.get (), -1, addr_str,
+                         locspec.get (),
+                         utp->cond_string.get (), -1, -1, addr_str,
                          false /* force_condition */,
                          0 /* parse cond/thread */,
                          0 /* tempflag */,
                          utp->type /* type_wanted */,
                          0 /* Ignore count */,
                          pending_break_support,
-                         &tracepoint_breakpoint_ops,
+                         &code_breakpoint_ops,
                          0 /* from_tty */,
                          utp->enabled /* enabled */,
                          0 /* internal */,
@@ -14709,8 +14240,8 @@ delete_trace_command (const char *arg, int from_tty)
         Do not delete internal or call-dummy breakpoints, these
         have to be deleted with an explicit breakpoint number 
         argument.  */
-      for (breakpoint *tp : all_tracepoints ())
-       if (is_tracepoint (tp) && user_breakpoint_p (tp))
+      for (breakpoint &tp : all_tracepoints ())
+       if (is_tracepoint (&tp) && user_breakpoint_p (&tp))
          {
            breaks_to_delete = 1;
            break;
@@ -14720,9 +14251,9 @@ delete_trace_command (const char *arg, int from_tty)
       if (!from_tty
          || (breaks_to_delete && query (_("Delete all tracepoints? "))))
        {
-         for (breakpoint *b : all_breakpoints_safe ())
-           if (is_tracepoint (b) && user_breakpoint_p (b))
-             delete_breakpoint (b);
+         for (breakpoint &b : all_breakpoints_safe ())
+           if (is_tracepoint (&b) && user_breakpoint_p (&b))
+             delete_breakpoint (&b);
        }
     }
   else
@@ -14739,10 +14270,10 @@ static void
 trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
 {
   tp->pass_count = count;
-  gdb::observers::breakpoint_modified.notify (tp);
+  notify_breakpoint_modified (tp);
   if (from_tty)
-    printf_filtered (_("Setting tracepoint %d's passcount to %d\n"),
-                    tp->number, count);
+    gdb_printf (_("Setting tracepoint %d's passcount to %d\n"),
+               tp->number, count);
 }
 
 /* Set passcount for tracepoint.
@@ -14754,7 +14285,6 @@ trace_pass_set_count (struct tracepoint *tp, int count, int from_tty)
 static void
 trace_pass_command (const char *args, int from_tty)
 {
-  struct tracepoint *t1;
   ULONGEST count;
 
   if (args == 0 || *args == 0)
@@ -14770,15 +14300,15 @@ trace_pass_command (const char *args, int from_tty)
       if (*args)
        error (_("Junk at end of arguments."));
 
-      for (breakpoint *b : all_tracepoints ())
+      for (breakpoint &b : all_tracepoints ())
        {
-         t1 = (struct tracepoint *) b;
-         trace_pass_set_count (t1, count, from_tty);
+         tracepoint &t1 = gdb::checked_static_cast<tracepoint &> (b);
+         trace_pass_set_count (&t1, count, from_tty);
        }
     }
   else if (*args == '\0')
     {
-      t1 = get_tracepoint_by_number (&args, NULL);
+      tracepoint *t1 = get_tracepoint_by_number (&args, NULL);
       if (t1)
        trace_pass_set_count (t1, count, from_tty);
     }
@@ -14787,7 +14317,7 @@ trace_pass_command (const char *args, int from_tty)
       number_or_range_parser parser (args);
       while (!parser.finished ())
        {
-         t1 = get_tracepoint_by_number (&args, &parser);
+         tracepoint *t1 = get_tracepoint_by_number (&args, &parser);
          if (t1)
            trace_pass_set_count (t1, count, from_tty);
        }
@@ -14797,9 +14327,9 @@ trace_pass_command (const char *args, int from_tty)
 struct tracepoint *
 get_tracepoint (int num)
 {
-  for (breakpoint *t : all_tracepoints ())
-    if (t->number == num)
-      return (struct tracepoint *) t;
+  for (breakpoint &t : all_tracepoints ())
+    if (t.number == num)
+      return gdb::checked_static_cast<tracepoint *> (&t);
 
   return NULL;
 }
@@ -14811,12 +14341,12 @@ get_tracepoint (int num)
 struct tracepoint *
 get_tracepoint_by_number_on_target (int num)
 {
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      struct tracepoint *t = (struct tracepoint *) b;
+      tracepoint &t = gdb::checked_static_cast<tracepoint &> (b);
 
-      if (t->number_on_target == num)
-       return t;
+      if (t.number_on_target == num)
+       return &t;
     }
 
   return NULL;
@@ -14847,31 +14377,34 @@ get_tracepoint_by_number (const char **arg,
   if (tpnum <= 0)
     {
       if (instring && *instring)
-       printf_filtered (_("bad tracepoint number at or near '%s'\n"), 
-                        instring);
+       gdb_printf (_("bad tracepoint number at or near '%s'\n"), 
+                   instring);
       else
-       printf_filtered (_("No previous tracepoint\n"));
+       gdb_printf (_("No previous tracepoint\n"));
       return NULL;
     }
 
-  for (breakpoint *t : all_tracepoints ())
-    if (t->number == tpnum)
-      return (struct tracepoint *) t;
+  for (breakpoint &t : all_tracepoints ())
+    if (t.number == tpnum)
+      return gdb::checked_static_cast<tracepoint *> (&t);
 
-  printf_filtered ("No tracepoint number %d.\n", tpnum);
+  gdb_printf ("No tracepoint number %d.\n", tpnum);
   return NULL;
 }
 
 void
-print_recreate_thread (struct breakpoint *b, struct ui_file *fp)
+breakpoint::print_recreate_thread (struct ui_file *fp) const
 {
-  if (b->thread != -1)
-    fprintf_unfiltered (fp, " thread %d", b->thread);
+  if (thread != -1)
+    {
+      struct thread_info *thr = find_thread_global_id (thread);
+      gdb_printf (fp, " thread %s", print_full_thread_id (thr));
+    }
 
-  if (b->task != 0)
-    fprintf_unfiltered (fp, " task %d", b->task);
+  if (task != -1)
+    gdb_printf (fp, " task %d", task);
 
-  fprintf_unfiltered (fp, "\n");
+  gdb_printf (fp, "\n");
 }
 
 /* Save information on user settable breakpoints (watchpoints, etc) to
@@ -14883,26 +14416,26 @@ static void
 save_breakpoints (const char *filename, int from_tty,
                  bool (*filter) (const struct breakpoint *))
 {
-  int any = 0;
+  bool any = false;
   int extra_trace_bits = 0;
 
   if (filename == 0 || *filename == 0)
     error (_("Argument required (file name in which to save)"));
 
   /* See if we have anything to save.  */
-  for (breakpoint *tp : all_breakpoints ())
+  for (breakpoint &tp : all_breakpoints ())
     {
       /* Skip internal and momentary breakpoints.  */
-      if (!user_breakpoint_p (tp))
+      if (!user_breakpoint_p (&tp))
        continue;
 
       /* If we have a filter, only save the breakpoints it accepts.  */
-      if (filter && !filter (tp))
+      if (filter && !filter (&tp))
        continue;
 
-      any = 1;
+      any = true;
 
-      if (is_tracepoint (tp))
+      if (is_tracepoint (&tp))
        {
          extra_trace_bits = 1;
 
@@ -14928,60 +14461,51 @@ save_breakpoints (const char *filename, int from_tty,
   if (extra_trace_bits)
     save_trace_state_variables (&fp);
 
-  for (breakpoint *tp : all_breakpoints ())
+  for (breakpoint &tp : all_breakpoints ())
     {
       /* Skip internal and momentary breakpoints.  */
-      if (!user_breakpoint_p (tp))
+      if (!user_breakpoint_p (&tp))
        continue;
 
       /* If we have a filter, only save the breakpoints it accepts.  */
-      if (filter && !filter (tp))
+      if (filter && !filter (&tp))
        continue;
 
-      tp->ops->print_recreate (tp, &fp);
+      tp.print_recreate (&fp);
 
       /* Note, we can't rely on tp->number for anything, as we can't
         assume the recreated breakpoint numbers will match.  Use $bpnum
         instead.  */
 
-      if (tp->cond_string)
-       fp.printf ("  condition $bpnum %s\n", tp->cond_string.get ());
+      if (tp.cond_string)
+       fp.printf ("  condition $bpnum %s\n", tp.cond_string.get ());
 
-      if (tp->ignore_count)
-       fp.printf ("  ignore $bpnum %d\n", tp->ignore_count);
+      if (tp.ignore_count)
+       fp.printf ("  ignore $bpnum %d\n", tp.ignore_count);
 
-      if (tp->type != bp_dprintf && tp->commands)
+      if (tp.type != bp_dprintf && tp.commands)
        {
          fp.puts ("  commands\n");
 
-         current_uiout->redirect (&fp);
-         try
-           {
-             print_command_lines (current_uiout, tp->commands.get (), 2);
-           }
-         catch (const gdb_exception &ex)
-           {
-           current_uiout->redirect (NULL);
-             throw;
-           }
+         ui_out_redirect_pop redir (current_uiout, &fp);
+         print_command_lines (current_uiout, tp.commands.get (), 2);
 
-         current_uiout->redirect (NULL);
          fp.puts ("  end\n");
        }
 
-      if (tp->enable_state == bp_disabled)
+      if (tp.enable_state == bp_disabled)
        fp.puts ("disable $bpnum\n");
 
       /* If this is a multi-location breakpoint, check if the locations
         should be individually disabled.  Watchpoint locations are
         special, and not user visible.  */
-      if (!is_watchpoint (tp) && tp->loc && tp->loc->next)
+      if (!is_watchpoint (&tp) && tp.has_multiple_locations ())
        {
          int n = 1;
 
-         for (bp_location *loc : tp->locations ())
+         for (bp_location &loc : tp.locations ())
            {
-             if (!loc->enabled)
+             if (!loc.enabled)
                fp.printf ("disable $bpnum.%d\n", n);
 
              n++;
@@ -14993,7 +14517,7 @@ save_breakpoints (const char *filename, int from_tty,
     fp.printf ("set default-collect %s\n", default_collect.c_str ());
 
   if (from_tty)
-    printf_filtered (_("Saved to file '%s'.\n"), expanded_filename.get ());
+    gdb_printf (_("Saved to file '%s'.\n"), expanded_filename.get ());
 }
 
 /* The `save breakpoints' command.  */
@@ -15016,7 +14540,7 @@ save_tracepoints_command (const char *args, int from_tty)
 /* This help string is used to consolidate all the help string for specifying
    locations used by several commands.  */
 
-#define LOCATION_HELP_STRING \
+#define LOCATION_SPEC_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\
@@ -15063,7 +14587,7 @@ CONDITION is a boolean expression.\n\
 \n\
 With the \"-force-condition\" flag, the condition is defined even when\n\
 it is invalid for all current locations.\n\
-\n" LOCATION_HELP_STRING "\n\n\
+\n" LOCATION_SPEC_HELP_STRING "\n\n\
 Multiple breakpoints at one place are permitted, and useful if their\n\
 conditions are different.\n\
 \n\
@@ -15097,18 +14621,15 @@ add_catch_command (const char *name, const char *docstring,
   set_cmd_completer (command, completer);
 }
 
-/* Zero if any of the breakpoint's locations could be a location where
-   functions have been inlined, nonzero otherwise.  */
+/* False if any of the breakpoint's locations could be a location where
+   functions have been inlined, true otherwise.  */
 
-static int
+static bool
 is_non_inline_function (struct breakpoint *b)
 {
   /* The shared library event breakpoint is set on the address of a
      non-inline function.  */
-  if (b->type == bp_shlib_event)
-    return 1;
-
-  return 0;
+  return (b->type == bp_shlib_event);
 }
 
 /* Nonzero if the specified PC cannot be a location where functions
@@ -15118,15 +14639,15 @@ int
 pc_at_non_inline_function (const address_space *aspace, CORE_ADDR pc,
                           const target_waitstatus &ws)
 {
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
-      if (!is_non_inline_function (b))
+      if (!is_non_inline_function (&b))
        continue;
 
-      for (bp_location *bl : b->locations ())
+      for (bp_location &bl : b.locations ())
        {
-         if (!bl->shlib_disabled
-             && bpstat_check_location (bl, aspace, pc, ws))
+         if (!bl.shlib_disabled
+             && bpstat_check_location (&bl, aspace, pc, ws))
            return 1;
        }
     }
@@ -15140,175 +14661,10 @@ void
 breakpoint_free_objfile (struct objfile *objfile)
 {
   for (bp_location *loc : all_bp_locations ())
-    if (loc->symtab != NULL && SYMTAB_OBJFILE (loc->symtab) == objfile)
+    if (loc->symtab != NULL && loc->symtab->compunit ()->objfile () == objfile)
       loc->symtab = NULL;
 }
 
-void
-initialize_breakpoint_ops (void)
-{
-  static int initialized = 0;
-
-  struct breakpoint_ops *ops;
-
-  if (initialized)
-    return;
-  initialized = 1;
-
-  /* The breakpoint_ops structure to be inherit by all kinds of
-     breakpoints (real breakpoints, i.e., user "break" breakpoints,
-     internal and momentary breakpoints, etc.).  */
-  ops = &bkpt_base_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->re_set = bkpt_re_set;
-  ops->insert_location = bkpt_insert_location;
-  ops->remove_location = bkpt_remove_location;
-  ops->breakpoint_hit = bkpt_breakpoint_hit;
-  ops->create_sals_from_location = bkpt_create_sals_from_location;
-  ops->create_breakpoints_sal = bkpt_create_breakpoints_sal;
-  ops->decode_location = bkpt_decode_location;
-
-  /* The breakpoint_ops structure to be used in regular breakpoints.  */
-  ops = &bkpt_breakpoint_ops;
-  *ops = bkpt_base_breakpoint_ops;
-  ops->re_set = bkpt_re_set;
-  ops->resources_needed = bkpt_resources_needed;
-  ops->print_it = bkpt_print_it;
-  ops->print_mention = bkpt_print_mention;
-  ops->print_recreate = bkpt_print_recreate;
-
-  /* Ranged breakpoints.  */
-  ops = &ranged_breakpoint_ops;
-  *ops = bkpt_breakpoint_ops;
-  ops->breakpoint_hit = breakpoint_hit_ranged_breakpoint;
-  ops->resources_needed = resources_needed_ranged_breakpoint;
-  ops->print_it = print_it_ranged_breakpoint;
-  ops->print_one = print_one_ranged_breakpoint;
-  ops->print_one_detail = print_one_detail_ranged_breakpoint;
-  ops->print_mention = print_mention_ranged_breakpoint;
-  ops->print_recreate = print_recreate_ranged_breakpoint;
-
-  /* Internal breakpoints.  */
-  ops = &internal_breakpoint_ops;
-  *ops = bkpt_base_breakpoint_ops;
-  ops->re_set = internal_bkpt_re_set;
-  ops->check_status = internal_bkpt_check_status;
-  ops->print_it = internal_bkpt_print_it;
-  ops->print_mention = internal_bkpt_print_mention;
-
-  /* Momentary breakpoints.  */
-  ops = &momentary_breakpoint_ops;
-  *ops = bkpt_base_breakpoint_ops;
-  ops->re_set = momentary_bkpt_re_set;
-  ops->check_status = momentary_bkpt_check_status;
-  ops->print_it = momentary_bkpt_print_it;
-  ops->print_mention = momentary_bkpt_print_mention;
-
-  /* Probe breakpoints.  */
-  ops = &bkpt_probe_breakpoint_ops;
-  *ops = bkpt_breakpoint_ops;
-  ops->insert_location = bkpt_probe_insert_location;
-  ops->remove_location = bkpt_probe_remove_location;
-  ops->create_sals_from_location = bkpt_probe_create_sals_from_location;
-  ops->decode_location = bkpt_probe_decode_location;
-
-  /* Watchpoints.  */
-  ops = &watchpoint_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->re_set = re_set_watchpoint;
-  ops->insert_location = insert_watchpoint;
-  ops->remove_location = remove_watchpoint;
-  ops->breakpoint_hit = breakpoint_hit_watchpoint;
-  ops->check_status = check_status_watchpoint;
-  ops->resources_needed = resources_needed_watchpoint;
-  ops->works_in_software_mode = works_in_software_mode_watchpoint;
-  ops->print_it = print_it_watchpoint;
-  ops->print_mention = print_mention_watchpoint;
-  ops->print_recreate = print_recreate_watchpoint;
-  ops->explains_signal = explains_signal_watchpoint;
-
-  /* Masked watchpoints.  */
-  ops = &masked_watchpoint_breakpoint_ops;
-  *ops = watchpoint_breakpoint_ops;
-  ops->insert_location = insert_masked_watchpoint;
-  ops->remove_location = remove_masked_watchpoint;
-  ops->resources_needed = resources_needed_masked_watchpoint;
-  ops->works_in_software_mode = works_in_software_mode_masked_watchpoint;
-  ops->print_it = print_it_masked_watchpoint;
-  ops->print_one_detail = print_one_detail_masked_watchpoint;
-  ops->print_mention = print_mention_masked_watchpoint;
-  ops->print_recreate = print_recreate_masked_watchpoint;
-
-  /* Tracepoints.  */
-  ops = &tracepoint_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->re_set = tracepoint_re_set;
-  ops->breakpoint_hit = tracepoint_breakpoint_hit;
-  ops->print_one_detail = tracepoint_print_one_detail;
-  ops->print_mention = tracepoint_print_mention;
-  ops->print_recreate = tracepoint_print_recreate;
-  ops->create_sals_from_location = tracepoint_create_sals_from_location;
-  ops->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
-  ops->decode_location = tracepoint_decode_location;
-
-  /* Probe tracepoints.  */
-  ops = &tracepoint_probe_breakpoint_ops;
-  *ops = tracepoint_breakpoint_ops;
-  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_location = strace_marker_create_sals_from_location;
-  ops->create_breakpoints_sal = strace_marker_create_breakpoints_sal;
-  ops->decode_location = strace_marker_decode_location;
-
-  /* Fork catchpoints.  */
-  ops = &catch_fork_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->insert_location = insert_catch_fork;
-  ops->remove_location = remove_catch_fork;
-  ops->breakpoint_hit = breakpoint_hit_catch_fork;
-  ops->print_it = print_it_catch_fork;
-  ops->print_one = print_one_catch_fork;
-  ops->print_mention = print_mention_catch_fork;
-  ops->print_recreate = print_recreate_catch_fork;
-
-  /* Exec catchpoints.  */
-  ops = &catch_exec_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->insert_location = insert_catch_exec;
-  ops->remove_location = remove_catch_exec;
-  ops->breakpoint_hit = breakpoint_hit_catch_exec;
-  ops->print_it = print_it_catch_exec;
-  ops->print_one = print_one_catch_exec;
-  ops->print_mention = print_mention_catch_exec;
-  ops->print_recreate = print_recreate_catch_exec;
-
-  /* Solib-related catchpoints.  */
-  ops = &catch_solib_breakpoint_ops;
-  *ops = base_breakpoint_ops;
-  ops->insert_location = insert_catch_solib;
-  ops->remove_location = remove_catch_solib;
-  ops->breakpoint_hit = breakpoint_hit_catch_solib;
-  ops->check_status = check_status_catch_solib;
-  ops->print_it = print_it_catch_solib;
-  ops->print_one = print_one_catch_solib;
-  ops->print_mention = print_mention_catch_solib;
-  ops->print_recreate = print_recreate_catch_solib;
-
-  ops = &dprintf_breakpoint_ops;
-  *ops = bkpt_base_breakpoint_ops;
-  ops->re_set = dprintf_re_set;
-  ops->resources_needed = bkpt_resources_needed;
-  ops->print_it = bkpt_print_it;
-  ops->print_mention = bkpt_print_mention;
-  ops->print_recreate = dprintf_print_recreate;
-  ops->after_condition_true = dprintf_after_condition_true;
-  ops->breakpoint_hit = dprintf_breakpoint_hit;
-}
-
 /* Chain containing all defined "enable breakpoint" subcommands.  */
 
 static struct cmd_list_element *enablebreaklist = NULL;
@@ -15323,8 +14679,6 @@ _initialize_breakpoint ()
 {
   struct cmd_list_element *c;
 
-  initialize_breakpoint_ops ();
-
   gdb::observers::solib_unloaded.attach (disable_breakpoints_in_unloaded_shlib,
                                         "breakpoint");
   gdb::observers::free_objfile.attach (disable_breakpoints_in_freed_objfile,
@@ -15332,7 +14686,6 @@ _initialize_breakpoint ()
   gdb::observers::memory_changed.attach (invalidate_bp_value_on_memory_change,
                                         "breakpoint");
 
-  breakpoint_chain = 0;
   /* Don't bother to call set_breakpoint_count.  $bpnum isn't useful
      before a breakpoint is set.  */
   breakpoint_count = 0;
@@ -15499,7 +14852,7 @@ 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" LOCATION_HELP_STRING "\n\n\
+"\n" LOCATION_SPEC_HELP_STRING "\n\n\
 See also the \"delete\" command which clears breakpoints by number."));
   add_com_alias ("cl", clear_cmd, class_breakpoint, 1);
 
@@ -15514,32 +14867,6 @@ BREAK_ARGS_HELP ("break")));
   add_com_alias ("bre", break_cmd, class_run, 1);
   add_com_alias ("brea", break_cmd, class_run, 1);
 
-  if (dbx_commands)
-    {
-      add_abbrev_prefix_cmd ("stop", class_breakpoint, stop_command, _("\
-Break in function/address or break at a line in the current file."),
-                            &stoplist, 1, &cmdlist);
-      add_cmd ("in", class_breakpoint, stopin_command,
-              _("Break in function or address."), &stoplist);
-      add_cmd ("at", class_breakpoint, stopat_command,
-              _("Break at a line in the current file."), &stoplist);
-      add_com ("status", class_info, info_breakpoints_command, _("\
-Status of user-settable breakpoints, or breakpoint number NUMBER.\n\
-The \"Type\" column indicates one of:\n\
-\tbreakpoint     - normal breakpoint\n\
-\twatchpoint     - watchpoint\n\
-The \"Disp\" column contains one of \"keep\", \"del\", or \"dis\" to indicate\n\
-the disposition of the breakpoint after it gets hit.  \"dis\" means that the\n\
-breakpoint will be disabled.  The \"Address\" and \"What\" columns indicate the\n\
-address and file/line number respectively.\n\
-\n\
-Convenience variable \"$_\" and default examine address for \"x\"\n\
-are set to the address of the last breakpoint listed unless the command\n\
-is prefixed with \"server \".\n\n\
-Convenience variable \"$bpnum\" contains the number of the last\n\
-breakpoint set."));
-    }
-
   cmd_list_element *info_breakpoints_cmd
     = add_info ("breakpoints", info_breakpoints_command, _("\
 Status of specified breakpoints (all user-settable breakpoints if no argument).\n\
@@ -15590,36 +14917,6 @@ Set temporary catchpoints to catch events."),
                        &tcatch_cmdlist,
                        0/*allow-unknown*/, &cmdlist);
 
-  add_catch_command ("fork", _("Catch calls to fork."),
-                    catch_fork_command_1,
-                    NULL,
-                    (void *) (uintptr_t) catch_fork_permanent,
-                    (void *) (uintptr_t) catch_fork_temporary);
-  add_catch_command ("vfork", _("Catch calls to vfork."),
-                    catch_fork_command_1,
-                    NULL,
-                    (void *) (uintptr_t) catch_vfork_permanent,
-                    (void *) (uintptr_t) catch_vfork_temporary);
-  add_catch_command ("exec", _("Catch calls to exec."),
-                    catch_exec_command_1,
-                    NULL,
-                    CATCH_PERMANENT,
-                    CATCH_TEMPORARY);
-  add_catch_command ("load", _("Catch loads of shared libraries.\n\
-Usage: catch load [REGEX]\n\
-If REGEX is given, only stop for libraries matching the regular expression."),
-                    catch_load_command_1,
-                    NULL,
-                    CATCH_PERMANENT,
-                    CATCH_TEMPORARY);
-  add_catch_command ("unload", _("Catch unloads of shared libraries.\n\
-Usage: catch unload [REGEX]\n\
-If REGEX is given, only stop for libraries matching the regular expression."),
-                    catch_unload_command_1,
-                    NULL,
-                    CATCH_PERMANENT,
-                    CATCH_TEMPORARY);
-
   const auto opts = make_watch_options_def_group (nullptr);
 
   static const std::string watch_help = gdb::option::build_help (_("\
@@ -15716,7 +15013,7 @@ 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" LOCATION_HELP_STRING "\n\n\
+\n" LOCATION_SPEC_HELP_STRING "\n\n\
 Multiple tracepoints at one place are permitted, and useful if their\n\
 conditions are different.\n\
 \n\
@@ -15836,6 +15133,15 @@ when execution stops."),
                                &breakpoint_set_cmdlist,
                                &breakpoint_show_cmdlist);
 
+  add_setshow_boolean_cmd ("breakpoint", class_maintenance,
+                          &debug_breakpoint, _("\
+Set breakpoint location debugging."), _("\
+Show breakpoint location debugging."), _("\
+When on, breakpoint location specific debugging is enabled."),
+                          NULL,
+                          show_debug_breakpoint,
+                          &setdebuglist, &showdebuglist);
+
   add_setshow_enum_cmd ("condition-evaluation", class_breakpoint,
                        condition_evaluation_enums,
                        &condition_evaluation_mode_1, _("\
@@ -15873,7 +15179,7 @@ range (including START-LOCATION and END-LOCATION)."));
 Set a dynamic printf at specified location.\n\
 dprintf location,format string,arg1,arg2,...\n\
 location may be a linespec, explicit, or address location.\n"
-"\n" LOCATION_HELP_STRING));
+"\n" LOCATION_SPEC_HELP_STRING));
   set_cmd_completer (c, location_completer);
 
   add_setshow_enum_cmd ("dprintf-style", class_support,
@@ -15925,4 +15231,6 @@ This is useful for formatted output in user-defined commands."));
                                           "breakpoint");
   gdb::observers::thread_exit.attach (remove_threaded_breakpoints,
                                      "breakpoint");
+  gdb::observers::inferior_removed.attach (remove_inferior_breakpoints,
+                                          "breakpoint");
 }