public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: "Ijaz, Abdul B" <abdul.b.ijaz@intel.com>
To: Lancelot SIX <lsix@lancelotsix.com>
Cc: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
	"pedro@palves.net" <pedro@palves.net>
Subject: RE: [PATCH v3 1/2] gdb: add annotation in 'info locals' command for variables shadowing case
Date: Tue, 19 Sep 2023 07:50:09 +0000	[thread overview]
Message-ID: <CY8PR11MB684478119E8446FFA78ED43ECBFAA@CY8PR11MB6844.namprd11.prod.outlook.com> (raw)
In-Reply-To: <20230918224557.czfvzbzzmq3ceaj5@octopus>

Hi Lancelot,

Thanks a lot for your feedback and pointing out the improvements. All these will be fixed in V4 patch series which I will try to test and push for review today.

> > +      size_t slash_index = file_path.find_last_of ("\\/");

> I think you might prefer to use lbasename (include/libiberty.h) as I guess this search can fail.  
This is helpful thanks for pointing to this header file.  Will be updated in Patch v4.

>> +      std::string file_name = (!file_path.empty ()
>> +			       ? file_path.substr (slash_index + 1)
>> +			       : "NA");
> As for the "NA" case, I am not sure when it can happen.  If the symtab's filename can be nullptr (or start with \0), a test might be necessary.
Will not be using NA anymore in Patch v4 as I am also not aware of NA case.

>> +			   std::unordered_set<std::string> shadowed_vars,

> This shadowed_vars parameter is only searched, not modified.  Did you mean to pass it by const ref?  Otherwise, you end-up copying the entire set.
Using const and by reference would be right here so will be added in V4 patch.

>> +      printed_vars.insert (name);

>I think you can simplify this a bit by using std::unordered_set<T>::insert's return value.  It is a pair whose second element is a bool indicating if the insertion took place.  If false, it means that the element was already in the set.

  >  bool already_printed = !printed_vars.insert (name).second;
Will be updated in v4 Patch.

>> +	  else
>> +	    {
>> +	      cb (name, sym, false, false);
>> +	    }

>As there is just one line in the else, no need for the { }.
Removing {} in Patch v4.

>>+  while (block)

>According to the GDB coding style, this should be

>  while (block != nullptr)
Updating in V4 patch.

>> +	    collected_vars.insert (name);

>Similarly, this could be

>  if (!collected_vars.insert (name).second)
 >   shadowed_vars.insert (name);
Fixed in V4 patch.

>> +void
>> +shadowing ()
 >             ^
>This should be

>void
>shadowing (void)
Fixing in V4 patch.

Thanks & Best Regards
Abdul Basit

-----Original Message-----
From: Lancelot SIX <lsix@lancelotsix.com> 
Sent: Tuesday, September 19, 2023 12:46 AM
To: Ijaz, Abdul B <abdul.b.ijaz@intel.com>
Cc: gdb-patches@sourceware.org; pedro@palves.net
Subject: Re: [PATCH v3 1/2] gdb: add annotation in 'info locals' command for variables shadowing case

Hi Abdul,

Thanks for working on this.  I have included some comments on the patch.

> diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 
> 8d7d04231fe..17e385138d2 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -2401,7 +2401,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 +2415,11 @@ print_variable_and_value (const char *name, struct symbol *var,
>      {
>        struct value *val;
>        struct value_print_options opts;
> +      std::string file_path = var->owner.symtab->filename;
> +      size_t slash_index = file_path.find_last_of ("\\/");

I think you might prefer to use lbasename (include/libiberty.h) as I guess this search can fail.  For example, "\" can in a filename on Linux (not saying it is a wise thing to do).

  const char *file_name = lbasename (var->owner.symtab->filename);

> +      std::string file_name = (!file_path.empty ()
> +			       ? file_path.substr (slash_index + 1)
> +			       : "NA");

As for the "NA" case, I am not sure when it can happen.  If the symtab's filename can be nullptr (or start with \0), a test might be necessary.

>  
>        /* 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 +2430,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.c_str (),
> +			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..f0f384c6270 
> 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 <unordered_set>
>  
>  /* The possible choices of "set print frame-arguments", and the value
>     of this setting.  */
> @@ -2211,10 +2212,18 @@ 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,
> +			   std::unordered_set<std::string> shadowed_vars,

This shadowed_vars parameter is only searched, not modified.  Did you mean to pass it by const ref?  Otherwise, you end-up copying the entire set.

> +			   std::unordered_set<std::string> &printed_vars)
>  {
>    for (struct symbol *sym : block_iterator_range (b))
>      {
> +      const char *name = sym->print_name ();
> +      bool already_printed
> +	= printed_vars.find (name) != printed_vars.end ();
> +      printed_vars.insert (name);

I think you can simplify this a bit by using std::unordered_set<T>::insert's return value.  It is a pair whose second element is a bool indicating if the insertion took place.  If false, it means that the element was already in the set.

    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 +2236,27 @@ 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 <file:line, shadowed> 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);
> +	    }

As there is just one line in the else, no need for the { }.

>  	  break;
>  
>  	default:
> @@ -2244,9 +2273,30 @@ void
>  iterate_over_block_local_vars (const struct block *block,
>  			       iterate_over_block_arg_local_vars_cb cb)  {
> +  std::unordered_set<std::string> 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)

According to the GDB coding style, this should be

  while (block != nullptr)

> +    {
> +      for (struct symbol *sym : block_iterator_range (block))
> +	{
> +	  const char *name = sym->print_name ();
> +	  if (collected_vars.find (name) != collected_vars.end ())
> +	    shadowed_vars.insert (name);
> +	  else
> +	    collected_vars.insert (name);

Similarly, this could be

  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.  */
> diff --git a/gdb/testsuite/gdb.base/var-shadowing.c 
> b/gdb/testsuite/gdb.base/var-shadowing.c
> new file mode 100755
> index 00000000000..00597b402ba
> --- /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 
> + <http://www.gnu.org/licenses/>.  */
> +
> +#include <stdlib.h>
> +
> +void
> +shadowing ()
              ^
This should be

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;
> +}

Best,
Lancelot.
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de <http://www.intel.de>
Managing Directors: Christin Eisenschmid, Sharon Heck, Tiffany Doon Silva  
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928

  reply	other threads:[~2023-09-19  7:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-09-18 16:47 [PATCH v3 0/2] " Abdul Basit Ijaz
2023-09-18 16:47 ` [PATCH v3 1/2] gdb: " Abdul Basit Ijaz
2023-09-18 22:46   ` Lancelot SIX
2023-09-19  7:50     ` Ijaz, Abdul B [this message]
2023-09-18 16:47 ` [PATCH v3 2/2] gdb: add shadowed field in '-stack-list-locals/variables' mi commands Abdul Basit Ijaz
2023-09-18 22:53   ` Lancelot SIX
2023-09-19 11:41     ` Ijaz, Abdul B
2023-09-19 13:20       ` Lancelot SIX
2023-09-19 15:46         ` Ijaz, Abdul B

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=CY8PR11MB684478119E8446FFA78ED43ECBFAA@CY8PR11MB6844.namprd11.prod.outlook.com \
    --to=abdul.b.ijaz@intel.com \
    --cc=gdb-patches@sourceware.org \
    --cc=lsix@lancelotsix.com \
    --cc=pedro@palves.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).