From patchwork Tue Sep 11 21:36:59 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tom Tromey X-Patchwork-Id: 29312 Received: (qmail 45202 invoked by alias); 11 Sep 2018 21:37:46 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 45192 invoked by uid 89); 11 Sep 2018 21:37:46 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-24.4 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=corner, x1, 54004, 18380 X-HELO: gateway23.websitewelcome.com Received: from gateway23.websitewelcome.com (HELO gateway23.websitewelcome.com) (192.185.48.84) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 11 Sep 2018 21:37:43 +0000 Received: from cm15.websitewelcome.com (cm15.websitewelcome.com [100.42.49.9]) by gateway23.websitewelcome.com (Postfix) with ESMTP id 6E807191C9 for ; Tue, 11 Sep 2018 16:37:42 -0500 (CDT) Received: from box5379.bluehost.com ([162.241.216.53]) by cmsmtp with SMTP id zqLPfl48JbXuJzqLff4APp; Tue, 11 Sep 2018 16:37:41 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=tromey.com; s=default; h=Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To:MIME-Version :Content-Type:Content-Transfer-Encoding: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=Tx3Knf42rDSdYm7Me5so9tYTHoLFggbYYrU80qhRcss=; b=k1SaQj6/QBZ6yfYPY8iDsrGS/Z GofaqC9Z3KCj6m2y6zIYSpY5RAI45nVFIeL7azE8Ag+ewQSHnIkBzr+CnWUCho1pAk1krfVtznu82 r3yNIO5mUhWKct6kVjhTvptiW; Received: from 97-122-189-157.hlrn.qwest.net ([97.122.189.157]:36130 helo=pokyo.Home) by box5379.bluehost.com with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.91) (envelope-from ) id 1fzqLO-000qjA-HI; Tue, 11 Sep 2018 16:37:10 -0500 From: Tom Tromey To: gdb-patches@sourceware.org Cc: Tom Tromey Subject: [PATCH] Fix crash with empty Rust enum Date: Tue, 11 Sep 2018 15:36:59 -0600 Message-Id: <20180911213659.10366-1-tom@tromey.com> While testing my Rust compiler patch to fix the DWARF representation of Rust enums (https://github.com/rust-lang/rust/pull/54004), I found a gdb crash coming from one of the Rust test cases. The bug here is that the new variant support in gdb does not handle the case where there are no variants in the enum. This patch fixes the problem in a straightforward way. Note that the new tests are somewhat lax because I did not want to try to fully fix this corner case for older compilers. If you think that's unacceptable, let meknow. Tested on x86-64 Fedora 28 using several versions of the Rust compiler. I intend to push this to the 8.2 branch as well. gdb/ChangeLog 2018-09-11 Tom Tromey PR rust/23626: * rust-lang.c (rust_enum_variant): Now static. (rust_empty_enum_p): New function. (rust_print_enum, rust_evaluate_subexp, rust_print_struct_def): Handle empty enum. gdb/testsuite/ChangeLog 2018-09-11 Tom Tromey PR rust/23626: * gdb.rust/simple.rs (EmptyEnum): New type. (main): Use it. * gdb.rust/simple.exp (test_one_slice): Add empty enum test. --- gdb/ChangeLog | 8 ++++++ gdb/rust-lang.c | 42 ++++++++++++++++++++++++++++++- gdb/testsuite/ChangeLog | 7 ++++++ gdb/testsuite/gdb.rust/simple.exp | 12 +++++++++ gdb/testsuite/gdb.rust/simple.rs | 4 +++ 5 files changed, 72 insertions(+), 1 deletion(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7adb11f4f0..9d853ecbda 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2018-09-11 Tom Tromey + + PR rust/23626: + * rust-lang.c (rust_enum_variant): Now static. + (rust_empty_enum_p): New function. + (rust_print_enum, rust_evaluate_subexp, rust_print_struct_def): + Handle empty enum. + 2018-09-10 Tom Tromey PR python/18380: diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 1871ec7df9..9c21995dc7 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -74,9 +74,22 @@ rust_enum_p (const struct type *type) && TYPE_FLAG_DISCRIMINATED_UNION (TYPE_FIELD_TYPE (type, 0))); } +/* Return true if TYPE, which must be an enum type, has no + variants. */ + +static bool +rust_empty_enum_p (const struct type *type) +{ + gdb_assert (rust_enum_p (type)); + /* In Rust the enum always fills the containing structure. */ + gdb_assert (TYPE_FIELD_BITPOS (type, 0) == 0); + + return TYPE_NFIELDS (TYPE_FIELD_TYPE (type, 0)) == 0; +} + /* Given an enum type and contents, find which variant is active. */ -struct field * +static struct field * rust_enum_variant (struct type *type, const gdb_byte *contents) { /* In Rust the enum always fills the containing structure. */ @@ -429,6 +442,13 @@ rust_print_enum (struct type *type, int embedded_offset, opts.deref_ref = 0; + if (rust_empty_enum_p (type)) + { + /* Print the enum type name here to be more clear. */ + fprintf_filtered (stream, _("%s {}"), TYPE_NAME (type)); + return; + } + const gdb_byte *valaddr = value_contents_for_printing (val); struct field *variant_field = rust_enum_variant (type, valaddr); embedded_offset += FIELD_BITPOS (*variant_field) / 8; @@ -664,6 +684,18 @@ rust_print_struct_def (struct type *type, const char *varstring, if (is_enum) { fputs_filtered ("enum ", stream); + + if (rust_empty_enum_p (type)) + { + if (tagname != NULL) + { + fputs_filtered (tagname, stream); + fputs_filtered (" ", stream); + } + fputs_filtered ("{}", stream); + return; + } + type = TYPE_FIELD_TYPE (type, 0); struct dynamic_prop *discriminant_prop @@ -1604,6 +1636,10 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp, if (rust_enum_p (type)) { + if (rust_empty_enum_p (type)) + error (_("Cannot access field of empty enum %s"), + TYPE_NAME (type)); + const gdb_byte *valaddr = value_contents (lhs); struct field *variant_field = rust_enum_variant (type, valaddr); @@ -1672,6 +1708,10 @@ tuple structs, and tuple-like enum variants")); type = value_type (lhs); if (TYPE_CODE (type) == TYPE_CODE_STRUCT && rust_enum_p (type)) { + if (rust_empty_enum_p (type)) + error (_("Cannot access field of empty enum %s"), + TYPE_NAME (type)); + const gdb_byte *valaddr = value_contents (lhs); struct field *variant_field = rust_enum_variant (type, valaddr); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index a360c225ef..8c684520d2 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-09-11 Tom Tromey + + PR rust/23626: + * gdb.rust/simple.rs (EmptyEnum): New type. + (main): Use it. + * gdb.rust/simple.exp (test_one_slice): Add empty enum test. + 2018-09-08 Tom Tromey * gdb.python/py-prettyprint.exp: Use with_test_prefix. diff --git a/gdb/testsuite/gdb.rust/simple.exp b/gdb/testsuite/gdb.rust/simple.exp index 20fe8dd0a8..07b2512220 100644 --- a/gdb/testsuite/gdb.rust/simple.exp +++ b/gdb/testsuite/gdb.rust/simple.exp @@ -303,6 +303,18 @@ gdb_test_sequence "ptype/o SimpleLayout" "" { " }" } +# PR rust/23626 - this used to crash. Note that the results are +# fairly lax because most existing versions of Rust (those before the +# DW_TAG_variant patches) do not emit what gdb wants here; and there +# was little point fixing gdb to cope with these cases as the fixed +# compilers will be available soon +gdb_test "print empty_enum_value" \ + " = simple::EmptyEnum.*" +gdb_test "ptype empty_enum_value" "simple::EmptyEnum.*" +# Just make sure these don't crash, for the same reason. +gdb_test "print empty_enum_value.0" "" +gdb_test "print empty_enum_value.something" "" + load_lib gdb-python.exp if {[skip_python_tests]} { continue diff --git a/gdb/testsuite/gdb.rust/simple.rs b/gdb/testsuite/gdb.rust/simple.rs index 1bcc030d60..00a25e0828 100644 --- a/gdb/testsuite/gdb.rust/simple.rs +++ b/gdb/testsuite/gdb.rust/simple.rs @@ -92,6 +92,8 @@ struct SimpleLayout { f2: u16 } +enum EmptyEnum {} + fn main () { let a = (); let b : [i32; 0] = []; @@ -168,6 +170,8 @@ fn main () { let u = Union { f2: 255 }; let simplelayout = SimpleLayout { f1: 8, f2: 9 }; + let empty_enum_value: EmptyEnum = unsafe { ::std::mem::zeroed() }; + println!("{}, {}", x.0, x.1); // set breakpoint here println!("{}", diff2(92, 45)); empty();