[08/10] Use block::block_and_superblocks

Message ID 20260501124504.2233495-9-tdevries@suse.de
State New
Headers
Series Add superblocks range loops |

Commit Message

Tom de Vries May 1, 2026, 12:45 p.m. UTC
  Add uses of block::block_and_superblocks.
---
 gdb/ada-lang.c                    | 18 ++++------
 gdb/blockframe.c                  | 11 +++---
 gdb/compile/compile-object-load.c |  8 +++--
 gdb/cp-namespace.c                |  6 ++--
 gdb/cp-support.c                  |  8 ++---
 gdb/d-namespace.c                 |  6 ++--
 gdb/dwarf2/line-program.c         | 24 +++++--------
 gdb/infrun.c                      | 10 +++---
 gdb/inline-frame.c                | 45 +++++++++++-------------
 gdb/linespec.c                    |  7 ++--
 gdb/symmisc.c                     |  9 +++--
 gdb/symtab.c                      | 58 ++++++++++++++++++-------------
 12 files changed, 101 insertions(+), 109 deletions(-)
  

Comments

Tom Tromey May 8, 2026, 7:41 p.m. UTC | #1
>>>>> "Tom" == Tom de Vries <tdevries@suse.de> writes:

Tom> diff --git a/gdb/blockframe.c b/gdb/blockframe.c
Tom> index 8aafa6ffe57..5c981748cbc 100644
Tom> --- a/gdb/blockframe.c
Tom> +++ b/gdb/blockframe.c
Tom> @@ -69,13 +69,14 @@ get_frame_block (const frame_info_ptr &frame, CORE_ADDR *addr_in_block)
 
Tom>    inline_count = frame_inlined_callees (frame);
 
Tom> -  while (inline_count > 0)
Tom> +  auto range = bl->block_and_superblocks ();
Tom> +  for (auto b = range.begin (); b != range.end (); ++b, bl = *b)
Tom>      {
Tom> -      if (bl->inlined_p ())
Tom> -	inline_count--;
Tom> +      if (inline_count <= 0)
Tom> +	break;
 
Tom> -      bl = bl->superblock ();
Tom> -      gdb_assert (bl != NULL);
Tom> +      if ((*b)->inlined_p ())
Tom> +	inline_count--;
Tom>      }

Tom>    return bl;

I think this particular change is less clear than the code it replaces.

