Skip to content

Commit 3535b61

Browse files
Merge pull request #7966 from thomasspriggs/tas/smt_empty_unions
Add support for empty unions in incremental SMT decision procedure
2 parents 09236f9 + 92a039e commit 3535b61

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

regression/cbmc/Union_Initialization2/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE gcc-only
1+
CORE gcc-only new-smt-backend
22
main.c
33

44
^EXIT=10$

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

+13-4
Original file line numberDiff line numberDiff line change
@@ -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.
131138
static 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)

unit/solvers/smt2_incremental/encoding/struct_encoding.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,17 @@ TEST_CASE("Encoding of union types", "[core][smt2_incremental]")
122122
{
123123
REQUIRE(test.struct_encoding.encode(union_tag) == bv_typet{8});
124124
}
125+
SECTION("Value enoding")
126+
{
127+
const symbolt symbol{"my_empty_union", union_tag, ID_C};
128+
test.symbol_table.insert(symbol);
129+
const auto symbol_is_empty =
130+
equal_exprt{symbol.symbol_expr(), empty_union_exprt{union_tag}};
131+
const auto expected = equal_exprt{
132+
symbol_exprt{"my_empty_union", bv_typet{8}},
133+
from_integer(0, bv_typet{8})};
134+
REQUIRE(test.struct_encoding.encode(symbol_is_empty) == expected);
135+
}
125136
}
126137
}
127138

0 commit comments

Comments
 (0)