From patchwork Tue Sep 19 16:46:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 76402 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id BCCE13856DFB for ; Tue, 19 Sep 2023 16:47:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org BCCE13856DFB DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1695142074; bh=rpKel8B86AMX7I12b2vyXv2QArofZtcsvWLYpSy2GSU=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=yD7XsJXRta7f+pY8GilLKqfituh3JUGWi3Ls13YFLw/K0+KVa0L1hTDxJuIGB0XLb kWEg/ldH8gK/GUNco0e72IF2tvd1ZHSM6UWUoqRkghO7/DYo+mSlBrWAq+10FUGhOk dphk2IRANXIbuCa1aeJmkfcxhP8ppaNA8udmSbF8= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id ABB513858017 for ; Tue, 19 Sep 2023 16:47:26 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org ABB513858017 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="382750869" X-IronPort-AV: E=Sophos;i="6.02,160,1688454000"; d="scan'208";a="382750869" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2023 09:47:26 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="1077056866" X-IronPort-AV: E=Sophos;i="6.02,160,1688454000"; d="scan'208";a="1077056866" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.252.38.6]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2023 09:47:23 -0700 To: gdb-patches@sourceware.org Subject: [PATCH v4 1/2] gdb: add annotation in 'info locals' command for variables shadowing case Date: Tue, 19 Sep 2023 18:46:59 +0200 Message-Id: <20230919164700.19891-2-abdul.b.ijaz@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230919164700.19891-1-abdul.b.ijaz@intel.com> References: <20230919164700.19891-1-abdul.b.ijaz@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Abdul Basit Ijaz via Gdb-patches From: Abdul Basit Ijaz Reply-To: Abdul Basit Ijaz Cc: "Ijaz, Abdul B" , lsix@lancelotsix.com, pedro@palves.net Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" From: "Ijaz, Abdul B" 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 "". 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 y = 52 x = 42 The patch adds the location annotations by keeping track of inner block and already printed variables to identify shadowing. So, GDB now prints "" for shadowed super-block variables and "" 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. --- gdb/doc/gdb.texinfo | 13 +++ gdb/printcmd.c | 11 ++- gdb/stack.c | 64 +++++++++++-- gdb/stack.h | 3 +- gdb/testsuite/gdb.ada/var_shadowing.exp | 38 ++++++++ .../gdb.ada/var_shadowing/var_shadowing.adb | 30 +++++++ gdb/testsuite/gdb.base/var-shadowing.c | 49 ++++++++++ gdb/testsuite/gdb.base/var-shadowing.exp | 90 +++++++++++++++++++ gdb/testsuite/gdb.base/var-shadowing2.c | 16 ++++ gdb/testsuite/gdb.rust/var_reuse.exp | 32 +++++++ gdb/testsuite/gdb.rust/var_reuse.rs | 20 +++++ gdb/tracepoint.c | 3 +- gdb/value.h | 4 +- 13 files changed, 362 insertions(+), 11 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/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 9b7e06f3156..6a22bbf2531 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -8831,6 +8831,19 @@ 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; // breakpt +4: @} +(gdb) info locals +x = 4 +x = 3 +@end smallexample + +If a variable is shadowed, then location information is printed and for +the outermost scope variables "shadowed" string is printed as well. + @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/printcmd.c b/gdb/printcmd.c index 8d7d04231fe..83008e5c3f3 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -55,6 +55,7 @@ #include "gdbsupport/gdb_optional.h" #include "gdbsupport/gdb-safe-ctype.h" #include "gdbsupport/rsp-low.h" +#include "include/libiberty.h" /* Chain containing all defined memory-tag subcommands. */ @@ -2401,7 +2402,8 @@ clear_dangling_display_expressions (struct objfile *objfile) void print_variable_and_value (const char *name, struct symbol *var, frame_info_ptr frame, - struct ui_file *stream, int indent) + struct ui_file *stream, int indent, + bool shadowed, bool printed) { if (!name) @@ -2414,6 +2416,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->owner.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 @@ -2424,6 +2427,12 @@ print_variable_and_value (const char *name, struct symbol *var, opts.deref_ref = true; common_val_print_checked (val, stream, indent, &opts, current_language); + if (shadowed) + /* Print location and shadowed variable information. */ + fprintf_styled (stream, metadata_style.style (), + _("\t<%s:%d%s>"), file_name, + var->line (), printed ? ", shadowed" : ""); + /* common_val_print invalidates FRAME when a pretty printer calls inferior function. */ frame = NULL; diff --git a/gdb/stack.c b/gdb/stack.c index 0b35d62f82f..0173e7341e9 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -56,6 +56,7 @@ #include "cli/cli-option.h" #include "cli/cli-style.h" #include "gdbsupport/buildargv.h" +#include /* The possible choices of "set print frame-arguments", and the value of this setting. */ @@ -2211,10 +2212,16 @@ backtrace_command_completer (struct cmd_list_element *ignore, static void iterate_over_block_locals (const struct block *b, - iterate_over_block_arg_local_vars_cb cb) + iterate_over_block_arg_local_vars_cb cb, + const std::unordered_set *shadowed_vars, + std::unordered_set &printed_vars) { for (struct symbol *sym : block_iterator_range (b)) { + const char *name = sym->print_name (); + bool already_printed = !printed_vars.insert (name).second; + bool shadowed = shadowed_vars->find (name) != shadowed_vars->end (); + switch (sym->aclass ()) { case LOC_CONST: @@ -2227,7 +2234,25 @@ iterate_over_block_locals (const struct block *b, break; if (sym->domain () == COMMON_BLOCK_DOMAIN) break; - cb (sym->print_name (), sym); + /* Only for C/C++/Fortran/Ada languages, in case of variables + shadowing print annotation after + the superblock variable. Iteration of block starts from inner + block which is printed only with location information. */ + if ((current_language->la_language == language_c + || current_language->la_language == language_cplus + || current_language->la_language == language_fortran + || current_language->la_language == language_ada) + && shadowed) + cb (name, sym, true, already_printed); + /* 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. */ + else if (current_language->la_language == language_rust + && shadowed && already_printed) + break; + else + cb (name, sym, false, false); break; default: @@ -2244,9 +2269,31 @@ void iterate_over_block_local_vars (const struct block *block, iterate_over_block_arg_local_vars_cb cb) { + std::unordered_set collected_vars, shadowed_vars, printed_vars; + const struct block *orig_block = block; + + /* Iterate over all the local variables in a block and store the list of + shadowed variables to later distinguish them from other variables. */ + while (block != nullptr) + { + for (struct symbol *sym : block_iterator_range (block)) + { + if (!sym->is_argument ()) + { + const char *name = sym->print_name (); + if (!collected_vars.insert (name).second) + shadowed_vars.insert (name); + } + } + if (block->function ()) + break; + block = block->superblock (); + } + + block = orig_block; while (block) { - iterate_over_block_locals (block, cb); + iterate_over_block_locals (block, cb, &shadowed_vars, printed_vars); /* After handling the function's top-level block, stop. Don't continue to its superblock, the block of per-file symbols. */ @@ -2268,14 +2315,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, bool shadowed, + bool printed); }; /* 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, + bool shadowed, bool printed) { frame_info_ptr frame; @@ -2295,7 +2344,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, shadowed, + printed); /* print_variable_and_value invalidates FRAME. */ frame = NULL; @@ -2478,7 +2528,7 @@ iterate_over_block_arg_vars (const struct block *b, struct symbol *sym2 = lookup_symbol_search_name (sym->search_name (), b, VAR_DOMAIN).symbol; - cb (sym->print_name (), sym2); + cb (sym->print_name (), sym2, false, false); } } } diff --git a/gdb/stack.h b/gdb/stack.h index 1b0c2b342a4..72d843b66fb 100644 --- a/gdb/stack.h +++ b/gdb/stack.h @@ -24,7 +24,8 @@ gdb::unique_xmalloc_ptr find_frame_funname (frame_info_ptr frame, enum language *funlang, struct symbol **funcp); -typedef gdb::function_view +typedef gdb::function_view iterate_over_block_arg_local_vars_cb; void iterate_over_block_arg_vars (const struct block *block, diff --git a/gdb/testsuite/gdb.ada/var_shadowing.exp b/gdb/testsuite/gdb.ada/var_shadowing.exp new file mode 100644 index 00000000000..da279da258d --- /dev/null +++ b/gdb/testsuite/gdb.ada/var_shadowing.exp @@ -0,0 +1,38 @@ +# Copyright 2023 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 . + +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" ${testdir}/var_shadowing.adb] +set i_level2 [gdb_get_line_number "I-Level2" ${testdir}/var_shadowing.adb] +set i_level3 [gdb_get_line_number "I-Level3" ${testdir}/var_shadowing.adb] +set bp_location [gdb_get_line_number "BREAK" ${testdir}/var_shadowing.adb] +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..93cef5f0d6c --- /dev/null +++ b/gdb/testsuite/gdb.ada/var_shadowing/var_shadowing.adb @@ -0,0 +1,30 @@ +-- Copyright 2023 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 . + +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..18963514bbf --- /dev/null +++ b/gdb/testsuite/gdb.base/var-shadowing.c @@ -0,0 +1,49 @@ +/* Copyright (C) 2023 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 . */ + +#include + +void +shadowing (void) +{ + int a; /* 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 = 0; /* 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..c7e1e9eae2e --- /dev/null +++ b/gdb/testsuite/gdb.base/var-shadowing.exp @@ -0,0 +1,90 @@ +# Copyright 2023 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 . + +standard_testfile +if [prepare_for_testing "failed to prepare" $testfile $srcfile] { + return -1 +} + +if ![runto_main] { + untested "failed to run to main" + return -1 +} + +set bp_line1 [gdb_get_line_number "bp for locals 1" ${srcfile}] +set bp_line2 [gdb_get_line_number "bp for locals 2" ${srcfile}] +set bp_line3 [gdb_get_line_number "bp for locals 3" ${srcfile}] +set bp_line4 [gdb_get_line_number "bp for locals 4" ${srcfile}] +set bp_line5 [gdb_get_line_number "bp for locals 5" ${srcfile}] + +set val1_d1 [gdb_get_line_number "val1-d1" ${srcfile}] +set val1_d2 [gdb_get_line_number "val1-d2" ${srcfile}] +set val1_d3 [gdb_get_line_number "val1-d3" ${srcfile}] +set val2_d1 [gdb_get_line_number "val2-d1" ${srcfile}] +set val2_d2 [gdb_get_line_number "val2-d2" ${srcfile}] +set val2_d3 [gdb_get_line_number "val2-d3" ${srcfile}] +set val3_d1 [gdb_get_line_number "val3-d1" ${srcfile}] +set val3_d2 [gdb_get_line_number "val3-d2" ${srcfile}] +set a_line [gdb_get_line_number "bp for entry" ${srcfile}] + +gdb_breakpoint $srcfile:$bp_line1 +gdb_test "continue" ".*bp for locals 1.*" "continue to outermost level" +gdb_test "info locals" [multi_line \ + "val1 = 1" \ + "val2 = 2" \ + ] "info locals at outermost level" + +gdb_breakpoint $srcfile:$bp_line2 +gdb_test "continue" ".*bp for locals 2.*" "continue to first level" +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_test "continue" ".*bp for locals 3.*" "continue to second level" +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_test "continue" ".*bp for locals 4.*" "continue to innermost level" +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_test "continue" ".*bp for locals 5.*" "continue to outermost level last" +gdb_test "info locals" [multi_line \ + "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..9bc55f95a84 --- /dev/null +++ b/gdb/testsuite/gdb.base/var-shadowing2.c @@ -0,0 +1,16 @@ +/* Copyright (C) 2023 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 . */ + +int a = 999; diff --git a/gdb/testsuite/gdb.rust/var_reuse.exp b/gdb/testsuite/gdb.rust/var_reuse.exp new file mode 100755 index 00000000000..58b85518f55 --- /dev/null +++ b/gdb/testsuite/gdb.rust/var_reuse.exp @@ -0,0 +1,32 @@ +# Copyright 2023 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 . + +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 +} + +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..03be7981ff1 --- /dev/null +++ b/gdb/testsuite/gdb.rust/var_reuse.rs @@ -0,0 +1,20 @@ +// Copyright (C) 2023 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 . + +fn main() { + let _x = 5; + let _x = _x + 7; + let _y = 8; // set breakpoint here +} diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 205380476b3..02669b3d909 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1048,7 +1048,8 @@ collection_list::add_local_symbols (struct gdbarch *gdbarch, CORE_ADDR pc, int count = 0; auto do_collect_symbol = [&] (const char *print_name, - struct symbol *sym) + struct symbol *sym, + bool shadowed, bool printed) { collect_symbol (sym, gdbarch, frame_regno, frame_offset, pc, trace_string); diff --git a/gdb/value.h b/gdb/value.h index 1d5a0018f92..879fce544c3 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -1537,7 +1537,9 @@ extern void print_variable_and_value (const char *name, struct symbol *var, frame_info_ptr frame, struct ui_file *stream, - int indent); + int indent, + bool shadowed, + bool printed); extern void typedef_print (struct type *type, struct symbol *news, struct ui_file *stream); From patchwork Tue Sep 19 16:47:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Abdul Basit Ijaz X-Patchwork-Id: 76403 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 8C22B3856DDA for ; Tue, 19 Sep 2023 16:48:00 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 8C22B3856DDA DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1695142080; bh=66W/jnkTuqlPrix0PrbaaWdsxAcN7Kw8H9AjGsNLzCQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=NUkr8dHYYMGGq9oTx1nMzmLtkSOZCPOM3xUDdywKRo01mZUi9MLtdo003V1skvVI5 OCjgPY0do+muTTDwJB7xHghGwyqWJaFvT1/GEV3XZjGEfMo8KeDGn9GdZ+a24cUDAO RSOq9KSsJ7i+Y1vvSu1SEGkUGmdOcO3XQd6yaI10= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [134.134.136.24]) by sourceware.org (Postfix) with ESMTPS id CF8F33858291 for ; Tue, 19 Sep 2023 16:47:34 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CF8F33858291 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="382750896" X-IronPort-AV: E=Sophos;i="6.02,160,1688454000"; d="scan'208";a="382750896" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2023 09:47:34 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6600,9927,10838"; a="1077056882" X-IronPort-AV: E=Sophos;i="6.02,160,1688454000"; d="scan'208";a="1077056882" Received: from abijaz-mobl2.ger.corp.intel.com (HELO localhost) ([10.252.38.6]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 19 Sep 2023 09:47:32 -0700 To: gdb-patches@sourceware.org Subject: [PATCH v4 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Date: Tue, 19 Sep 2023 18:47:00 +0200 Message-Id: <20230919164700.19891-3-abdul.b.ijaz@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20230919164700.19891-1-abdul.b.ijaz@intel.com> References: <20230919164700.19891-1-abdul.b.ijaz@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Abdul Basit Ijaz via Gdb-patches From: Abdul Basit Ijaz Reply-To: Abdul Basit Ijaz Cc: "Ijaz, Abdul B" , lsix@lancelotsix.com, pedro@palves.net Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" From: "Ijaz, Abdul B" 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="test.c",line="4"},{name="y",value="52"},{name="x",value="42",file="test.c",line="2",shadowed="true"}] (gdb) -stack-list-locals 2 ^done,locals=[{name="x",type="int",value="99",file="test.c",line="4"},{name="y",type="int",value="52"},{name="x",type="int",value="42",file="test.c",line="2",shadowed="true"}] (gdb) -stack-list-variables 0 ^done,variables=[{name="x",file="test.c",line="4"},{name="y"},{name="x",file="test.c",line="2",shadowed="true"}] (gdb) -stack-list-variables 1 ^done,variables=[{name="x",value="99",file="test.c",line="4"},{name="y",value="52"},{name="x",value="42",file="test.c",line="2",shadowed="true"}] (gdb) -stack-list-variables 2 ^done,variables=[{name="x",type="int",value="99",file="test.c",line="4"},{name="y",type="int",value="52"},{name="x",type="int",value="42",file="test.c",line="2",shadowed="true"}] ~~~ --- gdb/doc/gdb.texinfo | 13 ++ gdb/mi/mi-cmd-stack.c | 66 +++++++++- gdb/testsuite/gdb.mi/mi-var-shadowing.c | 48 ++++++++ gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141 ++++++++++++++++++++++ 4 files changed, 264 insertions(+), 4 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/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 6a22bbf2531..810e240da6f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -34430,6 +34430,19 @@ 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; // breakpt +4: @} +(gdb) -stack-list-variables 2 +^done,variables=[@{name="x",type="int",value="4",file="name.c",line="3"@},@{name="x",type="int",value="3",file="name.c",line="1",shadowed="true"@}] +@end smallexample + +If a variable is shadowed, then location information is printed and for +the outermost scope variables, the @code{shadowed} attribute is printed +as well. + @subsubheading Example @smallexample diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c index e473be7d465..21638796b63 100644 --- a/gdb/mi/mi-cmd-stack.c +++ b/gdb/mi/mi-cmd-stack.c @@ -38,6 +38,8 @@ #include "gdbsupport/gdb-safe-ctype.h" #include "inferior.h" #include "observable.h" +#include "include/libiberty.h" +#include enum what_to_list { locals, arguments, all }; @@ -491,7 +493,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) + enum print_values values, int skip_unavailable, + const std::unordered_set *shadowed_vars, + std::unordered_set &printed_vars) { struct ui_out *uiout = current_uiout; @@ -520,6 +524,18 @@ 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 (); + bool already_printed = !printed_vars.insert (name).second; + printed_vars.insert (name); + 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 (current_language->la_language == language_rust + && shadowed && already_printed) + return; stb.puts (arg->sym->print_name ()); if (arg->entry_kind == print_entry_values_only) @@ -559,6 +575,23 @@ 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 ((current_language->la_language == language_c + || current_language->la_language == language_cplus + || current_language->la_language == language_fortran + || current_language->la_language == language_ada) + && !(values == PRINT_NO_VALUES && what == locals) + && shadowed) + { + const char *file_name = lbasename (arg->sym->owner.symtab->filename); + uiout->field_string ("file", file_name); + uiout->field_unsigned ("line", arg->sym->m_line); + if (already_printed) + uiout->field_string ("shadowed", "true"); + } } /* Print a list of the objects for the frame FI in a certain form, @@ -572,9 +605,10 @@ list_args_or_locals (const frame_print_options &fp_opts, enum what_to_list what, enum print_values values, 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; + std::unordered_set collected_vars, shadowed_vars, printed_vars; block = get_frame_block (fi, 0); @@ -595,6 +629,26 @@ list_args_or_locals (const frame_print_options &fp_opts, ui_out_emit_list list_emitter (uiout, name_of_result); + 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)) + { + if (!sym->is_argument ()) + { + const char *name = sym->print_name (); + if (!collected_vars.insert (name).second) + shadowed_vars.insert (name); + } + } + if (block->function ()) + break; + block = block->superblock (); + } + + block = orig_block; while (block != 0) { for (struct symbol *sym : block_iterator_range (block)) @@ -663,9 +717,13 @@ 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); + list_arg_or_local (&arg, what, values, + skip_unavailable, &shadowed_vars, + printed_vars); if (entryarg.entry_kind != print_entry_values_no) - list_arg_or_local (&entryarg, what, values, skip_unavailable); + list_arg_or_local (&entryarg, what, values, + skip_unavailable, &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..f58a055c5e5 --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.c @@ -0,0 +1,48 @@ +/* Copyright (C) 2023 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 . */ + +#include + +void +shadowing (void) +{ + int a; /* 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..d0a4c3cd79a --- /dev/null +++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.exp @@ -0,0 +1,141 @@ +# Copyright 2023 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 . + +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" ${srcfile}] +set bp_line2 [gdb_get_line_number "bp for locals 2" ${srcfile}] +set bp_line3 [gdb_get_line_number "bp for locals 3" ${srcfile}] +set bp_line4 [gdb_get_line_number "bp for locals 4" ${srcfile}] +set bp_line5 [gdb_get_line_number "bp for locals 5" ${srcfile}] + +set val1_d1 [gdb_get_line_number "val1-d1" ${srcfile}] +set val1_d2 [gdb_get_line_number "val1-d2" ${srcfile}] +set val1_d3 [gdb_get_line_number "val1-d3" ${srcfile}] +set val2_d1 [gdb_get_line_number "val2-d1" ${srcfile}] +set val2_d2 [gdb_get_line_number "val2-d2" ${srcfile}] +set val2_d3 [gdb_get_line_number "val2-d3" ${srcfile}] +set val3_d1 [gdb_get_line_number "val3-d1" ${srcfile}] +set val3_d2 [gdb_get_line_number "val3-d2" ${srcfile}] +set a_line [gdb_get_line_number "entry bp" ${srcfile}] + +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=\"$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=\"$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" +set stack_test3_regx "\\^done,(locals|variables)=\\\[\{name=\"val1\",type=\"unsigned int\",value=\"5\",file=\"$srcfile\",line=\"$val1_d2\"\},\{name=\"val2\",type=\"unsigned int\",value=\"3\",file=\"$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=\"$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\",file=\"$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" +set stack_test4_regx "\\^done,(locals|variables)=\\\[\{name=\"val1\",type=\"unsigned int\",value=\"6\",file=\"$srcfile\",line=\"$val1_d3\"\},\{name=\"val2\",type=\"unsigned int\",value=\"7\",file=\"$srcfile\",line=\"$val2_d3\"\},\{name=\"val3\",type=\"unsigned int\",value=\"8\",file=\"$srcfile\",line=\"$val3_d2\"\},\{name=\"val1\",type=\"unsigned int\",value=\"5\",file=\"$srcfile\",line=\"$val1_d2\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"3\",file=\"$srcfile\",line=\"$val2_d2\",shadowed=\"true\"\},\{name=\"val3\",type=\"unsigned int\",value=\"4\",file=\"$srcfile\",line=\"$val3_d1\",shadowed=\"true\"\},\{name=\"a\",type=\"int\",value=\"103\"\},\{name=\"val1\",type=\"unsigned int\",value=\"1\",file=\"$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},\{name=\"val2\",type=\"unsigned int\",value=\"2\",file=\"$srcfile\",line=\"$val2_d1\",shadowed=\"true\"\}\\\]" +set stack_test5_regx "\\^done,(locals|variables)=\\\[\{name=\"a\",type=\"int\",value=\"104\"\},\{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=\"$srcfile\",line=\"$val2_d2\"},{name=\"val3\"},{name=\"a\"},{name=\"val1\"},{name=\"val2\",file=\"$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=\"$srcfile\",line=\"$val1_d2\"},{name=\"val2\",file=\"$srcfile\",line=\"$val2_d2\"},{name=\"val3\"},{name=\"a\"},{name=\"val1\",file=\"$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},{name=\"val2\",file=\"$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=\"$srcfile\",line=\"$val1_d3\"},{name=\"val2\",file=\"$srcfile\",line=\"$val2_d3\"},{name=\"val3\",file=\"$srcfile\",line=\"$val3_d2\"},{name=\"val1\",file=\"$srcfile\",line=\"$val1_d2\",shadowed=\"true\"\},\{name=\"val2\",file=\"$srcfile\",line=\"$val2_d2\",shadowed=\"true\"\},\{name=\"val3\",file=\"$srcfile\",line=\"$val3_d1\",shadowed=\"true\"\},{name=\"a\"},{name=\"val1\",file=\"$srcfile\",line=\"$val1_d1\",shadowed=\"true\"\},{name=\"val2\",file=\"$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"