@@ -176,19 +176,26 @@ static std::size_t count_trailing_bit_width(
176
176
trailing_widths.begin (), trailing_widths.end (), std::size_t {0 });
177
177
}
178
178
179
- // / The member expression selects the value of a field from a struct. The
180
- // / struct is encoded as a single bitvector where the first field is stored
179
+ // / The member expression selects the value of a field from a struct or union.
180
+ // / Both structs and unions are encoded into a single large bit vector.
181
+ // / The fields of a union are encoded into the lowest bits, with padding in the
182
+ // / highest bits if needed.
183
+ // / Structs are encoded as a single bitvector where the first field is stored
181
184
// / in the highest bits. The second field is stored in the next highest set of
182
185
// / bits and so on. As offsets are indexed from the lowest bit, any field can be
183
186
// / selected by extracting the range of bits starting from an offset based on
184
187
// / the combined width of the fields which follow the field being selected.
185
188
exprt struct_encodingt::encode_member (const member_exprt &member_expr) const
186
189
{
187
- const auto &struct_type = type_checked_cast<struct_typet>(
188
- ns.get ().follow (member_expr.compound ().type ()));
189
- const std::size_t offset_bits = count_trailing_bit_width (
190
- struct_type, member_expr.get_component_name (), *boolbv_width);
190
+ const auto &type = ns.get ().follow (member_expr.compound ().type ());
191
191
const auto member_bits_width = (*boolbv_width)(member_expr.type ());
192
+ const auto offset_bits = [&]() -> std::size_t {
193
+ if (can_cast_type<union_typet>(type))
194
+ return 0 ;
195
+ const auto &struct_type = type_checked_cast<struct_typet>(type);
196
+ return count_trailing_bit_width (
197
+ struct_type, member_expr.get_component_name (), *boolbv_width);
198
+ }();
192
199
return extractbits_exprt{
193
200
member_expr.compound (),
194
201
offset_bits + member_bits_width - 1 ,
0 commit comments