public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations
@ 2023-05-11 14:48 Simon Marchi
  2023-05-11 14:48 ` [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location Simon Marchi
                   ` (12 more replies)
  0 siblings, 13 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

This series changes two linked lists to use intrusive_list.  There are
some cleanups before that, and some small fixes that needed to be made
to some of our iterator wrappers.

Simon Marchi (12):
  gdb: get gdbarch from syscall_catchpoint instead of location
  gdb: make some breakpoint methods use `this`
  gdb: constify breakpoint::print_it parameter
  gdb: add breakpoint "has locations" methods
  gdb: add breakpoint::first_loc methods
  gdbsupport: add missing increment/decrement operators to
    reference_to_pointer_iterator
  gdb: link breakpoint locations with intrusive_list
  gdb: remove bp_location_pointer_iterator
  gdb: link breakpoints with intrusive_list
  gdbsupport: make basic_safe_iterator::operator* return the same thing
    as underlying iterator
  gdbsupport: make filtered_iterator::operator* return the same thing as
    underlying iterator
  gdb: remove breakpoint_pointer_iterator

 gdb/ada-lang.c                             |   20 +-
 gdb/break-catch-exec.c                     |    4 +-
 gdb/break-catch-fork.c                     |    4 +-
 gdb/break-catch-load.c                     |   25 +-
 gdb/break-catch-sig.c                      |    4 +-
 gdb/break-catch-syscall.c                  |   21 +-
 gdb/break-catch-throw.c                    |   10 +-
 gdb/breakpoint.c                           | 1225 ++++++++++----------
 gdb/breakpoint.h                           |  104 +-
 gdb/dummy-frame.c                          |    4 +-
 gdb/elfread.c                              |    8 +-
 gdb/guile/scm-breakpoint.c                 |    4 +-
 gdb/infrun.c                               |   11 +-
 gdb/jit.c                                  |    6 +-
 gdb/python/py-breakpoint.c                 |    8 +-
 gdb/python/py-finishbreakpoint.c           |    8 +-
 gdb/remote.c                               |    4 +-
 gdb/solib-svr4.c                           |   10 +-
 gdb/tracectf.c                             |    4 +-
 gdb/tracefile-tfile.c                      |    4 +-
 gdb/tracefile.c                            |    6 +-
 gdb/tracepoint.c                           |  108 +-
 gdb/tui/tui-winsource.c                    |   16 +-
 gdbsupport/filtered-iterator.h             |    7 +-
 gdbsupport/reference-to-pointer-iterator.h |   18 +
 gdbsupport/safe-iterator.h                 |    6 +-
 26 files changed, 848 insertions(+), 801 deletions(-)

-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-15  9:12   ` Alexandra Petlanova Hajkova
  2023-05-11 14:48 ` [PATCH 02/12] gdb: make some breakpoint methods use `this` Simon Marchi
                   ` (11 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

I noticed some methods of syscall_catchpoint doing this:

  struct gdbarch *gdbarch = loc->owner->gdbarch;

`loc` is the list of locations of this catchpoint.  Logically, the owner
the locations are this catchpoint.  So this just ends up getting
this->gdbarch.  Remove the unnecessary indirection through the loc.

syscall_catchpoint::print_recreate does something slightly different,
getting its arch from the loc:

  struct gdbarch *gdbarch = loc->gdbarch;

I suppose it's always going to be the same arch, so get it from the
catchpoint there too.

Change-Id: I6f6a6f8e0cd7cfb754cecfb6249e71ec12ba4855
---
 gdb/break-catch-syscall.c | 6 ------
 1 file changed, 6 deletions(-)

diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index d73f6616c97a..595b05c90c8e 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -197,7 +197,6 @@ syscall_catchpoint::print_it (const bpstat *bs) const
      must print "called syscall" or "returned from syscall".  */
   struct target_waitstatus last;
   struct syscall s;
-  struct gdbarch *gdbarch = b->gdbarch;
 
   get_last_target_status (nullptr, nullptr, &last);
 
@@ -242,7 +241,6 @@ syscall_catchpoint::print_one (bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
-  struct gdbarch *gdbarch = loc->owner->gdbarch;
 
   get_user_print_options (&opts);
   /* Field 4, the address, is omitted (which makes the columns not
@@ -293,8 +291,6 @@ syscall_catchpoint::print_one (bp_location **last_loc) const
 void
 syscall_catchpoint::print_mention () const
 {
-  struct gdbarch *gdbarch = loc->owner->gdbarch;
-
   if (!syscalls_to_be_caught.empty ())
     {
       if (syscalls_to_be_caught.size () > 1)
@@ -323,8 +319,6 @@ syscall_catchpoint::print_mention () const
 void
 syscall_catchpoint::print_recreate (struct ui_file *fp) const
 {
-  struct gdbarch *gdbarch = loc->gdbarch;
-
   gdb_printf (fp, "catch syscall");
 
   for (int iter : syscalls_to_be_caught)
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 02/12] gdb: make some breakpoint methods use `this`
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
  2023-05-11 14:48 ` [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-15 13:12   ` Alexandra Petlanova Hajkova
  2023-05-11 14:48 ` [PATCH 03/12] gdb: constify breakpoint::print_it parameter Simon Marchi
                   ` (10 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Some implementations of breakpoint::check_status and
breakpoint::print_it do this:

    struct breakpoint *b = bs->breakpoint_at;

bs->breakpoint_at is always the same as `this` (we can get convinced by
looking at the call sites of check_status and print_it), so it would
just be clearer to access fields through `this` instead.

Change-Id: Ic542a64fcd88e31ae2aad6feff1da278c7086891
---
 gdb/break-catch-load.c    |  9 ++++-----
 gdb/break-catch-syscall.c |  7 +++----
 gdb/break-catch-throw.c   |  6 ++----
 gdb/breakpoint.c          | 26 ++++++++++----------------
 4 files changed, 19 insertions(+), 29 deletions(-)

diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
index d8dab0bd091b..e01f6450fd76 100644
--- a/gdb/break-catch-load.c
+++ b/gdb/break-catch-load.c
@@ -141,19 +141,18 @@ solib_catchpoint::check_status (struct bpstat *bs)
 enum print_stop_action
 solib_catchpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b = bs->breakpoint_at;
   struct ui_out *uiout = current_uiout;
 
-  annotate_catchpoint (b->number);
+  annotate_catchpoint (this->number);
   maybe_print_thread_hit_breakpoint (uiout);
-  if (b->disposition == disp_del)
+  if (this->disposition == disp_del)
     uiout->text ("Temporary catchpoint ");
   else
     uiout->text ("Catchpoint ");
-  uiout->field_signed ("bkptno", b->number);
+  uiout->field_signed ("bkptno", this->number);
   uiout->text ("\n");
   if (uiout->is_mi_like_p ())
-    uiout->field_string ("disp", bpdisp_text (b->disposition));
+    uiout->field_string ("disp", bpdisp_text (this->disposition));
   print_solib_event (true);
   return PRINT_SRC_AND_LOC;
 }
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 595b05c90c8e..6475f4aa172a 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -190,7 +190,6 @@ enum print_stop_action
 syscall_catchpoint::print_it (const bpstat *bs) const
 {
   struct ui_out *uiout = current_uiout;
-  struct breakpoint *b = bs->breakpoint_at;
   /* These are needed because we want to know in which state a
      syscall is.  It can be in the TARGET_WAITKIND_SYSCALL_ENTRY
      or TARGET_WAITKIND_SYSCALL_RETURN, and depending on it we
@@ -202,10 +201,10 @@ syscall_catchpoint::print_it (const bpstat *bs) const
 
   get_syscall_by_number (gdbarch, last.syscall_number (), &s);
 
-  annotate_catchpoint (b->number);
+  annotate_catchpoint (this->number);
   maybe_print_thread_hit_breakpoint (uiout);
 
-  if (b->disposition == disp_del)
+  if (this->disposition == disp_del)
     uiout->text ("Temporary catchpoint ");
   else
     uiout->text ("Catchpoint ");
@@ -215,7 +214,7 @@ syscall_catchpoint::print_it (const bpstat *bs) const
 			   async_reason_lookup (last.kind () == TARGET_WAITKIND_SYSCALL_ENTRY
 						? EXEC_ASYNC_SYSCALL_ENTRY
 						: EXEC_ASYNC_SYSCALL_RETURN));
-      uiout->field_string ("disp", bpdisp_text (b->disposition));
+      uiout->field_string ("disp", bpdisp_text (this->disposition));
     }
   print_num_locno (bs, uiout);
 
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 457446efbc6e..604c1855c0de 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -160,15 +160,13 @@ fetch_probe_arguments (struct value **arg0, struct value **arg1)
 void
 exception_catchpoint::check_status (struct bpstat *bs)
 {
-  struct exception_catchpoint *self
-    = (struct exception_catchpoint *) bs->breakpoint_at;
   std::string type_name;
 
   this->breakpoint::check_status (bs);
   if (!bs->stop)
     return;
 
-  if (self->pattern == NULL)
+  if (this->pattern == NULL)
     return;
 
   const char *name = nullptr;
@@ -192,7 +190,7 @@ exception_catchpoint::check_status (struct bpstat *bs)
 
   if (name != nullptr)
     {
-      if (self->pattern->exec (name, 0, NULL, 0) != 0)
+      if (this->pattern->exec (name, 0, NULL, 0) != 0)
 	bs->stop = false;
     }
 }
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index dcb00bffdbe8..1fdd5c3767f9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -9699,8 +9699,6 @@ watchpoint::breakpoint_hit (const struct bp_location *bl,
 void
 watchpoint::check_status (bpstat *bs)
 {
-  gdb_assert (is_watchpoint (bs->breakpoint_at));
-
   bpstat_check_watchpoint (bs);
 }
 
@@ -9728,28 +9726,25 @@ watchpoint::works_in_software_mode () const
 enum print_stop_action
 watchpoint::print_it (const bpstat *bs) const
 {
-  struct breakpoint *b;
   enum print_stop_action result;
   struct ui_out *uiout = current_uiout;
 
   gdb_assert (bs->bp_location_at != NULL);
 
-  b = bs->breakpoint_at;
-
-  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);
@@ -9766,7 +9761,7 @@ watchpoint::print_it (const bpstat *bs) const
       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 (val.get (), &stb);
@@ -9782,7 +9777,7 @@ watchpoint::print_it (const bpstat *bs) const
 	    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);
@@ -9791,7 +9786,7 @@ watchpoint::print_it (const bpstat *bs) const
 	}
       else
 	{
-	  mention (b);
+	  mention (this);
 	  if (uiout->is_mi_like_p ())
 	    uiout->field_string
 	      ("reason",
@@ -9943,16 +9938,15 @@ masked_watchpoint::works_in_software_mode () const
 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->loc && this->loc->next == nullptr);
 
-  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 ())
@@ -9976,7 +9970,7 @@ masked_watchpoint::print_it (const bpstat *bs) const
       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"));
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 03/12] gdb: constify breakpoint::print_it parameter
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
  2023-05-11 14:48 ` [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location Simon Marchi
  2023-05-11 14:48 ` [PATCH 02/12] gdb: make some breakpoint methods use `this` Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 04/12] gdb: add breakpoint "has locations" methods Simon Marchi
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

The print_it method itself is const.  In a subsequent patch, the
locations that come out of a const breakpoint will be const as well.  It
will therefore be needed to make the last_loc output parameter const as
well.  Make that change now to reduce the size of the following patches.

Change-Id: I7ed962950bc9582646e31e2e42beca2a1c9c5105
---
 gdb/ada-lang.c            |  4 ++--
 gdb/break-catch-exec.c    |  4 ++--
 gdb/break-catch-fork.c    |  4 ++--
 gdb/break-catch-load.c    |  4 ++--
 gdb/break-catch-sig.c     |  4 ++--
 gdb/break-catch-syscall.c |  4 ++--
 gdb/break-catch-throw.c   |  4 ++--
 gdb/breakpoint.c          | 14 ++++++--------
 gdb/breakpoint.h          |  2 +-
 9 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 50d5c6f96971..d7316c845d6d 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12165,7 +12165,7 @@ struct ada_catchpoint : public code_breakpoint
   void re_set () override;
   void check_status (struct bpstat *bs) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
 
@@ -12430,7 +12430,7 @@ ada_catchpoint::print_it (const bpstat *bs) const
    catchpoint kinds.  */
 
 bool
-ada_catchpoint::print_one (bp_location **last_loc) const
+ada_catchpoint::print_one (const bp_location **last_loc) const
 { 
   struct ui_out *uiout = current_uiout;
   struct value_print_options opts;
diff --git a/gdb/break-catch-exec.c b/gdb/break-catch-exec.c
index 6cd498517aff..2e4ce59f49c5 100644
--- a/gdb/break-catch-exec.c
+++ b/gdb/break-catch-exec.c
@@ -49,7 +49,7 @@ struct exec_catchpoint : public catchpoint
 		      CORE_ADDR bp_addr,
 		      const target_waitstatus &ws) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
 
@@ -110,7 +110,7 @@ exec_catchpoint::print_it (const bpstat *bs) const
 }
 
 bool
-exec_catchpoint::print_one (bp_location **last_loc) const
+exec_catchpoint::print_one (const bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/break-catch-fork.c b/gdb/break-catch-fork.c
index 1b1dace99d1d..fc761bcaa2b8 100644
--- a/gdb/break-catch-fork.c
+++ b/gdb/break-catch-fork.c
@@ -49,7 +49,7 @@ struct fork_catchpoint : public catchpoint
 		      CORE_ADDR bp_addr,
 		      const target_waitstatus &ws) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
 
@@ -136,7 +136,7 @@ fork_catchpoint::print_it (const bpstat *bs) const
 /* Implement the "print_one" method for fork catchpoints.  */
 
 bool
-fork_catchpoint::print_one (bp_location **last_loc) const
+fork_catchpoint::print_one (const bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
index e01f6450fd76..d33313a1d989 100644
--- a/gdb/break-catch-load.c
+++ b/gdb/break-catch-load.c
@@ -56,7 +56,7 @@ struct solib_catchpoint : public catchpoint
 		      const target_waitstatus &ws) override;
   void check_status (struct bpstat *bs) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
 
@@ -158,7 +158,7 @@ solib_catchpoint::print_it (const bpstat *bs) const
 }
 
 bool
-solib_catchpoint::print_one (bp_location **locs) const
+solib_catchpoint::print_one (const bp_location **locs) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/break-catch-sig.c b/gdb/break-catch-sig.c
index 8c1fcbd69eef..10c8b81f8e83 100644
--- a/gdb/break-catch-sig.c
+++ b/gdb/break-catch-sig.c
@@ -57,7 +57,7 @@ struct signal_catchpoint : public catchpoint
 		      CORE_ADDR bp_addr,
 		      const target_waitstatus &ws) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
   bool explains_signal (enum gdb_signal) override;
@@ -213,7 +213,7 @@ signal_catchpoint::print_it (const bpstat *bs) const
 /* Implement the "print_one" method for signal catchpoints.  */
 
 bool
-signal_catchpoint::print_one (bp_location **last_loc) const
+signal_catchpoint::print_one (const bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 6475f4aa172a..18e2b20c1385 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -52,7 +52,7 @@ struct syscall_catchpoint : public catchpoint
 		      CORE_ADDR bp_addr,
 		      const target_waitstatus &ws) override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
 
@@ -236,7 +236,7 @@ syscall_catchpoint::print_it (const bpstat *bs) const
 /* Implement the "print_one" method for syscall catchpoints.  */
 
 bool
-syscall_catchpoint::print_one (bp_location **last_loc) const
+syscall_catchpoint::print_one (const bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 604c1855c0de..47d534c5ee88 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -87,7 +87,7 @@ struct exception_catchpoint : public code_breakpoint
 
   void re_set () override;
   enum print_stop_action print_it (const bpstat *bs) const override;
-  bool print_one (bp_location **) const override;
+  bool print_one (const bp_location **) const override;
   void print_mention () const override;
   void print_recreate (struct ui_file *fp) const override;
   void print_one_detail (struct ui_out *) const override;
@@ -259,7 +259,7 @@ exception_catchpoint::print_it (const bpstat *bs) const
 }
 
 bool
-exception_catchpoint::print_one (bp_location **last_loc) const
+exception_catchpoint::print_one (const bp_location **last_loc) const
 {
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 1fdd5c3767f9..0ca4528faef2 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -369,7 +369,7 @@ struct ranged_breakpoint : public ordinary_breakpoint
 		      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 (bp_location **) 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;
@@ -6340,7 +6340,7 @@ 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;
@@ -6703,9 +6703,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
@@ -6789,7 +6787,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);
 }
 
@@ -6827,7 +6825,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;
@@ -9407,7 +9405,7 @@ ranged_breakpoint::print_it (const bpstat *bs) const
 /* Implement the "print_one" method for ranged breakpoints.  */
 
 bool
-ranged_breakpoint::print_one (bp_location **last_loc) const
+ranged_breakpoint::print_one (const bp_location **last_loc) const
 {
   struct bp_location *bl = loc;
   struct value_print_options opts;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 7c5cf3f2bef4..80cb91b1a911 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -684,7 +684,7 @@ struct breakpoint
   /* Display information about this breakpoint, for "info
      breakpoints".  Returns false if this method should use the
      default behavior.  */
-  virtual bool print_one (bp_location **) const
+  virtual bool print_one (const bp_location **) const
   {
     return false;
   }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 04/12] gdb: add breakpoint "has locations" methods
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (2 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 03/12] gdb: constify breakpoint::print_it parameter Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 05/12] gdb: add breakpoint::first_loc methods Simon Marchi
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Add three convenience methods to struct breakpoint:

 - has_locations: returns true if the breakpoint has at least one
   location
 - has_single_location: returns true if the breakpoint has exactly one
   location
 - has_multiple_locations: returns true if the breakpoint has more than
   one location

A subsequent patch changes the list of breakpoints to be an
intrusive_list, so all these spots would need to change.  But in any
case, I think that this:

  if (b->has_multiple_locations ())

conveys the intention better than:

  if (b->loc != nullptr && b->loc->next != nullptr)

Change-Id: Ib18c3605fd35d425ef9df82cb7aacff1606c6747
---
 gdb/ada-lang.c        |  2 +-
 gdb/breakpoint.c      | 62 +++++++++++++++++++++++--------------------
 gdb/breakpoint.h      | 12 +++++++++
 gdb/elfread.c         |  4 +--
 gdb/tracectf.c        |  2 +-
 gdb/tracefile-tfile.c |  2 +-
 gdb/tracefile.c       |  4 +--
 gdb/tracepoint.c      |  2 +-
 8 files changed, 53 insertions(+), 37 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index d7316c845d6d..207d58e80a63 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12204,7 +12204,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c,
     return;
 
   /* Same if there are no locations... */
-  if (c->loc == NULL)
+  if (!c->has_locations ())
     return;
 
   /* Compute the condition expression in text form, from the specific
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0ca4528faef2..fefe18644cf9 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -818,7 +818,7 @@ has_multiple_locations (int num)
 {
   for (breakpoint *b : all_breakpoints ())
     if (b->number == num)
-      return b->loc != nullptr && b->loc->next != nullptr;
+      return b->has_multiple_locations ();
 
   return false;
 }
@@ -1876,7 +1876,7 @@ static void
 add_dummy_location (struct breakpoint *b,
 		    struct program_space *pspace)
 {
-  gdb_assert (b->loc == NULL);
+  gdb_assert (!b->has_locations ());
 
   b->loc = new bp_location (b, bp_loc_other);
   b->loc->pspace = pspace;
@@ -2241,7 +2241,7 @@ update_watchpoint (struct watchpoint *b, bool reparse)
 	 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)
+      if (b->type == bp_watchpoint && !b->has_locations ())
 	add_dummy_location (b, frame_pspace);
     }
   else if (!within_current_scope)
@@ -4106,7 +4106,7 @@ breakpoint_init_inferior (enum inf_context context)
 
   for (breakpoint *b : all_breakpoints_safe ())
     {
-      if (b->loc && b->loc->pspace != pspace)
+      if (b->has_locations () && b->loc->pspace != pspace)
 	continue;
 
       switch (b->type)
@@ -4520,7 +4520,7 @@ bpstat_locno (const bpstat *bs)
 
   int locno = 0;
 
-  if (b != nullptr && b->loc != nullptr && b->loc->next != nullptr)
+  if (b != nullptr && b->has_multiple_locations ())
     {
       const bp_location *bl_i;
 
@@ -6054,7 +6054,9 @@ bool
 bpstat_should_step ()
 {
   for (breakpoint *b : all_breakpoints ())
-    if (breakpoint_enabled (b) && b->type == bp_watchpoint && b->loc != NULL)
+    if (breakpoint_enabled (b)
+	&& b->type == bp_watchpoint
+	&& b->has_locations ())
       return true;
 
   return false;
@@ -6357,10 +6359,11 @@ 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->has_locations ()
+	  && (b->has_multiple_locations ()
 	      || !b->loc->enabled || b->loc->disabled_by_cond)))
     header_of_multiple = true;
+
   if (loc == NULL)
     loc = b->loc;
 
@@ -6451,7 +6454,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
@@ -6461,7 +6464,7 @@ print_one_breakpoint_location (struct breakpoint *b,
 	  annotate_field (5);
 	  if (!header_of_multiple)
 	    print_breakpoint_location (b, loc);
-	  if (b->loc)
+	  if (b->has_locations ())
 	    *last_loc = b->loc;
 	}
     }
@@ -6740,9 +6743,10 @@ print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
 	  && (!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->loc->enabled
+		      || b->loc->disabled_by_cond))))
 	{
 	  gdb::optional<ui_out_emit_list> locations_list;
 
@@ -6805,7 +6809,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).
@@ -7482,8 +7486,9 @@ set_breakpoint_location_function (struct bp_location *loc)
 
 	  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.  */
@@ -9374,13 +9379,12 @@ ranged_breakpoint::resources_needed (const struct bp_location *bl)
 enum print_stop_action
 ranged_breakpoint::print_it (const bpstat *bs) const
 {
-  struct bp_location *bl = loc;
   struct ui_out *uiout = current_uiout;
 
   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 (number);
 
@@ -9412,7 +9416,7 @@ ranged_breakpoint::print_one (const bp_location **last_loc) const
   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);
 
@@ -9939,7 +9943,7 @@ masked_watchpoint::print_it (const bpstat *bs) const
   struct ui_out *uiout = current_uiout;
 
   /* Masked watchpoints have only one location.  */
-  gdb_assert (this->loc && this->loc->next == nullptr);
+  gdb_assert (this->has_single_location ());
 
   annotate_watchpoint (this->number);
   maybe_print_thread_hit_breakpoint (uiout);
@@ -9985,7 +9989,7 @@ void
 masked_watchpoint::print_one_detail (struct ui_out *uiout) const
 {
   /* Masked watchpoints have only one location.  */
-  gdb_assert (loc && loc->next == NULL);
+  gdb_assert (this->has_single_location ());
 
   uiout->text ("\tmask ");
   uiout->field_core_addr ("mask", loc->gdbarch, hw_wp_mask);
@@ -11571,7 +11575,7 @@ code_breakpoint::say_where () const
 
   /* i18n: cagney/2005-02-11: Below needs to be merged into a
      single string.  */
-  if (loc == NULL)
+  if (!this->has_locations ())
     {
       /* For pending locations, the output differs slightly based
 	 on extra_string.  If this is non-NULL, it contains either
@@ -11604,7 +11608,7 @@ code_breakpoint::say_where () const
 	{
 	  /* If there is a single location, we can print the location
 	     more nicely.  */
-	  if (loc->next == NULL)
+	  if (!this->has_multiple_locations ())
 	    {
 	      const char *filename
 		= symtab_to_filename_for_display (loc->symtab);
@@ -11620,7 +11624,7 @@ code_breakpoint::say_where () const
 	    gdb_printf (": %s.", locspec->to_string ());
 	}
 
-      if (loc->next)
+      if (this->has_multiple_locations ())
 	{
 	  struct bp_location *iter = loc;
 	  int n = 0;
@@ -11879,7 +11883,7 @@ ordinary_breakpoint::print_recreate (struct ui_file *fp) const
 
   /* Print out extra_string if this breakpoint is pending.  It might
      contain, for example, conditions that were set by the user.  */
-  if (loc == NULL && extra_string != NULL)
+  if (!this->has_locations () && extra_string != NULL)
     gdb_printf (fp, " %s", extra_string.get ());
 
   print_recreate_thread (fp);
@@ -12867,11 +12871,11 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
 	 errors.  */
       if (e.error == NOT_FOUND_ERROR
 	  && (condition_not_parsed
-	      || (loc != NULL
+	      || (this->has_locations ()
 		  && search_pspace != NULL
 		  && loc->pspace != search_pspace)
-	      || (loc && loc->shlib_disabled)
-	      || (loc && loc->pspace->executing_startup)
+	      || (this->has_locations () && loc->shlib_disabled)
+	      || (this->has_locations () && loc->pspace->executing_startup)
 	      || enable_state == bp_disabled))
 	not_found_and_ok = true;
 
@@ -14265,7 +14269,7 @@ save_breakpoints (const char *filename, int from_tty,
       /* 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;
 
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 80cb91b1a911..2a3a5cf57b83 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -633,6 +633,18 @@ struct breakpoint
   /* Allocate a location for this breakpoint.  */
   virtual struct bp_location *allocate_location ();
 
+  /* Return true if this breakpoint has a least one location.  */
+  bool has_locations () const
+  { return this->loc != nullptr; }
+
+  /* Return true if this breakpoint has a single location.  */
+  bool has_single_location () const
+  { return this->loc != nullptr && this->loc->next == nullptr; }
+
+  /* Return true if this breakpoint has multiple locations.  */
+  bool has_multiple_locations () const
+  { return this->loc != nullptr && this->loc->next != nullptr; }
+
   /* Reevaluate a breakpoint.  This is necessary after symbols change
      (e.g., an executable or DSO was loaded, or the inferior just
      started).  */
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 0305bf218946..7169ae8808a8 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -970,7 +970,7 @@ elf_gnu_ifunc_resolver_stop (code_breakpoint *b)
        b_return = b_return->related_breakpoint)
     {
       gdb_assert (b_return->type == bp_gnu_ifunc_resolver_return);
-      gdb_assert (b_return->loc != NULL && b_return->loc->next == NULL);
+      gdb_assert (b_return->has_single_location ());
       gdb_assert (frame_id_p (b_return->frame_id));
 
       if (b_return->thread == thread_id
@@ -1039,7 +1039,7 @@ elf_gnu_ifunc_resolver_return_stop (code_breakpoint *b)
       b = (code_breakpoint *) b_next;
     }
   gdb_assert (b->type == bp_gnu_ifunc_resolver);
-  gdb_assert (b->loc->next == NULL);
+  gdb_assert (b->has_single_location ());
 
   func_func = value::allocate (func_func_type);
   func_func->set_lval (lval_memory);
diff --git a/gdb/tracectf.c b/gdb/tracectf.c
index d8d0f05d049b..ab513b1fa158 100644
--- a/gdb/tracectf.c
+++ b/gdb/tracectf.c
@@ -1535,7 +1535,7 @@ ctf_get_traceframe_address (void)
       struct tracepoint *tp
 	= get_tracepoint_by_number_on_target (tpnum);
 
-      if (tp && tp->loc)
+      if (tp != nullptr && tp->has_locations ())
 	addr = tp->loc->address;
     }
 
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index 31eb974d4163..9c1adee11bc3 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -667,7 +667,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
 
   tp = get_tracepoint_by_number_on_target (tpnum);
   /* FIXME this is a poor heuristic if multiple locations.  */
-  if (tp && tp->loc)
+  if (tp != nullptr && tp->has_locations ())
     addr = tp->loc->address;
 
   /* Restore our seek position.  */
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index b4543c9bf5fd..883ce4bf375a 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -390,11 +390,11 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 
   /* We can often usefully guess that the PC is going to be the same
      as the address of the tracepoint.  */
-  if (tp == NULL || tp->loc == NULL)
+  if (tp == nullptr || !tp->has_locations ())
     return;
 
   /* But don't try to guess if tracepoint is multi-location...  */
-  if (tp->loc->next)
+  if (tp->has_multiple_locations ())
     {
       warning (_("Tracepoint %d has multiple "
 		 "locations, cannot infer $pc"),
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index ffda4a6439e4..4a9d8491a54b 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1522,7 +1522,7 @@ process_tracepoint_on_disconnect (void)
      user that pending tracepoint will no longer work.  */
   for (breakpoint *b : all_tracepoints ())
     {
-      if (b->loc == NULL)
+      if (!b->has_locations ())
 	{
 	  has_pending_p = 1;
 	  break;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 05/12] gdb: add breakpoint::first_loc methods
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (3 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 04/12] gdb: add breakpoint "has locations" methods Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-18 12:50   ` Andrew Burgess
  2023-05-11 14:48 ` [PATCH 06/12] gdbsupport: add missing increment/decrement operators to reference_to_pointer_iterator Simon Marchi
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Add convenience first_loc methods to struct breakpoint (const and
non-const overloads).  A subsequent patch changes the list of locations
to be an intrusive_list and makes the actual list private, so these
spots would need to become something ugly like:

  -b->loc
  +*b->locations ().begin ()

That would make the code much heavier and not readable.  There is a
surprisingly big number of places that access the first location of
breakpoints.  Whether this is correct, or these spots fail to consider
the possibility of multi-location breakpoints, I don't know.  But
anyhow, I think that using this instead:

 b->first_loc ()

conveys the intention better than the other two forms.

Change-Id: Ibbefe3e4ca6cdfe570351fe7e2725f2ce11d1e95
---
 gdb/breakpoint.c        | 112 ++++++++++++++++++++--------------------
 gdb/breakpoint.h        |  14 +++++
 gdb/elfread.c           |   4 +-
 gdb/infrun.c            |  11 ++--
 gdb/tracectf.c          |   2 +-
 gdb/tracefile-tfile.c   |   2 +-
 gdb/tracefile.c         |   2 +-
 gdb/tracepoint.c        |   2 +-
 gdb/tui/tui-winsource.c |   2 +-
 9 files changed, 82 insertions(+), 69 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index fefe18644cf9..e9b6574bba77 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4106,7 +4106,7 @@ breakpoint_init_inferior (enum inf_context context)
 
   for (breakpoint *b : all_breakpoints_safe ())
     {
-      if (b->has_locations () && b->loc->pspace != pspace)
+      if (b->has_locations () && b->first_loc ().pspace != pspace)
 	continue;
 
       switch (b->type)
@@ -5633,7 +5633,7 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
 	     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)
@@ -6160,8 +6160,7 @@ bp_location_condition_evaluator (const struct bp_location *bl)
 /* Print the LOC location out of the list of B->LOC locations.  */
 
 static void
-print_breakpoint_location (const breakpoint *b,
-			   struct bp_location *loc)
+print_breakpoint_location (const breakpoint *b, const bp_location *loc)
 {
   struct ui_out *uiout = current_uiout;
 
@@ -6361,11 +6360,11 @@ print_one_breakpoint_location (struct breakpoint *b,
   if (loc == NULL 
       && (b->has_locations ()
 	  && (b->has_multiple_locations ()
-	      || !b->loc->enabled || b->loc->disabled_by_cond)))
+	      || !b->first_loc ().enabled || b->first_loc ().disabled_by_cond)))
     header_of_multiple = true;
 
-  if (loc == NULL)
-    loc = b->loc;
+  if (loc == NULL && b->has_locations ())
+    loc = &b->first_loc ();
 
   annotate_record ();
 
@@ -6465,7 +6464,7 @@ print_one_breakpoint_location (struct breakpoint *b,
 	  if (!header_of_multiple)
 	    print_breakpoint_location (b, loc);
 	  if (b->has_locations ())
-	    *last_loc = b->loc;
+	    *last_loc = &b->first_loc ();
 	}
     }
 
@@ -6745,8 +6744,8 @@ print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
 	  && (allflag
 	      || (b->has_locations ()
 		  && (b->has_multiple_locations ()
-		      || !b->loc->enabled
-		      || b->loc->disabled_by_cond))))
+		      || !b->first_loc ().enabled
+		      || b->first_loc ().disabled_by_cond))))
 	{
 	  gdb::optional<ui_out_emit_list> locations_list;
 
@@ -7743,7 +7742,7 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 
   b->enable_state = bp_enabled;
   /* locspec has to be used or breakpoint_re_set will delete me.  */
-  b->locspec = new_address_location_spec (b->loc->address, NULL, 0);
+  b->locspec = new_address_location_spec (b->first_loc ().address, NULL, 0);
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
@@ -7771,7 +7770,7 @@ remove_jit_event_breakpoints (void)
 {
   for (breakpoint *b : all_breakpoints_safe ())
     if (b->type == bp_jit_event
-	&& b->loc->pspace == current_program_space)
+	&& b->first_loc ().pspace == current_program_space)
       delete_breakpoint (b);
 }
 
@@ -7780,7 +7779,7 @@ remove_solib_event_breakpoints (void)
 {
   for (breakpoint *b : all_breakpoints_safe ())
     if (b->type == bp_shlib_event
-	&& b->loc->pspace == current_program_space)
+	&& b->first_loc ().pspace == current_program_space)
       delete_breakpoint (b);
 }
 
@@ -7791,7 +7790,7 @@ 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->first_loc ().pspace == current_program_space)
       b->disposition = disp_del_at_next_stop;
 }
 
@@ -7826,7 +7825,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;
@@ -8178,17 +8177,18 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
   std::unique_ptr<breakpoint> copy
     (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
 			       orig->frame_id, thread));
+  bp_location &orig_loc = orig->first_loc ();
   copy->loc = copy->allocate_location ();
   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->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));
@@ -8575,7 +8575,7 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
   if (locspec_ != nullptr)
     locspec = std::move (locspec_);
   else
-    locspec = new_address_location_spec (this->loc->address, NULL, 0);
+    locspec = new_address_location_spec (this->first_loc ().address, NULL, 0);
   filter = std::move (filter_);
 }
 
@@ -9411,7 +9411,6 @@ ranged_breakpoint::print_it (const bpstat *bs) const
 bool
 ranged_breakpoint::print_one (const bp_location **last_loc) const
 {
-  struct bp_location *bl = loc;
   struct value_print_options opts;
   struct ui_out *uiout = current_uiout;
 
@@ -9425,8 +9424,8 @@ ranged_breakpoint::print_one (const bp_location **last_loc) const
        by ranged_breakpoint::print_one_detail.  */
     uiout->field_skip ("addr");
   annotate_field (5);
-  print_breakpoint_location (this, bl);
-  *last_loc = bl;
+  print_breakpoint_location (this, &this->first_loc ());
+  *last_loc = &this->first_loc ();
 
   return true;
 }
@@ -9437,18 +9436,16 @@ void
 ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
 {
   CORE_ADDR address_start, address_end;
-  struct bp_location *bl = 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");
 }
@@ -9458,15 +9455,14 @@ ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
 void
 ranged_breakpoint::print_mention () const
 {
-  struct bp_location *bl = loc;
+  const bp_location &bl = this->first_loc ();
   struct ui_out *uiout = current_uiout;
 
-  gdb_assert (bl);
   gdb_assert (type == bp_hardware_breakpoint);
 
   uiout->message (_("Hardware assisted ranged breakpoint %d from %s to %s."),
-		  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" method for ranged breakpoints.  */
@@ -9992,7 +9988,7 @@ masked_watchpoint::print_one_detail (struct ui_out *uiout) const
   gdb_assert (this->has_single_location ());
 
   uiout->text ("\tmask ");
-  uiout->field_core_addr ("mask", loc->gdbarch, hw_wp_mask);
+  uiout->field_core_addr ("mask", this->first_loc ().gdbarch, hw_wp_mask);
   uiout->text ("\n");
 }
 
@@ -10302,11 +10298,11 @@ 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,
+	  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);
 	}
@@ -11599,23 +11595,24 @@ code_breakpoint::say_where () const
     }
   else
     {
-      if (opts.addressprint || 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 (loc->gdbarch,
-					     loc->address)));
-      if (loc->symtab != NULL)
+				   paddress (bl.gdbarch,
+					     bl.address)));
+      if (bl.symtab != NULL)
 	{
 	  /* If there is a single location, we can print the location
 	     more nicely.  */
 	  if (!this->has_multiple_locations ())
 	    {
 	      const char *filename
-		= symtab_to_filename_for_display (loc->symtab);
+		= symtab_to_filename_for_display (bl.symtab);
 	      gdb_printf (": file %ps, line %d.",
 			  styled_string (file_name_style.style (),
 					 filename),
-			  loc->line_number);
+			  bl.line_number);
 	    }
 	  else
 	    /* This is not ideal, but each location may have a
@@ -12629,14 +12626,14 @@ 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->loc->line_number;
+	  els->line_offset.offset = b->first_loc ().line_number;
 	  els->line_offset.sign = LINE_OFFSET_NONE;
 
 	  b->locspec = std::move (els);
@@ -12873,9 +12870,10 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
 	  && (condition_not_parsed
 	      || (this->has_locations ()
 		  && search_pspace != NULL
-		  && loc->pspace != search_pspace)
-	      || (this->has_locations () && loc->shlib_disabled)
-	      || (this->has_locations () && loc->pspace->executing_startup)
+		  && 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;
 
@@ -13047,7 +13045,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;
     }
 }
 
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 2a3a5cf57b83..9f49ed62a9ad 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -645,6 +645,20 @@ struct breakpoint
   bool has_multiple_locations () const
   { return this->loc != nullptr && this->loc->next != nullptr; }
 
+  /* Return a reference to the first location of this breakpoint.  */
+  bp_location &first_loc ()
+  {
+    gdb_assert (this->has_locations ());
+    return *this->loc;
+  }
+
+  /* Return a reference to the first location of this breakpoint.  */
+  const bp_location &first_loc () const
+  {
+    gdb_assert (this->has_locations ());
+    return *this->loc;
+  }
+
   /* Reevaluate a breakpoint.  This is necessary after symbols change
      (e.g., an executable or DSO was loaded, or the inferior just
      started).  */
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 7169ae8808a8..2d4f23416245 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -974,7 +974,7 @@ elf_gnu_ifunc_resolver_stop (code_breakpoint *b)
       gdb_assert (frame_id_p (b_return->frame_id));
 
       if (b_return->thread == thread_id
-	  && b_return->loc->requested_address == prev_pc
+	  && b_return->first_loc ().requested_address == prev_pc
 	  && b_return->frame_id == prev_frame_id)
 	break;
     }
@@ -1043,7 +1043,7 @@ elf_gnu_ifunc_resolver_return_stop (code_breakpoint *b)
 
   func_func = value::allocate (func_func_type);
   func_func->set_lval (lval_memory);
-  func_func->set_address (b->loc->related_address);
+  func_func->set_address (b->first_loc ().related_address);
 
   value = value::allocate (value_type);
   gdbarch_return_value_as_value (gdbarch, func_func, value_type, regcache,
diff --git a/gdb/infrun.c b/gdb/infrun.c
index efe2c00c489a..a9e2a2423b17 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -950,14 +950,14 @@ follow_inferior_reset_breakpoints (void)
   if (tp->control.step_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
-      tp->control.step_resume_breakpoint->loc->enabled = 1;
+      tp->control.step_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Treat exception_resume breakpoints like step_resume breakpoints.  */
   if (tp->control.exception_resume_breakpoint)
     {
       breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
-      tp->control.exception_resume_breakpoint->loc->enabled = 1;
+      tp->control.exception_resume_breakpoint->first_loc ().enabled = 1;
     }
 
   /* Reinsert all breakpoints in the child.  The user may have set
@@ -2551,7 +2551,8 @@ resume_1 (enum gdb_signal sig)
 		 user breakpoints at PC to trigger (again) when this
 		 hits.  */
 	      insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
-	      gdb_assert (tp->control.step_resume_breakpoint->loc->permanent);
+	      gdb_assert (tp->control.step_resume_breakpoint->first_loc ()
+			  .permanent);
 
 	      tp->step_after_step_resume_breakpoint = step;
 	    }
@@ -7008,9 +7009,9 @@ process_event_stop_test (struct execution_control_state *ecs)
 	= ecs->event_thread->control.step_resume_breakpoint;
 
       if (sr_bp != nullptr
-	  && sr_bp->loc->permanent
+	  && sr_bp->first_loc ().permanent
 	  && sr_bp->type == bp_hp_step_resume
-	  && sr_bp->loc->address == ecs->event_thread->prev_pc)
+	  && sr_bp->first_loc ().address == ecs->event_thread->prev_pc)
 	{
 	  infrun_debug_printf ("stepped permanent breakpoint, stopped in handler");
 	  delete_step_resume_breakpoint (ecs->event_thread);
diff --git a/gdb/tracectf.c b/gdb/tracectf.c
index ab513b1fa158..16461711da18 100644
--- a/gdb/tracectf.c
+++ b/gdb/tracectf.c
@@ -1536,7 +1536,7 @@ ctf_get_traceframe_address (void)
 	= get_tracepoint_by_number_on_target (tpnum);
 
       if (tp != nullptr && tp->has_locations ())
-	addr = tp->loc->address;
+	addr = tp->first_loc ().address;
     }
 
   /* Restore the position.  */
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index 9c1adee11bc3..9203bcc2e4bb 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -668,7 +668,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
   tp = get_tracepoint_by_number_on_target (tpnum);
   /* FIXME this is a poor heuristic if multiple locations.  */
   if (tp != nullptr && tp->has_locations ())
-    addr = tp->loc->address;
+    addr = tp->first_loc ().address;
 
   /* Restore our seek position.  */
   cur_offset = saved_offset;
diff --git a/gdb/tracefile.c b/gdb/tracefile.c
index 883ce4bf375a..5a2641919f74 100644
--- a/gdb/tracefile.c
+++ b/gdb/tracefile.c
@@ -412,7 +412,7 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
 
   /* Guess what we can from the tracepoint location.  */
   gdbarch_guess_tracepoint_registers (gdbarch, regcache,
-				      tp->loc->address);
+				      tp->first_loc ().address);
 }
 
 /* This is the implementation of target_ops method to_has_all_memory.  */
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 4a9d8491a54b..99d175d32e42 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2750,7 +2750,7 @@ get_traceframe_location (int *stepping_frame_p)
   /* If this is a stepping frame, we don't know which location
      triggered.  The first is as good (or bad) a guess as any...  */
   *stepping_frame_p = 1;
-  return t->loc;
+  return &t->first_loc ();
 }
 
 /* Return the default collect actions of a tracepoint T.  */
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 3c4ce501e5ee..3fc38b7be233 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -640,7 +640,7 @@ tui_source_window_base::update_breakpoint_info
 		    mode |= TUI_BP_ENABLED;
 		  if (bp->hit_count)
 		    mode |= TUI_BP_HIT;
-		  if (bp->loc->cond)
+		  if (bp->first_loc ().cond)
 		    mode |= TUI_BP_CONDITIONAL;
 		  if (bp->type == bp_hardware_breakpoint)
 		    mode |= TUI_BP_HARDWARE;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 06/12] gdbsupport: add missing increment/decrement operators to reference_to_pointer_iterator
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (4 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 05/12] gdb: add breakpoint::first_loc methods Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 07/12] gdb: link breakpoint locations with intrusive_list Simon Marchi
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Using the following patch, I would get this build failure:

      CXX    breakpoint.o
    In file included from /usr/include/c++/13.1.1/bits/stl_algobase.h:66,
                     from /usr/include/c++/13.1.1/bits/hashtable_policy.h:36,
                     from /usr/include/c++/13.1.1/bits/hashtable.h:35,
                     from /usr/include/c++/13.1.1/bits/unordered_map.h:33,
                     from /usr/include/c++/13.1.1/unordered_map:41,
                     from /usr/include/c++/13.1.1/functional:63,
                     from /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/ptid.h:35,
                     from /home/smarchi/src/binutils-gdb/gdb/../gdbsupport/common-defs.h:206,
                     from /home/smarchi/src/binutils-gdb/gdb/defs.h:26,
                     from /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:20:
    /usr/include/c++/13.1.1/bits/stl_iterator_base_funcs.h: In instantiation of ‘constexpr void std::__advance(_BidirectionalIterator&, _Distance, bidirectional_iterator_tag) [with _BidirectionalIterator = reference_to_pointer_iterator<intrusive_list_iterator<bp_location, intrusive_base_node<bp_location> > >; _Distance = long int]’:
    /usr/include/c++/13.1.1/bits/stl_iterator_base_funcs.h:224:21:   required from ‘constexpr void std::advance(_InputIterator&, _Distance) [with _InputIterator = reference_to_pointer_iterator<intrusive_list_iterator<bp_location, intrusive_base_node<bp_location> > >; _Distance = long int]’
    /usr/include/c++/13.1.1/bits/stl_iterator_base_funcs.h:237:19:   required from ‘constexpr _InputIterator std::next(_InputIterator, typename iterator_traits<_Iter>::difference_type) [with _InputIterator = reference_to_pointer_iterator<intrusive_list_iterator<bp_location, intrusive_base_node<bp_location> > >; typename iterator_traits<_Iter>::difference_type = long int]’
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:1073:19:   required from here
    /usr/include/c++/13.1.1/bits/stl_iterator_base_funcs.h:179:11: error: no match for ‘operator--’ (operand type is ‘reference_to_pointer_iterator<intrusive_list_iterator<bp_location, intrusive_base_node<bp_location> > >’)
      179 |           --__i;
          |           ^~~~~

This points out that while intrusive_list_iterator has an operator--,
the reference_to_pointer_iterator wrapper does not.  I'm not to sure why
the compiler chooses the overload of __advance that accepts a
_BidirectionalIterator, given that reference_to_pointer_iterator can't
be decremented, but adding those operators seems like the right thing to
do in any case, for completeness.

Change-Id: I8e2044b6734fadf0f21093047cf35bb7080dbdc3
---
 gdbsupport/reference-to-pointer-iterator.h | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/gdbsupport/reference-to-pointer-iterator.h b/gdbsupport/reference-to-pointer-iterator.h
index 792659b1611f..1579d4d26e9c 100644
--- a/gdbsupport/reference-to-pointer-iterator.h
+++ b/gdbsupport/reference-to-pointer-iterator.h
@@ -68,6 +68,24 @@ struct reference_to_pointer_iterator
     return *this;
   }
 
+  self_type &operator++ (int)
+  {
+    m_it++;
+    return *this;
+  }
+
+  self_type &operator-- ()
+  {
+    --m_it;
+    return *this;
+  }
+
+  self_type &operator-- (int)
+  {
+    m_it--;
+    return *this;
+  }
+
   bool operator== (const self_type &other) const
   { return m_it == other.m_it; }
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 07/12] gdb: link breakpoint locations with intrusive_list
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (5 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 06/12] gdbsupport: add missing increment/decrement operators to reference_to_pointer_iterator Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-18 14:44   ` Andrew Burgess
  2023-05-11 14:48 ` [PATCH 08/12] gdb: remove bp_location_pointer_iterator Simon Marchi
                   ` (5 subsequent siblings)
  12 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the hand-maintained linked lists of breakpoint locations with
and intrusive list.

 - Remove breakpoint::loc, add breakpoint::m_locations.

 - Add methods for the various manipulations that need to be done on the
   location list.

 - bp_location currently has a default constructor because of one use
   in hoist_existing_locations.  hoist_existing_locations now returns a
   bp_location_list, and doesn't need the default-constructor
   bp_location anymore, so remove the bp_location default constructor.

 - Add a call to clear_locations in delete_breakpoint to avoid a
   use-after-free when struct breakpoint objects get deleted

bp_location_range uses reference_to_pointer_iterator, so that all
existing callers of breakpoint::locations don't need to change right
now.  It will be removed in the next patch.

The rest of the changes are to adapt the call sites to use the new
methods, of breakpoint::locations, rather than breakpoint::loc directly.

Change-Id: I25f7ee3d66a4e914a0540589ac414b3b820b6e70
---
 gdb/breakpoint.c | 258 ++++++++++++++++++++++++-----------------------
 gdb/breakpoint.h |  77 ++++++++++----
 gdb/tracepoint.c |   4 +-
 3 files changed, 188 insertions(+), 151 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index e9b6574bba77..6ec0f6a11e88 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -1049,13 +1049,18 @@ 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 ())
+	  auto bp_loc_range = b->locations ();
+	  for (auto bp_loc_it = bp_loc_range.begin ();
+	       bp_loc_it != bp_loc_range.end ();
+	       ++bp_loc_it)
 	    {
+	      bp_location &loc = **bp_loc_it;
+
 	      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;
@@ -1065,7 +1070,7 @@ 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 (std::next (bp_loc_it) == bp_loc_range.end () && !force)
 		    throw;
 		}
 	    }
