diff options
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/dwarf2/read.c | 32 |
2 files changed, 30 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0665127..fc4fe7c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2020-08-05 Tom Tromey <tromey@adacore.com> + + PR rust/26197: + * dwarf2/read.c (alloc_rust_variant): Handle univariant case. + (quirk_rust_enum): Call alloc_rust_variant for univariant case. + Fix off-by-one and type size errors in ordinary case. + 2020-08-05 Tom de Vries <tdevries@suse.de> * gdbtypes.c (type_not_allocated, type_not_associated): Use diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index f591ef6..cf3a42a 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -9416,7 +9416,8 @@ rust_fully_qualify (struct obstack *obstack, const char *p1, const char *p2) /* A helper that allocates a variant part to attach to a Rust enum type. OBSTACK is where the results should be allocated. TYPE is the type we're processing. DISCRIMINANT_INDEX is the index of the - discriminant. It must be the index of one of the fields of TYPE. + discriminant. It must be the index of one of the fields of TYPE, + or -1 to mean there is no discriminant (univariant enum). DEFAULT_INDEX is the index of the default field; or -1 if there is no default. RANGES is indexed by "effective" field number (the field index, but omitting the discriminant and default fields) and @@ -9429,15 +9430,17 @@ alloc_rust_variant (struct obstack *obstack, struct type *type, int discriminant_index, int default_index, gdb::array_view<discriminant_range> ranges) { - /* When DISCRIMINANT_INDEX == -1, we have a univariant enum. Those - must be handled by the caller. */ - gdb_assert (discriminant_index >= 0 - && discriminant_index < type->num_fields ()); + /* When DISCRIMINANT_INDEX == -1, we have a univariant enum. */ + gdb_assert (discriminant_index == -1 + || (discriminant_index >= 0 + && discriminant_index < type->num_fields ())); gdb_assert (default_index == -1 || (default_index >= 0 && default_index < type->num_fields ())); /* We have one variant for each non-discriminant field. */ - int n_variants = type->num_fields () - 1; + int n_variants = type->num_fields (); + if (discriminant_index != -1) + --n_variants; variant *variants = new (obstack) variant[n_variants]; int var_idx = 0; @@ -9466,7 +9469,12 @@ alloc_rust_variant (struct obstack *obstack, struct type *type, variant_part *part = new (obstack) variant_part; part->discriminant_index = discriminant_index; - part->is_unsigned = TYPE_UNSIGNED (type->field (discriminant_index).type ()); + /* If there is no discriminant, then whether it is signed is of no + consequence. */ + part->is_unsigned + = (discriminant_index == -1 + ? false + : TYPE_UNSIGNED (type->field (discriminant_index).type ())); part->variants = gdb::array_view<variant> (variants, n_variants); void *storage = obstack_alloc (obstack, sizeof (gdb::array_view<variant_part>)); @@ -9594,6 +9602,8 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) field_type->set_name (rust_fully_qualify (&objfile->objfile_obstack, type->name (), variant_name)); + + alloc_rust_variant (&objfile->objfile_obstack, type, -1, 0, {}); } else { @@ -9682,10 +9692,14 @@ quirk_rust_enum (struct type *type, struct objfile *objfile) auto iter = discriminant_map.find (variant_name); if (iter != discriminant_map.end ()) { - ranges[i].low = iter->second; - ranges[i].high = iter->second; + ranges[i - 1].low = iter->second; + ranges[i - 1].high = iter->second; } + /* In Rust, each element should have the size of the + enclosing enum. */ + TYPE_LENGTH (type->field (i).type ()) = TYPE_LENGTH (type); + /* Remove the discriminant field, if it exists. */ struct type *sub_type = type->field (i).type (); if (sub_type->num_fields () > 0) |