Initial support for variant parts

This adds some initial support for variant parts to gdbtypes.h.  A
variant part is represented as a union.  The union has a flag
indicating that it has a discriminant, and information about the
discriminant is attached using the dynamic property system.

2018-02-26  Tom Tromey  <tom@tromey.com>

	* value.h (value_union_variant): Declare.
	* valops.c (value_union_variant): New function.
	* gdbtypes.h (TYPE_FLAG_DISCRIMINATED_UNION): New macro.
	(struct discriminant_info): New.
	(enum dynamic_prop_node_kind) <DYN_PROP_DISCRIMINATED>: New
	enumerator.
	(struct main_type) <flag_discriminated_union>: New field.
This commit is contained in:
Tom Tromey
2018-02-09 13:31:42 -07:00
parent 15ce8941e7
commit 7c22600aab
4 changed files with 113 additions and 0 deletions

View File

@@ -2257,6 +2257,50 @@ value_struct_elt_bitpos (struct value **argp, int bitpos, struct type *ftype,
return NULL;
}
/* See value.h. */
int
value_union_variant (struct type *union_type, const gdb_byte *contents)
{
gdb_assert (TYPE_CODE (union_type) == TYPE_CODE_UNION
&& TYPE_FLAG_DISCRIMINATED_UNION (union_type));
struct dynamic_prop *discriminant_prop
= get_dyn_prop (DYN_PROP_DISCRIMINATED, union_type);
gdb_assert (discriminant_prop != nullptr);
struct discriminant_info *info
= (struct discriminant_info *) discriminant_prop->data.baton;
gdb_assert (info != nullptr);
/* If this is a univariant union, just return the sole field. */
if (TYPE_NFIELDS (union_type) == 1)
return 0;
/* This should only happen for univariants, which we already dealt
with. */
gdb_assert (info->discriminant_index != -1);
/* Compute the discriminant. Note that unpack_field_as_long handles
sign extension when necessary, as does the DWARF reader -- so
signed discriminants will be handled correctly despite the use of
an unsigned type here. */
ULONGEST discriminant = unpack_field_as_long (union_type, contents,
info->discriminant_index);
for (int i = 0; i < TYPE_NFIELDS (union_type); ++i)
{
if (i != info->default_index
&& i != info->discriminant_index
&& discriminant == info->discriminants[i])
return i;
}
if (info->default_index == -1)
error (_("Could not find variant corresponding to discriminant %s"),
pulongest (discriminant));
return info->default_index;
}
/* Search through the methods of an object (and its bases) to find a
specified method. Return the pointer to the fn_field list FN_LIST of
overloaded instances defined in the source language. If available