@@ -1878,8 +1883,9 @@ add_dummy_location (struct breakpoint *b,
 {
   gdb_assert (!b->has_locations ());
 
-  b->loc = new bp_location (b, bp_loc_other);
-  b->loc->pspace = pspace;
+  bp_location *loc = new bp_location (b, bp_loc_other);
+  loc->pspace = pspace;
+  b->add_location (*loc);
 }
 
 /* Assuming that B is a watchpoint:
@@ -1982,7 +1988,7 @@ update_watchpoint (struct watchpoint *b, bool 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)
     {
@@ -2081,7 +2087,6 @@ update_watchpoint (struct watchpoint *b, bool reparse)
 		{
 		  CORE_ADDR addr;
 		  enum target_hw_bp_type type;
-		  struct bp_location *loc, **tmp;
 		  int bitpos = 0, bitsize = 0;
 
 		  if (v->bitsize () != 0)
@@ -2113,10 +2118,9 @@ update_watchpoint (struct watchpoint *b, bool reparse)
 		  else if (b->type == bp_access_watchpoint)
 		    type = hw_access;
 
-		  loc = b->allocate_location ();
-		  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
-		    ;
-		  *tmp = loc;
+		  bp_location *loc = b->allocate_location ();
+		  b->add_location (*loc);
+
 		  loc->gdbarch = v->type ()->arch ();
 
 		  loc->pspace = frame_pspace;
@@ -3029,23 +3033,11 @@ breakpoint_program_space_exit (struct program_space *pspace)
   /* 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.  */
@@ -4166,7 +4158,7 @@ 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)
 		  {
@@ -4518,28 +4510,23 @@ bpstat_locno (const bpstat *bs)
   const struct breakpoint *b = bs->breakpoint_at;
   const struct bp_location *bl = bs->bp_location_at.get ();
 
-  int locno = 0;
-
   if (b != nullptr && b->has_multiple_locations ())
     {
-      const bp_location *bl_i;
-
-      for (bl_i = b->loc;
-	   bl_i != bl && bl_i->next != nullptr;
-	   bl_i = bl_i->next)
-	locno++;
+      int locno = 1;
 
-      if (bl_i == bl)
-	locno++;
-      else
+      for (bp_location *loc : b->locations ())
 	{
-	  warning (_("location number not found for breakpoint %d address %s."),
-		   b->number, paddress (bl->gdbarch, bl->address));
-	  locno = 0;
+	  if (bl == loc)
+	    return locno;
+
+	  ++locno;
 	}
+
+      warning (_("location number not found for breakpoint %d address %s."),
+	       b->number, paddress (bl->gdbarch, bl->address));
     }
 
-  return locno;
+  return 0;
 }
 
 /* See breakpoint.h.  */
@@ -8178,18 +8165,19 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
     (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
 			       orig->frame_id, thread));
   bp_location &orig_loc = orig->first_loc ();
-  copy->loc = copy->allocate_location ();
-  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;
+  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);
@@ -8294,7 +8282,6 @@ handle_automatic_hardware_breakpoints (bp_location *bl)
 bp_location *
 code_breakpoint::add_location (const symtab_and_line &sal)
 {
-  struct bp_location *new_loc, **tmp;
   CORE_ADDR adjusted_address;
   struct gdbarch *loc_gdbarch = get_sal_arch (sal);
 
@@ -8312,12 +8299,8 @@ code_breakpoint::add_location (const symtab_and_line &sal)
 						sal.pspace);
 
   /* Sort the locations by their ADDRESS.  */
-  new_loc = allocate_location ();
-  for (tmp = &(loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
-       tmp = &((*tmp)->next))
-    ;
-  new_loc->next = *tmp;
-  *tmp = new_loc;
+  bp_location *new_loc = this->allocate_location ();
+  breakpoint::add_location (*new_loc, adjusted_address);
 
   new_loc->requested_address = sal.pc;
   new_loc->address = adjusted_address;
@@ -11623,10 +11606,7 @@ code_breakpoint::say_where () const
 
       if (this->has_multiple_locations ())
 	{
-	  struct bp_location *iter = loc;
-	  int n = 0;
-	  for (; iter; iter = iter->next)
-	    ++n;
+	  int n = std::distance (m_locations.begin (), m_locations.end ());
 	  gdb_printf (" (%d locations)", n);
 	}
     }
@@ -11636,7 +11616,9 @@ code_breakpoint::say_where () const
 
 bp_location_range breakpoint::locations () const
 {
-  return bp_location_range (this->loc);
+  return bp_location_range
+    (bp_location_pointer_iterator (m_locations.begin ()),
+     bp_location_pointer_iterator (m_locations.end ()));
 }
 
 struct bp_location *
@@ -11645,6 +11627,43 @@ breakpoint::allocate_location ()
   return new bp_location (this);
 }
 
+/* See breakpoint.h.  */
+
+void
+breakpoint::add_location (bp_location &loc)
+{
+  gdb_assert (loc.owner == this);
+  gdb_assert (!loc.is_linked ());
+
+  m_locations.push_back (loc);
+}
+
+/* See breakpoint.h.  */
+
+void
+breakpoint::add_location (bp_location &loc, CORE_ADDR address)
+{
+  gdb_assert (loc.owner == this);
+  gdb_assert (!loc.is_linked ());
+
+  auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
+			      address,
+			      [] (CORE_ADDR left, bp_location &right)
+				{ return left < right.address; });
+  m_locations.insert (ub, loc);
+}
+
+/* See breakpoint.h.  */
+
+void
+breakpoint::unadd_location (bp_location &loc)
+{
+  gdb_assert (loc.owner == this);
+  gdb_assert (loc.is_linked ());
+
+  m_locations.erase (m_locations.iterator_to (loc));
+}
+
 #define internal_error_pure_virtual_called() \
   gdb_assert_not_reached ("pure virtual function called")
 
