Skip to content

Commit 98103ff

Browse files
authored
Merge pull request #3725 from tautschnig/simplify-after-deref
Symex-dereference: simplify after deref [blocks: #2574, #4056]
2 parents 28dc3d7 + 0b09ffa commit 98103ff

File tree

7 files changed

+78
-0
lines changed

7 files changed

+78
-0
lines changed
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
public class Test {
2+
public static void main() {
3+
Generic<Integer> g = new GenericSub<Integer>();
4+
5+
int x = 0;
6+
for(int i = 0; i < 1000; ++i)
7+
x += g.get();
8+
9+
assert x == 0;
10+
}
11+
}
12+
13+
class Generic<T> {
14+
T key;
15+
int x;
16+
17+
public int get() { return 0; }
18+
19+
public Generic() {
20+
key = null;
21+
x = 5;
22+
}
23+
}
24+
25+
class GenericSub<S> extends Generic<S> {
26+
public int get() { return x; }
27+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
Test.class
3+
--function Test.main --show-vcc
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\{-\d+\} symex_dynamic::dynamic_object1#3 = \{ \{ \{ "java::GenericSub" \}, NULL, 0 \} \}$
7+
^\{-\d+\} symex_dynamic::dynamic_object1#4 = \{ \{ \{ "java::GenericSub" \}, NULL, 5 \} \}$
8+
--
9+
byte_extract_(big|little)_endian
10+
--
11+
The use of generics should not result in any byte_extract operations being
12+
generated for this test.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
: dynamic_object1#\d+\) WITH
9+
--
10+
The above pattern makes sure we don't have a conditional choice of objects
11+
within a "with" expression. We avoid having this by running the simplifier after
12+
dereferencing.

src/goto-symex/symex_dereference.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Daniel Kroening, [email protected]
1616
#include <util/byte_operators.h>
1717
#include <util/c_types.h>
1818
#include <util/exception_utils.h>
19+
#include <util/expr_util.h>
1920
#include <util/invariant.h>
2021
#include <util/pointer_offset_size.h>
2122

@@ -363,4 +364,30 @@ void goto_symext::dereference(exprt &expr, statet &state)
363364
// dereferencing may introduce new symbol_exprt
364365
// (like __CPROVER_memory)
365366
expr = state.rename<L1>(std::move(l1_expr), ns);
367+
368+
// Dereferencing is likely to introduce new member-of-if constructs --
369+
// for example, "x->field" may have become "(x == &o1 ? o1 : o2).field."
370+
// Run expression simplification, which converts that to
371+
// (x == &o1 ? o1.field : o2.field))
372+
// before applying field sensitivity. Field sensitivity can then turn such
373+
// field-of-symbol expressions into atomic SSA expressions instead of having
374+
// to rewrite all of 'o1' otherwise.
375+
// Even without field sensitivity this can be beneficial: for example,
376+
// "(b ? s1 : s2).member := X" results in
377+
// (b ? s1 : s2) := (b ? s1 : s2) with (member := X)
378+
// and then
379+
// s1 := b ? ((b ? s1 : s2) with (member := X)) : s1
380+
// when all we need is
381+
// s1 := s1 with (member := X) [and guard b]
382+
// s2 := s2 with (member := X) [and guard !b]
383+
do_simplify(expr);
384+
385+
if(symex_config.run_validation_checks)
386+
{
387+
// make sure simplify has not re-introduced any dereferencing that
388+
// had previously been cleaned away
389+
INVARIANT(
390+
!has_subexpr(expr, ID_dereference),
391+
"simplify re-introduced dereferencing");
392+
}
366393
}

0 commit comments

Comments
 (0)