Make evaluation and type-printing of all NonZero optimized enums work
gdb/ChangeLog: 2016-06-25 Manish Goregaokar <manish@mozilla.com> PR gdb/20239 * rust-lang.c (rust_get_disr_info): Correctly interpret NonZero-optimized enums of arbitrary depth. (rust_print_type): Correctly print NonZero-optimized enums.
This commit is contained in:
parent
6b8505468e
commit
b5a4b3c5e7
|
@ -1,3 +1,11 @@
|
|||
2016-06-25 Manish Goregaokar <manish@mozilla.com>
|
||||
|
||||
PR gdb/20239
|
||||
* rust-lang.c (rust_get_disr_info): Correctly interpret
|
||||
NonZero-optimized enums of arbitrary depth.
|
||||
(rust_print_type): Correctly print NonZero-optimized
|
||||
enums.
|
||||
|
||||
2016-06-24 David Taylor <dtaylor@emc.com>
|
||||
|
||||
PR gdb/17520 Structure offset wrong when 1/4 GB or greater.
|
||||
|
|
|
@ -121,7 +121,7 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
|
|||
if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
|
||||
strlen (RUST_ENUM_PREFIX)) == 0)
|
||||
{
|
||||
char *tail;
|
||||
char *name, *tail, *token;
|
||||
unsigned long fieldno;
|
||||
struct type *member_type;
|
||||
LONGEST value;
|
||||
|
@ -131,32 +131,57 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr,
|
|||
if (TYPE_NFIELDS (type) != 1)
|
||||
error (_("Only expected one field in %s type"), RUST_ENUM_PREFIX);
|
||||
|
||||
fieldno = strtoul (TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX),
|
||||
&tail, 10);
|
||||
if (*tail != '$')
|
||||
error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
|
||||
|
||||
/* Optimized enums have only one field. */
|
||||
member_type = TYPE_FIELD_TYPE (type, 0);
|
||||
|
||||
name = xstrdup (TYPE_FIELD_NAME (type, 0));
|
||||
cleanup = make_cleanup (xfree, name);
|
||||
tail = name + strlen (RUST_ENUM_PREFIX);
|
||||
|
||||
/* The location of the value that doubles as a discriminant is
|
||||
stored in the name of the field, as
|
||||
RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
|
||||
where the fieldnos are the indices of the fields that should be
|
||||
traversed in order to find the field (which may be several fields deep)
|
||||
and the variantname is the name of the variant of the case when the
|
||||
field is zero. */
|
||||
while ((token = strsep (&tail, "$")) != NULL)
|
||||
{
|
||||
if (sscanf (token, "%lu", &fieldno) != 1)
|
||||
{
|
||||
/* We have reached the enum name,
|
||||
which cannot start with a digit. */
|
||||
break;
|
||||
}
|
||||
if (fieldno >= TYPE_NFIELDS (member_type))
|
||||
error (_("%s refers to field after end of member type"),
|
||||
RUST_ENUM_PREFIX);
|
||||
|
||||
embedded_offset += TYPE_FIELD_BITPOS (member_type, fieldno) / 8;
|
||||
value = unpack_long (TYPE_FIELD_TYPE (member_type, fieldno),
|
||||
member_type = TYPE_FIELD_TYPE (member_type, fieldno);
|
||||
}
|
||||
|
||||
if (token >= name + strlen (TYPE_FIELD_NAME (type, 0)))
|
||||
error (_("Invalid form for %s"), RUST_ENUM_PREFIX);
|
||||
value = unpack_long (member_type,
|
||||
valaddr + embedded_offset);
|
||||
|
||||
|
||||
|
||||
if (value == 0)
|
||||
{
|
||||
ret.field_no = RUST_ENCODED_ENUM_HIDDEN;
|
||||
ret.name = concat (TYPE_NAME (type), "::", tail + 1, (char *) NULL);
|
||||
ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret.field_no = RUST_ENCODED_ENUM_REAL;
|
||||
ret.name = concat (TYPE_NAME (type), "::",
|
||||
rust_last_path_segment (TYPE_NAME (member_type)),
|
||||
rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))),
|
||||
(char *) NULL);
|
||||
}
|
||||
|
||||
do_cleanups (cleanup);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -840,8 +865,10 @@ rust_print_type (struct type *type, const char *varstring,
|
|||
|
||||
case TYPE_CODE_UNION:
|
||||
{
|
||||
/* ADT enums */
|
||||
/* ADT enums. */
|
||||
int i, len = 0;
|
||||
/* Skip the discriminant field. */
|
||||
int skip_to = 1;
|
||||
|
||||
fputs_filtered ("enum ", stream);
|
||||
if (TYPE_TAG_NAME (type) != NULL)
|
||||
|
@ -852,6 +879,17 @@ rust_print_type (struct type *type, const char *varstring,
|
|||
}
|
||||
fputs_filtered ("{\n", stream);
|
||||
|
||||
if (strncmp (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX,
|
||||
strlen (RUST_ENUM_PREFIX)) == 0) {
|
||||
const char *zero_field = strrchr (TYPE_FIELD_NAME (type, 0), '$');
|
||||
if (zero_field != NULL && strlen (zero_field) > 1)
|
||||
{
|
||||
fprintfi_filtered (level + 2, stream, "%s,\n", zero_field+1);
|
||||
/* There is no explicit discriminant field, skip nothing. */
|
||||
skip_to = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < TYPE_NFIELDS (type); ++i)
|
||||
{
|
||||
struct type *variant_type = TYPE_FIELD_TYPE (type, i);
|
||||
|
@ -860,14 +898,14 @@ rust_print_type (struct type *type, const char *varstring,
|
|||
|
||||
fprintfi_filtered (level + 2, stream, "%s", name);
|
||||
|
||||
if (TYPE_NFIELDS (variant_type) > 1)
|
||||
if (TYPE_NFIELDS (variant_type) > skip_to)
|
||||
{
|
||||
int first = 1;
|
||||
int is_tuple = rust_tuple_variant_type_p (variant_type);
|
||||
int j;
|
||||
|
||||
fputs_filtered (is_tuple ? "(" : "{", stream);
|
||||
for (j = 1; j < TYPE_NFIELDS (variant_type); j++)
|
||||
for (j = skip_to; j < TYPE_NFIELDS (variant_type); j++)
|
||||
{
|
||||
if (first)
|
||||
first = 0;
|
||||
|
|
Loading…
Reference in New Issue