@@ -12395,7 +12414,12 @@ 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 would access the locations after they are freed in
+     update_global_location_list.  */
+  bpt->clear_locations ();
   update_global_location_list (UGLL_DONT_INSERT);
 
   /* On the chance that someone will soon try again to delete this
@@ -12490,17 +12514,16 @@ all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
 }
 
 /* Subroutine of update_breakpoint_locations to simplify it.
-   Return true 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 bool
-ambiguous_names_p (struct bp_location *loc)
+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 ();
@@ -12645,72 +12668,56 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
   return sal;
 }
 
-/* Returns true 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 bool
-locations_are_equal (struct bp_location *a, struct bp_location *b)
+locations_are_equal (const bp_location_list &a, const bp_location_range &b)
 {
-  while (a && b)
+  auto a_iter = a.begin ();
+  auto b_iter = b.begin ();
+
+  for (; a_iter != a.end () && b_iter != b.end (); ++a_iter, ++b_iter)
     {
-      if (a->address != b->address)
+      if (a_iter->address != (*b_iter)->address)
 	return false;
 
-      if (a->shlib_disabled != b->shlib_disabled)
+      if (a_iter->shlib_disabled != (*b_iter)->shlib_disabled)
 	return false;
 
-      if (a->enabled != b->enabled)
+      if (a_iter->enabled != (*b_iter)->enabled)
 	return false;
 
-      if (a->disabled_by_cond != b->disabled_by_cond)
+      if (a_iter->disabled_by_cond != (*b_iter)->disabled_by_cond)
 	return false;
-
-      a = a->next;
-      b = b->next;
     }
 
-  if ((a == NULL) != (b == NULL))
-    return false;
-
-  return true;
+  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
@@ -12725,8 +12732,6 @@ update_breakpoint_locations (code_breakpoint *b,
 			     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
@@ -12748,7 +12753,7 @@ update_breakpoint_locations (code_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)
     {
@@ -12788,17 +12793,16 @@ update_breakpoint_locations (code_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)
 	      {
@@ -12811,10 +12815,10 @@ update_breakpoint_locations (code_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;
 		      }
 		  }
@@ -12823,11 +12827,11 @@ update_breakpoint_locations (code_breakpoint *b,
 	      {
 		for (bp_location *l : b->locations ())
 		  if (l->function_name
-		      && strcmp (e->function_name.get (),
+		      && 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;
 		    }
 	      }
@@ -12835,7 +12839,7 @@ update_breakpoint_locations (code_breakpoint *b,
       }
   }
 
-  if (!locations_are_equal (existing_locations, b->loc))
+  if (!locations_are_equal (existing_locations, b->locations ()))
     gdb::observers::breakpoint_modified.notify (b);
 }
 
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 9f49ed62a9ad..4da64d8c27c8 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -33,6 +33,7 @@
 #include "gdbsupport/next-iterator.h"
 #include "gdbsupport/iterator-range.h"
 #include "gdbsupport/refcounted-object.h"
+#include "gdbsupport/reference-to-pointer-iterator.h"
 #include "gdbsupport/safe-iterator.h"
 #include "cli/cli-script.h"
 #include "target/waitstatus.h"
@@ -321,11 +322,9 @@ enum bp_loc_type
   bp_loc_other			/* Miscellaneous...  */
 };
 
-class bp_location : public refcounted_object
+class bp_location : public refcounted_object, public intrusive_list_node<bp_location>
 {
 public:
-  bp_location () = default;
-
   /* Construct a bp_location with the type inferred from OWNER's
      type.  */
   explicit bp_location (breakpoint *owner);
@@ -335,10 +334,6 @@ class bp_location : public refcounted_object
 
   virtual ~bp_location () = default;
 
-  /* Chain pointer to the next breakpoint location for
-     the same parent breakpoint.  */
-  bp_location *next = NULL;
-
   /* Type of this breakpoint location.  */
   bp_loc_type loc_type {};
 
@@ -609,9 +604,11 @@ enum watchpoint_triggered
 
 extern bool target_exact_watchpoints;
 
-/* bp_location linked list range.  */
-
-using bp_location_range = next_range<bp_location>;
+using bp_location_list = intrusive_list<bp_location>;
+using bp_location_iterator = bp_location_list::iterator;
+using bp_location_pointer_iterator
+  = reference_to_pointer_iterator<bp_location_iterator>;
+using bp_location_range = iterator_range<bp_location_pointer_iterator>;
 
 /* Note that the ->silent field is not currently used by any commands
    (though the code is in there if it was to be, and set_raw_breakpoint
@@ -633,30 +630,71 @@ struct breakpoint
   /* Allocate a location for this breakpoint.  */
   virtual struct bp_location *allocate_location ();
 
+  /* Return a range of this breakpoint's locations.  */
+  bp_location_range locations () const;
+
+  /* Add LOC at the end of the location list of this breakpoint.
+
+     LOC must have this breakpoint as its owner.  LOC must not already be linked
+     in a location list.  */
+  void add_location (bp_location &loc);
+
+  /* Add LOC in the location list of this breakpoint, sorted by address.
+
+     LOC must have this breakpoint as its owner.  LOC must not already be linked
+     in a location list.  */
+  void add_location (bp_location &loc, CORE_ADDR address);
+
+  /* Remove LOC from this breakpoint's location list.  The name is a bit funny
+     because remove_location is already taken, and means something else.
+
+     LOC must be have this breakpoints as its owner.  LOC must be linked in this
+     breakpoint's location list.  */
+  void unadd_location (bp_location &loc);
+
+  /* Clear the location list of this breakpoint.  */
+  void clear_locations ()
+  { m_locations.clear (); }
+
+  /* Split all locations of this breakpoint that are bound to PSPACE out of its
+     location list to a separate list and return that list.  If
+     PSPACE is nullptr, hoist out all locations.  */
+  bp_location_list steal_locations (program_space *pspace);
+
   /* Return true if this breakpoint has a least one location.  */
   bool has_locations () const
-  { return this->loc != nullptr; }
+  { return !m_locations.empty (); }
 
   /* Return true if this breakpoint has a single location.  */
   bool has_single_location () const
-  { return this->loc != nullptr && this->loc->next == nullptr; }
+  {
+    if (!this->has_locations ())
+      return false;
+
+    return std::next (m_locations.begin ()) == m_locations.end ();
+  }
 
   /* Return true if this breakpoint has multiple locations.  */
   bool has_multiple_locations () const
-  { return this->loc != nullptr && this->loc->next != nullptr; }
+  {
+    if (!this->has_locations ())
+      return false;
+
+    return std::next (m_locations.begin ()) != m_locations.end ();
+  }
 
   /* Return a reference to the first location of this breakpoint.  */
   bp_location &first_loc ()
   {
     gdb_assert (this->has_locations ());
-    return *this->loc;
+    return m_locations.front ();
   }
 
   /* Return a reference to the first location of this breakpoint.  */
   const bp_location &first_loc () const
   {
     gdb_assert (this->has_locations ());
-    return *this->loc;
+    return m_locations.front ();
   }
 
   /* Reevaluate a breakpoint.  This is necessary after symbols change
@@ -753,9 +791,6 @@ struct breakpoint
     /* Nothing to do.  */
   }
 
-  /* Return a range of this breakpoint's locations.  */
-  bp_location_range locations () const;
-
   breakpoint *next = NULL;
   /* Type of breakpoint.  */
   bptype type = bp_none;
@@ -766,9 +801,6 @@ struct breakpoint
   /* Number assigned to distinguish breakpoints.  */
   int number = 0;
 
-  /* Location(s) associated with this high-level breakpoint.  */
-  bp_location *loc = NULL;
-
   /* True means a silent breakpoint (don't print frame info if we stop
      here).  */
   bool silent = false;
@@ -864,6 +896,9 @@ struct breakpoint
      thread 1", which needs outputting before any breakpoint-type
      specific extra command necessary for B's recreation.  */
   void print_recreate_thread (struct ui_file *fp) const;
+
+  /* Location(s) associated with this high-level breakpoint.  */
+  bp_location_list m_locations;
 };
 
 /* Abstract base class representing code breakpoints.  User "break"
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 99d175d32e42..3e0bdafa19d3 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -3044,8 +3044,6 @@ cond_string_is_same (char *str1, char *str2)
 static struct bp_location *
 find_matching_tracepoint_location (struct uploaded_tp *utp)
 {
-  struct bp_location *loc;
-
   for (breakpoint *b : all_tracepoints ())
     {
       struct tracepoint *t = (struct tracepoint *) b;
@@ -3059,7 +3057,7 @@ find_matching_tracepoint_location (struct uploaded_tp *utp)
 	  )
 	{
 	  /* Scan the locations for an address match.  */
-	  for (loc = b->loc; loc; loc = loc->next)
+	  for (bp_location *loc : b->locations ())
 	    {
 	      if (loc->address == utp->addr)
 		return loc;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 08/12] gdb: remove bp_location_pointer_iterator
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (6 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 07/12] gdb: link breakpoint locations with intrusive_list Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 09/12] gdb: link breakpoints with intrusive_list Simon Marchi
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Remove the bp_location_pointer_iterator layer.  Adjust all users of
breakpoint::locations to use references instead of pointers.

Change-Id: Iceed34f5e0f5790a9cf44736aa658be6d1ba1afa
---
 gdb/ada-lang.c             |  14 +--
 gdb/break-catch-load.c     |   4 +-
 gdb/breakpoint.c           | 242 ++++++++++++++++++-------------------
 gdb/breakpoint.h           |   4 +-
 gdb/jit.c                  |   6 +-
 gdb/python/py-breakpoint.c |   4 +-
 gdb/remote.c               |   4 +-
 gdb/solib-svr4.c           |   6 +-
 gdb/tracepoint.c           |  60 +++++----
 gdb/tui/tui-winsource.c    |   4 +-
 10 files changed, 169 insertions(+), 179 deletions(-)

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 207d58e80a63..b0cf2d8ff89e 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -12214,22 +12214,20 @@ create_excep_cond_exprs (struct ada_catchpoint *c,
 
   /* Iterate over all the catchpoint's locations, and parse an
      expression for each.  */
-  for (bp_location *bl : c->locations ())
+  for (bp_location &bl : c->locations ())
     {
-      struct ada_catchpoint_location *ada_loc
-	= (struct ada_catchpoint_location *) bl;
+      ada_catchpoint_location &ada_loc
+	= static_cast<ada_catchpoint_location &> (bl);
       expression_up exp;
 
-      if (!bl->shlib_disabled)
+      if (!bl.shlib_disabled)
 	{
 	  const char *s;
 
 	  s = cond_string.c_str ();
 	  try
 	    {
-	      exp = parse_exp_1 (&s, bl->address,
-				 block_for_pc (bl->address),
-				 0);
+	      exp = parse_exp_1 (&s, bl.address, block_for_pc (bl.address), 0);
 	    }
 	  catch (const gdb_exception_error &e)
 	    {
@@ -12239,7 +12237,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c,
 	    }
 	}
 
-      ada_loc->excep_cond_expr = std::move (exp);
+      ada_loc.excep_cond_expr = std::move (exp);
     }
 }
 
diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
index d33313a1d989..43962880cd96 100644
--- a/gdb/break-catch-load.c
+++ b/gdb/break-catch-load.c
@@ -102,9 +102,9 @@ solib_catchpoint::breakpoint_hit (const struct bp_location *bl,
       if (pspace != NULL && other->pspace != pspace)
 	continue;
 
-      for (bp_location *other_bl : other->locations ())
+      for (bp_location &other_bl : other->locations ())
 	{
-	  if (other->breakpoint_hit (other_bl, aspace, bp_addr, ws))
+	  if (other->breakpoint_hit (&other_bl, aspace, bp_addr, ws))
 	    return 1;
 	}
     }
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6ec0f6a11e88..bd3258a742e2 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -842,8 +842,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
@@ -1007,14 +1007,14 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
       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)
+	      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.disabled_by_cond = false;
 	      loc_num++;
 
 	      /* No need to free the condition agent expression
@@ -1054,7 +1054,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
 	       bp_loc_it != bp_loc_range.end ();
 	       ++bp_loc_it)
 	    {
-	      bp_location &loc = **bp_loc_it;
+	      bp_location &loc = *bp_loc_it;
 
 	      try
 		{
@@ -1077,9 +1077,9 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp,
 
 	  /* 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++;
 	    }
 	}
@@ -1417,8 +1417,8 @@ static_tracepoints_here (CORE_ADDR addr)
     if (b->type == bp_static_tracepoint
 	|| b->type == bp_static_marker_tracepoint)
       {
-	for (bp_location *loc : b->locations ())
-	  if (loc->address == addr)
+	for (bp_location &loc : b->locations ())
+	  if (loc.address == addr)
 	    found.push_back (b);
       }
 
@@ -2122,7 +2122,6 @@ update_watchpoint (struct watchpoint *b, bool reparse)
 		  b->add_location (*loc);
 
 		  loc->gdbarch = v->type ()->arch ();
-
 		  loc->pspace = frame_pspace;
 		  loc->address
 		    = gdbarch_remove_non_address_bits (loc->gdbarch, addr);
@@ -2237,8 +2236,9 @@ update_watchpoint (struct watchpoint *b, bool reparse)
 
 	  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
@@ -3187,9 +3187,9 @@ insert_breakpoint_locations (void)
 
       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 = true;
 	    break;
@@ -3197,9 +3197,9 @@ insert_breakpoint_locations (void)
 
       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 "
@@ -4355,14 +4355,14 @@ hardware_watchpoint_inserted_in_range (const address_space *aspace,
       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;
 	  }
@@ -4514,9 +4514,9 @@ bpstat_locno (const bpstat *bs)
     {
       int locno = 1;
 
-      for (bp_location *loc : b->locations ())
+      for (bp_location &loc : b->locations ())
 	{
-	  if (bl == loc)
+	  if (bl == &loc)
 	    return locno;
 
 	  ++locno;
@@ -5041,12 +5041,12 @@ watchpoints_triggered (const target_waitstatus &ws)
 	struct watchpoint *w = (struct watchpoint *) b;
 
 	w->watchpoint_triggered = watch_triggered_no;
-	for (bp_location *loc : b->locations ())
+	for (bp_location &loc : b->locations ())
 	  {
 	    if (is_masked_watchpoint (b))
 	      {
 		CORE_ADDR newaddr = addr & w->hw_wp_mask;
-		CORE_ADDR start = loc->address & w->hw_wp_mask;
+		CORE_ADDR start = loc.address & w->hw_wp_mask;
 
 		if (newaddr == start)
 		  {
@@ -5056,8 +5056,8 @@ watchpoints_triggered (const target_waitstatus &ws)
 	      }
 	    /* 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;
 		break;
@@ -5613,26 +5613,26 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
       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->first_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
@@ -6109,9 +6109,9 @@ bp_condition_evaluator (const 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++;
@@ -6743,10 +6743,10 @@ print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
 	    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++;
 	    }
@@ -6759,12 +6759,12 @@ breakpoint_address_bits (struct breakpoint *b)
 {
   int print_address_bits = 0;
 
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     {
-      if (!bl_address_is_meaningful (loc))
+      if (!bl_address_is_meaningful (&loc))
 	continue;
 
-      int 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;
     }
@@ -6924,8 +6924,8 @@ breakpoint_1 (const char *bp_num_list, bool show_internal,
 	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)
+	    for (bp_location &loc : b->locations ())
+	      if (loc.disabled_by_cond)
 		has_disabled_by_cond_location = true;
 	  }
       }
@@ -7018,11 +7018,11 @@ 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))
+      if (bl.pspace == pspace
+	  && bl.address == pc
+	  && (!overlay_debugging || bl.section == section))
 	return true;
     }
   return false;
@@ -7927,34 +7927,34 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
       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 = true;
 	    }
@@ -8016,11 +8016,11 @@ hw_breakpoint_used_count (void)
 
   for (breakpoint *b : all_breakpoints ())
     if (b->type == bp_hardware_breakpoint && breakpoint_enabled (b))
-      for (bp_location *bl : b->locations ())
+      for (bp_location &bl : b->locations ())
 	{
 	  /* Special types of hardware breakpoints may use more than
 	     one register.  */
-	  i += b->resources_needed (bl);
+	  i += b->resources_needed (&bl);
 	}
 
   return i;
@@ -8037,11 +8037,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->resources_needed (bl);
+      i += b->resources_needed (&bl);
     }
 
   return i;
@@ -8545,10 +8545,10 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
   /* The order of the locations is now stable.  Set the location
      condition using the location's number.  */
   int loc_num = 1;
-  for (bp_location *bl : locations ())
+  for (bp_location &bl : locations ())
     {
       if (cond_string != nullptr)
-	set_breakpoint_location_condition (cond_string.get (), bl,
+	set_breakpoint_location_condition (cond_string.get (), &bl,
 					   number, loc_num);
 
       ++loc_num;
@@ -10838,24 +10838,24 @@ clear_command (const char *arg, int from_tty)
 	  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;
 
@@ -11041,19 +11041,19 @@ 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;
+	  bl.inserted = 1;
 	  bp_location_downloaded = true;
 	}
       t = (struct tracepoint *) b;
@@ -11167,8 +11167,8 @@ update_global_location_list (enum ugll_insert_mode insert_mode)
   bp_locations.clear ();
 
   for (breakpoint *b : all_breakpoints ())
-    for (bp_location *loc : b->locations ())
-      bp_locations.push_back (loc);
+    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
@@ -11616,9 +11616,7 @@ code_breakpoint::say_where () const
 
 bp_location_range breakpoint::locations () const
 {
-  return bp_location_range
-    (bp_location_pointer_iterator (m_locations.begin ()),
-     bp_location_pointer_iterator (m_locations.end ()));
+  return bp_location_range (m_locations.begin (), m_locations.end ());
 }
 
 struct bp_location *
@@ -12504,11 +12502,11 @@ delete_command (const char *arg, int from_tty)
 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)
+	 || loc.pspace == pspace)
+	&& !loc.shlib_disabled
+	&& !loc.pspace->executing_startup)
       return false;
   return true;
 }
@@ -12523,10 +12521,10 @@ ambiguous_names_p (const bp_location_range &locs)
   htab_up htab (htab_create_alloc (13, htab_hash_string, htab_eq_string, NULL,
 				   xcalloc, xfree));
 
-  for (const bp_location *l : locs)
+  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)
@@ -12679,16 +12677,16 @@ locations_are_equal (const bp_location_list &a, const bp_location_range &b)
 
   for (; a_iter != a.end () && b_iter != b.end (); ++a_iter, ++b_iter)
     {
-      if (a_iter->address != (*b_iter)->address)
+      if (a_iter->address != b_iter->address)
 	return false;
 
-      if (a_iter->shlib_disabled != (*b_iter)->shlib_disabled)
+      if (a_iter->shlib_disabled != b_iter->shlib_disabled)
 	return false;
 
-      if (a_iter->enabled != (*b_iter)->enabled)
+      if (a_iter->enabled != b_iter->enabled)
 	return false;
 
-      if (a_iter->disabled_by_cond != (*b_iter)->disabled_by_cond)
+      if (a_iter->disabled_by_cond != b_iter->disabled_by_cond)
 	return false;
     }
 
@@ -12806,7 +12804,7 @@ update_breakpoint_locations (code_breakpoint *b,
 	  {
 	    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
@@ -12815,23 +12813,23 @@ update_breakpoint_locations (code_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
+		for (bp_location &l : b->locations ())
+		  if (l.function_name
 		      && strcmp (e.function_name.get (),
-				 l->function_name.get ()) == 0)
+				 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;
 		    }
 	      }
@@ -13186,9 +13184,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);
 }
@@ -13356,9 +13354,9 @@ find_loc_num_by_location (const bp_location *loc)
     {
       /* Locations use 1-based indexing.  */
       int loc_num = 1;
-      for (bp_location *it : loc->owner->locations ())
+      for (bp_location &it : loc->owner->locations ())
 	{
-	  if (it == loc)
+	  if (&it == loc)
 	    return loc_num;
 	  loc_num++;
 	}
@@ -13439,8 +13437,8 @@ 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);
@@ -13562,8 +13560,8 @@ 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;
@@ -13657,10 +13655,10 @@ invalidate_bp_value_on_memory_change (struct inferior *inferior,
 
 	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;
@@ -13736,9 +13734,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;
@@ -14275,9 +14273,9 @@ save_breakpoints (const char *filename, int from_tty,
 	{
 	  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++;
@@ -14416,10 +14414,10 @@ pc_at_non_inline_function (const address_space *aspace, CORE_ADDR pc,
       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;
 	}
     }
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 4da64d8c27c8..8c9541902cdd 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -606,9 +606,7 @@ extern bool target_exact_watchpoints;
 
 using bp_location_list = intrusive_list<bp_location>;
 using bp_location_iterator = bp_location_list::iterator;
-using bp_location_pointer_iterator
-  = reference_to_pointer_iterator<bp_location_iterator>;
-using bp_location_range = iterator_range<bp_location_pointer_iterator>;
+using bp_location_range = iterator_range<bp_location_iterator>;
 
 /* Note that the ->silent field is not currently used by any commands
    (though the code is in there if it was to be, and set_raw_breakpoint
diff --git a/gdb/jit.c b/gdb/jit.c
index e085d5623336..25c8ed8499a2 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -845,14 +845,14 @@ jit_breakpoint_deleted (struct breakpoint *b)
   if (b->type != bp_jit_event)
     return;
 
-  for (bp_location *iter : b->locations ())
+  for (bp_location &iter : b->locations ())
     {
-      for (objfile *objf : iter->pspace->objfiles ())
+      for (objfile *objf : iter.pspace->objfiles ())
 	{
 	  jiter_objfile_data *jiter_data = objf->jiter_data.get ();
 
 	  if (jiter_data != nullptr
-	      && jiter_data->jit_breakpoint == iter->owner)
+	      && jiter_data->jit_breakpoint == iter.owner)
 	    {
 	      jiter_data->cached_code_address = 0;
 	      jiter_data->jit_breakpoint = nullptr;
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index becb04c91c15..8a306c6b3318 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -752,14 +752,14 @@ bppy_get_locations (PyObject *self, void *closure)
   if (list == nullptr)
     return nullptr;
 
-  for (bp_location *loc : self_bp->bp->locations ())
+  for (bp_location &loc : self_bp->bp->locations ())
     {
       gdbpy_ref<py_bploc_t> py_bploc
 	(PyObject_New (py_bploc_t, &breakpoint_location_object_type));
       if (py_bploc == nullptr)
 	return nullptr;
 
-      bp_location_ref_ptr ref = bp_location_ref_ptr::new_reference (loc);
+      bp_location_ref_ptr ref = bp_location_ref_ptr::new_reference (&loc);
       /* The location takes a reference to the owner breakpoint.
 	 Decrements when they are de-allocated in bplocpy_dealloc */
       Py_INCREF (self);
diff --git a/gdb/remote.c b/gdb/remote.c
index 8eaa1b2c4d15..f7d5758cfdc5 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -13720,14 +13720,14 @@ remote_target::get_tracepoint_status (struct breakpoint *bp,
     {
       tp->hit_count = 0;
       tp->traceframe_usage = 0;
-      for (bp_location *loc : tp->locations ())
+      for (bp_location &loc : tp->locations ())
 	{
 	  /* If the tracepoint was never downloaded, don't go asking for
 	     any status.  */
 	  if (tp->number_on_target == 0)
 	    continue;
 	  xsnprintf (rs->buf.data (), size, "qTP:%x:%s", tp->number_on_target,
-		     phex_nz (loc->address, 0));
+		     phex_nz (loc.address, 0));
 	  putpkt (rs->buf);
 	  reply = remote_get_noisy_reply ();
 	  if (reply && *reply)
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 5a728939111a..46f09a7e63ce 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2117,16 +2117,16 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
       return false;
     }
 
-  for (bp_location *loc : b->locations ())
+  for (bp_location &loc : b->locations ())
     {
       struct svr4_info *info;
       struct probe_and_action *pa;
 
-      info = solib_svr4_pspace_data.get (loc->pspace);
+      info = solib_svr4_pspace_data.get (loc.pspace);
       if (info == NULL || info->probes_table == NULL)
 	continue;
 
-      pa = solib_event_probe_at (info, loc->address);
+      pa = solib_event_probe_at (info, loc.address);
       if (pa == NULL)
 	continue;
 
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 3e0bdafa19d3..fa65e0493720 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -676,11 +676,11 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      /* else fall thru, treat p as an expression and parse it!  */
 	    }
 	  tmp_p = p;
-	  for (bp_location *loc : t->locations ())
+	  for (bp_location &loc : t->locations ())
 	    {
 	      p = tmp_p;
-	      expression_up exp = parse_exp_1 (&p, loc->address,
-					       block_for_pc (loc->address), 1);
+	      expression_up exp = parse_exp_1 (&p, loc.address,
+					       block_for_pc (loc.address), 1);
 
 	      if (exp->first_opcode () == OP_VAR_VALUE)
 		{
@@ -708,7 +708,7 @@ validate_actionline (const char *line, struct breakpoint *b)
 	      /* We have something to collect, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      agent_expr_up aexpr = gen_trace_for_expr (loc->address,
+	      agent_expr_up aexpr = gen_trace_for_expr (loc.address,
 							exp.get (),
 							trace_string);
 
@@ -726,18 +726,18 @@ validate_actionline (const char *line, struct breakpoint *b)
 	  p = skip_spaces (p);
 
 	  tmp_p = p;
-	  for (bp_location *loc : t->locations ())
+	  for (bp_location &loc : t->locations ())
 	    {
 	      p = tmp_p;
 
 	      /* Only expressions are allowed for this action.  */
-	      expression_up exp = parse_exp_1 (&p, loc->address,
-					       block_for_pc (loc->address), 1);
+	      expression_up exp = parse_exp_1 (&p, loc.address,
+					       block_for_pc (loc.address), 1);
 
 	      /* We have something to evaluate, make sure that the expr to
 		 bytecode translator can handle it and that it's not too
 		 long.  */
-	      agent_expr_up aexpr = gen_eval_for_expr (loc->address, exp.get ());
+	      agent_expr_up aexpr = gen_eval_for_expr (loc.address, exp.get ());
 
 	      finalize_tracepoint_aexpr (aexpr.get ());
 	    }
@@ -1529,9 +1529,9 @@ process_tracepoint_on_disconnect (void)
 	}
       else
 	{
-	  for (bp_location *loc1 : b->locations ())
+	  for (bp_location &loc1 : b->locations ())
 	    {
-	      if (loc1->shlib_disabled)
+	      if (loc1.shlib_disabled)
 		{
 		  has_pending_p = 1;
 		  break;
@@ -1608,8 +1608,8 @@ start_tracing (const char *notes)
       int bp_location_downloaded = 0;
 
       /* Clear `inserted' flag.  */
-      for (bp_location *loc : b->locations ())
-	loc->inserted = 0;
+      for (bp_location &loc : b->locations ())
+	loc.inserted = 0;
 
       if ((b->type == bp_fast_tracepoint
 	   ? !may_insert_fast_tracepoints
@@ -1618,24 +1618,23 @@ start_tracing (const char *notes)
 
       t->number_on_target = 0;
 
-      for (bp_location *loc : b->locations ())
+      for (bp_location &loc : b->locations ())
 	{
 	  /* Since tracepoint locations are never duplicated, `inserted'
 	     flag should be zero.  */
-	  gdb_assert (!loc->inserted);
+	  gdb_assert (!loc.inserted);
 
-	  target_download_tracepoint (loc);
+	  target_download_tracepoint (&loc);
 
-	  loc->inserted = 1;
+	  loc.inserted = 1;
 	  bp_location_downloaded = 1;
 	}
 
       t->number_on_target = b->number;
 
-      for (bp_location *loc : b->locations ())
-	if (loc->probe.prob != NULL)
-	  loc->probe.prob->set_semaphore (loc->probe.objfile,
-					  loc->gdbarch);
+      for (bp_location &loc : b->locations ())
+	if (loc.probe.prob != NULL)
+	  loc.probe.prob->set_semaphore (loc.probe.objfile, loc.gdbarch);
 
       if (bp_location_downloaded)
 	gdb::observers::breakpoint_modified.notify (b);
@@ -1717,15 +1716,14 @@ stop_tracing (const char *note)
 	   : !may_insert_tracepoints))
 	continue;
 
-      for (bp_location *loc : t->locations ())
+      for (bp_location &loc : t->locations ())
 	{
 	  /* GDB can be totally absent in some disconnected trace scenarios,
 	     but we don't really care if this semaphore goes out of sync.
 	     That's why we are decrementing it here, but not taking care
 	     in other places.  */
-	  if (loc->probe.prob != NULL)
-	    loc->probe.prob->clear_semaphore (loc->probe.objfile,
-					      loc->gdbarch);
+	  if (loc.probe.prob != NULL)
+	    loc.probe.prob->clear_semaphore (loc.probe.objfile, loc.gdbarch);
 	}
     }
 
@@ -2740,11 +2738,11 @@ get_traceframe_location (int *stepping_frame_p)
      locations, assume it is a direct hit rather than a while-stepping
      frame.  (FIXME this is not reliable, should record each frame's
      type.)  */
-  for (bp_location *tloc : t->locations ())
-    if (tloc->address == regcache_read_pc (regcache))
+  for (bp_location &tloc : t->locations ())
+    if (tloc.address == regcache_read_pc (regcache))
       {
 	*stepping_frame_p = 0;
-	return tloc;
+	return &tloc;
       }
 
   /* If this is a stepping frame, we don't know which location
@@ -3057,11 +3055,9 @@ find_matching_tracepoint_location (struct uploaded_tp *utp)
 	  )
 	{
 	  /* Scan the locations for an address match.  */
-	  for (bp_location *loc : b->locations ())
-	    {
-	      if (loc->address == utp->addr)
-		return loc;
-	    }
+	  for (bp_location &loc : b->locations ())
+	    if (loc.address == utp->addr)
+	      return &loc;
 	}
     }
   return NULL;
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 3fc38b7be233..9e4760618187 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -630,9 +630,9 @@ tui_source_window_base::update_breakpoint_info
 	  if (bp == being_deleted)
 	    continue;
 
-	  for (bp_location *loc : bp->locations ())
+	  for (bp_location &loc : bp->locations ())
 	    {
-	      if (location_matches_p (loc, i))
+	      if (location_matches_p (&loc, i))
 		{
 		  if (bp->enable_state == bp_disabled)
 		    mode |= TUI_BP_DISABLED;
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 09/12] gdb: link breakpoints with intrusive_list
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (7 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 08/12] gdb: remove bp_location_pointer_iterator Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 10/12] gdbsupport: make basic_safe_iterator::operator* return the same thing as underlying iterator Simon Marchi
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Replace the hand-maintained linked list with an intrusive_list.
Since the breakpoint list (breakpoint_chain) is internal to
breakpoint.c, the changes are mostly localized in breakpoint.c.

Use reference_to_pointer_iterator to implement breakpoint_range, such
that users of all_breakpoints and all_tracepoints don't need to change
right now.  It is removed in the following patch.

Nothing too surprising other than that.

Change-Id: I043d8d6f3dd864d80d5088f6ffc2c098337249ea
---
 gdb/breakpoint.c | 36 ++++++++++--------------------------
 gdb/breakpoint.h | 13 ++++++++-----
 2 files changed, 18 insertions(+), 31 deletions(-)

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index bd3258a742e2..5f47dc777438 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -614,14 +614,16 @@ bool target_exact_watchpoints = false;
 
 /* 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_pointer_iterator (breakpoint_chain.begin ()),
+     breakpoint_pointer_iterator (breakpoint_chain.end ()));
 }
 
 /* See breakpoint.h.  */
@@ -637,7 +639,9 @@ all_breakpoints_safe ()
 tracepoint_range
 all_tracepoints ()
 {
-  return tracepoint_range (breakpoint_chain);
+  return tracepoint_range
+    (tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.begin ())),
+     tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.end ())));
 }
 
 /* Array is sorted by bp_location_is_less_than - primarily by the ADDRESS.  */
