Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Simon Marchi via Gdb-patches <gdb-patches@sourceware.org>
To: Lancelot SIX <lsix@lancelotsix.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v2 1/4] gdb: Add typesafe getter/setter for cmd_list_element.var
Date: Mon, 9 Aug 2021 21:29:48 -0400	[thread overview]
Message-ID: <d99451ed-0f14-7ee0-9996-c16df1e2baf5@polymtl.ca> (raw)
In-Reply-To: <20210808192302.3768766-2-lsix@lancelotsix.com>

On 2021-08-08 3:22 p.m., Lancelot SIX via Gdb-patches wrote:
> cmd_list_element can contain a pointer to data that can be set and / or
> shown.  This is achieved with a void* that points to the data that can
> be accessed, while the var_type (of type enum var_types) tells how to
> interpret the data pointed to.
> 
> With this pattern, the user of the cmd_list_element needs to know what
> the storage type associated with a given VAR_TYPES tag, and needs to do
> the proper casting.  No automatic check at compile or run time enforces
> that the adequate cast is done.
> 
> This looks something like:
> 
> 	if (c->var_type == var_zuinteger)
> 	  unsigned int v = *(unsigned int*)v->var_type;
> 
> With this approach, it is easy to make an error.
> 
> This patch aims at addressing the same problem as
> https://sourceware.org/pipermail/gdb-patches/2021-July/180920.html but
> uses a different approach.
> 
> This patch proposes to add an abstraction around the var_types and void*
> pointer pair.  The abstraction is meant to prevent the user from having
> to handle the cast.  This is achieved by introducing the setting
> struct, and a set of templated get / set member functions.  The template
> parameter is the type of the variable that holds the referred variable.
> 
> For example, instantiating the member functions with bool will yield
> something similar to:
> 
> 	bool get<bool> () const
> 	{
> 	  gdb_assert (this->m_var_type == var_boolean);
> 	  gdb_assert (this->m_var != nullptr);
> 	  return *static_cast<bool *> (this->m_var);
> 	}
> 	void set<bool> (bool var)
> 	{
> 	  gdb_assert (this->m_var_type == var_boolean);
> 	  gdb_assert (this->m_var != nullptr);
> 	  *static_cast<bool *> (this->m_var) = var;
> 	}
> 
> With such abstractions available, the var_type and var members of the
> cmd_list_element are replaced with a setting instance.
> 
> No user visible change is expected after this patch.
> 
> Tested on GNU/Linux x86_64, with no regression noticed.

Thanks, this is OK, with the following nits fixed.

