From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id CaXvAywAVWqFWAYAWB0awg (envelope-from ) for ; Mon, 13 Jul 2026 11:11:40 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g/yMCOR5; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 0ACD01E033; Mon, 13 Jul 2026 11:11:40 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-6.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham autolearn_force=no version=4.0.1 Received: from vm01.sourceware.org (vm01.sourceware.org [IPv6:2620:52:6:3111::32]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id F1AC51E033 for ; Mon, 13 Jul 2026 11:11:37 -0400 (EDT) Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 39B624BA2E15 for ; Mon, 13 Jul 2026 15:11:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 39B624BA2E15 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g/yMCOR5 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 9C6AF4BA2E07 for ; Mon, 13 Jul 2026 15:11:06 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 9C6AF4BA2E07 Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 9C6AF4BA2E07 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783955466; cv=none; b=ZqyikHJcck0OrhR/QO1gVJuokHbTkbGodtSh2gF6bPLaQw2eOKKT/mOH35QafnDkcfo7aOL2qlACY/TVNdpLnDiga2XGa+VSsb6TVLtw1b3TW26KEolGU91yQ1fqHHOfMuIWid9Vr+zuQSuyCjLPeWWesYsI5RWlbjefzCeDlmE= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1783955466; c=relaxed/simple; bh=ikm6sK5G01bjzrSrBSIhXmPuLb+jCFr8RPeDawldhvU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=lYIjejp9vdu3VWJ3nq1nUzSSZs6CPzzKlruWwGSm1UdI+jNyVfVFJ/VepYLy9QwokUYfnQDMpuXvRDC0UnkeKwlf1noLB39PDxykqKyJyWbOdZ206rB77M8I+FW9OfKT9idMfAl9GEpjABAywrSF/vTF0Zsh4rVJruh3EuHtRrI= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=g/yMCOR5 DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9C6AF4BA2E07 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1783955466; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G6vZnIdeiKW2FdRsx3is1+oBAGgYA4TOKG34yDiMiTQ=; b=g/yMCOR5K3ks4hbuzeWD7XkoXUK04Om5CxfElQYXdjgyXPKMM7KhYguibTgiUIEgwad7+A 84DLzmt80vZXw5qYgM0KQZ8obnlGajAcxBjxMHZhhklvPoAwS7lBgnPjjTKwl74/n80DFP /9pquFYR1/8vdvuEnDzj/Xd4BCDx/AM= Received: from mail-wm1-f69.google.com (mail-wm1-f69.google.com [209.85.128.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-136-DyEozFMFMU6itmr0R2swuQ-1; Mon, 13 Jul 2026 11:11:04 -0400 X-MC-Unique: DyEozFMFMU6itmr0R2swuQ-1 X-Mimecast-MFC-AGG-ID: DyEozFMFMU6itmr0R2swuQ_1783955464 Received: by mail-wm1-f69.google.com with SMTP id 5b1f17b1804b1-493caa3c54eso32934135e9.2 for ; Mon, 13 Jul 2026 08:11:04 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783955463; x=1784560263; h=content-transfer-encoding:content-type:mime-version:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=00x2qdYM2kFFyyQlnZF9hNSStHDhOixbfMYXtcE79sI=; b=HvneoEO/3a859gcPzsy1P7sfoLyIv992eK37F8acqskqg7p5Ary8ZYNyq8vvZiDUxt Z9UJUMyDFQzpYX4DKkZeqh9nUy/hWafKEjeo6AAl7QlgcGp108MSNL841LddswiahOwu FpKQYM9r2lZzHA8M5ZGpM6z4gRH5ldVnJL532roHDV96m4F0AXYXxC9HVAgOE0+UvJOT dLV6BPOgeKTSfaNUEPNuRH26YCx0Od+FuN6BNRCz+Tkv0fLQVFgVx2hWrNhccRHJOAdV 4d/dV0AC0A/Bh3dh1/Ywc2pW4qlOEvbkLU6KxBOKeK6HSYO63oVyjm9YK4dFwp3m/VwW KY5A== X-Forwarded-Encrypted: i=1; AHgh+RqT8SWHr+jVqLCzbEWJCLGaj6h3lhIbbtoXhsXhvCKzhjbTEuL0PL7r5zEb+JCvMu2+4KnMdvGLkK3W3w==@sourceware.org X-Gm-Message-State: AOJu0YwF/NTn/YYRf07D7OYup5xnmBvO9nFp8fANtxH0fMe8tgDK1I78 nf3AQDLSt1TKYAL3NwxDA9hclT11CbmD/AoAcy6pYZ60U+ySVFrtql6fiSdKFjlW4IzB3oyE8ZX 9Qa0DycYD7SDiXF/oOc441asoAAOh9juvqkvEQrFncLVlZc7hxt6GFdwnjmcFH5diwaxgsss= X-Gm-Gg: AfdE7ckZJW6KlzCRMj4CLFL7P+8xugsg97XeELKWc/ooNFICUneOQangDn117NQ9u+r OU06d70+ElRLjyXN3faA3cSodBVUDdnq6I9s5JHgrxjgI315L9IrJ8EYwle1uczfRs98K1veRZl /FsmoI2k+gftccyXBHcAdn2Gacof9LOOu5asy6jbVIedKtykYgz3pIiERX9AaZRARuQOvmPiNaJ VE6b9DUllIvQsnctjWMo3I4V4F0nQn3HyM70QZBYd09GJaBKbLqL6EuPyEmddPoq3rfyR2TU9eY fuC2706oj+/E0I4Lv5oVHhrmNJNk5P3WFVGycQ+Snx6z9yGI4m3+gyQbXJFjH9Ny1ZmBAoK6KO4 qxBtgypo= X-Received: by 2002:a05:600c:5489:b0:492:68f5:6b30 with SMTP id 5b1f17b1804b1-493f87f1b34mr95404655e9.17.1783955462913; Mon, 13 Jul 2026 08:11:02 -0700 (PDT) X-Received: by 2002:a05:600c:5489:b0:492:68f5:6b30 with SMTP id 5b1f17b1804b1-493f87f1b34mr95404135e9.17.1783955462171; Mon, 13 Jul 2026 08:11:02 -0700 (PDT) Received: from localhost ([31.111.209.233]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4950a2e8f07sm2041415e9.7.2026.07.13.08.11.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jul 2026 08:11:01 -0700 (PDT) From: Andrew Burgess To: Abdul Basit Ijaz , gdb-patches@sourceware.org Cc: pedro@palves.net, philippe.waroquiers@skynet.be, christina.schimpe@intel.com, lsix@lancelotsix.com, eliz@gnu.org, abdul.b.ijaz@intel.com, guinevere@redhat.com Subject: Re: [PATCH v13 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands In-Reply-To: <20260708180805.207722-3-abdul.b.ijaz@intel.com> References: <20260708180805.207722-1-abdul.b.ijaz@intel.com> <20260708180805.207722-3-abdul.b.ijaz@intel.com> Date: Mon, 13 Jul 2026 16:11:00 +0100 Message-ID: <87qzl6exh7.fsf@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: -Dpb8ZOG2i-RZWS6_U_rKBVEuWuJeO9pq6CWr375Bbw_1783955464 X-Mimecast-Originator: redhat.com Content-Type: text/plain Content-Transfer-Encoding: quoted-printable 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: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org Thank you for continuing to work on this feature. I have some comments inline below. Abdul Basit Ijaz writes: > 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 inform= ation > for shadowed variables and add 'shadowed' field also in '-stack-list-loca= ls' > and '-stack-list-variables' mi commands for super-block shadowed variable= . > > Suppose we have test.c file > > 1:int x =3D 42; > 2: { > 3: int x =3D 99; > 4: int y =3D 52; > 5: x =3D 99; /* break here */ > 6: } > > 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=3D[name=3D"x",name=3D"y",name=3D"x"] > (gdb) > -stack-list-locals 1 > ^done,locals=3D[{name=3D"x",value=3D"99"},{name=3D"y",value=3D"52"},{name= =3D"x",value=3D"42"}] > (gdb) > -stack-list-locals 2 > ^done,locals=3D[{name=3D"x",type=3D"int",value=3D"99"},{name=3D"y",type= =3D"int",value=3D"52"},{name=3D"x",type=3D"int",value=3D"42"}] > (gdb) > -stack-list-variables 0 > ^done,variables=3D[{name=3D"x"},{name=3D"y"},{name=3D"x"}] > (gdb) > -stack-list-variables 1 > ^done,variables=3D[{name=3D"x",value=3D"99"},{name=3D"y",value=3D"52"},{n= ame=3D"x",value=3D"42"}] > (gdb) > -stack-list-variables 2 > ^done,variables=3D[{name=3D"x",type=3D"int",value=3D"99"},{name=3D"y",typ= e=3D"int",value=3D"52"},{name=3D"x",type=3D"int",value=3D"42"}] > ~~~ > > With this patch we obtain: > > ~~~ > (gdb) > -stack-list-locals 0 > ^done,locals=3D[name=3D"x",name=3D"y",name=3D"x"] > (gdb) > -stack-list-locals 1 > ^done,locals=3D[{name=3D"x",value=3D"99",file=3D"/home/src/test.c",line= =3D"5"},{name=3D"y",value=3D"52"},{name=3D"x",value=3D"42",file=3D"/home/sr= c/test.c",line=3D"2",shadowed=3D"true"}] > (gdb) > -stack-list-locals 2 > ^done,locals=3D[{name=3D"x",type=3D"int",value=3D"99",file=3D"/home/src/t= est.c",line=3D"5"},{name=3D"y",type=3D"int",value=3D"52"},{name=3D"x",type= =3D"int",value=3D"42",file=3D"/home/src/test.c",line=3D"2",shadowed=3D"true= "}] > (gdb) > -stack-list-variables 0 > ^done,variables=3D[{name=3D"x",file=3D"/home/src/test.c",line=3D"5"},{nam= e=3D"y"},{name=3D"x",file=3D"/home/src/test.c",line=3D"2",shadowed=3D"true"= }] > (gdb) > -stack-list-variables 1 > ^done,variables=3D[{name=3D"x",value=3D"99",file=3D"/home/src/test.c",lin= e=3D"4"},{name=3D"y",value=3D"52"},{name=3D"x",value=3D"42",file=3D"/home/s= rc/test.c",line=3D"2",shadowed=3D"true"}] > (gdb) > -stack-list-variables 2 > ^done,variables=3D[{name=3D"x",type=3D"int",value=3D"99",file=3D"/home/sr= c/test.c",line=3D"4"},{name=3D"y",type=3D"int",value=3D"52"},{name=3D"x",ty= pe=3D"int",value=3D"42",file=3D"/home/src/test.c",line=3D"2",shadowed=3D"tr= ue"}] > ~~~ > Reviewed-By: Guinevere Larsen > --- > gdb/NEWS | 4 + > gdb/doc/gdb.texinfo | 21 ++++ > gdb/mi/mi-cmd-stack.c | 129 ++++++++++++++------ > gdb/testsuite/gdb.mi/mi-var-shadowing.c | 50 ++++++++ > gdb/testsuite/gdb.mi/mi-var-shadowing.exp | 141 ++++++++++++++++++++++ > 5 files changed, 310 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 6807a6c966b..483d2013e41 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -593,6 +593,10 @@ multi-wp-addr in qSupported > multiple times, and the same mapping was being reused. In all > other cases, this field will have the value 'false'. > =20 > +** 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. > =20 > diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo > index ee33bfdba13..64a1345e2f2 100644 > --- a/gdb/doc/gdb.texinfo > +++ b/gdb/doc/gdb.texinfo > @@ -35585,6 +35585,27 @@ If the @code{--skip-unavailable} option is speci= fied, local variables > and arguments that are not available are not listed. Partially > available arguments and local variables are still displayed, however. > =20 > +@smallexample > +@group > +1: int x =3D 3; > +2: @{ > +3: int x =3D 4; > +4: int y =3D 5; > +4: x =3D 99; // breakpoint-line Duplicate line number in this example. > +5: @} > +@end group > +@group > +(gdb) -stack-list-variables 2 > +^done,variables=3D[@{name=3D"x",type=3D"int",value=3D"4", > +file=3D"/home/src/name.c",line=3D"3"@},@{name=3D"y",type=3D"int",value= =3D"5", > +file=3D"/home/src/name.c",line=3D"4"@},@{name=3D"x",type=3D"int",value= =3D"3", > +file=3D"/home/src/name.c",line=3D"1",shadowed=3D"true"@}] > +@end group > +@end smallexample > + > +The location information and @samp{shadowed} attribute is only added > +for shadowed variables (@pxref{shadowed variables}). > + > @subsubheading Example > =20 > @smallexample > diff --git a/gdb/mi/mi-cmd-stack.c b/gdb/mi/mi-cmd-stack.c > index 280a08d121e..38955cc697b 100644 > --- a/gdb/mi/mi-cmd-stack.c > +++ b/gdb/mi/mi-cmd-stack.c > @@ -32,6 +32,7 @@ > #include "mi-parse.h" > #include > #include "inferior.h" > +#include "gdbsupport/unordered_map.h" > =20 > enum what_to_list { locals, arguments, all }; > =20 > @@ -490,7 +491,9 @@ mi_cmd_stack_list_variables (const char *command, con= st char *const *argv, > static void > list_arg_or_local (const struct frame_arg *arg, enum what_to_list what, > =09=09 enum print_values values, int skip_unavailable, > -=09=09 const frame_print_options &fp_opts) > +=09=09 const frame_print_options &fp_opts, > +=09=09 const gdb::unordered_set *shadowed_vars, > +=09=09 gdb::unordered_set &printed_vars) > { > struct ui_out *uiout =3D current_uiout; > =20 > @@ -519,6 +522,19 @@ list_arg_or_local (const struct frame_arg *arg, enum= what_to_list what, > tuple_emitter.emplace (uiout, nullptr); > =20 > string_file stb; > + const char *name =3D arg->sym->print_name (); > + /* To distinguish innermost variable from the rest in the shadowed_var= s > + this boolen is needed. */ Typo: s/boolen/boolean/ > + bool already_printed =3D !printed_vars.insert (name).second; > + bool shadowed =3D shadowed_vars->find (name) !=3D 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) > + =3D=3D lang_vars_shadowing::HIDE && shadowed && already_printed) > + return; I haven't created a reproducer, but I think there's an issue here. By the time we reach this line the `tuple_emitter` has already had a value emplaced, so if the rust early return triggers the tuple_emitter is going to emit an empty tuple ... at least I think that's what will happen. I think the code that give tuple_emitter a value needs to be after the rust early return. > =20 > stb.puts (arg->sym->print_name ()); > if (arg->entry_kind =3D=3D print_entry_values_only) > @@ -560,6 +576,59 @@ list_arg_or_local (const struct frame_arg *arg, enum= what_to_list what, > =09} > uiout->field_stream ("value", stb); > } > + > + /* Only for C/C++/Fortran/Ada languages, in case of variables shadowin= g > + print shadowed field after the superblock variable and only locatio= n > + of the variables in the innerblock. */ > + if (get_lang_vars_shadowing_option (current_language->la_language) > + =3D=3D lang_vars_shadowing::PRINT && shadowed > + && !(values =3D=3D PRINT_NO_VALUES && what =3D=3D locals)) > + { > + uiout->field_string ("file", arg->sym->symtab ()->filename ()); > + uiout->field_unsigned ("line", arg->sym->m_line); In the non-MI path you ended up having to guard the equivalent code to handle the case where symtab was NULL, but here you don't have a similar guard. I suspect the issue here is that the test you quote for the non-MI path gdb.dwarf2/missing-type-name-for-templates.exp, doesn't have shadowing, but does have the missing symtab case. In the non-MI code you use the symtab even when shadowing didn't occur (I suggested moving the code), which is why you hit the issue, but I suspect you might be able to both shadowing and no symtab ... maybe? When I tried to reproduce this I was ending up with a symtab with the name "", I'll leave you to investigate this more. Additionally, here, if you look at the function `mi_symbol_info` and `output_module_symbols_in_single_module_and_file` you'll see they always emit two strings, "filename" and "fullname", I think that you should follow the same pattern here. Also, the access to m_line should be done via the public 'line ()' method. One day maybe we'll even make these member variables private. > + if (already_printed) > +=09uiout->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 =3D false; > + > + switch (sym->loc_class ()) > + { > + default: > +=09case LOC_UNDEF: /* catches errors */ > +=09case LOC_CONST: /* constant */ > +=09case LOC_TYPEDEF: /* local typedef */ > +=09case LOC_LABEL: /* local label */ > +=09case LOC_BLOCK: /* local function */ > +=09case LOC_CONST_BYTES: /* loc. byte seq. */ > +=09case LOC_UNRESOLVED: /* unresolved static */ > +=09case LOC_OPTIMIZED_OUT: /* optimized out */ > +=09 print_me =3D false; > +=09 break; Not something I think you need to fix as this is moved code, but I noticed it while reviewing this patch -- this switch is almost certainly wrong. There's no reason why we cannot print LOC_CONST variables, e.g. variables defined with DW_AT_const_value. Also LOC_OPTIMIZED_OUT should probably be printed, if I do 'info locals' then I will see optimised out locals, but '-stack-list-locals 1' will skip them, which doesn't seem right to me. But this bug exists before this patch, so it's not yours to fix. You could however convert PRINT_ME from 'int' to 'bool', that would be a simple fix. And the indentation of the 'default' and 'case ...' statements seems to be messed up. Likely everything within the switch needs to be re-indented I think. > + > +=09case LOC_ARG: /* argument */ > +=09case LOC_REF_ARG: /* reference arg */ > +=09case LOC_REGPARM_ADDR: /* indirect register arg */ > +=09case LOC_LOCAL: /* stack local */ > +=09case LOC_STATIC: /* static */ > +=09case LOC_REGISTER: /* register */ > +=09case LOC_COMPUTED: /* computed location */ > +=09 if (what =3D=3D all) > +=09 print_me =3D true; > +=09 else if (what =3D=3D locals) > +=09 print_me =3D !sym->is_argument (); > +=09 else > +=09 print_me =3D sym->is_argument (); > +=09 break; > + } > + > + return print_me; > } > =20 > /* 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_o= pts, > =09=09 enum what_to_list what, enum print_values values, > =09=09 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 =3D current_uiout; > + gdb::unordered_set collected_vars, shadowed_vars, printed= _vars; > =20 > block =3D get_frame_block (fi, 0); > =20 > @@ -596,42 +666,31 @@ list_args_or_locals (const frame_print_options &fp_= opts, > =20 > ui_out_emit_list list_emitter (uiout, name_of_result); > =20 > - while (block !=3D 0) > + orig_block =3D block; > + /* Stored list of shadowed variables later help in identifying them > + from the rest. */ > + while (block !=3D nullptr) > { > for (struct symbol *sym : block_iterator_range (block)) > =09{ > -=09 int print_me =3D 0; > - > -=09 switch (sym->loc_class ()) > +=09 if (can_print_aclass (sym, what)) > =09 { > -=09 default: > -=09 case LOC_UNDEF:=09/* catches errors */ > -=09 case LOC_CONST:=09/* constant */ > -=09 case LOC_TYPEDEF:=09/* local typedef */ > -=09 case LOC_LABEL:=09/* local label */ > -=09 case LOC_BLOCK:=09/* local function */ > -=09 case LOC_CONST_BYTES:=09/* loc. byte seq. */ > -=09 case LOC_UNRESOLVED:=09/* unresolved static */ > -=09 case LOC_OPTIMIZED_OUT:=09/* optimized out */ > -=09 print_me =3D 0; > -=09 break; > - > -=09 case LOC_ARG:=09/* argument */ > -=09 case LOC_REF_ARG:=09/* reference arg */ > -=09 case LOC_REGPARM_ADDR:=09/* indirect register arg */ > -=09 case LOC_LOCAL:=09/* stack local */ > -=09 case LOC_STATIC:=09/* static */ > -=09 case LOC_REGISTER:=09/* register */ > -=09 case LOC_COMPUTED:=09/* computed location */ > -=09 if (what =3D=3D all) > -=09=09print_me =3D 1; > -=09 else if (what =3D=3D locals) > -=09=09print_me =3D !sym->is_argument (); > -=09 else > -=09=09print_me =3D sym->is_argument (); > -=09 break; > +=09 const char *name =3D sym->print_name (); > +=09 if (!collected_vars.insert (name).second) > +=09=09shadowed_vars.insert (name); > =09 } > -=09 if (print_me) > +=09} > + if (block->function ()) > +=09break; > + block =3D block->superblock (); > + } > + > + block =3D orig_block; > + while (block !=3D 0) > + { > + for (struct symbol *sym : block_iterator_range (block)) > +=09{ > +=09 if (can_print_aclass (sym, what)) > =09 { > =09 struct frame_arg arg, entryarg; > =20 > @@ -657,10 +716,10 @@ list_args_or_locals (const frame_print_options &fp_= opts, > =20 > =09 if (arg.entry_kind !=3D print_entry_values_only) > =09=09list_arg_or_local (&arg, what, values, skip_unavailable, > -=09=09=09=09 fp_opts); > +=09=09=09=09 fp_opts, &shadowed_vars, printed_vars); > =09 if (entryarg.entry_kind !=3D print_entry_values_no) > =09=09list_arg_or_local (&entryarg, what, values, skip_unavailable, > -=09=09=09=09 fp_opts); > +=09=09=09=09 fp_opts, &shadowed_vars, printed_vars); > =09 } > =09} > =20 > 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..875e753b485 > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.c > @@ -0,0 +1,50 @@ > +/* Copyright (C) 2023-2026 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 > + > +int > +shadowing (void) > +{ > + int a =3D 100;=09/* entry bp */ > + unsigned int val1 =3D 1;=09=09/* val1-d1 */ > + unsigned int val2 =3D 2;=09=09/* val2-d1 */ > + a =3D 101; /* bp for locals 1 */ > + { > + unsigned int val2 =3D 3;=09=09/* val2-d2 */ > + unsigned int val3 =3D 4;=09=09/* val3-d1 */ > + a =3D 102; /* bp for locals 2 */ > + { > + unsigned int val1 =3D 5;=09=09/* val1-d2 */ > + a =3D 103; /* bp for locals 3 */ > + { > +=09unsigned int val1 =3D 6;=09=09/* val1-d3 */ > +=09unsigned int val2 =3D 7;=09=09/* val2-d3 */ > +=09unsigned int val3 =3D 8;=09=09/* val3-d2 */ > +=09a =3D 104; /* bp for locals 4 */ > + } > + } > + } > + a =3D 105; > + > + return 0; /* bp for locals 5 */ > +} > + > +int > +main (void) > +{ > + shadowing (); > + return 0; > +} > diff --git a/gdb/testsuite/gdb.mi/mi-var-shadowing.exp b/gdb/testsuite/gd= b.mi/mi-var-shadowing.exp > new file mode 100644 > index 00000000000..f88c8c81736 > --- /dev/null > +++ b/gdb/testsuite/gdb.mi/mi-var-shadowing.exp > @@ -0,0 +1,141 @@ > +# Copyright 2023-2026 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=3Dmi" > + > +gdb_exit > +if [mi_gdb_start] { > + continue > +} > + > +standard_testfile > + > +set opts {debug} > +if [build_executable ${testfile}.exp ${testfile} ${srcfile} $opts] { > + return -1 Just 'return' at the top level, no -1 needed. Thanks, Andrew > +} > + > +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)=3D\\\[\{name=3D\"a\",ty= pe=3D\"int\",value=3D\"$decimal\"\},\{name=3D\"val1\",type=3D\"unsigned int= \",value=3D\"1\"\},{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"2\"\}= \\\]" > +set stack_test2_regx "\\^done,(locals|variables)=3D\\\[\{name=3D\"val2\"= ,type=3D\"unsigned int\",value=3D\"3\",file=3D\"$srcdir/$subdir/$srcfile\",= line=3D\"$val2_d2\"\},\{name=3D\"val3\",type=3D\"unsigned int\",value=3D\"4= \"\},\{name=3D\"a\",type=3D\"int\",value=3D\"101\"\},\{name=3D\"val1\",type= =3D\"unsigned int\",value=3D\"1\"\},\{name=3D\"val2\",type=3D\"unsigned int= \",value=3D\"2\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val2_d1\",sh= adowed=3D\"true\"\}\\\]" > +set stack_test3_regx "\\^done,(locals|variables)=3D\\\[\{name=3D\"val1\"= ,type=3D\"unsigned int\",value=3D\"5\",file=3D\"$srcdir/$subdir/$srcfile\",= line=3D\"$val1_d2\"\},\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"3= \",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val2_d2\"\},\{name=3D\"val= 3\",type=3D\"unsigned int\",value=3D\"4\"\},\{name=3D\"a\",type=3D\"int\",v= alue=3D\"102\"\},\{name=3D\"val1\",type=3D\"unsigned int\",value=3D\"1\",fi= le=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val1_d1\",shadowed=3D\"true\"\}= ,\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"2\",file=3D\"$srcdir/$= subdir/$srcfile\",line=3D\"$val2_d1\",shadowed=3D\"true\"\}\\\]" > +set stack_test4_regx "\\^done,(locals|variables)=3D\\\[\{name=3D\"val1\"= ,type=3D\"unsigned int\",value=3D\"6\",file=3D\"$srcdir/$subdir/$srcfile\",= line=3D\"$val1_d3\"\},\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"7= \",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val2_d3\"\},\{name=3D\"val= 3\",type=3D\"unsigned int\",value=3D\"8\",file=3D\"$srcdir/$subdir/$srcfile= \",line=3D\"$val3_d2\"\},\{name=3D\"val1\",type=3D\"unsigned int\",value=3D= \"5\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val1_d2\",shadowed=3D\"= true\"\},\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"3\",file=3D\"$= srcdir/$subdir/$srcfile\",line=3D\"$val2_d2\",shadowed=3D\"true\"\},\{name= =3D\"val3\",type=3D\"unsigned int\",value=3D\"4\",file=3D\"$srcdir/$subdir/= $srcfile\",line=3D\"$val3_d1\",shadowed=3D\"true\"\},\{name=3D\"a\",type=3D= \"int\",value=3D\"103\"\},\{name=3D\"val1\",type=3D\"unsigned int\",value= =3D\"1\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val1_d1\",shadowed= =3D\"true\"\},\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"2\",file= =3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val2_d1\",shadowed=3D\"true\"\}\\= \]" > +set stack_test5_regx "\\^done,(locals|variables)=3D\\\[\{name=3D\"a\",ty= pe=3D\"int\",value=3D\"105\"\},\{name=3D\"val1\",type=3D\"unsigned int\",va= lue=3D\"1\"\},\{name=3D\"val2\",type=3D\"unsigned int\",value=3D\"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_line= 1}" \ > + { "" "disp=3D\"keep\"" } "continue to outermost level" > +mi_gdb_test "-stack-list-locals 0" \ > + "\\^done,locals=3D\\\[name=3D\"a\",name=3D\"val1\",name=3D\"val2\"\\= \]" \ > + "-stack-list-locals 0 at outermost level" > +mi_gdb_test "-stack-list-variables 0" \ > + "\\^done,variables=3D\\\[{name=3D\"a\"},{name=3D\"val1\"},{name=3D\"= 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_line= 2}" \ > + { "" "disp=3D\"keep\"" } "continue to first level" > +mi_gdb_test "-stack-list-locals 0" \ > + "\\^done,locals=3D\\\[name=3D\"val2\",name=3D\"val3\",name=3D\"a\",n= ame=3D\"val1\",name=3D\"val2\"\\\]" \ > + "-stack-list-locals 0 at first level" > +mi_gdb_test "-stack-list-variables 0" \ > + "\\^done,variables=3D\\\[{name=3D\"val2\",file=3D\"$srcdir/$subdir/$= srcfile\",line=3D\"$val2_d2\"},{name=3D\"val3\"},{name=3D\"a\"},{name=3D\"v= al1\"},{name=3D\"val2\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val2_= d1\",shadowed=3D\"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_line= 3}" \ > + { "" "disp=3D\"keep\"" } "continue to second level" > +mi_gdb_test "-stack-list-locals 0" \ > + "\\^done,locals=3D\\\[name=3D\"val1\",name=3D\"val2\",name=3D\"val3= \",name=3D\"a\",name=3D\"val1\",name=3D\"val2\"\\\]" \ > + "-stack-list-locals 0 at second level" > +mi_gdb_test "-stack-list-variables 0" \ > + "\\^done,variables=3D\\\[{name=3D\"val1\",file=3D\"$srcdir/$subdir/= $srcfile\",line=3D\"$val1_d2\"},{name=3D\"val2\",file=3D\"$srcdir/$subdir/$= srcfile\",line=3D\"$val2_d2\"},{name=3D\"val3\"},{name=3D\"a\"},{name=3D\"v= al1\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val1_d1\",shadowed=3D\"= true\"\},{name=3D\"val2\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val= 2_d1\",shadowed=3D\"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_line= 4}" \ > + { "" "disp=3D\"keep\"" } "continue to third level" > +mi_gdb_test "-stack-list-locals 0" \ > + "\\^done,locals=3D\\\[name=3D\"val1\",name=3D\"val2\",name=3D\"val3\= ",name=3D\"val1\",name=3D\"val2\",name=3D\"val3\",name=3D\"a\",name=3D\"val= 1\",name=3D\"val2\"\\\]" \ > + "-stack-list-locals 0 at third level" > +mi_gdb_test "-stack-list-variables 0" \ > + "\\^done,variables=3D\\\[{name=3D\"val1\",file=3D\"$srcdir/$subdir/$= srcfile\",line=3D\"$val1_d3\"},{name=3D\"val2\",file=3D\"$srcdir/$subdir/$s= rcfile\",line=3D\"$val2_d3\"},{name=3D\"val3\",file=3D\"$srcdir/$subdir/$sr= cfile\",line=3D\"$val3_d2\"},{name=3D\"val1\",file=3D\"$srcdir/$subdir/$src= file\",line=3D\"$val1_d2\",shadowed=3D\"true\"\},\{name=3D\"val2\",file=3D\= "$srcdir/$subdir/$srcfile\",line=3D\"$val2_d2\",shadowed=3D\"true\"\},\{nam= e=3D\"val3\",file=3D\"$srcdir/$subdir/$srcfile\",line=3D\"$val3_d1\",shadow= ed=3D\"true\"\},{name=3D\"a\"},{name=3D\"val1\",file=3D\"$srcdir/$subdir/$s= rcfile\",line=3D\"$val1_d1\",shadowed=3D\"true\"\},{name=3D\"val2\",file=3D= \"$srcdir/$subdir/$srcfile\",line=3D\"$val2_d1\",shadowed=3D\"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_line= 5}" \ > + { "" "disp=3D\"keep\"" } "continue to outermost level last" > +mi_gdb_test "-stack-list-locals 0" \ > + "\\^done,locals=3D\\\[name=3D\"a\",name=3D\"val1\",name=3D\"val2\"\\= \]" \ > + "-stack-list-locals 0 at outermost level last" > +mi_gdb_test "-stack-list-variables 0" \ > + "\\^done,variables=3D\\\[{name=3D\"a\"},{name=3D\"val1\"},{name=3D\"= 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" > --=20 > 2.34.1 > > Intel Deutschland GmbH > > Registered Address: Dornacher Strasse 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 Muenchen HRB 186928