@@ -7432,23 +7436,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 ();
-    }
+  breakpoint_chain.push_back (*b.release ());
 
-  return result;
+  return &breakpoint_chain.back ();
 }
 
 /* Initialize loc->function_name.  */
@@ -12385,15 +12378,7 @@ delete_breakpoint (struct breakpoint *bpt)
   if (bpt->number)
     gdb::observers::breakpoint_deleted.notify (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.  */
@@ -14456,7 +14441,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;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 8c9541902cdd..a03b57734b9d 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -616,7 +616,7 @@ using bp_location_range = iterator_range<bp_location_iterator>;
 
 /* Abstract base class representing all kinds of breakpoints.  */
 
-struct breakpoint
+struct breakpoint : public intrusive_list_node<breakpoint>
 {
   breakpoint (struct gdbarch *gdbarch_, enum bptype bptype,
 	      bool temp = true, const char *cond_string = nullptr);
@@ -789,7 +789,6 @@ struct breakpoint
     /* Nothing to do.  */
   }
 
-  breakpoint *next = NULL;
   /* Type of breakpoint.  */
   bptype type = bp_none;
   /* Zero means disabled; remember the info but don't break here.  */
@@ -1892,11 +1891,15 @@ class scoped_rbreak_breakpoints
 
 /* Breakpoint linked list iterator.  */
 
-using breakpoint_iterator = next_iterator<breakpoint>;
+using breakpoint_list = intrusive_list<breakpoint>;
+
+using breakpoint_iterator = breakpoint_list::iterator;
+
+using breakpoint_pointer_iterator = reference_to_pointer_iterator<breakpoint_iterator>;
 
 /* Breakpoint linked list range.  */
 
-using breakpoint_range = iterator_range<breakpoint_iterator>;
+using breakpoint_range = iterator_range<breakpoint_pointer_iterator>;
 
 /* Return a range to iterate over all breakpoints.  */
 
@@ -1923,7 +1926,7 @@ struct tracepoint_filter
 /* Breakpoint linked list iterator, filtering to only keep tracepoints.  */
 
 using tracepoint_iterator
-  = filtered_iterator<breakpoint_iterator, tracepoint_filter>;
+  = filtered_iterator<breakpoint_pointer_iterator, tracepoint_filter>;
 
 /* Breakpoint linked list range, filtering to only keep tracepoints.  */
 
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 10/12] gdbsupport: make basic_safe_iterator::operator* return the same thing as underlying iterator
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (8 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 09/12] gdb: link breakpoints with intrusive_list Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 11/12] gdbsupport: make filtered_iterator::operator* " Simon Marchi
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Using the following patch that removes the reference_to_pointer_iterator
from breakpoint_range, I would get:

      CXX    breakpoint.o
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c: In function ‘void breakpoint_program_space_exit(program_space*)’:
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:3030:46: error: cannot allocate an object of abstract type ‘breakpoint’
     3030 |   for (breakpoint &b : all_breakpoints_safe ())
          |                                              ^
    In file included from /home/smarchi/src/binutils-gdb/gdb/gdbthread.h:26,
                     from /home/smarchi/src/binutils-gdb/gdb/infrun.h:21,
                     from /home/smarchi/src/binutils-gdb/gdb/gdbarch.h:28,
                     from /home/smarchi/src/binutils-gdb/gdb/arch-utils.h:23,
                     from /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:21:
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.h:619:8: note:   because the following virtual functions are pure within ‘breakpoint’:
      619 | struct breakpoint : public intrusive_list_node<breakpoint>
          |        ^~~~~~~~~~
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:250:1: note:     ‘virtual breakpoint::~breakpoint()’
      250 | breakpoint::~breakpoint ()
          | ^~~~~~~~~~

This is because the operator* method of the basic_safe_iterator iterator
wrapper returns a value_type.  So, even if the method of the underlying
iterator (breakpoint_iterator, an intrusive_list iterator) returns a
`breakpoint &`, the method of the wrapper returns a `breakpoint`.

I think it would make sense for iterator wrappers such as
basic_safe_iterator to return the exact same thing as the iterator they
wrap.  At least, it fixes my problem.

Change-Id: Ibbcd390ac03d2fb6ae4854923750c8d7c3c04e8a
---
 gdbsupport/safe-iterator.h | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/gdbsupport/safe-iterator.h b/gdbsupport/safe-iterator.h
index bc8b4356540e..ccd772ca2a59 100644
--- a/gdbsupport/safe-iterator.h
+++ b/gdbsupport/safe-iterator.h
@@ -19,6 +19,8 @@
 #ifndef COMMON_SAFE_ITERATOR_H
 #define COMMON_SAFE_ITERATOR_H
 
+#include "gdbsupport/invoke-result.h"
+
 /* A forward iterator that wraps Iterator, such that when iterating
    with iterator IT, it is possible to delete *IT without invalidating
    IT.  Suitably wrapped in a range type and used with range-for, this
@@ -75,7 +77,9 @@ class basic_safe_iterator
   basic_safe_iterator ()
   {}
 
-  value_type operator* () const { return *m_it; }
+  typename gdb::invoke_result<decltype(&Iterator::operator*), Iterator>::type
+    operator* () const
+  { return *m_it; }
 
   self_type &operator++ ()
   {
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 11/12] gdbsupport: make filtered_iterator::operator* return the same thing as underlying iterator
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (9 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 10/12] gdbsupport: make basic_safe_iterator::operator* return the same thing as underlying iterator Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-11 14:48 ` [PATCH 12/12] gdb: remove breakpoint_pointer_iterator Simon Marchi
  2023-05-18 15:54 ` [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Andrew Burgess
  12 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

This is the same idea as the previous patch, but for filtered_iterator.
Without this patch, I would see this when applying the patch that
removes reference_to_pointer_iterator from breakpoint_range:

      CXX    breakpoint.o
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c: In function ‘void download_tracepoint_locations()’:
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:11007:41: error: cannot allocate an object of abstract type ‘breakpoint’
    11007 |   for (breakpoint &b : all_tracepoints ())
          |                                         ^
    In file included from /home/smarchi/src/binutils-gdb/gdb/gdbthread.h:26,
                     from /home/smarchi/src/binutils-gdb/gdb/infrun.h:21,
                     from /home/smarchi/src/binutils-gdb/gdb/gdbarch.h:28,
                     from /home/smarchi/src/binutils-gdb/gdb/arch-utils.h:23,
                     from /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:21:
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.h:619:8: note:   because the following virtual functions are pure within ‘breakpoint’:
      619 | struct breakpoint : public intrusive_list_node<breakpoint>
          |        ^~~~~~~~~~
    /home/smarchi/src/binutils-gdb/gdb/breakpoint.c:250:1: note:     ‘virtual breakpoint::~breakpoint()’
      250 | breakpoint::~breakpoint ()
          | ^~~~~~~~~~

Change-Id: I05285ff27d21cb0ab80cba392ec4e959167e3cd7
---
 gdbsupport/filtered-iterator.h | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdbsupport/filtered-iterator.h b/gdbsupport/filtered-iterator.h
index d87484cadca4..9e9548ef824e 100644
--- a/gdbsupport/filtered-iterator.h
+++ b/gdbsupport/filtered-iterator.h
@@ -19,6 +19,8 @@
 #ifndef COMMON_FILTERED_ITERATOR_H
 #define COMMON_FILTERED_ITERATOR_H
 
+#include "gdbsupport/invoke-result.h"
+
 /* A filtered iterator.  This wraps BaseIterator and automatically
    skips elements that FilterFunc filters out.  Requires that
    default-constructing a BaseIterator creates a valid one-past-end
@@ -54,7 +56,10 @@ class filtered_iterator
     : filtered_iterator (static_cast<const filtered_iterator &> (other))
   {}
 
-  value_type operator* () const { return *m_it; }
+  typename gdb::invoke_result<decltype(&BaseIterator::operator*),
+			      BaseIterator>::type
+    operator* () const
+  { return *m_it; }
 
   self_type &operator++ ()
   {
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 12/12] gdb: remove breakpoint_pointer_iterator
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (10 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 11/12] gdbsupport: make filtered_iterator::operator* " Simon Marchi
@ 2023-05-11 14:48 ` Simon Marchi
  2023-05-18 15:53   ` Andrew Burgess
  2023-05-18 15:54 ` [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Andrew Burgess
  12 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-11 14:48 UTC (permalink / raw)
  To: gdb-patches; +Cc: Simon Marchi

Remove the breakpoint_pointer_iterator layer.  Adjust all users of
all_breakpoints and all_tracepoints to use references instead of
pointers.

Change-Id: I376826f812117cee1e6b199c384a10376973af5d
---
 gdb/break-catch-load.c           |  12 +-
 gdb/break-catch-syscall.c        |   4 +-
 gdb/breakpoint.c                 | 605 +++++++++++++++----------------
 gdb/breakpoint.h                 |  10 +-
 gdb/dummy-frame.c                |   4 +-
 gdb/guile/scm-breakpoint.c       |   4 +-
 gdb/python/py-breakpoint.c       |   4 +-
 gdb/python/py-finishbreakpoint.c |   8 +-
 gdb/solib-svr4.c                 |   4 +-
 gdb/tracepoint.c                 |  56 +--
 gdb/tui/tui-winsource.c          |  14 +-
 11 files changed, 360 insertions(+), 365 deletions(-)

diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
index 43962880cd96..440b42852bbf 100644
--- a/gdb/break-catch-load.c
+++ b/gdb/break-catch-load.c
@@ -91,20 +91,20 @@ solib_catchpoint::breakpoint_hit (const struct bp_location *bl,
   if (ws.kind () == TARGET_WAITKIND_LOADED)
     return 1;
 
-  for (breakpoint *other : all_breakpoints ())
+  for (breakpoint &other : all_breakpoints ())
     {
-      if (other == bl->owner)
+      if (&other == bl->owner)
 	continue;
 
-      if (other->type != bp_shlib_event)
+      if (other.type != bp_shlib_event)
 	continue;
 
-      if (pspace != NULL && other->pspace != pspace)
+      if (pspace != NULL && other.pspace != pspace)
 	continue;
 
-      for (bp_location &other_bl : other->locations ())
+      for (bp_location &other_bl : other.locations ())
 	{
-	  if (other->breakpoint_hit (&other_bl, aspace, bp_addr, ws))
+	  if (other.breakpoint_hit (&other_bl, aspace, bp_addr, ws))
 	    return 1;
 	}
     }
diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
index 18e2b20c1385..9abf8183984f 100644
--- a/gdb/break-catch-syscall.c
+++ b/gdb/break-catch-syscall.c
@@ -501,8 +501,8 @@ catching_syscall_number_1 (struct breakpoint *b, int syscall_number)
 bool
 catching_syscall_number (int syscall_number)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (catching_syscall_number_1 (b, syscall_number))
+  for (breakpoint &b : all_breakpoints ())
+    if (catching_syscall_number_1 (&b, syscall_number))
       return true;
 
   return false;
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 5f47dc777438..4de3716a0987 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -621,9 +621,7 @@ static intrusive_list<breakpoint> breakpoint_chain;
 breakpoint_range
 all_breakpoints ()
 {
-  return breakpoint_range
-    (breakpoint_pointer_iterator (breakpoint_chain.begin ()),
-     breakpoint_pointer_iterator (breakpoint_chain.end ()));
+  return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
 }
 
 /* See breakpoint.h.  */
@@ -639,9 +637,8 @@ all_breakpoints_safe ()
 tracepoint_range
 all_tracepoints ()
 {
-  return tracepoint_range
-    (tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.begin ())),
-     tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.end ())));
+  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.  */
@@ -796,8 +793,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
@@ -807,9 +804,9 @@ 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;
 }
@@ -820,9 +817,9 @@ get_breakpoint (int num)
 static bool
 has_multiple_locations (int num)
 {
-  for (breakpoint *b : all_breakpoints ())
-    if (b->number == num)
-      return b->has_multiple_locations ();
+  for (breakpoint &b : all_breakpoints ())
+    if (b.number == num)
+      return b.has_multiple_locations ();
 
   return false;
 }
@@ -1104,14 +1101,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)
 	  {
@@ -1119,9 +1116,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;
@@ -1196,11 +1193,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));
@@ -1417,13 +1414,13 @@ static_tracepoints_here (CORE_ADDR addr)
 {
   std::vector<breakpoint *> found;
 
-  for (breakpoint *b : all_breakpoints ())
-    if (b->type == bp_static_tracepoint
-	|| b->type == bp_static_marker_tracepoint)
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_static_tracepoint
+	|| b.type == bp_static_marker_tracepoint)
       {
-	for (bp_location &loc : b->locations ())
+	for (bp_location &loc : b.locations ())
 	  if (loc.address == addr)
-	    found.push_back (b);
+	    found.push_back (&b);
       }
 
   return found;
@@ -3030,9 +3027,9 @@ 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.  */
@@ -3055,12 +3052,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 = static_cast<watchpoint &> (bpt);
 
-	update_watchpoint (w, false /* don't reparse.  */);
+	update_watchpoint (&w, false /* don't reparse.  */);
       }
 
   /* Updating watchpoints creates new locations, so update the global
@@ -3179,20 +3176,20 @@ 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 ())
     {
       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 ())
+      for (bp_location &loc : bpt.locations ())
 	if (!loc.inserted && should_be_inserted (&loc))
 	  {
 	    some_failed = true;
@@ -3201,14 +3198,14 @@ insert_breakpoint_locations (void)
 
       if (some_failed)
 	{
-	  for (bp_location &loc : bpt->locations ())
+	  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;
 	}
     }
@@ -3249,14 +3246,14 @@ 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))
 	{
 	  gdb_printf (_("\
 Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
-		      b->number, print_thread_id (tp));
-	  delete_breakpoint (b);
+		      b.number, print_thread_id (tp));
+	  delete_breakpoint (&b);
        }
     }
 }
@@ -3765,60 +3762,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
@@ -3853,7 +3850,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;
 	}
@@ -3861,9 +3858,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_location_spec_empty_p (b))
+      if (breakpoint_location_spec_empty_p (&b))
 	{
-	  delete_breakpoint (b);
+	  delete_breakpoint (&b);
 	  continue;
 	}
     }
@@ -4100,12 +4097,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->has_locations () && b->first_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:
@@ -4142,7 +4139,7 @@ breakpoint_init_inferior (enum inf_context context)
 
 	  /* Also remove single-step breakpoints.  */
 
-	  delete_breakpoint (b);
+	  delete_breakpoint (&b);
 	  break;
 
 	case bp_watchpoint:
@@ -4150,11 +4147,11 @@ breakpoint_init_inferior (enum inf_context context)
 	case bp_read_watchpoint:
 	case bp_access_watchpoint:
 	  {
-	    struct watchpoint *w = (struct watchpoint *) b;
+	    watchpoint &w = 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
@@ -4162,14 +4159,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->clear_locations ();
+		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;
 		  }
 	      }
 	  }
@@ -4350,16 +4347,16 @@ 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 ())
+      for (bp_location &loc : bpt.locations ())
 	if (loc.pspace->aspace == aspace && loc.inserted)
 	  {
 	    CORE_ADDR l, h;
@@ -5009,12 +5006,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 = static_cast<watchpoint &> (b);
 
-	    w->watchpoint_triggered = watch_triggered_no;
+	    w.watchpoint_triggered = watch_triggered_no;
 	  }
 
       return 0;
@@ -5024,12 +5021,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 = static_cast<watchpoint &> (b);
 
-	    w->watchpoint_triggered = watch_triggered_unknown;
+	    w.watchpoint_triggered = watch_triggered_unknown;
 	  }
 
       return 1;
@@ -5039,22 +5036,22 @@ 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 = 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;
 		  }
 	      }
@@ -5063,7 +5060,7 @@ watchpoints_triggered (const target_waitstatus &ws)
 		       (current_inferior ()->top_target (), addr, loc.address,
 			loc.length))
 	      {
-		w->watchpoint_triggered = watch_triggered_yes;
+		w.watchpoint_triggered = watch_triggered_yes;
 		break;
 	      }
 	  }
@@ -5363,14 +5360,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 =
+			      static_cast<watchpoint &> (other_b);
 
-			    if (other_w->watchpoint_triggered
+			    if (other_w.watchpoint_triggered
 				== watch_triggered_yes)
 			      {
 				other_write_watchpoint = 1;
@@ -5612,19 +5609,19 @@ 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->first_loc ())
+	  if (b.type == bp_hardware_watchpoint && &bl != &b.first_loc ())
 	    break;
 
 	  if (!bl.enabled || bl.disabled_by_cond || bl.shlib_disabled)
@@ -5649,9 +5646,9 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
 	     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;
 	    }
@@ -6044,10 +6041,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->has_locations ())
+  for (breakpoint &b : all_breakpoints ())
+    if (breakpoint_enabled (&b)
+	&& b.type == bp_watchpoint
+	&& b.has_locations ())
       return true;
 
   return false;
@@ -6832,31 +6829,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;
 
@@ -6900,11 +6897,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
@@ -6914,21 +6911,21 @@ 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 ())
+	    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;
 	  }
@@ -7041,9 +7038,9 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
 {
   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)
     {
@@ -7051,23 +7048,24 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
 	gdb_printf (_("Note: breakpoint "));
       else /* if (others == ???) */
 	gdb_printf (_("Note: breakpoints "));
-      for (breakpoint *b : all_breakpoints ())
-	if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
+      for (breakpoint &b : all_breakpoints ())
+	if (user_breakpoint_p (&b)
+	    && breakpoint_has_pc (&b, pspace, pc, section))
 	  {
 	    others--;
-	    gdb_printf ("%d", b->number);
-	    if (b->thread == -1 && thread != -1)
+	    gdb_printf ("%d", b.number);
+	    if (b.thread == -1 && thread != -1)
 	      gdb_printf (" (all threads)");
-	    else if (b->thread != -1)
+	    else if (b.thread != -1)
 	      {
-		struct thread_info *thr = find_thread_global_id (b->thread);
+		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);
+	    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)
+			((b.enable_state == bp_disabled
+			  || b.enable_state == bp_call_disabled)
 			 ? " (disabled)"
 			 : ""),
 			(others > 1) ? "," 
@@ -7510,15 +7508,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;
+	bptype type = b.type == bp_longjmp_master ? bp_longjmp : bp_exception;
 	/* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
 	   after their removal.  */
-	momentary_breakpoint_from_master (b, type, 1, thread);
+	momentary_breakpoint_from_master (&b, type, 1, thread);
       }
 
   tp->initiating_frame = frame;
@@ -7528,22 +7526,22 @@ 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)
+	  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)
+	  b.disposition = disp_del_at_next_stop;
       }
 }
 
@@ -7557,12 +7555,12 @@ 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)
       {
 	int thread = inferior_thread ()->global_num;
 	breakpoint *new_b
-	  = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
+	  = momentary_breakpoint_from_master (&b, bp_longjmp_call_dummy,
 					      1, thread);
 
 	/* Link NEW_B into the chain of RETVAL breakpoints.  */
@@ -7596,15 +7594,15 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
      Save all breakpoints to delete in that set and delete them at the end.  */
   std::unordered_set<breakpoint *> to_delete;
 
-  for (struct breakpoint *b : all_breakpoints ())
+  for (struct breakpoint &b : all_breakpoints ())
     {
-      if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
+      if (b.type == bp_longjmp_call_dummy && b.thread == tp->global_num)
 	{
-	  struct breakpoint *dummy_b = b->related_breakpoint;
+	  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)
+	  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
@@ -7653,12 +7651,12 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
 
 	  dummy_frame_discard (dummy_b->frame_id, tp);
 
-	  for (breakpoint *related_breakpoint = b->related_breakpoint;
-	       related_breakpoint != b;
+	  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.related_breakpoint);
 
-	  to_delete.insert (b);
+	  to_delete.insert (&b);
 	}
     }
 
@@ -7669,10 +7667,10 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
 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;
       }
@@ -7681,10 +7679,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;
       }
@@ -7695,11 +7693,11 @@ 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, 1,
+	momentary_breakpoint_from_master (&b, bp_std_terminate, 1,
 					  inferior_thread ()->global_num);
       }
 }
@@ -7708,9 +7706,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 *
@@ -7748,19 +7746,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->first_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->first_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.  */
@@ -7768,10 +7766,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->first_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 /
@@ -7913,14 +7911,14 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
       || (objfile->flags & OBJF_USERLOADED) == 0)
     return;
 
-  for (breakpoint *b : all_breakpoints ())
+  for (breakpoint &b : all_breakpoints ())
     {
       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;
 
@@ -7954,7 +7952,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
 	}
 
       if (bp_modified)
-	gdb::observers::breakpoint_modified.notify (b);
+	gdb::observers::breakpoint_modified.notify (&b);
     }
 }
 
@@ -8007,13 +8005,13 @@ 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->resources_needed (&bl);
+	  i += b.resources_needed (&bl);
 	}
 
   return i;
@@ -8052,16 +8050,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;
     }
 
@@ -8071,10 +8069,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);
       }
 }
@@ -8082,10 +8080,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);
       }
 }
@@ -8421,9 +8419,9 @@ 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);
+  for (breakpoint &b : all_breakpoints ())
+    if (b.type == bp_dprintf)
+	update_dprintf_command_list (&b);
 }
 
 code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
@@ -10824,14 +10822,14 @@ 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)
-	      && user_breakpoint_p (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.  */
@@ -10861,7 +10859,7 @@ clear_command (const char *arg, int from_tty)
 	    }
 
 	  if (match)
-	    found.push_back (b);
+	    found.push_back (&b);
 	}
     }
 
@@ -10920,9 +10918,9 @@ 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
@@ -11013,12 +11011,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;
       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;
@@ -11034,7 +11031,7 @@ 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
@@ -11049,10 +11046,11 @@ download_tracepoint_locations (void)
 	  bl.inserted = 1;
 	  bp_location_downloaded = true;
 	}
-      t = (struct tracepoint *) b;
-      t->number_on_target = b->number;
+
+      tracepoint &t = static_cast<tracepoint &> (b);
+      t.number_on_target = b.number;
       if (bp_location_downloaded)
-	gdb::observers::breakpoint_modified.notify (b);
+	gdb::observers::breakpoint_modified.notify (&b);
     }
 }
 
@@ -11159,8 +11157,8 @@ 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 ())
+  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
@@ -12458,8 +12456,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;
@@ -12468,9 +12466,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
@@ -12991,17 +12989,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);
 	  }
       }
 
@@ -13046,10 +13044,10 @@ 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)
 	      gdb_printf (_("Ignore count ignored for tracepoint %d."),
@@ -13057,7 +13055,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
 	    return;
 	  }
 
-	b->ignore_count = count;
+	b.ignore_count = count;
 	if (from_tty)
 	  {
 	    if (count == 0)
@@ -13072,7 +13070,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
 			    "crossings of breakpoint %d."),
 			  count, bptnum);
 	  }
-	gdb::observers::breakpoint_modified.notify (b);
+	gdb::observers::breakpoint_modified.notify (&b);
 	return;
       }
 
@@ -13122,11 +13120,11 @@ 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)
@@ -13441,13 +13439,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
@@ -13632,21 +13630,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 = static_cast<watchpoint &> (bp);
 
-	if (wp->val_valid && wp->val != nullptr)
+	if (wp.val_valid && wp.val != nullptr)
 	  {
-	    for (bp_location &loc : bp->locations ())
+	    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;
 		}
 	  }
       }
@@ -13734,10 +13732,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;
@@ -13994,8 +13992,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;
@@ -14005,9 +14003,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
@@ -14039,7 +14037,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)
@@ -14055,15 +14052,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 = 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);
     }
@@ -14072,7 +14069,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);
 	}
@@ -14082,9 +14079,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 static_cast<tracepoint *> (&t);
 
   return NULL;
 }
@@ -14096,12 +14093,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 = static_cast<tracepoint &> (b);
 
-      if (t->number_on_target == num)
-	return t;
+      if (t.number_on_target == num)
+	return &t;
     }
 
   return NULL;
@@ -14139,9 +14136,9 @@ get_tracepoint_by_number (const char **arg,
       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 static_cast<tracepoint *> (&t);
 
   gdb_printf ("No tracepoint number %d.\n", tpnum);
   return NULL;
@@ -14178,19 +14175,19 @@ save_breakpoints (const char *filename, int from_tty,
     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 = true;
 
-      if (is_tracepoint (tp))
+      if (is_tracepoint (&tp))
 	{
 	  extra_trace_bits = 1;
 
@@ -14216,49 +14213,49 @@ 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->print_recreate (&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");
 
 	  ui_out_redirect_pop redir (current_uiout, &fp);
-	  print_command_lines (current_uiout, tp->commands.get (), 2);
+	  print_command_lines (current_uiout, tp.commands.get (), 2);
 
 	  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->has_multiple_locations ())
+      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)
 		fp.printf ("disable $bpnum.%d\n", n);
@@ -14394,12 +14391,12 @@ 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))
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index a03b57734b9d..c0d73d374cb0 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -1895,11 +1895,9 @@ using breakpoint_list = intrusive_list<breakpoint>;
 
 using breakpoint_iterator = breakpoint_list::iterator;
 
