]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Simon's changes users/simark/next-iterator
authorSimon Marchi <simon.marchi@efficios.com>
Thu, 30 Apr 2026 15:58:47 +0000 (11:58 -0400)
committerSimon Marchi <simon.marchi@efficios.com>
Thu, 30 Apr 2026 16:18:06 +0000 (12:18 -0400)
Change-Id: Ieee3c051b9b4bc949262ecbc44e1db2ad3bebe38

gdb/block.h
gdbsupport/next-iterator.h

index 11000b924efda1f7887488e77cd4394d425fd490..ae7f710b5707f0b98f2b0c6c9537fe9156f04ac3 100644 (file)
@@ -108,54 +108,6 @@ struct blockranges
 
 struct block : public allocate_on_obstack<block>
 {
-  /* Variant of next_iterator using the superblock field instead of next.  */
-  struct superblock_iterator : base_next_iterator<const block>
-  {
-    typedef superblock_iterator self_type;
-
-    explicit superblock_iterator (value_type item)
-      : base_next_iterator (item)
-    {
-    }
-
-    superblock_iterator () = default;
-
-    self_type &operator++ ()
-    {
-      this->m_item = this->m_item->superblock ();
-      return *this;
-    }
-  };
-
-  /* Variant of next_iterator using the superblock field instead of next.  */
-  struct function_block_iterator : base_next_iterator<const block>
-  {
-    typedef function_block_iterator self_type;
-
-    explicit function_block_iterator (value_type item)
-      : base_next_iterator (item->is_global_block () || item->is_static_block ()
-                           ? nullptr : item)
-    {
-    }
-
-    function_block_iterator () = default;
-
-    self_type &operator++ ()
-    {
-      if (this->m_item->function () != nullptr)
-       {
-         this->m_item = nullptr;
-         return *this;
-       }
-
-      this->m_item = this->m_item->superblock ();
-      return *this;
-    }
-  };
-
-  using superblock_range = iterator_range<superblock_iterator>;
-  using function_block_range = iterator_range<function_block_iterator>;
-
   /* Return this block's start address.  */
   CORE_ADDR start () const
   { return m_start; }
@@ -354,6 +306,20 @@ struct block : public allocate_on_obstack<block>
 
   struct dynamic_prop *static_link () const;
 
+  /* Iterator and range type to iterate over this block and its superblocks.  */
+
+  struct superblock_incrementer
+  {
+    const block *operator() (const block &b) const noexcept
+    { return b.superblock (); }
+  };
+
+  using superblock_iterator
+    = base_next_iterator<const block, superblock_incrementer>;
+  using superblock_range = iterator_range<superblock_iterator>;
+
+  /* Return a range to iterate over this block and its superblocks.  */
+
   superblock_range super_blocks () const
   {
     superblock_range::iterator begin (this);
@@ -361,13 +327,41 @@ struct block : public allocate_on_obstack<block>
     return superblock_range (std::move (begin));
   }
 
+  /* Iterator and range type to iterate over this block and its superblocks
+     within a function.  */
+
+  struct function_block_incrementer
+  {
+    const block *operator() (const block &b) const noexcept
+    {
+      /* If the current item is the function-defining block, we're done.  */
+      if (b.function () != nullptr)
+       return nullptr;
+
+      return b.superblock ();
+    }
+  };
+
+  using function_block_iterator
+    = base_next_iterator<const block, function_block_incrementer>;
+  using function_block_range = iterator_range<function_block_iterator>;
+
+  /* Assuming that this is a block within a function, return a range to iterate
+     over this block and its superblocks up to that function's block.
+
+     This method must not be called on global or static blocks.  */
+
   function_block_range function_blocks () const
   {
-    function_block_range::iterator begin (this);
+    gdb_assert (!this->is_global_block ());
+    gdb_assert (!this->is_static_block ());
 
-    return function_block_range (std::move (begin));
+    return function_block_range (function_block_iterator (this));
   }
 
+  /* Same as block::super_blocks, except that if B is nullptr, return an empty
+     range.  */
+
   static superblock_range super_blocks (const block *b)
   {
     if (b == nullptr)
@@ -376,6 +370,9 @@ struct block : public allocate_on_obstack<block>
     return b->super_blocks ();
   }
 
+  /* Same as block::function_blocks, except that if B is nullptr, return an
+     empty range.  */
+
   static function_block_range function_blocks (const block *b)
   {
     if (b == nullptr)
index 1dee941a252fd8b0637555e19a728a4b18a600bc..d5b96ae680ad2afa34067e6938bc39cdea347950 100644 (file)
 
 #include "gdbsupport/iterator-range.h"
 
-/* An iterator base class for iterating over a field of a type.  In order to
-   form a functioning iterator, classes inheriting this should define an
-   operator++, which determines the actual field that is iterated over.
-
-   Instead of factoring out a base class, we could use something like this:
-
-     template<typename T, auto F = &T::next>
-     struct next_iterator
-     {
-       ...
-       self_type &operator++ ()
-       {
-        m_item = m_item->*F;
-        return *this;
-       }
-       ...
-     }
-
-  but that has the drawback that it doesn't work with incomplete T.  */
-
-template<typename T>
+/* An iterator base class that defines pretty much everything except how to
+   obtain the next element, given the current element.
+
+   Increment is a functor that takes a T& and returns the next T* in the
+   sequence.  It shall return nullptr when there are no more elements.  */
+
+template<typename T, typename Incrementer>
 struct base_next_iterator
 {
-  typedef base_next_iterator self_type;
-  typedef T *value_type;
-  typedef T *&reference;
-  typedef T **pointer;
-  typedef std::forward_iterator_tag iterator_category;
-  typedef int difference_type;
+  using self_type = base_next_iterator<T, Incrementer>;
+  using value_type = T *;
+  using reference = T *&;
+  using pointer = T **;
+  using iterator_category = std::forward_iterator_tag;
+  using difference_type = int;
 
   explicit base_next_iterator (T *item)
     : m_item (item)
@@ -77,37 +63,30 @@ struct base_next_iterator
     return m_item != other.m_item;
   }
 
-protected:
+  self_type &operator++ ()
+  {
+    gdb_assert (m_item != nullptr);
+    this->m_item = Incrementer () (*m_item);
+    return *this;
+  }
 
+private:
   T *m_item;
 };
 
-/* An iterator that uses the 'next' field of a type to iterate.  This
-   can be used with various GDB types that are stored as linked
-   lists.  */
-
-template<typename T>
-struct next_iterator : base_next_iterator<T> {
-  typedef next_iterator self_type;
-  typedef T *value_type;
-  typedef T *&reference;
-  typedef T **pointer;
-
-  explicit next_iterator (T *item)
-    : base_next_iterator<T> (item)
-  {
-  }
+/* Iterator that follows the `next` field of a type.  */
 
-  next_iterator () = default;
-
-  self_type &operator++ ()
+template <typename T>
+struct next_field_incrementer
+{
+  T *operator() (T &item) const noexcept
   {
-    this->m_item = this->m_item->next;
-    return *this;
+    return item.next;
   }
 };
 
-/* A convenience wrapper to make a range type around a next_iterator.  */
+template <typename T>
+using next_iterator = base_next_iterator<T, next_field_incrementer<T>>;
 
 template <typename T>
 using next_range = iterator_range<next_iterator<T>>;