Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: Keith Seitz <keiths@redhat.com>, gdb-patches@sourceware.org
Subject: Re: [PATCH v6] infcall: Add support for integer literals as reference function parameters
Date: Tue, 17 Mar 2026 14:10:02 +0000	[thread overview]
Message-ID: <878qbq7dj9.fsf@redhat.com> (raw)
In-Reply-To: <d14d67d5012dea438e79f875afbfcc747b9839a9.1773334009.git.keiths@redhat.com>

Keith Seitz <keiths@redhat.com> writes:

> [With apologies for all the typos in v5...]
>
> This is v6 of my attempt to add simple integer literal support for reference
> parameters in inferior function calls. The goal here is to take a step toward
> a better user experience when working with standard containers such as std::map.
>
> While hacking at the parser to add new related functionality, I've come to realize
> that heap allocation is much safer than using the stack. We just really cannot know
> how a user (or their program) handles any of these values.
>
> I've looked at c++/32365, and this patch does not address that issue. I have been
> working on a patch to add construction to the parser which will address some of
> the issues in that bug, but it relies on this patch. [That is, "p d[var(0)]"
> works with my work-in-progress parser patch.]
>
> Keith
>
> Changes in v6
> - Fix a bunch of typos
> - Revert some missed stack-related changes from v4

I took a look through, and this all looks great.

Approved-By: Andrew Burgess <aburgess@redhat.com>

thanks,
Andrew


>
> Changes in v5
> - Return to heap allocation
>
> Changes in v4
> - Allocate to stack instead of heap
> - Use value::force_lval to simply copying to inferior memory
> - Add some addition tests
>
> Changes in v3
> - Move logic to value_arg_coerce
> - Add some attempt to limit copying to trivially copyable types
>
> -----
>
> This patch attempts to mitigate the shortcomings of passing literals
> to inferior function calls requiring references.  The specific use case here
> is std::map's operator[]:
>
> std::map int_map<int, int>;
> int_map[1] = 10;
> (gdb) print int_map[1]
> Attempt to take address of value not located in memory.
>
> This is occurring because while value_coerce_to_target understands
> that some values need to be allocated and copied to the inferior's
> memory, it only considers the actual parsed type of the argument value,
> ignoring the actual type of the function parameter. That is,
> in this specific case, the value's parsed type is TYPE_CODE_INT, but
> the function requires TYPE_CODE_REF. We need to account for the
> reference.
>
> In value_arg_coerce, we have special handling for references, but it
> has not specifically dealt with this case. It now checks if the
> reference is in memory, and if it isn't, it copies it, if the type
> is trivially copyable.
>
> As a result of this patch, the last remaining failure in c++/15372 is now
> fixed, and that bug can be closed.
>
> With this patch, we can now print map entries with integer keys:
>
> (gdb) print int_map[1]
> $1 = (std::map<int, int, std::less<int>, std::allocator<std::pair<int const, int> > >::mapped_type &) @0x41f2d4: 10
>
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=15372
> Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25957
> ---
>  gdb/infcall.c                                |  16 +-
>  gdb/testsuite/gdb.cp/ref-params.cc           |  95 +++++++++++-
>  gdb/testsuite/gdb.cp/ref-params.exp          | 146 +++++++++++++++++++
>  gdb/testsuite/gdb.cp/rvalue-ref-overload.exp |   1 -
>  4 files changed, 253 insertions(+), 5 deletions(-)
>
> diff --git a/gdb/infcall.c b/gdb/infcall.c
> index 51636ff5403..941b0a95c5b 100644
> --- a/gdb/infcall.c
> +++ b/gdb/infcall.c
> @@ -276,10 +276,20 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
>  	  return value_cast_pointers (type, arg, 0);
>  
>  	/* Cast the value to the reference's target type, and then
> -	   convert it back to a reference.  This will issue an error
> -	   if the value was not previously in memory - in some cases
> -	   we should clearly be allowing this, but how?  */
> +	   convert it back to a reference.  If the value is not already
> +	   in memory (e.g., a literal), we need to allocate space in the
> +	   inferior and copy it there.  */
>  	new_value = value_cast (type->target_type (), arg);
> +	if (new_value->lval () != lval_memory
> +	    && (language_pass_by_reference (new_value->type ())
> +		.trivially_copyable))
> +	  {
> +	    LONGEST length = check_typedef (new_value->type ())->length ();
> +	    struct value *addr_val = value_allocate_space_in_inferior (length);
> +	    CORE_ADDR addr = value_as_address (addr_val);
> +	    new_value->force_lval (addr);
> +	  }
> +
>  	new_value = value_ref (new_value, type->code ());
>  	return new_value;
>        }
> diff --git a/gdb/testsuite/gdb.cp/ref-params.cc b/gdb/testsuite/gdb.cp/ref-params.cc
> index 12e2716b435..3c1aa82396a 100644
> --- a/gdb/testsuite/gdb.cp/ref-params.cc
> +++ b/gdb/testsuite/gdb.cp/ref-params.cc
> @@ -60,6 +60,68 @@ int mf2(MultiChild& C)
>    return mf1(C);
>  }
>  
> +/* A class to be used by functions and methods exercising c++/25957.  */
> +class TestClass
> +{
> +  public:
> +  int value;
> +
> +  TestClass (int v) : value (v) {}
> +
> +  int
> +  const_ref_method (const int &x) const
> +  {
> +    return value + x;
> +  }
> +
> +  int
> +  const_ref_method (const TestClass &obj) const
> +  {
> +    return value + obj.value;
> +  }
> +
> +  int
> +  ref_method (int &x)
> +  {
> +    return value + 2 * x;
> +  }
> +
> +  int
> +  ref_method (TestClass &obj)
> +  {
> +    return value + 2 * obj.value;
> +  }
> +};
> +
> +/* Define globals to be used by functions and methods exercising c++/25957.  */
> +int global_int = 42;
> +TestClass global_obj (10);
> +
> +/* Helper functions to test reference parameter behavior for c++/25957.  */
> +int
> +const_ref_func (const int &x)
> +{
> +  return x * 2;
> +}
> +
> +int
> +const_ref_func (const TestClass &obj)
> +{
> +  return obj.value * 2;
> +}
> +
> +int
> +ref_func (int &x)
> +{
> +  return x + 1;
> +}
> +
> +int
> +ref_func (TestClass &obj)
> +{
> +  return obj.value + 1;
> +}
> +
>  int main(void)
>  {
>    Child Q(42);
> @@ -76,5 +138,36 @@ int main(void)
>  
>    mf2(MQ);			/* Set breakpoint MQ here.  */
>  
> -  return 0;
> +  TestClass obj (5);
> +  int local_var = 15;
> +
> +  /* Prevent compiler from optimizing away the function and method calls.  */
> +  int dummy_int = 99;
> +  (void) const_ref_func (dummy_int);
> +  (void) const_ref_func (global_int);
> +  (void) const_ref_func (obj);
> +  (void) const_ref_func (global_obj);
> +  (void) ref_func (dummy_int);
> +  (void) ref_func (global_int);
> +  (void) ref_func (obj);
> +  (void) ref_func (global_obj);
> +  (void) obj.const_ref_method (dummy_int);
> +  (void) obj.const_ref_method (global_int);
> +  (void) obj.const_ref_method (obj);
> +  (void) obj.const_ref_method (global_obj);
> +  (void) obj.ref_method (dummy_int);
> +  (void) obj.ref_method (global_int);
> +  (void) obj.ref_method (obj);
> +  (void) obj.ref_method (global_obj);
> +  (void) global_obj.const_ref_method (dummy_int);
> +  (void) global_obj.const_ref_method (global_int);
> +  (void) global_obj.const_ref_method (obj);
> +  (void) global_obj.const_ref_method (global_obj);
> +  (void) global_obj.ref_method (dummy_int);
> +  (void) global_obj.ref_method (global_int);
> +  (void) global_obj.ref_method (obj);
> +  (void) global_obj.ref_method (global_obj);
> +
> +  /* Breakpoint here for c++/25957 testing.  */
> +  return 0;  /* breakpoint-here */
>  }
> diff --git a/gdb/testsuite/gdb.cp/ref-params.exp b/gdb/testsuite/gdb.cp/ref-params.exp
> index b61055e9f50..31144fcba21 100644
> --- a/gdb/testsuite/gdb.cp/ref-params.exp
> +++ b/gdb/testsuite/gdb.cp/ref-params.exp
> @@ -63,3 +63,149 @@ gdb_test "print f1(MQR)" ".* = 53"
>  gdb_test "print mf1(MQR)" ".* = 106"
>  gdb_test "print mf2(MQR)" ".* = 106"
>  gdb_test "print f3(Q.id)" ".* = 42"
> +
> +# Inferior function call tests which have reference arguments.
> +# https://sourceware.org/bugzilla/show_bug.cgi?id=25957
> +gdb_start_again "breakpoint-here"
> +
> +# Test functions taking const reference parameter.
> +gdb_test "print const_ref_func(10)" \
> +    "= 20" \
> +    "call function with const ref param and literal"
> +
> +gdb_test "print const_ref_func(global_int)" \
> +    "= 84" \
> +    "call function with const ref param and global variable"
> +
> +gdb_test "print const_ref_func(local_var)" \
> +    "= 30" \
> +    "call function with const ref param and local variable"
> +
> +gdb_test "print const_ref_func(obj)" \
> +    "= 10" \
> +    "call function with const ref param and object"
> +
> +gdb_test "print const_ref_func(global_obj)" \
> +    "= 20" \
> +    "call function with const ref param and global object"
> +
> +gdb_test "print const_ref_func((TestClass) {42})" \
> +    "= 84" \
> +    "call function with const ref param and literal object"
> +
> +# Test functions taking non-const reference parameter.
> +gdb_test "print ref_func(10)" \
> +    "Cannot resolve function ref_func to any overloaded instance" \
> +    "call function with non-const ref param and literal"
> +
> +gdb_test "print ref_func(global_int)" \
> +    " = 43" \
> +    "call function with non-const ref param and global variable"
> +
> +gdb_test "print ref_func(local_var)" \
> +    " = 16" \
> +    "call function with non-const ref param and local variable"
> +
> +gdb_test "print ref_func(obj)" \
> +    "= 6" \
> +    "call function with non-const ref param and object"
> +
> +gdb_test "print ref_func(global_obj)" \
> +    "= 11" \
> +    "call function with non-const ref param and global object"
> +
> +gdb_test "print ref_func((TestClass) {42})" \
> +    "Cannot resolve function ref_func to any overloaded instance" \
> +    "call function with ref param and literal object"
> +
> +# Test methods taking constant reference parameter.
> +gdb_test "print obj.const_ref_method(5)" \
> +    "= 10" \
> +    "call const method with const ref param and literal"
> +
> +gdb_test "print obj.const_ref_method(global_int)" \
> +    "= 47" \
> +    "call const method with const ref param and global variable"
> +
> +gdb_test "print obj.const_ref_method(local_var)" \
> +    "= 20" \
> +    "call const method with const ref param and local variable"
> +
> +gdb_test "print obj.const_ref_method(obj)" \
> +    "= 10" \
> +    "call method with const ref param and object"
> +
> +gdb_test "print obj.const_ref_method((TestClass) {42})" \
> +    "= 47" \
> +    "call method with const ref param and literal object"
> +
> +# Test methods taking non-const reference parameters.
> +gdb_test "print obj.ref_method(5)" \
> +    "Cannot resolve method TestClass::ref_method to any overloaded instance" \
> +    "call method with non-const ref param and literal"
> +
> +gdb_test "print obj.ref_method(global_int)" \
> +    "= 89" \
> +    "cal method with non-const ref param and global variable"
> +
> +gdb_test "print obj.ref_method(local_var)" \
> +    " = 35" \
> +    "call method with non-const ref param and local variable"
> +
> +gdb_test "print obj.ref_method(obj)" \
> +    "= 15" \
> +    "call method with non-const ref param and object"
> +
> +gdb_test "print obj.ref_method((TestClass) {42})" \
> +    "Cannot resolve method TestClass::ref_method to any overloaded instance" \
> +    "call method with non-const ref param and literal object"
> +
> +# Test global_obj methods taking constant reference parameter.
> +gdb_test "print global_obj.const_ref_method(5)" \
> +    "= 15" \
> +    "call global const method with const ref param and literal"
> +
> +gdb_test "print global_obj.const_ref_method(global_int)" \
> +    "= 52" \
> +    "call global const method with const ref param and global variable"
> +
> +gdb_test "print global_obj.const_ref_method(local_var)" \
> +    "= 25" \
> +    "call global const method with const ref param and local variable"
> +
> +gdb_test "print global_obj.const_ref_method(obj)" \
> +    "= 15" \
> +    "call global method with const ref param and object"
> +
> +gdb_test "print global_obj.const_ref_method(global_obj)" \
> +    "= 20" \
> +    "call global method with const ref param and global object"
> +
> +gdb_test "print global_obj.const_ref_method((TestClass) {42})" \
> +    "= 52" \
> +    "call global method with const ref param and literal object"
> +
> +# Test global_obj methods taking non-const reference parameters.
> +gdb_test "print global_obj.ref_method(5)" \
> +    "Cannot resolve method TestClass::ref_method to any overloaded instance" \
> +    "call global method with non-const ref param and literal"
> +
> +gdb_test "print global_obj.ref_method(global_int)" \
> +    "= 94" \
> +    "call global method with non-const ref param and global variable"
> +
> +gdb_test "print global_obj.ref_method(local_var)" \
> +    "= 40" \
> +    "call global method with non-const ref param and local variable"
> +
> +gdb_test "print global_obj.ref_method(obj)" \
> +    "= 20" \
> +    "call global method with non-const ref param and object"
> +
> +gdb_test "print global_obj.ref_method(global_obj)" \
> +    "= 30" \
> +    "call global method with non-const ref param and global object"
> +
> +gdb_test "print global_obj.ref_method ((TestClass) {42})" \
> +    "Cannot resolve method TestClass::ref_method to any overloaded instance" \
> +    "call global method with non-const ref param and literal object"
> diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
> index bd6933673db..b9da32c244e 100644
> --- a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
> +++ b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
> @@ -64,7 +64,6 @@ gdb_test "print f (i)" "1" "lvalue reference overload"
>  
>  gdb_test "print f (ci)" "2" "lvalue reference to const overload"
>  
> -setup_kfail "c++/15372" "*-*-*"
>  gdb_test "print f (3)" "3" "rvalue reference overload"
>  
>  gdb_test "print g (i)" \
>
> base-commit: 71f898443500ba572511579cf699994828542c96
> -- 
> 2.53.0


  reply	other threads:[~2026-03-17 14:12 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-16 15:48 [PATCH] infcall: Add support for integer literals as reference function paramters Keith Seitz
2025-10-17 14:49 ` Tom Tromey
2025-10-20 19:00   ` Keith Seitz
2025-10-20 19:36 ` [PATCH v2] " Keith Seitz
2025-10-21 20:19   ` Tom Tromey
2025-10-22 12:05     ` Andrew Burgess
2025-10-22 13:21       ` Tom Tromey
2026-01-22 19:05       ` Keith Seitz
2026-01-23 14:07         ` Aktemur, Tankut Baris
2026-01-27 18:43           ` Keith Seitz
2026-01-27 19:01 ` [PATCH v4] " Keith Seitz
2026-01-28  8:24   ` Aktemur, Tankut Baris
2026-01-28 13:54   ` Andrew Burgess
2026-02-02 17:05     ` Aktemur, Tankut Baris
2026-02-02 17:21     ` Keith Seitz
2026-01-30 20:59   ` Tom Tromey
2026-02-02 16:58     ` Keith Seitz
2026-02-02 17:22       ` Aktemur, Tankut Baris
2026-02-12 16:31       ` Tom Tromey
2026-03-12 14:14 ` [PATCH v5] infcall: Add support for integer literals as reference function parameters Keith Seitz
2026-03-12 16:23   ` Tom de Vries
2026-03-12 16:45     ` Keith Seitz
2026-03-12 17:12 ` [PATCH v6] " Keith Seitz
2026-03-17 14:10   ` Andrew Burgess [this message]
2026-03-17 18:11     ` Keith Seitz

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=878qbq7dj9.fsf@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    --cc=keiths@redhat.com \
    /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