File tree Expand file tree Collapse file tree 23 files changed +994
-10
lines changed
local_control_flow_history_01
local_control_flow_history_02
local_control_flow_history_03
local_control_flow_history_04
local_control_flow_history_05
local_control_flow_history_06 Expand file tree Collapse file tree 23 files changed +994
-10
lines changed Original file line number Diff line number Diff line change 1+ #include <assert.h>
2+
3+ int main (int argc , char * * argv )
4+ {
5+ int branch ;
6+ int x = 0 ;
7+
8+ if (branch )
9+ {
10+ x = 1 ;
11+ }
12+ else
13+ {
14+ x = -1 ;
15+ }
16+
17+ // Merging a constant domain here will make this unprovable
18+ assert (x != 0 );
19+
20+ // Some subtle points here...
21+ // The history tracks paths, it is up to the domain to track the
22+ // path conditon / consequences of that path.
23+ //
24+ // We have two paths:
25+ // branch == ?, x == 1
26+ // branch == 0, x == -1
27+ //
28+ // As the domain in the first case can't express branch != 0
29+ // we will wind up with three paths here, including a spurious
30+ // one with branch == 0, x == 1.
31+ if (branch )
32+ {
33+ assert (x == 1 );
34+ }
35+ else
36+ {
37+ assert (x == -1 );
38+ }
39+
40+ // Working around the domain issues...
41+ // (This doesn't increase the number of paths)
42+ if (x == 1 )
43+ {
44+ x -- ;
45+ }
46+ else
47+ {
48+ x ++ ;
49+ }
50+
51+ // Should be true in all 3 paths
52+ assert (x == 0 );
53+
54+ return 0 ;
55+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --verify --recursive-interprocedural --branching 0 --constants --one-domain-per-history
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.assertion.1\] .* assertion x != 0: SUCCESS$
7+ ^\[main.assertion.2\] .* assertion x == 1: SUCCESS$
8+ ^\[main.assertion.3\] .* assertion x == -1: FAILURE \(if reachable\)$
9+ ^\[main.assertion.4\] .* assertion x == 0: SUCCESS$
10+ --
11+ ^warning: ignoring
12+ --
13+ This demonstrates the "lazy merging" that comes from tracking the history of branching
Original file line number Diff line number Diff line change 1+ #include <assert.h>
2+
3+ int main (int argc , char * * argv )
4+ {
5+ int branching_array [5 ];
6+ int x = 1 ;
7+
8+ if (branching_array [0 ])
9+ {
10+ ++ x ;
11+ }
12+ // Two paths...
13+ assert (x > 0 );
14+
15+ if (branching_array [1 ])
16+ {
17+ ++ x ;
18+ }
19+ // Four paths...
20+ assert (x > 0 );
21+
22+ if (branching_array [2 ])
23+ {
24+ ++ x ;
25+ }
26+ // Eight paths...
27+ assert (x > 0 );
28+
29+ if (branching_array [3 ])
30+ {
31+ ++ x ;
32+ }
33+ // Paths merge so there will be some paths that will set x to \top
34+ // and so this will be flagged as unknown
35+ assert (x > 0 );
36+ // In principle it would be possible to merge paths in such a way
37+ // that the those with similar domains are merged and this would be
38+ // able to be proved. The local_control_flow_history code doesn't
39+ // do this though.
40+
41+ return 0 ;
42+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --verify --recursive-interprocedural --branching 12 --constants --one-domain-per-history
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.assertion.1\] .* assertion x > 0: SUCCESS$
7+ ^\[main.assertion.2\] .* assertion x > 0: SUCCESS$
8+ ^\[main.assertion.3\] .* assertion x > 0: SUCCESS$
9+ ^\[main.assertion.4\] .* assertion x > 0: UNKNOWN$
10+ --
11+ ^warning: ignoring
12+ --
13+ This demonstrates hitting the path limit and the merging of paths
Original file line number Diff line number Diff line change 1+ #include <assert.h>
2+
3+ int main (int argc , char * * argv )
4+ {
5+ int total = 0 ;
6+ int n = 50 ;
7+ int i ;
8+
9+ for (i = 0 ; i < n ; ++ i )
10+ {
11+ total += i ;
12+ }
13+
14+ assert (total == (n * (n - 1 ) / 2 ));
15+
16+ return 0 ;
17+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --verify --recursive-interprocedural --loop-unwind 0 --constants --one-domain-per-history
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.assertion.1\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
7+ --
8+ ^warning: ignoring
9+ --
10+ A basic test of loop unwinding.
Original file line number Diff line number Diff line change 1+ #include <assert.h>
2+
3+ int main (int argc , char * * argv )
4+ {
5+ int total ;
6+ int n ;
7+ int i ;
8+
9+ total = 0 ;
10+ n = 8 ;
11+ for (i = 0 ; i < n ; ++ i )
12+ {
13+ total += i ;
14+ }
15+
16+ // Unknown due to the limit on unwindings
17+ assert (total == (n * (n - 1 ) / 2 ));
18+
19+ // Condense down to one path...
20+
21+ total = 0 ;
22+ n = 16 ;
23+ for (i = 0 ; i < n ; ++ i )
24+ {
25+ total += i ;
26+ }
27+
28+ // Creates a merge path but only one user of it
29+ assert (total == (n * (n - 1 ) / 2 ));
30+
31+ total = 0 ;
32+ n = 32 ;
33+ for (i = 0 ; i < n ; ++ i )
34+ {
35+ total += i ;
36+ }
37+
38+ // Provable
39+ assert (total == (n * (n - 1 ) / 2 ));
40+
41+ return 0 ;
42+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --verify --recursive-interprocedural --loop-unwind 17 --constants --one-domain-per-history
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.assertion.1\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
7+ ^\[main.assertion.2\] .* assertion total == \(n \* \(n - 1\) / 2\): SUCCESS$
8+ ^\[main.assertion.3\] .* assertion total == \(n \* \(n - 1\) / 2\): UNKNOWN$
9+ --
10+ ^warning: ignoring
11+ --
12+ A basic test of the loop unwinding limit.
13+ You might think this has an off-by-one error but to process a loop 16 times
14+ you have to visit the loop guard 17 times. Setting the loop limit to 16 will
15+ cause the last two visits to merge loosing the precision needed to prove the
16+ conjecture.
Original file line number Diff line number Diff line change 1+ #include <assert.h>
2+
3+ int main (int argc , char * * argv )
4+ {
5+ int total ;
6+ int n ;
7+ int i ;
8+ int branching [4 ];
9+
10+ total = 0 ;
11+ n = 4 ;
12+ for (i = 0 ; i < n ; ++ i )
13+ {
14+ if (branching [i ])
15+ {
16+ total += i ;
17+ }
18+ }
19+
20+ assert (total <= (n * (n - 1 ) / 2 ));
21+
22+ return 0 ;
23+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --verify --recursive-interprocedural --loop-unwind-and-branching 32 --constants --one-domain-per-history
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.assertion.1\] .* assertion total <= \(n \* \(n - 1\) / 2\): SUCCESS$
7+ --
8+ ^warning: ignoring
9+ --
10+ Test tracking all local control-flow history.
11+ Note the exponential rise in the number of paths!
You can’t perform that action at this time.
0 commit comments