Skip to content

Commit e5039dd

Browse files
Correct find_index function for if-expressions
find_index would give up if the array in the index expression does not correspond exactly to the given `str`, however it could be an expression that contains str. For instance `(cond?str1:str2)[i+1]` is equivalent to `cond?(str1[i+1]):(str2[i+1])`, so in both cases `find_index(e, str1, i)` should return `i+1`.
1 parent 27a5425 commit e5039dd

File tree

1 file changed

+20
-17
lines changed

1 file changed

+20
-17
lines changed

src/solvers/refinement/string_refinement.cpp

+20-17
Original file line numberDiff line numberDiff line change
@@ -2088,23 +2088,26 @@ static void update_index_set(
20882088
/// \param [in] expr: the expression to search
20892089
/// \param [in] str: the string which must be indexed
20902090
/// \param [in] qvar: the universal variable that must be in the index
2091-
/// \return an index expression in `expr` on `str` containing `qvar`
2092-
static exprt find_index(
2093-
const exprt &expr, const exprt &str, const symbol_exprt &qvar)
2091+
/// \return an index expression in `expr` on `str` containing `qvar`. Returns
2092+
/// an empty optional when `expr` does not contain `str`.
2093+
static optionalt<exprt>
2094+
find_index(const exprt &expr, const exprt &str, const symbol_exprt &qvar)
20942095
{
2095-
const auto it=std::find_if(
2096-
expr.depth_begin(),
2097-
expr.depth_end(),
2098-
[&] (const exprt &e) -> bool
2099-
{
2100-
return e.id()==ID_index
2101-
&& to_index_expr(e).array()==str
2102-
&& find_qvar(to_index_expr(e).index(), qvar);
2096+
const auto it = std::find_if(
2097+
expr.depth_begin(), expr.depth_end(), [&](const exprt &e) { // NOLINT
2098+
if(auto index_expr = expr_try_dynamic_cast<index_exprt>(e))
2099+
{
2100+
const auto &arr = index_expr->array();
2101+
const auto str_it = std::find(arr.depth_begin(), arr.depth_end(), str);
2102+
return str_it != arr.depth_end() &&
2103+
find_qvar(index_expr->index(), qvar);
2104+
}
2105+
return false;
21032106
});
21042107

2105-
return it==expr.depth_end()
2106-
?nil_exprt()
2107-
:to_index_expr(*it).index();
2108+
if(it != expr.depth_end())
2109+
return to_index_expr(*it).index();
2110+
return {};
21082111
}
21092112

21102113
/// Instantiates a string constraint by substituting the quantifiers.
@@ -2125,11 +2128,11 @@ static exprt instantiate(
21252128
const exprt &str,
21262129
const exprt &val)
21272130
{
2128-
const exprt idx = find_index(axiom.body(), str, axiom.univ_var());
2129-
if(idx.is_nil())
2131+
const optionalt<exprt> idx = find_index(axiom.body(), str, axiom.univ_var());
2132+
if(!idx.has_value())
21302133
return true_exprt();
21312134

2132-
const exprt r = compute_inverse_function(stream, axiom.univ_var(), val, idx);
2135+
const exprt r = compute_inverse_function(stream, axiom.univ_var(), val, *idx);
21332136
implies_exprt instance(
21342137
and_exprt(
21352138
and_exprt(

0 commit comments

Comments
 (0)