-using breakpoint_pointer_iterator = reference_to_pointer_iterator<breakpoint_iterator>;
-
 /* Breakpoint linked list range.  */
 
-using breakpoint_range = iterator_range<breakpoint_pointer_iterator>;
+using breakpoint_range = iterator_range<breakpoint_iterator>;
 
 /* Return a range to iterate over all breakpoints.  */
 
@@ -1919,14 +1917,14 @@ breakpoint_safe_range all_breakpoints_safe ();
 
 struct tracepoint_filter
 {
-  bool operator() (breakpoint *b)
-  { return is_tracepoint (b); }
+  bool operator() (breakpoint &b)
+  { return is_tracepoint (&b); }
 };
 
 /* Breakpoint linked list iterator, filtering to only keep tracepoints.  */
 
 using tracepoint_iterator
-  = filtered_iterator<breakpoint_pointer_iterator, tracepoint_filter>;
+  = filtered_iterator<breakpoint_iterator, tracepoint_filter>;
 
 /* Breakpoint linked list range, filtering to only keep tracepoints.  */
 
diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
index 961b3ac7a25f..520450125a84 100644
--- a/gdb/dummy-frame.c
+++ b/gdb/dummy-frame.c
@@ -166,8 +166,8 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr)
 
   restore_infcall_suspend_state (dummy->caller_state);
 
-  for (breakpoint *bp : all_breakpoints_safe ())
-    if (pop_dummy_frame_bpt (bp, dummy))
+  for (breakpoint &bp : all_breakpoints_safe ())
+    if (pop_dummy_frame_bpt (&bp, dummy))
       break;
 
   /* restore_infcall_control_state frees inf_state,
diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
index 2931df265d74..6c6dacb38836 100644
--- a/gdb/guile/scm-breakpoint.c
+++ b/gdb/guile/scm-breakpoint.c
@@ -569,8 +569,8 @@ gdbscm_breakpoints (void)
 {
   SCM list = SCM_EOL;
 
-  for (breakpoint *bp : all_breakpoints ())
-    bpscm_build_bp_list (bp, &list);
+  for (breakpoint &bp : all_breakpoints ())
+    bpscm_build_bp_list (&bp, &list);
 
   return scm_reverse_x (list, SCM_EOL);
 }
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 8a306c6b3318..d11fc64df204 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -1035,8 +1035,8 @@ gdbpy_breakpoints (PyObject *self, PyObject *args)
 
   /* If build_bp_list returns false, it signals an error condition.  In that
      case abandon building the list and return nullptr.  */
-  for (breakpoint *bp : all_breakpoints ())
-    if (!build_bp_list (bp, list.get ()))
+  for (breakpoint &bp : all_breakpoints ())
+    if (!build_bp_list (&bp, list.get ()))
       return nullptr;
 
   return PyList_AsTuple (list.get ());
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index bb4591e3a6ba..b71e5fafc461 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -416,9 +416,9 @@ bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
 {
   gdbpy_enter enter_py;
 
-  for (breakpoint *bp : all_breakpoints_safe ())
+  for (breakpoint &bp : all_breakpoints_safe ())
     bpfinishpy_detect_out_scope_cb
-      (bp, bs == NULL ? NULL : bs->breakpoint_at, true);
+      (&bp, bs == NULL ? NULL : bs->breakpoint_at, true);
 }
 
 /* Attached to `exit' notifications, triggers all the necessary out of
@@ -429,8 +429,8 @@ bpfinishpy_handle_exit (struct inferior *inf)
 {
   gdbpy_enter enter_py (target_gdbarch ());
 
-  for (breakpoint *bp : all_breakpoints_safe ())
-    bpfinishpy_detect_out_scope_cb (bp, nullptr, true);
+  for (breakpoint &bp : all_breakpoints_safe ())
+    bpfinishpy_detect_out_scope_cb (&bp, nullptr, true);
 }
 
 /* Initialize the Python finish breakpoint code.  */
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 46f09a7e63ce..59bb086821e5 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2151,8 +2151,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
 static void
 svr4_update_solib_event_breakpoints (void)
 {
-  for (breakpoint *bp : all_breakpoints_safe ())
-    svr4_update_solib_event_breakpoint (bp);
+  for (breakpoint &bp : all_breakpoints_safe ())
+    svr4_update_solib_event_breakpoint (&bp);
 }
 
 /* Create and register solib event breakpoints.  PROBES is an array
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index fa65e0493720..36cbd1f5bb64 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -1520,16 +1520,16 @@ process_tracepoint_on_disconnect (void)
 
   /* Check whether we still have pending tracepoint.  If we have, warn the
      user that pending tracepoint will no longer work.  */
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      if (!b->has_locations ())
+      if (!b.has_locations ())
 	{
 	  has_pending_p = 1;
 	  break;
 	}
       else
 	{
-	  for (bp_location &loc1 : b->locations ())
+	  for (bp_location &loc1 : b.locations ())
 	    {
 	      if (loc1.shlib_disabled)
 		{
@@ -1571,18 +1571,18 @@ start_tracing (const char *notes)
   if (tracepoint_range.begin () == tracepoint_range.end ())
     error (_("No tracepoints defined, not starting trace"));
 
-  for (breakpoint *b : tracepoint_range)
+  for (breakpoint &b : tracepoint_range)
     {
-      if (b->enable_state == bp_enabled)
+      if (b.enable_state == bp_enabled)
 	any_enabled = 1;
 
-      if ((b->type == bp_fast_tracepoint
+      if ((b.type == bp_fast_tracepoint
 	   ? may_insert_fast_tracepoints
 	   : may_insert_tracepoints))
 	++num_to_download;
       else
 	warning (_("May not insert %stracepoints, skipping tracepoint %d"),
-		 (b->type == bp_fast_tracepoint ? "fast " : ""), b->number);
+		 (b.type == bp_fast_tracepoint ? "fast " : ""), b.number);
     }
 
   if (!any_enabled)
@@ -1602,23 +1602,23 @@ start_tracing (const char *notes)
 
   target_trace_init ();
 
-  for (breakpoint *b : tracepoint_range)
+  for (breakpoint &b : tracepoint_range)
     {
-      struct tracepoint *t = (struct tracepoint *) b;
+      tracepoint &t = static_cast<tracepoint &> (b);
       int bp_location_downloaded = 0;
 
       /* Clear `inserted' flag.  */
-      for (bp_location &loc : b->locations ())
+      for (bp_location &loc : b.locations ())
 	loc.inserted = 0;
 
-      if ((b->type == bp_fast_tracepoint
+      if ((b.type == bp_fast_tracepoint
 	   ? !may_insert_fast_tracepoints
 	   : !may_insert_tracepoints))
 	continue;
 
-      t->number_on_target = 0;
+      t.number_on_target = 0;
 
-      for (bp_location &loc : b->locations ())
+      for (bp_location &loc : b.locations ())
 	{
 	  /* Since tracepoint locations are never duplicated, `inserted'
 	     flag should be zero.  */
@@ -1630,14 +1630,14 @@ start_tracing (const char *notes)
 	  bp_location_downloaded = 1;
 	}
 
-      t->number_on_target = b->number;
+      t.number_on_target = b.number;
 
-      for (bp_location &loc : b->locations ())
+      for (bp_location &loc : b.locations ())
 	if (loc.probe.prob != NULL)
 	  loc.probe.prob->set_semaphore (loc.probe.objfile, loc.gdbarch);
 
       if (bp_location_downloaded)
-	gdb::observers::breakpoint_modified.notify (b);
+	gdb::observers::breakpoint_modified.notify (&b);
     }
 
   /* Send down all the trace state variables too.  */
@@ -1709,14 +1709,14 @@ stop_tracing (const char *note)
 
   target_trace_stop ();
 
-  for (breakpoint *t : all_tracepoints ())
+  for (breakpoint &t : all_tracepoints ())
     {
-      if ((t->type == bp_fast_tracepoint
+      if ((t.type == bp_fast_tracepoint
 	   ? !may_insert_fast_tracepoints
 	   : !may_insert_tracepoints))
 	continue;
 
-      for (bp_location &loc : t->locations ())
+      for (bp_location &loc : t.locations ())
 	{
 	  /* GDB can be totally absent in some disconnected trace scenarios,
 	     but we don't really care if this semaphore goes out of sync.
@@ -1887,8 +1887,8 @@ tstatus_command (const char *args, int from_tty)
 		(long int) (ts->stop_time % 1000000));
 
   /* Now report any per-tracepoint status available.  */
-  for (breakpoint *t : all_tracepoints ())
-    target_get_tracepoint_status (t, NULL);
+  for (breakpoint &t : all_tracepoints ())
+    target_get_tracepoint_status (&t, NULL);
 }
 
 /* Report the trace status to uiout, in a way suitable for MI, and not
@@ -3042,20 +3042,20 @@ cond_string_is_same (char *str1, char *str2)
 static struct bp_location *
 find_matching_tracepoint_location (struct uploaded_tp *utp)
 {
-  for (breakpoint *b : all_tracepoints ())
+  for (breakpoint &b : all_tracepoints ())
     {
-      struct tracepoint *t = (struct tracepoint *) b;
+      tracepoint &t = static_cast<tracepoint &> (b);
 
-      if (b->type == utp->type
-	  && t->step_count == utp->step
-	  && t->pass_count == utp->pass
-	  && cond_string_is_same (t->cond_string.get (),
+      if (b.type == utp->type
+	  && t.step_count == utp->step
+	  && t.pass_count == utp->pass
+	  && cond_string_is_same (t.cond_string.get (),
 				  utp->cond_string.get ())
 	  /* FIXME also test actions.  */
 	  )
 	{
 	  /* Scan the locations for an address match.  */
-	  for (bp_location &loc : b->locations ())
+	  for (bp_location &loc : b.locations ())
 	    if (loc.address == utp->addr)
 	      return &loc;
 	}
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 9e4760618187..a3714fce46fe 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -625,24 +625,24 @@ tui_source_window_base::update_breakpoint_info
 	 do with it.  Identify enable/disabled breakpoints as well as
 	 those that we already hit.  */
       tui_bp_flags mode = 0;
-      for (breakpoint *bp : all_breakpoints ())
+      for (breakpoint &bp : all_breakpoints ())
 	{
-	  if (bp == being_deleted)
+	  if (&bp == being_deleted)
 	    continue;
 
-	  for (bp_location &loc : bp->locations ())
+	  for (bp_location &loc : bp.locations ())
 	    {
 	      if (location_matches_p (&loc, i))
 		{
-		  if (bp->enable_state == bp_disabled)
+		  if (bp.enable_state == bp_disabled)
 		    mode |= TUI_BP_DISABLED;
 		  else
 		    mode |= TUI_BP_ENABLED;
-		  if (bp->hit_count)
+		  if (bp.hit_count)
 		    mode |= TUI_BP_HIT;
-		  if (bp->first_loc ().cond)
+		  if (bp.first_loc ().cond)
 		    mode |= TUI_BP_CONDITIONAL;
-		  if (bp->type == bp_hardware_breakpoint)
+		  if (bp.type == bp_hardware_breakpoint)
 		    mode |= TUI_BP_HARDWARE;
 		}
 	    }
-- 
2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location
  2023-05-11 14:48 ` [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location Simon Marchi
@ 2023-05-15  9:12   ` Alexandra Petlanova Hajkova
  0 siblings, 0 replies; 28+ messages in thread
From: Alexandra Petlanova Hajkova @ 2023-05-15  9:12 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 955 bytes --]

On Thu, May 11, 2023 at 4:48 PM Simon Marchi via Gdb-patches <
gdb-patches@sourceware.org> wrote:

> I noticed some methods of syscall_catchpoint doing this:
>
>   struct gdbarch *gdbarch = loc->owner->gdbarch;
>
> `loc` is the list of locations of this catchpoint.  Logically, the owner
> the locations are this catchpoint.  So this just ends up getting
> this->gdbarch.  Remove the unnecessary indirection through the loc.
>
> syscall_catchpoint::print_recreate does something slightly different,
> getting its arch from the loc:
>
>   struct gdbarch *gdbarch = loc->gdbarch;
>
> I suppose it's always going to be the same arch, so get it from the
> catchpoint there too.
>
> Change-Id: I6f6a6f8e0cd7cfb754cecfb6249e71ec12ba4855
> ---
>  gdb/break-catch-syscall.c | 6 ------
>  1 file changed, 6 deletions(-)
>
>
> This change seems to be reasonable and I can confirm it causes no
regression on aarch64 with Fedora-Rawhide.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/12] gdb: make some breakpoint methods use `this`
  2023-05-11 14:48 ` [PATCH 02/12] gdb: make some breakpoint methods use `this` Simon Marchi
@ 2023-05-15 13:12   ` Alexandra Petlanova Hajkova
  2023-05-15 18:25     ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Alexandra Petlanova Hajkova @ 2023-05-15 13:12 UTC (permalink / raw)
  To: Simon Marchi; +Cc: gdb-patches

[-- Attachment #1: Type: text/plain, Size: 640 bytes --]

On Thu, May 11, 2023 at 4:49 PM Simon Marchi via Gdb-patches <
gdb-patches@sourceware.org> wrote:

> Some implementations of breakpoint::check_status and
> breakpoint::print_it do this:
>
>     struct breakpoint *b = bs->breakpoint_at;
>
> bs->breakpoint_at is always the same as `this` (we can get convinced by
> looking at the call sites of check_status and print_it), so it would
> just be clearer to access fields through `this` instead.
>
> Change-Id: Ic542a64fcd88e31ae2aad6feff1da278c7086891
>
> I think this chage simplifies the code and I can confirm this change
causes no regressions  on aarch64 Fedora_Rawhide.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 02/12] gdb: make some breakpoint methods use `this`
  2023-05-15 13:12   ` Alexandra Petlanova Hajkova
@ 2023-05-15 18:25     ` Simon Marchi
  0 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-15 18:25 UTC (permalink / raw)
  To: Alexandra Petlanova Hajkova; +Cc: gdb-patches

On 5/15/23 09:12, Alexandra Petlanova Hajkova wrote:
> 
> 
> On Thu, May 11, 2023 at 4:49 PM Simon Marchi via Gdb-patches <gdb-patches@sourceware.org <mailto:gdb-patches@sourceware.org>> wrote:
> 
>     Some implementations of breakpoint::check_status and
>     breakpoint::print_it do this:
> 
>         struct breakpoint *b = bs->breakpoint_at;
> 
>     bs->breakpoint_at is always the same as `this` (we can get convinced by
>     looking at the call sites of check_status and print_it), so it would
>     just be clearer to access fields through `this` instead.
> 
>     Change-Id: Ic542a64fcd88e31ae2aad6feff1da278c7086891
> 
> I think this chage simplifies the code and I can confirm this change causes no regressions  on aarch64 Fedora_Rawhide.

Thanks, I'll add your Reviewed-By for patches 1 and 2.

Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 05/12] gdb: add breakpoint::first_loc methods
  2023-05-11 14:48 ` [PATCH 05/12] gdb: add breakpoint::first_loc methods Simon Marchi
@ 2023-05-18 12:50   ` Andrew Burgess
  2023-05-18 17:55     ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Burgess @ 2023-05-18 12:50 UTC (permalink / raw)
  To: Simon Marchi via Gdb-patches, gdb-patches; +Cc: Simon Marchi

Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:

> Add convenience first_loc methods to struct breakpoint (const and
> non-const overloads).  A subsequent patch changes the list of locations
> to be an intrusive_list and makes the actual list private, so these
> spots would need to become something ugly like:
>
>   -b->loc
>   +*b->locations ().begin ()

It took me longer than I'd like to admit to realise the leading -/+ here
were indicating that this was an extract from a diff.  Maybe there's
some way to make it clearer?  Or just drop the first line, I think the
second line is clear enough (given the description before).

>
> That would make the code much heavier and not readable.  There is a
> surprisingly big number of places that access the first location of
> breakpoints.  Whether this is correct, or these spots fail to consider
> the possibility of multi-location breakpoints, I don't know.  But
> anyhow, I think that using this instead:
>
>  b->first_loc ()
>
> conveys the intention better than the other two forms.
>
> Change-Id: Ibbefe3e4ca6cdfe570351fe7e2725f2ce11d1e95
> ---
>  gdb/breakpoint.c        | 112 ++++++++++++++++++++--------------------
>  gdb/breakpoint.h        |  14 +++++
>  gdb/elfread.c           |   4 +-
>  gdb/infrun.c            |  11 ++--
>  gdb/tracectf.c          |   2 +-
>  gdb/tracefile-tfile.c   |   2 +-
>  gdb/tracefile.c         |   2 +-
>  gdb/tracepoint.c        |   2 +-
>  gdb/tui/tui-winsource.c |   2 +-
>  9 files changed, 82 insertions(+), 69 deletions(-)
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index fefe18644cf9..e9b6574bba77 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -4106,7 +4106,7 @@ breakpoint_init_inferior (enum inf_context context)
>  
>    for (breakpoint *b : all_breakpoints_safe ())
>      {
> -      if (b->has_locations () && b->loc->pspace != pspace)
> +      if (b->has_locations () && b->first_loc ().pspace != pspace)
>  	continue;
>  
>        switch (b->type)
> @@ -5633,7 +5633,7 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
>  	     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)
> @@ -6160,8 +6160,7 @@ bp_location_condition_evaluator (const struct bp_location *bl)
>  /* Print the LOC location out of the list of B->LOC locations.  */
>  
>  static void
> -print_breakpoint_location (const breakpoint *b,
> -			   struct bp_location *loc)
> +print_breakpoint_location (const breakpoint *b, const bp_location *loc)
>  {
>    struct ui_out *uiout = current_uiout;
>  
> @@ -6361,11 +6360,11 @@ print_one_breakpoint_location (struct breakpoint *b,
>    if (loc == NULL 
>        && (b->has_locations ()
>  	  && (b->has_multiple_locations ()
> -	      || !b->loc->enabled || b->loc->disabled_by_cond)))
> +	      || !b->first_loc ().enabled || b->first_loc ().disabled_by_cond)))
>      header_of_multiple = true;
>  
> -  if (loc == NULL)
> -    loc = b->loc;
> +  if (loc == NULL && b->has_locations ())
> +    loc = &b->first_loc ();
>  
>    annotate_record ();
>  
> @@ -6465,7 +6464,7 @@ print_one_breakpoint_location (struct breakpoint *b,
>  	  if (!header_of_multiple)
>  	    print_breakpoint_location (b, loc);
>  	  if (b->has_locations ())
> -	    *last_loc = b->loc;
> +	    *last_loc = &b->first_loc ();
>  	}
>      }
>  
> @@ -6745,8 +6744,8 @@ print_one_breakpoint (breakpoint *b, const bp_location **last_loc, int allflag)
>  	  && (allflag
>  	      || (b->has_locations ()
>  		  && (b->has_multiple_locations ()
> -		      || !b->loc->enabled
> -		      || b->loc->disabled_by_cond))))
> +		      || !b->first_loc ().enabled
> +		      || b->first_loc ().disabled_by_cond))))
>  	{
>  	  gdb::optional<ui_out_emit_list> locations_list;
>  
> @@ -7743,7 +7742,7 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
>  
>    b->enable_state = bp_enabled;
>    /* locspec has to be used or breakpoint_re_set will delete me.  */
> -  b->locspec = new_address_location_spec (b->loc->address, NULL, 0);
> +  b->locspec = new_address_location_spec (b->first_loc ().address, NULL, 0);
>  
>    update_global_location_list_nothrow (UGLL_MAY_INSERT);
>  
> @@ -7771,7 +7770,7 @@ remove_jit_event_breakpoints (void)
>  {
>    for (breakpoint *b : all_breakpoints_safe ())
>      if (b->type == bp_jit_event
> -	&& b->loc->pspace == current_program_space)
> +	&& b->first_loc ().pspace == current_program_space)
>        delete_breakpoint (b);
>  }
>  
> @@ -7780,7 +7779,7 @@ remove_solib_event_breakpoints (void)
>  {
>    for (breakpoint *b : all_breakpoints_safe ())
>      if (b->type == bp_shlib_event
> -	&& b->loc->pspace == current_program_space)
> +	&& b->first_loc ().pspace == current_program_space)
>        delete_breakpoint (b);
>  }
>  
> @@ -7791,7 +7790,7 @@ 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->first_loc ().pspace == current_program_space)
>        b->disposition = disp_del_at_next_stop;
>  }
>  
> @@ -7826,7 +7825,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;
> @@ -8178,17 +8177,18 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
>    std::unique_ptr<breakpoint> copy
>      (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
>  			       orig->frame_id, thread));
> +  bp_location &orig_loc = orig->first_loc ();

Maybe 'const bp_location &' ?

Otherwise, looks good.

Thanks,
Andrew

>    copy->loc = copy->allocate_location ();
>    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->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));
> @@ -8575,7 +8575,7 @@ code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
>    if (locspec_ != nullptr)
>      locspec = std::move (locspec_);
>    else
> -    locspec = new_address_location_spec (this->loc->address, NULL, 0);
> +    locspec = new_address_location_spec (this->first_loc ().address, NULL, 0);
>    filter = std::move (filter_);
>  }
>  
> @@ -9411,7 +9411,6 @@ ranged_breakpoint::print_it (const bpstat *bs) const
>  bool
>  ranged_breakpoint::print_one (const bp_location **last_loc) const
>  {
> -  struct bp_location *bl = loc;
>    struct value_print_options opts;
>    struct ui_out *uiout = current_uiout;
>  
> @@ -9425,8 +9424,8 @@ ranged_breakpoint::print_one (const bp_location **last_loc) const
>         by ranged_breakpoint::print_one_detail.  */
>      uiout->field_skip ("addr");
>    annotate_field (5);
> -  print_breakpoint_location (this, bl);
> -  *last_loc = bl;
> +  print_breakpoint_location (this, &this->first_loc ());
> +  *last_loc = &this->first_loc ();
>  
>    return true;
>  }
> @@ -9437,18 +9436,16 @@ void
>  ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
>  {
>    CORE_ADDR address_start, address_end;
> -  struct bp_location *bl = 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");
>  }
> @@ -9458,15 +9455,14 @@ ranged_breakpoint::print_one_detail (struct ui_out *uiout) const
>  void
>  ranged_breakpoint::print_mention () const
>  {
> -  struct bp_location *bl = loc;
> +  const bp_location &bl = this->first_loc ();
>    struct ui_out *uiout = current_uiout;
>  
> -  gdb_assert (bl);
>    gdb_assert (type == bp_hardware_breakpoint);
>  
>    uiout->message (_("Hardware assisted ranged breakpoint %d from %s to %s."),
> -		  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" method for ranged breakpoints.  */
> @@ -9992,7 +9988,7 @@ masked_watchpoint::print_one_detail (struct ui_out *uiout) const
>    gdb_assert (this->has_single_location ());
>  
>    uiout->text ("\tmask ");
> -  uiout->field_core_addr ("mask", loc->gdbarch, hw_wp_mask);
> +  uiout->field_core_addr ("mask", this->first_loc ().gdbarch, hw_wp_mask);
>    uiout->text ("\n");
>  }
>  
> @@ -10302,11 +10298,11 @@ 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,
> +	  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);
>  	}
> @@ -11599,23 +11595,24 @@ code_breakpoint::say_where () const
>      }
>    else
>      {
> -      if (opts.addressprint || 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 (loc->gdbarch,
> -					     loc->address)));
> -      if (loc->symtab != NULL)
> +				   paddress (bl.gdbarch,
> +					     bl.address)));
> +      if (bl.symtab != NULL)
>  	{
>  	  /* If there is a single location, we can print the location
>  	     more nicely.  */
>  	  if (!this->has_multiple_locations ())
>  	    {
>  	      const char *filename
> -		= symtab_to_filename_for_display (loc->symtab);
> +		= symtab_to_filename_for_display (bl.symtab);
>  	      gdb_printf (": file %ps, line %d.",
>  			  styled_string (file_name_style.style (),
>  					 filename),
> -			  loc->line_number);
> +			  bl.line_number);
>  	    }
>  	  else
>  	    /* This is not ideal, but each location may have a
> @@ -12629,14 +12626,14 @@ 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->loc->line_number;
> +	  els->line_offset.offset = b->first_loc ().line_number;
>  	  els->line_offset.sign = LINE_OFFSET_NONE;
>  
>  	  b->locspec = std::move (els);
> @@ -12873,9 +12870,10 @@ code_breakpoint::location_spec_to_sals (location_spec *locspec,
>  	  && (condition_not_parsed
>  	      || (this->has_locations ()
>  		  && search_pspace != NULL
> -		  && loc->pspace != search_pspace)
> -	      || (this->has_locations () && loc->shlib_disabled)
> -	      || (this->has_locations () && loc->pspace->executing_startup)
> +		  && 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;
>  
> @@ -13047,7 +13045,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;
>      }
>  }
>  
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index 2a3a5cf57b83..9f49ed62a9ad 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -645,6 +645,20 @@ struct breakpoint
>    bool has_multiple_locations () const
>    { return this->loc != nullptr && this->loc->next != nullptr; }
>  
> +  /* Return a reference to the first location of this breakpoint.  */
> +  bp_location &first_loc ()
> +  {
> +    gdb_assert (this->has_locations ());
> +    return *this->loc;
> +  }
> +
> +  /* Return a reference to the first location of this breakpoint.  */
> +  const bp_location &first_loc () const
> +  {
> +    gdb_assert (this->has_locations ());
> +    return *this->loc;
> +  }
> +
>    /* Reevaluate a breakpoint.  This is necessary after symbols change
>       (e.g., an executable or DSO was loaded, or the inferior just
>       started).  */
> diff --git a/gdb/elfread.c b/gdb/elfread.c
> index 7169ae8808a8..2d4f23416245 100644
> --- a/gdb/elfread.c
> +++ b/gdb/elfread.c
> @@ -974,7 +974,7 @@ elf_gnu_ifunc_resolver_stop (code_breakpoint *b)
>        gdb_assert (frame_id_p (b_return->frame_id));
>  
>        if (b_return->thread == thread_id
> -	  && b_return->loc->requested_address == prev_pc
> +	  && b_return->first_loc ().requested_address == prev_pc
>  	  && b_return->frame_id == prev_frame_id)
>  	break;
>      }
> @@ -1043,7 +1043,7 @@ elf_gnu_ifunc_resolver_return_stop (code_breakpoint *b)
>  
>    func_func = value::allocate (func_func_type);
>    func_func->set_lval (lval_memory);
> -  func_func->set_address (b->loc->related_address);
> +  func_func->set_address (b->first_loc ().related_address);
>  
>    value = value::allocate (value_type);
>    gdbarch_return_value_as_value (gdbarch, func_func, value_type, regcache,
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index efe2c00c489a..a9e2a2423b17 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -950,14 +950,14 @@ follow_inferior_reset_breakpoints (void)
>    if (tp->control.step_resume_breakpoint)
>      {
>        breakpoint_re_set_thread (tp->control.step_resume_breakpoint);
> -      tp->control.step_resume_breakpoint->loc->enabled = 1;
> +      tp->control.step_resume_breakpoint->first_loc ().enabled = 1;
>      }
>  
>    /* Treat exception_resume breakpoints like step_resume breakpoints.  */
>    if (tp->control.exception_resume_breakpoint)
>      {
>        breakpoint_re_set_thread (tp->control.exception_resume_breakpoint);
> -      tp->control.exception_resume_breakpoint->loc->enabled = 1;
> +      tp->control.exception_resume_breakpoint->first_loc ().enabled = 1;
>      }
>  
>    /* Reinsert all breakpoints in the child.  The user may have set
> @@ -2551,7 +2551,8 @@ resume_1 (enum gdb_signal sig)
>  		 user breakpoints at PC to trigger (again) when this
>  		 hits.  */
>  	      insert_hp_step_resume_breakpoint_at_frame (get_current_frame ());
> -	      gdb_assert (tp->control.step_resume_breakpoint->loc->permanent);
> +	      gdb_assert (tp->control.step_resume_breakpoint->first_loc ()
> +			  .permanent);
>  
>  	      tp->step_after_step_resume_breakpoint = step;
>  	    }
> @@ -7008,9 +7009,9 @@ process_event_stop_test (struct execution_control_state *ecs)
>  	= ecs->event_thread->control.step_resume_breakpoint;
>  
>        if (sr_bp != nullptr
> -	  && sr_bp->loc->permanent
> +	  && sr_bp->first_loc ().permanent
>  	  && sr_bp->type == bp_hp_step_resume
> -	  && sr_bp->loc->address == ecs->event_thread->prev_pc)
> +	  && sr_bp->first_loc ().address == ecs->event_thread->prev_pc)
>  	{
>  	  infrun_debug_printf ("stepped permanent breakpoint, stopped in handler");
>  	  delete_step_resume_breakpoint (ecs->event_thread);
> diff --git a/gdb/tracectf.c b/gdb/tracectf.c
> index ab513b1fa158..16461711da18 100644
> --- a/gdb/tracectf.c
> +++ b/gdb/tracectf.c
> @@ -1536,7 +1536,7 @@ ctf_get_traceframe_address (void)
>  	= get_tracepoint_by_number_on_target (tpnum);
>  
>        if (tp != nullptr && tp->has_locations ())
> -	addr = tp->loc->address;
> +	addr = tp->first_loc ().address;
>      }
>  
>    /* Restore the position.  */
> diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
> index 9c1adee11bc3..9203bcc2e4bb 100644
> --- a/gdb/tracefile-tfile.c
> +++ b/gdb/tracefile-tfile.c
> @@ -668,7 +668,7 @@ tfile_get_traceframe_address (off_t tframe_offset)
>    tp = get_tracepoint_by_number_on_target (tpnum);
>    /* FIXME this is a poor heuristic if multiple locations.  */
>    if (tp != nullptr && tp->has_locations ())
> -    addr = tp->loc->address;
> +    addr = tp->first_loc ().address;
>  
>    /* Restore our seek position.  */
>    cur_offset = saved_offset;
> diff --git a/gdb/tracefile.c b/gdb/tracefile.c
> index 883ce4bf375a..5a2641919f74 100644
> --- a/gdb/tracefile.c
> +++ b/gdb/tracefile.c
> @@ -412,7 +412,7 @@ tracefile_fetch_registers (struct regcache *regcache, int regno)
>  
>    /* Guess what we can from the tracepoint location.  */
>    gdbarch_guess_tracepoint_registers (gdbarch, regcache,
> -				      tp->loc->address);
> +				      tp->first_loc ().address);
>  }
>  
>  /* This is the implementation of target_ops method to_has_all_memory.  */
> diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
> index 4a9d8491a54b..99d175d32e42 100644
> --- a/gdb/tracepoint.c
> +++ b/gdb/tracepoint.c
> @@ -2750,7 +2750,7 @@ get_traceframe_location (int *stepping_frame_p)
>    /* If this is a stepping frame, we don't know which location
>       triggered.  The first is as good (or bad) a guess as any...  */
>    *stepping_frame_p = 1;
> -  return t->loc;
> +  return &t->first_loc ();
>  }
>  
>  /* Return the default collect actions of a tracepoint T.  */
> diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
> index 3c4ce501e5ee..3fc38b7be233 100644
> --- a/gdb/tui/tui-winsource.c
> +++ b/gdb/tui/tui-winsource.c
> @@ -640,7 +640,7 @@ tui_source_window_base::update_breakpoint_info
>  		    mode |= TUI_BP_ENABLED;
>  		  if (bp->hit_count)
>  		    mode |= TUI_BP_HIT;
> -		  if (bp->loc->cond)
> +		  if (bp->first_loc ().cond)
>  		    mode |= TUI_BP_CONDITIONAL;
>  		  if (bp->type == bp_hardware_breakpoint)
>  		    mode |= TUI_BP_HARDWARE;
> -- 
> 2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 07/12] gdb: link breakpoint locations with intrusive_list
  2023-05-11 14:48 ` [PATCH 07/12] gdb: link breakpoint locations with intrusive_list Simon Marchi
@ 2023-05-18 14:44   ` Andrew Burgess
  2023-05-18 18:40     ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Burgess @ 2023-05-18 14:44 UTC (permalink / raw)
  To: Simon Marchi via Gdb-patches, gdb-patches; +Cc: Simon Marchi

Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:

