@@ -3,6 +3,20 @@
*** Changes since GDB 18
+* New commands
+
+set print shadowed on|off
+show print shadowed
+ This controls the output of the "info locals" command. If the option is
+ "off", shadowed variables will be omitted from the output. The default is
+ to print shadowed variables.
+
+* Changed commands
+
+info locals
+ The new "-shadowed on|off" option overrides the "set print shadowed"
+ setting for a single invocation of the command.
+
*** Changes in GDB 18
* Support for the Common Trace Format (CTF) has been removed. GDB now
@@ -9178,7 +9178,7 @@ If both @var{regexp} and @var{type_regexp} are provided, an argument
is printed only if its name matches @var{regexp} and its type matches
@var{type_regexp}.
-@item info locals [-q]
+@item info locals [-q] [-shadowed [on|off]]
@kindex info locals
Print the local variables of the selected frame, each on a separate
line. These are all variables (declared either static or automatic)
@@ -9188,6 +9188,9 @@ The optional flag @samp{-q}, which stands for @samp{quiet}, disables
printing header information and messages explaining why no local variables
have been printed.
+The optional argument @samp{-shadowed} overrides the @code{set print shadowed}
+setting (@pxref{set print shadowed}) for this invocation of the command.
+
@smallexample
@group
1: int x = 3;
@@ -9202,6 +9205,7 @@ have been printed.
x = 4 <file.c:3>
y = 52
x = 3 <file.c:1, shadowed>
+Use "set print shadowed off" to hide shadowed variables.
@end group
@end smallexample
@@ -9212,7 +9216,8 @@ same name which is declared within an inner scope (decision block,
method, or inner class). When shadowing is detected, location
information is added to all instances of the shadowed variable name.
The outermost instances are additionally followed by @samp{shadowed}
-to indicate that they are not the active variable.
+to indicate that they are not the active variable. Printing shadowed
+variables can be controlled by @ref{set print shadowed}.
@item info locals [-q] [-t @var{type_regexp}] [@var{regexp}]
Like @kbd{info locals}, but only print the local variables selected
@@ -12829,6 +12834,19 @@ Do not pretty print C@t{++} virtual function tables.
@item show print vtbl
Show whether C@t{++} virtual function tables are pretty printed, or not.
+
+@anchor{set print shadowed}
+@item set print shadowed
+@itemx set print shadowed on
+@cindex printing shadowed variables
+Print variables that are shadowed by a declaration in an inner scope
+(@pxref{shadowed variables}). The default is on.
+
+@item set print shadowed off
+Do not print shadowed variables.
+
+@item show print shadowed
+Show whether shadowed variables are printed or not.
@end table
@node Pretty Printing
@@ -217,10 +217,48 @@ static const gdb::option::option_def backtrace_command_option_defs[] = {
},
};
+/* Option for printing shadowed variables. */
+
+struct shadowed_print_options
+{
+ bool print_shadowed = true;
+};
+
+/* Store the user's "set print shadowed" setting. It can be overridden
+ with "info locals -shadowed on|off". */
+
+static shadowed_print_options user_shadowed_print_options;
+
+/* Implement "show print shadowed". */
+
+static void
+show_print_shadowed (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
+{
+ gdb_printf (file, _("Printing of shadowed variables is %s.\n"), value);
+}
+
+/* Option definitions for the shadowed variables setting. */
+
+static const gdb::option::option_def shadowed_print_option_defs[] = {
+
+ gdb::option::boolean_option_def<shadowed_print_options> {
+ "shadowed",
+ [] (shadowed_print_options *opt) { return &opt->print_shadowed; },
+ show_print_shadowed, /* show_cmd_cb */
+ N_("Set printing of shadowed variables."),
+ N_("Show printing of shadowed variables."),
+ N_("When on, variables that are shadowed by a declaration in an inner\n\
+scope are printed, annotated with the location of their declaration.\n\
+When off, such variables are omitted."),
+ },
+};
+
/* Prototypes for local functions. */
static void print_frame_local_vars (const frame_info_ptr &frame,
- bool quiet,
+ bool quiet, bool print_shadowed,
+ bool print_shadowed_msg,
const char *regexp, const char *t_regexp,
int num_tabs, struct ui_file *stream);
@@ -1985,7 +2023,9 @@ backtrace_command_1 (const frame_print_options &fp_opts,
print_frame_info (fp_opts, fi, 1, LOCATION, 1, 0);
if ((flags & PRINT_LOCALS) != 0)
- print_frame_local_vars (fi, false, NULL, NULL, 1, gdb_stdout);
+ print_frame_local_vars (fi, false,
+ user_shadowed_print_options.print_shadowed,
+ false, NULL, NULL, 1, gdb_stdout);
/* Save the last frame to check for error conditions. */
trailing = fi;
@@ -2258,6 +2298,9 @@ struct print_variable_and_value_data
int num_tabs;
struct ui_file *stream;
int values_printed;
+ bool print_shadowed = true;
+ bool printed_shadowed_variables = false;
+ bool omitted_shadowed_variables = false;
void operator() (const char *print_name, struct symbol *sym,
var_shadowing shadow_status);
@@ -2281,6 +2324,12 @@ print_variable_and_value_data::operator() (const char *print_name,
if (language_def (sym->language ())->symbol_printing_suppressed (sym))
return;
+ if (!print_shadowed && shadow_status == var_shadowing::SHADOWED)
+ {
+ omitted_shadowed_variables = true;
+ return;
+ }
+
frame = frame_find_by_id (frame_id);
if (frame == NULL)
{
@@ -2289,9 +2338,13 @@ print_variable_and_value_data::operator() (const char *print_name,
}
print_variable_and_value (print_name, sym, frame, stream, num_tabs,
- shadow_status);
+ print_shadowed
+ ? shadow_status : var_shadowing::NONE);
values_printed = 1;
+
+ if (shadow_status == var_shadowing::SHADOWED)
+ printed_shadowed_variables = true;
}
/* Prepares the regular expression REG from REGEXP.
@@ -2312,6 +2365,9 @@ prepare_reg (const char *regexp, std::optional<compiled_regex> *reg)
/* Print all variables from the innermost up to the function block of FRAME.
Print them with values to STREAM indented by NUM_TABS.
+ PRINT_SHADOWED controls whether shadowed variables are printed.
+ PRINT_SHADOWED_MSG controls whether a trailing "set print shadowed" message
+ is printed.
If REGEXP is not NULL, only print local variables whose name
matches REGEXP.
If T_REGEXP is not NULL, only print local variables whose type
@@ -2321,9 +2377,10 @@ prepare_reg (const char *regexp, std::optional<compiled_regex> *reg)
static void
print_frame_local_vars (const frame_info_ptr &frame,
- bool quiet,
- const char *regexp, const char *t_regexp,
- int num_tabs, struct ui_file *stream)
+ bool quiet, bool print_shadowed,
+ bool print_shadowed_msg, const char *regexp,
+ const char *t_regexp, int num_tabs,
+ struct ui_file *stream)
{
struct print_variable_and_value_data cb_data;
const struct block *block;
@@ -2351,6 +2408,7 @@ print_frame_local_vars (const frame_info_ptr &frame,
cb_data.num_tabs = 4 * num_tabs;
cb_data.stream = stream;
cb_data.values_printed = 0;
+ cb_data.print_shadowed = print_shadowed;
/* Temporarily change the selected frame to the given FRAME.
This allows routines that rely on the selected frame instead
@@ -2360,13 +2418,31 @@ print_frame_local_vars (const frame_info_ptr &frame,
iterate_over_block_local_vars_printing (block, cb_data);
- if (!cb_data.values_printed && !quiet)
+ if (quiet)
+ return;
+
+ if (!cb_data.values_printed)
{
if (regexp == NULL && t_regexp == NULL)
gdb_printf (stream, _("No locals.\n"));
else
gdb_printf (stream, _("No matching locals.\n"));
}
+
+ if (!print_shadowed_msg)
+ return;
+
+ if (cb_data.printed_shadowed_variables)
+ gdb_printf (stream,
+ _("Use \"%ps\" to hide shadowed variables.\n"),
+ styled_string (command_style.style (),
+ "set print shadowed off"));
+ else if (cb_data.omitted_shadowed_variables)
+ gdb_printf (stream,
+ _("Some shadowed variables were omitted, use \"%ps\" "
+ "to include them.\n"),
+ styled_string (command_style.style (),
+ "set print shadowed on"));
}
/* Structure to hold the values of the options used by the 'info
@@ -2397,24 +2473,51 @@ static const gdb::option::option_def info_print_options_defs[] = {
}
};
-/* Returns the option group used by 'info locals' and 'info args'
- commands. */
+/* Returns the option group used by the "info args" command. */
static gdb::option::option_def_group
-make_info_print_options_def_group (info_print_options *opts)
+make_info_args_options_def_group (info_print_options *opts)
{
return {{info_print_options_defs}, opts};
}
-/* Command completer for 'info locals' and 'info args'. */
+/* Returns the option groups used by the "info locals" command. */
+
+static std::array<gdb::option::option_def_group, 2>
+make_info_locals_options_def_group (info_print_options *opts,
+ shadowed_print_options *sh_opts)
+{
+ return {{
+ { {info_print_options_defs}, opts },
+ { {shadowed_print_option_defs}, sh_opts }
+ }};
+}
+
+/* Command completer for "info args". */
static void
-info_print_command_completer (struct cmd_list_element *ignore,
- completion_tracker &tracker,
- const char *text, const char * /* word */)
+info_args_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
{
const auto group
- = make_info_print_options_def_group (nullptr);
+ = make_info_args_options_def_group (nullptr);
+ if (gdb::option::complete_options
+ (tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
+ return;
+
+ const char *word = advance_to_expression_complete_word_point (tracker, text);
+ symbol_completer (ignore, tracker, text, word);
+}
+
+/* Command completer for "info locals". */
+
+static void
+info_locals_command_completer (struct cmd_list_element *ignore,
+ completion_tracker &tracker,
+ const char *text, const char * /* word */)
+{
+ const auto group = make_info_locals_options_def_group (nullptr, nullptr);
if (gdb::option::complete_options
(tracker, &text, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, group))
return;
@@ -2429,7 +2532,8 @@ void
info_locals_command (const char *args, int from_tty)
{
info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
+ shadowed_print_options sh_opts = user_shadowed_print_options;
+ auto grp = make_info_locals_options_def_group (&opts, &sh_opts);
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
if (args != nullptr && *args == '\0')
@@ -2437,7 +2541,7 @@ info_locals_command (const char *args, int from_tty)
print_frame_local_vars
(get_selected_frame (_("No frame selected.")),
- opts.quiet, args,
+ opts.quiet, sh_opts.print_shadowed, true, args,
opts.type_regexp.empty () ? nullptr : opts.type_regexp.c_str (),
0, gdb_stdout);
}
@@ -2546,7 +2650,7 @@ void
info_args_command (const char *args, int from_tty)
{
info_print_options opts;
- auto grp = make_info_print_options_def_group (&opts);
+ auto grp = make_info_args_options_def_group (&opts);
gdb::option::process_options
(&args, gdb::option::PROCESS_OPTIONS_UNKNOWN_IS_OPERAND, grp);
if (args != nullptr && *args == '\0')
@@ -3508,11 +3612,13 @@ Usage: info frame level LEVEL"),
cmd = add_info ("locals", info_locals_command,
info_print_args_help (_("\
All local variables of current stack frame or those matching REGEXPs.\n\
-Usage: info locals [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
-Prints the local variables of the current stack frame.\n"),
+Usage: info locals [-q] [-shadowed [on|off]] [-t TYPEREGEXP] [NAMEREGEXP]\n\
+Prints the local variables of the current stack frame.\n\
+The -shadowed option overrides the \"set print shadowed\" setting for this\n\
+command.\n"),
_("local variables"),
false));
- set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
+ set_cmd_completer_handle_brkchars (cmd, info_locals_command_completer);
cmd = add_info ("args", info_args_command,
info_print_args_help (_("\
All argument variables of current stack frame or those matching REGEXPs.\n\
@@ -3520,7 +3626,7 @@ Usage: info args [-q] [-t TYPEREGEXP] [NAMEREGEXP]\n\
Prints the argument variables of the current stack frame.\n"),
_("argument variables"),
false));
- set_cmd_completer_handle_brkchars (cmd, info_print_command_completer);
+ set_cmd_completer_handle_brkchars (cmd, info_args_command_completer);
/* Install "set print raw frame-arguments", a deprecated spelling of
"set print raw-frame-arguments". */
@@ -3560,4 +3666,8 @@ source line."),
gdb::option::add_setshow_cmds_for_options
(class_stack, &user_frame_print_options,
frame_print_option_defs, &setprintlist, &showprintlist);
+
+ gdb::option::add_setshow_cmds_for_options
+ (class_support, &user_shadowed_print_options,
+ shadowed_print_option_defs, &setprintlist, &showprintlist);
}
@@ -36,4 +36,5 @@ 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>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
] "info locals at innermost level"
@@ -30,6 +30,7 @@
# - tfaas
# - thread apply
# - taas
+# - info locals
load_lib compile-support.exp
load_lib completion-support.exp
@@ -531,6 +532,25 @@ proc_with_prefix test-info-threads {} {
test_gdb_complete_none "info threads I"
}
+# Basic option-machinery + "info locals" command integration tests.
+proc_with_prefix test-info-locals {} {
+ clean_restart $::testfile
+
+ if {![runto_main]} {
+ return
+ }
+
+ test_gdb_complete_multiple "info locals " "-" "" {
+ "-q"
+ "-shadowed"
+ "-t"
+ }
+
+ test_gdb_complete_unique \
+ "info locals -s" \
+ "info locals -shadowed"
+}
+
# Miscellaneous tests.
proc_with_prefix test-misc {variant} {
global all_options
@@ -1175,6 +1195,9 @@ test-thread-apply
# Basic "info threads" integration tests.
test-info-threads
+# Basic "info locals" integration tests.
+test-info-locals
+
# There was a bug where the "metasyntactic variable" was glued to the
# option.
gdb_test "help maintenance test-options unknown-is-operand" \
@@ -24,7 +24,7 @@ shadowing (void)
a = 101; /* bp for locals 1 */
{
unsigned int val2 = 3; /* val2-d2 */
- unsigned int val3 = 4; /* val3-d1 */
+ double val3 = 4; /* val3-d1 */
a = 102; /* bp for locals 2 */
{
unsigned int val1 = 5; /* val1-d2 */
@@ -54,6 +54,7 @@ gdb_test "info locals" [multi_line \
"a = 101" \
"val1 = 1" \
"val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
] "info locals first level"
gdb_breakpoint $srcfile:$bp_line3
@@ -65,6 +66,7 @@ gdb_test "info locals" [multi_line \
"a = 102" \
"val1 = 1\t<$srcfile:$val1_d1, shadowed>" \
"val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
] "info locals second level"
gdb_breakpoint $srcfile:$bp_line4
@@ -80,8 +82,94 @@ gdb_test "info locals" [multi_line \
"a = 103\t<$srcfile:$a_line, shadowed>" \
"val1 = 1\t<$srcfile:$val1_d1, shadowed>" \
"val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
] "info locals at innermost level"
+gdb_test "info locals -shadowed off" [multi_line \
+ "a = 999" \
+ "val1 = 6" \
+ "val2 = 7" \
+ "val3 = 8" \
+ "Some shadowed variables were omitted, use \"set print shadowed on\" to include them." \
+ ] "info locals -shadowed off at innermost level"
+
+# Use a type filter. Only the shadowed variable is of type double.
+gdb_test "info locals -t double" [multi_line \
+ "val3 = 4\t<$srcfile:$val3_d1, shadowed>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
+ ] "info locals -t double at innermost level"
+
+gdb_test "backtrace -full" [multi_line \
+ "#0 +shadowing \\(\\) at .*" \
+ "\[ \t\]+a = 999\t<${testfile}2.c:16>" \
+ "\[ \t\]+val1 = 6\t<$srcfile:$val1_d3>" \
+ "\[ \t\]+val2 = 7\t<$srcfile:$val2_d3>" \
+ "\[ \t\]+val3 = 8\t<$srcfile:$val3_d2>" \
+ "\[ \t\]+val1 = 5\t<$srcfile:$val1_d2, shadowed>" \
+ "\[ \t\]+val2 = 3\t<$srcfile:$val2_d2, shadowed>" \
+ "\[ \t\]+val3 = 4\t<$srcfile:$val3_d1, shadowed>" \
+ "\[ \t\]+a = 103\t<$srcfile:$a_line, shadowed>" \
+ "\[ \t\]+val1 = 1\t<$srcfile:$val1_d1, shadowed>" \
+ "\[ \t\]+val2 = 2\t<$srcfile:$val2_d1, shadowed>" \
+ "#1 +$hex in main \\(\\) at .*" \
+ "No locals\\." \
+ ] "backtrace -full including shadowed variables"
+
+gdb_test_no_output "set print shadowed off"
+
+gdb_test "show print shadowed" \
+ "Printing of shadowed variables is off\\." \
+ "show print shadowed off"
+
+gdb_test "backtrace -full" [multi_line \
+ "#0 +shadowing \\(\\) at .*" \
+ "\[ \t\]+a = 999" \
+ "\[ \t\]+val1 = 6" \
+ "\[ \t\]+val2 = 7" \
+ "\[ \t\]+val3 = 8" \
+ "#1 +$hex in main \\(\\) at .*" \
+ "No locals\\." \
+ ] "backtrace -full excluding shadowed variables"
+
+gdb_test "info locals" [multi_line \
+ "a = 999" \
+ "val1 = 6" \
+ "val2 = 7" \
+ "val3 = 8" \
+ "Some shadowed variables were omitted, use \"set print shadowed on\" to include them." \
+ ] "info locals at innermost level with filtered out shadowed"
+
+# Use a type filter. Printing of shadowed variables is disabled, so nothing
+# is printed.
+gdb_test "info locals -t double" [multi_line \
+ "No matching locals\\." \
+ "Some shadowed variables were omitted, use \"set print shadowed on\" to include them." \
+ ] "info locals -t double with filtered out shadowed"
+
+# Variables filtered by a regexp are not reported as shadowed.
+gdb_test "info locals -t float" "No matching locals\\." \
+ "info locals -t float with filtered out shadowed"
+
+# Override the user's setting to print shadowed variables.
+gdb_test "info locals -shadowed on" [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>" \
+ "Use \"set print shadowed off\" to hide shadowed variables." \
+ ] "info locals -shadowed on at innermost level"
+
+# The quiet option suppresses the hint about the shadowed setting.
+gdb_test_no_output "info locals -q -t double"
+
+gdb_test_no_output "set print shadowed on"
+
gdb_breakpoint $srcfile:$bp_line5
gdb_continue_to_breakpoint "continue to outermost level last" \
".*$srcfile:$bp_line5.*"