Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/solvers/strings/string_constraint_generator_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,8 @@ array_string_exprt array_poolt::make_char_array_for_char_pointer(
if_expr.cond(),
to_array_type(t.type()).size(),
to_array_type(f.type()).size()));
// BEWARE: this expression is possibly type-inconsistent and must not be
// used for any purposes other than passing it to concretisation
return to_array_string_expr(if_exprt(if_expr.cond(), t, f, array_type));
}
const bool is_constant_array =
Expand Down
48 changes: 47 additions & 1 deletion src/solvers/strings/string_refinement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,49 @@ decision_proceduret::resultt string_refinementt::dec_solve()
return resultt::D_ERROR;
}

/// In a best-effort manner, try to clean up the type inconsistencies introduced
/// by \ref array_poolt::make_char_array_for_char_pointer, which creates
/// conditional expressions for the size of arrays. The cleanup is achieved by
/// removing branches that are found to be infeasible, and by simplifying the
/// conditional size expressions previously generated.
/// \param expr: Expression to be cleaned
/// \param ns: Namespace
/// \return Cleaned expression
static exprt adjust_if_recursive(exprt expr, const namespacet &ns)
{
for(auto it = expr.depth_begin(); it != expr.depth_end();)
{
if(it->id() == ID_if)
{
if_exprt if_expr = to_if_expr(*it);
const exprt simp_cond = simplify_expr(if_expr.cond(), ns);
if(simp_cond.is_true())
{
it.mutate() = adjust_if_recursive(if_expr.true_case(), ns);
it.next_sibling_or_parent();
}
else if(simp_cond.is_false())
{
it.mutate() = adjust_if_recursive(if_expr.false_case(), ns);
it.next_sibling_or_parent();
}
else if(
it->type().id() == ID_array &&
to_array_type(it->type()).size().id() == ID_if)
{
simplify(to_array_type(it.mutate().type()).size(), ns);
++it;
}
else
++it;
}
else
++it;
}

return expr;
}

/// Add the given lemma to the solver.
/// \param lemma: a Boolean expression
/// \param simplify_lemma: whether the lemma should be simplified before being
Expand All @@ -869,7 +912,10 @@ void string_refinementt::add_lemma(

exprt simple_lemma = lemma;
if(simplify_lemma)
{
simple_lemma = adjust_if_recursive(std::move(simple_lemma), ns);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will probably not get rid of all the inconsistencies, so I'm not sure about how useful it is. Ideally we should get rid of the introduction of type inconsistencies, but I'm not sure about the best way to do that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recall having tried removing them completely (which would be done by using type casts), but that did not seem to work very well. It's the long-term solution, and maybe that's what we should actually invest in instead of this hack. Not sure though, I'm certainly curious about the results with TG!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything is green on our side, so nothing blocking merging it.

simplify(simple_lemma, ns);
}

if(simple_lemma.is_true())
{
Expand Down Expand Up @@ -917,7 +963,7 @@ static optionalt<exprt> get_array(
{
const auto eom = messaget::eom;
const exprt &size = arr.length();
exprt arr_val = simplify_expr(super_get(arr), ns);
exprt arr_val = simplify_expr(adjust_if_recursive(super_get(arr), ns), ns);
exprt size_val = super_get(size);
size_val = simplify_expr(size_val, ns);
const typet char_type = arr.type().subtype();
Expand Down