> Replace the hand-maintained linked lists of breakpoint locations with
> and intrusive list.
>
>  - Remove breakpoint::loc, add breakpoint::m_locations.
>
>  - Add methods for the various manipulations that need to be done on the
>    location list.
>
>  - bp_location currently has a default constructor because of one use
>    in hoist_existing_locations.  hoist_existing_locations now returns a
>    bp_location_list, and doesn't need the default-constructor
>    bp_location anymore, so remove the bp_location default constructor.
>
>  - Add a call to clear_locations in delete_breakpoint to avoid a
>    use-after-free when struct breakpoint objects get deleted
>
> bp_location_range uses reference_to_pointer_iterator, so that all
> existing callers of breakpoint::locations don't need to change right
> now.  It will be removed in the next patch.
>
> The rest of the changes are to adapt the call sites to use the new
> methods, of breakpoint::locations, rather than breakpoint::loc directly.
>
> Change-Id: I25f7ee3d66a4e914a0540589ac414b3b820b6e70
> ---
>  gdb/breakpoint.c | 258 ++++++++++++++++++++++++-----------------------
>  gdb/breakpoint.h |  77 ++++++++++----
>  gdb/tracepoint.c |   4 +-
>  3 files changed, 188 insertions(+), 151 deletions(-)
>
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index e9b6574bba77..6ec0f6a11e88 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -1049,13 +1049,18 @@ 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 ())
> +	  auto bp_loc_range = b->locations ();
> +	  for (auto bp_loc_it = bp_loc_range.begin ();
> +	       bp_loc_it != bp_loc_range.end ();
> +	       ++bp_loc_it)
>  	    {
> +	      bp_location &loc = **bp_loc_it;
> +

You could switch this to:

  for (const bp_location *loc : b->locations ())

if we could also do .... (continued below)

>  	      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;
> @@ -1065,7 +1070,7 @@ 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 (std::next (bp_loc_it) == bp_loc_range.end () && !force)

... this:

  if (loc == b->last_loc ())
    throw

This requires adding 'breakpoint::last_loc ()' but we already have
'breakpoint::first_loc ()' so that doesn't seem crazy, and I think the
resulting code would be easier to read maybe?

>  		    throw;
>  		}
>  	    }
> @@ -1878,8 +1883,9 @@ add_dummy_location (struct breakpoint *b,
>  {
>    gdb_assert (!b->has_locations ());
>  
> -  b->loc = new bp_location (b, bp_loc_other);
> -  b->loc->pspace = pspace;
> +  bp_location *loc = new bp_location (b, bp_loc_other);
> +  loc->pspace = pspace;
> +  b->add_location (*loc);
>  }
>  
>  /* Assuming that B is a watchpoint:
> @@ -1982,7 +1988,7 @@ update_watchpoint (struct watchpoint *b, bool 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)
>      {
> @@ -2081,7 +2087,6 @@ update_watchpoint (struct watchpoint *b, bool reparse)
>  		{
>  		  CORE_ADDR addr;
>  		  enum target_hw_bp_type type;
> -		  struct bp_location *loc, **tmp;
>  		  int bitpos = 0, bitsize = 0;
>  
>  		  if (v->bitsize () != 0)
> @@ -2113,10 +2118,9 @@ update_watchpoint (struct watchpoint *b, bool reparse)
>  		  else if (b->type == bp_access_watchpoint)
>  		    type = hw_access;
>  
> -		  loc = b->allocate_location ();
> -		  for (tmp = &(b->loc); *tmp != NULL; tmp = &((*tmp)->next))
> -		    ;
> -		  *tmp = loc;
> +		  bp_location *loc = b->allocate_location ();
> +		  b->add_location (*loc);
> +
>  		  loc->gdbarch = v->type ()->arch ();
>  
>  		  loc->pspace = frame_pspace;
> @@ -3029,23 +3033,11 @@ breakpoint_program_space_exit (struct program_space *pspace)
>    /* 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.  */
> @@ -4166,7 +4158,7 @@ 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)
>  		  {
> @@ -4518,28 +4510,23 @@ bpstat_locno (const bpstat *bs)
>    const struct breakpoint *b = bs->breakpoint_at;
>    const struct bp_location *bl = bs->bp_location_at.get ();
>  
> -  int locno = 0;
> -
>    if (b != nullptr && b->has_multiple_locations ())
>      {
> -      const bp_location *bl_i;
> -
> -      for (bl_i = b->loc;
> -	   bl_i != bl && bl_i->next != nullptr;
> -	   bl_i = bl_i->next)
> -	locno++;
> +      int locno = 1;
>  
> -      if (bl_i == bl)
> -	locno++;
> -      else
> +      for (bp_location *loc : b->locations ())
>  	{
> -	  warning (_("location number not found for breakpoint %d address %s."),
> -		   b->number, paddress (bl->gdbarch, bl->address));
> -	  locno = 0;
> +	  if (bl == loc)
> +	    return locno;
> +
> +	  ++locno;
>  	}
> +
> +      warning (_("location number not found for breakpoint %d address %s."),
> +	       b->number, paddress (bl->gdbarch, bl->address));
>      }

I might be missing something here, but could this code be simplified by
using std::distance in some way?  We already use std::distance later in
this patch to count the total number of locations, so it feels like this
should work.

I know that the current code allows for the possibility that the
location (from the bp_stat) might not be in the location list of the
breakpoint (from bp_stat), but, surely that can't happen, right?  Surely
the location was originally found by looking through the locations of
the breakpoint... so it should be certain that we find the location.

I guess maybe we could remove the breakpoint_at from bp_stat, and just
use the owner of the bp_location_at variable, that way we could be
certain about all this...

Either way, there's nothing wrong with your code above, just wondering
if we can make it tighter...

>  
> -  return locno;
> +  return 0;
>  }
>  
>  /* See breakpoint.h.  */
> @@ -8178,18 +8165,19 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
>      (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
>  			       orig->frame_id, thread));
>    bp_location &orig_loc = orig->first_loc ();
> -  copy->loc = copy->allocate_location ();
> -  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;
> +  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);
> @@ -8294,7 +8282,6 @@ handle_automatic_hardware_breakpoints (bp_location *bl)
>  bp_location *
>  code_breakpoint::add_location (const symtab_and_line &sal)
>  {
> -  struct bp_location *new_loc, **tmp;
>    CORE_ADDR adjusted_address;
>    struct gdbarch *loc_gdbarch = get_sal_arch (sal);
>  
> @@ -8312,12 +8299,8 @@ code_breakpoint::add_location (const symtab_and_line &sal)
>  						sal.pspace);
>  
>    /* Sort the locations by their ADDRESS.  */
> -  new_loc = allocate_location ();
> -  for (tmp = &(loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
> -       tmp = &((*tmp)->next))
> -    ;
> -  new_loc->next = *tmp;
> -  *tmp = new_loc;
> +  bp_location *new_loc = this->allocate_location ();
> +  breakpoint::add_location (*new_loc, adjusted_address);

I notice here the code basically does:

  1. Create bp_location object,
  2. Add bp_location object to list,
  3. Initialise bp_location object.

We have to pass adjusted_address through because the address of new_loc
has not yet been initialised.

Could we reorder things so we:

  1. Create bp_location object,
  2. Initialise bp_location object,
  3. Add bp_location object to list.

The benefit I think would be that we can remove these two functions:

  void breakpoint::add_location (bp_location &loc);
  void breakpoint::add_location (bp_location &loc, CORE_ADDR address);

And we replace them with one function:

  void breakpoint::add_location (bp_location &loc, bool sorted = false);

The implementation would be free to use 'loc.address' for the sorting.

>  
>    new_loc->requested_address = sal.pc;
>    new_loc->address = adjusted_address;
> @@ -11623,10 +11606,7 @@ code_breakpoint::say_where () const
>  
>        if (this->has_multiple_locations ())
>  	{
> -	  struct bp_location *iter = loc;
> -	  int n = 0;
> -	  for (; iter; iter = iter->next)
> -	    ++n;
> +	  int n = std::distance (m_locations.begin (), m_locations.end ());
>  	  gdb_printf (" (%d locations)", n);
>  	}
>      }
> @@ -11636,7 +11616,9 @@ code_breakpoint::say_where () const
>  
>  bp_location_range breakpoint::locations () const
>  {
> -  return bp_location_range (this->loc);
> +  return bp_location_range
> +    (bp_location_pointer_iterator (m_locations.begin ()),
> +     bp_location_pointer_iterator (m_locations.end ()));
>  }
>  
>  struct bp_location *
> @@ -11645,6 +11627,43 @@ breakpoint::allocate_location ()
>    return new bp_location (this);
>  }
>  
> +/* See breakpoint.h.  */
> +
> +void
> +breakpoint::add_location (bp_location &loc)
> +{
> +  gdb_assert (loc.owner == this);
> +  gdb_assert (!loc.is_linked ());
> +
> +  m_locations.push_back (loc);
> +}
> +
> +/* See breakpoint.h.  */
> +
> +void
> +breakpoint::add_location (bp_location &loc, CORE_ADDR address)
> +{
> +  gdb_assert (loc.owner == this);
> +  gdb_assert (!loc.is_linked ());
> +
> +  auto ub = std::upper_bound (m_locations.begin (), m_locations.end (),
> +			      address,
> +			      [] (CORE_ADDR left, bp_location &right)
> +				{ return left < right.address; });
> +  m_locations.insert (ub, loc);
> +}
> +
> +/* See breakpoint.h.  */
> +
> +void
> +breakpoint::unadd_location (bp_location &loc)
> +{
> +  gdb_assert (loc.owner == this);
> +  gdb_assert (loc.is_linked ());
> +
> +  m_locations.erase (m_locations.iterator_to (loc));
> +}
> +
>  #define internal_error_pure_virtual_called() \
>    gdb_assert_not_reached ("pure virtual function called")
>  
> @@ -12395,7 +12414,12 @@ 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 would access the locations after they are freed in
> +     update_global_location_list.  */
> +  bpt->clear_locations ();
>    update_global_location_list (UGLL_DONT_INSERT);
>  
>    /* On the chance that someone will soon try again to delete this
> @@ -12490,17 +12514,16 @@ all_locations_are_pending (struct breakpoint *b, struct program_space *pspace)
>  }
>  
>  /* Subroutine of update_breakpoint_locations to simplify it.
> -   Return true 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 bool
> -ambiguous_names_p (struct bp_location *loc)
> +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 ();
> @@ -12645,72 +12668,56 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
>    return sal;
>  }
>  
> -/* Returns true 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 bool
> -locations_are_equal (struct bp_location *a, struct bp_location *b)
> +locations_are_equal (const bp_location_list &a, const bp_location_range &b)
>  {
> -  while (a && b)
> +  auto a_iter = a.begin ();
> +  auto b_iter = b.begin ();
> +
> +  for (; a_iter != a.end () && b_iter != b.end (); ++a_iter, ++b_iter)
>      {
> -      if (a->address != b->address)
> +      if (a_iter->address != (*b_iter)->address)
>  	return false;
>  
> -      if (a->shlib_disabled != b->shlib_disabled)
> +      if (a_iter->shlib_disabled != (*b_iter)->shlib_disabled)
>  	return false;
>  
> -      if (a->enabled != b->enabled)
> +      if (a_iter->enabled != (*b_iter)->enabled)
>  	return false;
>  
> -      if (a->disabled_by_cond != b->disabled_by_cond)
> +      if (a_iter->disabled_by_cond != (*b_iter)->disabled_by_cond)
>  	return false;
> -
> -      a = a->next;
> -      b = b->next;
>      }
>  
> -  if ((a == NULL) != (b == NULL))
> -    return false;
> -
> -  return true;
> +  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
> @@ -12725,8 +12732,6 @@ update_breakpoint_locations (code_breakpoint *b,
>  			     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
> @@ -12748,7 +12753,7 @@ update_breakpoint_locations (code_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)
>      {
> @@ -12788,17 +12793,16 @@ update_breakpoint_locations (code_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)
>  	      {
> @@ -12811,10 +12815,10 @@ update_breakpoint_locations (code_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;
>  		      }
>  		  }
> @@ -12823,11 +12827,11 @@ update_breakpoint_locations (code_breakpoint *b,
>  	      {
>  		for (bp_location *l : b->locations ())
>  		  if (l->function_name
> -		      && strcmp (e->function_name.get (),
> +		      && 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;
>  		    }
>  	      }
> @@ -12835,7 +12839,7 @@ update_breakpoint_locations (code_breakpoint *b,
>        }
>    }
>  
> -  if (!locations_are_equal (existing_locations, b->loc))
> +  if (!locations_are_equal (existing_locations, b->locations ()))
>      gdb::observers::breakpoint_modified.notify (b);
>  }
>  
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index 9f49ed62a9ad..4da64d8c27c8 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h
> @@ -33,6 +33,7 @@
>  #include "gdbsupport/next-iterator.h"
>  #include "gdbsupport/iterator-range.h"
>  #include "gdbsupport/refcounted-object.h"
> +#include "gdbsupport/reference-to-pointer-iterator.h"
>  #include "gdbsupport/safe-iterator.h"
>  #include "cli/cli-script.h"
>  #include "target/waitstatus.h"
> @@ -321,11 +322,9 @@ enum bp_loc_type
>    bp_loc_other			/* Miscellaneous...  */
>  };
>  
> -class bp_location : public refcounted_object
> +class bp_location : public refcounted_object, public intrusive_list_node<bp_location>
>  {
>  public:
> -  bp_location () = default;
> -
>    /* Construct a bp_location with the type inferred from OWNER's
>       type.  */
>    explicit bp_location (breakpoint *owner);
> @@ -335,10 +334,6 @@ class bp_location : public refcounted_object
>  
>    virtual ~bp_location () = default;
>  
> -  /* Chain pointer to the next breakpoint location for
> -     the same parent breakpoint.  */
> -  bp_location *next = NULL;
> -
>    /* Type of this breakpoint location.  */
>    bp_loc_type loc_type {};
>  
> @@ -609,9 +604,11 @@ enum watchpoint_triggered
>  
>  extern bool target_exact_watchpoints;
>  
> -/* bp_location linked list range.  */
> -
> -using bp_location_range = next_range<bp_location>;
> +using bp_location_list = intrusive_list<bp_location>;
> +using bp_location_iterator = bp_location_list::iterator;
> +using bp_location_pointer_iterator
> +  = reference_to_pointer_iterator<bp_location_iterator>;
> +using bp_location_range = iterator_range<bp_location_pointer_iterator>;
>  
>  /* Note that the ->silent field is not currently used by any commands
>     (though the code is in there if it was to be, and set_raw_breakpoint
> @@ -633,30 +630,71 @@ struct breakpoint
>    /* Allocate a location for this breakpoint.  */
>    virtual struct bp_location *allocate_location ();
>  
> +  /* Return a range of this breakpoint's locations.  */
> +  bp_location_range locations () const;
> +
> +  /* Add LOC at the end of the location list of this breakpoint.
> +
> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
> +     in a location list.  */
> +  void add_location (bp_location &loc);
> +
> +  /* Add LOC in the location list of this breakpoint, sorted by address.
> +
> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
> +     in a location list.  */
> +  void add_location (bp_location &loc, CORE_ADDR address);

It would be nice for the comment to mention what ADDRESS means here.
However, my earlier comments for where this function is used might mean
this is no longer needed in this form.

Thanks,
Andrew

> +
> +  /* Remove LOC from this breakpoint's location list.  The name is a bit funny
> +     because remove_location is already taken, and means something else.
> +
> +     LOC must be have this breakpoints as its owner.  LOC must be linked in this
> +     breakpoint's location list.  */
> +  void unadd_location (bp_location &loc);
> +
> +  /* Clear the location list of this breakpoint.  */
> +  void clear_locations ()
> +  { m_locations.clear (); }
> +
> +  /* Split all locations of this breakpoint that are bound to PSPACE out of its
> +     location list to a separate list and return that list.  If
> +     PSPACE is nullptr, hoist out all locations.  */
> +  bp_location_list steal_locations (program_space *pspace);
> +
>    /* Return true if this breakpoint has a least one location.  */
>    bool has_locations () const
> -  { return this->loc != nullptr; }
> +  { return !m_locations.empty (); }
>  
>    /* Return true if this breakpoint has a single location.  */
>    bool has_single_location () const
> -  { return this->loc != nullptr && this->loc->next == nullptr; }
> +  {
> +    if (!this->has_locations ())
> +      return false;
> +
> +    return std::next (m_locations.begin ()) == m_locations.end ();
> +  }
>  
>    /* Return true if this breakpoint has multiple locations.  */
>    bool has_multiple_locations () const
> -  { return this->loc != nullptr && this->loc->next != nullptr; }
> +  {
> +    if (!this->has_locations ())
> +      return false;
> +
> +    return std::next (m_locations.begin ()) != m_locations.end ();
> +  }
>  
>    /* Return a reference to the first location of this breakpoint.  */
>    bp_location &first_loc ()
>    {
>      gdb_assert (this->has_locations ());
> -    return *this->loc;
> +    return m_locations.front ();
>    }
>  
>    /* Return a reference to the first location of this breakpoint.  */
>    const bp_location &first_loc () const
>    {
>      gdb_assert (this->has_locations ());
> -    return *this->loc;
> +    return m_locations.front ();
>    }
>  
>    /* Reevaluate a breakpoint.  This is necessary after symbols change
> @@ -753,9 +791,6 @@ struct breakpoint
>      /* Nothing to do.  */
>    }
>  
> -  /* Return a range of this breakpoint's locations.  */
> -  bp_location_range locations () const;
> -
>    breakpoint *next = NULL;
>    /* Type of breakpoint.  */
>    bptype type = bp_none;
> @@ -766,9 +801,6 @@ struct breakpoint
>    /* Number assigned to distinguish breakpoints.  */
>    int number = 0;
>  
> -  /* Location(s) associated with this high-level breakpoint.  */
> -  bp_location *loc = NULL;
> -
>    /* True means a silent breakpoint (don't print frame info if we stop
>       here).  */
>    bool silent = false;
> @@ -864,6 +896,9 @@ struct breakpoint
>       thread 1", which needs outputting before any breakpoint-type
>       specific extra command necessary for B's recreation.  */
>    void print_recreate_thread (struct ui_file *fp) const;
> +
> +  /* Location(s) associated with this high-level breakpoint.  */
> +  bp_location_list m_locations;
>  };
>  
>  /* Abstract base class representing code breakpoints.  User "break"
> diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
> index 99d175d32e42..3e0bdafa19d3 100644
> --- a/gdb/tracepoint.c
> +++ b/gdb/tracepoint.c
> @@ -3044,8 +3044,6 @@ cond_string_is_same (char *str1, char *str2)
>  static struct bp_location *
>  find_matching_tracepoint_location (struct uploaded_tp *utp)
>  {
> -  struct bp_location *loc;
> -
>    for (breakpoint *b : all_tracepoints ())
>      {
>        struct tracepoint *t = (struct tracepoint *) b;
> @@ -3059,7 +3057,7 @@ find_matching_tracepoint_location (struct uploaded_tp *utp)
>  	  )
>  	{
>  	  /* Scan the locations for an address match.  */
> -	  for (loc = b->loc; loc; loc = loc->next)
> +	  for (bp_location *loc : b->locations ())
>  	    {
>  	      if (loc->address == utp->addr)
>  		return loc;
> -- 
> 2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 12/12] gdb: remove breakpoint_pointer_iterator
  2023-05-11 14:48 ` [PATCH 12/12] gdb: remove breakpoint_pointer_iterator Simon Marchi
@ 2023-05-18 15:53   ` Andrew Burgess
  2023-05-18 18:44     ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Andrew Burgess @ 2023-05-18 15:53 UTC (permalink / raw)
  To: Simon Marchi via Gdb-patches, gdb-patches; +Cc: Simon Marchi

Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:

