aboutsummaryrefslogtreecommitdiff
path: root/gdb/valops.c
diff options
context:
space:
mode:
authorTom Tromey <tom@tromey.com>2018-02-09 13:31:42 -0700
committerTom Tromey <tom@tromey.com>2018-02-26 09:21:08 -0700
commit7c22600aabfd10e190e98fff0b7c2d69cd191325 (patch)
treefe62912bb7071c2d73027cd20f5c0b3c7fb8bf04 /gdb/valops.c
parent15ce8941e7d2807a3396a6874c528b24c387660a (diff)
downloadgdb-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.c44
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