Skip to content

Commit 7a82951

Browse files
authored
Merge pull request #6810 from tautschnig/bugfixes/binding
Extend support for binding expressions beyond quantifiers
2 parents f9938c5 + 6f8a7b8 commit 7a82951

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

src/goto-symex/symex_clean_expr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ void goto_symext::lift_lets(statet &state, exprt &rhs)
212212

213213
it.next_sibling_or_parent();
214214
}
215-
else if(it->id() == ID_exists || it->id() == ID_forall)
215+
else if(can_cast_expr<binding_exprt>(*it))
216216
{
217217
// expressions within exists/forall may depend on bound variables, we
218218
// cannot safely lift let expressions out of those, just skip

src/goto-symex/symex_dereference.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -249,16 +249,16 @@ goto_symext::cache_dereference(exprt &dereference_result, statet &state)
249249
/// goto_symext::address_arithmetic) and certain common expression patterns
250250
/// such as `&struct.flexible_array[0]` (see inline comments in code).
251251
/// Note that \p write is used to alter behaviour when this function is
252-
/// operating on the LHS of an assignment. Similarly \p is_in_quantifier
253-
/// indicates when the dereference is inside a quantifier (related to scoping
254-
/// when dereference caching is enabled).
252+
/// operating on the LHS of an assignment. Similarly \p is_in_binding_expression
253+
/// indicates when the dereference is inside a binding expression (related to
254+
/// scoping when dereference caching is enabled).
255255
/// For full details of this method's pointer replacement and potential side-
256256
/// effects see \ref goto_symext::dereference
257257
void goto_symext::dereference_rec(
258258
exprt &expr,
259259
statet &state,
260260
bool write,
261-
bool is_in_quantifier)
261+
bool is_in_binding_expression)
262262
{
263263
if(expr.id()==ID_dereference)
264264
{
@@ -281,7 +281,7 @@ void goto_symext::dereference_rec(
281281
tmp1.swap(to_dereference_expr(expr).pointer());
282282

283283
// first make sure there are no dereferences in there
284-
dereference_rec(tmp1, state, false, is_in_quantifier);
284+
dereference_rec(tmp1, state, false, is_in_binding_expression);
285285

286286
// Depending on the nature of the pointer expression, the recursive deref
287287
// operation might have introduced a construct such as
@@ -345,7 +345,7 @@ void goto_symext::dereference_rec(
345345
// (p == &something ? something : ...))
346346
// Otherwise we should just return it unchanged.
347347
if(
348-
symex_config.cache_dereferences && !write && !is_in_quantifier &&
348+
symex_config.cache_dereferences && !write && !is_in_binding_expression &&
349349
(tmp2.id() == ID_if || tmp2.id() == ID_let))
350350
{
351351
expr = cache_dereference(tmp2, state);
@@ -372,7 +372,7 @@ void goto_symext::dereference_rec(
372372
tmp.add_source_location()=expr.source_location();
373373

374374
// recursive call
375-
dereference_rec(tmp, state, write, is_in_quantifier);
375+
dereference_rec(tmp, state, write, is_in_binding_expression);
376376

377377
expr.swap(tmp);
378378
}
@@ -406,18 +406,22 @@ void goto_symext::dereference_rec(
406406
expr = address_of_exprt(index_exprt(
407407
to_address_of_expr(tc_op).object(), from_integer(0, c_index_type())));
408408

409-
dereference_rec(expr, state, write, is_in_quantifier);
409+
dereference_rec(expr, state, write, is_in_binding_expression);
410410
}
411411
else
412412
{
413-
dereference_rec(tc_op, state, write, is_in_quantifier);
413+
dereference_rec(tc_op, state, write, is_in_binding_expression);
414414
}
415415
}
416416
else
417417
{
418-
bool is_quantifier = expr.id() == ID_forall || expr.id() == ID_exists;
418+
bool is_binding_expression =
419+
can_cast_expr<binding_exprt>(expr) || can_cast_expr<let_exprt>(expr);
419420
Forall_operands(it, expr)
420-
dereference_rec(*it, state, write, is_in_quantifier || is_quantifier);
421+
{
422+
dereference_rec(
423+
*it, state, write, is_in_binding_expression || is_binding_expression);
424+
}
421425
}
422426
}
423427

src/util/std_expr.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3099,6 +3099,13 @@ class binding_exprt : public binary_exprt
30993099
exprt instantiate(const variablest &) const;
31003100
};
31013101

3102+
template <>
3103+
inline bool can_cast_expr<binding_exprt>(const exprt &base)
3104+
{
3105+
return base.id() == ID_forall || base.id() == ID_exists ||
3106+
base.id() == ID_lambda || base.id() == ID_array_comprehension;
3107+
}
3108+
31023109
inline void validate_expr(const binding_exprt &binding_expr)
31033110
{
31043111
validate_operands(

0 commit comments

Comments
 (0)