Tom> diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
Tom> index b9da1b4799f..227ec01aec9 100644
Tom> --- a/gdb/dwarf2/line-program.c
Tom> +++ b/gdb/dwarf2/line-program.c
Tom> @@ -373,21 +373,15 @@ dwarf_find_and_extend_inline_block_range (dwarf2_cu *cu,
Tom>       the child of a non-inline block.  This is new inline block is our
Tom>       candidate for extending.  */
Tom>    struct block *block = nullptr;
Tom> -  for (const struct block *b = it->second;
Tom> -       b != nullptr;
Tom> -       b = b->superblock ())
Tom> -    {
Tom> -      if (b->function () != nullptr && b->inlined_p ())
Tom> -	{
Tom> -	  if (b->superblock () != nullptr
Tom> -	      && b->superblock ()->function () != nullptr
Tom> -	      && !b->superblock ()->inlined_p ())
Tom> -	    {
Tom> -	      block = const_cast<struct block *> (b);
Tom> -	      break;
Tom> -	    }
Tom> -	}
Tom> -    }
Tom> +  for (auto b : block::block_and_superblocks (it->second))
Tom> +    if (b->inlined_p ()
Tom> +	&& b->superblock () != nullptr
Tom> +	&& b->superblock ()->function () != nullptr
Tom> +	&& !b->superblock ()->inlined_p ())
Tom> +      {
Tom> +	block = const_cast<struct block *> (b);
Tom> +	break;
Tom> +      }

It took me a while to figure out why you removed the check of
'function', but it's because inlined_p already does this check.

It's helpful to call out this kind of change or to put it in a separate
patch.

Tom> --- a/gdb/infrun.c
Tom> +++ b/gdb/infrun.c
Tom> @@ -8261,13 +8261,15 @@ process_event_stop_test (struct execution_control_state *ecs)
Tom>        const struct block *prev
Tom>  	= block_for_pc (ecs->event_thread->control.step_frame_id.code_addr);
Tom>        const struct block *curr = block_for_pc (ecs->event_thread->stop_pc ());
Tom> -      while (curr != nullptr && !curr->contains (prev))
Tom> +      for (auto b : block::block_and_superblocks (curr))
Tom>  	{

This code would be clearer if 'curr' were eliminated entirely.
In this case I had to go see if it was used after the loop.

Tom> +  auto range = block::block_and_superblocks (cur_block);
Tom> +  for (auto b = range.begin (); b != range.end (); ++b, cur_block = *b)

This is another case where the result is harder to reason about that the
earlier code.

Maybe it could be salvaged somehow by assigning at the breaks, not sure.

Tom> diff --git a/gdb/symmisc.c b/gdb/symmisc.c
Tom> index 89374bd8a2f..f882f3add17 100644
Tom> --- a/gdb/symmisc.c
Tom> +++ b/gdb/symmisc.c
Tom> @@ -961,11 +961,10 @@ block_depth (const struct block *block)
Tom>  {
Tom>    int i = 0;
 
Tom> -  while ((block = block->superblock ()) != NULL)
Tom> -    {
Tom> -      i++;
Tom> -    }
Tom> -  return i;
Tom> +  for (auto b [[maybe_unused]]: block::block_and_superblocks (block))
Tom> +    i++;
Tom> +
Tom> +  return i - 1;

Can this just be std::count?

Also this doesn't have to handle the case where the initial block is
nullptr.

Tom> +	  auto range = block::block_and_superblocks (bl);
Tom> +	  for (auto b = range.begin (); b != range.end (); ++b, bl = *b)

Like the earlier ones.  I don't think multiple assignments like this
make it clearer or easier to work with.

Tom
  

Patch

diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 71a338ce17e..6eb928b445d 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5402,17 +5402,15 @@  ada_add_local_symbols (std::vector<struct block_symbol> &result,
 		       const lookup_name_info &lookup_name,
 		       const struct block *block, domain_search_flags domain)
 {
-  while (block != NULL)
+  for (auto b : block::block_and_superblocks (block))
     {
-      ada_add_block_symbols (result, block, lookup_name, domain, NULL);
+      ada_add_block_symbols (result, b, lookup_name, domain, nullptr);
 
       /* If we found a non-function match, assume that's the one.  We
 	 only check this when finding a function boundary, so that we
 	 can accumulate all results from intervening blocks first.  */
-      if (block->function () != nullptr && is_nonfunction (result))
+      if (b->function () != nullptr && is_nonfunction (result))
 	return;
-
-      block = block->superblock ();
     }
 }
 
@@ -13825,9 +13823,7 @@  class ada_language : public language_defn
     /* Search upwards from currently selected frame (so that we can
        complete on local vars.  */
 
-    for (const block *b = get_selected_block (0);
-	 b != nullptr;
-	 b = b->superblock ())
+    for (auto b : block::block_and_superblocks (get_selected_block (0)))
       {
 	if (b->is_static_block ())
 	  surrounding_static_block = b;   /* For elmin of dups */
@@ -13852,9 +13848,9 @@  class ada_language : public language_defn
 	auto callback = [&] (compunit_symtab *s)
 	  {
 	    QUIT;
-	    for (const block *b = s->blockvector ()->static_block ();
-		 b != nullptr;
-		 b = b->superblock ())
+	    const struct block *static_block
+	      = s->blockvector ()->static_block ();
+	    for (auto b : block::block_and_superblocks (static_block))
 	      {
 		/* Don't do this block twice.  */
 		if (b == surrounding_static_block)
diff --git a/gdb/blockframe.c b/gdb/blockframe.c
index 8aafa6ffe57..5c981748cbc 100644
--- a/gdb/blockframe.c
+++ b/gdb/blockframe.c
@@ -69,13 +69,14 @@  get_frame_block (const frame_info_ptr &frame, CORE_ADDR *addr_in_block)
 
   inline_count = frame_inlined_callees (frame);
 
-  while (inline_count > 0)
+  auto range = bl->block_and_superblocks ();
+  for (auto b = range.begin (); b != range.end (); ++b, bl = *b)
     {
-      if (bl->inlined_p ())
-	inline_count--;
+      if (inline_count <= 0)
+	break;
 
-      bl = bl->superblock ();
-      gdb_assert (bl != NULL);
+      if ((*b)->inlined_p ())
+	inline_count--;
     }
 
   return bl;
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index 4ea924582fb..32c6fe0bacf 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -443,10 +443,12 @@  get_out_value_type (struct symbol *func_sym, struct objfile *objfile,
 	continue;
 
       function_block = block;
-      while (function_block != bv->static_block ()
-	     && function_block != bv->global_block ())
+      for (auto b : block::block_and_superblocks (block))
 	{
-	  function_block = function_block->superblock ();
+	  if (b == bv->static_block () || b == bv->global_block ())
+	    break;
+
+	  function_block = b->superblock ();
 	  function = function_block->function ();
 	  if (function != NULL)
 	    break;
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index c8cd5c245aa..534f2d0b8f9 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -613,13 +613,11 @@  cp_lookup_symbol_via_all_imports (const char *scope, const char *name,
 {
   struct block_symbol sym;
 
-  while (block != NULL)
+  for (auto b : block::block_and_superblocks (block))
     {
-      sym = cp_lookup_symbol_via_imports (scope, name, block, domain, 0, 1);
+      sym = cp_lookup_symbol_via_imports (scope, name, b, domain, 0, 1);
       if (sym.symbol != nullptr)
 	return sym;
-
-      block = block->superblock ();
     }
 
   return {};
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index d040ad79469..c04a5120380 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -1408,15 +1408,11 @@  add_symbol_overload_list_using (const char *func_name,
 				const char *the_namespace,
 				std::vector<symbol *> *overload_list)
 {
-  const struct block *block;
-
   /* First, go through the using directives.  If any of them apply,
      look in the appropriate namespaces for new functions to match
      on.  */
 
-  for (block = get_selected_block (0);
-       block != NULL;
-       block = block->superblock ())
+  for (auto block : block::block_and_superblocks (get_selected_block (0)))
     for (using_direct *current : block->get_using ())
       {
 	/* Prevent recursive calls.  */
@@ -1459,7 +1455,7 @@  add_symbol_overload_list_qualified (const char *func_name,
   /* Search upwards from currently selected frame (so that we can
      complete on local vars.  */
 
-  for (const block *b = selected_block; b != nullptr; b = b->superblock ())
+  for (auto b : block::block_and_superblocks (selected_block))
     add_symbol_overload_list_block (func_name, b, overload_list);
 
   const block *surrounding_static_block = (selected_block == nullptr
diff --git a/gdb/d-namespace.c b/gdb/d-namespace.c
index 34b90c0ed93..a8bb90320c3 100644
--- a/gdb/d-namespace.c
+++ b/gdb/d-namespace.c
@@ -481,14 +481,12 @@  d_lookup_symbol_module (const char *scope, const char *name,
 
   /* Search for name in modules imported to this and parent
      blocks.  */
-  while (block != NULL)
+  for (auto b : block::block_and_superblocks (block))
     {
-      sym = d_lookup_symbol_imports (scope, name, block, domain);
+      sym = d_lookup_symbol_imports (scope, name, b, domain);
 
       if (sym.symbol != NULL)
 	return sym;
-
-      block = block->superblock ();
     }
 
   return {};
diff --git a/gdb/dwarf2/line-program.c b/gdb/dwarf2/line-program.c
index b9da1b4799f..227ec01aec9 100644
--- a/gdb/dwarf2/line-program.c
+++ b/gdb/dwarf2/line-program.c
@@ -373,21 +373,15 @@  dwarf_find_and_extend_inline_block_range (dwarf2_cu *cu,
      the child of a non-inline block.  This is new inline block is our
      candidate for extending.  */
   struct block *block = nullptr;
-  for (const struct block *b = it->second;
-       b != nullptr;
-       b = b->superblock ())
-    {
-      if (b->function () != nullptr && b->inlined_p ())
-	{
-	  if (b->superblock () != nullptr
-	      && b->superblock ()->function () != nullptr
-	      && !b->superblock ()->inlined_p ())
-	    {
-	      block = const_cast<struct block *> (b);
-	      break;
-	    }
-	}
-    }
+  for (auto b : block::block_and_superblocks (it->second))
+    if (b->inlined_p ()
+	&& b->superblock () != nullptr
+	&& b->superblock ()->function () != nullptr
+	&& !b->superblock ()->inlined_p ())
+      {
+	block = const_cast<struct block *> (b);
+	break;
+      }
 
   /* If we didn't find a block, or the block we found wasn't called from
      the expected LINE, then we're done.  Maybe we should try harder to
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 11c5d5214d6..be57c521a0d 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -8261,13 +8261,15 @@  process_event_stop_test (struct execution_control_state *ecs)
       const struct block *prev
 	= block_for_pc (ecs->event_thread->control.step_frame_id.code_addr);
       const struct block *curr = block_for_pc (ecs->event_thread->stop_pc ());
-      while (curr != nullptr && !curr->contains (prev))
+      for (auto b : block::block_and_superblocks (curr))
 	{
-	  if (curr->inlined_p ())
+	  if (b->contains (prev))
+	    break;
+
+	  if (b->inlined_p ())
 	    depth++;
-	  else if (curr->function () != nullptr)
+	  else if (b->function () != nullptr)
 	    break;
-	  curr = curr->superblock ();
        }
       while (inline_skipped_frames (ecs->event_thread) > depth)
 	step_into_inline_frame (ecs->event_thread);
diff --git a/gdb/inline-frame.c b/gdb/inline-frame.c
index a1ccd4ed0da..3aeaebffa2d 100644
--- a/gdb/inline-frame.c
+++ b/gdb/inline-frame.c
@@ -217,7 +217,7 @@  inline_frame_sniffer (const struct frame_unwind *self,
 		      void **this_cache)
 {
   CORE_ADDR this_pc;
-  const struct block *frame_block, *cur_block;
+  const struct block *frame_block;
   int depth;
   frame_info_ptr next_frame;
   struct inline_state *state = find_inline_frame_state (inferior_thread ());
@@ -230,15 +230,15 @@  inline_frame_sniffer (const struct frame_unwind *self,
   /* Calculate DEPTH, the number of inlined functions at this
      location.  */
   depth = 0;
-  cur_block = frame_block;
-  while (cur_block->superblock ())
+  for (auto cur_block : frame_block->block_and_superblocks ())
     {
+      if (cur_block->superblock () == nullptr)
+	break;
+
       if (cur_block->inlined_p ())
 	depth++;
       else if (cur_block->function () != NULL)
 	break;
-
-      cur_block = cur_block->superblock ();
     }
 
   /* Check how many inlined functions already have frames.  */
@@ -361,25 +361,22 @@  gather_inline_frames (CORE_ADDR this_pc)
     return {};
 
   std::vector<const symbol *> function_symbols;
-  while (cur_block != nullptr)
-    {
-      if (cur_block->inlined_p ())
-	{
-	  gdb_assert (cur_block->function () != nullptr);
-
-	  /* See comments in inline_frame_this_id about this use
-	     of BLOCK_ENTRY_PC.  */
-	  if (cur_block->entry_pc () == this_pc
-	      || block_starting_point_at (bv, this_pc, cur_block))
-	    function_symbols.push_back (cur_block->function ());
-	  else
-	    break;
-	}
-      else if (cur_block->function () != nullptr)
-	break;
-
-      cur_block = cur_block->superblock ();
-    }
+  auto range = block::block_and_superblocks (cur_block);
+  for (auto b = range.begin (); b != range.end (); ++b, cur_block = *b)
+    if (cur_block->inlined_p ())
+      {
+	gdb_assert (cur_block->function () != nullptr);
+
+	/* See comments in inline_frame_this_id about this use
+	   of BLOCK_ENTRY_PC.  */
+	if (cur_block->entry_pc () == this_pc
+	    || block_starting_point_at (bv, this_pc, cur_block))
+	  function_symbols.push_back (cur_block->function ());
+	else
+	  break;
+      }
+    else if (cur_block->function () != nullptr)
+      break;
 
   /* If we have a code region for which we have no function blocks,
      possibly due to bad debug, or possibly just when some debug
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 6ed4b4553d3..c393e855a91 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1194,11 +1194,10 @@  iterate_over_file_blocks
    domain_search_flags domain,
    for_each_symbol_callback_ftype callback)
 {
-  const struct block *block;
+  const struct block *static_block
+    = symtab->compunit ()->blockvector ()->static_block ();
 
-  for (block = symtab->compunit ()->blockvector ()->static_block ();
-       block != NULL;
-       block = block->superblock ())
+  for (auto block : block::block_and_superblocks (static_block))
     current_language->for_each_symbol (block, name, domain, callback);
 }
 
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 89374bd8a2f..f882f3add17 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -961,11 +961,10 @@  block_depth (const struct block *block)
 {
   int i = 0;
 
-  while ((block = block->superblock ()) != NULL)
-    {
-      i++;
-    }
-  return i;
+  for (auto b [[maybe_unused]]: block::block_and_superblocks (block))
+    i++;
+
+  return i - 1;
 }
 
 
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 3c10e1fd750..d8e4e6375d9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -2181,14 +2181,17 @@  lookup_local_symbol (const char *name,
 
   const char *scope = block->scope ();
 
-  while (!block->is_global_block () && !block->is_static_block ())
+  for (auto b : block->block_and_superblocks ())
     {
+      if (b->is_global_block () || b->is_static_block ())
+	break;
+
       struct symbol *sym = lookup_symbol_in_block (name, match_type,
-						   block, domain);
+						   b, domain);
       if (sym != NULL)
-	return (struct block_symbol) {sym, block};
+	return (struct block_symbol) {sym, b};
 
-      struct symbol *function = block->function ();
+      struct symbol *function = b->function ();
       if (function != nullptr && function->is_template_function ())
 	{
 	  struct template_symbol *templ = (struct template_symbol *) function;
@@ -2196,17 +2199,16 @@  lookup_local_symbol (const char *name,
 				    templ->n_template_arguments,
 				    templ->template_arguments);
 	  if (sym != nullptr)
-	    return (struct block_symbol) {sym, block};
+	    return (struct block_symbol) {sym, b};
 	}
 
       struct block_symbol blocksym
-	= langdef->lookup_symbol_local (scope, name, block, domain);
+	= langdef->lookup_symbol_local (scope, name, b, domain);
       if (blocksym.symbol != nullptr)
 	return blocksym;
 
-      if (block->inlined_p ())
+      if (b->inlined_p ())
 	break;
-      block = block->superblock ();
     }
 
   /* We've reached the end of the function without finding a result.  */
@@ -3829,13 +3831,17 @@  skip_prologue_sal (struct symtab_and_line *sal)
      use the call site of the function instead.  */
   const block *function_block = nullptr;
 
-  for (const block *b = block_for_pc_sect (sal->pc, sal->section);
-       b != nullptr;
-       b = b->superblock ())
-    if (b->function () != NULL && b->inlined_p ())
-      function_block = b;
-    else if (b->function () != NULL)
-      break;
+  const block *pc_block = block_for_pc_sect (sal->pc, sal->section);
+  for (auto b: block::block_and_superblocks (pc_block))
+    {
+      if (b->function () == nullptr)
+	continue;
+
+      if (b->inlined_p ())
+	function_block = b;
+      else
+	break;
+    }
 
   if (function_block != NULL
       && function_block->function ()->line () != 0)
@@ -3929,7 +3935,8 @@  skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
 	     same function, not something inlined.  If it's inlined,
 	     then there is no point comparing the line numbers.  */
 	  bl = block_for_pc (prologue_sal.end);
-	  while (bl)
+	  auto range = block::block_and_superblocks (bl);
+	  for (auto b = range.begin (); b != range.end (); ++b, bl = *b)
 	    {
 	      if (bl->inlined_p ())
 		break;
@@ -3938,7 +3945,6 @@  skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
 		  bl = NULL;
 		  break;
 		}
-	      bl = bl->superblock ();
 	    }
 	  if (bl != NULL)
 	    break;
@@ -5868,7 +5874,7 @@  default_collect_symbol_completion_matches_break_on
      frees them.  I'm not going to worry about this; hopefully there
      won't be that many.  */
 
-  const struct block *b;
+  const struct block *selected_block;
   const struct block *surrounding_static_block, *surrounding_global_block;
   /* The symbol we are completing on.  Points in same buffer as text.  */
   const char *sym_text;
@@ -5977,12 +5983,17 @@  default_collect_symbol_completion_matches_break_on
      this places which match our text string.  Only complete on types
      visible from current context.  */
 
-  b = get_selected_block (0);
-  surrounding_static_block = b == nullptr ? nullptr : b->static_block ();
-  surrounding_global_block = b == nullptr ? nullptr : b->global_block ();
+  selected_block = get_selected_block (0);
+  surrounding_static_block
+    = selected_block == nullptr ? nullptr : selected_block->static_block ();
+  surrounding_global_block
+    = selected_block == nullptr ? nullptr : selected_block->global_block ();
   if (surrounding_static_block != NULL)
-    while (b != surrounding_static_block)
+    for (auto b : block::block_and_superblocks (selected_block))
       {
+	if (b == surrounding_static_block)
+	  break;
+
 	QUIT;
 
 	for (struct symbol *sym : block_iterator_range (b))
@@ -6003,9 +6014,8 @@  default_collect_symbol_completion_matches_break_on
 	/* Stop when we encounter an enclosing function.  Do not stop for
 	   non-inlined functions - the locals of the enclosing function
 	   are in scope for a nested function.  */
-	if (b->function () != NULL && b->inlined_p ())
+	if (b->inlined_p ())
 	  break;
-	b = b->superblock ();
       }
 
   /* Add fields from the file's types; symbols will be added below.  */