* [PATCH v11 0/2] add annotation in 'info locals' command for variables shadowing case
@ 2025-11-28 12:03 Abdul Basit Ijaz
2025-11-28 12:03 ` [PATCH v11 1/2] gdb: " Abdul Basit Ijaz
2025-11-28 12:03 ` [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Abdul Basit Ijaz
0 siblings, 2 replies; 8+ messages in thread
From: Abdul Basit Ijaz @ 2025-11-28 12:03 UTC (permalink / raw)
To: gdb-patches
Cc: pedro, philippe.waroquiers, aburgess, tankut.baris.aktemur,
christina.schimpe, lsix, eliz, abdul.b.ijaz, tom
[-- Attachment #1: Type: text/plain, Size: 3185 bytes --]
Hi All,
For the variable shadowing case, these patches add the annotation "shadowed"
and location information to the shadowed variables so that it is easier for
the end user to identify which variable was shadowed.
Patch#1 updates "info locals" command and Path #2 is for the mi commands
'-stack-list-locals' and '-stack-list-variables'.
Last V10 Series:
https://sourceware.org/pipermail/gdb-patches/2025-April/217019.html
V9 Series:
https://sourceware.org/pipermail/gdb-patches/2025-March/216590.html
V8 Series:
https://sourceware.org/pipermail/gdb-patches/2024-December/214263.html
Documentation in V7 Series was already approved by Eli:
https://sourceware.org/pipermail/gdb-patches/2024-October/212228.html
https://sourceware.org/pipermail/gdb-patches/2024-October/212229.html
Patch#1 V6 was Reviewed-by Larsen:
https://sourceware.org/pipermail/gdb-patches/2024-January/205923.html
Patch#2 V2 was Tested-by Larsen:
https://sourceware.org/pipermail/gdb-patches/2024-January/205922.html
Changes since V10:
* This V10 series fixes the feedback from Andrew:
https://sourceware.org/pipermail/gdb-patches/2025-October/222129.html
Testing is done for unix/m32/native-gdbserver configurations and no
issue is seen.
Thanks & Best Rergards
Abdul Basit
Ijaz, Abdul B (2):
gdb: add annotation in 'info locals' command for variables shadowing
case
gdb: add shadowed field in '-stack-list-locals/variables' mi commands
gdb/NEWS | 8 +
gdb/doc/gdb.texinfo | 38 +++++
gdb/language.c | 20 +++
gdb/language.h | 19 +++
gdb/mi/mi-cmd-stack.c | 129 +++++++++++-----
gdb/printcmd.c | 29 +++-
gdb/stack.c | 115 +++++++++++++-
gdb/stack.h | 14 ++
gdb/testsuite/gdb.ada/var_shadowing.exp | 39 +++++
.../gdb.ada/var_shadowing/var_shadowing.adb | 30 ++++
gdb/testsuite/gdb.base/var-shadowing.c | 49 ++++++
gdb/testsuite/gdb.base/var-shadowing.exp | 92 ++++++++++++
gdb/testsuite/gdb.base/var-shadowing2.c | 16 ++
gdb/testsuite/gdb.mi/mi-var-shadowing.c | 48 ++++++
gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141 ++++++++++++++++++
gdb/testsuite/gdb.opt/inline-locals.exp | 21 ++-
gdb/testsuite/gdb.rust/var_reuse.exp | 36 +++++
gdb/testsuite/gdb.rust/var_reuse.rs | 20 +++
gdb/value.h | 17 ++-
19 files changed, 829 insertions(+), 52 deletions(-)
create mode 100644 gdb/testsuite/gdb.ada/var_shadowing.exp
create mode 100644 gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
create mode 100755 gdb/testsuite/gdb.base/var-shadowing.c
create mode 100755 gdb/testsuite/gdb.base/var-shadowing.exp
create mode 100644 gdb/testsuite/gdb.base/var-shadowing2.c
create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.c
create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.exp
create mode 100755 gdb/testsuite/gdb.rust/var_reuse.exp
create mode 100755 gdb/testsuite/gdb.rust/var_reuse.rs
--
2.51.1
[-- Attachment #2.1: Type: text/plain, Size: 329 bytes --]
Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928
[-- Attachment #2.2: Type: text/html, Size: 357 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v11 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
2025-11-28 12:03 [PATCH v11 0/2] add annotation in 'info locals' command for variables shadowing case Abdul Basit Ijaz
@ 2025-11-28 12:03 ` Abdul Basit Ijaz
2025-11-28 14:15 ` Eli Zaretskii
2025-11-28 12:03 ` [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Abdul Basit Ijaz
1 sibling, 1 reply; 8+ messages in thread
From: Abdul Basit Ijaz @ 2025-11-28 12:03 UTC (permalink / raw)
To: gdb-patches
Cc: pedro, philippe.waroquiers, aburgess, tankut.baris.aktemur,
christina.schimpe, lsix, eliz, abdul.b.ijaz, tom
[-- Attachment #1: Type: text/plain, Size: 31711 bytes --]
From: "Ijaz, Abdul B" <abdul.b.ijaz@intel.com>
For C/C++/Fortran/Ada languages GDB prints same name variable multiple
times in case of variable shadowing and it is confusing for user to identify
which variable belongs to the current scope. So for such cases add location
info to the innermost listed variables and for super block variables add
"shadowed" annotation in the form of "<file.c:line, shadowed>".
Suppose we have
1:int x = 42;
2: {
3: int x = 99;
4: int y = 52;
5: x = 99; /* break here */
6: }
Currently:
(gdb) info locals
x = 99
x = 42
y = 52
After applying this patch, we obtain:
(gdb) info locals
x = 99 <file.c:3>
y = 52
x = 42 <file.c:1, shadowed>
The patch adds the location annotations by keeping track of inner block
and already printed variables to identify shadowing. So, GDB now prints
"<file.c:line, shadowed>" for shadowed super-block variables and
"<file.c:line>" for innermost declarations of such variables only.
The location annotations are printed for shadowed variables in case of
C/C++/Fortran/Ada languages. In Rust, it is possible to declare a
variable with the same name many times. So in this case, just the first
instance of the variable is printed. RUST language test "var_reuse.exp"
fails with rustc compiler version >= 1.73 so XFAIL is added accordingly.
Fix regex expression in the gdb.opt/inline-locals.exp test according to
this change. The test update is only required due to the existing gdb
known ticket gdb/25695 where this issue is seen with 7.5.0 version on
sles15sp6 but it is not seen anymore on the newer gcc versions e.g.
gcc-11.4.0.
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
---
gdb/NEWS | 4 +
gdb/doc/gdb.texinfo | 20 +++
gdb/language.c | 20 +++
gdb/language.h | 19 +++
gdb/printcmd.c | 29 ++++-
gdb/stack.c | 115 ++++++++++++++++--
gdb/stack.h | 14 +++
gdb/testsuite/gdb.ada/var_shadowing.exp | 39 ++++++
.../gdb.ada/var_shadowing/var_shadowing.adb | 30 +++++
gdb/testsuite/gdb.base/var-shadowing.c | 49 ++++++++
gdb/testsuite/gdb.base/var-shadowing.exp | 92 ++++++++++++++
gdb/testsuite/gdb.base/var-shadowing2.c | 16 +++
gdb/testsuite/gdb.opt/inline-locals.exp | 21 ++--
gdb/testsuite/gdb.rust/var_reuse.exp | 36 ++++++
gdb/testsuite/gdb.rust/var_reuse.rs | 20 +++
gdb/value.h | 17 ++-
16 files changed, 524 insertions(+), 17 deletions(-)
create mode 100644 gdb/testsuite/gdb.ada/var_shadowing.exp
create mode 100644 gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
create mode 100755 gdb/testsuite/gdb.base/var-shadowing.c
create mode 100755 gdb/testsuite/gdb.base/var-shadowing.exp
create mode 100644 gdb/testsuite/gdb.base/var-shadowing2.c
create mode 100755 gdb/testsuite/gdb.rust/var_reuse.exp
create mode 100755 gdb/testsuite/gdb.rust/var_reuse.rs
diff --git a/gdb/NEWS b/gdb/NEWS
index c976727ee45..616899147c3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -74,6 +74,10 @@ New command class for help
commands that we, as developers, believe would be close to a minimal
set of commands for a new user of GDB.
+info locals
+ GDB now shows the "shadowed" annotation and the location information in
+ the output of this command for variables shadowing case.
+
* Changed remote packets
single-inf-arg in qSupported
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 1cc7d295fbf..9ea4a2705bf 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -9121,6 +9121,26 @@ The optional flag @samp{-q}, which stands for @samp{quiet}, disables
printing header information and messages explaining why no local variables
have been printed.
+@smallexample
+1: int x = 3;
+2: @{
+3: int x = 4;
+4: int y = 52;
+5: x = 99; // breakpoint-line
+6: @}
+(gdb) info locals
+x = 4 <file.c:3>
+y = 52
+x = 3 <file.c:1, shadowed>
+@end smallexample
+
+A variable is shadowed when there's another variable with the same
+name which is declared within an inner scope (decision block,
+method, or inner class). For such cases, its location for the
+outermost scope is followed by @samp{shadowed}. The location can
+help to locate the instances of shadowed variables. So,
+location information is only added for shadowed variables.
+
@item info locals [-q] [-t @var{type_regexp}] [@var{regexp}]
Like @kbd{info locals}, but only print the local variables selected
with the provided regexp(s).
diff --git a/gdb/language.c b/gdb/language.c
index 168b9381bee..b2e2d54b421 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1092,6 +1092,26 @@ language_lookup_primitive_type_as_symbol (const struct language_defn *la,
return sym;
}
+/* See language.h. */
+
+lang_vars_shadowing get_lang_vars_shadowing_option (enum language lang)
+{
+ switch (lang)
+ {
+ case language_c:
+ case language_cplus:
+ case language_fortran:
+ case language_ada:
+ return lang_vars_shadowing::PRINT;
+
+ case language_rust:
+ return lang_vars_shadowing::HIDE;
+
+ default:
+ return lang_vars_shadowing::NONE;
+ }
+}
+
/* Initialize the language routines. */
INIT_GDB_FILE (language)
diff --git a/gdb/language.h b/gdb/language.h
index 926d94405ea..ff49d82ce01 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -83,6 +83,21 @@ enum macro_expansion
macro_expansion_no, macro_expansion_c
};
+/* In the case of variable shadowing if extra information should be
+ printed for the current language is compared against it. */
+
+enum class lang_vars_shadowing
+ {
+ /* Adds shadowed information for such variables. */
+ PRINT,
+
+ /* Does not print shadowed variables. */
+ HIDE,
+
+ /* Print variables without shadow information. */
+ NONE,
+ };
+
\f
/* Per architecture (OS/ABI) language information. */
@@ -825,6 +840,10 @@ void c_get_string (struct value *value,
symbol_name_matcher_ftype *get_symbol_name_matcher
(const language_defn *lang, const lookup_name_info &lookup_name);
+/* Returns the shadowing option supported for the input language. */
+
+extern lang_vars_shadowing get_lang_vars_shadowing_option (enum language lang);
+
/* Save the current language and restore it upon destruction. */
class scoped_restore_current_language
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index b9618f0a333..b05b42d395a 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -2334,7 +2334,8 @@ clear_dangling_display_expressions (struct objfile *objfile)
void
print_variable_and_value (const char *name, struct symbol *var,
const frame_info_ptr &frame,
- struct ui_file *stream, int indent)
+ struct ui_file *stream, int indent,
+ var_shadowing shadow_status)
{
if (!name)
@@ -2347,6 +2348,7 @@ print_variable_and_value (const char *name, struct symbol *var,
{
struct value *val;
struct value_print_options opts;
+ const char *file_name = lbasename (var->symtab ()->filename ());
/* READ_VAR_VALUE needs a block in order to deal with non-local
references (i.e. to handle nested functions). In this context, we
@@ -2356,6 +2358,31 @@ print_variable_and_value (const char *name, struct symbol *var,
get_user_print_options (&opts);
opts.deref_ref = true;
common_val_print_checked (val, stream, indent, &opts, current_language);
+
+ /* Print <%line, shadowed> after the variable value only when it is variable
+ shadowing case. */
+ if (shadow_status != var_shadowing::NONE)
+ {
+ bool printed = (shadow_status == var_shadowing::SHADOWED);
+ string_file out (current_uiout->can_emit_style_escape ());
+
+ gdb_printf (&out, "\t<%ps:",
+ styled_string (file_name_style.style (), file_name));
+
+ if (var->line () > 0)
+ gdb_printf (&out, "%ps",
+ styled_string (line_number_style.style (),
+ pulongest (var->line ())));
+ else
+ gdb_puts ("No line number information available", &out);
+
+ gdb_printf (&out, "%ps",
+ styled_string (metadata_style.style (),
+ printed ? ", shadowed" : ""));
+ gdb_puts (">", &out);
+
+ gdb_puts (out.c_str ());
+ }
}
catch (const gdb_exception_error &except)
{
diff --git a/gdb/stack.c b/gdb/stack.c
index c2c76be8163..01314ca0754 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -58,6 +58,7 @@
#include "cli/cli-option.h"
#include "cli/cli-style.h"
#include "gdbsupport/buildargv.h"
+#include "gdbsupport/unordered_set.h"
/* The possible choices of "set print frame-arguments", and the value
of this setting. */
@@ -2211,8 +2212,9 @@ backtrace_command_completer (struct cmd_list_element *ignore,
/* Iterate over the local variables of a block B, calling CB. */
static void
-iterate_over_block_locals (const struct block *b,
- iterate_over_block_arg_local_vars_cb cb)
+iterate_over_block_locals
+ (const struct block *b,
+ gdb::function_view <void (const char *, struct symbol *)> cb)
{
for (struct symbol *sym : block_iterator_range (b))
{
@@ -2258,6 +2260,71 @@ iterate_over_block_local_vars (const struct block *block,
}
}
+/* Iterate over all the local variables in block B, including all its
+ superblocks, stopping when the top-level block is reached. */
+
+void
+iterate_over_block_local_vars_printing
+ (const struct block *block,
+ iterate_over_block_arg_local_vars_cb_printing cb)
+{
+ gdb::unordered_set<std::string> collected_vars, shadowed_vars, printed_vars;
+
+ /* Phase one: iterate over all locals within the block, and every parent
+ block up to the enclosing function block. Record all of the locals
+ seen, this allows us to know which locals are shadowing locals from a
+ more outer scope. */
+ iterate_over_block_local_vars
+ (block, [&] (const char *print_name, struct symbol *sym)
+ {
+ if (!sym->is_argument ())
+ {
+ if (!collected_vars.insert (print_name).second)
+ shadowed_vars.insert (print_name);
+ }
+ });
+
+ /* Phase two: iterate over all locals within the block, and every parent
+ block up to the enclosing function block. Print all the locals seen
+ by calling CB. Depending on the current language we vary the
+ arguments to CB to indicate shadowing. Or in some cases, we don't
+ print the local at all. */
+ iterate_over_block_local_vars
+ (block, [&] (const char *print_name, struct symbol *sym)
+ {
+ bool already_printed = !printed_vars.insert (print_name).second;
+ bool shadowed = shadowed_vars.find (print_name) != shadowed_vars.end ();
+
+ enum var_shadowing shadowing_status;
+ if (already_printed && shadowed)
+ shadowing_status = var_shadowing::SHADOWED;
+ else if (!already_printed && shadowed)
+ shadowing_status = var_shadowing::SHADOWING;
+ else
+ shadowing_status = var_shadowing::NONE;
+
+ /* Only for C/C++/Fortran/Ada languages, in case of variables
+ shadowing print <file:line, shadowed> annotation after
+ the superblock variable. Iteration of block starts from inner
+ block which is printed only with location information. */
+ if (get_lang_vars_shadowing_option (current_language->la_language)
+ == lang_vars_shadowing::PRINT && shadowing_status != var_shadowing::NONE)
+ cb (print_name, sym, shadowing_status);
+ /* In case of Rust language it is possible to declare variable with
+ same name multiple times and only innermost instance of variable
+ is accessible. So print only the innermost instance and there is
+ no need of printing duplicates. */
+ else if (get_lang_vars_shadowing_option (current_language->la_language)
+ == lang_vars_shadowing::HIDE
+ && shadowing_status == var_shadowing::SHADOWED)
+ {
+ /* Nothing. */
+ }
+ else
+ cb (print_name, sym, var_shadowing::NONE);
+ });
+}
+
/* Data to be passed around in the calls to the locals and args
iterators. */
@@ -2270,14 +2337,16 @@ struct print_variable_and_value_data
struct ui_file *stream;
int values_printed;
- void operator() (const char *print_name, struct symbol *sym);
+ void operator() (const char *print_name, struct symbol *sym,
+ var_shadowing shadow_status);
};
/* The callback for the locals and args iterators. */
void
print_variable_and_value_data::operator() (const char *print_name,
- struct symbol *sym)
+ struct symbol *sym,
+ var_shadowing shadow_status)
{
frame_info_ptr frame;
@@ -2297,7 +2366,8 @@ print_variable_and_value_data::operator() (const char *print_name,
return;
}
- print_variable_and_value (print_name, sym, frame, stream, num_tabs);
+ print_variable_and_value (print_name, sym, frame, stream, num_tabs,
+ shadow_status);
values_printed = 1;
}
@@ -2366,7 +2436,7 @@ print_frame_local_vars (const frame_info_ptr &frame,
scoped_restore_selected_frame restore_selected_frame;
select_frame (frame);
- iterate_over_block_local_vars (block, cb_data);
+ iterate_over_block_local_vars_printing (block, cb_data);
if (!cb_data.values_printed && !quiet)
{
@@ -2480,6 +2550,37 @@ iterate_over_block_arg_vars (const struct block *b,
}
}
+/* Iterate over all the argument variables in block B. */
+
+void
+iterate_over_block_arg_vars_printing
+ (const struct block *b,
+ iterate_over_block_arg_local_vars_cb_printing cb)
+{
+ for (struct symbol *sym : block_iterator_range (b))
+ {
+ /* Don't worry about things which aren't arguments. */
+ if (sym->is_argument ())
+ {
+ /* We have to look up the symbol because arguments can have
+ two entries (one a parameter, one a local) and the one we
+ want is the local, which lookup_symbol will find for us.
+ This includes gcc1 (not gcc2) on the sparc when passing a
+ small structure and gcc2 when the argument type is float
+ and it is passed as a double and converted to float by
+ the prologue (in the latter case the type of the LOC_ARG
+ symbol is double and the type of the LOC_LOCAL symbol is
+ float). There are also LOC_ARG/LOC_REGISTER pairs which
+ are not combined in symbol-reading. */
+
+ struct symbol *sym2
+ = lookup_symbol_search_name (sym->search_name (),
+ b, SEARCH_VAR_DOMAIN).symbol;
+ cb (sym->print_name (), sym2, var_shadowing::NONE);
+ }
+ }
+}
+
/* Print all argument variables of the function of FRAME.
Print them with values to STREAM.
If REGEXP is not NULL, only print argument variables whose name
@@ -2524,7 +2625,7 @@ print_frame_arg_vars (const frame_info_ptr &frame,
cb_data.stream = stream;
cb_data.values_printed = 0;
- iterate_over_block_arg_vars (func->value_block (), cb_data);
+ iterate_over_block_arg_vars_printing (func->value_block (), cb_data);
if (!cb_data.values_printed && !quiet)
{
diff --git a/gdb/stack.h b/gdb/stack.h
index 6b2efb8fe60..5557a722213 100644
--- a/gdb/stack.h
+++ b/gdb/stack.h
@@ -20,6 +20,8 @@
#ifndef GDB_STACK_H
#define GDB_STACK_H
+enum class var_shadowing;
+
gdb::unique_xmalloc_ptr<char> find_frame_funname (const frame_info_ptr &frame,
enum language *funlang,
struct symbol **funcp);
@@ -27,12 +29,24 @@ gdb::unique_xmalloc_ptr<char> find_frame_funname (const frame_info_ptr &frame,
typedef gdb::function_view<void (const char *print_name, struct symbol *sym)>
iterate_over_block_arg_local_vars_cb;
+typedef gdb::function_view<void (const char *print_name, struct symbol *sym,
+ var_shadowing shadow_status)>
+ iterate_over_block_arg_local_vars_cb_printing;
+
void iterate_over_block_arg_vars (const struct block *block,
iterate_over_block_arg_local_vars_cb cb);
void iterate_over_block_local_vars (const struct block *block,
iterate_over_block_arg_local_vars_cb cb);
+void iterate_over_block_arg_vars_printing
+ (const struct block *block,
+ iterate_over_block_arg_local_vars_cb_printing cb);
+
+void iterate_over_block_local_vars_printing
+ (const struct block *block,
+ iterate_over_block_arg_local_vars_cb_printing cb);
+
/* Initialize *WHAT to be a copy of the user desired print what frame info.
If !WHAT.has_value (), the printing function chooses a default set of
information to print, otherwise the printing function should print
diff --git a/gdb/testsuite/gdb.ada/var_shadowing.exp b/gdb/testsuite/gdb.ada/var_shadowing.exp
new file mode 100644
index 00000000000..8f0619d3e7e
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/var_shadowing.exp
@@ -0,0 +1,39 @@
+# Copyright 2023-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib "ada.exp"
+
+require allow_ada_tests
+
+standard_ada_testfile var_shadowing
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" \
+ executable [list debug]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+set i_level1 [gdb_get_line_number "I-Level1"]
+set i_level2 [gdb_get_line_number "I-Level2"]
+set i_level3 [gdb_get_line_number "I-Level3"]
+set bp_location [gdb_get_line_number "BREAK"]
+runto "var_shadowing.adb:$bp_location"
+
+gdb_test "info locals" [multi_line \
+ "i = 111\t<$testfile.adb:$i_level3>" \
+ "i = 11\t<$testfile.adb:$i_level2, shadowed>" \
+ "i = 1\t<$testfile.adb:$i_level1, shadowed>" \
+] "info locals at innermost level"
diff --git a/gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb b/gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
new file mode 100644
index 00000000000..1c8f4e395a2
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
@@ -0,0 +1,30 @@
+-- Copyright 2023-2025 Free Software Foundation, Inc.
+--
+-- This program is free software; you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation; either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+with Ada.Text_IO; use Ada.Text_IO;
+
+procedure Varshadow is
+ I : Integer := 1; -- I-Level1
+begin
+ declare
+ I : Integer := 11; -- I-Level2
+ begin
+ declare
+ I : Integer := 111; -- I-Level3
+ begin
+ Put_Line ("hello"); -- BREAK
+ end;
+ end;
+end;
diff --git a/gdb/testsuite/gdb.base/var-shadowing.c b/gdb/testsuite/gdb.base/var-shadowing.c
new file mode 100755
index 00000000000..454bbcb5235
--- /dev/null
+++ b/gdb/testsuite/gdb.base/var-shadowing.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+void
+shadowing (void)
+{
+ int a = 100; /* bp for entry */
+ unsigned int val1 = 1; /* val1-d1 */
+ unsigned int val2 = 2; /* val2-d1 */
+ a = 101; /* bp for locals 1 */
+ {
+ unsigned int val2 = 3; /* val2-d2 */
+ unsigned int val3 = 4; /* val3-d1 */
+ a = 102; /* bp for locals 2 */
+ {
+ unsigned int val1 = 5; /* val1-d2 */
+ a = 103; /* bp for locals 3 */
+ {
+ #include "var-shadowing2.c"
+ unsigned int val1 = 6; /* val1-d3 */
+ unsigned int val2 = 7; /* val2-d3 */
+ unsigned int val3 = 8; /* val3-d2 */
+ a = 104; /* bp for locals 4 */
+ }
+ }
+ }
+ a = 105;
+} /* bp for locals 5 */
+
+int
+main (void)
+{
+ shadowing ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/var-shadowing.exp b/gdb/testsuite/gdb.base/var-shadowing.exp
new file mode 100755
index 00000000000..53bf9474fbd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/var-shadowing.exp
@@ -0,0 +1,92 @@
+# Copyright 2023-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+standard_testfile
+if [prepare_for_testing "failed to prepare" $testfile $srcfile] {
+ return -1
+}
+
+if ![runto_main] {
+ return -1
+}
+
+set bp_line1 [gdb_get_line_number "bp for locals 1"]
+set bp_line2 [gdb_get_line_number "bp for locals 2"]
+set bp_line3 [gdb_get_line_number "bp for locals 3"]
+set bp_line4 [gdb_get_line_number "bp for locals 4"]
+set bp_line5 [gdb_get_line_number "bp for locals 5"]
+
+set val1_d1 [gdb_get_line_number "val1-d1"]
+set val1_d2 [gdb_get_line_number "val1-d2"]
+set val1_d3 [gdb_get_line_number "val1-d3"]
+set val2_d1 [gdb_get_line_number "val2-d1"]
+set val2_d2 [gdb_get_line_number "val2-d2"]
+set val2_d3 [gdb_get_line_number "val2-d3"]
+set val3_d1 [gdb_get_line_number "val3-d1"]
+set val3_d2 [gdb_get_line_number "val3-d2"]
+set a_line [gdb_get_line_number "bp for entry"]
+
+gdb_breakpoint $srcfile:$bp_line1
+gdb_continue_to_breakpoint "continue to outermost level" \
+ ".*$srcfile:$bp_line1.*"
+gdb_test "info locals" [multi_line \
+ "val1 = 1" \
+ "val2 = 2" \
+ ] "info locals at outermost level"
+
+gdb_breakpoint $srcfile:$bp_line2
+gdb_continue_to_breakpoint "continue to first level" ".*$srcfile:$bp_line2.*"
+gdb_test "info locals" [multi_line \
+ "val2 = 3\t<$srcfile:$val2_d2>" \
+ "val3 = 4" \
+ "a = 101" \
+ "val1 = 1" \
+ "val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ ] "info locals first level"
+
+gdb_breakpoint $srcfile:$bp_line3
+gdb_continue_to_breakpoint "continue to second level" ".*$srcfile:$bp_line3.*"
+gdb_test "info locals" [multi_line \
+ "val1 = 5\t<$srcfile:$val1_d2>" \
+ "val2 = 3\t<$srcfile:$val2_d2>" \
+ "val3 = 4" \
+ "a = 102" \
+ "val1 = 1\t<$srcfile:$val1_d1, shadowed>" \
+ "val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ ] "info locals second level"
+
+gdb_breakpoint $srcfile:$bp_line4
+gdb_continue_to_breakpoint "continue to innermost level" ".*$srcfile:$bp_line4.*"
+gdb_test "info locals" [multi_line \
+ "a = 999\t<${testfile}2.c:16>" \
+ "val1 = 6\t<$srcfile:$val1_d3>" \
+ "val2 = 7\t<$srcfile:$val2_d3>" \
+ "val3 = 8\t<$srcfile:$val3_d2>" \
+ "val1 = 5\t<$srcfile:$val1_d2, shadowed>" \
+ "val2 = 3\t<$srcfile:$val2_d2, shadowed>" \
+ "val3 = 4\t<$srcfile:$val3_d1, shadowed>" \
+ "a = 103\t<$srcfile:$a_line, shadowed>" \
+ "val1 = 1\t<$srcfile:$val1_d1, shadowed>" \
+ "val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ ] "info locals at innermost level"
+
+gdb_breakpoint $srcfile:$bp_line5
+gdb_continue_to_breakpoint "continue to outermost level last" \
+ ".*$srcfile:$bp_line5.*"
+gdb_test "info locals" [multi_line \
+ "a = 105" \
+ "val1 = 1" \
+ "val2 = 2" \
+ ] "info locals at outermost level last"
diff --git a/gdb/testsuite/gdb.base/var-shadowing2.c b/gdb/testsuite/gdb.base/var-shadowing2.c
new file mode 100644
index 00000000000..b678f4d3916
--- /dev/null
+++ b/gdb/testsuite/gdb.base/var-shadowing2.c
@@ -0,0 +1,16 @@
+/* Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+int a = 999;
diff --git a/gdb/testsuite/gdb.opt/inline-locals.exp b/gdb/testsuite/gdb.opt/inline-locals.exp
index 6561cc39f3e..070b2953ce3 100644
--- a/gdb/testsuite/gdb.opt/inline-locals.exp
+++ b/gdb/testsuite/gdb.opt/inline-locals.exp
@@ -42,9 +42,11 @@ if { ! $no_frames } {
"backtrace from bar 2"
gdb_test "up" "#1 .*func1 .* at .*" "up from bar 2"
gdb_test "info frame" ".*inlined into frame.*" "func1 inlined 2"
- set pass_re "array = \\{0 <repeats 64 times>\\}"
+ set shadowed_pass_re "\t<$srcfile:$decimal>"
+ set shadowed_fail_re "\t<$srcfile:$decimal, shadowed>"
+ set pass_re "array = \\{0 <repeats 64 times>\\}($shadowed_pass_re)?"
set kfail_re [multi_line $pass_re \
- "array = <optimized out>"]
+ "array = <optimized out>$shadowed_fail_re"]
gdb_test_multiple "info locals" "info locals above bar 2" {
-re -wrap $pass_re {
pass $gdb_test_name
@@ -91,9 +93,9 @@ if { ! $no_frames } {
"backtrace from bar 3"
gdb_test "up" "#1 .*func1 .* at .*" "up from bar 3"
gdb_test "info frame" ".*inlined into frame.*" "func1 inlined 3"
- set pass_re "array = {$decimal, \[^\r\n\]*}"
+ set pass_re "array = {$decimal, \[^\r\n\]*}($shadowed_pass_re)?"
set kfail_re [multi_line $pass_re \
- "array = <optimized out>"]
+ "array = <optimized out>$shadowed_fail_re"]
gdb_test_multiple "info locals" "info locals above bar 3" {
-re -wrap $pass_re {
pass $gdb_test_name
@@ -133,7 +135,8 @@ proc check_scoped_locals {bp_label pass_re} {
gdb_breakpoint $srcfile:$locals_bp
gdb_continue_to_breakpoint "$bp_label" ".*$srcfile:$locals_bp.*"
- set kfail_re [multi_line $pass_re ".*<optimized out>"]
+ set kfail_re [multi_line $pass_re \
+ ".*<optimized out>(.*<$srcfile:$::decimal, shadowed>)?"]
gdb_test_multiple "info locals" "scoped info locals at $bp_label" {
-re -wrap $pass_re {
pass $gdb_test_name
@@ -149,7 +152,9 @@ proc check_scoped_locals {bp_label pass_re} {
}
if {! $no_frames } {
- check_scoped_locals "bp for locals 1" "loc2 = 20\r\nloc1 = 10"
- check_scoped_locals "bp for locals 2" "loc3 = 30\r\nloc2 = 20\r\nloc1 = 10"
- check_scoped_locals "bp for locals 3" "loc1 = 10"
+ check_scoped_locals "bp for locals 1" \
+ "loc2 = 20(\t<$srcfile:$decimal>)?\r\nloc1 = 10(\t<$srcfile:$decimal>)?"
+ check_scoped_locals "bp for locals 2" \
+ "loc3 = 30(\t<$srcfile:$decimal>)?\r\nloc2 = 20(\t<$srcfile:$decimal>)?\r\nloc1 = 10(\t<$srcfile:$decimal>)?"
+ check_scoped_locals "bp for locals 3" "loc1 = 10(\t<$srcfile:$decimal>)?"
}
diff --git a/gdb/testsuite/gdb.rust/var_reuse.exp b/gdb/testsuite/gdb.rust/var_reuse.exp
new file mode 100755
index 00000000000..2a5fb43bbf7
--- /dev/null
+++ b/gdb/testsuite/gdb.rust/var_reuse.exp
@@ -0,0 +1,36 @@
+# Copyright 2023-2025 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib rust-support.exp
+require allow_rust_tests
+require {can_compile rust}
+
+standard_testfile .rs
+if {[prepare_for_testing "failed to prepare" \
+ $testfile $srcfile {debug rust}]} {
+ return -1
+}
+
+set line [gdb_get_line_number "set breakpoint here"]
+if {![runto ${srcfile}:$line]} {
+ untested "could not run to breakpoint"
+ return -1
+}
+
+# Wrong local values are shown for rustc version >= 1.73.
+if {[rust_at_least 1.73]} {
+ setup_xfail "*-*-*" "gdb/31079"
+}
+gdb_test "info local _x" "_x = 12" "print local _x variable"
diff --git a/gdb/testsuite/gdb.rust/var_reuse.rs b/gdb/testsuite/gdb.rust/var_reuse.rs
new file mode 100755
index 00000000000..361744b9503
--- /dev/null
+++ b/gdb/testsuite/gdb.rust/var_reuse.rs
@@ -0,0 +1,20 @@
+// Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+fn main() {
+ let _x = 5;
+ let _x = _x + 7;
+ let _y = 8; // set breakpoint here
+}
diff --git a/gdb/value.h b/gdb/value.h
index 67c12a9ac62..b506022977b 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1568,11 +1568,26 @@ extern int val_print_string (struct type *elttype, const char *encoding,
struct ui_file *stream,
const struct value_print_options *options);
+/* Track the shadowing status of a variable. */
+enum class var_shadowing
+{
+ /* This variable is not shadowed, and not shadowing. */
+ NONE,
+
+ /* This variable is shadowed by a later one.*/
+ SHADOWED,
+
+ /* This variable is shadowing an earlier one, and is not itself
+ shadowed. */
+ SHADOWING
+};
+
extern void print_variable_and_value (const char *name,
struct symbol *var,
const frame_info_ptr &frame,
struct ui_file *stream,
- int indent);
+ int indent,
+ enum var_shadowing shadow_status);
extern void typedef_print (struct type *type, struct symbol *news,
struct ui_file *stream);
--
2.51.1
[-- Attachment #2.1: Type: text/plain, Size: 329 bytes --]
Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928
[-- Attachment #2.2: Type: text/html, Size: 357 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands
2025-11-28 12:03 [PATCH v11 0/2] add annotation in 'info locals' command for variables shadowing case Abdul Basit Ijaz
2025-11-28 12:03 ` [PATCH v11 1/2] gdb: " Abdul Basit Ijaz
@ 2025-11-28 12:03 ` Abdul Basit Ijaz
2025-11-28 14:21 ` Eli Zaretskii
1 sibling, 1 reply; 8+ messages in thread
From: Abdul Basit Ijaz @ 2025-11-28 12:03 UTC (permalink / raw)
To: gdb-patches
Cc: pedro, philippe.waroquiers, aburgess, tankut.baris.aktemur,
christina.schimpe, lsix, eliz, abdul.b.ijaz, tom
[-- Attachment #1: Type: text/plain, Size: 23489 bytes --]
From: "Ijaz, Abdul B" <abdul.b.ijaz@intel.com>
For C/C++/Fortran languages GDB prints same name variable multiple times in
case of variable shadowing and it is confusing for user to identify which
variable belongs to the current scope. So GDB now prints location information
for shadowed variables and add 'shadowed' field also in '-stack-list-locals'
and '-stack-list-variables' mi commands for super-block shadowed variable.
Suppose we have test.c file
1:int x = 42;
2: {
3: int x = 99;
4: int y = 52;
4: x = 99; /* break here */
5: }
The "-stack-list-locals" and "-stack-list-variables" mi commands at the
"break here" line gives the following output:
Before the change:
~~~
(gdb)
-stack-list-locals 0
^done,locals=[name="x",name="y",name="x"]
(gdb)
-stack-list-locals 1
^done,locals=[{name="x",value="99"},{name="y",value="52"},{name="x",value="42"}]
(gdb)
-stack-list-locals 2
^done,locals=[{name="x",type="int",value="99"},{name="y",type="int",value="52"},{name="x",type="int",value="42"}]
(gdb)
-stack-list-variables 0
^done,variables=[{name="x"},{name="y"},{name="x"}]
(gdb)
-stack-list-variables 1
^done,variables=[{name="x",value="99"},{name="y",value="52"},{name="x",value="42"}]
(gdb)
-stack-list-variables 2
^done,variables=[{name="x",type="int",value="99"},{name="y",type="int",value="52"},{name="x",type="int",value="42"}]
~~~
With this patch we obtain:
~~~
(gdb)
-stack-list-locals 0
^done,locals=[name="x",name="y",name="x"]
(gdb)
-stack-list-locals 1
^done,locals=[{name="x",value="99",file="/home/src/test.c",line="4"},{name="y",value="52"},{name="x",value="42",file="/home/src/test.c",line="2",shadowed="true"}]
(gdb)
-stack-list-locals 2
^done,locals=[{name="x",type="int",value="99",file="/home/src/test.c",line="4"},{name="y",type="int",value="52"},{name="x",type="int",value="42",file="/home/src/test.c",line="2",shadowed="true"}]
(gdb)
-stack-list-variables 0
^done,variables=[{name="x",file="/home/src/test.c",line="4"},{name="y"},{name="x",file="/home/src/test.c",line="2",shadowed="true"}]
(gdb)
-stack-list-variables 1
^done,variables=[{name="x",value="99",file="/home/src/test.c",line="4"},{name="y",value="52"},{name="x",value="42",file="/home/src/test.c",line="2",shadowed="true"}]
(gdb)
-stack-list-variables 2
^done,variables=[{name="x",type="int",value="99",file="/home/src/test.c",line="4"},{name="y",type="int",value="52"},{name="x",type="int",value="42",file="/home/src/test.c",line="2",shadowed="true"}]
~~~
---
gdb/NEWS | 4 +
gdb/doc/gdb.texinfo | 18 +++
gdb/mi/mi-cmd-stack.c | 129 ++++++++++++++------
gdb/testsuite/gdb.mi/mi-var-shadowing.c | 48 ++++++++
gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141 ++++++++++++++++++++++
5 files changed, 305 insertions(+), 35 deletions(-)
create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.c
create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.exp
diff --git a/gdb/NEWS b/gdb/NEWS
index 616899147c3..034b530a7bf 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -371,6 +371,10 @@ vFile:stat
multiple times, and the same mapping was being reused. In all
other cases, this field will have the value 'false'.
+** GDB now shows "shadowed", "file" and "line" fields in the output
+ of '-stack-list-locals/variables' mi commands for variables
+ shadowing case.
+
* Support for stabs debugging format and the a.out/dbx object format is
deprecated, and will be removed in GDB 18.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 9ea4a2705bf..f761e85ee28 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -35417,6 +35417,24 @@ If the @code{--skip-unavailable} option is specified, local variables
and arguments that are not available are not listed. Partially
available arguments and local variables are still displayed, however.
+@smallexample
+1: int x = 3;
+2: @{
+3: int x = 4;
+4: int y = 5;
+4: x = 99; // breakpoint-line
+5: @}
+(gdb) -stack-list-variables 2
+^done,variables=[@{name="x",type="int",value="4",file="/home/src/name.c",line="3"@},@{name="y",type="int",value="5",file="/home/src/name.c",line="4"@},@{name="x",type="int",value="3",file="/home/src/name.c",line="1",shadowed="true"@}]
+@end smallexample
+
+A variable is shadowed when there's another variable with the same
+name which is declared within an inner scope (decision block,
+method, or inner class). For such cases, its location for the
+outermost scope is followed by @samp{shadowed} attribute. The
+location can help to locate the instances of shadowed variables. So,
+location information is only added for shadowed variables.
+
@subsubheading Example
@smallexample
diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c
index 6c4a0e262f2..4996307c2e7 100644
--- a/gdb/mi/mi-cmd-stack.c
+++ b/gdb/mi/mi-cmd-stack.c
@@ -32,6 +32,7 @@
#include "mi-parse.h"
#include <optional>
#include "inferior.h"
+#include "gdbsupport/unordered_map.h"
enum what_to_list { locals, arguments, all };
@@ -490,7 +491,9 @@ mi_cmd_stack_list_variables (const char *command, const char *const *argv,
static void
list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
enum print_values values, int skip_unavailable,
- const frame_print_options &fp_opts)
+ const frame_print_options &fp_opts,
+ const gdb::unordered_set<std::string> *shadowed_vars,
+ gdb::unordered_set<std::string> &printed_vars)
{
struct ui_out *uiout = current_uiout;
@@ -519,6 +522,19 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
tuple_emitter.emplace (uiout, nullptr);
string_file stb;
+ const char *name = arg->sym->print_name ();
+ /* To distinguish innermost variable from the rest in the shadowed_vars
+ this boolen is needed. */
+ bool already_printed = !printed_vars.insert (name).second;
+ bool shadowed = shadowed_vars->find (name) != shadowed_vars->end ();
+
+ /* In case of Rust language it is possible to declare variable with
+ same name multiple times and only latest declaration of variable
+ is accessible. So print only the first instance and there is no
+ need of printing duplicates. */
+ if (get_lang_vars_shadowing_option (current_language->la_language)
+ == lang_vars_shadowing::HIDE && shadowed && already_printed)
+ return;
stb.puts (arg->sym->print_name ());
if (arg->entry_kind == print_entry_values_only)
@@ -560,6 +576,59 @@ list_arg_or_local (const struct frame_arg *arg, enum what_to_list what,
}
uiout->field_stream ("value", stb);
}
+
+ /* Only for C/C++/Fortran/Ada languages, in case of variables shadowing
+ print shadowed field after the superblock variable and only location
+ of the variables in the innerblock. */
+ if (get_lang_vars_shadowing_option (current_language->la_language)
+ == lang_vars_shadowing::PRINT && shadowed
+ && !(values == PRINT_NO_VALUES && what == locals))
+ {
+ uiout->field_string ("file", arg->sym->symtab ()->filename ());
+ uiout->field_unsigned ("line", arg->sym->m_line);
+ if (already_printed)
+ uiout->field_string ("shadowed", "true");
+ }
+}
+
+/* Returns true if address_class can be printed, otherwise returns false. */
+
+static bool
+can_print_aclass (struct symbol *sym, enum what_to_list what)
+{
+ int print_me = false;
+
+ switch (sym->loc_class ())
+ {
+ default:
+ case LOC_UNDEF: /* catches errors */
+ case LOC_CONST: /* constant */
+ case LOC_TYPEDEF: /* local typedef */
+ case LOC_LABEL: /* local label */
+ case LOC_BLOCK: /* local function */
+ case LOC_CONST_BYTES: /* loc. byte seq. */
+ case LOC_UNRESOLVED: /* unresolved static */
+ case LOC_OPTIMIZED_OUT: /* optimized out */
+ print_me = false;
+ break;
+
+ case LOC_ARG: /* argument */
+ case LOC_REF_ARG: /* reference arg */
+ case LOC_REGPARM_ADDR: /* indirect register arg */
+ case LOC_LOCAL: /* stack local */
+ case LOC_STATIC: /* static */
+ case LOC_REGISTER: /* register */
+ case LOC_COMPUTED: /* computed location */
+ if (what == all)
+ print_me = true;
+ else if (what == locals)
+ print_me = !sym->is_argument ();
+ else
+ print_me = sym->is_argument ();
+ break;
+ }
+
+ return print_me;
}
/* Print a list of the objects for the frame FI in a certain form,
@@ -573,9 +642,10 @@ list_args_or_locals (const frame_print_options &fp_opts,
enum what_to_list what, enum print_values values,
const frame_info_ptr &fi, int skip_unavailable)
{
- const struct block *block;
+ const struct block *block, *orig_block;
const char *name_of_result;
struct ui_out *uiout = current_uiout;
+ gdb::unordered_set<std::string> collected_vars, shadowed_vars, printed_vars;
block = get_frame_block (fi, 0);
@@ -596,42 +666,31 @@ list_args_or_locals (const frame_print_options &fp_opts,
ui_out_emit_list list_emitter (uiout, name_of_result);
- while (block != 0)
+ orig_block = block;
+ /* Stored list of shadowed variables later help in identifying them
+ from the rest. */
+ while (block != nullptr)
{
for (struct symbol *sym : block_iterator_range (block))
{
- int print_me = 0;
-
- switch (sym->loc_class ())
+ if (can_print_aclass (sym, what))
{
- default:
- case LOC_UNDEF: /* catches errors */
- case LOC_CONST: /* constant */
- case LOC_TYPEDEF: /* local typedef */
- case LOC_LABEL: /* local label */
- case LOC_BLOCK: /* local function */
- case LOC_CONST_BYTES: /* loc. byte seq. */
- case LOC_UNRESOLVED: /* unresolved static */
- case LOC_OPTIMIZED_OUT: /* optimized out */
- print_me = 0;
- break;
-
- case LOC_ARG: /* argument */
- case LOC_REF_ARG: /* reference arg */
- case LOC_REGPARM_ADDR: /* indirect register arg */
- case LOC_LOCAL: /* stack local */
- case LOC_STATIC: /* static */
- case LOC_REGISTER: /* register */
- case LOC_COMPUTED: /* computed location */
- if (what == all)
- print_me = 1;
- else if (what == locals)
- print_me = !sym->is_argument ();
- else
- print_me = sym->is_argument ();
- break;
+ const char *name = sym->print_name ();
+ if (!collected_vars.insert (name).second)
+ shadowed_vars.insert (name);
}
- if (print_me)
+ }
+ if (block->function ())
+ break;
+ block = block->superblock ();
+ }
+
+ block = orig_block;
+ while (block != 0)
+ {
+ for (struct symbol *sym : block_iterator_range (block))
+ {
+ if (can_print_aclass (sym, what))
{
struct symbol *sym2;
struct frame_arg arg, entryarg;
@@ -666,10 +725,10 @@ list_args_or_locals (const frame_print_options &fp_opts,
if (arg.entry_kind != print_entry_values_only)
list_arg_or_local (&arg, what, values, skip_unavailable,
- fp_opts);
+ fp_opts, &shadowed_vars, printed_vars);
if (entryarg.entry_kind != print_entry_values_no)
list_arg_or_local (&entryarg, what, values, skip_unavailable,
- fp_opts);
+ fp_opts, &shadowed_vars, printed_vars);
}
}
diff --git a/gdb/testsuite/gdb.mi/mi-var-shadowing.c b/gdb/testsuite/gdb.mi/mi-var-shadowing.c
new file mode 100644
index 00000000000..d01717099e1
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+void
+shadowing (void)
+{
+ int a = 100; /* entry bp */
+ unsigned int val1 = 1; /* val1-d1 */
+ unsigned int val2 = 2; /* val2-d1 */
+ a = 101; /* bp for locals 1 */
+ {
+ unsigned int val2 = 3; /* val2-d2 */
+ unsigned int val3 = 4; /* val3-d1 */
+ a = 102; /* bp for locals 2 */
+ {
+ unsigned int val1 = 5; /* val1-d2 */
+ a = 103; /* bp for locals 3 */
+ {
+ unsigned int val1 = 6; /* val1-d3 */
+ unsigned int val2 = 7; /* val2-d3 */
+ unsigned int val3 = 8; /* val3-d2 */
+ a = 104; /* bp for locals 4 */
+ }
+ }
+ }
+ a = 105;
+} /* bp for locals 5 */
+
+int
+main (void)
+{
+ shadowing ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.mi/mi-var-shadowing.exp b/gdb/testsuite/gdb.mi/mi-var-shadowing.exp
new file mode 100644
index 00000000000..7114dde56f0
--- /dev/null
+++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.exp
@@ -0,0 +1,141 @@
+# Copyright 2023-2025 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+load_lib mi-support.exp
+set MIFLAGS "-i=mi"
+
+gdb_exit
+if [mi_gdb_start] {
+ continue
+}
+
+standard_testfile
+
+set opts {debug}
+if [build_executable ${testfile}.exp ${testfile} ${srcfile} $opts] {
+ return -1
+}
+
+mi_delete_breakpoints
+mi_gdb_reinitialize_dir $srcdir/$subdir
+mi_gdb_load ${binfile}
+mi_runto main
+
+set bp_line1 [gdb_get_line_number "bp for locals 1"]
+set bp_line2 [gdb_get_line_number "bp for locals 2"]
+set bp_line3 [gdb_get_line_number "bp for locals 3"]
+set bp_line4 [gdb_get_line_number "bp for locals 4"]
+set bp_line5 [gdb_get_line_number "bp for locals 5"]
+
+set val1_d1 [gdb_get_line_number "val1-d1"]
+set val1_d2 [gdb_get_line_number "val1-d2"]
+set val1_d3 [gdb_get_line_number "val1-d3"]
+set val2_d1 [gdb_get_line_number "val2-d1"]
+set val2_d2 [gdb_get_line_number "val2-d2"]
+set val2_d3 [gdb_get_line_number "val2-d3"]
+set val3_d1 [gdb_get_line_number "val3-d1"]
+set val3_d2 [gdb_get_line_number "val3-d2"]
+set a_line [gdb_get_line_number "entry bp"]
+
+set stack_test1_regx "\\^done,(locals|variables)=\\\[\{name=\"a\",type=\"int\",value=\"$decimal\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\"\},{name=\"val2\",type=\"unsigned int\",value=\"2\"\}\\\]"
+set stack_test2_regx "\\^done,(locals|variables)=\\\[\{name=\"val2\",type=\"unsigned int\",value=\"3\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\"\},\{name=\"val3\",type=\"unsigned int\",value=\"4\"\},\{name=\"a\",type=\"int\",value=\"101\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]"
+set stack_test3_regx "\\^done,(locals|variables)=\\\[\{name=\"val1\",type=\"unsigned int\",value=\"5\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d2\"\},\{name=\"val2\",type=\"unsigned int\",value=\"3\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\"\},\{name=\"val3\",type=\"unsigned int\",value=\"4\"\},\{name=\"a\",type=\"int\",value=\"102\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]"
+set stack_test4_regx "\\^done,(locals|variables)=\\\[\{name=\"val1\",type=\"unsigned int\",value=\"6\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d3\"\},\{name=\"val2\",type=\"unsigned int\",value=\"7\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d3\"\},\{name=\"val3\",type=\"unsigned int\",value=\"8\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val3_d2\"\},\{name=\"val1\",type=\"unsigned int\",value=\"5\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d2\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"3\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\",shadowed=\"true\"\},\{name=\"val3\",type=\"unsigned int\",value=\"4\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val3_d1\",shadowed=\"true\"\},\{name=\"a\",type=\"int\",value=\"103\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]"
+set stack_test5_regx "\\^done,(locals|variables)=\\\[\{name=\"a\",type=\"int\",value=\"105\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\"\}\\\]"
+
+mi_gdb_test \
+ "-break-insert --source ${srcfile} --line ${bp_line1}" \
+ "\\^done.*source ${srcfile} \\-line ${bp_line1}.*" \
+ "bp at outermost level"
+mi_execute_to "exec-continue" "breakpoint-hit" ".*" ".*" ".*" "${bp_line1}" \
+ { "" "disp=\"keep\"" } "continue to outermost level"
+mi_gdb_test "-stack-list-locals 0" \
+ "\\^done,locals=\\\[name=\"a\",name=\"val1\",name=\"val2\"\\\]" \
+ "-stack-list-locals 0 at outermost level"
+mi_gdb_test "-stack-list-variables 0" \
+ "\\^done,variables=\\\[{name=\"a\"},{name=\"val1\"},{name=\"val2\"}\\\]" \
+ "-stack-list-variables 0 at outermost level"
+mi_gdb_test "-stack-list-locals 2" "${stack_test1_regx}" \
+ "-stack-list-locals 2 at outermost level"
+mi_gdb_test "-stack-list-variables 2" "${stack_test1_regx}" \
+ "-stack-list-variables 2 at outermost level"
+
+mi_gdb_test \
+ "-break-insert --source ${srcfile} --line ${bp_line2}" \
+ "\\^done.*source ${srcfile} \\-line ${bp_line2}.*" \
+ "bp at first level"
+mi_execute_to "exec-continue" "breakpoint-hit" ".*" ".*" ".*" "${bp_line2}" \
+ { "" "disp=\"keep\"" } "continue to first level"
+mi_gdb_test "-stack-list-locals 0" \
+ "\\^done,locals=\\\[name=\"val2\",name=\"val3\",name=\"a\",name=\"val1\",name=\"val2\"\\\]" \
+ "-stack-list-locals 0 at first level"
+mi_gdb_test "-stack-list-variables 0" \
+ "\\^done,variables=\\\[{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\"},{name=\"val3\"},{name=\"a\"},{name=\"val1\"},{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" \
+ "-stack-list-variables 0 at first level"
+mi_gdb_test "-stack-list-locals 2" "${stack_test2_regx}" \
+ "-stack-list-locals 2 at first level"
+mi_gdb_test "-stack-list-variables 2" "${stack_test2_regx}" \
+ "-stack-list-variables 2 at first level"
+
+mi_gdb_test \
+ "-break-insert --source ${srcfile} --line ${bp_line3}" \
+ "\\^done.*source ${srcfile} \\-line ${bp_line3}.*" \
+ "bp at second level"
+mi_execute_to "exec-continue" "breakpoint-hit" ".*" ".*" ".*" "${bp_line3}" \
+ { "" "disp=\"keep\"" } "continue to second level"
+mi_gdb_test "-stack-list-locals 0" \
+ "\\^done,locals=\\\[name=\"val1\",name=\"val2\",name=\"val3\",name=\"a\",name=\"val1\",name=\"val2\"\\\]" \
+ "-stack-list-locals 0 at second level"
+mi_gdb_test "-stack-list-variables 0" \
+ "\\^done,variables=\\\[{name=\"val1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d2\"},{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\"},{name=\"val3\"},{name=\"a\"},{name=\"val1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" \
+ "-stack-list-variables 0 at second level"
+mi_gdb_test "-stack-list-locals 2" "${stack_test3_regx}" \
+ "-stack-list-locals 2 at second level"
+mi_gdb_test "-stack-list-variables 2" "${stack_test3_regx}" \
+ "-stack-list-variables 2 at second level"
+
+mi_gdb_test \
+ "-break-insert --source ${srcfile} --line ${bp_line4}" \
+ "\\^done.*source ${srcfile} \\-line ${bp_line4}.*" \
+ "bp at third level"
+mi_execute_to "exec-continue" "breakpoint-hit" ".*" ".*" ".*" "${bp_line4}" \
+ { "" "disp=\"keep\"" } "continue to third level"
+mi_gdb_test "-stack-list-locals 0" \
+ "\\^done,locals=\\\[name=\"val1\",name=\"val2\",name=\"val3\",name=\"val1\",name=\"val2\",name=\"val3\",name=\"a\",name=\"val1\",name=\"val2\"\\\]" \
+ "-stack-list-locals 0 at third level"
+mi_gdb_test "-stack-list-variables 0" \
+ "\\^done,variables=\\\[{name=\"val1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d3\"},{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d3\"},{name=\"val3\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val3_d2\"},{name=\"val1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d2\",shadowed=\"true\"\},\{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d2\",shadowed=\"true\"\},\{name=\"val3\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val3_d1\",shadowed=\"true\"\},{name=\"a\"},{name=\"val1\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},{name=\"val2\",file=\"$srcdir/$subdir/$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" \
+ "-stack-list-variables 0 at third level"
+mi_gdb_test "-stack-list-locals 2" "${stack_test4_regx}" \
+ "-stack-list-locals 2 at third level"
+mi_gdb_test "-stack-list-variables 2" "${stack_test4_regx}" \
+ "-stack-list-variables 2 at third level"
+
+mi_gdb_test \
+ "-break-insert --source ${srcfile} --line ${bp_line5}" \
+ "\\^done.*source ${srcfile} \\-line ${bp_line5}.*" \
+ "bp at outermost level last"
+mi_execute_to "exec-continue" "breakpoint-hit" ".*" ".*" ".*" "${bp_line5}" \
+ { "" "disp=\"keep\"" } "continue to outermost level last"
+mi_gdb_test "-stack-list-locals 0" \
+ "\\^done,locals=\\\[name=\"a\",name=\"val1\",name=\"val2\"\\\]" \
+ "-stack-list-locals 0 at outermost level last"
+mi_gdb_test "-stack-list-variables 0" \
+ "\\^done,variables=\\\[{name=\"a\"},{name=\"val1\"},{name=\"val2\"}\\\]" \
+ "-stack-list-variables at outermost level last"
+mi_gdb_test "-stack-list-locals 2" "${stack_test5_regx}" \
+ "-stack-list-locals 2 at outermost level last"
+mi_gdb_test "-stack-list-variables 2" "${stack_test5_regx}" \
+ "-stack-list-variables 2 at outermost level last"
--
2.51.1
[-- Attachment #2.1: Type: text/plain, Size: 329 bytes --]
Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928
[-- Attachment #2.2: Type: text/html, Size: 357 bytes --]
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v11 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
2025-11-28 12:03 ` [PATCH v11 1/2] gdb: " Abdul Basit Ijaz
@ 2025-11-28 14:15 ` Eli Zaretskii
2025-11-28 14:37 ` Ijaz, Abdul B
0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2025-11-28 14:15 UTC (permalink / raw)
To: Abdul Basit Ijaz
Cc: gdb-patches, pedro, philippe.waroquiers, aburgess,
tankut.baris.aktemur, christina.schimpe, lsix, tom
> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: pedro@palves.net,
> philippe.waroquiers@skynet.be,
> aburgess@redhat.com,
> tankut.baris.aktemur@intel.com,
> christina.schimpe@intel.com,
> lsix@lancelotsix.com,
> eliz@gnu.org,
> abdul.b.ijaz@intel.com,
> tom@tromey.com
> Date: Fri, 28 Nov 2025 13:03:16 +0100
>
> gdb/NEWS | 4 +
> gdb/doc/gdb.texinfo | 20 +++
> gdb/language.c | 20 +++
> gdb/language.h | 19 +++
> gdb/printcmd.c | 29 ++++-
> gdb/stack.c | 115 ++++++++++++++++--
> gdb/stack.h | 14 +++
> gdb/testsuite/gdb.ada/var_shadowing.exp | 39 ++++++
> .../gdb.ada/var_shadowing/var_shadowing.adb | 30 +++++
> gdb/testsuite/gdb.base/var-shadowing.c | 49 ++++++++
> gdb/testsuite/gdb.base/var-shadowing.exp | 92 ++++++++++++++
> gdb/testsuite/gdb.base/var-shadowing2.c | 16 +++
> gdb/testsuite/gdb.opt/inline-locals.exp | 21 ++--
> gdb/testsuite/gdb.rust/var_reuse.exp | 36 ++++++
> gdb/testsuite/gdb.rust/var_reuse.rs | 20 +++
> gdb/value.h | 17 ++-
> 16 files changed, 524 insertions(+), 17 deletions(-)
> create mode 100644 gdb/testsuite/gdb.ada/var_shadowing.exp
> create mode 100644 gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
> create mode 100755 gdb/testsuite/gdb.base/var-shadowing.c
> create mode 100755 gdb/testsuite/gdb.base/var-shadowing.exp
> create mode 100644 gdb/testsuite/gdb.base/var-shadowing2.c
> create mode 100755 gdb/testsuite/gdb.rust/var_reuse.exp
> create mode 100755 gdb/testsuite/gdb.rust/var_reuse.rs
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index c976727ee45..616899147c3 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -74,6 +74,10 @@ New command class for help
> commands that we, as developers, believe would be close to a minimal
> set of commands for a new user of GDB.
>
> +info locals
> + GDB now shows the "shadowed" annotation and the location information in
> + the output of this command for variables shadowing case.
This sounds like the annotations are only shown when variables' values
are shadowed. Is that really the case? If so, why not show also
annotations for the non-shadowed variables?
> +@smallexample
> +1: int x = 3;
> +2: @{
> +3: int x = 4;
> +4: int y = 52;
> +5: x = 99; // breakpoint-line
> +6: @}
> +(gdb) info locals
> +x = 4 <file.c:3>
> +y = 52
> +x = 3 <file.c:1, shadowed>
> +@end smallexample
Please use @group..@end group to prevent multi-line examples, or their
parts, from being split between pages (which makes reading harder).
> +A variable is shadowed when there's another variable with the same
I suggest to have "shadowed" in @dfn, and add a @cindex entry before
this paragraph saying
@cindex shadowed variables
This will make it easier to find this stuff if someone is looking for
it.
> +name which is declared within an inner scope (decision block,
> +method, or inner class). For such cases, its location for the
> +outermost scope is followed by @samp{shadowed}. The location can
> +help to locate the instances of shadowed variables. So,
> +location information is only added for shadowed variables.
I suggest to add the annotations for all variables.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands
2025-11-28 12:03 ` [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Abdul Basit Ijaz
@ 2025-11-28 14:21 ` Eli Zaretskii
2025-11-28 15:09 ` Ijaz, Abdul B
0 siblings, 1 reply; 8+ messages in thread
From: Eli Zaretskii @ 2025-11-28 14:21 UTC (permalink / raw)
To: Abdul Basit Ijaz
Cc: gdb-patches, pedro, philippe.waroquiers, aburgess,
tankut.baris.aktemur, christina.schimpe, lsix, tom
> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: pedro@palves.net,
> philippe.waroquiers@skynet.be,
> aburgess@redhat.com,
> tankut.baris.aktemur@intel.com,
> christina.schimpe@intel.com,
> lsix@lancelotsix.com,
> eliz@gnu.org,
> abdul.b.ijaz@intel.com,
> tom@tromey.com
> Date: Fri, 28 Nov 2025 13:03:17 +0100
>
> gdb/NEWS | 4 +
> gdb/doc/gdb.texinfo | 18 +++
> gdb/mi/mi-cmd-stack.c | 129 ++++++++++++++------
> gdb/testsuite/gdb.mi/mi-var-shadowing.c | 48 ++++++++
> gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141 ++++++++++++++++++++++
> 5 files changed, 305 insertions(+), 35 deletions(-)
> create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.c
> create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.exp
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 616899147c3..034b530a7bf 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -371,6 +371,10 @@ vFile:stat
> multiple times, and the same mapping was being reused. In all
> other cases, this field will have the value 'false'.
>
> +** GDB now shows "shadowed", "file" and "line" fields in the output
> + of '-stack-list-locals/variables' mi commands for variables
> + shadowing case.
> +
> * Support for stabs debugging format and the a.out/dbx object format is
> deprecated, and will be removed in GDB 18.
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index 9ea4a2705bf..f761e85ee28 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -35417,6 +35417,24 @@ If the @code{--skip-unavailable} option is specified, local variables
> and arguments that are not available are not listed. Partially
> available arguments and local variables are still displayed, however.
>
> +@smallexample
> +1: int x = 3;
> +2: @{
> +3: int x = 4;
> +4: int y = 5;
> +4: x = 99; // breakpoint-line
> +5: @}
> +(gdb) -stack-list-variables 2
> +^done,variables=[@{name="x",type="int",value="4",file="/home/src/name.c",line="3"@},@{name="y",type="int",value="5",file="/home/src/name.c",line="4"@},@{name="x",type="int",value="3",file="/home/src/name.c",line="1",shadowed="true"@}]
> +@end smallexample
Same comment as in the previous patch regarding multi-line examples.
Also, the last line is too long, so please break it into several
lines, each one no longer than 72 characters (and preferably even
fewer).
> +A variable is shadowed when there's another variable with the same
> +name which is declared within an inner scope (decision block,
> +method, or inner class). For such cases, its location for the
> +outermost scope is followed by @samp{shadowed} attribute. The
> +location can help to locate the instances of shadowed variables. So,
> +location information is only added for shadowed variables.
There's no reason to explain twice what does "shadowed variable" mean.
Instead, please put here a cross-reference to the other node where
this is explained.
I still think that all variables should have this annotation. In the
MI output, it will make the job of the front-end which needs to parse
this output simpler, since the fields will always be present.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v11 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
2025-11-28 14:15 ` Eli Zaretskii
@ 2025-11-28 14:37 ` Ijaz, Abdul B
2025-11-28 15:23 ` Eli Zaretskii
0 siblings, 1 reply; 8+ messages in thread
From: Ijaz, Abdul B @ 2025-11-28 14:37 UTC (permalink / raw)
To: Eli Zaretskii
Cc: gdb-patches, pedro, philippe.waroquiers, aburgess, Aktemur,
Tankut Baris, Schimpe, Christina, lsix, tom
Hi Eli,
Thanks a lot for the feedback. Please review my feedback below.
>> + the output of this command for variables shadowing case.
Eli>This sounds like the annotations are only shown when variables' values are shadowed. Is that really the case? If so, why not show also annotations for the non-shadowed variables?
Abdul>Yes it the case. As otherwise this information is not useful. For example if variable is shown for "info locals" 5 times then 4 instances will have shadowed annotation with location info while the one instance will be without it. So it will be easier for user to identify the variable in current scope from the rest but any variable is only shown once then the information is not that useful.
>> +@smallexample
>> +1: int x = 3;
>> +2: @{
>> +3: int x = 4;
>> +4: int y = 52;
>> +5: x = 99; // breakpoint-line
>> +6: @}
>> +(gdb) info locals
>> +x = 4 <file.c:3>
>> +y = 52
>> +x = 3 <file.c:1, shadowed>
>> +@end smallexample
Eli>Please use @group..@end group to prevent multi-line examples, or their parts, from being split between pages (which makes reading harder).
Abdul>Sure, will make use of "group " in the example in the next patch.
>> +A variable is shadowed when there's another variable with the same
Eli>I suggest to have "shadowed" in @dfn, and add a @cindex entry before this paragraph saying
Abdul>Will update in patch v12.
>> +is only added for shadowed variables.
Eli>I suggest to add the annotations for all variables.
Abdul>Please confirm if the first comment above addresses your concerns.
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Eli Zaretskii <eliz@gnu.org>
Sent: Friday, November 28, 2025 3:16 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; pedro@palves.net; philippe.waroquiers@skynet.be; aburgess@redhat.com; Aktemur, Tankut Baris <tankut.baris.aktemur@intel.com>; Schimpe, Christina <christina.schimpe@intel.com>; lsix@lancelotsix.com; tom@tromey.com
Subject: Re: [PATCH v11 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: pedro@palves.net,
> philippe.waroquiers@skynet.be,
> aburgess@redhat.com,
> tankut.baris.aktemur@intel.com,
> christina.schimpe@intel.com,
> lsix@lancelotsix.com,
> eliz@gnu.org,
> abdul.b.ijaz@intel.com,
> tom@tromey.com
> Date: Fri, 28 Nov 2025 13:03:16 +0100
>
> gdb/NEWS | 4 +
> gdb/doc/gdb.texinfo | 20 +++
> gdb/language.c | 20 +++
> gdb/language.h | 19 +++
> gdb/printcmd.c | 29 ++++-
> gdb/stack.c | 115 ++++++++++++++++--
> gdb/stack.h | 14 +++
> gdb/testsuite/gdb.ada/var_shadowing.exp | 39 ++++++
> .../gdb.ada/var_shadowing/var_shadowing.adb | 30 +++++
> gdb/testsuite/gdb.base/var-shadowing.c | 49 ++++++++
> gdb/testsuite/gdb.base/var-shadowing.exp | 92 ++++++++++++++
> gdb/testsuite/gdb.base/var-shadowing2.c | 16 +++
> gdb/testsuite/gdb.opt/inline-locals.exp | 21 ++--
> gdb/testsuite/gdb.rust/var_reuse.exp | 36 ++++++
> gdb/testsuite/gdb.rust/var_reuse.rs | 20 +++
> gdb/value.h | 17 ++-
> 16 files changed, 524 insertions(+), 17 deletions(-) create mode
> 100644 gdb/testsuite/gdb.ada/var_shadowing.exp
> create mode 100644
> gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb
> create mode 100755 gdb/testsuite/gdb.base/var-shadowing.c
> create mode 100755 gdb/testsuite/gdb.base/var-shadowing.exp
> create mode 100644 gdb/testsuite/gdb.base/var-shadowing2.c
> create mode 100755 gdb/testsuite/gdb.rust/var_reuse.exp
> create mode 100755 gdb/testsuite/gdb.rust/var_reuse.rs
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index c976727ee45..616899147c3 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -74,6 +74,10 @@ New command class for help
> commands that we, as developers, believe would be close to a minimal
> set of commands for a new user of GDB.
>
> +info locals
> + GDB now shows the "shadowed" annotation and the location
> +information in
> + the output of this command for variables shadowing case.
This sounds like the annotations are only shown when variables' values are shadowed. Is that really the case? If so, why not show also annotations for the non-shadowed variables?
> +@smallexample
> +1: int x = 3;
> +2: @{
> +3: int x = 4;
> +4: int y = 52;
> +5: x = 99; // breakpoint-line
> +6: @}
> +(gdb) info locals
> +x = 4 <file.c:3>
> +y = 52
> +x = 3 <file.c:1, shadowed>
> +@end smallexample
Please use @group..@end group to prevent multi-line examples, or their parts, from being split between pages (which makes reading harder).
> +A variable is shadowed when there's another variable with the same
I suggest to have "shadowed" in @dfn, and add a @cindex entry before this paragraph saying
@cindex shadowed variables
This will make it easier to find this stuff if someone is looking for it.
> +name which is declared within an inner scope (decision block, method,
> +or inner class). For such cases, its location for the outermost
> +scope is followed by @samp{shadowed}. The location can help to
> +locate the instances of shadowed variables. So, location information
> +is only added for shadowed variables.
I suggest to add the annotations for all variables.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928
^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands
2025-11-28 14:21 ` Eli Zaretskii
@ 2025-11-28 15:09 ` Ijaz, Abdul B
0 siblings, 0 replies; 8+ messages in thread
From: Ijaz, Abdul B @ 2025-11-28 15:09 UTC (permalink / raw)
To: Eli Zaretskii
Cc: gdb-patches, pedro, philippe.waroquiers, aburgess, Aktemur,
Tankut Baris, Schimpe, Christina, lsix, tom
Hi Eli,
Thanks for the feedback.
>> +",line="4"@},@{name="x",type="int",value="3",file="/home/src/name.c",
>> +line="1",shadowed="true"@}]
>> +@end smallexample
Eli>Same comment as in the previous patch regarding multi-line examples.
Abdul>Sure will fix in Patchv12.
Eli>Also, the last line is too long, so please break it into several lines, each one no longer than 72 characters (and preferably even fewer).
Abdul>Sure will break it.
>> +A variable is shadowed when there's another variable with the same
>> +name which is declared within an inner scope (decision block, method,
>> +or inner class). For such cases, its location for the outermost
>> +scope is followed by @samp{shadowed} attribute. The location can
>> +help to locate the instances of shadowed variables. So, location
>> +information is only added for shadowed variables.
Eli>Instead, please put here a cross-reference to the other node where this is explained.
Abdul>Sure, will add a cross-reference in Patch v12.
Eli>I still think that all variables should have this annotation. In the MI output, it will make the job of the front-end which needs to parse this output simpler, since the fields will always be present.
Abdul>Replied on the other patch also. We may continue on this topic in other patch or here as you like. For future reference we already have this discussion [1] in upstream to address similar kind of concern by making it configurable which will address your concern in MI RSP where user will have the option to disable it completely. But to add it to all variables by default might be some thing which may not be that useful for the reason mentioned in other patch. As this series is ongoing for sometime now so will like to merge it first to fix the purpose it was opened. But please let me know your thoughts if this will address your concern then once this patch series is merged then we will continue to address it like discussed in [1] or if there is greater concern regarding it then may try to make it part of this patch series already.
[1] https://sourceware.org/pipermail/gdb-patches/2023-November/203961.html
Thanks & Best Regards
Abdul Basit
-----Original Message-----
From: Eli Zaretskii <eliz@gnu.org>
Sent: Friday, November 28, 2025 3:21 PM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; pedro@palves.net; philippe.waroquiers@skynet.be; aburgess@redhat.com; Aktemur, Tankut Baris <tankut.baris.aktemur@intel.com>; Schimpe, Christina <christina.schimpe@intel.com>; lsix@lancelotsix.com; tom@tromey.com
Subject: Re: [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands
> From: Abdul Basit Ijaz <abdul.b.ijaz@intel.com>
> Cc: pedro@palves.net,
> philippe.waroquiers@skynet.be,
> aburgess@redhat.com,
> tankut.baris.aktemur@intel.com,
> christina.schimpe@intel.com,
> lsix@lancelotsix.com,
> eliz@gnu.org,
> abdul.b.ijaz@intel.com,
> tom@tromey.com
> Date: Fri, 28 Nov 2025 13:03:17 +0100
>
> gdb/NEWS | 4 +
> gdb/doc/gdb.texinfo | 18 +++
> gdb/mi/mi-cmd-stack.c | 129 ++++++++++++++------
> gdb/testsuite/gdb.mi/mi-var-shadowing.c | 48 ++++++++
> gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141
> ++++++++++++++++++++++
> 5 files changed, 305 insertions(+), 35 deletions(-) create mode
> 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.c
> create mode 100644 gdb/testsuite/gdb.mi/mi-var-shadowing.exp
Thanks.
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 616899147c3..034b530a7bf 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -371,6 +371,10 @@ vFile:stat
> multiple times, and the same mapping was being reused. In all
> other cases, this field will have the value 'false'.
>
> +** GDB now shows "shadowed", "file" and "line" fields in the output
> + of '-stack-list-locals/variables' mi commands for variables
> + shadowing case.
> +
> * Support for stabs debugging format and the a.out/dbx object format is
> deprecated, and will be removed in GDB 18.
>
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index
> 9ea4a2705bf..f761e85ee28 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -35417,6 +35417,24 @@ If the @code{--skip-unavailable} option is
> specified, local variables and arguments that are not available are
> not listed. Partially available arguments and local variables are still displayed, however.
>
> +@smallexample
> +1: int x = 3;
> +2: @{
> +3: int x = 4;
> +4: int y = 5;
> +4: x = 99; // breakpoint-line
> +5: @}
> +(gdb) -stack-list-variables 2
> +^done,variables=[@{name="x",type="int",value="4",file="/home/src/name
> +.c",line="3"@},@{name="y",type="int",value="5",file="/home/src/name.c
> +",line="4"@},@{name="x",type="int",value="3",file="/home/src/name.c",
> +line="1",shadowed="true"@}]
> +@end smallexample
Same comment as in the previous patch regarding multi-line examples.
Also, the last line is too long, so please break it into several lines, each one no longer than 72 characters (and preferably even fewer).
> +A variable is shadowed when there's another variable with the same
> +name which is declared within an inner scope (decision block, method,
> +or inner class). For such cases, its location for the outermost
> +scope is followed by @samp{shadowed} attribute. The location can
> +help to locate the instances of shadowed variables. So, location
> +information is only added for shadowed variables.
There's no reason to explain twice what does "shadowed variable" mean.
Instead, please put here a cross-reference to the other node where this is explained.
I still think that all variables should have this annotation. In the MI output, it will make the job of the front-end which needs to parse this output simpler, since the fields will always be present.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Intel Deutschland GmbH
Registered Address: Dornacher Straße 1, 85622 Feldkirchen, Germany
Tel: +49 89 991 430, www.intel.de
Managing Directors: Harry Demas, Jeffrey Schneiderman, Yin Chong Sorrell
Chairperson of the Supervisory Board: Nicole Lau
Registered Seat: Munich
Commercial Register: Amtsgericht München HRB 186928
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v11 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
2025-11-28 14:37 ` Ijaz, Abdul B
@ 2025-11-28 15:23 ` Eli Zaretskii
0 siblings, 0 replies; 8+ messages in thread
From: Eli Zaretskii @ 2025-11-28 15:23 UTC (permalink / raw)
To: Ijaz, Abdul B
Cc: gdb-patches, pedro, philippe.waroquiers, aburgess,
tankut.baris.aktemur, christina.schimpe, lsix, tom
> From: "Ijaz, Abdul B" <abdul.b.ijaz@intel.com>
> CC: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
> "pedro@palves.net" <pedro@palves.net>, "philippe.waroquiers@skynet.be"
> <philippe.waroquiers@skynet.be>, "aburgess@redhat.com" <aburgess@redhat.com>,
> "Aktemur, Tankut Baris" <tankut.baris.aktemur@intel.com>, "Schimpe,
> Christina" <christina.schimpe@intel.com>, "lsix@lancelotsix.com"
> <lsix@lancelotsix.com>, "tom@tromey.com" <tom@tromey.com>
> Date: Fri, 28 Nov 2025 14:37:34 +0000
>
> Hi Eli,
>
> Thanks a lot for the feedback. Please review my feedback below.
>
> >> + the output of this command for variables shadowing case.
>
> Eli>This sounds like the annotations are only shown when variables' values are shadowed. Is that really the case? If so, why not show also annotations for the non-shadowed variables?
>
> Abdul>Yes it the case. As otherwise this information is not useful. For example if variable is shown for "info locals" 5 times then 4 instances will have shadowed annotation with location info while the one instance will be without it. So it will be easier for user to identify the variable in current scope from the rest but any variable is only shown once then the information is not that useful.
I think it will be better if we would show the last line before the
location of PC where each local got its value.
I will not argue about this anymore, but I'd like to hear what others
think about that.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2025-11-28 15:25 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-28 12:03 [PATCH v11 0/2] add annotation in 'info locals' command for variables shadowing case Abdul Basit Ijaz
2025-11-28 12:03 ` [PATCH v11 1/2] gdb: " Abdul Basit Ijaz
2025-11-28 14:15 ` Eli Zaretskii
2025-11-28 14:37 ` Ijaz, Abdul B
2025-11-28 15:23 ` Eli Zaretskii
2025-11-28 12:03 ` [PATCH v11 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Abdul Basit Ijaz
2025-11-28 14:21 ` Eli Zaretskii
2025-11-28 15:09 ` Ijaz, Abdul B
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox