RE: [PATCH v2] infcall: Add support for integer literals as reference function paramters

Aktemur, Tankut Baris
2026-01-23T14:08:20Z

On Thursday, January 22, 2026 8:06 PM, Keith Seitz wrote:
> 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
>
> Changes in v2
> - Move logic to value_arg_coerce
> - Add some attempt to limit copying to trivially copyable types
> ---
> gdb/infcall.c | 19 ++-
> gdb/testsuite/gdb.cp/ref-params.cc | 95 ++++++++++++++-
> gdb/testsuite/gdb.cp/ref-params.exp | 122 +++++++++++++++++++
> gdb/testsuite/gdb.cp/rvalue-ref-overload.exp | 1 -
> 4 files changed, 232 insertions(+), 5 deletions(-)
>
> diff --git a/gdb/infcall.c b/gdb/infcall.c
> index dcbae679d07..b836a868d15 100644
> --- a/gdb/infcall.c
> +++ b/gdb/infcall.c
> @@ -276,10 +276,23 @@ 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. For C++ reference parameters,
> + if the value is not already in memory (e.g., a literal), we
> + need to allocate space in the inferior and copy the value there.
> + If the value is already in memory, we can use its address
> + directly. */
> 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);

This uses malloc to allocate the space. I was wondering if allocating
space on the stack wouldn't be better. That's how arguments that are
implicitly pass-by-reference are passed. Also struct return values
are forced to lval in stack-allocated memory.

Furthermore, malloc would not be possible everywhere (e.g. on GPUs);
stack allocation would be supported by more platforms.

There is gdbarch_reserve_stack_space to allocate space on stack,
but it needs to be passed the current stack pointer. I don't know
how easy it is to get and set the SP in this context.

> + CORE_ADDR addr = value_as_address (addr_val);
> + write_memory (addr, new_value->contents ().data (), length);
> + new_value = value_at_lazy (new_value->type (), addr);

IMHO, we could use

CORE_ADDR addr = allocate_space_in_inferior (length); // Or stack space.
new_value->force_lval (addr);

for some simplification.

> + }
> +
> 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..a94927fae56 100644
> --- a/gdb/testsuite/gdb.cp/ref-params.exp
> +++ b/gdb/testsuite/gdb.cp/ref-params.exp
> @@ -63,3 +63,125 @@ 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"

Another potentially interesting testcase would be passing
a "literal" object, like this:

print const_ref_func((TestClass) {42})

This case is also fixed with your patch.

> +# 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"
> +
> +# 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)" \

Nit: The other tests don't have space before parenthesis.

> + "= 10" \
> + "call method with const ref param and 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"
> +
> +# 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"
> +
> +# 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"
> \ No newline at end of file

Could you please add a new line at the end?

Regards,
-Baris

> 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: 01be62d46b2e05e5a994b080974dd3832755e137
> --
> 2.52.0

Intel Deutschland GmbH
Registered Address: Dornacher Straße 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 München HRB 186928