@@ -122,16 +122,23 @@ static exprt encode(const with_exprt &with, const namespacet &ns)
122122 return struct_exprt{components, tag_type};
123123}
124124
125- // / Non-empty structs are flattened into a large bit vector using concatenation
126- // / to express all the member operands of \p struct_expr. Empty structs are
127- // / encoded as a zero byte. This has useful properties such as -
125+ // / Empty structs and unions are encoded as a zero byte. This has useful
126+ // / properties such as -
128127// / * A zero byte is valid SMT, unlike zero length bit vectors.
129128// / * Any two zero byte instances are always equal. This property would not
130129// / be true of two instances of a non-det byte for instance.
130+ static exprt empty_encoding ()
131+ {
132+ static auto empty_byte = from_integer (0 , bv_typet{8 });
133+ return empty_byte;
134+ }
135+
136+ // / Structs are flattened into a large bit vector using concatenation to express
137+ // / all the member operands of \p struct_expr.
131138static exprt encode (const struct_exprt &struct_expr)
132139{
133140 if (struct_expr.operands ().empty ())
134- return from_integer ( 0 , bv_typet{ 8 } );
141+ return empty_encoding ( );
135142 if (struct_expr.operands ().size () == 1 )
136143 return struct_expr.operands ().front ();
137144 return concatenation_exprt{struct_expr.operands (), struct_expr.type ()};
@@ -221,6 +228,8 @@ exprt struct_encodingt::encode(exprt expr) const
221228 update = ::encode (*struct_expr);
222229 if (const auto union_expr = expr_try_dynamic_cast<union_exprt>(current))
223230 update = ::encode (*union_expr, *boolbv_width);
231+ if (can_cast_expr<empty_union_exprt>(current))
232+ update = ::empty_encoding ();
224233 if (const auto member_expr = expr_try_dynamic_cast<member_exprt>(current))
225234 update = encode_member (*member_expr);
226235 if (update)
0 commit comments