> Remove the breakpoint_pointer_iterator layer.  Adjust all users of
> all_breakpoints and all_tracepoints to use references instead of
> pointers.
>
> Change-Id: I376826f812117cee1e6b199c384a10376973af5d
> ---
>  gdb/break-catch-load.c           |  12 +-
>  gdb/break-catch-syscall.c        |   4 +-
>  gdb/breakpoint.c                 | 605 +++++++++++++++----------------
>  gdb/breakpoint.h                 |  10 +-
>  gdb/dummy-frame.c                |   4 +-
>  gdb/guile/scm-breakpoint.c       |   4 +-
>  gdb/python/py-breakpoint.c       |   4 +-
>  gdb/python/py-finishbreakpoint.c |   8 +-
>  gdb/solib-svr4.c                 |   4 +-
>  gdb/tracepoint.c                 |  56 +--
>  gdb/tui/tui-winsource.c          |  14 +-
>  11 files changed, 360 insertions(+), 365 deletions(-)
>
> diff --git a/gdb/break-catch-load.c b/gdb/break-catch-load.c
> index 43962880cd96..440b42852bbf 100644
> --- a/gdb/break-catch-load.c
> +++ b/gdb/break-catch-load.c
> @@ -91,20 +91,20 @@ solib_catchpoint::breakpoint_hit (const struct bp_location *bl,
>    if (ws.kind () == TARGET_WAITKIND_LOADED)
>      return 1;
>  
> -  for (breakpoint *other : all_breakpoints ())
> +  for (breakpoint &other : all_breakpoints ())
>      {
> -      if (other == bl->owner)
> +      if (&other == bl->owner)
>  	continue;
>  
> -      if (other->type != bp_shlib_event)
> +      if (other.type != bp_shlib_event)
>  	continue;
>  
> -      if (pspace != NULL && other->pspace != pspace)
> +      if (pspace != NULL && other.pspace != pspace)
>  	continue;
>  
> -      for (bp_location &other_bl : other->locations ())
> +      for (bp_location &other_bl : other.locations ())
>  	{
> -	  if (other->breakpoint_hit (&other_bl, aspace, bp_addr, ws))
> +	  if (other.breakpoint_hit (&other_bl, aspace, bp_addr, ws))
>  	    return 1;
>  	}
>      }
> diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c
> index 18e2b20c1385..9abf8183984f 100644
> --- a/gdb/break-catch-syscall.c
> +++ b/gdb/break-catch-syscall.c
> @@ -501,8 +501,8 @@ catching_syscall_number_1 (struct breakpoint *b, int syscall_number)
>  bool
>  catching_syscall_number (int syscall_number)
>  {
> -  for (breakpoint *b : all_breakpoints ())
> -    if (catching_syscall_number_1 (b, syscall_number))
> +  for (breakpoint &b : all_breakpoints ())
> +    if (catching_syscall_number_1 (&b, syscall_number))
>        return true;
>  
>    return false;
> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
> index 5f47dc777438..4de3716a0987 100644
> --- a/gdb/breakpoint.c
> +++ b/gdb/breakpoint.c
> @@ -621,9 +621,7 @@ static intrusive_list<breakpoint> breakpoint_chain;
>  breakpoint_range
>  all_breakpoints ()
>  {
> -  return breakpoint_range
> -    (breakpoint_pointer_iterator (breakpoint_chain.begin ()),
> -     breakpoint_pointer_iterator (breakpoint_chain.end ()));
> +  return breakpoint_range (breakpoint_chain.begin (), breakpoint_chain.end ());
>  }
>  
>  /* See breakpoint.h.  */
> @@ -639,9 +637,8 @@ all_breakpoints_safe ()
>  tracepoint_range
>  all_tracepoints ()
>  {
> -  return tracepoint_range
> -    (tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.begin ())),
> -     tracepoint_iterator (breakpoint_pointer_iterator (breakpoint_chain.end ())));
> +  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.  */
> @@ -796,8 +793,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
> @@ -807,9 +804,9 @@ 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;
>  }
> @@ -820,9 +817,9 @@ get_breakpoint (int num)
>  static bool
>  has_multiple_locations (int num)
>  {
> -  for (breakpoint *b : all_breakpoints ())
> -    if (b->number == num)
> -      return b->has_multiple_locations ();
> +  for (breakpoint &b : all_breakpoints ())
> +    if (b.number == num)
> +      return b.has_multiple_locations ();
>  
>    return false;
>  }
> @@ -1104,14 +1101,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)
>  	  {
> @@ -1119,9 +1116,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;
> @@ -1196,11 +1193,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));
> @@ -1417,13 +1414,13 @@ static_tracepoints_here (CORE_ADDR addr)
>  {
>    std::vector<breakpoint *> found;
>  
> -  for (breakpoint *b : all_breakpoints ())
> -    if (b->type == bp_static_tracepoint
> -	|| b->type == bp_static_marker_tracepoint)
> +  for (breakpoint &b : all_breakpoints ())
> +    if (b.type == bp_static_tracepoint
> +	|| b.type == bp_static_marker_tracepoint)
>        {
> -	for (bp_location &loc : b->locations ())
> +	for (bp_location &loc : b.locations ())
>  	  if (loc.address == addr)
> -	    found.push_back (b);
> +	    found.push_back (&b);
>        }
>  
>    return found;
> @@ -3030,9 +3027,9 @@ 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.  */
> @@ -3055,12 +3052,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 = static_cast<watchpoint &> (bpt);

Could possibly use gdb::checked_static_cast here?  And in other places
throughout this patch?

>  
> -	update_watchpoint (w, false /* don't reparse.  */);
> +	update_watchpoint (&w, false /* don't reparse.  */);
>        }
>  
>    /* Updating watchpoints creates new locations, so update the global
> @@ -3179,20 +3176,20 @@ 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 ())
>      {
>        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 ())
> +      for (bp_location &loc : bpt.locations ())
>  	if (!loc.inserted && should_be_inserted (&loc))
>  	  {
>  	    some_failed = true;
> @@ -3201,14 +3198,14 @@ insert_breakpoint_locations (void)
>  
>        if (some_failed)
>  	{
> -	  for (bp_location &loc : bpt->locations ())
> +	  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;
>  	}
>      }
> @@ -3249,14 +3246,14 @@ 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))
>  	{
>  	  gdb_printf (_("\
>  Thread-specific breakpoint %d deleted - thread %s no longer in the thread list.\n"),
> -		      b->number, print_thread_id (tp));
> -	  delete_breakpoint (b);
> +		      b.number, print_thread_id (tp));
> +	  delete_breakpoint (&b);
>         }
>      }
>  }
> @@ -3765,60 +3762,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
> @@ -3853,7 +3850,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;
>  	}
> @@ -3861,9 +3858,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_location_spec_empty_p (b))
> +      if (breakpoint_location_spec_empty_p (&b))
>  	{
> -	  delete_breakpoint (b);
> +	  delete_breakpoint (&b);
>  	  continue;
>  	}
>      }
> @@ -4100,12 +4097,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->has_locations () && b->first_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:
> @@ -4142,7 +4139,7 @@ breakpoint_init_inferior (enum inf_context context)
>  
>  	  /* Also remove single-step breakpoints.  */
>  
> -	  delete_breakpoint (b);
> +	  delete_breakpoint (&b);
>  	  break;
>  
>  	case bp_watchpoint:
> @@ -4150,11 +4147,11 @@ breakpoint_init_inferior (enum inf_context context)
>  	case bp_read_watchpoint:
>  	case bp_access_watchpoint:
>  	  {
> -	    struct watchpoint *w = (struct watchpoint *) b;
> +	    watchpoint &w = 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
> @@ -4162,14 +4159,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->clear_locations ();
> +		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;
>  		  }
>  	      }
>  	  }
> @@ -4350,16 +4347,16 @@ 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 ())
> +      for (bp_location &loc : bpt.locations ())
>  	if (loc.pspace->aspace == aspace && loc.inserted)
>  	  {
>  	    CORE_ADDR l, h;
> @@ -5009,12 +5006,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 = static_cast<watchpoint &> (b);
>  
> -	    w->watchpoint_triggered = watch_triggered_no;
> +	    w.watchpoint_triggered = watch_triggered_no;
>  	  }
>  
>        return 0;
> @@ -5024,12 +5021,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 = static_cast<watchpoint &> (b);
>  
> -	    w->watchpoint_triggered = watch_triggered_unknown;
> +	    w.watchpoint_triggered = watch_triggered_unknown;
>  	  }
>  
>        return 1;
> @@ -5039,22 +5036,22 @@ 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 = 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;
>  		  }
>  	      }
> @@ -5063,7 +5060,7 @@ watchpoints_triggered (const target_waitstatus &ws)
>  		       (current_inferior ()->top_target (), addr, loc.address,
>  			loc.length))
>  	      {
> -		w->watchpoint_triggered = watch_triggered_yes;
> +		w.watchpoint_triggered = watch_triggered_yes;
>  		break;
>  	      }
>  	  }
> @@ -5363,14 +5360,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 =
> +			      static_cast<watchpoint &> (other_b);
>  
> -			    if (other_w->watchpoint_triggered
> +			    if (other_w.watchpoint_triggered
>  				== watch_triggered_yes)
>  			      {
>  				other_write_watchpoint = 1;
> @@ -5612,19 +5609,19 @@ 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->first_loc ())
> +	  if (b.type == bp_hardware_watchpoint && &bl != &b.first_loc ())
>  	    break;
>  
>  	  if (!bl.enabled || bl.disabled_by_cond || bl.shlib_disabled)
> @@ -5649,9 +5646,9 @@ build_bpstat_chain (const address_space *aspace, CORE_ADDR bp_addr,
>  	     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;
>  	    }
> @@ -6044,10 +6041,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->has_locations ())
> +  for (breakpoint &b : all_breakpoints ())
> +    if (breakpoint_enabled (&b)
> +	&& b.type == bp_watchpoint
> +	&& b.has_locations ())
>        return true;
>  
>    return false;
> @@ -6832,31 +6829,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;
>  
> @@ -6900,11 +6897,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
> @@ -6914,21 +6911,21 @@ 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 ())
> +	    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;
>  	  }
> @@ -7041,9 +7038,9 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
>  {
>    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)
>      {
> @@ -7051,23 +7048,24 @@ describe_other_breakpoints (struct gdbarch *gdbarch,
>  	gdb_printf (_("Note: breakpoint "));
>        else /* if (others == ???) */
>  	gdb_printf (_("Note: breakpoints "));
> -      for (breakpoint *b : all_breakpoints ())
> -	if (user_breakpoint_p (b) && breakpoint_has_pc (b, pspace, pc, section))
> +      for (breakpoint &b : all_breakpoints ())
> +	if (user_breakpoint_p (&b)
> +	    && breakpoint_has_pc (&b, pspace, pc, section))
>  	  {
>  	    others--;
> -	    gdb_printf ("%d", b->number);
> -	    if (b->thread == -1 && thread != -1)
> +	    gdb_printf ("%d", b.number);
> +	    if (b.thread == -1 && thread != -1)
>  	      gdb_printf (" (all threads)");
> -	    else if (b->thread != -1)
> +	    else if (b.thread != -1)
>  	      {
> -		struct thread_info *thr = find_thread_global_id (b->thread);
> +		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);
> +	    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)
> +			((b.enable_state == bp_disabled
> +			  || b.enable_state == bp_call_disabled)
>  			 ? " (disabled)"
>  			 : ""),
>  			(others > 1) ? "," 
> @@ -7510,15 +7508,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;
> +	bptype type = b.type == bp_longjmp_master ? bp_longjmp : bp_exception;
>  	/* longjmp_breakpoint_ops ensures INITIATING_FRAME is cleared again
>  	   after their removal.  */
> -	momentary_breakpoint_from_master (b, type, 1, thread);
> +	momentary_breakpoint_from_master (&b, type, 1, thread);
>        }
>  
>    tp->initiating_frame = frame;
> @@ -7528,22 +7526,22 @@ 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)
> +	  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)
> +	  b.disposition = disp_del_at_next_stop;
>        }
>  }
>  
> @@ -7557,12 +7555,12 @@ 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)
>        {
>  	int thread = inferior_thread ()->global_num;
>  	breakpoint *new_b
> -	  = momentary_breakpoint_from_master (b, bp_longjmp_call_dummy,
> +	  = momentary_breakpoint_from_master (&b, bp_longjmp_call_dummy,
>  					      1, thread);
>  
>  	/* Link NEW_B into the chain of RETVAL breakpoints.  */
> @@ -7596,15 +7594,15 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
>       Save all breakpoints to delete in that set and delete them at the end.  */
>    std::unordered_set<breakpoint *> to_delete;
>  
> -  for (struct breakpoint *b : all_breakpoints ())
> +  for (struct breakpoint &b : all_breakpoints ())
>      {
> -      if (b->type == bp_longjmp_call_dummy && b->thread == tp->global_num)
> +      if (b.type == bp_longjmp_call_dummy && b.thread == tp->global_num)
>  	{
> -	  struct breakpoint *dummy_b = b->related_breakpoint;
> +	  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)
> +	  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
> @@ -7653,12 +7651,12 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
>  
>  	  dummy_frame_discard (dummy_b->frame_id, tp);
>  
> -	  for (breakpoint *related_breakpoint = b->related_breakpoint;
> -	       related_breakpoint != b;
> +	  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.related_breakpoint);
>  
> -	  to_delete.insert (b);
> +	  to_delete.insert (&b);
>  	}
>      }
>  
> @@ -7669,10 +7667,10 @@ check_longjmp_breakpoint_for_call_dummy (struct thread_info *tp)
>  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;
>        }
> @@ -7681,10 +7679,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;
>        }
> @@ -7695,11 +7693,11 @@ 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, 1,
> +	momentary_breakpoint_from_master (&b, bp_std_terminate, 1,
>  					  inferior_thread ()->global_num);
>        }
>  }
> @@ -7708,9 +7706,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 *
> @@ -7748,19 +7746,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->first_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->first_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.  */
> @@ -7768,10 +7766,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->first_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 /
> @@ -7913,14 +7911,14 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
>        || (objfile->flags & OBJF_USERLOADED) == 0)
>      return;
>  
> -  for (breakpoint *b : all_breakpoints ())
> +  for (breakpoint &b : all_breakpoints ())
>      {
>        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;
>  
> @@ -7954,7 +7952,7 @@ disable_breakpoints_in_freed_objfile (struct objfile *objfile)
>  	}
>  
>        if (bp_modified)
> -	gdb::observers::breakpoint_modified.notify (b);
> +	gdb::observers::breakpoint_modified.notify (&b);
>      }
>  }
>  
> @@ -8007,13 +8005,13 @@ 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->resources_needed (&bl);
> +	  i += b.resources_needed (&bl);
>  	}
>  
>    return i;
> @@ -8052,16 +8050,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;
>      }
>  
> @@ -8071,10 +8069,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);
>        }
>  }
> @@ -8082,10 +8080,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);
>        }
>  }
> @@ -8421,9 +8419,9 @@ 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);
> +  for (breakpoint &b : all_breakpoints ())
> +    if (b.type == bp_dprintf)
> +	update_dprintf_command_list (&b);
>  }
>  
>  code_breakpoint::code_breakpoint (struct gdbarch *gdbarch_,
> @@ -10824,14 +10822,14 @@ 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)
> -	      && user_breakpoint_p (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.  */
> @@ -10861,7 +10859,7 @@ clear_command (const char *arg, int from_tty)
>  	    }
>  
>  	  if (match)
> -	    found.push_back (b);
> +	    found.push_back (&b);
>  	}
>      }
>  
> @@ -10920,9 +10918,9 @@ 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
> @@ -11013,12 +11011,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;
>        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;
> @@ -11034,7 +11031,7 @@ 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
> @@ -11049,10 +11046,11 @@ download_tracepoint_locations (void)
>  	  bl.inserted = 1;
>  	  bp_location_downloaded = true;
>  	}
> -      t = (struct tracepoint *) b;
> -      t->number_on_target = b->number;
> +
> +      tracepoint &t = static_cast<tracepoint &> (b);
> +      t.number_on_target = b.number;
>        if (bp_location_downloaded)
> -	gdb::observers::breakpoint_modified.notify (b);
> +	gdb::observers::breakpoint_modified.notify (&b);
>      }
>  }
>  
> @@ -11159,8 +11157,8 @@ 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 ())
> +  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
> @@ -12458,8 +12456,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;
> @@ -12468,9 +12466,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
> @@ -12991,17 +12989,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);
>  	  }
>        }
>  
> @@ -13046,10 +13044,10 @@ 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)
>  	      gdb_printf (_("Ignore count ignored for tracepoint %d."),
> @@ -13057,7 +13055,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
>  	    return;
>  	  }
>  
> -	b->ignore_count = count;
> +	b.ignore_count = count;
>  	if (from_tty)
>  	  {
>  	    if (count == 0)
> @@ -13072,7 +13070,7 @@ set_ignore_count (int bptnum, int count, int from_tty)
>  			    "crossings of breakpoint %d."),
>  			  count, bptnum);
>  	  }
> -	gdb::observers::breakpoint_modified.notify (b);
> +	gdb::observers::breakpoint_modified.notify (&b);
>  	return;
>        }
>  
> @@ -13122,11 +13120,11 @@ 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)
> @@ -13441,13 +13439,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
> @@ -13632,21 +13630,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 = static_cast<watchpoint &> (bp);
>  
> -	if (wp->val_valid && wp->val != nullptr)
> +	if (wp.val_valid && wp.val != nullptr)
>  	  {
> -	    for (bp_location &loc : bp->locations ())
> +	    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;
>  		}
>  	  }
>        }
> @@ -13734,10 +13732,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;
> @@ -13994,8 +13992,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;
> @@ -14005,9 +14003,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
> @@ -14039,7 +14037,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)
> @@ -14055,15 +14052,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 = 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);
>      }
> @@ -14072,7 +14069,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);
>  	}
> @@ -14082,9 +14079,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 static_cast<tracepoint *> (&t);
>  
>    return NULL;
>  }
> @@ -14096,12 +14093,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 = static_cast<tracepoint &> (b);
>  
> -      if (t->number_on_target == num)
> -	return t;
> +      if (t.number_on_target == num)
> +	return &t;
>      }
>  
>    return NULL;
> @@ -14139,9 +14136,9 @@ get_tracepoint_by_number (const char **arg,
>        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 static_cast<tracepoint *> (&t);
>  
>    gdb_printf ("No tracepoint number %d.\n", tpnum);
>    return NULL;
> @@ -14178,19 +14175,19 @@ save_breakpoints (const char *filename, int from_tty,
>      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 = true;
>  
> -      if (is_tracepoint (tp))
> +      if (is_tracepoint (&tp))
>  	{
>  	  extra_trace_bits = 1;
>  
> @@ -14216,49 +14213,49 @@ 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->print_recreate (&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");
>  
>  	  ui_out_redirect_pop redir (current_uiout, &fp);
> -	  print_command_lines (current_uiout, tp->commands.get (), 2);
> +	  print_command_lines (current_uiout, tp.commands.get (), 2);
>  
>  	  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->has_multiple_locations ())
> +      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)
>  		fp.printf ("disable $bpnum.%d\n", n);
> @@ -14394,12 +14391,12 @@ 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))
> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
> index a03b57734b9d..c0d73d374cb0 100644
> --- a/gdb/breakpoint.h
> +++ b/gdb/breakpoint.h

In patch #7 you added:

  #include "gdbsupport/reference-to-pointer-iterator.h"

Is this still needed after this patch?  I haven't checked, but it feels
like maybe it could be removed now.

Thanks,
Andrew

