Skip to content

Commit 82b0938

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 0034624 commit 82b0938

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
@@ -2091,23 +2091,26 @@ static void update_index_set(
20912091
/// \param [in] expr: the expression to search
20922092
/// \param [in] str: the string which must be indexed
20932093
/// \param [in] qvar: the universal variable that must be in the index
2094-
/// \return an index expression in `expr` on `str` containing `qvar`
2095-
static exprt find_index(
2096-
const exprt &expr, const exprt &str, const symbol_exprt &qvar)
2094+
/// \return an index expression in `expr` on `str` containing `qvar`. Returns
2095+
/// an empty optional when `expr` does not contain `str`.
2096+
static optionalt<exprt>
2097+
find_index(const exprt &expr, const exprt &str, const symbol_exprt &qvar)
20972098
{
2098-
const auto it=std::find_if(
2099-
expr.depth_begin(),
2100-
expr.depth_end(),
2101-
[&] (const exprt &e) -> bool
2102-
{
2103-
return e.id()==ID_index
2104-
&& to_index_expr(e).array()==str
2105-
&& find_qvar(to_index_expr(e).index(), qvar);
2099+
const auto it = std::find_if(
2100+
expr.depth_begin(), expr.depth_end(), [&](const exprt &e) { // NOLINT
2101+
if(auto index_expr = expr_try_dynamic_cast<index_exprt>(e))
2102+
{
2103+
const auto &arr = index_expr->array();
2104+
const auto str_it = std::find(arr.depth_begin(), arr.depth_end(), str);
2105+
return str_it != arr.depth_end() &&
2106+
find_qvar(index_expr->index(), qvar);
2107+
}
2108+
return false;
21062109
});
21072110

2108-
return it==expr.depth_end()
2109-
?nil_exprt()
2110-
:to_index_expr(*it).index();
2111+
if(it != expr.depth_end())
2112+
return to_index_expr(*it).index();
2113+
return {};
21112114
}
21122115

21132116
/// Instantiates a string constraint by substituting the quantifiers.
@@ -2128,11 +2131,11 @@ static exprt instantiate(
21282131
const exprt &str,
21292132
const exprt &val)
21302133
{
2131-
const exprt idx = find_index(axiom.body(), str, axiom.univ_var());
2132-
if(idx.is_nil())
2134+
const optionalt<exprt> idx = find_index(axiom.body(), str, axiom.univ_var());
2135+
if(!idx.has_value())
21332136
return true_exprt();
21342137

2135-
const exprt r = compute_inverse_function(stream, axiom.univ_var(), val, idx);
2138+
const exprt r = compute_inverse_function(stream, axiom.univ_var(), val, *idx);
21362139
implies_exprt instance(
21372140
and_exprt(
21382141
binary_relation_exprt(axiom.univ_var(), ID_ge, axiom.lower_bound()),

0 commit comments

Comments
 (0)