public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Hannes Domani <ssbssa@yahoo.de>
To: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>,
	 Guinevere Larsen <blarsen@redhat.com>
Subject: Re: [PATCH] Allow calling of user-defined function call operators
Date: Sat, 27 Apr 2024 16:43:03 +0000 (UTC)	[thread overview]
Message-ID: <1734445421.7258219.1714236183866@mail.yahoo.com> (raw)
In-Reply-To: <28251b39-dda2-4da6-8bb6-2a5d81ef39df@redhat.com>

 Am Donnerstag, 25. April 2024 um 20:34:19 MESZ hat Guinevere Larsen <blarsen@redhat.com> Folgendes geschrieben:

> On 4/21/24 09:49, Hannes Domani wrote:
> > Currently it's not possible to call user-defined function call
> > operators, at least not without specifying operator() directly:
> > ```
> > (gdb) l 1
> > 1      struct S {
> > 2        int operator() (int x) { return x + 5; }
> > 3      };
> > 4
> > 5      int main () {
> > 6        S s;
> > 7
> > 8        return s(23);
> > 9      }
> > (gdb) p s(10)
> > Invalid data type for function to be called.
> > (gdb) p s.operator()(10)
> > $1 = 15
> > ```
> >
> > This now looks if an user-defined call operator is available when
> > trying to 'call' a struct value, and calls it instead, making this
> > possible:
> > ```
> > (gdb) p s(10)
> > $1 = 15
> > ```
> >
> > Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=12213
>
> Thanks for this fix, this has been a long time coming.
>
> I have one, possibly big, question.
>
> > ---
> >  gdb/eval.c                      | 46 +++++++++++++++++++++++++++-----
> >  gdb/testsuite/gdb.cp/userdef.cc  | 18 +++++++++++++
> >  gdb/testsuite/gdb.cp/userdef.exp |  4 +++
> >  3 files changed, 62 insertions(+), 6 deletions(-)
> >
> > diff --git a/gdb/eval.c b/gdb/eval.c
> > index 6b752e70635..e737774ca28 100644
> > --- a/gdb/eval.c
> > +++ b/gdb/eval.c
> > @@ -664,14 +664,34 @@ operation::evaluate_funcall (struct type *expect_type,
> >
> >    value *callee = evaluate_with_coercion (exp, noside);
> >    struct type *type = callee->type ();
> > -  if (type->code () == TYPE_CODE_PTR)
> > -    type = type->target_type ();
> > -  for (int i = 0; i < args.size (); ++i)
> > +
> > +  /* If the callee is a struct, there might be a user-defined function call
> > +    operator that should be used instead.  */
> > +  if (overload_resolution
> > +      && exp->language_defn->la_language == language_cplus
> > +      && check_typedef (type)->code () == TYPE_CODE_STRUCT)
> >      {
> > -      if (i < type->num_fields ())
> > -    vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside);
> > -      else
> > +      for (int i = 0; i < args.size (); ++i)
> >      vals[i] = args[i]->evaluate_with_coercion (exp, noside);
> > +
> > +      vals.insert (vals.begin(), value_addr (callee));
> > +      int static_memfuncp;
> > +      find_overload_match (vals, "operator()", METHOD, &vals[0], nullptr,
> > +              &callee, nullptr, &static_memfuncp, 0, noside);
> > +      if (static_memfuncp)
> > +    vals.erase (vals.begin ());
> > +    }
> > +  else
> > +    {
> > +      if (type->code () == TYPE_CODE_PTR)
> > +    type = type->target_type ();
> > +      for (int i = 0; i < args.size (); ++i)
> > +    {
> > +      if (i < type->num_fields ())
> > +        vals[i] = args[i]->evaluate (type->field (i).type (), exp, noside);
> > +      else
> > +        vals[i] = args[i]->evaluate_with_coercion (exp, noside);
> > +    }
>
> This change had me confused for quite a bit. I couldn't figure out why
> the base operation::evaluate_funcall. The problem seems to be that if
> command used is something less straightforward, like "print (foo+bar)
> (args)", we will use the evaluate_funcall of the operation (in this
> case, add_operation) instead of var_value_operation's. Did I understand
> it correctly?
>
> Assuming I did, I don't think this code duplication is the best way to
> go. Especially seeing as there are some differences in those functions
> already, and if all that it takes to defeat out expression parser is use
> (*&foo) or (a + b) (), we probably already have latent bugs in this
> area. I don't know how to verify it, though, because I really don't
> understand the code differences.
>
> Ideally, I think the best way would be to put all the code in
> var_value_operation::evaluate_funcall, but to do this, you'd need to be
> able to find a way to call the resulting var_value_operation's function
> from all relevant operations, which is probably a lot.
>
> Another option is to just park all the logic in
> operation::evaluate_funcall, so we're always using the correct function.
> This comes with the cost of being very confusing in a couple of months
> to a year.
>
> Does this make sense?

Yes, it does.
And it turns out my patch already didn't work if you e.g. try to use the
operator() on struct members.

Not sure why I didn't see this before, but all evaluate_funcall variations
call evaluate_subexp_do_call at the end, so I just moved the logic there
in this v2: https://sourceware.org/pipermail/gdb-patches/2024-April/208663.html


Hannes

      reply	other threads:[~2024-04-27 16:43 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240421124954.3285-1-ssbssa.ref@yahoo.de>
2024-04-21 12:49 ` Hannes Domani
2024-04-25 18:34   ` Guinevere Larsen
2024-04-27 16:43     ` Hannes Domani [this message]

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=1734445421.7258219.1714236183866@mail.yahoo.com \
    --to=ssbssa@yahoo.de \
    --cc=blarsen@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /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).