From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from gproxy3-pub.mail.unifiedlayer.com (gproxy3-pub.mail.unifiedlayer.com [69.89.30.42]) by sourceware.org (Postfix) with ESMTPS id EA2B03858000 for ; Tue, 25 Jan 2022 01:35:14 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EA2B03858000 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tromey.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tromey.com Received: from cmgw12.mail.unifiedlayer.com (unknown [10.0.90.127]) by progateway5.mail.pro1.eigbox.com (Postfix) with ESMTP id 1DBA1100563B1 for ; Tue, 25 Jan 2022 01:35:14 +0000 (UTC) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with ESMTP id CAjpnj1s9XOyfCAjpnghaG; Tue, 25 Jan 2022 01:35:14 +0000 X-Authority-Reason: nr=8 X-Authority-Analysis: v=2.4 cv=Ot6Kdwzt c=1 sm=1 tr=0 ts=61ef53d2 a=ApxJNpeYhEAb1aAlGBBbmA==:117 a=ApxJNpeYhEAb1aAlGBBbmA==:17 a=dLZJa+xiwSxG16/P+YVxDGlgEgI=:19 a=DghFqjY3_ZEA:10:nop_rcvd_month_year a=Qbun_eYptAEA:10:endurance_base64_authed_username_1 a=CCpqsmhAAAAA:8 a=mDV3o1hIAAAA:8 a=nyMaWTQxvjWoiKHSdyoA:9 a=ul9cdbp4aOFLsgKbc677:22 a=_FVE-zBwftR9WsbkzFJk:22 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Content-Transfer-Encoding:MIME-Version:Message-Id:Date:Subject: Cc:To:From:Sender:Reply-To:Content-Type:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=KlP9Ybetucv+og+PSIf6tl+u61x5oZCvtEjPw1cSEGY=; b=kC5+u43YSsbHGCkR3yKK8RMPQW In9bgz4sKSrko58b6vZVyvTqK95wWHEcR7MtDAojWFCdfNCgwCu3qCHF15gtCKHH2xzc96hRFZzMj iD+gRZC7ParpbrlyQxytIw4lF; Received: from 75-166-128-165.hlrn.qwest.net ([75.166.128.165]:40680 helo=prentzel.Home) by box5379.bluehost.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1nCAjp-001Nn8-9W; Mon, 24 Jan 2022 18:35:13 -0700 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] Fix Rust parser bug with function fields Date: Mon, 24 Jan 2022 18:35:11 -0700 Message-Id: <20220125013511.854657-1-tom@tromey.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - box5379.bluehost.com X-AntiAbuse: Original Domain - sourceware.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - tromey.com X-BWhitelist: no X-Source-IP: 75.166.128.165 X-Source-L: No X-Exim-ID: 1nCAjp-001Nn8-9W X-Source: X-Source-Args: X-Source-Dir: X-Source-Sender: 75-166-128-165.hlrn.qwest.net (prentzel.Home) [75.166.128.165]:40680 X-Source-Auth: tom+tromey.com X-Email-Count: 1 X-Source-Cap: ZWx5bnJvYmk7ZWx5bnJvYmk7Ym94NTM3OS5ibHVlaG9zdC5jb20= X-Local-Domain: yes X-Spam-Status: No, score=-3031.6 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 25 Jan 2022 01:35:16 -0000 In Rust, 'obj.f()' is a method call -- but '(obj.f)()' is a call of a function-valued field 'f' in 'obj'. The Rust parser in gdb currently gets this wrong. This is PR rust/24082. The expression and Rust parser rewrites made this simple to fix -- simply wrapping a parenthesized expression in a new operation handles it. This patch has a slight hack because I didn't want to introduce a new exp_opcode enumeration constant just for this. IMO this doesn't matter, since we should work toward removing dependencies on these opcodes anyway; but let me know what you think of this. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=24082 --- gdb/rust-exp.h | 27 +++++++++++++++++++++ gdb/rust-parse.c | 2 +- gdb/testsuite/gdb.rust/fnfield.exp | 38 +++++++++++++++++++++++++++++ gdb/testsuite/gdb.rust/fnfield.rs | 39 ++++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 gdb/testsuite/gdb.rust/fnfield.exp create mode 100644 gdb/testsuite/gdb.rust/fnfield.rs diff --git a/gdb/rust-exp.h b/gdb/rust-exp.h index 6a24f2cbc10..778d87f4078 100644 --- a/gdb/rust-exp.h +++ b/gdb/rust-exp.h @@ -197,6 +197,33 @@ class rust_aggregate_operation { return OP_AGGREGATE; } }; +/* Rust parenthesized operation. This is needed to distinguish + between 'obj.f()', which is a method call, and '(obj.f)()', which + is a call of a function-valued field 'f'. */ +class rust_parenthesized_operation + : public tuple_holding_operation +{ +public: + + explicit rust_parenthesized_operation (operation_up op) + : tuple_holding_operation (std::move (op)) + { + } + + value *evaluate (struct type *expect_type, + struct expression *exp, + enum noside noside) override + { + return std::get<0> (m_storage)->evaluate (expect_type, exp, noside); + } + + enum exp_opcode opcode () const override + { + /* A lie but this isn't worth introducing a new opcode for. */ + return UNOP_PLUS; + } +}; + } /* namespace expr */ #endif /* RUST_EXP_H */ diff --git a/gdb/rust-parse.c b/gdb/rust-parse.c index 31a1ee3b38f..894f2e79d49 100644 --- a/gdb/rust-parse.c +++ b/gdb/rust-parse.c @@ -1105,7 +1105,7 @@ rust_parser::parse_tuple () { /* Parenthesized expression. */ lex (); - return expr; + return make_operation (std::move (expr)); } std::vector ops; diff --git a/gdb/testsuite/gdb.rust/fnfield.exp b/gdb/testsuite/gdb.rust/fnfield.exp new file mode 100644 index 00000000000..45755710626 --- /dev/null +++ b/gdb/testsuite/gdb.rust/fnfield.exp @@ -0,0 +1,38 @@ +# Copyright (C) 2022 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test trait object printing. + +load_lib rust-support.exp +if {[skip_rust_tests]} { + continue +} + +standard_testfile .rs +if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug rust}]} { + return -1 +} + +set line [gdb_get_line_number "set breakpoint here"] +if {![runto ${srcfile}:$line]} { + untested "could not run to breakpoint" + return -1 +} + +gdb_test "print foo.f()" " = 6" "call impl function" +gdb_test "print (foo.f)()" " = 5" "call function field" +gdb_test "print foo.g()" " = 7" "call impl function g" +gdb_test "print (foo.g)()" "There is no member named g." \ + "cannot call g with parens" diff --git a/gdb/testsuite/gdb.rust/fnfield.rs b/gdb/testsuite/gdb.rust/fnfield.rs new file mode 100644 index 00000000000..b80136c057f --- /dev/null +++ b/gdb/testsuite/gdb.rust/fnfield.rs @@ -0,0 +1,39 @@ +// Copyright (C) 2022 Free Software Foundation, Inc. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#![allow(warnings)] + +fn five() -> i32 { 5 } + +fn main() { + let foo = Foo {x: 5, f: five}; + foo.print(); // set breakpoint here + println!("Hello, world! {}, {}, {}", foo.f(), (foo.f)(), + foo.g ()); +} + +struct Foo { + x :i32, + f: fn () -> i32, +} + +impl Foo { + fn print(&self) { + println!("hello {}", self.x) + } + + fn f(&self) -> i32 { 6 } + fn g(&self) -> i32 { 7 } +} -- 2.31.1