Skip to content

Commit cd64a96

Browse files
authored
Merge pull request #8942 from tautschnig/let-bound-arrays
Connect let-bound arrays to originals in array theory
2 parents 582cc2a + 14105d5 commit cd64a96

5 files changed

Lines changed: 59 additions & 2 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
let-array.smt2
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^unsat$
7+
--
8+
^sat$
9+
--
10+
Let-bound arrays must be connected to the original array in the
11+
array theory so that element-wise constraints propagate correctly.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; Test that let-bound arrays are properly connected to the original
2+
; array in the array theory. A let binding creates a fresh symbol
3+
; internally; without proper connection, the element-wise constraints
4+
; on the original array don't propagate to the let-bound copy.
5+
(set-option :produce-models true)
6+
(declare-fun arr () (Array (_ BitVec 32) (_ BitVec 32)))
7+
(assert (= (select arr (_ bv0 32)) (_ bv42 32)))
8+
(assert (= (select arr (_ bv1 32)) (_ bv99 32)))
9+
(assert (not (= (let ((?a arr)) (select ?a (_ bv1 32))) (_ bv99 32))))
10+
(check-sat)
11+
(exit)

src/solvers/flattening/arrays.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ literalt arrayst::record_array_equality(
8080
return array_equalities.back().l;
8181
}
8282

83+
void arrayst::record_array_let_binding(
84+
const symbol_exprt &symbol,
85+
const exprt &value)
86+
{
87+
DATA_INVARIANT(
88+
symbol.type().id() == ID_array,
89+
"record_array_let_binding parameter should be array-typed");
90+
91+
const equal_exprt eq{symbol, value};
92+
const literalt eq_lit = record_array_equality(eq);
93+
prop.l_set_to_true(eq_lit);
94+
}
95+
8396
void arrayst::collect_indices()
8497
{
8598
for(std::size_t i=0; i<arrays.size(); i++)

src/solvers/flattening/arrays.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class array_of_exprt;
2626
class equal_exprt;
2727
class if_exprt;
2828
class index_exprt;
29+
class symbol_exprt;
2930
class with_exprt;
3031
class update_exprt;
3132

@@ -52,6 +53,12 @@ class arrayst:public equalityt
5253
literalt record_array_equality(const equal_exprt &expr);
5354
void record_array_index(const index_exprt &expr);
5455

56+
/// Record that \p symbol is equal to \p value for the purposes of the
57+
/// array theory. For unbounded-array-typed bindings this connects the
58+
/// two expressions in the union-find so that element-wise constraints
59+
/// propagate correctly.
60+
void record_array_let_binding(const symbol_exprt &symbol, const exprt &value);
61+
5562
protected:
5663
const namespacet &ns;
5764
messaget log;

src/solvers/flattening/boolbv_let.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@ Author: Daniel Kroening, kroening@kroening.com
66
77
\*******************************************************************/
88

9-
#include "boolbv.h"
10-
9+
#include <util/byte_operators.h>
1110
#include <util/range.h>
1211
#include <util/replace_symbol.h>
1312
#include <util/std_expr.h>
1413

14+
#include "boolbv.h"
15+
1516
bvt boolbvt::convert_let(const let_exprt &expr)
1617
{
1718
const auto &variables = expr.variables();
@@ -69,6 +70,20 @@ bvt boolbvt::convert_let(const let_exprt &expr)
6970
for(const auto &pair : make_range(variables).zip(fresh_variables))
7071
replace_symbol.insert(pair.first, pair.second);
7172

73+
// Connect fresh let-bound symbols to their values in the array theory.
74+
for(const auto &pair : make_range(fresh_variables).zip(values))
75+
{
76+
if(
77+
pair.first.type().id() == ID_array &&
78+
is_unbounded_array(to_array_type(pair.first.type())))
79+
{
80+
const exprt lowered_value = has_byte_operator(pair.second)
81+
? lower_byte_operators(pair.second, ns)
82+
: pair.second;
83+
record_array_let_binding(pair.first, pair.second);
84+
}
85+
}
86+
7287
// rename the bound symbols in 'where'
7388
exprt where_renamed = expr.where();
7489
replace_symbol(where_renamed);

0 commit comments

Comments
 (0)