+/* * Information about a single discriminant. */
+
+struct discriminant_range
+{
+ /* * The range of values for the variant. This is an inclusive
+ range. */
+ ULONGEST low, high;
+
+ /* * Return true if VALUE is contained in this range. IS_UNSIGNED
+ is true if this should be an unsigned comparison; false for
+ signed. */
+ bool contains (ULONGEST value, bool is_unsigned) const
+ {
+ if (is_unsigned)
+ return value >= low && value <= high;
+ LONGEST valuel = (LONGEST) value;
+ return valuel >= (LONGEST) low && valuel <= (LONGEST) high;
+ }
+};
+
+struct variant_part;
+
+/* * A single variant. A variant has a list of discriminant values.
+ When the discriminator matches one of these, the variant is
+ enabled. Each variant controls zero or more fields; and may also
+ control other variant parts as well. This struct corresponds to
+ DW_TAG_variant in DWARF. */
+
+struct variant : allocate_on_obstack
+{
+ /* * The discriminant ranges for this variant. */
+ gdb::array_view<discriminant_range> discriminants;
+
+ /* * The fields controlled by this variant. This is inclusive on
+ the low end and exclusive on the high end. A variant may not
+ control any fields, in which case the two values will be equal.
+ These are indexes into the type's array of fields. */
+ int first_field;
+ int last_field;
+
+ /* * Variant parts controlled by this variant. */
+ gdb::array_view<variant_part> parts;
+
+ /* * Return true if this is the default variant. The default
+ variant can be recognized because it has no associated
+ discriminants. */
+ bool is_default () const
+ {
+ return discriminants.empty ();
+ }
+
+ /* * Return true if this variant matches VALUE. IS_UNSIGNED is true
+ if this should be an unsigned comparison; false for signed. */
+ bool matches (ULONGEST value, bool is_unsigned) const;
+};
+
+/* * A variant part. Each variant part has an optional discriminant
+ and holds an array of variants. This struct corresponds to
+ DW_TAG_variant_part in DWARF. */
+
+struct variant_part : allocate_on_obstack
+{
+ /* * The index of the discriminant field in the outer type. This is
+ an index into the type's array of fields. If this is -1, there
+ is no discriminant, and only the default variant can be
+ considered to be selected. */
+ int discriminant_index;
+
+ /* * True if this discriminant is unsigned; false if signed. This
+ comes from the type of the discriminant. */
+ bool is_unsigned;
+
+ /* * The variants that are controlled by this variant part. Note
+ that these will always be sorted by field number. */
+ gdb::array_view<variant> variants;
+};
+
+
+enum dynamic_prop_kind
+{
+ PROP_UNDEFINED, /* Not defined. */
+ PROP_CONST, /* Constant. */
+ PROP_ADDR_OFFSET, /* Address offset. */
+ PROP_LOCEXPR, /* Location expression. */
+ PROP_LOCLIST, /* Location list. */
+ PROP_VARIANT_PARTS, /* Variant parts. */
+ PROP_TYPE, /* Type. */
+};
+
+union dynamic_prop_data
+{
+ /* Storage for constant property. */
+
+ LONGEST const_val;
+
+ /* Storage for dynamic property. */
+
+ void *baton;
+
+ /* Storage of variant parts for a type. A type with variant parts
+ has all its fields "linearized" -- stored in a single field
+ array, just as if they had all been declared that way. The
+ variant parts are attached via a dynamic property, and then are
+ used to control which fields end up in the final type during
+ dynamic type resolution. */
+
+ const gdb::array_view<variant_part> *variant_parts;
+
+ /* Once a variant type is resolved, we may want to be able to go
+ from the resolved type to the original type. In this case we
+ rewrite the property's kind and set this field. */
+
+ struct type *original_type;
+};
+
+/* * Used to store a dynamic property. */
+
+struct dynamic_prop
+{
+ /* Determine which field of the union dynamic_prop.data is used. */
+ enum dynamic_prop_kind kind;
+
+ /* Storage for dynamic or static value. */
+ union dynamic_prop_data data;
+};
+
+/* Compare two dynamic_prop objects for equality. dynamic_prop
+ instances are equal iff they have the same type and storage. */
+extern bool operator== (const dynamic_prop &l, const dynamic_prop &r);
+
+/* Compare two dynamic_prop objects for inequality. */
+static inline bool operator!= (const dynamic_prop &l, const dynamic_prop &r)
+{
+ return !(l == r);
+}
+
+/* * Define a type's dynamic property node kind. */
+enum dynamic_prop_node_kind
+{
+ /* A property providing a type's data location.
+ Evaluating this field yields to the location of an object's data. */
+ DYN_PROP_DATA_LOCATION,
+
+ /* A property representing DW_AT_allocated. The presence of this attribute
+ indicates that the object of the type can be allocated/deallocated. */
+ DYN_PROP_ALLOCATED,
+
+ /* A property representing DW_AT_associated. The presence of this attribute
+ indicated that the object of the type can be associated. */
+ DYN_PROP_ASSOCIATED,
+
+ /* A property providing an array's byte stride. */
+ DYN_PROP_BYTE_STRIDE,
+
+ /* A property holding variant parts. */
+ DYN_PROP_VARIANT_PARTS,
+
+ /* A property holding the size of the type. */
+ DYN_PROP_BYTE_SIZE,
+};
+
+/* * List for dynamic type attributes. */
+struct dynamic_prop_list
+{
+ /* The kind of dynamic prop in this node. */
+ enum dynamic_prop_node_kind prop_kind;
+
+ /* The dynamic property itself. */
+ struct dynamic_prop prop;
+
+ /* A pointer to the next dynamic property. */
+ struct dynamic_prop_list *next;
+};
+
+/* * Determine which field of the union main_type.fields[x].loc is
+ used. */