mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-27 17:40:49 +00:00
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:
@@ -1,3 +1,13 @@
|
||||
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.
|
||||
|
||||
2018-02-26 Tom Tromey <tom@tromey.com>
|
||||
|
||||
* Makefile.in (SUBDIR_UNITTESTS_SRCS): Add
|
||||
|
||||
@@ -312,6 +312,14 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
|
||||
|
||||
#define TYPE_FLAG_ENUM(t) (TYPE_MAIN_TYPE (t)->flag_flag_enum)
|
||||
|
||||
/* * True if this type is a discriminated union type. Only valid for
|
||||
TYPE_CODE_UNION. A discriminated union stores a reference to the
|
||||
discriminant field along with the discriminator values in a dynamic
|
||||
property. */
|
||||
|
||||
#define TYPE_FLAG_DISCRIMINATED_UNION(t) \
|
||||
(TYPE_MAIN_TYPE (t)->flag_discriminated_union)
|
||||
|
||||
/* * Constant type. If this is set, the corresponding type has a
|
||||
const modifier. */
|
||||
|
||||
@@ -381,6 +389,39 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags);
|
||||
#define TYPE_ADDRESS_CLASS_ALL(t) (TYPE_INSTANCE_FLAGS(t) \
|
||||
& TYPE_INSTANCE_FLAG_ADDRESS_CLASS_ALL)
|
||||
|
||||
/* * Information needed for a discriminated union. A discriminated
|
||||
union is handled somewhat differently from an ordinary union.
|
||||
|
||||
One field is designated as the discriminant. Only one other field
|
||||
is active at a time; which one depends on the value of the
|
||||
discriminant and the data in this structure.
|
||||
|
||||
Additionally, it is possible to have a univariant discriminated
|
||||
union. In this case, the union has just a single field, which is
|
||||
assumed to be the only active variant -- in this case no
|
||||
discriminant is provided. */
|
||||
|
||||
struct discriminant_info
|
||||
{
|
||||
/* * The index of the discriminant field. If -1, then this union
|
||||
must have just a single field. */
|
||||
|
||||
int discriminant_index;
|
||||
|
||||
/* * The index of the default branch of the union. If -1, then
|
||||
there is no default branch. */
|
||||
|
||||
int default_index;
|
||||
|
||||
/* * The discriminant values corresponding to each branch. This has
|
||||
a number of entries equal to the number of fields in this union.
|
||||
If discriminant_index is not -1, then that entry in this array is
|
||||
not used. If default_index is not -1, then that entry in this
|
||||
array is not used. */
|
||||
|
||||
ULONGEST discriminants[1];
|
||||
};
|
||||
|
||||
enum dynamic_prop_kind
|
||||
{
|
||||
PROP_UNDEFINED, /* Not defined. */
|
||||
@@ -439,6 +480,9 @@ enum dynamic_prop_node_kind
|
||||
|
||||
/* A property providing an array's byte stride. */
|
||||
DYN_PROP_BYTE_STRIDE,
|
||||
|
||||
/* A property holding information about a discriminated union. */
|
||||
DYN_PROP_DISCRIMINATED,
|
||||
};
|
||||
|
||||
/* * List for dynamic type attributes. */
|
||||
@@ -658,6 +702,13 @@ struct main_type
|
||||
|
||||
unsigned int flag_flag_enum : 1;
|
||||
|
||||
/* * True if this type is a discriminated union type. Only valid
|
||||
for TYPE_CODE_UNION. A discriminated union stores a reference to
|
||||
the discriminant field along with the discriminator values in a
|
||||
dynamic property. */
|
||||
|
||||
unsigned int flag_discriminated_union : 1;
|
||||
|
||||
/* * A discriminant telling us which field of the type_specific
|
||||
union is being used for this type, if any. */
|
||||
|
||||
|
||||
44
gdb/valops.c
44
gdb/valops.c
@@ -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
|
||||
|
||||
@@ -1169,4 +1169,12 @@ extern struct type *result_type_of_xmethod (struct value *method,
|
||||
extern struct value *call_xmethod (struct value *method,
|
||||
int argc, struct value **argv);
|
||||
|
||||
/* Given a discriminated union type and some corresponding value
|
||||
contents, this will return the field index of the currently active
|
||||
variant. This will throw an exception if no active variant can be
|
||||
found. */
|
||||
|
||||
extern int value_union_variant (struct type *union_type,
|
||||
const gdb_byte *contents);
|
||||
|
||||
#endif /* !defined (VALUE_H) */
|
||||
|
||||
Reference in New Issue
Block a user