Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Keith Seitz <keiths@redhat.com>
To: gdb-patches@sourceware.org
Subject: [PATCH v2] infcall: Add support for integer literals as reference function paramters
Date: Mon, 20 Oct 2025 12:36:09 -0700	[thread overview]
Message-ID: <f5fff161e92f0acd0cc06b0f3bc6b774ae603927.1760988969.git.keiths@redhat.com> (raw)
In-Reply-To: <92575c2eb6805095b41ebbe62ba99b81e4e5dd63.1760629738.git.keiths@redhat.com>

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.

I uncovered one small hiccup while implementing this change. It
appears that Fortran compilers use a hidden first argument which
is used to pass results from functions back to callers, and these
are implemented behind the scenes as references, marked in the debug
info as DW_TAG_reference. These should not be subject to this logic,
and I have therefore limited this to types defined in C++.

On the plus side, the last remaining failure in c++/15372 is now
fixed, and that bug could 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                                |   2 +-
 gdb/testsuite/gdb.cp/ref-params.cc           |  97 ++++++++++++++-
 gdb/testsuite/gdb.cp/ref-params.exp          | 122 +++++++++++++++++++
 gdb/testsuite/gdb.cp/rvalue-ref-overload.exp |   1 -
 gdb/valops.c                                 |  25 ++--
 gdb/value.h                                  |   3 +-
 6 files changed, 238 insertions(+), 12 deletions(-)

diff --git a/gdb/infcall.c b/gdb/infcall.c
index c4b4c8f0bea..823a2b96591 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -263,7 +263,7 @@ value_arg_coerce (struct gdbarch *gdbarch, struct value *arg,
      this point, we could allocate arguments on the stack instead of
      calling malloc if we knew that their addresses would not be
      saved by the called function.  */
-  arg = value_coerce_to_target (arg);
+  arg = value_coerce_to_target (arg, type);
 
   switch (type->code ())
     {
diff --git a/gdb/testsuite/gdb.cp/ref-params.cc b/gdb/testsuite/gdb.cp/ref-params.cc
index cd53adb834f..ea3e14302eb 100644
--- a/gdb/testsuite/gdb.cp/ref-params.cc
+++ b/gdb/testsuite/gdb.cp/ref-params.cc
@@ -60,7 +60,69 @@ int mf2(MultiChild& C)
   return mf1(C);
 }
 
-int main(void) 
+/* 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);
   Child& QR = Q;
@@ -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 4f2cbb5dace..96571963140 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"
+
+# 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)" \
+    "= 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
diff --git a/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp b/gdb/testsuite/gdb.cp/rvalue-ref-overload.exp
index f4d55be92ef..8d8fe0bee99 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)" \
diff --git a/gdb/valops.c b/gdb/valops.c
index fa87546770a..78f411f7211 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -1464,18 +1464,29 @@ value_must_coerce_to_target (struct value *val)
    storage, and this function copies them to the target.  */
 
 struct value *
-value_coerce_to_target (struct value *val)
+value_coerce_to_target (struct value *val, struct type *param_type)
 {
   LONGEST length;
   CORE_ADDR addr;
 
-  if (!value_must_coerce_to_target (val))
-    return val;
+  if (param_type != nullptr && param_type->language () == language_cplus
+      && TYPE_IS_REFERENCE (param_type))
+    {
+      length = check_typedef (val->type ())->length ();
+      addr = allocate_space_in_inferior (length);
+      write_memory (addr, val->contents ().data (), length);
+      return value_ref (value_at_lazy (val->type (), addr),
+			param_type->code ());
+    }
+  else if (value_must_coerce_to_target (val))
+    {
+      length = check_typedef (val->type ())->length ();
+      addr = allocate_space_in_inferior (length);
+      write_memory (addr, val->contents ().data (), length);
+      return value_at_lazy (val->type (), addr);
+    }
 
-  length = check_typedef (val->type ())->length ();
-  addr = allocate_space_in_inferior (length);
-  write_memory (addr, val->contents ().data (), length);
-  return value_at_lazy (val->type (), addr);
+  return val;
 }
 
 /* Given a value which is an array, return a value which is a pointer
diff --git a/gdb/value.h b/gdb/value.h
index b9d2809bead..eecfc729714 100644
--- a/gdb/value.h
+++ b/gdb/value.h
@@ -1278,7 +1278,8 @@ extern LONGEST value_ptrdiff (struct value *arg1, struct value *arg2);
 
 extern bool value_must_coerce_to_target (struct value *arg1);
 
-extern struct value *value_coerce_to_target (struct value *arg1);
+extern struct value *value_coerce_to_target (struct value *arg1,
+					     struct type *param_type = nullptr);
 
 extern struct value *value_coerce_array (struct value *arg1);
 

base-commit: 2c3d37c44b70a6e45a43045fcf07e8e739573c49
-- 
2.51.0


  parent reply	other threads:[~2025-10-20 19:38 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-10-16 15:48 [PATCH] " Keith Seitz
2025-10-17 14:49 ` Tom Tromey
2025-10-20 19:00   ` Keith Seitz
2025-10-20 19:36 ` Keith Seitz [this message]
2025-10-21 20:19   ` [PATCH v2] " 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
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=f5fff161e92f0acd0cc06b0f3bc6b774ae603927.1760988969.git.keiths@redhat.com \
    --to=keiths@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