|
16 | 16 | #include <util/byte_operators.h>
|
17 | 17 | #include <util/c_types.h>
|
18 | 18 | #include <util/exception_utils.h>
|
| 19 | +#include <util/expr_util.h> |
19 | 20 | #include <util/invariant.h>
|
20 | 21 | #include <util/pointer_offset_size.h>
|
21 | 22 |
|
@@ -389,4 +390,23 @@ void goto_symext::dereference(
|
389 | 390 | // dereferencing may introduce new symbol_exprt
|
390 | 391 | // (like __CPROVER_memory)
|
391 | 392 | state.rename(expr, ns, goto_symex_statet::L1);
|
| 393 | + |
| 394 | + // dereferencing is likely to introduce new member-of-if constructs -- |
| 395 | + // for example, "x->field" may have become "(x == &o1 ? o1 : o2).field" |
| 396 | + // Simplify (which converts that to (x == &o1 ? o1.field : o2.field)) before |
| 397 | + // applying field sensitivity, which can turn such field-of-symbol expressions |
| 398 | + // into atomic SSA expressions, but would have to rewrite all of 'o1' |
| 399 | + // otherwise. |
| 400 | + // make the structure of the lhs as simple as possible to avoid, |
| 401 | + // Similarly, (b ? s1 : s2).member=X results in |
| 402 | + // (b ? s1 : s2)=(b ? s1 : s2) with member:=X and then |
| 403 | + // s1=b ? ((b ? s1 : s2) with member:=X) : s1 |
| 404 | + // when all we need is |
| 405 | + // s1=s1 with member:=X [and guard b] |
| 406 | + // s2=s2 with member:=X [and guard !b] |
| 407 | + do_simplify(expr); |
| 408 | + // make sure simplify has not re-introduced any dereferencing that |
| 409 | + // had previously been cleaned away |
| 410 | + INVARIANT( |
| 411 | + !has_subexpr(expr, ID_dereference), "simplify re-introduced dereferencing"); |
392 | 412 | }
|
0 commit comments