diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a454307c61a..f989489263b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2018-09-13 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 Eli Zaretskii * Makefile.in (transformed_name): Use INSTALL_SCRIPT instead of diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 5f4aceb86ba..b72e0e4e4d9 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 %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); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 35173f0df58..3df7668547a 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2018-09-13 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-08-31 Tom Tromey * gdb.rust/simple.rs: Rename second variable "v". diff --git a/gdb/testsuite/gdb.rust/simple.exp b/gdb/testsuite/gdb.rust/simple.exp index 20fe8dd0a88..07b25122200 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 1bcc030d608..00a25e0828d 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();