diff options
author | Tom Tromey <tom@tromey.com> | 2018-02-09 13:31:42 -0700 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2018-02-26 09:21:08 -0700 |
commit | 7c22600aabfd10e190e98fff0b7c2d69cd191325 (patch) | |
tree | fe62912bb7071c2d73027cd20f5c0b3c7fb8bf04 /gdb/valops.c | |
parent | 15ce8941e7d2807a3396a6874c528b24c387660a (diff) | |
download | gdb-7c22600aabfd10e190e98fff0b7c2d69cd191325.zip gdb-7c22600aabfd10e190e98fff0b7c2d69cd191325.tar.gz gdb-7c22600aabfd10e190e98fff0b7c2d69cd191325.tar.bz2 |
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.
Diffstat (limited to 'gdb/valops.c')
-rw-r--r-- | gdb/valops.c | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/gdb/valops.c b/gdb/valops.c index e038c04..bf028fd 100644 --- a/gdb/valops.c +++ b/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 |