Fix Fortran regression with variables in nested functions
authorTom Tromey <tromey@adacore.com>
Tue, 13 Aug 2019 17:39:58 +0000 (11:39 -0600)
committerTom Tromey <tromey@adacore.com>
Mon, 19 Aug 2019 16:32:03 +0000 (10:32 -0600)
Sergio pointed out that commit commit aa3b6533 ("Allow nested function
displays") regressed a few gdb.fortran tests.  I was able to reproduce
these failures with gcc head.

The bug is that some spots calling contained_in will in fact do the
wrong thing if nested functions are considered as contained.  In the
particular case of the Fortran regression, it was the call in
block_innermost_frame, being called from get_hosting_frame -- in this
case, the caller is specifically trying to avoid the nested case.

This patch fixes the problem by adding an "allow_nested" parameter to
contained_in, essentially reverting the change for most callers.

gdb/ChangeLog
2019-08-19  Tom Tromey  <tromey@adacore.com>

* printcmd.c (do_one_display, info_display_command): Update.
* block.h (contained_in): Return bool.  Add allow_nested
parameter.
* block.c (contained_in): Return bool.  Add allow_nested
parameter.

gdb/ChangeLog
gdb/block.c
gdb/block.h
gdb/printcmd.c

index c654872..6c9b2e0 100644 (file)
@@ -1,3 +1,11 @@
+2019-08-19  Tom Tromey  <tromey@adacore.com>
+
+       * printcmd.c (do_one_display, info_display_command): Update.
+       * block.h (contained_in): Return bool.  Add allow_nested
+       parameter.
+       * block.c (contained_in): Return bool.  Add allow_nested
+       parameter.
+
 2019-08-19  Tom Tromey  <tom@tromey.com>
 
        * configure: Rebuild.
index 5c6faa8..ca4dc22 100644 (file)
@@ -65,25 +65,28 @@ block_gdbarch (const struct block *block)
   return get_objfile_arch (block_objfile (block));
 }
 
-/* Return Nonzero if block a is lexically nested within block b,
-   or if a and b have the same pc range.
-   Return zero otherwise.  */
+/* See block.h.  */
 
-int
-contained_in (const struct block *a, const struct block *b)
+bool
+contained_in (const struct block *a, const struct block *b,
+             bool allow_nested)
 {
   if (!a || !b)
-    return 0;
+    return false;
 
   do
     {
       if (a == b)
-       return 1;
+       return true;
+      /* If A is a function block, then A cannot be contained in B,
+         except if A was inlined.  */
+      if (!allow_nested && BLOCK_FUNCTION (a) != NULL && !block_inlined_p (a))
+        return false;
       a = BLOCK_SUPERBLOCK (a);
     }
   while (a != NULL);
 
-  return 0;
+  return true;
 }
 
 
index 9291deb..4c02e01 100644 (file)
@@ -219,7 +219,15 @@ extern struct symbol *block_containing_function (const struct block *);
 
 extern int block_inlined_p (const struct block *block);
 
-extern int contained_in (const struct block *, const struct block *);
+/* Return true if block A is lexically nested within block B, or if a
+   and b have the same pc range.  Return false otherwise.  If
+   ALLOW_NESTED is true, then block A is considered to be in block B
+   if A is in a nested function in B's function.  If ALLOW_NESTED is
+   false (the default), then blocks in nested functions are not
+   considered to be contained.  */
+
+extern bool contained_in (const struct block *a, const struct block *b,
+                         bool allow_nested = false);
 
 extern const struct blockvector *blockvector_for_pc (CORE_ADDR,
                                               const struct block **);
index 7529842..9b29b53 100644 (file)
@@ -1936,7 +1936,8 @@ do_one_display (struct display *d)
   if (d->block)
     {
       if (d->pspace == current_program_space)
-       within_current_scope = contained_in (get_selected_block (0), d->block);
+       within_current_scope = contained_in (get_selected_block (0), d->block,
+                                            true);
       else
        within_current_scope = 0;
     }
@@ -2098,7 +2099,7 @@ Num Enb Expression\n"));
       else if (d->format.format)
        printf_filtered ("/%c ", d->format.format);
       puts_filtered (d->exp_string);
-      if (d->block && !contained_in (get_selected_block (0), d->block))
+      if (d->block && !contained_in (get_selected_block (0), d->block, true))
        printf_filtered (_(" (cannot be evaluated in the current context)"));
       printf_filtered ("\n");
     }