Simon's changes

Change-Id: Ieee3c051b9b4bc949262ecbc44e1db2ad3bebe38
This commit is contained in:
Simon Marchi 2026-04-30 11:58:47 -04:00
parent b22fc8ee9b
commit e8d35bb501
2 changed files with 73 additions and 97 deletions

View 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)

View file

@ -21,35 +21,21 @@
#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.
/* An iterator base class that defines pretty much everything except how to
obtain the next element, given the current element.
Instead of factoring out a base class, we could use something like this:
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, 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>
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. */
/* Iterator that follows the `next` field of a type. */
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)
template <typename T>
struct next_field_incrementer
{
T *operator() (T &item) const noexcept
{
}
next_iterator () = default;
self_type &operator++ ()
{
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>>;