Skip to content

Commit 081ea12

Browse files
committed
Fix crash with empty Rust enum
While testing my Rust compiler patch to fix the DWARF representation of Rust enums (rust-lang/rust#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 <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-11 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.
1 parent 849cba3 commit 081ea12

File tree

5 files changed

+72
-1
lines changed

5 files changed

+72
-1
lines changed

gdb/ChangeLog

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
2018-09-11 Tom Tromey <tom@tromey.com>
2+
3+
PR rust/23626:
4+
* rust-lang.c (rust_enum_variant): Now static.
5+
(rust_empty_enum_p): New function.
6+
(rust_print_enum, rust_evaluate_subexp, rust_print_struct_def):
7+
Handle empty enum.
8+
19
2018-09-10 Tom Tromey <tom@tromey.com>
210

311
PR python/18380:

gdb/rust-lang.c

+41-1
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,22 @@ rust_enum_p (const struct type *type)
7474
&& TYPE_FLAG_DISCRIMINATED_UNION (TYPE_FIELD_TYPE (type, 0)));
7575
}
7676

77+
/* Return true if TYPE, which must be an enum type, has no
78+
variants. */
79+
80+
static bool
81+
rust_empty_enum_p (const struct type *type)
82+
{
83+
gdb_assert (rust_enum_p (type));
84+
/* In Rust the enum always fills the containing structure. */
85+
gdb_assert (TYPE_FIELD_BITPOS (type, 0) == 0);
86+
87+
return TYPE_NFIELDS (TYPE_FIELD_TYPE (type, 0)) == 0;
88+
}
89+
7790
/* Given an enum type and contents, find which variant is active. */
7891

79-
struct field *
92+
static struct field *
8093
rust_enum_variant (struct type *type, const gdb_byte *contents)
8194
{
8295
/* In Rust the enum always fills the containing structure. */
@@ -429,6 +442,13 @@ rust_print_enum (struct type *type, int embedded_offset,
429442

430443
opts.deref_ref = 0;
431444

445+
if (rust_empty_enum_p (type))
446+
{
447+
/* Print the enum type name here to be more clear. */
448+
fprintf_filtered (stream, _("%s {<No data fields>}"), TYPE_NAME (type));
449+
return;
450+
}
451+
432452
const gdb_byte *valaddr = value_contents_for_printing (val);
433453
struct field *variant_field = rust_enum_variant (type, valaddr);
434454
embedded_offset += FIELD_BITPOS (*variant_field) / 8;
@@ -664,6 +684,18 @@ rust_print_struct_def (struct type *type, const char *varstring,
664684
if (is_enum)
665685
{
666686
fputs_filtered ("enum ", stream);
687+
688+
if (rust_empty_enum_p (type))
689+
{
690+
if (tagname != NULL)
691+
{
692+
fputs_filtered (tagname, stream);
693+
fputs_filtered (" ", stream);
694+
}
695+
fputs_filtered ("{}", stream);
696+
return;
697+
}
698+
667699
type = TYPE_FIELD_TYPE (type, 0);
668700

669701
struct dynamic_prop *discriminant_prop
@@ -1604,6 +1636,10 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp,
16041636

16051637
if (rust_enum_p (type))
16061638
{
1639+
if (rust_empty_enum_p (type))
1640+
error (_("Cannot access field of empty enum %s"),
1641+
TYPE_NAME (type));
1642+
16071643
const gdb_byte *valaddr = value_contents (lhs);
16081644
struct field *variant_field = rust_enum_variant (type, valaddr);
16091645

@@ -1672,6 +1708,10 @@ tuple structs, and tuple-like enum variants"));
16721708
type = value_type (lhs);
16731709
if (TYPE_CODE (type) == TYPE_CODE_STRUCT && rust_enum_p (type))
16741710
{
1711+
if (rust_empty_enum_p (type))
1712+
error (_("Cannot access field of empty enum %s"),
1713+
TYPE_NAME (type));
1714+
16751715
const gdb_byte *valaddr = value_contents (lhs);
16761716
struct field *variant_field = rust_enum_variant (type, valaddr);
16771717

gdb/testsuite/ChangeLog

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2018-09-11 Tom Tromey <tom@tromey.com>
2+
3+
PR rust/23626:
4+
* gdb.rust/simple.rs (EmptyEnum): New type.
5+
(main): Use it.
6+
* gdb.rust/simple.exp (test_one_slice): Add empty enum test.
7+
18
2018-09-08 Tom Tromey <tom@tromey.com>
29

310
* gdb.python/py-prettyprint.exp: Use with_test_prefix.

gdb/testsuite/gdb.rust/simple.exp

+12
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,18 @@ gdb_test_sequence "ptype/o SimpleLayout" "" {
303303
" }"
304304
}
305305

306+
# PR rust/23626 - this used to crash. Note that the results are
307+
# fairly lax because most existing versions of Rust (those before the
308+
# DW_TAG_variant patches) do not emit what gdb wants here; and there
309+
# was little point fixing gdb to cope with these cases as the fixed
310+
# compilers will be available soon
311+
gdb_test "print empty_enum_value" \
312+
" = simple::EmptyEnum.*"
313+
gdb_test "ptype empty_enum_value" "simple::EmptyEnum.*"
314+
# Just make sure these don't crash, for the same reason.
315+
gdb_test "print empty_enum_value.0" ""
316+
gdb_test "print empty_enum_value.something" ""
317+
306318
load_lib gdb-python.exp
307319
if {[skip_python_tests]} {
308320
continue

gdb/testsuite/gdb.rust/simple.rs

+4
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@ struct SimpleLayout {
9292
f2: u16
9393
}
9494

95+
enum EmptyEnum {}
96+
9597
fn main () {
9698
let a = ();
9799
let b : [i32; 0] = [];
@@ -168,6 +170,8 @@ fn main () {
168170
let u = Union { f2: 255 };
169171
let simplelayout = SimpleLayout { f1: 8, f2: 9 };
170172

173+
let empty_enum_value: EmptyEnum = unsafe { ::std::mem::zeroed() };
174+
171175
println!("{}, {}", x.0, x.1); // set breakpoint here
172176
println!("{}", diff2(92, 45));
173177
empty();

0 commit comments

Comments
 (0)