> diff --git a/gdb/command.h b/gdb/command.h
> index baf34401a07..644812c4d46 100644
> --- a/gdb/command.h
> +++ b/gdb/command.h
> @@ -125,6 +125,164 @@ typedef enum var_types
>    }
>  var_types;
>  
> +/* Return true if a setting of type VAR_TYPE is backed with type T.
> +
> +   This  function is left without definition intentionally.  This template

Double space.

> +   is specialized for all valid types that are used to back var_types.
> +   Therefore if one tries to instantiate this un-specialized template it
> +   means the T parameter is not a type used to back a var_type and it is most
> +   likely a programming error.  */
> +template<typename T>
> +inline bool var_type_uses (var_types t);
> +
> +/* Return true if a setting of type T is backed by a bool variable.  */
> +template<>
> +inline bool var_type_uses<bool> (var_types t)
> +{
> +  return t == var_boolean;
> +};
> +
> +/* Return true if a setting of type T is backed by a auto_boolean variable.
> +*/
> +template<>
> +inline bool var_type_uses<enum auto_boolean> (var_types t)
> +{
> +  return t == var_auto_boolean;
> +}
> +
> +/* Return true if a setting of type T is backed by an unsigned int variable.
> +*/
> +template<>
> +inline bool var_type_uses<unsigned int> (var_types t)
> +{
> +  return (t == var_uinteger || t == var_zinteger || t == var_zuinteger);
> +}
> +
> +/* Return true if a setting of type T is backed by an int variable.  */
> +template<>
> +inline bool var_type_uses<int> (var_types t)
> +{
> +  return (t == var_integer || t == var_zinteger
> +	  || t == var_zuinteger_unlimited);
> +}
> +
> +/* Return true if a setting of type T is backed by a char * variable.  */
> +template<>
> +inline bool var_type_uses<char *> (var_types t)
> +{
> +  return (t == var_string || t == var_string_noescape
> +	  || t == var_optional_filename || t == var_filename);
> +}
> +
> +/* Return true if a setting of type T is backed by a const char * variable.
> +*/
> +template<>
> +inline bool var_type_uses<const char *> (var_types t)
> +{
> +  return t == var_enum;
> +}
> +
> +/* Abstraction that contains access to data that can be set or shown.
> +
> +   The underlying data can be of any VAR_TYPES type.  */
> +struct base_setting
> +{
> +  /* Access the type of the current var.  */
> +  var_types type () const
> +  {
> +    return m_var_type;
> +  }
> +
> +  /* Return the current value (by pointer).
> +
> +     The template parameter T is the type of the variable used to store the
> +     setting.
> +
> +     The returned value cannot be NULL (this is checked at runtime).  */
> +  template<typename T>
> +  T const *
> +  get_p () const
> +  {
> +    gdb_assert (var_type_uses<T> (this->m_var_type));
> +    gdb_assert (!this->empty ());
> +
> +    return static_cast<T const *> (this->m_var);
> +  }
> +
> +  /* Return the current value.
> +
> +     See get_p for discussion on the return type and template parameters.  */
> +  template<typename T>
> +  T get () const
> +  {
> +    return *get_p<T> ();
> +  }
> +
> +  /* Sets the value V to the underlying buffer.
> +
> +     The template parameter T indicates the type of the variable used to store
> +     the setting.
> +
> +     The var_type of the setting must match T.  */
> +  template<typename T>
> +  void set (T v)
> +  {
> +    /* Check that the current instance is of one of the supported types for
> +       this instantiation.  */
> +    gdb_assert (var_type_uses<T> (this->m_var_type));
> +    gdb_assert (!this->empty ());
> +
> +    *static_cast<T *> (this->m_var) = v;
> +  }
> +
> +  /* A setting is valid (can be evaluated to true) if it contains a valid
> +     reference to a memory buffer.  */
> +  explicit operator bool () const
> +  {
> +    return !this->empty ();
> +  }
> +
> +protected:
> +  /* The type of the variable M_VAR is pointing to.  If M_VAR is nullptr,
> +     M_VAR_TYPE is ignored.  */
> +  var_types m_var_type { var_boolean };
> +
> +  /* Pointer to the enclosed variable.  The type of the variable is encoded
> +     in M_VAR_TYPE.  Can be nullptr.  */
> +  void *m_var { nullptr };
> +
> +  /* Indicates if the current instance has a underlying buffer.  */
> +  bool empty () const
> +  {
> +    return m_var == nullptr;
> +  }
> +
> +};
> +
> +
> +/* A base_setting with additional methods to set the underlying buffer and

Remove extra empty line above.

> @@ -566,14 +577,13 @@ pascm_param_type_name (enum var_types param_type)
>     If TYPE is not supported, then a <gdb:exception> object is returned.  */
>  
>  static SCM
> -pascm_param_value (enum var_types type, void *var,
> -		   int arg_pos, const char *func_name)
> +pascm_param_value (base_setting const &var, int arg_pos, const char *func_name)

The comment "If TYPE is not supported..." should be updated.

Simon

  reply	other threads:[~2021-08-10  1:32 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-08 19:22 [PATCH v2 0/4] gdb: Refactor cmd_list_element.var Lancelot SIX via Gdb-patches
2021-08-08 19:22 ` [PATCH v2 1/4] gdb: Add typesafe getter/setter for cmd_list_element.var Lancelot SIX via Gdb-patches
2021-08-10  1:29   ` Simon Marchi via Gdb-patches [this message]
2021-08-10 12:22   ` Simon Marchi via Gdb-patches
2021-08-10 21:58     ` Lancelot SIX via Gdb-patches
2021-08-11  0:56       ` Simon Marchi via Gdb-patches
2021-08-08 19:23 ` [PATCH v2 2/4] gdb: make string-like set show commands use std::string variable Lancelot SIX via Gdb-patches
2021-08-08 19:23 ` [PATCH v2 3/4] gdb: Have setter and getter callbacks for settings Lancelot SIX via Gdb-patches
2021-08-10  3:01   ` Simon Marchi via Gdb-patches
2021-08-10 22:18     ` Lancelot SIX via Gdb-patches
2021-08-11  1:01       ` Simon Marchi via Gdb-patches
2021-08-11 20:00         ` Lancelot SIX via Gdb-patches
2021-08-19 21:03           ` Simon Marchi via Gdb-patches
2021-08-20  7:04             ` Lancelot SIX via Gdb-patches
2021-08-08 19:23 ` [PATCH v2 4/4] gdb: Setting setter return a bool to tell if the value changed Lancelot SIX via Gdb-patches

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=d99451ed-0f14-7ee0-9996-c16df1e2baf5@polymtl.ca \
    --to=gdb-patches@sourceware.org \
    --cc=lsix@lancelotsix.com \
    --cc=simon.marchi@polymtl.ca \
    /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