> @@ -1895,11 +1895,9 @@ using breakpoint_list = intrusive_list<breakpoint>;
>  
>  using breakpoint_iterator = breakpoint_list::iterator;
>  
> -using breakpoint_pointer_iterator = reference_to_pointer_iterator<breakpoint_iterator>;
> -
>  /* Breakpoint linked list range.  */
>  
> -using breakpoint_range = iterator_range<breakpoint_pointer_iterator>;
> +using breakpoint_range = iterator_range<breakpoint_iterator>;
>  
>  /* Return a range to iterate over all breakpoints.  */
>  
> @@ -1919,14 +1917,14 @@ breakpoint_safe_range all_breakpoints_safe ();
>  
>  struct tracepoint_filter
>  {
> -  bool operator() (breakpoint *b)
> -  { return is_tracepoint (b); }
> +  bool operator() (breakpoint &b)
> +  { return is_tracepoint (&b); }
>  };
>  
>  /* Breakpoint linked list iterator, filtering to only keep tracepoints.  */
>  
>  using tracepoint_iterator
> -  = filtered_iterator<breakpoint_pointer_iterator, tracepoint_filter>;
> +  = filtered_iterator<breakpoint_iterator, tracepoint_filter>;
>  
>  /* Breakpoint linked list range, filtering to only keep tracepoints.  */
>  
> diff --git a/gdb/dummy-frame.c b/gdb/dummy-frame.c
> index 961b3ac7a25f..520450125a84 100644
> --- a/gdb/dummy-frame.c
> +++ b/gdb/dummy-frame.c
> @@ -166,8 +166,8 @@ pop_dummy_frame (struct dummy_frame **dummy_ptr)
>  
>    restore_infcall_suspend_state (dummy->caller_state);
>  
> -  for (breakpoint *bp : all_breakpoints_safe ())
> -    if (pop_dummy_frame_bpt (bp, dummy))
> +  for (breakpoint &bp : all_breakpoints_safe ())
> +    if (pop_dummy_frame_bpt (&bp, dummy))
>        break;
>  
>    /* restore_infcall_control_state frees inf_state,
> diff --git a/gdb/guile/scm-breakpoint.c b/gdb/guile/scm-breakpoint.c
> index 2931df265d74..6c6dacb38836 100644
> --- a/gdb/guile/scm-breakpoint.c
> +++ b/gdb/guile/scm-breakpoint.c
> @@ -569,8 +569,8 @@ gdbscm_breakpoints (void)
>  {
>    SCM list = SCM_EOL;
>  
> -  for (breakpoint *bp : all_breakpoints ())
> -    bpscm_build_bp_list (bp, &list);
> +  for (breakpoint &bp : all_breakpoints ())
> +    bpscm_build_bp_list (&bp, &list);
>  
>    return scm_reverse_x (list, SCM_EOL);
>  }
> diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
> index 8a306c6b3318..d11fc64df204 100644
> --- a/gdb/python/py-breakpoint.c
> +++ b/gdb/python/py-breakpoint.c
> @@ -1035,8 +1035,8 @@ gdbpy_breakpoints (PyObject *self, PyObject *args)
>  
>    /* If build_bp_list returns false, it signals an error condition.  In that
>       case abandon building the list and return nullptr.  */
> -  for (breakpoint *bp : all_breakpoints ())
> -    if (!build_bp_list (bp, list.get ()))
> +  for (breakpoint &bp : all_breakpoints ())
> +    if (!build_bp_list (&bp, list.get ()))
>        return nullptr;
>  
>    return PyList_AsTuple (list.get ());
> diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
> index bb4591e3a6ba..b71e5fafc461 100644
> --- a/gdb/python/py-finishbreakpoint.c
> +++ b/gdb/python/py-finishbreakpoint.c
> @@ -416,9 +416,9 @@ bpfinishpy_handle_stop (struct bpstat *bs, int print_frame)
>  {
>    gdbpy_enter enter_py;
>  
> -  for (breakpoint *bp : all_breakpoints_safe ())
> +  for (breakpoint &bp : all_breakpoints_safe ())
>      bpfinishpy_detect_out_scope_cb
> -      (bp, bs == NULL ? NULL : bs->breakpoint_at, true);
> +      (&bp, bs == NULL ? NULL : bs->breakpoint_at, true);
>  }
>  
>  /* Attached to `exit' notifications, triggers all the necessary out of
> @@ -429,8 +429,8 @@ bpfinishpy_handle_exit (struct inferior *inf)
>  {
>    gdbpy_enter enter_py (target_gdbarch ());
>  
> -  for (breakpoint *bp : all_breakpoints_safe ())
> -    bpfinishpy_detect_out_scope_cb (bp, nullptr, true);
> +  for (breakpoint &bp : all_breakpoints_safe ())
> +    bpfinishpy_detect_out_scope_cb (&bp, nullptr, true);
>  }
>  
>  /* Initialize the Python finish breakpoint code.  */
> diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
> index 46f09a7e63ce..59bb086821e5 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -2151,8 +2151,8 @@ svr4_update_solib_event_breakpoint (struct breakpoint *b)
>  static void
>  svr4_update_solib_event_breakpoints (void)
>  {
> -  for (breakpoint *bp : all_breakpoints_safe ())
> -    svr4_update_solib_event_breakpoint (bp);
> +  for (breakpoint &bp : all_breakpoints_safe ())
> +    svr4_update_solib_event_breakpoint (&bp);
>  }
>  
>  /* Create and register solib event breakpoints.  PROBES is an array
> diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
> index fa65e0493720..36cbd1f5bb64 100644
> --- a/gdb/tracepoint.c
> +++ b/gdb/tracepoint.c
> @@ -1520,16 +1520,16 @@ process_tracepoint_on_disconnect (void)
>  
>    /* Check whether we still have pending tracepoint.  If we have, warn the
>       user that pending tracepoint will no longer work.  */
> -  for (breakpoint *b : all_tracepoints ())
> +  for (breakpoint &b : all_tracepoints ())
>      {
> -      if (!b->has_locations ())
> +      if (!b.has_locations ())
>  	{
>  	  has_pending_p = 1;
>  	  break;
>  	}
>        else
>  	{
> -	  for (bp_location &loc1 : b->locations ())
> +	  for (bp_location &loc1 : b.locations ())
>  	    {
>  	      if (loc1.shlib_disabled)
>  		{
> @@ -1571,18 +1571,18 @@ start_tracing (const char *notes)
>    if (tracepoint_range.begin () == tracepoint_range.end ())
>      error (_("No tracepoints defined, not starting trace"));
>  
> -  for (breakpoint *b : tracepoint_range)
> +  for (breakpoint &b : tracepoint_range)
>      {
> -      if (b->enable_state == bp_enabled)
> +      if (b.enable_state == bp_enabled)
>  	any_enabled = 1;
>  
> -      if ((b->type == bp_fast_tracepoint
> +      if ((b.type == bp_fast_tracepoint
>  	   ? may_insert_fast_tracepoints
>  	   : may_insert_tracepoints))
>  	++num_to_download;
>        else
>  	warning (_("May not insert %stracepoints, skipping tracepoint %d"),
> -		 (b->type == bp_fast_tracepoint ? "fast " : ""), b->number);
> +		 (b.type == bp_fast_tracepoint ? "fast " : ""), b.number);
>      }
>  
>    if (!any_enabled)
> @@ -1602,23 +1602,23 @@ start_tracing (const char *notes)
>  
>    target_trace_init ();
>  
> -  for (breakpoint *b : tracepoint_range)
> +  for (breakpoint &b : tracepoint_range)
>      {
> -      struct tracepoint *t = (struct tracepoint *) b;
> +      tracepoint &t = static_cast<tracepoint &> (b);
>        int bp_location_downloaded = 0;
>  
>        /* Clear `inserted' flag.  */
> -      for (bp_location &loc : b->locations ())
> +      for (bp_location &loc : b.locations ())
>  	loc.inserted = 0;
>  
> -      if ((b->type == bp_fast_tracepoint
> +      if ((b.type == bp_fast_tracepoint
>  	   ? !may_insert_fast_tracepoints
>  	   : !may_insert_tracepoints))
>  	continue;
>  
> -      t->number_on_target = 0;
> +      t.number_on_target = 0;
>  
> -      for (bp_location &loc : b->locations ())
> +      for (bp_location &loc : b.locations ())
>  	{
>  	  /* Since tracepoint locations are never duplicated, `inserted'
>  	     flag should be zero.  */
> @@ -1630,14 +1630,14 @@ start_tracing (const char *notes)
>  	  bp_location_downloaded = 1;
>  	}
>  
> -      t->number_on_target = b->number;
> +      t.number_on_target = b.number;
>  
> -      for (bp_location &loc : b->locations ())
> +      for (bp_location &loc : b.locations ())
>  	if (loc.probe.prob != NULL)
>  	  loc.probe.prob->set_semaphore (loc.probe.objfile, loc.gdbarch);
>  
>        if (bp_location_downloaded)
> -	gdb::observers::breakpoint_modified.notify (b);
> +	gdb::observers::breakpoint_modified.notify (&b);
>      }
>  
>    /* Send down all the trace state variables too.  */
> @@ -1709,14 +1709,14 @@ stop_tracing (const char *note)
>  
>    target_trace_stop ();
>  
> -  for (breakpoint *t : all_tracepoints ())
> +  for (breakpoint &t : all_tracepoints ())
>      {
> -      if ((t->type == bp_fast_tracepoint
> +      if ((t.type == bp_fast_tracepoint
>  	   ? !may_insert_fast_tracepoints
>  	   : !may_insert_tracepoints))
>  	continue;
>  
> -      for (bp_location &loc : t->locations ())
> +      for (bp_location &loc : t.locations ())
>  	{
>  	  /* GDB can be totally absent in some disconnected trace scenarios,
>  	     but we don't really care if this semaphore goes out of sync.
> @@ -1887,8 +1887,8 @@ tstatus_command (const char *args, int from_tty)
>  		(long int) (ts->stop_time % 1000000));
>  
>    /* Now report any per-tracepoint status available.  */
> -  for (breakpoint *t : all_tracepoints ())
> -    target_get_tracepoint_status (t, NULL);
> +  for (breakpoint &t : all_tracepoints ())
> +    target_get_tracepoint_status (&t, NULL);
>  }
>  
>  /* Report the trace status to uiout, in a way suitable for MI, and not
> @@ -3042,20 +3042,20 @@ cond_string_is_same (char *str1, char *str2)
>  static struct bp_location *
>  find_matching_tracepoint_location (struct uploaded_tp *utp)
>  {
> -  for (breakpoint *b : all_tracepoints ())
> +  for (breakpoint &b : all_tracepoints ())
>      {
> -      struct tracepoint *t = (struct tracepoint *) b;
> +      tracepoint &t = static_cast<tracepoint &> (b);
>  
> -      if (b->type == utp->type
> -	  && t->step_count == utp->step
> -	  && t->pass_count == utp->pass
> -	  && cond_string_is_same (t->cond_string.get (),
> +      if (b.type == utp->type
> +	  && t.step_count == utp->step
> +	  && t.pass_count == utp->pass
> +	  && cond_string_is_same (t.cond_string.get (),
>  				  utp->cond_string.get ())
>  	  /* FIXME also test actions.  */
>  	  )
>  	{
>  	  /* Scan the locations for an address match.  */
> -	  for (bp_location &loc : b->locations ())
> +	  for (bp_location &loc : b.locations ())
>  	    if (loc.address == utp->addr)
>  	      return &loc;
>  	}
> diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
> index 9e4760618187..a3714fce46fe 100644
> --- a/gdb/tui/tui-winsource.c
> +++ b/gdb/tui/tui-winsource.c
> @@ -625,24 +625,24 @@ tui_source_window_base::update_breakpoint_info
>  	 do with it.  Identify enable/disabled breakpoints as well as
>  	 those that we already hit.  */
>        tui_bp_flags mode = 0;
> -      for (breakpoint *bp : all_breakpoints ())
> +      for (breakpoint &bp : all_breakpoints ())
>  	{
> -	  if (bp == being_deleted)
> +	  if (&bp == being_deleted)
>  	    continue;
>  
> -	  for (bp_location &loc : bp->locations ())
> +	  for (bp_location &loc : bp.locations ())
>  	    {
>  	      if (location_matches_p (&loc, i))
>  		{
> -		  if (bp->enable_state == bp_disabled)
> +		  if (bp.enable_state == bp_disabled)
>  		    mode |= TUI_BP_DISABLED;
>  		  else
>  		    mode |= TUI_BP_ENABLED;
> -		  if (bp->hit_count)
> +		  if (bp.hit_count)
>  		    mode |= TUI_BP_HIT;
> -		  if (bp->first_loc ().cond)
> +		  if (bp.first_loc ().cond)
>  		    mode |= TUI_BP_CONDITIONAL;
> -		  if (bp->type == bp_hardware_breakpoint)
> +		  if (bp.type == bp_hardware_breakpoint)
>  		    mode |= TUI_BP_HARDWARE;
>  		}
>  	    }
> -- 
> 2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations
  2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
                   ` (11 preceding siblings ...)
  2023-05-11 14:48 ` [PATCH 12/12] gdb: remove breakpoint_pointer_iterator Simon Marchi
@ 2023-05-18 15:54 ` Andrew Burgess
  2023-05-18 21:01   ` Simon Marchi
  12 siblings, 1 reply; 28+ messages in thread
From: Andrew Burgess @ 2023-05-18 15:54 UTC (permalink / raw)
  To: Simon Marchi via Gdb-patches, gdb-patches; +Cc: Simon Marchi

Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:

> This series changes two linked lists to use intrusive_list.  There are
> some cleanups before that, and some small fixes that needed to be made
> to some of our iterator wrappers.

I took a look through and left a few comments, but otherwise, this looks
great.

I also ran the testsuite locally, and saw no regressions.

Reviewed-By: Andrew Burgess <aburgess@redhat.com>

Thanks,
Andrew

>
> Simon Marchi (12):
>   gdb: get gdbarch from syscall_catchpoint instead of location
>   gdb: make some breakpoint methods use `this`
>   gdb: constify breakpoint::print_it parameter
>   gdb: add breakpoint "has locations" methods
>   gdb: add breakpoint::first_loc methods
>   gdbsupport: add missing increment/decrement operators to
>     reference_to_pointer_iterator
>   gdb: link breakpoint locations with intrusive_list
>   gdb: remove bp_location_pointer_iterator
>   gdb: link breakpoints with intrusive_list
>   gdbsupport: make basic_safe_iterator::operator* return the same thing
>     as underlying iterator
>   gdbsupport: make filtered_iterator::operator* return the same thing as
>     underlying iterator
>   gdb: remove breakpoint_pointer_iterator
>
>  gdb/ada-lang.c                             |   20 +-
>  gdb/break-catch-exec.c                     |    4 +-
>  gdb/break-catch-fork.c                     |    4 +-
>  gdb/break-catch-load.c                     |   25 +-
>  gdb/break-catch-sig.c                      |    4 +-
>  gdb/break-catch-syscall.c                  |   21 +-
>  gdb/break-catch-throw.c                    |   10 +-
>  gdb/breakpoint.c                           | 1225 ++++++++++----------
>  gdb/breakpoint.h                           |  104 +-
>  gdb/dummy-frame.c                          |    4 +-
>  gdb/elfread.c                              |    8 +-
>  gdb/guile/scm-breakpoint.c                 |    4 +-
>  gdb/infrun.c                               |   11 +-
>  gdb/jit.c                                  |    6 +-
>  gdb/python/py-breakpoint.c                 |    8 +-
>  gdb/python/py-finishbreakpoint.c           |    8 +-
>  gdb/remote.c                               |    4 +-
>  gdb/solib-svr4.c                           |   10 +-
>  gdb/tracectf.c                             |    4 +-
>  gdb/tracefile-tfile.c                      |    4 +-
>  gdb/tracefile.c                            |    6 +-
>  gdb/tracepoint.c                           |  108 +-
>  gdb/tui/tui-winsource.c                    |   16 +-
>  gdbsupport/filtered-iterator.h             |    7 +-
>  gdbsupport/reference-to-pointer-iterator.h |   18 +
>  gdbsupport/safe-iterator.h                 |    6 +-
>  26 files changed, 848 insertions(+), 801 deletions(-)
>
> -- 
> 2.40.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 05/12] gdb: add breakpoint::first_loc methods
  2023-05-18 12:50   ` Andrew Burgess
@ 2023-05-18 17:55     ` Simon Marchi
  2023-05-24 13:00       ` Andrew Burgess
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-18 17:55 UTC (permalink / raw)
  To: Andrew Burgess, Simon Marchi via Gdb-patches; +Cc: Simon Marchi

On 5/18/23 08:50, Andrew Burgess via Gdb-patches wrote:
> Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
>> Add convenience first_loc methods to struct breakpoint (const and
>> non-const overloads).  A subsequent patch changes the list of locations
>> to be an intrusive_list and makes the actual list private, so these
>> spots would need to become something ugly like:
>>
>>   -b->loc
>>   +*b->locations ().begin ()
> 
> It took me longer than I'd like to admit to realise the leading -/+ here
> were indicating that this was an extract from a diff.  Maybe there's
> some way to make it clearer?  Or just drop the first line, I think the
> second line is clear enough (given the description before).

Sorry, I thought I was being smart writing it this way.  I'll change it
to say, these spots would need from:

  b->loc

to something ugly like:

  b->locations ().begin ()

>> @@ -8178,17 +8177,18 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
>>    std::unique_ptr<breakpoint> copy
>>      (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
>>  			       orig->frame_id, thread));
>> +  bp_location &orig_loc = orig->first_loc ();
> 
> Maybe 'const bp_location &' ?

Yes, changed.

> Otherwise, looks good.

Thanks,

Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 07/12] gdb: link breakpoint locations with intrusive_list
  2023-05-18 14:44   ` Andrew Burgess
@ 2023-05-18 18:40     ` Simon Marchi
  2023-05-24 13:04       ` Andrew Burgess
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-18 18:40 UTC (permalink / raw)
  To: Andrew Burgess, Simon Marchi via Gdb-patches

>> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
>> index e9b6574bba77..6ec0f6a11e88 100644
>> --- a/gdb/breakpoint.c
>> +++ b/gdb/breakpoint.c
>> @@ -1049,13 +1049,18 @@ 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 ())
>> +	  auto bp_loc_range = b->locations ();
>> +	  for (auto bp_loc_it = bp_loc_range.begin ();
>> +	       bp_loc_it != bp_loc_range.end ();
>> +	       ++bp_loc_it)
>>  	    {
>> +	      bp_location &loc = **bp_loc_it;
>> +
> 
> You could switch this to:
> 
>   for (const bp_location *loc : b->locations ())
> 
> if we could also do .... (continued below)
> 
>>  	      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;
>> @@ -1065,7 +1070,7 @@ 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 (std::next (bp_loc_it) == bp_loc_range.end () && !force)
> 
> ... this:
> 
>   if (loc == b->last_loc ())
>     throw
> 
> This requires adding 'breakpoint::last_loc ()' but we already have
> 'breakpoint::first_loc ()' so that doesn't seem crazy, and I think the
> resulting code would be easier to read maybe?
Yeah, that's a good idea.  It makes the code read just like the comment
does (if the loc is the last loc), which is a plus for readability.

Note that I used &b->last_loc (), as I made last_loc return a reference
(like first_loc).

>> @@ -4518,28 +4510,23 @@ bpstat_locno (const bpstat *bs)
>>    const struct breakpoint *b = bs->breakpoint_at;
>>    const struct bp_location *bl = bs->bp_location_at.get ();
>>  
>> -  int locno = 0;
>> -
>>    if (b != nullptr && b->has_multiple_locations ())
>>      {
>> -      const bp_location *bl_i;
>> -
>> -      for (bl_i = b->loc;
>> -	   bl_i != bl && bl_i->next != nullptr;
>> -	   bl_i = bl_i->next)
>> -	locno++;
>> +      int locno = 1;
>>  
>> -      if (bl_i == bl)
>> -	locno++;
>> -      else
>> +      for (bp_location *loc : b->locations ())
>>  	{
>> -	  warning (_("location number not found for breakpoint %d address %s."),
>> -		   b->number, paddress (bl->gdbarch, bl->address));
>> -	  locno = 0;
>> +	  if (bl == loc)
>> +	    return locno;
>> +
>> +	  ++locno;
>>  	}
>> +
>> +      warning (_("location number not found for breakpoint %d address %s."),
>> +	       b->number, paddress (bl->gdbarch, bl->address));
>>      }
> 
> I might be missing something here, but could this code be simplified by
> using std::distance in some way?  We already use std::distance later in
> this patch to count the total number of locations, so it feels like this
> should work.
> 
> I know that the current code allows for the possibility that the
> location (from the bp_stat) might not be in the location list of the
> breakpoint (from bp_stat), but, surely that can't happen, right?  Surely
> the location was originally found by looking through the locations of
> the breakpoint... so it should be certain that we find the location.
> 
> I guess maybe we could remove the breakpoint_at from bp_stat, and just
> use the owner of the bp_location_at variable, that way we could be
> certain about all this...
> 
> Either way, there's nothing wrong with your code above, just wondering
> if we can make it tighter...

I'm not sure about whether we are sure that the location is in its
parent location list, there is perhaps some corner cases about handling
a breakpoint hit event on a location that has been removed since.
However, I see that before putting a location in the moribund_locations
vector, we set its owner to NULL.  So if the owner field is non-NULL, it
should be safe to assume the location is in the list.

I don't think it's easy to use std::distance right now though, because
with the reference_to_pointer_iterator wrapper, we can't go from item to
iterator in O(1).  We can if we had access to the intrusive_list
directly, since it has an "iterator_to" method.

In any case, I will not make such a change in this patch to avoid mixing
things together.  I tried to make this patch a straightforward
translation without any unnecessary algorithmic changes.  I'll check if
it becomes possible at the end of the series though.

>> @@ -8312,12 +8299,8 @@ code_breakpoint::add_location (const symtab_and_line &sal)
>>  						sal.pspace);
>>  
>>    /* Sort the locations by their ADDRESS.  */
>> -  new_loc = allocate_location ();
>> -  for (tmp = &(loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
>> -       tmp = &((*tmp)->next))
>> -    ;
>> -  new_loc->next = *tmp;
>> -  *tmp = new_loc;
>> +  bp_location *new_loc = this->allocate_location ();
>> +  breakpoint::add_location (*new_loc, adjusted_address);
> 
> I notice here the code basically does:
> 
>   1. Create bp_location object,
>   2. Add bp_location object to list,
>   3. Initialise bp_location object.
> 
> We have to pass adjusted_address through because the address of new_loc
> has not yet been initialised.
> 
> Could we reorder things so we:
> 
>   1. Create bp_location object,
>   2. Initialise bp_location object,
>   3. Add bp_location object to list.
> 
> The benefit I think would be that we can remove these two functions:
> 
>   void breakpoint::add_location (bp_location &loc);
>   void breakpoint::add_location (bp_location &loc, CORE_ADDR address);
> 
> And we replace them with one function:
> 
>   void breakpoint::add_location (bp_location &loc, bool sorted = false);
> 
> The implementation would be free to use 'loc.address' for the sorting.

Good idea, I will do that.  That seems like a minor / low-risk change,
so I'll do it in this patch.

For consistency, I moved the "add_location" call after setting
loc->address in update_watchpoint as well, even though it wouldn't
matter in that case.

>> @@ -633,30 +630,71 @@ struct breakpoint
>>    /* Allocate a location for this breakpoint.  */
>>    virtual struct bp_location *allocate_location ();
>>  
>> +  /* Return a range of this breakpoint's locations.  */
>> +  bp_location_range locations () const;
>> +
>> +  /* Add LOC at the end of the location list of this breakpoint.
>> +
>> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
>> +     in a location list.  */
>> +  void add_location (bp_location &loc);
>> +
>> +  /* Add LOC in the location list of this breakpoint, sorted by address.
>> +
>> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
>> +     in a location list.  */
>> +  void add_location (bp_location &loc, CORE_ADDR address);
> 
> It would be nice for the comment to mention what ADDRESS means here.
> However, my earlier comments for where this function is used might mean
> this is no longer needed in this form.

Yes, this gets removed.

Thanks,

Simon


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 12/12] gdb: remove breakpoint_pointer_iterator
  2023-05-18 15:53   ` Andrew Burgess
@ 2023-05-18 18:44     ` Simon Marchi
  2023-05-18 20:59       ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-18 18:44 UTC (permalink / raw)
  To: Andrew Burgess, Simon Marchi via Gdb-patches

>> @@ -3055,12 +3052,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 = static_cast<watchpoint &> (bpt);
> 
> Could possibly use gdb::checked_static_cast here?  And in other places
> throughout this patch?

checked_static_cast doesn't work with references though... so I would
have to write:

  watchpoint &w = *gdb::checked_static_cast<watchpoint *> (&bpt);

Do you think it's possible to make checked_static_cast work for
references?  I'll give it a try.

>> diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
>> index a03b57734b9d..c0d73d374cb0 100644
>> --- a/gdb/breakpoint.h
>> +++ b/gdb/breakpoint.h
> 
> In patch #7 you added:
> 
>   #include "gdbsupport/reference-to-pointer-iterator.h"
> 
> Is this still needed after this patch?  I haven't checked, but it feels
> like maybe it could be removed now.

Yep removed.

Simon


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 12/12] gdb: remove breakpoint_pointer_iterator
  2023-05-18 18:44     ` Simon Marchi
@ 2023-05-18 20:59       ` Simon Marchi
  0 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-18 20:59 UTC (permalink / raw)
  To: Simon Marchi, Andrew Burgess, Simon Marchi via Gdb-patches

On 5/18/23 14:44, Simon Marchi via Gdb-patches wrote:
>>> @@ -3055,12 +3052,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 = static_cast<watchpoint &> (bpt);
>>
>> Could possibly use gdb::checked_static_cast here?  And in other places
>> throughout this patch?
> 
> checked_static_cast doesn't work with references though... so I would
> have to write:
> 
>   watchpoint &w = *gdb::checked_static_cast<watchpoint *> (&bpt);
> 
> Do you think it's possible to make checked_static_cast work for
> references?  I'll give it a try.

I sent a patch to make checked_static_cast work with references here:

https://inbox.sourceware.org/gdb-patches/20230518205737.403656-1-simon.marchi@efficios.com/T/#u

I put that patch under this series, and modified this patch (patch 12)
to use checked_static_cast.

Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations
  2023-05-18 15:54 ` [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Andrew Burgess
@ 2023-05-18 21:01   ` Simon Marchi
  2023-05-25 14:01     ` Simon Marchi
  0 siblings, 1 reply; 28+ messages in thread
From: Simon Marchi @ 2023-05-18 21:01 UTC (permalink / raw)
  To: Andrew Burgess, Simon Marchi via Gdb-patches; +Cc: Simon Marchi

On 5/18/23 11:54, Andrew Burgess via Gdb-patches wrote:
> Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:
> 
>> This series changes two linked lists to use intrusive_list.  There are
>> some cleanups before that, and some small fixes that needed to be made
>> to some of our iterator wrappers.
> 
> I took a look through and left a few comments, but otherwise, this looks
> great.
> 
> I also ran the testsuite locally, and saw no regressions.
> 
> Reviewed-By: Andrew Burgess <aburgess@redhat.com>

Thanks for reviewing.  Since the adjustments were mostly trivial, I will
push the modified version of this series once the checked_static_cast
for references patches (or an equivalent) is in.

Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 05/12] gdb: add breakpoint::first_loc methods
  2023-05-18 17:55     ` Simon Marchi
@ 2023-05-24 13:00       ` Andrew Burgess
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Burgess @ 2023-05-24 13:00 UTC (permalink / raw)
  To: Simon Marchi, Simon Marchi via Gdb-patches; +Cc: Simon Marchi

Simon Marchi <simark@simark.ca> writes:

> On 5/18/23 08:50, Andrew Burgess via Gdb-patches wrote:
>> Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:
>> 
>>> Add convenience first_loc methods to struct breakpoint (const and
>>> non-const overloads).  A subsequent patch changes the list of locations
>>> to be an intrusive_list and makes the actual list private, so these
>>> spots would need to become something ugly like:
>>>
>>>   -b->loc
>>>   +*b->locations ().begin ()
>> 
>> It took me longer than I'd like to admit to realise the leading -/+ here
>> were indicating that this was an extract from a diff.  Maybe there's
>> some way to make it clearer?  Or just drop the first line, I think the
>> second line is clear enough (given the description before).
>
> Sorry, I thought I was being smart writing it this way.  I'll change it
> to say, these spots would need from:
>
>   b->loc
>
> to something ugly like:
>
>   b->locations ().begin ()

Looks great.

Thanks,
Andrew

>
>>> @@ -8178,17 +8177,18 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
>>>    std::unique_ptr<breakpoint> copy
>>>      (new_momentary_breakpoint (orig->gdbarch, type, orig->pspace,
>>>  			       orig->frame_id, thread));
>>> +  bp_location &orig_loc = orig->first_loc ();
>> 
>> Maybe 'const bp_location &' ?
>
> Yes, changed.
>
>> Otherwise, looks good.
>
> Thanks,
>
> Simon


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 07/12] gdb: link breakpoint locations with intrusive_list
  2023-05-18 18:40     ` Simon Marchi
@ 2023-05-24 13:04       ` Andrew Burgess
  0 siblings, 0 replies; 28+ messages in thread
From: Andrew Burgess @ 2023-05-24 13:04 UTC (permalink / raw)
  To: Simon Marchi, Simon Marchi via Gdb-patches

Simon Marchi <simon.marchi@efficios.com> writes:

>>> diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
>>> index e9b6574bba77..6ec0f6a11e88 100644
>>> --- a/gdb/breakpoint.c
>>> +++ b/gdb/breakpoint.c
>>> @@ -1049,13 +1049,18 @@ 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 ())
>>> +	  auto bp_loc_range = b->locations ();
>>> +	  for (auto bp_loc_it = bp_loc_range.begin ();
>>> +	       bp_loc_it != bp_loc_range.end ();
>>> +	       ++bp_loc_it)
>>>  	    {
>>> +	      bp_location &loc = **bp_loc_it;
>>> +
>> 
>> You could switch this to:
>> 
>>   for (const bp_location *loc : b->locations ())
>> 
>> if we could also do .... (continued below)
>> 
>>>  	      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;
>>> @@ -1065,7 +1070,7 @@ 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 (std::next (bp_loc_it) == bp_loc_range.end () && !force)
>> 
>> ... this:
>> 
>>   if (loc == b->last_loc ())
>>     throw
>> 
>> This requires adding 'breakpoint::last_loc ()' but we already have
>> 'breakpoint::first_loc ()' so that doesn't seem crazy, and I think the
>> resulting code would be easier to read maybe?
> Yeah, that's a good idea.  It makes the code read just like the comment
> does (if the loc is the last loc), which is a plus for readability.
>
> Note that I used &b->last_loc (), as I made last_loc return a reference
> (like first_loc).
>
>>> @@ -4518,28 +4510,23 @@ bpstat_locno (const bpstat *bs)
>>>    const struct breakpoint *b = bs->breakpoint_at;
>>>    const struct bp_location *bl = bs->bp_location_at.get ();
>>>  
>>> -  int locno = 0;
>>> -
>>>    if (b != nullptr && b->has_multiple_locations ())
>>>      {
>>> -      const bp_location *bl_i;
>>> -
>>> -      for (bl_i = b->loc;
>>> -	   bl_i != bl && bl_i->next != nullptr;
>>> -	   bl_i = bl_i->next)
>>> -	locno++;
>>> +      int locno = 1;
>>>  
>>> -      if (bl_i == bl)
>>> -	locno++;
>>> -      else
>>> +      for (bp_location *loc : b->locations ())
>>>  	{
>>> -	  warning (_("location number not found for breakpoint %d address %s."),
>>> -		   b->number, paddress (bl->gdbarch, bl->address));
>>> -	  locno = 0;
>>> +	  if (bl == loc)
>>> +	    return locno;
>>> +
>>> +	  ++locno;
>>>  	}
>>> +
>>> +      warning (_("location number not found for breakpoint %d address %s."),
>>> +	       b->number, paddress (bl->gdbarch, bl->address));
>>>      }
>> 
>> I might be missing something here, but could this code be simplified by
>> using std::distance in some way?  We already use std::distance later in
>> this patch to count the total number of locations, so it feels like this
>> should work.
>> 
>> I know that the current code allows for the possibility that the
>> location (from the bp_stat) might not be in the location list of the
>> breakpoint (from bp_stat), but, surely that can't happen, right?  Surely
>> the location was originally found by looking through the locations of
>> the breakpoint... so it should be certain that we find the location.
>> 
>> I guess maybe we could remove the breakpoint_at from bp_stat, and just
>> use the owner of the bp_location_at variable, that way we could be
>> certain about all this...
>> 
>> Either way, there's nothing wrong with your code above, just wondering
>> if we can make it tighter...
>
> I'm not sure about whether we are sure that the location is in its
> parent location list, there is perhaps some corner cases about handling
> a breakpoint hit event on a location that has been removed since.
> However, I see that before putting a location in the moribund_locations
> vector, we set its owner to NULL.  So if the owner field is non-NULL, it
> should be safe to assume the location is in the list.
>
> I don't think it's easy to use std::distance right now though, because
> with the reference_to_pointer_iterator wrapper, we can't go from item to
> iterator in O(1).  We can if we had access to the intrusive_list
> directly, since it has an "iterator_to" method.
>
> In any case, I will not make such a change in this patch to avoid mixing
> things together.  I tried to make this patch a straightforward
> translation without any unnecessary algorithmic changes.  I'll check if
> it becomes possible at the end of the series though.

Not a problem, I did wonder if there was going to be some reason why
this wasn't a helpful suggestion :)

Thanks for looking into it though.

Andrew

>
>>> @@ -8312,12 +8299,8 @@ code_breakpoint::add_location (const symtab_and_line &sal)
>>>  						sal.pspace);
>>>  
>>>    /* Sort the locations by their ADDRESS.  */
>>> -  new_loc = allocate_location ();
>>> -  for (tmp = &(loc); *tmp != NULL && (*tmp)->address <= adjusted_address;
>>> -       tmp = &((*tmp)->next))
>>> -    ;
>>> -  new_loc->next = *tmp;
>>> -  *tmp = new_loc;
>>> +  bp_location *new_loc = this->allocate_location ();
>>> +  breakpoint::add_location (*new_loc, adjusted_address);
>> 
>> I notice here the code basically does:
>> 
>>   1. Create bp_location object,
>>   2. Add bp_location object to list,
>>   3. Initialise bp_location object.
>> 
>> We have to pass adjusted_address through because the address of new_loc
>> has not yet been initialised.
>> 
>> Could we reorder things so we:
>> 
>>   1. Create bp_location object,
>>   2. Initialise bp_location object,
>>   3. Add bp_location object to list.
>> 
>> The benefit I think would be that we can remove these two functions:
>> 
>>   void breakpoint::add_location (bp_location &loc);
>>   void breakpoint::add_location (bp_location &loc, CORE_ADDR address);
>> 
>> And we replace them with one function:
>> 
>>   void breakpoint::add_location (bp_location &loc, bool sorted = false);
>> 
>> The implementation would be free to use 'loc.address' for the sorting.
>
> Good idea, I will do that.  That seems like a minor / low-risk change,
> so I'll do it in this patch.
>
> For consistency, I moved the "add_location" call after setting
> loc->address in update_watchpoint as well, even though it wouldn't
> matter in that case.
>
>>> @@ -633,30 +630,71 @@ struct breakpoint
>>>    /* Allocate a location for this breakpoint.  */
>>>    virtual struct bp_location *allocate_location ();
>>>  
>>> +  /* Return a range of this breakpoint's locations.  */
>>> +  bp_location_range locations () const;
>>> +
>>> +  /* Add LOC at the end of the location list of this breakpoint.
>>> +
>>> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
>>> +     in a location list.  */
>>> +  void add_location (bp_location &loc);
>>> +
>>> +  /* Add LOC in the location list of this breakpoint, sorted by address.
>>> +
>>> +     LOC must have this breakpoint as its owner.  LOC must not already be linked
>>> +     in a location list.  */
>>> +  void add_location (bp_location &loc, CORE_ADDR address);
>> 
>> It would be nice for the comment to mention what ADDRESS means here.
>> However, my earlier comments for where this function is used might mean
>> this is no longer needed in this form.
>
> Yes, this gets removed.
>
> Thanks,
>
> Simon


^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations
  2023-05-18 21:01   ` Simon Marchi
@ 2023-05-25 14:01     ` Simon Marchi
  0 siblings, 0 replies; 28+ messages in thread
From: Simon Marchi @ 2023-05-25 14:01 UTC (permalink / raw)
  To: Andrew Burgess, Simon Marchi via Gdb-patches; +Cc: Simon Marchi

On 5/18/23 17:01, Simon Marchi via Gdb-patches wrote:
> On 5/18/23 11:54, Andrew Burgess via Gdb-patches wrote:
>> Simon Marchi via Gdb-patches <gdb-patches@sourceware.org> writes:
>>
>>> This series changes two linked lists to use intrusive_list.  There are
>>> some cleanups before that, and some small fixes that needed to be made
>>> to some of our iterator wrappers.
>>
>> I took a look through and left a few comments, but otherwise, this looks
>> great.
>>
>> I also ran the testsuite locally, and saw no regressions.
>>
>> Reviewed-By: Andrew Burgess <aburgess@redhat.com>
> 
> Thanks for reviewing.  Since the adjustments were mostly trivial, I will
> push the modified version of this series once the checked_static_cast
> for references patches (or an equivalent) is in.

I pushed this.

Simon

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2023-05-25 14:01 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-11 14:48 [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Simon Marchi
2023-05-11 14:48 ` [PATCH 01/12] gdb: get gdbarch from syscall_catchpoint instead of location Simon Marchi
2023-05-15  9:12   ` Alexandra Petlanova Hajkova
2023-05-11 14:48 ` [PATCH 02/12] gdb: make some breakpoint methods use `this` Simon Marchi
2023-05-15 13:12   ` Alexandra Petlanova Hajkova
2023-05-15 18:25     ` Simon Marchi
2023-05-11 14:48 ` [PATCH 03/12] gdb: constify breakpoint::print_it parameter Simon Marchi
2023-05-11 14:48 ` [PATCH 04/12] gdb: add breakpoint "has locations" methods Simon Marchi
2023-05-11 14:48 ` [PATCH 05/12] gdb: add breakpoint::first_loc methods Simon Marchi
2023-05-18 12:50   ` Andrew Burgess
2023-05-18 17:55     ` Simon Marchi
2023-05-24 13:00       ` Andrew Burgess
2023-05-11 14:48 ` [PATCH 06/12] gdbsupport: add missing increment/decrement operators to reference_to_pointer_iterator Simon Marchi
2023-05-11 14:48 ` [PATCH 07/12] gdb: link breakpoint locations with intrusive_list Simon Marchi
2023-05-18 14:44   ` Andrew Burgess
2023-05-18 18:40     ` Simon Marchi
2023-05-24 13:04       ` Andrew Burgess
2023-05-11 14:48 ` [PATCH 08/12] gdb: remove bp_location_pointer_iterator Simon Marchi
2023-05-11 14:48 ` [PATCH 09/12] gdb: link breakpoints with intrusive_list Simon Marchi
2023-05-11 14:48 ` [PATCH 10/12] gdbsupport: make basic_safe_iterator::operator* return the same thing as underlying iterator Simon Marchi
2023-05-11 14:48 ` [PATCH 11/12] gdbsupport: make filtered_iterator::operator* " Simon Marchi
2023-05-11 14:48 ` [PATCH 12/12] gdb: remove breakpoint_pointer_iterator Simon Marchi
2023-05-18 15:53   ` Andrew Burgess
2023-05-18 18:44     ` Simon Marchi
2023-05-18 20:59       ` Simon Marchi
2023-05-18 15:54 ` [PATCH 00/12] Use intrusive_list for breakpoints and breakpoint locations Andrew Burgess
2023-05-18 21:01   ` Simon Marchi
2023-05-25 14:01     ` Simon Marchi

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