Skip to content

Commit 79ece0b

Browse files
Merge pull request #7951 from thomasspriggs/tas/smt_struct_of_struct
Fix SMT encoding of structs which contain a single struct field
2 parents 16e4cf1 + 7eab7ac commit 79ece0b

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

regression/cbmc/Struct_Initialization5/test.desc

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

44
^EXIT=0$

src/solvers/smt2_incremental/encoding/struct_encoding.cpp

+16-4
Original file line numberDiff line numberDiff line change
@@ -203,19 +203,31 @@ exprt struct_encodingt::encode(exprt expr) const
203203
while(!work_queue.empty())
204204
{
205205
exprt &current = *work_queue.front();
206-
work_queue.pop();
207206
// Note that "with" expressions are handled before type encoding in order to
208207
// facilitate checking that they are applied to structs rather than arrays.
209208
if(const auto with_expr = expr_try_dynamic_cast<with_exprt>(current))
210209
if(can_cast_type<struct_tag_typet>(current.type()))
211210
current = ::encode(*with_expr, ns);
212211
current.type() = encode(current.type());
212+
optionalt<exprt> update;
213213
if(const auto struct_expr = expr_try_dynamic_cast<struct_exprt>(current))
214-
current = ::encode(*struct_expr);
214+
update = ::encode(*struct_expr);
215215
if(const auto union_expr = expr_try_dynamic_cast<union_exprt>(current))
216-
current = ::encode(*union_expr, *boolbv_width);
216+
update = ::encode(*union_expr, *boolbv_width);
217217
if(const auto member_expr = expr_try_dynamic_cast<member_exprt>(current))
218-
current = encode_member(*member_expr);
218+
update = encode_member(*member_expr);
219+
if(update)
220+
{
221+
INVARIANT(
222+
current != *update,
223+
"Updates in struct encoding are expected to be a change of state.");
224+
current = std::move(*update);
225+
// Repeat on the updated node until we reach a fixed point. This is needed
226+
// because the encoding of an outer struct/union may be initially
227+
// expressed in terms of an inner struct/union which it contains.
228+
continue;
229+
}
230+
work_queue.pop();
219231
for(auto &operand : current.operands())
220232
work_queue.push(&operand);
221233
}

unit/solvers/smt2_incremental/encoding/struct_encoding.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ TEST_CASE("struct encoding of expressions", "[core][smt2_incremental]")
169169
const concatenation_exprt expected_result{
170170
{green_ham.symbol_expr(), forty_two, minus_one}, bv_typet{72}};
171171
REQUIRE(test.struct_encoding.encode(struct_expr) == expected_result);
172+
SECTION("struct containing a single struct")
173+
{
174+
const struct_typet struct_struct_type{
175+
struct_union_typet::componentst{{"inner", struct_tag}}};
176+
const type_symbolt struct_struct_type_symbol{
177+
"struct_structt", struct_type, ID_C};
178+
test.symbol_table.insert(type_symbol);
179+
const struct_tag_typet struct_struct_tag{type_symbol.name};
180+
const struct_exprt struct_struct{
181+
exprt::operandst{struct_expr}, struct_struct_tag};
182+
REQUIRE(test.struct_encoding.encode(struct_struct) == expected_result);
183+
}
172184
}
173185
SECTION("member expression selecting a data member of a struct")
174186
{

0 commit comments

Comments
 (0)