diff options
author | Tom Tromey <tom@tromey.com> | 2018-09-11 15:28:04 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-09-13 10:57:39 -0600 |
commit | 098b2108a2b61531c0bc8ea16854f773083a95d7 (patch) | |
tree | e339871e7317c64d838590db69d4c429512cee9b /gdb/rust-lang.c | |
parent | 80ca5f98b86c9b209f392cb52dde8b8471856c5a (diff) | |
download | gdb-098b2108a2b61531c0bc8ea16854f773083a95d7.zip gdb-098b2108a2b61531c0bc8ea16854f773083a95d7.tar.gz gdb-098b2108a2b61531c0bc8ea16854f773083a95d7.tar.bz2 |
Fix crash with empty Rust enum
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-13 Tom Tromey <tom@tromey.com>
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-13 Tom Tromey <tom@tromey.com>
PR rust/23626:
* gdb.rust/simple.rs (EmptyEnum): New type.
(main): Use it.
* gdb.rust/simple.exp (test_one_slice): Add empty enum test.
Diffstat (limited to 'gdb/rust-lang.c')
-rw-r--r-- | gdb/rust-lang.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 1871ec7..b777389 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 {<No data fields>}"), 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 %d of empty enum %s"), + field_number, 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 %s of empty enum %s"), + field_name, TYPE_NAME (type)); + const gdb_byte *valaddr = value_contents (lhs); struct field *variant_field = rust_enum_variant (type, valaddr); |