@@ -236,6 +236,34 @@ static exprt unpack_rec(
236236 std::move (byte_operands),
237237 array_typet (unsignedbv_typet (8 ), from_integer (size, size_type ())));
238238 }
239+ else if (src.type ().id () == ID_union || src.type ().id () == ID_union_tag)
240+ {
241+ const union_typet &union_type = to_union_type (ns.follow (src.type ()));
242+ const union_typet::componentst &components = union_type.components ();
243+
244+ mp_integer max_width = 0 ;
245+ typet max_comp_type;
246+ irep_idt max_comp_name;
247+
248+ for (const auto &comp : components)
249+ {
250+ auto element_width = pointer_offset_bits (comp.type (), ns);
251+
252+ if (!element_width.has_value () || *element_width <= max_width)
253+ continue ;
254+
255+ max_width = *element_width;
256+ max_comp_type = comp.type ();
257+ max_comp_name = comp.get_name ();
258+ }
259+
260+ if (max_width > 0 )
261+ {
262+ member_exprt member (src, max_comp_name, max_comp_type);
263+ return unpack_rec (
264+ member, little_endian, offset_bytes, max_bytes, ns, true );
265+ }
266+ }
239267 else if (src.type ().id ()!=ID_empty)
240268 {
241269 // a basic type; we turn that into extractbits while considering
@@ -455,6 +483,36 @@ exprt lower_byte_extract(const byte_extract_exprt &src, const namespacet &ns)
455483 if (!failed)
456484 return simplify_expr (s, ns);
457485 }
486+ else if (src.type ().id () == ID_union || src.type ().id () == ID_union_tag)
487+ {
488+ const union_typet &union_type = to_union_type (ns.follow (src.type ()));
489+ const union_typet::componentst &components = union_type.components ();
490+
491+ mp_integer max_width = 0 ;
492+ typet max_comp_type;
493+ irep_idt max_comp_name;
494+
495+ for (const auto &comp : components)
496+ {
497+ auto element_width = pointer_offset_bits (comp.type (), ns);
498+
499+ if (!element_width.has_value () || *element_width <= max_width)
500+ continue ;
501+
502+ max_width = *element_width;
503+ max_comp_type = comp.type ();
504+ max_comp_name = comp.get_name ();
505+ }
506+
507+ if (max_width > 0 )
508+ {
509+ byte_extract_exprt tmp (unpacked);
510+ tmp.type () = max_comp_type;
511+
512+ return union_exprt (
513+ max_comp_name, lower_byte_extract (tmp, ns), union_type);
514+ }
515+ }
458516
459517 const exprt &root=unpacked.op ();
460518 const exprt &offset=unpacked.offset ();
0 commit comments