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; }
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);
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)
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)
#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)
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>>;