From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id xdojKhcU8WgY6TgAWB0awg (envelope-from ) for ; Thu, 16 Oct 2025 11:49:43 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=fyuU+Sb+; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id 9A54F1E047; Thu, 16 Oct 2025 11:49:43 -0400 (EDT) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-25) on simark.ca X-Spam-Level: X-Spam-Status: No, score=-3.4 required=5.0 tests=ARC_SIGNED,ARC_VALID,BAYES_00, DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_VALIDITY_CERTIFIED_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED,RCVD_IN_VALIDITY_SAFE_BLOCKED autolearn=ham autolearn_force=no version=4.0.1 Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 076EA1E047 for ; Thu, 16 Oct 2025 11:49:42 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 69F6B3858436 for ; Thu, 16 Oct 2025 15:49:41 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 69F6B3858436 Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=fyuU+Sb+ Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTP id 7748F3858D1E for ; Thu, 16 Oct 2025 15:49:02 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 7748F3858D1E Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 7748F3858D1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1760629742; cv=none; b=SAa7rLci9rw5VxoieJEhkyCm7LURQwlGX7qoP5KExz79OzhrIO1eDimUanvRXVLCSU9GTj8sj0aKMtRF5XVz7vt/8d91XS8IYu/NPGO3/Te2u0ELGN4YjqC+VIFHuy89wvNTMI2UlmQiq43JG0YJHh1UkWra5Mjmr28Ra3G6bDg= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1760629742; c=relaxed/simple; bh=kbPcb01F1be6I5ogfOCQvV+8SKWX17zF108dQztorvU=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=vY81wt22Hx2QmrGDyyy+ZM20J9XVyMw5hdRTy8XaLUGNAolG7w+PmEjuVoZLg8qVt2H8RWImf5HuwM7BRvojtB0GnEo2+xz3uVpMHsndBDI5Q4jyfabW6ljfneoO7yYQLaB8ULV0EQ5ZmkWqURAmKW2+UaQNc9O5FP1FJ9j0uzc= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 7748F3858D1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1760629742; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=cbzwOPrK9zpi1jIvZQ5zqmN2qE1R/8V8TmjcQd4RM3A=; b=fyuU+Sb+ZPhMcr8Qqlaa8X97lIVhVX4LZjAPxju0qH6ptGeH0owTl4/a5ui70kG/GXt+Mc 1bHwKAeFnYW7MYkDuWWEptbEhCd0/herGzDA9brUmWt27M3qEPyAlzm/KwsQPuZYHQvF1G pdJA1obvG1P2jNl1BK/DKl21WoeQsFQ= Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-446-ztnQMUgOP6-oY9nNCKB1ZQ-1; Thu, 16 Oct 2025 11:49:00 -0400 X-MC-Unique: ztnQMUgOP6-oY9nNCKB1ZQ-1 X-Mimecast-MFC-AGG-ID: ztnQMUgOP6-oY9nNCKB1ZQ_1760629740 Received: from mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.4]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 2891218002C1 for ; Thu, 16 Oct 2025 15:49:00 +0000 (UTC) Received: from keiths-thinkpadp1gen7.rmtuswa.csb (unknown [10.22.65.57]) by mx-prod-int-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 81042300019F for ; Thu, 16 Oct 2025 15:48:59 +0000 (UTC) From: Keith Seitz To: gdb-patches@sourceware.org Subject: [PATCH] infcall: Add support for integer literals as reference function paramters Date: Thu, 16 Oct 2025 08:48:58 -0700 Message-ID: <92575c2eb6805095b41ebbe62ba99b81e4e5dd63.1760629738.git.keiths@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.4 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: g0Ep_4rfeLlYYKyjurOs8khHEFFx0PCsJCayR4GxPIc_1760629740 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit content-type: text/plain; charset="US-ASCII"; x-default=true X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces~public-inbox=simark.ca@sourceware.org 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_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've added some tests to start testing string-based maps, e.g., std::map, but that is quite a bit more complicated to deal with -- we need to not only allocate memory in the inferior, we need to initialize the string and its contents. Perhaps this can be done, but I have not attempted that in this patch. 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, std::allocator > >::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 | 78 +++++++++++++- gdb/testsuite/gdb.cp/ref-params.exp | 106 ++++++++++++++++++- gdb/testsuite/gdb.cp/rvalue-ref-overload.exp | 1 - gdb/valops.c | 25 +++-- gdb/value.h | 3 +- 6 files changed, 202 insertions(+), 13 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..827b0a1ccf9 100644 --- a/gdb/testsuite/gdb.cp/ref-params.cc +++ b/gdb/testsuite/gdb.cp/ref-params.cc @@ -17,6 +17,9 @@ /* Author: Paul N. Hilfinger, AdaCore Inc. */ +#include +#include + struct Parent { Parent (int id0) : id(id0) { } int id; @@ -60,7 +63,53 @@ int mf2(MultiChild& C) return mf1(C); } -int main(void) +/* For C++/25957 (const reference parameters and std::map operator[]). */ +std::map int_map; +std::map string_map; +int global_int_key = 42; +std::string global_string_key = "test"; + +/* Helper functions to test reference parameter behavior. */ +int +const_ref_func (const int &x) +{ + return x * 2; +} + +int +ref_func (int &x) +{ + x++; + return x; +} + +std::string +const_string_ref_func (const std::string &s) +{ + return s + "_modified"; +} + +class TestClass +{ +public: + int value; + + TestClass (int v) : value (v) {} + + int + const_ref_method (const int &x) const + { + return value + x; + } + + int + ref_method (int &x) + { + return value + 2 * x; + } +}; + +int main(void) { Child Q(42); Child& QR = Q; @@ -76,5 +125,30 @@ int main(void) mf2(MQ); /* Set breakpoint MQ here. */ - return 0; + /* c++/25957 test setup - Initialize maps with some data. */ + int_map[1] = 10; + int_map[2] = 20; + int_map[global_int_key] = 100; + + string_map["hello"] = 1; + string_map["world"] = 2; + string_map[global_string_key] = 99; + + TestClass obj (5); + int local_var = 15; + + /* Prevent compiler from optimizing away the method calls. */ + (void) int_map.size (); + (void) int_map.empty (); + (void) int_map.find (1); + (void) int_map.count (1); + int dummy_int = 99; + (void) const_ref_func (dummy_int); + (void) ref_func (dummy_int); + (void) const_string_ref_func (global_string_key); + (void) obj.const_ref_method (dummy_int); + (void) obj.ref_method (dummy_int); + + /* 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..b1b7ef93317 100644 --- a/gdb/testsuite/gdb.cp/ref-params.exp +++ b/gdb/testsuite/gdb.cp/ref-params.exp @@ -24,7 +24,7 @@ require allow_cplus_tests standard_testfile .cc -if {[build_executable $testfile.exp $testfile $srcfile {debug c++}] == -1} { +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug c++}]} { return -1 } @@ -63,3 +63,107 @@ 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 accessing existing map elements +gdb_test "print int_map\[1\]" ": 10" \ + "access existing map element with literal key" + +gdb_test "print int_map\[global_int_key\]" ": 100" \ + "access existing map element with variable key" + +# Test accessing non-existing elements with literals +gdb_test "print int_map\[99\]" \ + ": 0" \ + "attempt to access non-existing map element with literal" \ + +# Test using operator[] syntax explicitly +gdb_test "print int_map.operator\[\]\(1\)" \ + ": 10" \ + "explicit operator[] call with literal" + +# Test with string maps +setup_xfail c++/25957 *-*-* +gdb_test "print string_map\[\"hello\"\]" \ + ": 1" \ + "string map access with literal string" + +gdb_test "print string_map\[global_string_key\]" \ + ": 99" \ + "string map access with variable string" + +# Test calling function with const reference parameter and literal +gdb_test "print const_ref_func(10)" \ + "= 20" \ + "call function with const ref param and literal" + +# Test calling function with const reference parameter and variable +gdb_test "print const_ref_func(global_int_key)" \ + "= 84" \ + "call function with const ref param and variable" + +# Test with local variable +gdb_test "print const_ref_func(local_var)" \ + "= 30" \ + "call function with const ref param and local var" + +# Test string const reference +setup_xfail c++/25957 *-*-* +gdb_test "print const_string_ref_func(\"test\")" \ + {= "test_modified"} \ + "call function with const string ref and literal" + +# Test calling function with non-const reference parameter. +# This should work with variables but not literals. +gdb_test "print ref_func(global_int_key)" \ + " = 43" \ + "call function with non-const ref param and variable" + +gdb_test "print ref_func(local_var)" \ + " = 16" \ + "call function with non-const ref param and local var" + +# This should fail: literals can't be non-const refs. +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 obj.const_ref_method(5)" \ + "= 10" \ + "call const method with const ref param and literal" + +gdb_test "print obj.const_ref_method(local_var)" \ + "= 20" \ + "call const method with const ref param and variable" + +gdb_test "print obj.ref_method(local_var)" \ + " = 35" \ + "call method with non-const ref param and variable" + +# Test potential workarounds +gdb_test_no_output {set $temp_key = 99} "create temporary variable" +gdb_test_no_output {set var int_map[$temp_key] = 1234} +gdb_test {print int_map[$temp_key]} \ + ": 1234" \ + "map access with convenience variable" + +gdb_test "print int_map.size()" " = 4" + +gdb_test "print int_map.empty()" " = false" + +gdb_test "print int_map.find(1)" " = {.*}" + +gdb_test "print int_map.count(1)" " = 1" + +gdb_test "print int_map.count(1234)" "= 0" + +gdb_test "whatis const_ref_func" \ + {type = int \(const int &\)} \ + "show function signature with const reference" + +gdb_test "whatis ref_func" \ + {type = int \(int &\)} \ + "show function signature with reference" 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: b6753354fbbe7c2c66ae9f452ba7aa049db0fe0c -- 2.51.0