From 87b142883b344eaa2c48607e569137d599b0ed24 Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Fri, 9 Jun 2017 18:07:45 +0100
Subject: [PATCH 001/322] Name CBMC support branch for 2LS 0.5
---
install.sh | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/install.sh b/install.sh
index c72d8988e..596b2c259 100755
--- a/install.sh
+++ b/install.sh
@@ -1,7 +1,7 @@
#!/bin/bash
CBMC_REPO=https://github.com/peterschrammel/cbmc
-CBMC_VERSION=d95e7da28018fd315b04a1201d5b7cfe8195cbc6
+CBMC_VERSION=2ls-prerequisites-0.5
if [ "$1" != "" ]
then
From 7c979dfdba2f15e2d4ce59359240d3edb186621e Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Thu, 20 Jul 2017 18:17:12 +0100
Subject: [PATCH 002/322] Whitespace clean-up
---
regression/graphml/Makefile | 2 +-
regression/graphml/loop23/main.c | 4 +-
regression/graphml/loop29/main.c | 6 +-
regression/graphml/malloc1/main.c | 8 +-
regression/interprocedural/abort1/main.c | 2 +-
.../interprocedural/contextsensitive1/main.c | 32 +++--
.../interprocedural/contextsensitive2/main.c | 54 ++++-----
.../interprocedural/contextsensitive3/main.c | 54 ++++-----
.../interprocedural/contextsensitive4/main.c | 56 +++++----
.../interprocedural/contextsensitive5/main.c | 29 +++--
.../interprocedural/contextsensitive6/main.c | 22 ++--
regression/interprocedural/equal1/main.c | 4 +-
regression/interprocedural/equal2/main.c | 4 +-
regression/interprocedural/equal3/main.c | 4 +-
regression/interprocedural/equal4/main.c | 4 +-
regression/interprocedural/equal7/main.c | 4 +-
.../equality_through_array7/main.c | 2 +-
regression/interprocedural/global1/main.c | 41 +++----
regression/interprocedural/global2/main.c | 43 ++++---
regression/interprocedural/global3/main.c | 4 +-
regression/interprocedural/global4/main.c | 8 +-
regression/interprocedural/ite2/main.c | 10 +-
regression/interprocedural/ite3/main.c | 10 +-
regression/interprocedural/ite4/main.c | 8 +-
regression/interprocedural/pointer1/main.c | 4 +-
regression/interprocedural/pointer2/main.c | 4 +-
regression/interprocedural/simple1/main.c | 10 +-
regression/interprocedural/simple2/main.c | 4 +-
regression/interprocedural/sum1/main.c | 54 ++++-----
regression/invariants/array_safe5/main.c | 4 +-
regression/invariants/complexity1/main.c | 2 +-
regression/invariants/complexity2/main.c | 2 +-
regression/invariants/custom1/main.c | 2 +-
regression/invariants/custom2/main.c | 2 +-
regression/invariants/equal6/main.c | 2 +-
.../invariants/equality_through_array8/main.c | 2 +-
regression/invariants/float1/main.c | 2 +-
regression/invariants/float2/main.c | 2 +-
regression/invariants/float3/main.c | 2 +-
regression/invariants/float4/main.c | 2 +-
regression/invariants/gotoloop1/main.c | 2 +-
regression/invariants/gotoloop2/main.c | 2 +-
regression/invariants/ite1/main.c | 26 ++--
regression/invariants/loop1/main.c | 2 +-
regression/invariants/loop10/main.c | 2 +-
regression/invariants/loop11/main.c | 2 +-
regression/invariants/loop13/main.c | 2 +-
regression/invariants/loop14/main.c | 2 +-
regression/invariants/loop15/main.c | 2 +-
regression/invariants/loop16/main.c | 4 +-
regression/invariants/loop17/main.c | 2 +-
regression/invariants/loop18/main.c | 2 +-
regression/invariants/loop2/main.c | 2 +-
regression/invariants/loop21/main.c | 2 +-
regression/invariants/loop22/main.c | 2 +-
regression/invariants/loop3/main.c | 4 +-
regression/invariants/loop5/main.c | 2 +-
regression/invariants/loop6/main.c | 4 +-
regression/invariants/loop7/main.c | 2 +-
regression/invariants/nested4/main.c | 6 +-
regression/invariants/nested5/main.c | 8 +-
regression/invariants/nonmonotone1/main.c | 2 +-
regression/invariants/nonmonotone2/main.c | 2 +-
regression/invariants/predabs1/main.c | 2 +-
regression/invariants/predabs4/main.c | 2 +-
regression/invariants/unwind1/main.c | 2 +-
regression/invariants/unwind12/main.c | 2 +-
regression/invariants/unwind14/main.c | 4 +-
regression/invariants/unwind15/main.c | 2 +-
regression/invariants/unwind16/main.c | 4 +-
regression/invariants/unwind17/main.c | 6 +-
regression/invariants/unwind18/main.c | 2 +-
regression/invariants/unwind19/main.c | 2 +-
regression/invariants/unwind2/main.c | 2 +-
regression/invariants/unwind3/main.c | 2 +-
regression/invariants/unwind4/main.c | 2 +-
regression/invariants/unwind5/main.c | 4 +-
regression/invariants/unwind6/main.c | 2 +-
regression/invariants/unwind9/main.c | 2 +-
regression/kiki/array1/main.c | 2 +-
regression/kiki/byte_add/main.c | 2 +-
regression/kiki/elevator_13_21/main.c | 8 +-
regression/kiki/encoder1/main.c | 20 +--
regression/kiki/induction1/main.c | 2 +-
regression/kiki/induction2/main.c | 2 +-
regression/kiki/induction3/main.c | 2 +-
regression/kiki/induction4/main.c | 32 ++---
regression/kiki/induction5/main.c | 32 ++---
regression/kiki/induction6/main.c | 114 +++++++++---------
regression/kiki/induction7/main.c | 46 +++----
regression/kiki/induction8/main.c | 38 +++---
regression/kiki/loop12/main.c | 2 +-
regression/kiki/loop23/main.c | 4 +-
regression/kiki/loop24/main.c | 26 ++--
regression/kiki/loop25/main.c | 24 ++--
regression/kiki/loop25/test.desc | 2 +-
regression/kiki/loop26/main.c | 26 ++--
regression/kiki/loop27/main.c | 26 ++--
regression/kiki/loop28/main.c | 16 +--
regression/kiki/loop29/main.c | 6 +-
regression/kiki/loop30/main.c | 6 +-
regression/kiki/loop9/main.c | 2 +-
regression/kiki/malloc1/main.c | 8 +-
regression/kiki/malloc3/main.c | 2 +-
regression/kiki/nested11/main.c | 2 +-
regression/kiki/nested12/main.c | 36 +++---
regression/kiki/s3_clnt_1/main.c | 8 +-
regression/kiki/trafficlight1/main.c | 4 +-
regression/preconditions/precond1/main.c | 4 +-
regression/preconditions/precond2/main.c | 4 +-
regression/preconditions/precond3/main.c | 4 +-
regression/preconditions/precond4/main.c | 6 +-
regression/preconditions/precond5/main.c | 4 +-
regression/preconditions/precond6/main.c | 4 +-
.../precond_contextsensitive1/main.c | 30 ++---
.../precond_contextsensitive2/main.c | 22 ++--
regression/termination/abe_createBack1/main.c | 2 +-
regression/termination/abort1/main.c | 2 +-
regression/termination/abort3/main.c | 2 +-
regression/termination/array_safe5/main.c | 4 +-
regression/termination/array_safe5/test.desc | 2 +-
regression/termination/bubble_sort2/main.c | 2 +-
regression/termination/cav08_1/main.c | 8 +-
regression/termination/cav08_1p/main.c | 8 +-
regression/termination/cav08_2/main.c | 8 +-
regression/termination/cav08_2p/main.c | 8 +-
regression/termination/cav08_3/main.c | 6 +-
regression/termination/cav08_3p/main.c | 6 +-
regression/termination/cav08_4/main.c | 10 +-
regression/termination/cav08_4p/main.c | 10 +-
regression/termination/cav08_5/main.c | 8 +-
regression/termination/cav08_5p/main.c | 8 +-
regression/termination/cav08_6/main.c | 10 +-
regression/termination/cav08_6p/main.c | 10 +-
regression/termination/cav08_7/main.c | 12 +-
regression/termination/cav08_7p/main.c | 12 +-
.../termination/contextsensitive1/main.c | 34 +++---
.../termination/contextsensitive2/main.c | 56 ++++-----
.../termination/contextsensitive3/main.c | 56 ++++-----
.../termination/contextsensitive4/main.c | 58 ++++-----
.../termination/contextsensitive5/main.c | 30 ++---
.../termination/contextsensitive6/main.c | 24 ++--
regression/termination/equal1/main.c | 4 +-
regression/termination/equal2/main.c | 4 +-
regression/termination/equal3/main.c | 4 +-
regression/termination/equal4/main.c | 4 +-
regression/termination/equal6/main.c | 2 +-
regression/termination/equal7/main.c | 4 +-
.../equality_through_array7/main.c | 2 +-
.../equality_through_array7/main.c | 2 +-
.../equality_through_array8/main.c | 2 +-
regression/termination/float1/main.c | 2 +-
regression/termination/float2/main.c | 2 +-
regression/termination/float3/main.c | 2 +-
regression/termination/float4/main.c | 2 +-
regression/termination/float5/main.c | 2 +-
regression/termination/float6/main.c | 2 +-
regression/termination/global1/main.c | 42 +++----
regression/termination/global2/main.c | 44 +++----
regression/termination/global3/main.c | 4 +-
regression/termination/global4/main.c | 8 +-
regression/termination/ite1/main.c | 26 ++--
regression/termination/ite2/main.c | 10 +-
regression/termination/ite3/main.c | 10 +-
regression/termination/ite4/main.c | 8 +-
regression/termination/locks1/main.c | 4 +-
regression/termination/locks2/main.c | 4 +-
regression/termination/loop1/main.c | 2 +-
regression/termination/loop2/main.c | 2 +-
regression/termination/loop3/main.c | 4 +-
regression/termination/loop5/main.c | 2 +-
regression/termination/loop6/main.c | 4 +-
regression/termination/loop7/main.c | 2 +-
regression/termination/loop9/main.c | 2 +-
regression/termination/loops/array_false.c | 12 +-
regression/termination/loops/array_true.c | 12 +-
.../termination/loops/bubble_sort_false.c | 28 ++---
.../termination/loops/eureka_01_false.c | 2 +-
regression/termination/loops/eureka_01_true.c | 2 +-
regression/termination/loops/eureka_05_true.c | 2 +-
.../termination/loops/insertion_sort_false.c | 10 +-
.../termination/loops/insertion_sort_true.c | 10 +-
.../termination/loops/invert_string_false.c | 4 +-
.../termination/loops/invert_string_true.c | 4 +-
.../termination/loops/linear_sea.ch_true.c | 2 +-
.../termination/loops/linear_search_false.c | 2 +-
regression/termination/loops/lu.cmp_true.c | 6 +-
regression/termination/loops/ludcmp_false.c | 6 +-
regression/termination/loops/matrix_false.c | 14 +--
regression/termination/loops/matrix_true.c | 16 +--
regression/termination/loops/n.c11_true.c | 6 +-
regression/termination/loops/n.c24_true.c | 30 ++---
regression/termination/loops/n.c40_true.c | 6 +-
regression/termination/loops/nec11_false.c | 6 +-
regression/termination/loops/nec20_false.c | 6 +-
regression/termination/loops/nec40_true.c | 6 +-
regression/termination/loops/string_false.c | 22 ++--
regression/termination/loops/string_true.c | 22 ++--
.../termination/loops/sum01_bug02_false.c | 4 +-
.../sum01_bug02_sum01_bug02_base.case_false.c | 2 +-
regression/termination/loops/sum01_false.c | 2 +-
regression/termination/loops/sum01_true.c | 2 +-
regression/termination/loops/sum03_false.c | 2 +-
regression/termination/loops/sum03_true.c | 2 +-
regression/termination/loops/sum04_false.c | 2 +-
regression/termination/loops/sum04_true.c | 2 +-
.../termination/loops/sum_array_false.c | 6 +-
regression/termination/loops/sum_array_true.c | 6 +-
.../termination/loops/terminator_01_false.c | 6 +-
.../termination/loops/terminator_02_false.c | 8 +-
.../termination/loops/terminator_02_true.c | 6 +-
.../termination/loops/terminator_03_false.c | 6 +-
.../termination/loops/terminator_03_true.c | 8 +-
regression/termination/loops/trex03_false.c | 2 +-
regression/termination/loops/trex03_true.c | 2 +-
regression/termination/loops/trex04_true.c | 2 +-
...c_OpenSER__cases1_stripFullBoth_arr_true.c | 6 +-
..._OpenSER__cases1_stripFullBoth_arr_false.c | 6 +-
regression/termination/loops/vogal_false.c | 14 +--
regression/termination/loops/vogal_true.c | 14 +--
.../loops/while_infinite_loop_1_true.c | 2 +-
.../loops/while_infinite_loop_2_true.c | 2 +-
.../loops/while_infinite_loop_3_true.c | 4 +-
.../loops/while_infinite_loop_4_false.c | 4 +-
regression/termination/phase1/main.c | 4 +-
regression/termination/phase2/main.c | 6 +-
regression/termination/phase3/main.c | 4 +-
regression/termination/phase4/main.c | 4 +-
regression/termination/phase5/main.c | 4 +-
regression/termination/phase6/main.c | 4 +-
regression/termination/phase7/debug.c | 4 +-
regression/termination/phase7/main.c | 4 +-
regression/termination/phase7/main_verify.c | 8 +-
regression/termination/phase8/debug.c | 4 +-
regression/termination/phase8/main.c | 6 +-
regression/termination/phase8/main_verify.c | 8 +-
regression/termination/phase9/main.c | 4 +-
regression/termination/pointer1/main.c | 4 +-
regression/termination/pointer2/main.c | 4 +-
regression/termination/precond_term4/main.c | 4 +-
regression/termination/refinement1/main.c | 4 +-
regression/termination/refinement2/main.c | 4 +-
regression/termination/refinement3/main.c | 4 +-
regression/termination/runall.sh | 4 +-
regression/termination/running1/main.c | 10 +-
regression/termination/running2/main.c | 12 +-
regression/termination/running3/main.c | 22 ++--
regression/termination/running4/main.c | 22 ++--
regression/termination/simple1/main.c | 10 +-
regression/termination/simple2/main.c | 4 +-
regression/termination/sum1/main.c | 54 ++++-----
251 files changed, 1203 insertions(+), 1216 deletions(-)
diff --git a/regression/graphml/Makefile b/regression/graphml/Makefile
index bfa217de8..7a53bfe32 100644
--- a/regression/graphml/Makefile
+++ b/regression/graphml/Makefile
@@ -1,6 +1,6 @@
#FLAGS = --k-induction --competition-mode --32
FLAGS = --unwind 11 --no-unwinding-assertions
-#2LS = ../../../src/summarizer/2ls
+#2LS = ../../../src/summarizer/2ls
2LS = $W/svncprover/branches/peter-incremental-unwinding/src/cbmc/cbmc
CPACHECKER = $W/svncpachecker
ULTIMATE = $W/UltimateAutomizer
diff --git a/regression/graphml/loop23/main.c b/regression/graphml/loop23/main.c
index ac7fc9378..5b2e53f86 100644
--- a/regression/graphml/loop23/main.c
+++ b/regression/graphml/loop23/main.c
@@ -6,10 +6,10 @@ int main()
int y;
if(x) { return x;}
- for(x=0;x<2;x++)
+ for(x=0;x<2;x++)
{
if(x==y) { return x;}
-
+
}
__VERIFIER_assert(0);
return 0;
diff --git a/regression/graphml/loop29/main.c b/regression/graphml/loop29/main.c
index ec555a910..da0ea8cbe 100644
--- a/regression/graphml/loop29/main.c
+++ b/regression/graphml/loop29/main.c
@@ -7,6 +7,6 @@ void main() {
int y;
if(-3>y || y>-1) return;
x += y;
- }
- __VERIFIER_assert(x==0 || x==-2);
-}
+ }
+ __VERIFIER_assert(x==0 || x==-2);
+}
diff --git a/regression/graphml/malloc1/main.c b/regression/graphml/malloc1/main.c
index 30f3fc751..36eda4d94 100644
--- a/regression/graphml/malloc1/main.c
+++ b/regression/graphml/malloc1/main.c
@@ -1029,7 +1029,7 @@ int ssl3_connect(SSL *s )
{
blastFlag = 0;
- s->state = 12292;
+ s->state = 12292;
while (1) {
if (s->state == 12292) {
goto switch_1_12292;
@@ -1047,15 +1047,15 @@ int ssl3_connect(SSL *s )
switch_1_4368: ;
if (blastFlag == 0) {
blastFlag = 1;
- }
+ }
s->state = 4384;
goto switch_1_break;
switch_1_4384: ;
if (blastFlag == 1) {
blastFlag = 2;
goto ERROR;
- }
-
+ }
+
goto end;
switch_1_default:
goto end;
diff --git a/regression/interprocedural/abort1/main.c b/regression/interprocedural/abort1/main.c
index 6d591ee39..84b6451b0 100644
--- a/regression/interprocedural/abort1/main.c
+++ b/regression/interprocedural/abort1/main.c
@@ -7,6 +7,6 @@ int foo(int x)
void main()
{
int x;
- x = foo(x);
+ x = foo(x);
assert(x<=0);
}
diff --git a/regression/interprocedural/contextsensitive1/main.c b/regression/interprocedural/contextsensitive1/main.c
index c1b928562..ecfa72170 100644
--- a/regression/interprocedural/contextsensitive1/main.c
+++ b/regression/interprocedural/contextsensitive1/main.c
@@ -1,17 +1,15 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-void main()
-{
- int x = 1;
- int y = sign(x);
- x = -x;
- int z = sign(x);
- assert(-1<=y && y<=1 && -1<=z && z<=1);
-}
-
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+void main()
+{
+ int x = 1;
+ int y = sign(x);
+ x = -x;
+ int z = sign(x);
+ assert(-1<=y && y<=1 && -1<=z && z<=1);
+}
diff --git a/regression/interprocedural/contextsensitive2/main.c b/regression/interprocedural/contextsensitive2/main.c
index b228a31b4..70fd27c8b 100644
--- a/regression/interprocedural/contextsensitive2/main.c
+++ b/regression/interprocedural/contextsensitive2/main.c
@@ -1,28 +1,26 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int x = 1;
- int y = do1(x);
- assert(y==1);
- x = -x;
- int z = do2(x);
- assert(-1<=z && z<=1);
-}
-
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int x = 1;
+ int y = do1(x);
+ assert(y==1);
+ x = -x;
+ int z = do2(x);
+ assert(-1<=z && z<=1);
+}
diff --git a/regression/interprocedural/contextsensitive3/main.c b/regression/interprocedural/contextsensitive3/main.c
index deab63659..b4cd07854 100644
--- a/regression/interprocedural/contextsensitive3/main.c
+++ b/regression/interprocedural/contextsensitive3/main.c
@@ -1,28 +1,26 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int x = 1;
- int y = do2(x);
- assert(y==1);
- x = -x;
- int z = do1(x);
- assert(-1<=z && z<=1);
-}
-
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int x = 1;
+ int y = do2(x);
+ assert(y==1);
+ x = -x;
+ int z = do1(x);
+ assert(-1<=z && z<=1);
+}
diff --git a/regression/interprocedural/contextsensitive4/main.c b/regression/interprocedural/contextsensitive4/main.c
index 9f1348396..05af1ee45 100644
--- a/regression/interprocedural/contextsensitive4/main.c
+++ b/regression/interprocedural/contextsensitive4/main.c
@@ -1,29 +1,27 @@
-
-int x = 1;
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int y = do1(x);
- assert(y==1);
- x = -x;
- int z = do2(x);
- assert(-1<=z && z<=1);
-}
-
+int x = 1;
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int y = do1(x);
+ assert(y==1);
+ x = -x;
+ int z = do2(x);
+ assert(-1<=z && z<=1);
+}
diff --git a/regression/interprocedural/contextsensitive5/main.c b/regression/interprocedural/contextsensitive5/main.c
index fb0251140..a23d53997 100644
--- a/regression/interprocedural/contextsensitive5/main.c
+++ b/regression/interprocedural/contextsensitive5/main.c
@@ -1,15 +1,14 @@
-#include
-
-void foo(int* x)
-{
- assert(x!=NULL);
- *x = 0;
-}
-
-void main()
-{
- int x;
- int *y = &x;
- foo(y);
-}
-
+#include
+
+void foo(int* x)
+{
+ assert(x!=NULL);
+ *x = 0;
+}
+
+void main()
+{
+ int x;
+ int *y = &x;
+ foo(y);
+}
diff --git a/regression/interprocedural/contextsensitive6/main.c b/regression/interprocedural/contextsensitive6/main.c
index be4631faa..b9267eb75 100644
--- a/regression/interprocedural/contextsensitive6/main.c
+++ b/regression/interprocedural/contextsensitive6/main.c
@@ -1,12 +1,10 @@
-
-void foo(int x)
-{
- assert(x!=0);
-}
-
-void main()
-{
- int x = 1;
- foo(x);
-}
-
+void foo(int x)
+{
+ assert(x!=0);
+}
+
+void main()
+{
+ int x = 1;
+ foo(x);
+}
diff --git a/regression/interprocedural/equal1/main.c b/regression/interprocedural/equal1/main.c
index e4434c38e..44bbd284d 100644
--- a/regression/interprocedural/equal1/main.c
+++ b/regression/interprocedural/equal1/main.c
@@ -1,5 +1,5 @@
-int foo(int x, int y)
-{
+int foo(int x, int y)
+{
return x;
}
diff --git a/regression/interprocedural/equal2/main.c b/regression/interprocedural/equal2/main.c
index 5dffe2105..5280ce06f 100644
--- a/regression/interprocedural/equal2/main.c
+++ b/regression/interprocedural/equal2/main.c
@@ -1,5 +1,5 @@
-unsigned foo(unsigned x, unsigned y)
-{
+unsigned foo(unsigned x, unsigned y)
+{
__CPROVER_assume(x<10*y && y>10);
return x/y;
}
diff --git a/regression/interprocedural/equal3/main.c b/regression/interprocedural/equal3/main.c
index 6e0366b24..64deebaa1 100644
--- a/regression/interprocedural/equal3/main.c
+++ b/regression/interprocedural/equal3/main.c
@@ -1,5 +1,5 @@
-unsigned foo(unsigned x, unsigned y)
-{
+unsigned foo(unsigned x, unsigned y)
+{
if(x) return y+1;
return y-1;
}
diff --git a/regression/interprocedural/equal4/main.c b/regression/interprocedural/equal4/main.c
index 876f00c5c..62fc9aadd 100644
--- a/regression/interprocedural/equal4/main.c
+++ b/regression/interprocedural/equal4/main.c
@@ -3,10 +3,10 @@ int foo(int x, int y)
while(x<10)
{
y++;
- x++;
+ x++;
y--;
}
-
+
return y;
}
diff --git a/regression/interprocedural/equal7/main.c b/regression/interprocedural/equal7/main.c
index e44115507..305bb780d 100644
--- a/regression/interprocedural/equal7/main.c
+++ b/regression/interprocedural/equal7/main.c
@@ -1,5 +1,5 @@
-int foo(int x)
-{
+int foo(int x)
+{
__CPROVER_assume(x==0);
return -x;
}
diff --git a/regression/interprocedural/equality_through_array7/main.c b/regression/interprocedural/equality_through_array7/main.c
index 2fc0c7e03..8432f2840 100644
--- a/regression/interprocedural/equality_through_array7/main.c
+++ b/regression/interprocedural/equality_through_array7/main.c
@@ -14,6 +14,6 @@ void main (void) {
a[1] = 0;
pass_through_array();
-
+
assert(a[0] == 0 && a[1] == 0);
}
diff --git a/regression/interprocedural/global1/main.c b/regression/interprocedural/global1/main.c
index ecb897b62..1436e7631 100644
--- a/regression/interprocedural/global1/main.c
+++ b/regression/interprocedural/global1/main.c
@@ -1,21 +1,20 @@
-#include
-
-int g;
-
-int foo(int y)
-{
- __CPROVER_assume(g=1);
- assert(z==0);
-}
-
+#include
+
+int g;
+
+int foo(int y)
+{
+ __CPROVER_assume(g=1);
+ assert(z==0);
+}
diff --git a/regression/interprocedural/global2/main.c b/regression/interprocedural/global2/main.c
index f653bce18..b41dd7bf4 100644
--- a/regression/interprocedural/global2/main.c
+++ b/regression/interprocedural/global2/main.c
@@ -1,22 +1,21 @@
-int g;
-
-void foo()
-{
- g=10;
-}
-
-int bar()
-{
- return 20;
-}
-
-void main()
-{
- g = 1;
- int x;
- foo();
- x = bar();
- assert(g==10);
- assert(x==20);
-}
-
+int g;
+
+void foo()
+{
+ g=10;
+}
+
+int bar()
+{
+ return 20;
+}
+
+void main()
+{
+ g = 1;
+ int x;
+ foo();
+ x = bar();
+ assert(g==10);
+ assert(x==20);
+}
diff --git a/regression/interprocedural/global3/main.c b/regression/interprocedural/global3/main.c
index 965a7f015..347464275 100644
--- a/regression/interprocedural/global3/main.c
+++ b/regression/interprocedural/global3/main.c
@@ -1,8 +1,8 @@
int x;
int z;
-void foo()
-{
+void foo()
+{
for(x=0;x<10;x++);
}
diff --git a/regression/interprocedural/global4/main.c b/regression/interprocedural/global4/main.c
index 80e8b6e50..646b6a47b 100644
--- a/regression/interprocedural/global4/main.c
+++ b/regression/interprocedural/global4/main.c
@@ -1,6 +1,6 @@
int g = 1;
-void modify_global()
+void modify_global()
{
g = g;
}
@@ -11,12 +11,12 @@ void main()
//g = g;
- if(x)
+ if(x)
{
- modify_global();
+ modify_global();
}
- modify_global();
+ modify_global();
assert(g==1);
}
diff --git a/regression/interprocedural/ite2/main.c b/regression/interprocedural/ite2/main.c
index e6b24818f..fbb4eddee 100644
--- a/regression/interprocedural/ite2/main.c
+++ b/regression/interprocedural/ite2/main.c
@@ -1,11 +1,11 @@
-int foo(int x, int y)
-{
+int foo(int x, int y)
+{
int res = y;
if(x) res = y+1;
return res;
}
-int bar(int x)
-{
+int bar(int x)
+{
if(x) return 1;
return 2;
}
@@ -13,7 +13,7 @@ int bar(int x)
void main()
{
int x;
- int y = 0;
+ int y = 0;
int z = bar(x);
int w = foo(z,y);
diff --git a/regression/interprocedural/ite3/main.c b/regression/interprocedural/ite3/main.c
index 0bd206af3..624104931 100644
--- a/regression/interprocedural/ite3/main.c
+++ b/regression/interprocedural/ite3/main.c
@@ -1,14 +1,14 @@
-int foo(int x)
-{
+int foo(int x)
+{
int res = 0;
if(x) res = 1;
return res;
}
-int bar(int x)
-{
+int bar(int x)
+{
int res = 2;
if(x) res = 1;
- return res;
+ return res;
}
void main()
diff --git a/regression/interprocedural/ite4/main.c b/regression/interprocedural/ite4/main.c
index fd030a9a5..cd12c0013 100644
--- a/regression/interprocedural/ite4/main.c
+++ b/regression/interprocedural/ite4/main.c
@@ -1,13 +1,13 @@
-int foo(int x)
-{
+int foo(int x)
+{
int res;
if(x) return 0;
else return 1;
}
-int bar(int x)
-{
+int bar(int x)
+{
int res;
if(x) res = 0;
else res = 1;
diff --git a/regression/interprocedural/pointer1/main.c b/regression/interprocedural/pointer1/main.c
index 34c87bb31..da5aa119a 100644
--- a/regression/interprocedural/pointer1/main.c
+++ b/regression/interprocedural/pointer1/main.c
@@ -1,5 +1,5 @@
-void foo(int *x)
-{
+void foo(int *x)
+{
*x = 10;
}
diff --git a/regression/interprocedural/pointer2/main.c b/regression/interprocedural/pointer2/main.c
index 02f54b869..318e03ee5 100644
--- a/regression/interprocedural/pointer2/main.c
+++ b/regression/interprocedural/pointer2/main.c
@@ -1,5 +1,5 @@
-void foo(int *x)
-{
+void foo(int *x)
+{
x++;
*x = 10;
}
diff --git a/regression/interprocedural/simple1/main.c b/regression/interprocedural/simple1/main.c
index 8a95214f7..0b9154bec 100644
--- a/regression/interprocedural/simple1/main.c
+++ b/regression/interprocedural/simple1/main.c
@@ -1,10 +1,10 @@
-int foo()
-{
+int foo()
+{
return 1;
}
-int bar()
-{
- return 2;
+int bar()
+{
+ return 2;
}
void main()
diff --git a/regression/interprocedural/simple2/main.c b/regression/interprocedural/simple2/main.c
index e1f62b82d..984b32921 100644
--- a/regression/interprocedural/simple2/main.c
+++ b/regression/interprocedural/simple2/main.c
@@ -1,5 +1,5 @@
-int foo(int x)
-{
+int foo(int x)
+{
if(x) return 9;
return 10;
}
diff --git a/regression/interprocedural/sum1/main.c b/regression/interprocedural/sum1/main.c
index df354feeb..c6f4ab383 100644
--- a/regression/interprocedural/sum1/main.c
+++ b/regression/interprocedural/sum1/main.c
@@ -1,27 +1,27 @@
-#include
-
-int max(int x, int y)
-{
- if(x>y) return x;
- return y;
-}
-
-int inv(int x)
-{
- __CPROVER_assume(x>INT_MIN); //would not be needed if we did not extend the bitvector sizes
- return -x;
-}
-
-void main()
-{
- int x;
- __CPROVER_assume(2<=x && x<=3);
-
- int y=inv(x);
- int z=max(y,0);
-
- assert(y<=-2);
- assert(y==-x);
- assert(z>=0);
- assert(z>=y);
-}
+#include
+
+int max(int x, int y)
+{
+ if(x>y) return x;
+ return y;
+}
+
+int inv(int x)
+{
+ __CPROVER_assume(x>INT_MIN); //would not be needed if we did not extend the bitvector sizes
+ return -x;
+}
+
+void main()
+{
+ int x;
+ __CPROVER_assume(2<=x && x<=3);
+
+ int y=inv(x);
+ int z=max(y,0);
+
+ assert(y<=-2);
+ assert(y==-x);
+ assert(z>=0);
+ assert(z>=y);
+}
diff --git a/regression/invariants/array_safe5/main.c b/regression/invariants/array_safe5/main.c
index 20cd3eb88..9e3671eb3 100644
--- a/regression/invariants/array_safe5/main.c
+++ b/regression/invariants/array_safe5/main.c
@@ -4,10 +4,10 @@ void main (void)
{
unsigned a[SIZE] = {0, }; //without initializtion a[i] for i>0 are not initialized in the 1st iteration, and hence we cannot do better than UINT_MAX for the upper bounds
- for(unsigned i=0; i0)
{
diff --git a/regression/invariants/float2/main.c b/regression/invariants/float2/main.c
index 235de6c53..a0c2c4a5d 100644
--- a/regression/invariants/float2/main.c
+++ b/regression/invariants/float2/main.c
@@ -1,6 +1,6 @@
void main()
{
- float x = 10.0;
+ float x = 10.0;
while(x>0)
{
diff --git a/regression/invariants/float3/main.c b/regression/invariants/float3/main.c
index 06b63a8f0..f1f7fdd07 100644
--- a/regression/invariants/float3/main.c
+++ b/regression/invariants/float3/main.c
@@ -1,6 +1,6 @@
void main()
{
- float x = 10.0;
+ float x = 10.0;
while(x>0) // does not terminate
{
diff --git a/regression/invariants/float4/main.c b/regression/invariants/float4/main.c
index a3edc4f6e..87b35329f 100644
--- a/regression/invariants/float4/main.c
+++ b/regression/invariants/float4/main.c
@@ -1,6 +1,6 @@
void main()
{
- float x = 10.0;
+ float x = 10.0;
while(x>0.0) // does not terminate
{
diff --git a/regression/invariants/gotoloop1/main.c b/regression/invariants/gotoloop1/main.c
index 57fde266c..06b649e04 100644
--- a/regression/invariants/gotoloop1/main.c
+++ b/regression/invariants/gotoloop1/main.c
@@ -2,7 +2,7 @@ void main()
{
int x,y;
if(x<-5) goto LOOP;
-
+
x = 0;
while(x<10)
{
diff --git a/regression/invariants/gotoloop2/main.c b/regression/invariants/gotoloop2/main.c
index 7f9c3ea57..8a457218e 100644
--- a/regression/invariants/gotoloop2/main.c
+++ b/regression/invariants/gotoloop2/main.c
@@ -2,7 +2,7 @@ void main()
{
int x,y;
if(x<-5) goto LOOP;
-
+
x = 0;
while(x<10)
{
diff --git a/regression/invariants/ite1/main.c b/regression/invariants/ite1/main.c
index d34a2cd40..f846c9438 100644
--- a/regression/invariants/ite1/main.c
+++ b/regression/invariants/ite1/main.c
@@ -1,13 +1,13 @@
-void main()
-{
- int x;
- int y = 0;
-
- while(y==0) //need to distinguish first iteration
- {
- if(x>=5) y=x;
- else y=5;
- }
-
- assert(y>=5);
-}
+void main()
+{
+ int x;
+ int y = 0;
+
+ while(y==0) //need to distinguish first iteration
+ {
+ if(x>=5) y=x;
+ else y=5;
+ }
+
+ assert(y>=5);
+}
diff --git a/regression/invariants/loop1/main.c b/regression/invariants/loop1/main.c
index f35f1c6ae..e67fdcb0f 100644
--- a/regression/invariants/loop1/main.c
+++ b/regression/invariants/loop1/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
while(x<10)
{
diff --git a/regression/invariants/loop10/main.c b/regression/invariants/loop10/main.c
index 72ee9fdf3..4c44c5306 100644
--- a/regression/invariants/loop10/main.c
+++ b/regression/invariants/loop10/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
int y;
while(y)
diff --git a/regression/invariants/loop11/main.c b/regression/invariants/loop11/main.c
index 47a26ae58..3a6b50399 100644
--- a/regression/invariants/loop11/main.c
+++ b/regression/invariants/loop11/main.c
@@ -2,7 +2,7 @@ void main()
{
int n;
__CPROVER_assume(n==0);
- int x = 0;
+ int x = 0;
while(x=0);
do
diff --git a/regression/invariants/loop14/main.c b/regression/invariants/loop14/main.c
index bb35394d4..be0199467 100644
--- a/regression/invariants/loop14/main.c
+++ b/regression/invariants/loop14/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x,y,z;
+ int x,y,z;
__CPROVER_assume(x>=0);
__CPROVER_assume(-20<=z && z<=-1);
diff --git a/regression/invariants/loop15/main.c b/regression/invariants/loop15/main.c
index 03b3a0c55..7e336dc14 100644
--- a/regression/invariants/loop15/main.c
+++ b/regression/invariants/loop15/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x,y,z;
+ int x,y,z;
__CPROVER_assume(x>=0);
__CPROVER_assume(x==y);
__CPROVER_assume(-1<=z && z<=-1);
diff --git a/regression/invariants/loop16/main.c b/regression/invariants/loop16/main.c
index 93a2dec12..771672940 100644
--- a/regression/invariants/loop16/main.c
+++ b/regression/invariants/loop16/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 0;
+ int x = 0;
int y = 0;
do
@@ -10,7 +10,7 @@ void main()
}
while(x<10);
- do
+ do
{
++y;
}
diff --git a/regression/invariants/loop17/main.c b/regression/invariants/loop17/main.c
index 71d68b591..db66138b0 100644
--- a/regression/invariants/loop17/main.c
+++ b/regression/invariants/loop17/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x;
+ int x;
__CPROVER_assume(x>=0);
do
diff --git a/regression/invariants/loop18/main.c b/regression/invariants/loop18/main.c
index c60b7b07d..22575a138 100644
--- a/regression/invariants/loop18/main.c
+++ b/regression/invariants/loop18/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x,y,z;
+ int x,y,z;
__CPROVER_assume(x>=0);
__CPROVER_assume(x==y);
__CPROVER_assume(-20<=z && z<=-1);
diff --git a/regression/invariants/loop2/main.c b/regression/invariants/loop2/main.c
index e67632a94..dd5d9c810 100644
--- a/regression/invariants/loop2/main.c
+++ b/regression/invariants/loop2/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 0;
+ int x = 0;
int y = 0;
while(x<10)
diff --git a/regression/invariants/loop21/main.c b/regression/invariants/loop21/main.c
index 1a80bc24f..85f265c5d 100644
--- a/regression/invariants/loop21/main.c
+++ b/regression/invariants/loop21/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0, y = 100;
+ int x = 0, y = 100;
while(x<100 && y>0)
{
diff --git a/regression/invariants/loop22/main.c b/regression/invariants/loop22/main.c
index 3346995c0..7a13c955d 100644
--- a/regression/invariants/loop22/main.c
+++ b/regression/invariants/loop22/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0, y = 100;
+ int x = 0, y = 100;
while(x<100 && y>0)
{
diff --git a/regression/invariants/loop3/main.c b/regression/invariants/loop3/main.c
index 21a30e139..6ddb8924c 100644
--- a/regression/invariants/loop3/main.c
+++ b/regression/invariants/loop3/main.c
@@ -4,13 +4,13 @@ void main()
int y;
x=0;
y=0;
-
+
while(x<10 && y<20)
{
++x;
++y;
}
-
+
int z=x+y;
assert(z>=0);
diff --git a/regression/invariants/loop5/main.c b/regression/invariants/loop5/main.c
index f301dde9d..2fd0a019f 100644
--- a/regression/invariants/loop5/main.c
+++ b/regression/invariants/loop5/main.c
@@ -1,6 +1,6 @@
void main()
{
- unsigned x = 0;
+ unsigned x = 0;
while(x<10)
++x;
diff --git a/regression/invariants/loop6/main.c b/regression/invariants/loop6/main.c
index 2c4213934..c7bd862fe 100644
--- a/regression/invariants/loop6/main.c
+++ b/regression/invariants/loop6/main.c
@@ -4,13 +4,13 @@ void main()
{
int x = 0;
unsigned y = 0;
-
+
while(x<10 && y<20)
{
++x;
++y;
}
-
+
int z=x+y;
assert(z<=20);
}
diff --git a/regression/invariants/loop7/main.c b/regression/invariants/loop7/main.c
index 3c7dea455..1707acb1d 100644
--- a/regression/invariants/loop7/main.c
+++ b/regression/invariants/loop7/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x;
+ int x;
unsigned y;
x = -10;
y = 10;
diff --git a/regression/invariants/nested4/main.c b/regression/invariants/nested4/main.c
index 35b9f5b5a..799dc282f 100644
--- a/regression/invariants/nested4/main.c
+++ b/regression/invariants/nested4/main.c
@@ -5,10 +5,10 @@ void main()
int n;
__CPROVER_assume(0<=n && n<=N);
int cost0 = 0;
-for(int i=0;i=0);
int y = 0;
do
- {
+ {
if(z) y = y + x;
else break;
x -= 3;
diff --git a/regression/invariants/unwind15/main.c b/regression/invariants/unwind15/main.c
index fb6137ec8..022ea24fa 100644
--- a/regression/invariants/unwind15/main.c
+++ b/regression/invariants/unwind15/main.c
@@ -2,7 +2,7 @@ extern int nondet();
void main()
{
- int x;
+ int x;
__CPROVER_assume(x>=0);
int y = 0;
diff --git a/regression/invariants/unwind16/main.c b/regression/invariants/unwind16/main.c
index 41f3f2dbf..5d6334051 100644
--- a/regression/invariants/unwind16/main.c
+++ b/regression/invariants/unwind16/main.c
@@ -1,11 +1,11 @@
void main()
{
- int x, z;
+ int x, z;
__CPROVER_assume(x>=0);
int y = 0;
while(x>0)
- {
+ {
if(z) y = y + x;
else break;
x -= 3;
diff --git a/regression/invariants/unwind17/main.c b/regression/invariants/unwind17/main.c
index fee7987dc..b2a0505e4 100644
--- a/regression/invariants/unwind17/main.c
+++ b/regression/invariants/unwind17/main.c
@@ -1,16 +1,16 @@
void main()
{
- int x, z, w;
+ int x, z, w;
__CPROVER_assume(x>=0);
int y = 0;
while(x>0)
- {
+ {
x = x;
if(z) y = y + x;
else break;
x--;
- if(w) break;
+ if(w) break;
else x++;
x -= 3;
}
diff --git a/regression/invariants/unwind18/main.c b/regression/invariants/unwind18/main.c
index b67d02ce0..44ff548cf 100644
--- a/regression/invariants/unwind18/main.c
+++ b/regression/invariants/unwind18/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
int y;
while(x<10)
diff --git a/regression/invariants/unwind19/main.c b/regression/invariants/unwind19/main.c
index 635faa760..8fa6b264b 100644
--- a/regression/invariants/unwind19/main.c
+++ b/regression/invariants/unwind19/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
int y;
do
diff --git a/regression/invariants/unwind2/main.c b/regression/invariants/unwind2/main.c
index f8b4ebbd8..703691405 100644
--- a/regression/invariants/unwind2/main.c
+++ b/regression/invariants/unwind2/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
if(x>=5)
{
diff --git a/regression/invariants/unwind3/main.c b/regression/invariants/unwind3/main.c
index 9eb900bc9..a13c56059 100644
--- a/regression/invariants/unwind3/main.c
+++ b/regression/invariants/unwind3/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x;
+ int x;
__CPROVER_assume(5<=x && x<=100);
for(int y=0;y<5;y++) x++;
diff --git a/regression/invariants/unwind4/main.c b/regression/invariants/unwind4/main.c
index 1e6dc4576..d395ee75e 100644
--- a/regression/invariants/unwind4/main.c
+++ b/regression/invariants/unwind4/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
while(x<10)
++x;
diff --git a/regression/invariants/unwind5/main.c b/regression/invariants/unwind5/main.c
index 6fdd141b1..5bcf04154 100644
--- a/regression/invariants/unwind5/main.c
+++ b/regression/invariants/unwind5/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 0;
- int y = 0;
+ int x = 0;
+ int y = 0;
while(x<10)
{
diff --git a/regression/invariants/unwind6/main.c b/regression/invariants/unwind6/main.c
index 5742ddea5..ea0047ea3 100644
--- a/regression/invariants/unwind6/main.c
+++ b/regression/invariants/unwind6/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
while(x<10)
{
diff --git a/regression/invariants/unwind9/main.c b/regression/invariants/unwind9/main.c
index b8a4fea79..6c9b96fa1 100644
--- a/regression/invariants/unwind9/main.c
+++ b/regression/invariants/unwind9/main.c
@@ -10,7 +10,7 @@ void main()
y++;
}
while(y=x);
+ assert(y>=x);
x++;
}
assert(x==10);
diff --git a/regression/kiki/array1/main.c b/regression/kiki/array1/main.c
index 056e454f9..76764b015 100644
--- a/regression/kiki/array1/main.c
+++ b/regression/kiki/array1/main.c
@@ -8,7 +8,7 @@ int main(int argc, char** argv)
{
int y = 2;
int x;
- if(1 == x)
+ if(1 == x)
s[i] = x;
else y = x;
}
diff --git a/regression/kiki/byte_add/main.c b/regression/kiki/byte_add/main.c
index b7010d14d..b4cd4b941 100644
--- a/regression/kiki/byte_add/main.c
+++ b/regression/kiki/byte_add/main.c
@@ -15,7 +15,7 @@ unsigned int mp_add(unsigned int a, unsigned int b)
i = i; r0 = r0; r1 = r1;
}
*/
-
+
while (i < (unsigned char)2) {
if (i == (unsigned char)0) { r0 = (unsigned char)0; }
if (i == (unsigned char)1) { r1 = (unsigned char)0; }
diff --git a/regression/kiki/elevator_13_21/main.c b/regression/kiki/elevator_13_21/main.c
index 48217ef19..7b50321f6 100644
--- a/regression/kiki/elevator_13_21/main.c
+++ b/regression/kiki/elevator_13_21/main.c
@@ -38,7 +38,7 @@ void main()
goto _L___6;
}
} else {
- _L___6:
+ _L___6:
if (i___0 == 1) {
if (floorButtons_1) {
retValue_acc = 1;
@@ -47,7 +47,7 @@ void main()
goto _L___5;
}
} else {
- _L___5:
+ _L___5:
if (i___0 == 2) {
if (floorButtons_2) {
retValue_acc = 1;
@@ -56,7 +56,7 @@ void main()
goto _L___4;
}
} else {
- _L___4:
+ _L___4:
if (i___0 == 3) {
if (floorButtons_3) {
retValue_acc = 1;
@@ -65,7 +65,7 @@ void main()
goto _L___3;
}
} else {
- _L___3:
+ _L___3:
if (i___0 == 4) {
if (floorButtons_4) {
retValue_acc = 1;
diff --git a/regression/kiki/encoder1/main.c b/regression/kiki/encoder1/main.c
index 4223e9cd8..e1695894e 100644
--- a/regression/kiki/encoder1/main.c
+++ b/regression/kiki/encoder1/main.c
@@ -8,33 +8,33 @@ int main () {
int outputBytes = 0;
int encodedBytes = 0;
- int last = EOF;
+ int last = EOF;
unsigned char count = 1;
int current;
- do
+ do
{
current = getchar();
inputBytes += (current == EOF) ? 0 : 1;
- if ((current == last) && (count < 5 /*UCHAR_MAX - 1*/))
+ if ((current == last) && (count < 5 /*UCHAR_MAX - 1*/))
{
++count;
- }
- else
+ }
+ else
{
- if (last != EOF)
+ if (last != EOF)
{
- if (count > 1)
+ if (count > 1)
{
putchar(UCHAR_MAX); ++outputBytes;
putchar(count); ++outputBytes;
}
- if (last == UCHAR_MAX)
+ if (last == UCHAR_MAX)
{
putchar(UCHAR_MAX); ++outputBytes;
}
- putchar(last);
+ putchar(last);
++outputBytes;
encodedBytes += count;
}
@@ -42,7 +42,7 @@ int main () {
last = current;
count = 1;
}
- }
+ }
while (last != EOF);
assert(inputBytes != encodedBytes); //should fail
diff --git a/regression/kiki/induction1/main.c b/regression/kiki/induction1/main.c
index 23a7e0054..0ecf6a0c3 100644
--- a/regression/kiki/induction1/main.c
+++ b/regression/kiki/induction1/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 1;
+ int x = 1;
while(1)
{
diff --git a/regression/kiki/induction2/main.c b/regression/kiki/induction2/main.c
index 76f88d6eb..5114dc168 100644
--- a/regression/kiki/induction2/main.c
+++ b/regression/kiki/induction2/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 1, y = -1, z = 1;
+ int x = 1, y = -1, z = 1;
while(1)
{
diff --git a/regression/kiki/induction3/main.c b/regression/kiki/induction3/main.c
index 38ef4b24f..aaa525389 100644
--- a/regression/kiki/induction3/main.c
+++ b/regression/kiki/induction3/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0, y = 0, z = 0;
+ int x = 0, y = 0, z = 0;
while(1)
{
diff --git a/regression/kiki/induction4/main.c b/regression/kiki/induction4/main.c
index c55adf781..7a7096e3c 100644
--- a/regression/kiki/induction4/main.c
+++ b/regression/kiki/induction4/main.c
@@ -1,16 +1,16 @@
-#define a 2
-
-extern int nondet_int();
-
-int main() {
- int i=0, n=3;
-
- int sn0 = nondet_int();
- int sn = sn0;
-
- while(i=10) {
- x = y = z = 0;
- }
-// if(x>z+2) break;
-// assert(x<=z+2);
- }
- assert(0); //this works with assertion hoisting
-}
+int main() {
+ int x,y,z;
+ __CPROVER_assume(x==y && y==z && -10<=x && x<0);
+
+// while(1)
+ while(x<=z+2)
+ {
+// __CPROVER_assume(x<=z+2);
+ z = -y;
+ y = -x;
+ if(nondet()) x = x+1;
+ if(x>=10) {
+ x = y = z = 0;
+ }
+// if(x>z+2) break;
+// assert(x<=z+2);
+ }
+ assert(0); //this works with assertion hoisting
+}
diff --git a/regression/kiki/loop12/main.c b/regression/kiki/loop12/main.c
index 171881bda..43464f4fb 100644
--- a/regression/kiki/loop12/main.c
+++ b/regression/kiki/loop12/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
int y;
while(y)
diff --git a/regression/kiki/loop23/main.c b/regression/kiki/loop23/main.c
index 274fe8975..944133675 100644
--- a/regression/kiki/loop23/main.c
+++ b/regression/kiki/loop23/main.c
@@ -5,10 +5,10 @@ int main()
int y;
if(x) { return x;}
- for(x=0;x<2;x++)
+ for(x=0;x<2;x++)
{
if(x==y) { return x;}
-
+
}
assert(0);
return 0;
diff --git a/regression/kiki/loop24/main.c b/regression/kiki/loop24/main.c
index 8833d199d..9266d50b7 100644
--- a/regression/kiki/loop24/main.c
+++ b/regression/kiki/loop24/main.c
@@ -1,13 +1,13 @@
-void main()
-{
- int x = 1, y = -1, z = 1;
-
- while(1)
- {
- if(x!=z) break;
- z = y;
- y = x;
- x = -x;
- }
- assert(0);
-}
+void main()
+{
+ int x = 1, y = -1, z = 1;
+
+ while(1)
+ {
+ if(x!=z) break;
+ z = y;
+ y = x;
+ x = -x;
+ }
+ assert(0);
+}
diff --git a/regression/kiki/loop25/main.c b/regression/kiki/loop25/main.c
index 8febd85d7..e05732e45 100644
--- a/regression/kiki/loop25/main.c
+++ b/regression/kiki/loop25/main.c
@@ -1,12 +1,12 @@
-void main()
-{
- int x = 1, y = -1, z = 1;
-
- while(x==z)
- {
- z = y;
- y = x;
- x = -x;
- }
- assert(0);
-}
+void main()
+{
+ int x = 1, y = -1, z = 1;
+
+ while(x==z)
+ {
+ z = y;
+ y = x;
+ x = -x;
+ }
+ assert(0);
+}
diff --git a/regression/kiki/loop25/test.desc b/regression/kiki/loop25/test.desc
index 6755e58a3..34e465e33 100644
--- a/regression/kiki/loop25/test.desc
+++ b/regression/kiki/loop25/test.desc
@@ -1,6 +1,6 @@
CORE
main.c
---k-induction
+--k-induction
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
diff --git a/regression/kiki/loop26/main.c b/regression/kiki/loop26/main.c
index ae5c34f7d..f9f6ed3fd 100644
--- a/regression/kiki/loop26/main.c
+++ b/regression/kiki/loop26/main.c
@@ -1,15 +1,15 @@
-void main()
-{
- int x = 1, y = -1, z = 1;
-
- while(1)
- {
- z = y;
- y = x;
- x = -x;
- if(x!=z) break;
- }
- assert(0);
-}
+void main()
+{
+ int x = 1, y = -1, z = 1;
+
+ while(1)
+ {
+ z = y;
+ y = x;
+ x = -x;
+ if(x!=z) break;
+ }
+ assert(0);
+}
diff --git a/regression/kiki/loop27/main.c b/regression/kiki/loop27/main.c
index ca9acda4c..3c5aa9703 100644
--- a/regression/kiki/loop27/main.c
+++ b/regression/kiki/loop27/main.c
@@ -1,13 +1,13 @@
-void main()
-{
- int x = 1, y = -1, z = 1;
-
- do
- {
- z = y;
- y = x;
- x = -x;
- }
- while(x==z);
- assert(0);
-}
+void main()
+{
+ int x = 1, y = -1, z = 1;
+
+ do
+ {
+ z = y;
+ y = x;
+ x = -x;
+ }
+ while(x==z);
+ assert(0);
+}
diff --git a/regression/kiki/loop28/main.c b/regression/kiki/loop28/main.c
index 7ae8d5301..bd0509336 100644
--- a/regression/kiki/loop28/main.c
+++ b/regression/kiki/loop28/main.c
@@ -1,8 +1,8 @@
-void main() {
- int b = 3;
- unsigned int j=0;
- while (j<1 && b!=3) {
- j++;
- }
- assert(j<1);
-}
+void main() {
+ int b = 3;
+ unsigned int j=0;
+ while (j<1 && b!=3) {
+ j++;
+ }
+ assert(j<1);
+}
diff --git a/regression/kiki/loop29/main.c b/regression/kiki/loop29/main.c
index 0135d5b6d..bbde2d56a 100644
--- a/regression/kiki/loop29/main.c
+++ b/regression/kiki/loop29/main.c
@@ -5,6 +5,6 @@ void main() {
int y;
__CPROVER_assume(-3<=y && y<=-1);
x += y;
- }
- assert(x==0 || x==-2);
-}
+ }
+ assert(x==0 || x==-2);
+}
diff --git a/regression/kiki/loop30/main.c b/regression/kiki/loop30/main.c
index c0ae436c1..e77a78ef8 100644
--- a/regression/kiki/loop30/main.c
+++ b/regression/kiki/loop30/main.c
@@ -4,6 +4,6 @@ void main() {
{
x += 1;
assert(x<5);
- }
- while(x<10);
-}
+ }
+ while(x<10);
+}
diff --git a/regression/kiki/loop9/main.c b/regression/kiki/loop9/main.c
index 13cf22ccd..763566845 100644
--- a/regression/kiki/loop9/main.c
+++ b/regression/kiki/loop9/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
int y;
while(y)
diff --git a/regression/kiki/malloc1/main.c b/regression/kiki/malloc1/main.c
index 4f3bca21f..2b5cb01c3 100644
--- a/regression/kiki/malloc1/main.c
+++ b/regression/kiki/malloc1/main.c
@@ -1035,7 +1035,7 @@ int ssl3_connect(SSL *s )
{
blastFlag = 0;
- s->state = 12292;
+ s->state = 12292;
while (1) {
if (s->state == 12292) {
goto switch_1_12292;
@@ -1053,15 +1053,15 @@ int ssl3_connect(SSL *s )
switch_1_4368: ;
if (blastFlag == 0) {
blastFlag = 1;
- }
+ }
s->state = 4384;
goto switch_1_break;
switch_1_4384: ;
if (blastFlag == 1) {
blastFlag = 2;
goto ERROR;
- }
-
+ }
+
goto end;
switch_1_default:
goto end;
diff --git a/regression/kiki/malloc3/main.c b/regression/kiki/malloc3/main.c
index 2c823a1ec..33bc7c05d 100644
--- a/regression/kiki/malloc3/main.c
+++ b/regression/kiki/malloc3/main.c
@@ -13,7 +13,7 @@ void main()
w = x;
}*/
float *f;
-
+
for(int z=0;z<1;z++)
{
//assert(w==5);
diff --git a/regression/kiki/nested11/main.c b/regression/kiki/nested11/main.c
index 790b6c4b3..d6f5d20a3 100644
--- a/regression/kiki/nested11/main.c
+++ b/regression/kiki/nested11/main.c
@@ -3,7 +3,7 @@ void main()
int x,y;
for(x=0;x<10;)
{
- for(y=0;y=0);
}
diff --git a/regression/preconditions/precond2/main.c b/regression/preconditions/precond2/main.c
index b67310cdc..5b50bb943 100644
--- a/regression/preconditions/precond2/main.c
+++ b/regression/preconditions/precond2/main.c
@@ -1,5 +1,5 @@
-void foo(int x)
-{
+void foo(int x)
+{
int y = x;
assert(y>=0);
}
diff --git a/regression/preconditions/precond3/main.c b/regression/preconditions/precond3/main.c
index 0045d70a5..7a25fd03b 100644
--- a/regression/preconditions/precond3/main.c
+++ b/regression/preconditions/precond3/main.c
@@ -1,5 +1,5 @@
-void foo(char* x)
-{
+void foo(char* x)
+{
assert(x!=0);
*x = 0;
}
diff --git a/regression/preconditions/precond4/main.c b/regression/preconditions/precond4/main.c
index e612011ba..f458914de 100644
--- a/regression/preconditions/precond4/main.c
+++ b/regression/preconditions/precond4/main.c
@@ -1,9 +1,9 @@
-int FirstOccurrence(int len, int a[])
-{
+int FirstOccurrence(int len, int a[])
+{
if(len<=0) return -1;
int i = 0;
assert(i=0)
{
assert(len>=3);
diff --git a/regression/preconditions/precond6/main.c b/regression/preconditions/precond6/main.c
index b67310cdc..5b50bb943 100644
--- a/regression/preconditions/precond6/main.c
+++ b/regression/preconditions/precond6/main.c
@@ -1,5 +1,5 @@
-void foo(int x)
-{
+void foo(int x)
+{
int y = x;
assert(y>=0);
}
diff --git a/regression/preconditions/precond_contextsensitive1/main.c b/regression/preconditions/precond_contextsensitive1/main.c
index ccf80ffd1..39cc080fa 100644
--- a/regression/preconditions/precond_contextsensitive1/main.c
+++ b/regression/preconditions/precond_contextsensitive1/main.c
@@ -1,15 +1,15 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-void main()
-{
- int x;
- int y = sign(x);
- assert(y==0);
-}
-
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+void main()
+{
+ int x;
+ int y = sign(x);
+ assert(y==0);
+}
+
diff --git a/regression/preconditions/precond_contextsensitive2/main.c b/regression/preconditions/precond_contextsensitive2/main.c
index d1713f3e3..72b6f0cf7 100644
--- a/regression/preconditions/precond_contextsensitive2/main.c
+++ b/regression/preconditions/precond_contextsensitive2/main.c
@@ -1,11 +1,11 @@
-
-void foo(int x)
-{
- assert(x!=1);
-}
-
-int main(int argc, char** argv)
-{
- foo(argc);
-}
-
+
+void foo(int x)
+{
+ assert(x!=1);
+}
+
+int main(int argc, char** argv)
+{
+ foo(argc);
+}
+
diff --git a/regression/termination/abe_createBack1/main.c b/regression/termination/abe_createBack1/main.c
index 8bfbfb993..5397ab702 100644
--- a/regression/termination/abe_createBack1/main.c
+++ b/regression/termination/abe_createBack1/main.c
@@ -59,7 +59,7 @@ void createBack(struct SDL_Surface back_surface)
// SDL_UpperBlit(img, (struct SDL_Rect *)NULL, *back_surface, &pos);
}
//assert(-y>-(y+img.h));
- // assert(-y+(y+img.h)>0);
+ // assert(-y+(y+img.h)>0);
assert(img.h!=0);
}
}
diff --git a/regression/termination/abort1/main.c b/regression/termination/abort1/main.c
index ab6bd07ef..3e8ad47a7 100644
--- a/regression/termination/abort1/main.c
+++ b/regression/termination/abort1/main.c
@@ -8,7 +8,7 @@ int foo(int x)
int main(int argc, char** argv)
{
int x = argc;
- x = foo(x);
+ x = foo(x);
assert(x>=1);
return x;
}
diff --git a/regression/termination/abort3/main.c b/regression/termination/abort3/main.c
index ecc2f25b9..84dc211a7 100644
--- a/regression/termination/abort3/main.c
+++ b/regression/termination/abort3/main.c
@@ -7,7 +7,7 @@ int foo(int x)
int main(int argc, char** argv)
{
int x = argc;
- x = foo(x);
+ x = foo(x);
assert(x>=1);
return x;
}
diff --git a/regression/termination/array_safe5/main.c b/regression/termination/array_safe5/main.c
index 20cd3eb88..9e3671eb3 100644
--- a/regression/termination/array_safe5/main.c
+++ b/regression/termination/array_safe5/main.c
@@ -4,10 +4,10 @@ void main (void)
{
unsigned a[SIZE] = {0, }; //without initializtion a[i] for i>0 are not initialized in the 1st iteration, and hence we cannot do better than UINT_MAX for the upper bounds
- for(unsigned i=0; i 0 || l_var<0 || l_var>=1073741824); // precondition for termination
int i=0;
- if (l_var >= 0)
+ if (l_var >= 0)
{
- while (l_var < 1073741824)
+ while (l_var < 1073741824)
{
i++;
l_var = l_var << 1;
@@ -21,7 +21,7 @@ void f(int l_var)
int main()
{
int l_var = nondet_int();
-
+
f(l_var);
return 0;
diff --git a/regression/termination/cav08_1p/main.c b/regression/termination/cav08_1p/main.c
index e30cb8c9d..9f0ebeb54 100644
--- a/regression/termination/cav08_1p/main.c
+++ b/regression/termination/cav08_1p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -8,9 +8,9 @@ void f(int l_var)
{
// __CPROVER_assume(l_var> 0 || l_var<0 || l_var>=1073741824); // precondition for termination
int i=0;
- if (l_var >= 0)
+ if (l_var >= 0)
{
- while (l_var < 1073741824)
+ while (l_var < 1073741824)
{
i++;
l_var = l_var << 1;
@@ -21,7 +21,7 @@ void f(int l_var)
int main()
{
int l_var = nondet_int();
-
+
f(l_var);
return 0;
diff --git a/regression/termination/cav08_2/main.c b/regression/termination/cav08_2/main.c
index 67b296232..3c0991765 100644
--- a/regression/termination/cav08_2/main.c
+++ b/regression/termination/cav08_2/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -15,7 +15,7 @@ void f(int cbSrcLength, int cbHeader, int nBlockAlignment, DWORD *pbSrc, DWORD *
{
__CPROVER_assume(cbSrcLength < cbHeader || nBlockAlignment > 0 && cbHeader > 0); // precondition for termination
- while (cbSrcLength >= cbHeader)
+ while (cbSrcLength >= cbHeader)
{
DWORD dwHeader;
UINT cbBlockLength;
@@ -28,7 +28,7 @@ void f(int cbSrcLength, int cbHeader, int nBlockAlignment, DWORD *pbSrc, DWORD *
int nStepIndex = (int)(BYTE)HIWORD(dwHeader);
if( !imaadpcmValidStepIndex(nStepIndex) ) return 0;
*pbDst++ = (BYTE)((nPredSample >> 8) + 128); */
- while (cbBlockLength--)
+ while (cbBlockLength--)
{
/* DWORD bSample = *pbSrc++;
DWORD nEncSample = (bSample & (BYTE)0x0F);
@@ -56,7 +56,7 @@ int main()
int nBlockAlignment = nondet_int();
DWORD *pbSrc, *pbDst;
int *step;
-
+
f(cbSrcLength, cbHeader, nBlockAlignment, pbSrc, pbSrc, step);
return 0;
diff --git a/regression/termination/cav08_2p/main.c b/regression/termination/cav08_2p/main.c
index ab173d9ae..72a0c3c9d 100644
--- a/regression/termination/cav08_2p/main.c
+++ b/regression/termination/cav08_2p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -15,7 +15,7 @@ void f(int cbSrcLength, int cbHeader, int nBlockAlignment, DWORD *pbSrc, DWORD *
{
// __CPROVER_assume(cbSrcLength < cbHeader || nBlockAlignment > 0 && cbHeader > 0); // precondition for termination
- while (cbSrcLength >= cbHeader)
+ while (cbSrcLength >= cbHeader)
{
DWORD dwHeader;
UINT cbBlockLength;
@@ -28,7 +28,7 @@ void f(int cbSrcLength, int cbHeader, int nBlockAlignment, DWORD *pbSrc, DWORD *
int nStepIndex = (int)(BYTE)HIWORD(dwHeader);
if( !imaadpcmValidStepIndex(nStepIndex) ) return 0;
*pbDst++ = (BYTE)((nPredSample >> 8) + 128); */
- while (cbBlockLength--)
+ while (cbBlockLength--)
{
/* DWORD bSample = *pbSrc++;
DWORD nEncSample = (bSample & (BYTE)0x0F);
@@ -56,7 +56,7 @@ int main()
int nBlockAlignment = nondet_int();
DWORD *pbSrc, *pbDst;
int *step;
-
+
f(cbSrcLength, cbHeader, nBlockAlignment, pbSrc, pbSrc, step);
return 0;
diff --git a/regression/termination/cav08_3/main.c b/regression/termination/cav08_3/main.c
index fff20a220..efc7bce87 100644
--- a/regression/termination/cav08_3/main.c
+++ b/regression/termination/cav08_3/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -8,7 +8,7 @@ void f(int x, int y, int z)
{
__CPROVER_assume(x<=0 || x+y<=0 || x+2*y+z<=0 || x+3*y+3*z<=0 || z<0 || z<=0 && y<=0); // precondition for termination
- while (x>0)
+ while (x>0)
{
x = x + y;
y = y + z;
@@ -20,7 +20,7 @@ int main()
int x = nondet_int();
int y = nondet_int();
int z = nondet_int();
-
+
f(x,y,z);
return 0;
diff --git a/regression/termination/cav08_3p/main.c b/regression/termination/cav08_3p/main.c
index 3d56eff51..7a6fa2b39 100644
--- a/regression/termination/cav08_3p/main.c
+++ b/regression/termination/cav08_3p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -8,7 +8,7 @@ void f(int x, int y, int z)
{
// __CPROVER_assume(x<=0 || x+y<=0 || x+2*y+z<=0 || x+3*y+3*z<=0 || z<0 || z<=0 && y<=0); // precondition for termination
- while (x>0)
+ while (x>0)
{
x = x + y;
y = y + z;
@@ -20,7 +20,7 @@ int main()
int x = nondet_int();
int y = nondet_int();
int z = nondet_int();
-
+
f(x,y,z);
return 0;
diff --git a/regression/termination/cav08_4/main.c b/regression/termination/cav08_4/main.c
index 61fb56ac3..4e6b8ca57 100644
--- a/regression/termination/cav08_4/main.c
+++ b/regression/termination/cav08_4/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -7,11 +7,11 @@ unsigned nondet_int();
void f(int x, int y, int N)
{
__CPROVER_assume(x>N || x+y>=0); // precondition for termination
-
- while (x<=N)
+
+ while (x<=N)
{
int c;
- if(c)
+ if(c)
{
x = 2*x + y;
y = y + 1;
@@ -28,7 +28,7 @@ int main()
int x = nondet_int();
int y = nondet_int();
int N = nondet_int();
-
+
f(x,y,N);
return 0;
diff --git a/regression/termination/cav08_4p/main.c b/regression/termination/cav08_4p/main.c
index 6016788b8..f87616cd0 100644
--- a/regression/termination/cav08_4p/main.c
+++ b/regression/termination/cav08_4p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -7,11 +7,11 @@ unsigned nondet_int();
void f(int x, int y, int N)
{
// __CPROVER_assume(x>N || x+y>=0); // precondition for termination
-
- while (x<=N)
+
+ while (x<=N)
{
int c;
- if(c)
+ if(c)
{
x = 2*x + y;
y = y + 1;
@@ -28,7 +28,7 @@ int main()
int x = nondet_int();
int y = nondet_int();
int N = nondet_int();
-
+
f(x,y,N);
return 0;
diff --git a/regression/termination/cav08_5/main.c b/regression/termination/cav08_5/main.c
index e101bf65a..8c01cbd34 100644
--- a/regression/termination/cav08_5/main.c
+++ b/regression/termination/cav08_5/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -7,8 +7,8 @@ unsigned nondet_int();
void f(int x)
{
__CPROVER_assume(x>5 || x<0);
-
- while (x>=0)
+
+ while (x>=0)
{
x = -2*x + 10;
}
@@ -17,7 +17,7 @@ void f(int x)
int main()
{
int x = nondet_int();
-
+
f(x);
return 0;
diff --git a/regression/termination/cav08_5p/main.c b/regression/termination/cav08_5p/main.c
index 991ef5997..f96dd606d 100644
--- a/regression/termination/cav08_5p/main.c
+++ b/regression/termination/cav08_5p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -7,8 +7,8 @@ unsigned nondet_int();
void f(int x)
{
// __CPROVER_assume(x>5 || x<0);
-
- while (x>=0)
+
+ while (x>=0)
{
x = -2*x + 10;
}
@@ -17,7 +17,7 @@ void f(int x)
int main()
{
int x = nondet_int();
-
+
f(x);
return 0;
diff --git a/regression/termination/cav08_6/main.c b/regression/termination/cav08_6/main.c
index 75719e100..21436c6be 100644
--- a/regression/termination/cav08_6/main.c
+++ b/regression/termination/cav08_6/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -9,10 +9,10 @@ void f(int y, int n)
__CPROVER_assume(n>200 && y<9); //additional assumption given
__CPROVER_assume(y>0); // precondition for termination
int x = 0;
- while (1)
+ while (1)
{
- if (x= 200) break;
}
@@ -23,7 +23,7 @@ int main()
{
int y = nondet_int();
int n = nondet_int();
-
+
f(y,n);
return 0;
diff --git a/regression/termination/cav08_6p/main.c b/regression/termination/cav08_6p/main.c
index 9194b0fdb..54a1d9499 100644
--- a/regression/termination/cav08_6p/main.c
+++ b/regression/termination/cav08_6p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -9,10 +9,10 @@ void f(int y, int n)
__CPROVER_assume(n>200 && y<9); //additional assumption given
// __CPROVER_assume(y>0); // precondition for termination
int x = 0;
- while (1)
+ while (1)
{
- if (x= 200) break;
}
@@ -23,7 +23,7 @@ int main()
{
int y = nondet_int();
int n = nondet_int();
-
+
f(y,n);
return 0;
diff --git a/regression/termination/cav08_7/main.c b/regression/termination/cav08_7/main.c
index 337ee200b..eb88a2ae8 100644
--- a/regression/termination/cav08_7/main.c
+++ b/regression/termination/cav08_7/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -8,12 +8,12 @@ void f(int x, int y)
{
__CPROVER_assume(x==y || x>0 && y>0); // precondition for termination
- while (x!=y)
- {
- if (x>y)
+ while (x!=y)
+ {
+ if (x>y)
{
x=x-y;
- }
+ }
else
{
y=y-x;
@@ -25,7 +25,7 @@ int main()
{
int x = nondet_int();
int y = nondet_int();
-
+
f(x,y);
return 0;
diff --git a/regression/termination/cav08_7p/main.c b/regression/termination/cav08_7p/main.c
index 7de383b19..3579f823a 100644
--- a/regression/termination/cav08_7p/main.c
+++ b/regression/termination/cav08_7p/main.c
@@ -1,4 +1,4 @@
-/*
+/*
Example from Cook et al, CAV 2008
*/
@@ -8,12 +8,12 @@ void f(int x, int y)
{
// __CPROVER_assume(x==y || x>0 && y>0); // precondition for termination
- while (x!=y)
- {
- if (x>y)
+ while (x!=y)
+ {
+ if (x>y)
{
x=x-y;
- }
+ }
else
{
y=y-x;
@@ -25,7 +25,7 @@ int main()
{
int x = nondet_int();
int y = nondet_int();
-
+
f(x,y);
return 0;
diff --git a/regression/termination/contextsensitive1/main.c b/regression/termination/contextsensitive1/main.c
index c1b928562..80cbc563c 100644
--- a/regression/termination/contextsensitive1/main.c
+++ b/regression/termination/contextsensitive1/main.c
@@ -1,17 +1,17 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-void main()
-{
- int x = 1;
- int y = sign(x);
- x = -x;
- int z = sign(x);
- assert(-1<=y && y<=1 && -1<=z && z<=1);
-}
-
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+void main()
+{
+ int x = 1;
+ int y = sign(x);
+ x = -x;
+ int z = sign(x);
+ assert(-1<=y && y<=1 && -1<=z && z<=1);
+}
+
diff --git a/regression/termination/contextsensitive2/main.c b/regression/termination/contextsensitive2/main.c
index b228a31b4..bcd5eb7ed 100644
--- a/regression/termination/contextsensitive2/main.c
+++ b/regression/termination/contextsensitive2/main.c
@@ -1,28 +1,28 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int x = 1;
- int y = do1(x);
- assert(y==1);
- x = -x;
- int z = do2(x);
- assert(-1<=z && z<=1);
-}
-
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int x = 1;
+ int y = do1(x);
+ assert(y==1);
+ x = -x;
+ int z = do2(x);
+ assert(-1<=z && z<=1);
+}
+
diff --git a/regression/termination/contextsensitive3/main.c b/regression/termination/contextsensitive3/main.c
index deab63659..a67b572d0 100644
--- a/regression/termination/contextsensitive3/main.c
+++ b/regression/termination/contextsensitive3/main.c
@@ -1,28 +1,28 @@
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int x = 1;
- int y = do2(x);
- assert(y==1);
- x = -x;
- int z = do1(x);
- assert(-1<=z && z<=1);
-}
-
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int x = 1;
+ int y = do2(x);
+ assert(y==1);
+ x = -x;
+ int z = do1(x);
+ assert(-1<=z && z<=1);
+}
+
diff --git a/regression/termination/contextsensitive4/main.c b/regression/termination/contextsensitive4/main.c
index 9f1348396..f90baaa2d 100644
--- a/regression/termination/contextsensitive4/main.c
+++ b/regression/termination/contextsensitive4/main.c
@@ -1,29 +1,29 @@
-
-int x = 1;
-
-int sign(int x)
-{
- if(x>0) return 1;
- else if (x==0) return 0;
- return -1;
-}
-
-int do1(int x)
-{
- return sign(x);
-}
-
-int do2(int x)
-{
- return sign(x);
-}
-
-void main()
-{
- int y = do1(x);
- assert(y==1);
- x = -x;
- int z = do2(x);
- assert(-1<=z && z<=1);
-}
-
+
+int x = 1;
+
+int sign(int x)
+{
+ if(x>0) return 1;
+ else if (x==0) return 0;
+ return -1;
+}
+
+int do1(int x)
+{
+ return sign(x);
+}
+
+int do2(int x)
+{
+ return sign(x);
+}
+
+void main()
+{
+ int y = do1(x);
+ assert(y==1);
+ x = -x;
+ int z = do2(x);
+ assert(-1<=z && z<=1);
+}
+
diff --git a/regression/termination/contextsensitive5/main.c b/regression/termination/contextsensitive5/main.c
index fb0251140..81be7a8ed 100644
--- a/regression/termination/contextsensitive5/main.c
+++ b/regression/termination/contextsensitive5/main.c
@@ -1,15 +1,15 @@
-#include
-
-void foo(int* x)
-{
- assert(x!=NULL);
- *x = 0;
-}
-
-void main()
-{
- int x;
- int *y = &x;
- foo(y);
-}
-
+#include
+
+void foo(int* x)
+{
+ assert(x!=NULL);
+ *x = 0;
+}
+
+void main()
+{
+ int x;
+ int *y = &x;
+ foo(y);
+}
+
diff --git a/regression/termination/contextsensitive6/main.c b/regression/termination/contextsensitive6/main.c
index be4631faa..ed39a132c 100644
--- a/regression/termination/contextsensitive6/main.c
+++ b/regression/termination/contextsensitive6/main.c
@@ -1,12 +1,12 @@
-
-void foo(int x)
-{
- assert(x!=0);
-}
-
-void main()
-{
- int x = 1;
- foo(x);
-}
-
+
+void foo(int x)
+{
+ assert(x!=0);
+}
+
+void main()
+{
+ int x = 1;
+ foo(x);
+}
+
diff --git a/regression/termination/equal1/main.c b/regression/termination/equal1/main.c
index e4434c38e..44bbd284d 100644
--- a/regression/termination/equal1/main.c
+++ b/regression/termination/equal1/main.c
@@ -1,5 +1,5 @@
-int foo(int x, int y)
-{
+int foo(int x, int y)
+{
return x;
}
diff --git a/regression/termination/equal2/main.c b/regression/termination/equal2/main.c
index 5dffe2105..5280ce06f 100644
--- a/regression/termination/equal2/main.c
+++ b/regression/termination/equal2/main.c
@@ -1,5 +1,5 @@
-unsigned foo(unsigned x, unsigned y)
-{
+unsigned foo(unsigned x, unsigned y)
+{
__CPROVER_assume(x<10*y && y>10);
return x/y;
}
diff --git a/regression/termination/equal3/main.c b/regression/termination/equal3/main.c
index 6e0366b24..64deebaa1 100644
--- a/regression/termination/equal3/main.c
+++ b/regression/termination/equal3/main.c
@@ -1,5 +1,5 @@
-unsigned foo(unsigned x, unsigned y)
-{
+unsigned foo(unsigned x, unsigned y)
+{
if(x) return y+1;
return y-1;
}
diff --git a/regression/termination/equal4/main.c b/regression/termination/equal4/main.c
index 876f00c5c..62fc9aadd 100644
--- a/regression/termination/equal4/main.c
+++ b/regression/termination/equal4/main.c
@@ -3,10 +3,10 @@ int foo(int x, int y)
while(x<10)
{
y++;
- x++;
+ x++;
y--;
}
-
+
return y;
}
diff --git a/regression/termination/equal6/main.c b/regression/termination/equal6/main.c
index e439e7892..22e381c9d 100644
--- a/regression/termination/equal6/main.c
+++ b/regression/termination/equal6/main.c
@@ -4,7 +4,7 @@ void main()
while(x<10)
{
- x++;
+ x++;
while(y0)
{
diff --git a/regression/termination/float2/main.c b/regression/termination/float2/main.c
index 9a5d17658..46d257f96 100644
--- a/regression/termination/float2/main.c
+++ b/regression/termination/float2/main.c
@@ -2,7 +2,7 @@
int main(int argc, char** argv)
{
- float x = 10.0;
+ float x = 10.0;
while(x>0)
{
diff --git a/regression/termination/float3/main.c b/regression/termination/float3/main.c
index ba27d41b6..9915bcd95 100644
--- a/regression/termination/float3/main.c
+++ b/regression/termination/float3/main.c
@@ -1,6 +1,6 @@
void main()
{
- float x = 10.0;
+ float x = 10.0;
while(x>0) // does not terminate
{
diff --git a/regression/termination/float4/main.c b/regression/termination/float4/main.c
index 98c97c5d9..e52a531f4 100644
--- a/regression/termination/float4/main.c
+++ b/regression/termination/float4/main.c
@@ -1,6 +1,6 @@
void main()
{
- float x = 10.0;
+ float x = 10.0;
while(x>0.0) // does not terminate
{
diff --git a/regression/termination/float5/main.c b/regression/termination/float5/main.c
index 411a1d54e..3b93d22ed 100644
--- a/regression/termination/float5/main.c
+++ b/regression/termination/float5/main.c
@@ -2,7 +2,7 @@
int main(int argc, char** argv)
{
float x;
- __CPROVER_assume(-FLT_MAX<=x && x<=FLT_MAX);
+ __CPROVER_assume(-FLT_MAX<=x && x<=FLT_MAX);
while(x>0.0f)
{
x *= 0.1f; //terminates
diff --git a/regression/termination/float6/main.c b/regression/termination/float6/main.c
index 2625189cd..2db9b4007 100644
--- a/regression/termination/float6/main.c
+++ b/regression/termination/float6/main.c
@@ -5,7 +5,7 @@ int main(int argc, char** argv)
while(x>=0) //doesn't terminate
{
x -= 0.15f;
- if(0>x && x>-0.15f)
+ if(0>x && x>-0.15f)
{
x = 15.0f;
}
diff --git a/regression/termination/global1/main.c b/regression/termination/global1/main.c
index ecb897b62..368fcddd7 100644
--- a/regression/termination/global1/main.c
+++ b/regression/termination/global1/main.c
@@ -1,21 +1,21 @@
-#include
-
-int g;
-
-int foo(int y)
-{
- __CPROVER_assume(g=1);
- assert(z==0);
-}
-
+#include
+
+int g;
+
+int foo(int y)
+{
+ __CPROVER_assume(g=1);
+ assert(z==0);
+}
+
diff --git a/regression/termination/global2/main.c b/regression/termination/global2/main.c
index f653bce18..32734b1a1 100644
--- a/regression/termination/global2/main.c
+++ b/regression/termination/global2/main.c
@@ -1,22 +1,22 @@
-int g;
-
-void foo()
-{
- g=10;
-}
-
-int bar()
-{
- return 20;
-}
-
-void main()
-{
- g = 1;
- int x;
- foo();
- x = bar();
- assert(g==10);
- assert(x==20);
-}
-
+int g;
+
+void foo()
+{
+ g=10;
+}
+
+int bar()
+{
+ return 20;
+}
+
+void main()
+{
+ g = 1;
+ int x;
+ foo();
+ x = bar();
+ assert(g==10);
+ assert(x==20);
+}
+
diff --git a/regression/termination/global3/main.c b/regression/termination/global3/main.c
index 965a7f015..347464275 100644
--- a/regression/termination/global3/main.c
+++ b/regression/termination/global3/main.c
@@ -1,8 +1,8 @@
int x;
int z;
-void foo()
-{
+void foo()
+{
for(x=0;x<10;x++);
}
diff --git a/regression/termination/global4/main.c b/regression/termination/global4/main.c
index 80e8b6e50..646b6a47b 100644
--- a/regression/termination/global4/main.c
+++ b/regression/termination/global4/main.c
@@ -1,6 +1,6 @@
int g = 1;
-void modify_global()
+void modify_global()
{
g = g;
}
@@ -11,12 +11,12 @@ void main()
//g = g;
- if(x)
+ if(x)
{
- modify_global();
+ modify_global();
}
- modify_global();
+ modify_global();
assert(g==1);
}
diff --git a/regression/termination/ite1/main.c b/regression/termination/ite1/main.c
index b4829d864..4f98ef44c 100644
--- a/regression/termination/ite1/main.c
+++ b/regression/termination/ite1/main.c
@@ -1,13 +1,13 @@
-void main()
-{
- int x;
- int y = 0;
-
- while(y==0)
- {
- if(x>=5) y=x;
- else y=5;
- }
-
- assert(y>=5);
-}
+void main()
+{
+ int x;
+ int y = 0;
+
+ while(y==0)
+ {
+ if(x>=5) y=x;
+ else y=5;
+ }
+
+ assert(y>=5);
+}
diff --git a/regression/termination/ite2/main.c b/regression/termination/ite2/main.c
index e6b24818f..fbb4eddee 100644
--- a/regression/termination/ite2/main.c
+++ b/regression/termination/ite2/main.c
@@ -1,11 +1,11 @@
-int foo(int x, int y)
-{
+int foo(int x, int y)
+{
int res = y;
if(x) res = y+1;
return res;
}
-int bar(int x)
-{
+int bar(int x)
+{
if(x) return 1;
return 2;
}
@@ -13,7 +13,7 @@ int bar(int x)
void main()
{
int x;
- int y = 0;
+ int y = 0;
int z = bar(x);
int w = foo(z,y);
diff --git a/regression/termination/ite3/main.c b/regression/termination/ite3/main.c
index 0bd206af3..624104931 100644
--- a/regression/termination/ite3/main.c
+++ b/regression/termination/ite3/main.c
@@ -1,14 +1,14 @@
-int foo(int x)
-{
+int foo(int x)
+{
int res = 0;
if(x) res = 1;
return res;
}
-int bar(int x)
-{
+int bar(int x)
+{
int res = 2;
if(x) res = 1;
- return res;
+ return res;
}
void main()
diff --git a/regression/termination/ite4/main.c b/regression/termination/ite4/main.c
index fd030a9a5..cd12c0013 100644
--- a/regression/termination/ite4/main.c
+++ b/regression/termination/ite4/main.c
@@ -1,13 +1,13 @@
-int foo(int x)
-{
+int foo(int x)
+{
int res;
if(x) return 0;
else return 1;
}
-int bar(int x)
-{
+int bar(int x)
+{
int res;
if(x) res = 0;
else res = 1;
diff --git a/regression/termination/locks1/main.c b/regression/termination/locks1/main.c
index 99ddf6417..4f76b0c20 100644
--- a/regression/termination/locks1/main.c
+++ b/regression/termination/locks1/main.c
@@ -10,7 +10,7 @@ int acquire_lock(char tid)
return 0;
}
-void release_lock()
+void release_lock()
{
lock = 0;
}
@@ -20,7 +20,7 @@ void thread1()
if(acquire_lock(1))
{
//do_stuff1();
- exit=1;
+ exit=1;
release_lock();
}
}
diff --git a/regression/termination/locks2/main.c b/regression/termination/locks2/main.c
index 5d2948237..789f0d094 100644
--- a/regression/termination/locks2/main.c
+++ b/regression/termination/locks2/main.c
@@ -10,7 +10,7 @@ int acquire_lock(char tid)
return 0;
}
-void release_lock()
+void release_lock()
{
lock = 0;
}
@@ -20,7 +20,7 @@ void thread1()
if(acquire_lock(1))
{
//do_stuff1();
- exit=1;
+ exit=1;
//release_lock();
}
}
diff --git a/regression/termination/loop1/main.c b/regression/termination/loop1/main.c
index 6750175ea..6c0d1f808 100644
--- a/regression/termination/loop1/main.c
+++ b/regression/termination/loop1/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 0;
+ int x = 0;
while(x<10)
{
diff --git a/regression/termination/loop2/main.c b/regression/termination/loop2/main.c
index e67632a94..dd5d9c810 100644
--- a/regression/termination/loop2/main.c
+++ b/regression/termination/loop2/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 0;
+ int x = 0;
int y = 0;
while(x<10)
diff --git a/regression/termination/loop3/main.c b/regression/termination/loop3/main.c
index 21a30e139..6ddb8924c 100644
--- a/regression/termination/loop3/main.c
+++ b/regression/termination/loop3/main.c
@@ -4,13 +4,13 @@ void main()
int y;
x=0;
y=0;
-
+
while(x<10 && y<20)
{
++x;
++y;
}
-
+
int z=x+y;
assert(z>=0);
diff --git a/regression/termination/loop5/main.c b/regression/termination/loop5/main.c
index f301dde9d..2fd0a019f 100644
--- a/regression/termination/loop5/main.c
+++ b/regression/termination/loop5/main.c
@@ -1,6 +1,6 @@
void main()
{
- unsigned x = 0;
+ unsigned x = 0;
while(x<10)
++x;
diff --git a/regression/termination/loop6/main.c b/regression/termination/loop6/main.c
index 2c4213934..c7bd862fe 100644
--- a/regression/termination/loop6/main.c
+++ b/regression/termination/loop6/main.c
@@ -4,13 +4,13 @@ void main()
{
int x = 0;
unsigned y = 0;
-
+
while(x<10 && y<20)
{
++x;
++y;
}
-
+
int z=x+y;
assert(z<=20);
}
diff --git a/regression/termination/loop7/main.c b/regression/termination/loop7/main.c
index 3c7dea455..1707acb1d 100644
--- a/regression/termination/loop7/main.c
+++ b/regression/termination/loop7/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x;
+ int x;
unsigned y;
x = -10;
y = 10;
diff --git a/regression/termination/loop9/main.c b/regression/termination/loop9/main.c
index ca602a19a..201463c41 100644
--- a/regression/termination/loop9/main.c
+++ b/regression/termination/loop9/main.c
@@ -1,6 +1,6 @@
void main()
{
- int x = 10;
+ int x = 10;
while(x>0)
{
diff --git a/regression/termination/loops/array_false.c b/regression/termination/loops/array_false.c
index 8e391d4b1..eeb8a1f76 100644
--- a/regression/termination/loops/array_false.c
+++ b/regression/termination/loops/array_false.c
@@ -11,16 +11,16 @@ main()
unsigned int SIZE=1;
unsigned int j,k;
int array[SIZE], menor;
-
+
menor = __VERIFIER_nondet_int();
for(j=0;jmenor);
+ menor = array[j];
+ }
+
+ __VERIFIER_assert(array[0]>menor);
}
diff --git a/regression/termination/loops/array_true.c b/regression/termination/loops/array_true.c
index e40b4725c..7cb2de419 100644
--- a/regression/termination/loops/array_true.c
+++ b/regression/termination/loops/array_true.c
@@ -11,16 +11,16 @@ main()
unsigned int SIZE=1;
unsigned int j,k;
int array[SIZE], menor;
-
+
menor = __VERIFIER_nondet_int();
for(j=0;j=menor);
+ menor = array[j];
+ }
+
+ __VERIFIER_assert(array[0]>=menor);
}
diff --git a/regression/termination/loops/bubble_sort_false.c b/regression/termination/loops/bubble_sort_false.c
index fa4558983..603a86c21 100644
--- a/regression/termination/loops/bubble_sort_false.c
+++ b/regression/termination/loops/bubble_sort_false.c
@@ -24,8 +24,8 @@ extern __attribute__((__nothrow__, __noreturn__)) void abort(void) ;
#line 5 "test-0180.c"
extern int __VERIFIER_nondet_int(void);
#line 7 "test-0180.c"
-static void fail(void)
-{
+static void fail(void)
+{
{
ERROR: assert(0);
@@ -35,7 +35,7 @@ static void fail(void)
#line 39 "test-0180.c"
struct list_head gl_list = {& gl_list, & gl_list};
#line 41 "test-0180.c"
-static void inspect(struct list_head const *head )
+static void inspect(struct list_head const *head )
{ struct node const *node ;
unsigned int __cil_tmp3 ;
struct list_head *__cil_tmp4 ;
@@ -744,7 +744,7 @@ static void inspect(struct list_head const *head )
}
}
#line 74 "test-0180.c"
-__inline static void __list_add(struct list_head *new , struct list_head *prev , struct list_head *next )
+__inline static void __list_add(struct list_head *new , struct list_head *prev , struct list_head *next )
{ unsigned int __cil_tmp4 ;
unsigned int __cil_tmp5 ;
unsigned int __cil_tmp6 ;
@@ -772,7 +772,7 @@ __inline static void __list_add(struct list_head *new , struct list_head *prev ,
}
}
#line 84 "test-0180.c"
-__inline static void __list_del(struct list_head *prev , struct list_head *next )
+__inline static void __list_del(struct list_head *prev , struct list_head *next )
{ unsigned int __cil_tmp3 ;
unsigned int __cil_tmp4 ;
@@ -790,7 +790,7 @@ __inline static void __list_del(struct list_head *prev , struct list_head *next
}
}
#line 90 "test-0180.c"
-__inline static void list_add(struct list_head *new , struct list_head *head )
+__inline static void list_add(struct list_head *new , struct list_head *head )
{ struct list_head *__cil_tmp3 ;
{
@@ -805,7 +805,7 @@ __inline static void list_add(struct list_head *new , struct list_head *head )
}
}
#line 95 "test-0180.c"
-__inline static void list_move(struct list_head *list , struct list_head *head )
+__inline static void list_move(struct list_head *list , struct list_head *head )
{ unsigned int __cil_tmp3 ;
unsigned int __cil_tmp4 ;
struct list_head *__cil_tmp5 ;
@@ -831,7 +831,7 @@ __inline static void list_move(struct list_head *list , struct list_head *head )
}
}
#line 101 "test-0180.c"
-static void gl_insert(int value )
+static void gl_insert(int value )
{ struct node *node ;
void *tmp ;
unsigned int __cil_tmp4 ;
@@ -910,7 +910,7 @@ static void gl_insert(int value )
}
}
#line 112 "test-0180.c"
-static void gl_read(void)
+static void gl_read(void)
{ int tmp ;
int tmp___0 ;
@@ -941,7 +941,7 @@ static void gl_read(void)
}
}
#line 120 "test-0180.c"
-static void gl_destroy(void)
+static void gl_destroy(void)
{ struct list_head *next ;
struct list_head *__cil_tmp2 ;
unsigned int __cil_tmp3 ;
@@ -1012,7 +1012,7 @@ static void gl_destroy(void)
}
}
#line 129 "test-0180.c"
-static int val_from_node(struct list_head *head )
+static int val_from_node(struct list_head *head )
{ struct node *entry ;
struct node *__cil_tmp3 ;
unsigned int __cil_tmp4 ;
@@ -1044,7 +1044,7 @@ static int val_from_node(struct list_head *head )
}
}
#line 134 "test-0180.c"
-static _Bool gl_sort_pass(void)
+static _Bool gl_sort_pass(void)
{ _Bool any_change ;
struct list_head *pos0 ;
struct list_head *pos1 ;
@@ -1113,7 +1113,7 @@ static _Bool gl_sort_pass(void)
}
}
#line 156 "test-0180.c"
-static void gl_sort(void)
+static void gl_sort(void)
{ _Bool tmp ;
{
@@ -1139,7 +1139,7 @@ static void gl_sort(void)
}
}
#line 162 "test-0180.c"
-int main(void)
+int main(void)
{ struct list_head const *__cil_tmp1 ;
struct list_head const *__cil_tmp2 ;
diff --git a/regression/termination/loops/eureka_01_false.c b/regression/termination/loops/eureka_01_false.c
index 87e5d9f0e..61c73651c 100644
--- a/regression/termination/loops/eureka_01_false.c
+++ b/regression/termination/loops/eureka_01_false.c
@@ -18,7 +18,7 @@ void main(){
int distance[5];
int x,y;
int i,j;
-
+
for(i = 0; i < nodecount; i++){
if(i == source){
distance[i] = 0;
diff --git a/regression/termination/loops/eureka_01_true.c b/regression/termination/loops/eureka_01_true.c
index 2f67ad9fe..1d519eeda 100644
--- a/regression/termination/loops/eureka_01_true.c
+++ b/regression/termination/loops/eureka_01_true.c
@@ -16,7 +16,7 @@ int main(){
int distance[5];
int x,y;
int i,j;
-
+
for(i = 0; i < nodecount; i++){
if(i == source){
distance[i] = 0;
diff --git a/regression/termination/loops/eureka_05_true.c b/regression/termination/loops/eureka_05_true.c
index 5345b95f1..ec315384c 100644
--- a/regression/termination/loops/eureka_05_true.c
+++ b/regression/termination/loops/eureka_05_true.c
@@ -16,7 +16,7 @@ void SelectionSort()
for (lh = 0; lh < n; lh++) {
rh = lh;
- for (i = lh + 1; i < n; i++)
+ for (i = lh + 1; i < n; i++)
if (array[i] < array[rh]) rh = i;
temp = array[lh];
array[lh] = array[rh];
diff --git a/regression/termination/loops/insertion_sort_false.c b/regression/termination/loops/insertion_sort_false.c
index e11e4d208..8efc0cb0d 100644
--- a/regression/termination/loops/insertion_sort_false.c
+++ b/regression/termination/loops/insertion_sort_false.c
@@ -8,8 +8,8 @@ unsigned int __VERIFIER_nondet_uint();
int main() {
unsigned int SIZE=__VERIFIER_nondet_uint();
int i, j, k, key;
- int v[SIZE];
- for (j=1;j=0) && (v[i]>key)) {
@@ -17,9 +17,9 @@ int main() {
v[i+1] = v[i];
i = i - 1;
}
- v[i+1] = key;
- }
+ v[i+1] = key;
+ }
for (k=1;k=0) && (v[i]>key)) {
v[i+1] = v[i];
i = i - 1;
}
- v[i+1] = key;
- }
+ v[i+1] = key;
+ }
for (k=1;k= 0; i--) {
str2[j] = str1[0];
j++;
diff --git a/regression/termination/loops/invert_string_true.c b/regression/termination/loops/invert_string_true.c
index cb62c80f5..14d7e1864 100644
--- a/regression/termination/loops/invert_string_true.c
+++ b/regression/termination/loops/invert_string_true.c
@@ -18,7 +18,7 @@ int main() {
str1[max-1]= '\0';
j = 0;
-
+
for (i = max - 1; i >= 0; i--) {
str2[j] = str1[i];
j++;
@@ -28,6 +28,6 @@ int main() {
for (i=0; imaior)
- maior = matriz[j][k];
- }
-
+ maior = matriz[j][k];
+ }
+
for(j=0;j=maior)
- maior = matriz[j][k];
- }
-
- __VERIFIER_assert(matriz[0][0]<=maior);
+ maior = matriz[j][k];
+ }
+
+ __VERIFIER_assert(matriz[0][0]<=maior);
}
diff --git a/regression/termination/loops/n.c11_true.c b/regression/termination/loops/n.c11_true.c
index 90df007e5..7fa8a09e6 100644
--- a/regression/termination/loops/n.c11_true.c
+++ b/regression/termination/loops/n.c11_true.c
@@ -15,10 +15,10 @@ int main(){
while(__VERIFIER_nondet_bool()){
-
+
if (len==4)
len =0;
-
+
a[len]=0;
len++;
@@ -26,6 +26,6 @@ int main(){
__VERIFIER_assert(len>=0 && len<5);
return 1;
-
+
}
diff --git a/regression/termination/loops/n.c24_true.c b/regression/termination/loops/n.c24_true.c
index 6aa4889c4..8d5fb6f16 100644
--- a/regression/termination/loops/n.c24_true.c
+++ b/regression/termination/loops/n.c24_true.c
@@ -23,7 +23,7 @@ int main(){
for (i = 0; i < 1000; ++i)
x[i]= __VERIFIER_nondet_int();
-
+
for (i= 0; i < 1000; ++i){
ret = __VERIFIER_nondet_int();
@@ -32,50 +32,50 @@ int main(){
tmp_cnt = __VERIFIER_nondet_int();
if (tmp_cnt < 0)
return -1;
-
-
+
+
for ( offset = 0; offset < tmp_cnt; offset++ )
{
ret = foo(&tel_data ) ;
if ( ( ret == 0 ) || ( ret == 1 ) )
{
-
+
return 1 ;
}
else if ( ret == -1 )
{
-
+
continue ;
}
-
+
for ( j = 0; x[j] != 0; j++ )
{
-
+
if ( x[i] == 1)
{
-
+
memmove( &x[i], &x[i + 1], (1001) - ( i + 1 ) ) ;
}
}
-
+
ret = bar( x) ;
-
+
if ( ret != -1 )
{
-
+
continue ;
}
-
+
klen = strlen(x ) ;
-
+
if ( klen > 20 )
{
-
+
x[i]=0;
-
+
}
else if ( klen > 0 )
{
diff --git a/regression/termination/loops/n.c40_true.c b/regression/termination/loops/n.c40_true.c
index 51401c6c1..482b5ba07 100644
--- a/regression/termination/loops/n.c40_true.c
+++ b/regression/termination/loops/n.c40_true.c
@@ -3,16 +3,16 @@ int __VERIFIER_nondet_int();
char x[100], y[100];
int i,j,k;
-void main() {
+void main() {
k = __VERIFIER_nondet_int();
-
+
i = 0;
while(x[i] != 0){
y[i] = x[i];
i++;
}
y[i] = 0;
-
+
if(k >= 0 && k < i)
if(y[k] == 0)
{ERROR: goto ERROR;}
diff --git a/regression/termination/loops/nec11_false.c b/regression/termination/loops/nec11_false.c
index 839657cb3..cdc6710a6 100644
--- a/regression/termination/loops/nec11_false.c
+++ b/regression/termination/loops/nec11_false.c
@@ -15,10 +15,10 @@ int main(){
while(c){
-
+
if (len==4)
len =0;
-
+
a[len]=0;
len++;
@@ -26,5 +26,5 @@ int main(){
__VERIFIER_assert(len==5);
return 1;
-
+
}
diff --git a/regression/termination/loops/nec20_false.c b/regression/termination/loops/nec20_false.c
index 2558467f4..dacfb5f99 100644
--- a/regression/termination/loops/nec20_false.c
+++ b/regression/termination/loops/nec20_false.c
@@ -10,7 +10,7 @@ int main(){
_Bool k=__VERIFIER_nondet_bool();
int i,n,j;
int a[1025];
-
+
if (k){
n=0;
} else {
@@ -32,7 +32,7 @@ int main(){
a[b]=1;
else
a[b%1023] =1;
-
+
return 1;
-
+
}
diff --git a/regression/termination/loops/nec40_true.c b/regression/termination/loops/nec40_true.c
index d113517f0..13f7d086e 100644
--- a/regression/termination/loops/nec40_true.c
+++ b/regression/termination/loops/nec40_true.c
@@ -9,16 +9,16 @@ int __VERIFIER_nondet_int();
char x[100], y[100];
int i,j,k;
-void main() {
+void main() {
k = __VERIFIER_nondet_int();
-
+
i = 0;
while(x[i] != 0){
y[i] = x[i];
i++;
}
y[i] = 0;
-
+
if(k >= 0 && k < i)
if(y[k] != 0)
{__VERIFIER_assert(0);}
diff --git a/regression/termination/loops/string_false.c b/regression/termination/loops/string_false.c
index ec8a43f07..5e30e6305 100644
--- a/regression/termination/loops/string_false.c
+++ b/regression/termination/loops/string_false.c
@@ -14,14 +14,14 @@ main()
{
char string_A[MAX], string_B[MAX];
int i, j, nc_A, nc_B, found=0;
-
-
+
+
for(i=0; i= nc_A);
-
-
+
+
i=j=0;
while((inc_B-1)<= nc_A);
-
-
+
+
i=j=0;
while((inc_B-1);
-
+
__VERIFIER_assert(found == 0 || found == 1);
}
diff --git a/regression/termination/loops/sum01_bug02_false.c b/regression/termination/loops/sum01_bug02_false.c
index 1f98f5e30..bcdd3b7a2 100644
--- a/regression/termination/loops/sum01_bug02_false.c
+++ b/regression/termination/loops/sum01_bug02_false.c
@@ -6,10 +6,10 @@ void __VERIFIER_assert(int cond) {
}
#define a (2)
extern unsigned int __VERIFIER_nondet_uint();
-int main() {
+int main() {
int i, j=10, n=__VERIFIER_nondet_uint(), sn=0;
for(i=1; i<=n; i++) {
- if (i=100 || z<=100);
}
diff --git a/regression/termination/loops/terminator_03_false.c b/regression/termination/loops/terminator_03_false.c
index 6554eb44b..3d44d6e58 100644
--- a/regression/termination/loops/terminator_03_false.c
+++ b/regression/termination/loops/terminator_03_false.c
@@ -13,12 +13,12 @@ main()
if (y>0)
{
- while(x<100)
+ while(x<100)
{
x=x+y;
}
- }
- __VERIFIER_assert(y<=0 || (y<0 && x>=100));
+ }
+ __VERIFIER_assert(y<=0 || (y<0 && x>=100));
}
diff --git a/regression/termination/loops/terminator_03_true.c b/regression/termination/loops/terminator_03_true.c
index fcfa5948a..5f923a55b 100644
--- a/regression/termination/loops/terminator_03_true.c
+++ b/regression/termination/loops/terminator_03_true.c
@@ -14,13 +14,13 @@ main()
if (y>0)
{
- while(x<100)
+ while(x<100)
{
x=x+y;
}
- }
-
- __VERIFIER_assert(y<=0 || (y>0 && x>=100));
+ }
+
+ __VERIFIER_assert(y<=0 || (y>0 && x>=100));
}
diff --git a/regression/termination/loops/trex03_false.c b/regression/termination/loops/trex03_false.c
index 3d540b049..bb1c139d4 100644
--- a/regression/termination/loops/trex03_false.c
+++ b/regression/termination/loops/trex03_false.c
@@ -14,7 +14,7 @@ int main()
unsigned int x1=__VERIFIER_nondet_uint(), x2=__VERIFIER_nondet_uint(), x3=__VERIFIER_nondet_uint();
unsigned int d1=1, d2=1, d3=1;
bool c1=__VERIFIER_nondet_bool(), c2=__VERIFIER_nondet_bool();
-
+
while(x1>0 && x2>0 && x3>0)
{
if (c1) x1=x1-d1;
diff --git a/regression/termination/loops/trex03_true.c b/regression/termination/loops/trex03_true.c
index ebdd7c14a..62bf91091 100644
--- a/regression/termination/loops/trex03_true.c
+++ b/regression/termination/loops/trex03_true.c
@@ -12,7 +12,7 @@ int main()
unsigned int x1=__VERIFIER_nondet_uint(), x2=__VERIFIER_nondet_uint(), x3=__VERIFIER_nondet_uint();
unsigned int d1=1, d2=1, d3=1;
_Bool c1=__VERIFIER_nondet_bool(), c2=__VERIFIER_nondet_bool();
-
+
while(x1>0 && x2>0 && x3>0)
{
if (c1) x1=x1-d1;
diff --git a/regression/termination/loops/trex04_true.c b/regression/termination/loops/trex04_true.c
index b0e1926e8..6dee2e188 100644
--- a/regression/termination/loops/trex04_true.c
+++ b/regression/termination/loops/trex04_true.c
@@ -29,7 +29,7 @@ int main()
if (c1) foo();
if (c2) d = d - 1;
-
+
while(x>0)
{
x=x-d;
diff --git a/regression/termination/loops/veris.c_OpenSER__cases1_stripFullBoth_arr_true.c b/regression/termination/loops/veris.c_OpenSER__cases1_stripFullBoth_arr_true.c
index 57033331f..e27f33c65 100644
--- a/regression/termination/loops/veris.c_OpenSER__cases1_stripFullBoth_arr_true.c
+++ b/regression/termination/loops/veris.c_OpenSER__cases1_stripFullBoth_arr_true.c
@@ -133,11 +133,11 @@ struct sockaddr_un
-static int parse_expression_list(char *str)
+static int parse_expression_list(char *str)
{
int start=0, i=-1, j=-1;
char str2[EXPRESSION_LENGTH];
-
+
if (!str) return -1;
do {
@@ -177,7 +177,7 @@ static int parse_expression_list(char *str)
start = i+1;
}
} while (str[i] != EOS);
-
+
return 0;
}
diff --git a/regression/termination/loops/verisec_OpenSER__cases1_stripFullBoth_arr_false.c b/regression/termination/loops/verisec_OpenSER__cases1_stripFullBoth_arr_false.c
index c1990a839..4609139d0 100644
--- a/regression/termination/loops/verisec_OpenSER__cases1_stripFullBoth_arr_false.c
+++ b/regression/termination/loops/verisec_OpenSER__cases1_stripFullBoth_arr_false.c
@@ -133,11 +133,11 @@ struct sockaddr_un
-static int parse_expression_list(char *str)
+static int parse_expression_list(char *str)
{
int start=0, i=-1, j=-1;
char str2[EXPRESSION_LENGTH];
-
+
if (!str) return -1;
do {
@@ -175,7 +175,7 @@ static int parse_expression_list(char *str)
start = i+1;
}
} while (str[i] != EOS);
-
+
return 0;
}
diff --git a/regression/termination/loops/vogal_false.c b/regression/termination/loops/vogal_false.c
index 006a9596f..6b8cfb03c 100644
--- a/regression/termination/loops/vogal_false.c
+++ b/regression/termination/loops/vogal_false.c
@@ -10,14 +10,14 @@ extern char __VERIFIER_nondet_char();
main(void)
{
- char string_entrada[MAX], vetor_vogais[]={'a','A','e','E','i','I','o','O','u','U','\0'};;
+ char string_entrada[MAX], vetor_vogais[]={'a','A','e','E','i','I','o','O','u','U','\0'};;
unsigned int i,j,cont, tam_string, n_caracter;
for(i=0;i0)
{
diff --git a/regression/termination/phase2/main.c b/regression/termination/phase2/main.c
index 71187b9b3..069c660a0 100644
--- a/regression/termination/phase2/main.c
+++ b/regression/termination/phase2/main.c
@@ -1,8 +1,8 @@
void main()
{
- unsigned char x = 1;
- unsigned char y = 1;
- unsigned char w = 0;
+ unsigned char x = 1;
+ unsigned char y = 1;
+ unsigned char w = 0;
while(x>0) //terminates after overflow of x // -w, -y, -x
{
diff --git a/regression/termination/phase3/main.c b/regression/termination/phase3/main.c
index 0bba05b6d..67c31f21f 100644
--- a/regression/termination/phase3/main.c
+++ b/regression/termination/phase3/main.c
@@ -1,7 +1,7 @@
void main()
{
- unsigned char x = 1;
- unsigned char y = 1;
+ unsigned char x = 1;
+ unsigned char y = 1;
while(x>0) //does not terminate
{
diff --git a/regression/termination/phase4/main.c b/regression/termination/phase4/main.c
index 6f3a905d8..f80f66a97 100644
--- a/regression/termination/phase4/main.c
+++ b/regression/termination/phase4/main.c
@@ -1,7 +1,7 @@
void main()
{
- unsigned char x = 1;
- unsigned char y = 1;
+ unsigned char x = 1;
+ unsigned char y = 1;
while(x>0) //does not terminate
{
diff --git a/regression/termination/phase5/main.c b/regression/termination/phase5/main.c
index 603f6ff90..e74f5ff72 100644
--- a/regression/termination/phase5/main.c
+++ b/regression/termination/phase5/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 1;
- int y = 1;
+ int x = 1;
+ int y = 1;
while(x>0)
{
diff --git a/regression/termination/phase6/main.c b/regression/termination/phase6/main.c
index be3c469a8..938fe91f1 100644
--- a/regression/termination/phase6/main.c
+++ b/regression/termination/phase6/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 1;
- int y = 1;
+ int x = 1;
+ int y = 1;
while(x>0)
{
diff --git a/regression/termination/phase7/debug.c b/regression/termination/phase7/debug.c
index dab17127b..4c26f0e6c 100644
--- a/regression/termination/phase7/debug.c
+++ b/regression/termination/phase7/debug.c
@@ -20,11 +20,11 @@ void main() {
/* __CPROVER_assume(y29 == 1 + yphi21); */
/* __CPROVER_assume(uphi29 == (cond27 && guard27 ? uphi21 : u28)); */
/* __CPROVER_assume(guard29 == (cond27 && guard27 || guard28)); */
-
+
// assert(!(guard21 && guardls30 && guard29 && cond30 && (-(long)ylb30 <= -(long)y29 || -(long)ulb30 < -(long)uphi29) && -(long)ulb30 <= -(long)uphi29));
//assert(!(guard21 && guardls30 && guard29 && cond30 && (-ylb30 <= -y29 || -ulb30 < -uphi29) && -ulb30 <= -uphi29));
- __CPROVER_bitvector[32] c0$1$0, c0$1$1, c0$1$2, c0$0$0, c0$0$1, c0$0$2;
+ __CPROVER_bitvector[32] c0$1$0, c0$1$1, c0$1$2, c0$0$0, c0$0$1, c0$0$2;
/* assert(c0$1$0 * 4194304 + c0$1$1 * 2147483647 + c0$1$2 * -1656643584 > c0$1$0 * 4194303 + c0$1$1 * -2147483648 + c0$1$2 * -1656643583 || */
/* c0$0$0 * 4194304 + c0$0$1 * 2147483647 + c0$0$2 * -1656643584 > c0$0$0 * 4194303 + c0$0$1 * -2147483648 + c0$0$2 * -1656643583 && c0$1$0 * 4194304 + c0$1$1 * 2147483647 + c0$1$2 * -1656643584 >= c0$1$0 * 4194303 + c0$1$1 * -2147483648 + c0$1$2 * -1656643583); */
diff --git a/regression/termination/phase7/main.c b/regression/termination/phase7/main.c
index 36e0c4de6..17f57a84b 100644
--- a/regression/termination/phase7/main.c
+++ b/regression/termination/phase7/main.c
@@ -2,8 +2,8 @@
void main()
{
- int x = 1;
- int y = 1;
+ int x = 1;
+ int y = 1;
int u = 0;
while(x>0 && u < INT_MAX) //-u, -y, x
diff --git a/regression/termination/phase7/main_verify.c b/regression/termination/phase7/main_verify.c
index 0fdaf7e94..57a821083 100644
--- a/regression/termination/phase7/main_verify.c
+++ b/regression/termination/phase7/main_verify.c
@@ -2,8 +2,8 @@
void main()
{
- int x;// = 1;
- int y;// = 1;
+ int x;// = 1;
+ int y;// = 1;
int u;// = 0;
assert(verify(x, y, u) != 0);
@@ -34,8 +34,8 @@ int verify(int x, int y, int u) {
//if(-u0 <= -u && (-u0 != -u || -y0 <= -y))
//if(-(long)u0+(long)x0 <= -(long)u+(long)x && (-(long)u0+(long)x0 != -(long)u+(long)x || ( -(long)u0-(long)x0 <= -(long)u-(long)x && (-(long)u0-(long)x0 != -(long)u-(long)x || (long)u0+(long)x0 <= (long)u+(long)x))))
//if((long)x0 <= (long)x && ((long)x0 != (long)x || -(long)u0-(long)x0 <= -(long)u-(long)x))
- // if(-(long)u0+(long)x0 <= -(long)u+(long)x && (-(long)u0+(long)x0 != -(long)u+(long)x ||
- // (-(long)u0-(long)x0 <= -(long)u-(long)x && (-(long)u0-(long)x0 != -(long)u-(long)x ||
+ // if(-(long)u0+(long)x0 <= -(long)u+(long)x && (-(long)u0+(long)x0 != -(long)u+(long)x ||
+ // (-(long)u0-(long)x0 <= -(long)u-(long)x && (-(long)u0-(long)x0 != -(long)u-(long)x ||
// (long)u0+(long)x0 <= (long)u+(long)x))))
return 0;
}
diff --git a/regression/termination/phase8/debug.c b/regression/termination/phase8/debug.c
index dab17127b..4c26f0e6c 100644
--- a/regression/termination/phase8/debug.c
+++ b/regression/termination/phase8/debug.c
@@ -20,11 +20,11 @@ void main() {
/* __CPROVER_assume(y29 == 1 + yphi21); */
/* __CPROVER_assume(uphi29 == (cond27 && guard27 ? uphi21 : u28)); */
/* __CPROVER_assume(guard29 == (cond27 && guard27 || guard28)); */
-
+
// assert(!(guard21 && guardls30 && guard29 && cond30 && (-(long)ylb30 <= -(long)y29 || -(long)ulb30 < -(long)uphi29) && -(long)ulb30 <= -(long)uphi29));
//assert(!(guard21 && guardls30 && guard29 && cond30 && (-ylb30 <= -y29 || -ulb30 < -uphi29) && -ulb30 <= -uphi29));
- __CPROVER_bitvector[32] c0$1$0, c0$1$1, c0$1$2, c0$0$0, c0$0$1, c0$0$2;
+ __CPROVER_bitvector[32] c0$1$0, c0$1$1, c0$1$2, c0$0$0, c0$0$1, c0$0$2;
/* assert(c0$1$0 * 4194304 + c0$1$1 * 2147483647 + c0$1$2 * -1656643584 > c0$1$0 * 4194303 + c0$1$1 * -2147483648 + c0$1$2 * -1656643583 || */
/* c0$0$0 * 4194304 + c0$0$1 * 2147483647 + c0$0$2 * -1656643584 > c0$0$0 * 4194303 + c0$0$1 * -2147483648 + c0$0$2 * -1656643583 && c0$1$0 * 4194304 + c0$1$1 * 2147483647 + c0$1$2 * -1656643584 >= c0$1$0 * 4194303 + c0$1$1 * -2147483648 + c0$1$2 * -1656643583); */
diff --git a/regression/termination/phase8/main.c b/regression/termination/phase8/main.c
index 26b7587d8..39fac0a35 100644
--- a/regression/termination/phase8/main.c
+++ b/regression/termination/phase8/main.c
@@ -2,11 +2,11 @@
void main()
{
- int x = 1;
- int y = 1;
+ int x = 1;
+ int y = 1;
int u = 0;
int w = 0;
-
+
while(x>0 && w0)
{
diff --git a/regression/termination/pointer1/main.c b/regression/termination/pointer1/main.c
index 34c87bb31..da5aa119a 100644
--- a/regression/termination/pointer1/main.c
+++ b/regression/termination/pointer1/main.c
@@ -1,5 +1,5 @@
-void foo(int *x)
-{
+void foo(int *x)
+{
*x = 10;
}
diff --git a/regression/termination/pointer2/main.c b/regression/termination/pointer2/main.c
index 02f54b869..318e03ee5 100644
--- a/regression/termination/pointer2/main.c
+++ b/regression/termination/pointer2/main.c
@@ -1,5 +1,5 @@
-void foo(int *x)
-{
+void foo(int *x)
+{
x++;
*x = 10;
}
diff --git a/regression/termination/precond_term4/main.c b/regression/termination/precond_term4/main.c
index ff0e4f92e..70fbe40c6 100644
--- a/regression/termination/precond_term4/main.c
+++ b/regression/termination/precond_term4/main.c
@@ -16,9 +16,9 @@ signed long int full_write(signed int fd, const void *buf, unsigned long int len
void main()
{
- signed int fd;
+ signed int fd;
char buf[256];
- unsigned long int len;
+ unsigned long int len;
signed long int cc;
full_write(fd,buf,len,cc);
}
diff --git a/regression/termination/refinement1/main.c b/regression/termination/refinement1/main.c
index 8b5cf8474..da4da16df 100644
--- a/regression/termination/refinement1/main.c
+++ b/regression/termination/refinement1/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 10;
- int y = 0;
+ int x = 10;
+ int y = 0;
while(x>2*y)
{
diff --git a/regression/termination/refinement2/main.c b/regression/termination/refinement2/main.c
index ccdcfb657..f4b7f0407 100644
--- a/regression/termination/refinement2/main.c
+++ b/regression/termination/refinement2/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 10;
- int y = 0;
+ int x = 10;
+ int y = 0;
while(x>y)
{
diff --git a/regression/termination/refinement3/main.c b/regression/termination/refinement3/main.c
index 8b5cf8474..da4da16df 100644
--- a/regression/termination/refinement3/main.c
+++ b/regression/termination/refinement3/main.c
@@ -1,7 +1,7 @@
void main()
{
- int x = 10;
- int y = 0;
+ int x = 10;
+ int y = 0;
while(x>2*y)
{
diff --git a/regression/termination/runall.sh b/regression/termination/runall.sh
index dd85b93a6..14e5d0498 100755
--- a/regression/termination/runall.sh
+++ b/regression/termination/runall.sh
@@ -12,8 +12,8 @@ do
do
cd $d
rm -f ../$d.$o.log
- for f in *.c
- do
+ for f in *.c
+ do
echo $d/$f "using" $o
echo "FILE:" $f >> ../$d.$o.log
(time (perl -e 'alarm shift @ARGV; exec @ARGV' $TIMEOUT $SUMMARIZER $CHECKS $f --$o)) &>> ../$d.$o.log
diff --git a/regression/termination/running1/main.c b/regression/termination/running1/main.c
index 7345364ba..e4e9fcdac 100644
--- a/regression/termination/running1/main.c
+++ b/regression/termination/running1/main.c
@@ -1,12 +1,12 @@
-/*
+/*
C version of the lapack library
http://www.netlib.org/clapack/cblas/sasum.c
-
+
run with
-
+
../../../src/summarizer/summarizer main.c --termination --context-sensitive
-
+
*/
int nondet_int();
@@ -22,7 +22,7 @@ int main()
{
int n =nondet_int(), incx=nondet_int();
-
+
__CPROVER_assume(incx > 0 && incx < 1000);
__CPROVER_assume(n < 1000 && n > 0);
diff --git a/regression/termination/running2/main.c b/regression/termination/running2/main.c
index cc4656778..6ec3b7437 100644
--- a/regression/termination/running2/main.c
+++ b/regression/termination/running2/main.c
@@ -1,12 +1,12 @@
-/*
+/*
C version of the lapack library
http://www.netlib.org/clapack/cblas/sasum.c
-
+
run with
-
+
../../../src/summarizer/summarizer main.c --termination --context-sensitive
-
+
*/
int nondet_int();
@@ -31,8 +31,8 @@ int g(int n, int incx)
int main()
{
int n = nondet_int(), incx = nondet_int();
-
+
g(n,incx);
-
+
return 0;
}
diff --git a/regression/termination/running3/main.c b/regression/termination/running3/main.c
index 5fba32973..85b6c59cb 100644
--- a/regression/termination/running3/main.c
+++ b/regression/termination/running3/main.c
@@ -1,32 +1,32 @@
-/*
+/*
C version of the lapack library
http://www.netlib.org/clapack/cblas/sasum.c
-
+
run with
-
+
../../../src/summarizer/summarizer main.c --termination --context-sensitive
-
+
*/
int nondet_int();
-int foo(int *sx, int n, int incx)
-{
+int foo(int *sx, int n, int incx)
+{
int nincx = n * incx;
int stemp=0;
int i;
- for (i=0; incx < 0 ? i >= nincx : i <= nincx; i += incx)
- {
+ for (i=0; incx < 0 ? i >= nincx : i <= nincx; i += incx)
+ {
stemp += sx[i-1];
}
return stemp;
}
-int bar(int n, int incx)
+int bar(int n, int incx)
{
int sx[n];
- if(100 <= n && n <= 10000 && 0 < incx && incx <= 1000)
+ if(100 <= n && n <= 10000 && 0 < incx && incx <= 1000)
{
int stemp = foo(&sx, n, incx);
}
@@ -35,6 +35,6 @@ int bar(int n, int incx)
int main()
{
- int n = nondet_int(), incx = nondet_int();
+ int n = nondet_int(), incx = nondet_int();
bar(n,incx);
}
diff --git a/regression/termination/running4/main.c b/regression/termination/running4/main.c
index ffb76a47c..2bd727165 100644
--- a/regression/termination/running4/main.c
+++ b/regression/termination/running4/main.c
@@ -1,32 +1,32 @@
-/*
+/*
C version of the lapack library
http://www.netlib.org/clapack/cblas/sasum.c
-
+
run with
-
+
../../../src/summarizer/summarizer main.c --termination --context-sensitive
-
+
*/
int nondet_int();
-int foo(int *sx, int n, int incx)
-{
+int foo(int *sx, int n, int incx)
+{
int nincx = n * incx;
int stemp=0;
int i;
- for (i=0; incx < 0 ? i >= nincx : i <= nincx; i += incx)
- {
+ for (i=0; incx < 0 ? i >= nincx : i <= nincx; i += incx)
+ {
stemp += sx[i-1];
}
return stemp;
}
-int bar(int n, int incx)
+int bar(int n, int incx)
{
int sx[n];
- if(100 <= n && n <= 10000 && 0 <= incx && incx <= 1000)
+ if(100 <= n && n <= 10000 && 0 <= incx && incx <= 1000)
{
int stemp = foo(&sx, n, incx);
}
@@ -35,6 +35,6 @@ int bar(int n, int incx)
int main()
{
- int n = nondet_int(), incx = nondet_int();
+ int n = nondet_int(), incx = nondet_int();
bar(n,incx);
}
diff --git a/regression/termination/simple1/main.c b/regression/termination/simple1/main.c
index 8a95214f7..0b9154bec 100644
--- a/regression/termination/simple1/main.c
+++ b/regression/termination/simple1/main.c
@@ -1,10 +1,10 @@
-int foo()
-{
+int foo()
+{
return 1;
}
-int bar()
-{
- return 2;
+int bar()
+{
+ return 2;
}
void main()
diff --git a/regression/termination/simple2/main.c b/regression/termination/simple2/main.c
index e1f62b82d..984b32921 100644
--- a/regression/termination/simple2/main.c
+++ b/regression/termination/simple2/main.c
@@ -1,5 +1,5 @@
-int foo(int x)
-{
+int foo(int x)
+{
if(x) return 9;
return 10;
}
diff --git a/regression/termination/sum1/main.c b/regression/termination/sum1/main.c
index df354feeb..c6f4ab383 100644
--- a/regression/termination/sum1/main.c
+++ b/regression/termination/sum1/main.c
@@ -1,27 +1,27 @@
-#include
-
-int max(int x, int y)
-{
- if(x>y) return x;
- return y;
-}
-
-int inv(int x)
-{
- __CPROVER_assume(x>INT_MIN); //would not be needed if we did not extend the bitvector sizes
- return -x;
-}
-
-void main()
-{
- int x;
- __CPROVER_assume(2<=x && x<=3);
-
- int y=inv(x);
- int z=max(y,0);
-
- assert(y<=-2);
- assert(y==-x);
- assert(z>=0);
- assert(z>=y);
-}
+#include
+
+int max(int x, int y)
+{
+ if(x>y) return x;
+ return y;
+}
+
+int inv(int x)
+{
+ __CPROVER_assume(x>INT_MIN); //would not be needed if we did not extend the bitvector sizes
+ return -x;
+}
+
+void main()
+{
+ int x;
+ __CPROVER_assume(2<=x && x<=3);
+
+ int y=inv(x);
+ int z=max(y,0);
+
+ assert(y<=-2);
+ assert(y==-x);
+ assert(z>=0);
+ assert(z>=y);
+}
From b7bc0469122b65a0feff6b66f5105bdc09a4d008 Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Thu, 20 Jul 2017 15:47:56 +0100
Subject: [PATCH 003/322] BMC option
---
src/2ls/2ls_parse_options.cpp | 249 +++++++++++++++++--------------
src/2ls/2ls_parse_options.h | 2 +-
src/2ls/cover_goals_ext.h | 3 +-
src/2ls/summary_checker_base.cpp | 12 +-
src/2ls/summary_checker_bmc.cpp | 7 +-
5 files changed, 153 insertions(+), 120 deletions(-)
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index b1363d104..3426fbd14 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -141,7 +141,15 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("unwindset", cmdline.get_value("unwindset"));
if(cmdline.isset("unwind"))
+ {
options.set_option("unwind", cmdline.get_value("unwind"));
+ options.set_option("unwind-min", cmdline.get_value("unwind"));
+ }
+ else
+ {
+ options.set_option("unwind", 0);
+ options.set_option("unwind-min", 0);
+ }
if(cmdline.isset("inline-partial"))
options.set_option("inline-partial", cmdline.get_value("inline-partial"));
@@ -263,7 +271,9 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("k-induction", true);
options.set_option("inline", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", UINT_MAX);
+ options.set_option("unwind", std::numeric_limits::max());
+ else
+ options.set_option("unwind-min", 0);
}
// do incremental bmc
@@ -273,7 +283,19 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("inline", true);
options.set_option("havoc", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", UINT_MAX);
+ options.set_option("unwind", std::numeric_limits::max());
+ else
+ options.set_option("unwind-min", 0);
+ }
+
+ // do bmc
+ if(cmdline.isset("bmc"))
+ {
+ options.set_option("bmc", true);
+ options.set_option("inline", true);
+ options.set_option("havoc", true);
+ if(!cmdline.isset("unwind"))
+ throw "--bmc only possible with --unwind";
}
// check for spuriousness of assertion failures
@@ -343,153 +365,156 @@ Function: twols_parse_optionst::doit
int twols_parse_optionst::doit()
{
- if(cmdline.isset("version"))
+ try
{
- std::cout << TWOLS_VERSION << std::endl;
- return 0;
- }
+ if(cmdline.isset("version"))
+ {
+ std::cout << TWOLS_VERSION << std::endl;
+ return 0;
+ }
- //
- // command line options
- //
+ //
+ // command line options
+ //
- optionst options;
- get_command_line_options(options);
+ optionst options;
+ get_command_line_options(options);
- eval_verbosity();
+ eval_verbosity();
- //
- // Print a banner
- //
- status() << "2LS version " TWOLS_VERSION " (based on CBMC " CBMC_VERSION ")"
- << eom;
+ //
+ // Print a banner
+ //
+ status() << "2LS version " TWOLS_VERSION " (based on CBMC " CBMC_VERSION ")"
+ << eom;
- goto_modelt goto_model;
+ goto_modelt goto_model;
- register_languages();
+ register_languages();
- if(get_goto_program(options, goto_model))
- return 6;
+ if(get_goto_program(options, goto_model))
+ return 6;
- if(cmdline.isset("show-stats"))
- {
- show_stats(goto_model, std::cout);
- return 7;
- }
+ if(cmdline.isset("show-stats"))
+ {
+ show_stats(goto_model, std::cout);
+ return 7;
+ }
- // options for various debug outputs
+ // options for various debug outputs
- if(cmdline.isset("show-ssa"))
- {
- bool simplify=!cmdline.isset("no-simplify");
- irep_idt function=cmdline.get_value("function");
- show_ssa(goto_model, function, simplify, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-ssa"))
+ {
+ bool simplify=!cmdline.isset("no-simplify");
+ irep_idt function=cmdline.get_value("function");
+ show_ssa(goto_model, function, simplify, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-defs"))
- {
- irep_idt function=cmdline.get_value("function");
- show_defs(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-defs"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_defs(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-assignments"))
- {
- irep_idt function=cmdline.get_value("function");
- show_assignments(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-assignments"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_assignments(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-guards"))
- {
- irep_idt function=cmdline.get_value("function");
- show_guards(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-guards"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_guards(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-value-sets"))
- {
- irep_idt function=cmdline.get_value("function");
- show_value_sets(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-value-sets"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_value_sets(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-invariants"))
- {
- options.set_option("show-invariants", true);
- }
+ if(cmdline.isset("show-invariants"))
+ {
+ options.set_option("show-invariants", true);
+ }
#if IGNORE_RECURSION
- if(recursion_detected)
- {
- status() << "Recursion not supported" << eom;
- report_unknown();
- return 5;
- }
+ if(recursion_detected)
+ {
+ status() << "Recursion not supported" << eom;
+ report_unknown();
+ return 5;
+ }
#endif
#if IGNORE_THREADS
- if(threads_detected)
- {
- status() << "Threads not supported" << eom;
- report_unknown();
- return 5;
- }
+ if(threads_detected)
+ {
+ status() << "Threads not supported" << eom;
+ report_unknown();
+ return 5;
+ }
#endif
- if(cmdline.isset("context-sensitive"))
- {
- options.set_option("context-sensitive", true);
- status() << "Context-sensitive analysis from " <<
- goto_model.goto_functions.entry_point() << eom;
- }
+ if(cmdline.isset("context-sensitive"))
+ {
+ options.set_option("context-sensitive", true);
+ status() << "Context-sensitive analysis from " <<
+ goto_model.goto_functions.entry_point() << eom;
+ }
- if(cmdline.isset("arrays"))
- {
- options.set_option("arrays", true);
- status() << "Do not ignore array contents" << eom;
- }
+ if(cmdline.isset("arrays"))
+ {
+ options.set_option("arrays", true);
+ status() << "Do not ignore array contents" << eom;
+ }
- // TODO: check option inconsistencies, ignored options etc
- if(options.get_bool_option("havoc"))
- status() << "Havocking loops and function calls" << eom;
- else if(options.get_bool_option("equalities"))
- status() << "Using (dis)equalities domain" << eom;
- else
- {
- if(options.get_bool_option("intervals"))
- status() << "Using intervals domain";
- else if(options.get_bool_option("zones"))
- status() << "Using zones domain";
- else if(options.get_bool_option("octagons"))
- status() << "Using octagons domain";
+ // TODO: check option inconsistencies, ignored options etc
+ if(options.get_bool_option("havoc"))
+ status() << "Havocking loops and function calls" << eom;
+ else if(options.get_bool_option("equalities"))
+ status() << "Using (dis)equalities domain" << eom;
else
- assert(false);
+ {
+ if(options.get_bool_option("intervals"))
+ status() << "Using intervals domain";
+ else if(options.get_bool_option("zones"))
+ status() << "Using zones domain";
+ else if(options.get_bool_option("octagons"))
+ status() << "Using octagons domain";
+ else
+ assert(false);
- if(options.get_bool_option("enum-solver"))
- status() << " with enumeration solver";
- else if(options.get_bool_option("binsearch-solver"))
- status() << " with binary search solver";
- else
- assert(false);
+ if(options.get_bool_option("enum-solver"))
+ status() << " with enumeration solver";
+ else if(options.get_bool_option("binsearch-solver"))
+ status() << " with binary search solver";
+ else
+ assert(false);
- status() << eom;
- }
+ status() << eom;
+ }
- try
- {
std::unique_ptr checker;
if(!options.get_bool_option("k-induction") &&
- !options.get_bool_option("incremental-bmc"))
+ !options.get_bool_option("incremental-bmc") &&
+ !options.get_bool_option("bmc"))
checker=std::unique_ptr(
new summary_checker_ait(options));
if(options.get_bool_option("k-induction") &&
- !options.get_bool_option("incremental-bmc"))
+ !options.get_bool_option("incremental-bmc") &&
+ !options.get_bool_option("bmc"))
checker=std::unique_ptr(
new summary_checker_kindt(options));
if(!options.get_bool_option("k-induction") &&
- options.get_bool_option("incremental-bmc"))
+ (options.get_bool_option("incremental-bmc") ||
+ options.get_bool_option("bmc")))
checker=std::unique_ptr(
new summary_checker_bmct(options));
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index d564b1279..b332b216a 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -48,7 +48,7 @@ class optionst;
"(show-locs)(show-vcc)(show-properties)(show-trace)(show-stats)" \
"(show-goto-functions)(show-guards)(show-defs)(show-ssa)(show-assignments)" \
"(show-invariants)(std-invariants)" \
- "(property):(all-properties)(k-induction)(incremental-bmc)" \
+ "(property):(all-properties)(k-induction)(incremental-bmc)(bmc)" \
"(no-spurious-check)(all-functions)" \
"(no-simplify)(no-fixed-point)" \
"(graphml-witness):(json-cex):" \
diff --git a/src/2ls/cover_goals_ext.h b/src/2ls/cover_goals_ext.h
index d777a8a66..a0e9fb3c1 100644
--- a/src/2ls/cover_goals_ext.h
+++ b/src/2ls/cover_goals_ext.h
@@ -52,7 +52,8 @@ class cover_goals_extt:public messaget
incremental_solvert &_solver,
const exprt::operandst& _loophead_selects,
property_checkert::property_mapt &_property_map,
- bool _spurious_check, bool _all_properties,
+ bool _spurious_check,
+ bool _all_properties,
bool _build_error_trace):
SSA(_SSA),
solver(_solver),
diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp
index c910b184c..4ff792162 100644
--- a/src/2ls/summary_checker_base.cpp
+++ b/src/2ls/summary_checker_base.cpp
@@ -243,10 +243,13 @@ void summary_checker_baset::check_properties(
is_fully_unwound(loop_continues, loophead_selects, solver);
status() << "Loops " << (fully_unwound ? "" : "not ")
<< "fully unwound" << eom;
-
+
+ bool require_spurious_check=
+ !fully_unwound && options.get_bool_option("spurious-check");
+
cover_goals_extt cover_goals(
SSA, solver, loophead_selects, property_map,
- !fully_unwound && options.get_bool_option("spurious-check"),
+ require_spurious_check,
all_properties,
options.get_bool_option("show-trace") ||
options.get_option("graphml-witness")!="" ||
@@ -330,7 +333,10 @@ void summary_checker_baset::check_properties(
// set all non-covered goals to PASS except if we do not try
// to cover all goals and we have found a FAIL
- if(all_properties || cover_goals.number_covered()==0)
+ if(all_properties &&
+ (fully_unwound ||
+ (!options.get_bool_option("bmc") &&
+ !options.get_bool_option("incremental-bmc"))))
{
std::list::const_iterator g_it=
cover_goals.goals.begin();
diff --git a/src/2ls/summary_checker_bmc.cpp b/src/2ls/summary_checker_bmc.cpp
index 38e9e925e..afa1ffd0b 100644
--- a/src/2ls/summary_checker_bmc.cpp
+++ b/src/2ls/summary_checker_bmc.cpp
@@ -31,11 +31,12 @@ property_checkert::resultt summary_checker_bmct::operator()(
ssa_unwinder.init(false, true);
property_checkert::resultt result=property_checkert::UNKNOWN;
+ unsigned min_unwind=options.get_unsigned_int_option("unwind-min");
unsigned max_unwind=options.get_unsigned_int_option("unwind");
status() << "Max-unwind is " << max_unwind << eom;
ssa_unwinder.init_localunwinders();
- for(unsigned unwind=0; unwind<=max_unwind; unwind++)
+ for(unsigned unwind=min_unwind; unwind<=max_unwind; unwind++)
{
status() << "Unwinding (k=" << unwind << ")" << messaget::eom;
summary_db.mark_recompute_all();
@@ -43,13 +44,13 @@ property_checkert::resultt summary_checker_bmct::operator()(
result=check_properties();
if(result==property_checkert::PASS)
{
- status() << "incremental BMC proof found after "
+ status() << "BMC proof found after "
<< unwind << " unwinding(s)" << messaget::eom;
break;
}
else if(result==property_checkert::FAIL)
{
- status() << "incremental BMC counterexample found after "
+ status() << "BMC counterexample found after "
<< unwind << " unwinding(s)" << messaget::eom;
break;
}
From aac26ff96b14c2963a4faeed874d447479101afd Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Tue, 25 Jul 2017 14:20:43 +0200
Subject: [PATCH 004/322] Rename --show-trace to --trace
---
src/2ls/2ls_parse_options.cpp | 7 ++++---
src/2ls/2ls_parse_options.h | 2 +-
src/2ls/summary_checker_base.cpp | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index 3426fbd14..d6ca3731e 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -343,8 +343,8 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
}
#endif
- if(cmdline.isset("show-trace"))
- options.set_option("show-trace", true);
+ if(cmdline.isset("trace"))
+ options.set_option("trace", true);
if(cmdline.isset("graphml-witness"))
options.set_option("graphml-witness", cmdline.get_value("graphml-witness"));
if(cmdline.isset("json-cex"))
@@ -1241,7 +1241,7 @@ void twols_parse_optionst::report_properties(
<< eom;
}
- if(cmdline.isset("show-trace") &&
+ if(cmdline.isset("trace") &&
it->second.result==property_checkert::FAIL)
show_counterexample(goto_model, it->second.error_trace);
if(cmdline.isset("json-cex") &&
@@ -1604,6 +1604,7 @@ void twols_parse_optionst::help()
"Backend options:\n"
" --all-functions check each function as entry point\n"
" --stop-on-fail stop on first failing assertion\n"
+ " --trace give a counterexample trace for failed properties\n" //NOLINT(*)
" --context-sensitive context-sensitive analysis from entry point\n" // NOLINT(*)
" --termination compute ranking functions to prove termination\n" // NOLINT(*)
" --k-induction use k-induction\n"
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index b332b216a..80eae0b4e 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -45,7 +45,7 @@ class optionst;
"(lexicographic-ranking-function):(monolithic-ranking-function)" \
"(max-inner-ranking-iterations):" \
"(preconditions)(sufficient)" \
- "(show-locs)(show-vcc)(show-properties)(show-trace)(show-stats)" \
+ "(show-locs)(show-vcc)(show-properties)(trace)(show-stats)" \
"(show-goto-functions)(show-guards)(show-defs)(show-ssa)(show-assignments)" \
"(show-invariants)(std-invariants)" \
"(property):(all-properties)(k-induction)(incremental-bmc)(bmc)" \
diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp
index 4ff792162..4915111d4 100644
--- a/src/2ls/summary_checker_base.cpp
+++ b/src/2ls/summary_checker_base.cpp
@@ -251,7 +251,7 @@ void summary_checker_baset::check_properties(
SSA, solver, loophead_selects, property_map,
require_spurious_check,
all_properties,
- options.get_bool_option("show-trace") ||
+ options.get_bool_option("trace") ||
options.get_option("graphml-witness")!="" ||
options.get_option("json-cex")!="");
From 905cde1836948edddd209773a17e78ee4ace93df Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sun, 29 Oct 2017 12:28:51 +0000
Subject: [PATCH 005/322] Remove --bmc option
---
src/2ls/2ls_parse_options.cpp | 249 ++++++++++++++-----------------
src/2ls/2ls_parse_options.h | 2 +-
src/2ls/summary_checker_base.cpp | 12 +-
src/2ls/summary_checker_bmc.cpp | 7 +-
4 files changed, 119 insertions(+), 151 deletions(-)
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index d6ca3731e..8859ea604 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -141,15 +141,7 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("unwindset", cmdline.get_value("unwindset"));
if(cmdline.isset("unwind"))
- {
options.set_option("unwind", cmdline.get_value("unwind"));
- options.set_option("unwind-min", cmdline.get_value("unwind"));
- }
- else
- {
- options.set_option("unwind", 0);
- options.set_option("unwind-min", 0);
- }
if(cmdline.isset("inline-partial"))
options.set_option("inline-partial", cmdline.get_value("inline-partial"));
@@ -271,9 +263,7 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("k-induction", true);
options.set_option("inline", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", std::numeric_limits::max());
- else
- options.set_option("unwind-min", 0);
+ options.set_option("unwind", UINT_MAX);
}
// do incremental bmc
@@ -283,19 +273,7 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("inline", true);
options.set_option("havoc", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", std::numeric_limits::max());
- else
- options.set_option("unwind-min", 0);
- }
-
- // do bmc
- if(cmdline.isset("bmc"))
- {
- options.set_option("bmc", true);
- options.set_option("inline", true);
- options.set_option("havoc", true);
- if(!cmdline.isset("unwind"))
- throw "--bmc only possible with --unwind";
+ options.set_option("unwind", UINT_MAX);
}
// check for spuriousness of assertion failures
@@ -365,156 +343,153 @@ Function: twols_parse_optionst::doit
int twols_parse_optionst::doit()
{
- try
+ if(cmdline.isset("version"))
{
- if(cmdline.isset("version"))
- {
- std::cout << TWOLS_VERSION << std::endl;
- return 0;
- }
+ std::cout << TWOLS_VERSION << std::endl;
+ return 0;
+ }
- //
- // command line options
- //
+ //
+ // command line options
+ //
- optionst options;
- get_command_line_options(options);
+ optionst options;
+ get_command_line_options(options);
- eval_verbosity();
+ eval_verbosity();
- //
- // Print a banner
- //
- status() << "2LS version " TWOLS_VERSION " (based on CBMC " CBMC_VERSION ")"
- << eom;
+ //
+ // Print a banner
+ //
+ status() << "2LS version " TWOLS_VERSION " (based on CBMC " CBMC_VERSION ")"
+ << eom;
- goto_modelt goto_model;
+ goto_modelt goto_model;
- register_languages();
+ register_languages();
- if(get_goto_program(options, goto_model))
- return 6;
+ if(get_goto_program(options, goto_model))
+ return 6;
- if(cmdline.isset("show-stats"))
- {
- show_stats(goto_model, std::cout);
- return 7;
- }
+ if(cmdline.isset("show-stats"))
+ {
+ show_stats(goto_model, std::cout);
+ return 7;
+ }
- // options for various debug outputs
+ // options for various debug outputs
- if(cmdline.isset("show-ssa"))
- {
- bool simplify=!cmdline.isset("no-simplify");
- irep_idt function=cmdline.get_value("function");
- show_ssa(goto_model, function, simplify, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-ssa"))
+ {
+ bool simplify=!cmdline.isset("no-simplify");
+ irep_idt function=cmdline.get_value("function");
+ show_ssa(goto_model, function, simplify, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-defs"))
- {
- irep_idt function=cmdline.get_value("function");
- show_defs(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-defs"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_defs(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-assignments"))
- {
- irep_idt function=cmdline.get_value("function");
- show_assignments(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-assignments"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_assignments(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-guards"))
- {
- irep_idt function=cmdline.get_value("function");
- show_guards(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-guards"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_guards(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-value-sets"))
- {
- irep_idt function=cmdline.get_value("function");
- show_value_sets(goto_model, function, std::cout, ui_message_handler);
- return 7;
- }
+ if(cmdline.isset("show-value-sets"))
+ {
+ irep_idt function=cmdline.get_value("function");
+ show_value_sets(goto_model, function, std::cout, ui_message_handler);
+ return 7;
+ }
- if(cmdline.isset("show-invariants"))
- {
- options.set_option("show-invariants", true);
- }
+ if(cmdline.isset("show-invariants"))
+ {
+ options.set_option("show-invariants", true);
+ }
#if IGNORE_RECURSION
- if(recursion_detected)
- {
- status() << "Recursion not supported" << eom;
- report_unknown();
- return 5;
- }
+ if(recursion_detected)
+ {
+ status() << "Recursion not supported" << eom;
+ report_unknown();
+ return 5;
+ }
#endif
#if IGNORE_THREADS
- if(threads_detected)
- {
- status() << "Threads not supported" << eom;
- report_unknown();
- return 5;
- }
+ if(threads_detected)
+ {
+ status() << "Threads not supported" << eom;
+ report_unknown();
+ return 5;
+ }
#endif
- if(cmdline.isset("context-sensitive"))
- {
- options.set_option("context-sensitive", true);
- status() << "Context-sensitive analysis from " <<
- goto_model.goto_functions.entry_point() << eom;
- }
+ if(cmdline.isset("context-sensitive"))
+ {
+ options.set_option("context-sensitive", true);
+ status() << "Context-sensitive analysis from " <<
+ goto_model.goto_functions.entry_point() << eom;
+ }
- if(cmdline.isset("arrays"))
- {
- options.set_option("arrays", true);
- status() << "Do not ignore array contents" << eom;
- }
+ if(cmdline.isset("arrays"))
+ {
+ options.set_option("arrays", true);
+ status() << "Do not ignore array contents" << eom;
+ }
- // TODO: check option inconsistencies, ignored options etc
- if(options.get_bool_option("havoc"))
- status() << "Havocking loops and function calls" << eom;
- else if(options.get_bool_option("equalities"))
- status() << "Using (dis)equalities domain" << eom;
+ // TODO: check option inconsistencies, ignored options etc
+ if(options.get_bool_option("havoc"))
+ status() << "Havocking loops and function calls" << eom;
+ else if(options.get_bool_option("equalities"))
+ status() << "Using (dis)equalities domain" << eom;
+ else
+ {
+ if(options.get_bool_option("intervals"))
+ status() << "Using intervals domain";
+ else if(options.get_bool_option("zones"))
+ status() << "Using zones domain";
+ else if(options.get_bool_option("octagons"))
+ status() << "Using octagons domain";
else
- {
- if(options.get_bool_option("intervals"))
- status() << "Using intervals domain";
- else if(options.get_bool_option("zones"))
- status() << "Using zones domain";
- else if(options.get_bool_option("octagons"))
- status() << "Using octagons domain";
- else
- assert(false);
+ assert(false);
- if(options.get_bool_option("enum-solver"))
- status() << " with enumeration solver";
- else if(options.get_bool_option("binsearch-solver"))
- status() << " with binary search solver";
- else
- assert(false);
+ if(options.get_bool_option("enum-solver"))
+ status() << " with enumeration solver";
+ else if(options.get_bool_option("binsearch-solver"))
+ status() << " with binary search solver";
+ else
+ assert(false);
- status() << eom;
- }
+ status() << eom;
+ }
+ try
+ {
std::unique_ptr checker;
if(!options.get_bool_option("k-induction") &&
- !options.get_bool_option("incremental-bmc") &&
- !options.get_bool_option("bmc"))
+ !options.get_bool_option("incremental-bmc"))
checker=std::unique_ptr(
new summary_checker_ait(options));
if(options.get_bool_option("k-induction") &&
- !options.get_bool_option("incremental-bmc") &&
- !options.get_bool_option("bmc"))
+ !options.get_bool_option("incremental-bmc"))
checker=std::unique_ptr(
new summary_checker_kindt(options));
if(!options.get_bool_option("k-induction") &&
- (options.get_bool_option("incremental-bmc") ||
- options.get_bool_option("bmc")))
+ options.get_bool_option("incremental-bmc"))
checker=std::unique_ptr(
new summary_checker_bmct(options));
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index 80eae0b4e..0a42e12f9 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -48,7 +48,7 @@ class optionst;
"(show-locs)(show-vcc)(show-properties)(trace)(show-stats)" \
"(show-goto-functions)(show-guards)(show-defs)(show-ssa)(show-assignments)" \
"(show-invariants)(std-invariants)" \
- "(property):(all-properties)(k-induction)(incremental-bmc)(bmc)" \
+ "(property):(all-properties)(k-induction)(incremental-bmc)" \
"(no-spurious-check)(all-functions)" \
"(no-simplify)(no-fixed-point)" \
"(graphml-witness):(json-cex):" \
diff --git a/src/2ls/summary_checker_base.cpp b/src/2ls/summary_checker_base.cpp
index 4915111d4..0274201e4 100644
--- a/src/2ls/summary_checker_base.cpp
+++ b/src/2ls/summary_checker_base.cpp
@@ -243,13 +243,10 @@ void summary_checker_baset::check_properties(
is_fully_unwound(loop_continues, loophead_selects, solver);
status() << "Loops " << (fully_unwound ? "" : "not ")
<< "fully unwound" << eom;
-
- bool require_spurious_check=
- !fully_unwound && options.get_bool_option("spurious-check");
-
+
cover_goals_extt cover_goals(
SSA, solver, loophead_selects, property_map,
- require_spurious_check,
+ !fully_unwound && options.get_bool_option("spurious-check"),
all_properties,
options.get_bool_option("trace") ||
options.get_option("graphml-witness")!="" ||
@@ -333,10 +330,7 @@ void summary_checker_baset::check_properties(
// set all non-covered goals to PASS except if we do not try
// to cover all goals and we have found a FAIL
- if(all_properties &&
- (fully_unwound ||
- (!options.get_bool_option("bmc") &&
- !options.get_bool_option("incremental-bmc"))))
+ if(all_properties || cover_goals.number_covered()==0)
{
std::list::const_iterator g_it=
cover_goals.goals.begin();
diff --git a/src/2ls/summary_checker_bmc.cpp b/src/2ls/summary_checker_bmc.cpp
index afa1ffd0b..38e9e925e 100644
--- a/src/2ls/summary_checker_bmc.cpp
+++ b/src/2ls/summary_checker_bmc.cpp
@@ -31,12 +31,11 @@ property_checkert::resultt summary_checker_bmct::operator()(
ssa_unwinder.init(false, true);
property_checkert::resultt result=property_checkert::UNKNOWN;
- unsigned min_unwind=options.get_unsigned_int_option("unwind-min");
unsigned max_unwind=options.get_unsigned_int_option("unwind");
status() << "Max-unwind is " << max_unwind << eom;
ssa_unwinder.init_localunwinders();
- for(unsigned unwind=min_unwind; unwind<=max_unwind; unwind++)
+ for(unsigned unwind=0; unwind<=max_unwind; unwind++)
{
status() << "Unwinding (k=" << unwind << ")" << messaget::eom;
summary_db.mark_recompute_all();
@@ -44,13 +43,13 @@ property_checkert::resultt summary_checker_bmct::operator()(
result=check_properties();
if(result==property_checkert::PASS)
{
- status() << "BMC proof found after "
+ status() << "incremental BMC proof found after "
<< unwind << " unwinding(s)" << messaget::eom;
break;
}
else if(result==property_checkert::FAIL)
{
- status() << "BMC counterexample found after "
+ status() << "incremental BMC counterexample found after "
<< unwind << " unwinding(s)" << messaget::eom;
break;
}
From 4edea2dd2cc32e27e1af3833dcad20ab44928572 Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sat, 4 Nov 2017 17:10:04 +0000
Subject: [PATCH 006/322] Improve Readme file
---
README.md | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 113 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index aa46ece57..5b9e4c352 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
About
=====
-2LS is a verification tool for C programs. It is built upon the
+2LS ("tools") is a verification tool for C programs. It is built upon the
CPROVER framework ([cprover.org](http://www.cprover.org)), which
supports C89, C99, most of C11 and most compiler extensions provided
by gcc and Visual Studio. It allows verifying array bounds (buffer
@@ -11,7 +11,6 @@ overflows), pointer safety, exceptions, user-specified assertions, and
termination properties. The analysis is performed by template-based
predicate synthesis and abstraction refinements techniques.
-For more information see [cprover.org](http://www.cprover.org/2LS).
License
=======
@@ -19,3 +18,115 @@ License
[build_img]: https://travis-ci.org/diffblue/2ls.svg?branch=master
[travis]: https://travis-ci.org/diffblue/2ls
+
+
+Overview
+========
+
+ 2LS reduces program analysis problems expressed in second order logic
+ such as invariant or ranking function inference to synthesis problems
+ over templates. Hence, it reduces (an existential fragment of) 2nd
+ order Logic Solving to quantifier elimination in first order logic.
+
+The current tool has following capabilities:
+
+* function-modular interprocedural analysis of C code based on summaries
+* summary and invariant inference using generic templates
+* combined k-induction and invariant inference
+* function-modular termination analysis
+
+Releases
+========
+
+Download using `git clone http://github.com/diffblue/2ls; cd 2ls; git checkout 2ls-x.y`
+
+* [2LS 0.5](http://github.com/diffblue/2ls/releases/tag/2ls-0.5) (01/2017)
+* [2LS 0.4](http://github.com/diffblue/2ls/releases/tag/2ls-0.4) (08/2016)
+* [2LS 0.3](http://svn.cprover.org/svn/deltacheck/releases/2ls-0.3) (08/2015)
+* [2LS 0.2](http://svn.cprover.org/svn/deltacheck/releases/2ls-0.2) (06/2015)
+* [2LS 0.1](http://svn.cprover.org/svn/deltacheck/releases/2ls-0.1) (11/2014)
+
+Software Verification Competition Contributions
+
+* [SV-COMP 2017](http://github.com/diffblue/2ls/releases/tag/2ls-0.5-sv-comp-2017) (01/2017)
+* [SV-COMP 2016](http://svn.cprover.org/svn/deltacheck/releases/2ls-0.3-sv-comp-2016) (11/2015) [Follow these instructions](http://www.cprover.org/2LS/2ls-sv-comp-2016.pdf)
+
+Installation
+============
+
+`cd 2ls; ./install.h`
+
+ Run `src/2ls/2ls`
+
+Command line options
+====================
+
+The default abstract domain are intervals. If no options are given a context-insensitive interprocedural analysis is performed. For context-sensitivity, add --context-sensitive.
+
+Other analyses include:
+
+* BMC: --inline --havoc --unwind n
+* Incremental BMC: --incremental-bmc
+* Incremental k-induction: --havoc --k-induction
+* Incremental k-induction and k-invariants (kIkI): --k-induction
+* Intraprocedural abstract interpretation with property checks: --inline
+* Necessary preconditions: --preconditions
+* Sufficient preconditions: --preconditions --sufficient
+
+Currently the following abstract domains are available:
+
+* Intervals (default): --intervals
+* Zones: --zones
+* Octagons --octagons
+* Equalities/disequalities: --equalities
+* The abstract domain consisting of the Top element: --havoc
+
+Interprocedural Termination Analysis
+====================================
+
+Is supported by release 0.1 and >=0.3.
+
+* Universal termination: --termination
+* Context-sensitive universal termination: --termination --context-sensitive
+* Sufficient preconditions for termination --termination --context-sensitive --preconditions
+
+Features in development
+=======================
+
+* ACDL solver (ATVA'17 [Lifting CDCL to Template-Based Abstract Domains for Program Verification](https://doi.org/10.1007/978-3-319-68167-2_2))
+* abstract heap domain
+* nontermination analysis
+* custom template specifications
+* modular refinement
+* template refinement
+* thread-modular analysis
+
+Publications
+============
+
+* TACAS'16 [2LS for Program Analysis](http://dl.acm.org/citation.cfm?id=2945506)
+* SAS'15 [Safety Verification and Refutation by k-Invariants and k-Induction](http://link.springer.com/chapter/10.1007%2F978-3-662-48288-9_9)
+* ASE'15 [Synthesising Interprocedural Bit-Precise Termination Proofs](http://dl.acm.org/citation.cfm?id=2916211) [Experimental log](http://www.cs.ox.ac.uk/people/peter.schrammel/2ls/ase15-experimental_results_log.txt) [Additional material](http://www.cs.ox.ac.uk/people/peter.schrammel/2ls/ase15-additional-material.tgz) [Website](http://www.cprover.org/termination/modular)
+
+Contributors
+============
+
+* Björn Wachter
+* Cristina David
+* Daniel Kroening
+* Hongyi Chen
+* Madhukar Kumar
+* Martin Brain
+* Peter Schrammel
+* Rajdeep Mukherjee
+* Samuel Bücheli
+* Saurabh Joshi
+* Stefan Marticek
+* Viktor Malik
+
+Contact
+=======
+
+[Peter Schrammel](http://www.schrammel.it)
+
+
From c92a3c1ac6fdba4d33c86132f3dc9fba31c534ea Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Fri, 3 Nov 2017 23:23:08 +0000
Subject: [PATCH 007/322] Add ssa_var_collector
Author: Stefan Marticek
---
src/ssa/Makefile | 2 +-
src/ssa/ssa_var_collector.cpp | 245 ++++++++++++++++++++++++++++++++++
src/ssa/ssa_var_collector.h | 79 +++++++++++
3 files changed, 325 insertions(+), 1 deletion(-)
create mode 100644 src/ssa/ssa_var_collector.cpp
create mode 100644 src/ssa/ssa_var_collector.h
diff --git a/src/ssa/Makefile b/src/ssa/Makefile
index 0c4c0263f..f66679938 100644
--- a/src/ssa/Makefile
+++ b/src/ssa/Makefile
@@ -1,4 +1,4 @@
-SRC = local_ssa.cpp \
+SRC = local_ssa.cpp ssa_var_collector.cpp \
ssa_domain.cpp translate_union_member.cpp malloc_ssa.cpp \
guard_map.cpp ssa_object.cpp assignments.cpp ssa_dereference.cpp \
ssa_value_set.cpp address_canonizer.cpp simplify_ssa.cpp \
diff --git a/src/ssa/ssa_var_collector.cpp b/src/ssa/ssa_var_collector.cpp
new file mode 100644
index 000000000..7bf67d28a
--- /dev/null
+++ b/src/ssa/ssa_var_collector.cpp
@@ -0,0 +1,245 @@
+/*******************************************************************\
+
+Module: Template Generator for Summaries, Invariants and Preconditions
+
+Author: Peter Schrammel, Stefan Marticek
+
+\*******************************************************************/
+
+#include "ssa_var_collector.h"
+
+/*******************************************************************\
+
+Function: template_generator_baset::add_var
+
+ Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void ssa_var_collectort::add_var(
+ const domaint::vart &var,
+ const domaint::guardt &pre_guard,
+ domaint::guardt post_guard,
+ const domaint::kindt &kind,
+ domaint::var_specst &var_specs)
+{
+ exprt aux_expr=true_exprt();
+ if(std_invariants && pre_guard.id()==ID_and)
+ {
+ exprt init_guard=and_exprt(pre_guard.op0(), not_exprt(pre_guard.op1()));
+ exprt post_var=post_renaming_map[var];
+ exprt aux_var=aux_renaming_map[var];
+ exprt aux_equals_post=equal_exprt(aux_var, post_var);
+ exprt aux_equals_init=equal_exprt(aux_var, init_renaming_map[var]);
+ aux_expr=
+ and_exprt(
+ implies_exprt(
+ and_exprt(post_guard, not_exprt(init_guard)),
+ aux_equals_post),
+ implies_exprt(
+ init_guard,
+ aux_equals_init));
+ post_guard=or_exprt(post_guard, init_guard);
+ }
+ if(var.type().id()!=ID_array)
+ {
+ var_specs.push_back(domaint::var_spect());
+ domaint::var_spect &var_spec=var_specs.back();
+ var_spec.pre_guard=pre_guard;
+ var_spec.post_guard=post_guard;
+ var_spec.aux_expr=aux_expr;
+ var_spec.kind=kind;
+ var_spec.var=var;
+ }
+
+ // arrays
+ if(var.type().id()==ID_array && options.get_bool_option("arrays"))
+ {
+ const array_typet &array_type=to_array_type(var.type());
+ mp_integer size;
+ to_integer(array_type.size(), size);
+ for(mp_integer i=0; ilocation->location_number << std::endl;
+ assert(n_it->loophead!=SSA.nodes.end());
+ std::cout << "pre-location: "
+ << n_it->loophead->location->location_number << std::endl;
+#endif
+ exprt lhguard=SSA.guard_symbol(n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(lhguard), *n_it, true);
+ exprt lsguard=
+ SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(lsguard), *n_it, true);
+ pre_guard=and_exprt(lhguard, lsguard);
+
+ exprt pguard=SSA.guard_symbol(n_it->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(pguard), *n_it, false);
+ exprt pcond=SSA.cond_symbol(n_it->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(pcond), *n_it, false);
+ post_guard=and_exprt(pguard, pcond);
+}
+
+/*******************************************************************\
+
+Function: template_generator_baset::get_pre_var
+
+ Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void ssa_var_collectort::get_pre_var(
+ const local_SSAt &SSA,
+ local_SSAt::objectst::const_iterator o_it,
+ local_SSAt::nodest::const_iterator n_it,
+ symbol_exprt &pre_var)
+{
+ pre_var=SSA.name(*o_it, local_SSAt::LOOP_BACK, n_it->location);
+ ssa_local_unwinder.unwinder_rename(pre_var, *n_it, true);
+
+ symbol_exprt post_var=SSA.read_rhs(*o_it, n_it->location);
+ ssa_local_unwinder.unwinder_rename(post_var, *n_it, false);
+ post_renaming_map[pre_var]=post_var;
+
+ rename_aux_post(post_var);
+ aux_renaming_map[pre_var]=post_var;
+}
+
+/*******************************************************************\
+
+Function: template_generator_baset::get_init_expr
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: supposes that loop head PHIs are of the form
+ xphi=gls?xlb:x0
+
+\*******************************************************************/
+
+void ssa_var_collectort::get_init_expr(
+ const local_SSAt &SSA,
+ local_SSAt::objectst::const_iterator o_it,
+ local_SSAt::nodest::const_iterator n_it,
+ exprt &init_expr)
+{
+ symbol_exprt phi_var=
+ SSA.name(*o_it, local_SSAt::PHI, n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(phi_var, *n_it->loophead, true);
+ for(local_SSAt::nodet::equalitiest::const_iterator e_it=
+ n_it->loophead->equalities.begin();
+ e_it!=n_it->loophead->equalities.end(); e_it++)
+ {
+ if(e_it->rhs().id()==ID_if &&
+ to_symbol_expr(e_it->lhs()).get_identifier()==phi_var.get_identifier())
+ {
+ const if_exprt &if_expr=to_if_expr(e_it->rhs());
+ init_expr=if_expr.false_case();
+ // should already be renamed for inner loops
+ break;
+ }
+ }
+
+ symbol_exprt pre_var=SSA.name(*o_it, local_SSAt::LOOP_BACK, n_it->location);
+ ssa_local_unwinder.unwinder_rename(pre_var, *n_it, true);
+ init_renaming_map[pre_var]=init_expr;
+}
+
+/*******************************************************************\
+
+Function: ssa_var_collectort::collect_variables_loop
+
+ Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+void ssa_var_collectort::collect_variables_loop(
+ const local_SSAt &SSA,
+ bool forward)
+{
+ // used for renaming map
+ var_listt pre_state_vars, post_state_vars;
+
+ // add loop variables
+ for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
+ n_it!=SSA.nodes.end(); n_it++)
+ {
+ if(n_it->loophead!=SSA.nodes.end()) // we've found a loop
+ {
+ exprt pre_guard, post_guard;
+ get_pre_post_guards(SSA, n_it, pre_guard, post_guard);
+
+ const ssa_domaint::phi_nodest &phi_nodes=
+ SSA.ssa_analysis[n_it->loophead->location].phi_nodes;
+
+ // Record the objects modified by the loop to get
+ // 'primed' (post-state) and 'unprimed' (pre-state) variables.
+ for(local_SSAt::objectst::const_iterator
+ o_it=SSA.ssa_objects.objects.begin();
+ o_it!=SSA.ssa_objects.objects.end();
+ o_it++)
+ {
+ ssa_domaint::phi_nodest::const_iterator p_it=
+ phi_nodes.find(o_it->get_identifier());
+
+ if(p_it==phi_nodes.end())
+ continue; // object not modified in this loop
+
+ symbol_exprt pre_var;
+ get_pre_var(SSA, o_it, n_it, pre_var);
+ exprt init_expr;
+ get_init_expr(SSA, o_it, n_it, init_expr);
+ add_var(pre_var, pre_guard, post_guard, domaint::LOOP, var_specs);
+
+#ifdef DEBUG
+ std::cout << "Adding " << from_expr(ns, "", in) << " "
+ << from_expr(ns, "", out) << std::endl;
+#endif
+ }
+ }
+ }
+}
diff --git a/src/ssa/ssa_var_collector.h b/src/ssa/ssa_var_collector.h
new file mode 100644
index 000000000..1c69981aa
--- /dev/null
+++ b/src/ssa/ssa_var_collector.h
@@ -0,0 +1,79 @@
+/*******************************************************************\
+
+Module: SSA var collector class
+
+Author: Peter Schrammel, Stefan Marticek
+
+\*******************************************************************/
+
+#ifndef CPROVER_2LS_SSA_SSA_VAR_COLLECTOR_H
+#define CPROVER_2LS_SSA_SSA_VAR_COLLECTOR_H
+
+#include
+
+#include "local_ssa.h"
+#include "ssa_unwinder.h"
+
+#include
+
+class ssa_var_collectort
+{
+public:
+ typedef strategy_solver_baset::var_listt var_listt;
+
+ explicit ssa_var_collectort(
+ optionst &_options,
+ ssa_local_unwindert &_ssa_local_unwinder):
+ options(_options),
+ ssa_local_unwinder(_ssa_local_unwinder)
+ {
+ std_invariants=options.get_bool_option("std-invariants");
+ }
+
+ domaint::var_specst var_specs;
+ replace_mapt post_renaming_map;
+ replace_mapt init_renaming_map;
+ replace_mapt aux_renaming_map;
+
+ optionst options; // copy: we may override options
+
+ void add_var(
+ const domaint::vart &var_to_add,
+ const domaint::guardt &pre_guard,
+ domaint::guardt post_guard,
+ const domaint::kindt &kind,
+ domaint::var_specst &var_specs);
+
+ void get_pre_post_guards(
+ const local_SSAt &SSA,
+ local_SSAt::nodest::const_iterator n_it,
+ exprt &pre_guard,
+ exprt &post_guard);
+
+ void get_pre_var(
+ const local_SSAt &SSA,
+ local_SSAt::objectst::const_iterator o_it,
+ local_SSAt::nodest::const_iterator n_it,
+ symbol_exprt &pre_var);
+
+ void get_init_expr(
+ const local_SSAt &SSA,
+ local_SSAt::objectst::const_iterator o_it,
+ local_SSAt::nodest::const_iterator n_it,
+ exprt &init_expr);
+
+ void rename_aux_post(symbol_exprt &expr)
+ {
+ expr.set_identifier(id2string(expr.get_identifier())+"'");
+ }
+
+ virtual void collect_variables_loop(
+ const local_SSAt &SSA,
+ bool forward);
+
+protected:
+ bool std_invariants; // include value at loop entry
+ const ssa_local_unwindert &ssa_local_unwinder;
+};
+
+#endif // CPROVER_2LS_SSA_SSA_VAR_COLLECTOR_H
From 983b87546a6a2effdc78f378113074683a32b7dd Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sat, 4 Nov 2017 14:44:05 +0000
Subject: [PATCH 008/322] Nontermination checker
Author: Stefan Marticek
---
src/2ls/2ls_parse_options.cpp | 43 +-
src/2ls/2ls_parse_options.h | 2 +-
src/2ls/Makefile | 2 +-
src/2ls/summary_checker_ai.cpp | 7 +-
src/2ls/summary_checker_base.h | 10 +-
src/2ls/summary_checker_nonterm.cpp | 628 ++++++++++++++++++++++++++++
src/2ls/summary_checker_nonterm.h | 34 ++
src/ssa/ssa_build_goto_trace.cpp | 9 +-
8 files changed, 720 insertions(+), 15 deletions(-)
create mode 100644 src/2ls/summary_checker_nonterm.cpp
create mode 100644 src/2ls/summary_checker_nonterm.h
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index 8859ea604..95900d778 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -51,6 +51,7 @@ Author: Daniel Kroening, Peter Schrammel
#include "summary_checker_ai.h"
#include "summary_checker_bmc.h"
#include "summary_checker_kind.h"
+#include "summary_checker_nonterm.h"
#include "show.h"
#include "horn_encoding.h"
@@ -263,7 +264,16 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("k-induction", true);
options.set_option("inline", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", UINT_MAX);
+ options.set_option("unwind", std::numeric_limits::max());
+ }
+
+ // compute singleton recurrence set - simple nontermination
+ if(cmdline.isset("nontermination"))
+ {
+ options.set_option("nontermination", true);
+ options.set_option("inline", true);
+ if(!cmdline.isset("unwind"))
+ options.set_option("unwind", std::numeric_limits::max());
}
// do incremental bmc
@@ -273,7 +283,7 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("inline", true);
options.set_option("havoc", true);
if(!cmdline.isset("unwind"))
- options.set_option("unwind", UINT_MAX);
+ options.set_option("unwind", std::numeric_limits::max());
}
// check for spuriousness of assertion failures
@@ -420,6 +430,20 @@ int twols_parse_optionst::doit()
options.set_option("show-invariants", true);
}
+ if(cmdline.isset("nontermination"))
+ {
+ // turn assertions (from generic checks) into assumptions
+ Forall_goto_functions(f_it, goto_model.goto_functions)
+ {
+ goto_programt &body=f_it->second.body;
+ Forall_goto_program_instructions(i_it, body)
+ {
+ if(i_it->is_assert())
+ i_it->type=goto_program_instruction_typet::ASSUME;
+ }
+ }
+ }
+
#if IGNORE_RECURSION
if(recursion_detected)
{
@@ -492,6 +516,9 @@ int twols_parse_optionst::doit()
options.get_bool_option("incremental-bmc"))
checker=std::unique_ptr(
new summary_checker_bmct(options));
+ if(options.get_bool_option("nontermination"))
+ checker=std::unique_ptr(
+ new summary_checker_nontermt(options));
checker->set_message_handler(get_message_handler());
checker->simplify=!cmdline.isset("no-simplify");
@@ -840,7 +867,7 @@ void twols_parse_optionst::require_entry(
if(goto_model.symbol_table.symbols.find(entry_point)==
symbol_table.symbols.end())
- throw "The program has no entry point; please complete linking";
+ throw "the program has no entry point; please complete linking";
}
/*******************************************************************\
@@ -1014,8 +1041,7 @@ bool twols_parse_optionst::process_goto_program(
try
{
status() << "Function Pointer Removal" << eom;
- remove_function_pointers(
- goto_model, cmdline.isset("pointer-check"));
+ remove_function_pointers(goto_model, cmdline.isset("pointer-check"));
// do partial inlining
if(options.get_bool_option("inline-partial"))
@@ -1047,7 +1073,9 @@ bool twols_parse_optionst::process_goto_program(
status() << "Performing full inlining" << eom;
const namespacet ns(goto_model.symbol_table);
goto_inlinet goto_inline(
- goto_model.goto_functions, ns, ui_message_handler);
+ goto_model.goto_functions,
+ ns,
+ ui_message_handler);
goto_inline();
#if IGNORE_RECURSION
recursion_detected=goto_inline.recursion_detected();
@@ -1204,7 +1232,8 @@ void twols_parse_optionst::report_properties(
xmlt xml_result("result");
xml_result.set_attribute("property", id2string(it->first));
xml_result.set_attribute(
- "status", property_checkert::as_string(it->second.result));
+ "status",
+ property_checkert::as_string(it->second.result));
std::cout << xml_result << "\n";
}
else
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index 0a42e12f9..342b79c21 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -41,7 +41,7 @@ class optionst;
"(string-abstraction)(no-arch)(arch):(floatbv)(fixedbv)" \
"(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \
"(inline)(inline-main)(inline-partial):" \
- "(context-sensitive)(termination)" \
+ "(context-sensitive)(termination)(nontermination)" \
"(lexicographic-ranking-function):(monolithic-ranking-function)" \
"(max-inner-ranking-iterations):" \
"(preconditions)(sufficient)" \
diff --git a/src/2ls/Makefile b/src/2ls/Makefile
index 06b9d4486..5b9362169 100644
--- a/src/2ls/Makefile
+++ b/src/2ls/Makefile
@@ -6,7 +6,7 @@ SRC = 2ls_main.cpp 2ls_parse_options.cpp \
2ls_languages.cpp \
show.cpp summary_checker_base.cpp \
summary_checker_ai.cpp summary_checker_bmc.cpp \
- summary_checker_kind.cpp \
+ summary_checker_kind.cpp summary_checker_nonterm.cpp \
cover_goals_ext.cpp horn_encoding.cpp \
preprocessing_util.cpp \
instrument_goto.cpp dynamic_cfg.cpp \
diff --git a/src/2ls/summary_checker_ai.cpp b/src/2ls/summary_checker_ai.cpp
index 6cda09787..d11a9c6d7 100644
--- a/src/2ls/summary_checker_ai.cpp
+++ b/src/2ls/summary_checker_ai.cpp
@@ -9,7 +9,7 @@ Author: Peter Schrammel
#include "summary_checker_ai.h"
#include
-#define TERM_CEX 1
+#define TERM_CEX 0
/*******************************************************************\
@@ -174,7 +174,12 @@ property_checkert::resultt summary_checker_ait::report_termination()
}
}
#endif
+#if 1
return property_checkert::FAIL;
+#else
+ // rely on nontermination checker to find counterexample
+ return property_checkert::UNKNOWN;
+#endif
}
return property_checkert::UNKNOWN;
}
diff --git a/src/2ls/summary_checker_base.h b/src/2ls/summary_checker_base.h
index d4b1ad0e5..2dfd88bb2 100644
--- a/src/2ls/summary_checker_base.h
+++ b/src/2ls/summary_checker_base.h
@@ -81,16 +81,20 @@ class summary_checker_baset:public property_checkert
bool termination=false);
property_checkert::resultt check_properties();
- void check_properties(
+ virtual void check_properties(
const ssa_dbt::functionst::const_iterator f_it);
exprt::operandst get_loophead_selects(
- const irep_idt &function_name, const local_SSAt &, prop_convt &);
+ const irep_idt &function_name,
+ const local_SSAt &,
+ prop_convt &);
bool is_spurious(
const exprt::operandst& loophead_selects,
incremental_solvert&);
exprt::operandst get_loop_continues(
- const irep_idt &function_name, const local_SSAt &, prop_convt &);
+ const irep_idt &function_name,
+ const local_SSAt &,
+ prop_convt &);
bool is_fully_unwound(
const exprt::operandst& loop_continues,
const exprt::operandst& loophead_selects,
diff --git a/src/2ls/summary_checker_nonterm.cpp b/src/2ls/summary_checker_nonterm.cpp
new file mode 100644
index 000000000..c8166a828
--- /dev/null
+++ b/src/2ls/summary_checker_nonterm.cpp
@@ -0,0 +1,628 @@
+/*******************************************************************\
+
+Module: Summarizer for Nontermination Bit-level analysis
+
+Author: Stefan Marticek
+
+\*******************************************************************/
+
+#include "summary_checker_nonterm.h"
+
+#include
+#include
+#include
+
+#include
+#include <2ls/show.h>
+
+#include
+
+/*******************************************************************\
+
+Function: summary_checker_nontermt::operator()
+
+ Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+property_checkert::resultt summary_checker_nontermt::operator()(
+ const goto_modelt &goto_model)
+{
+ const namespacet ns(goto_model.symbol_table);
+
+ SSA_functions(goto_model, ns);
+
+ ssa_unwinder.init(false, true);
+
+ property_checkert::resultt result=property_checkert::UNKNOWN;
+ unsigned max_unwind=options.get_unsigned_int_option("unwind");
+ status() << "Max-unwind is " << max_unwind << eom;
+ ssa_unwinder.init_localunwinders();
+
+ for(unsigned unwind=1; unwind<=max_unwind; unwind++)
+ {
+ status() << "Unwinding (k=" << unwind << ")" << messaget::eom;
+ ssa_unwinder.unwind_all(unwind);
+ if(unwind==51) // use a different nontermination technique
+ {
+ result=check_nonterm_linear();
+ if(result==property_checkert::PASS)
+ {
+ status() << "Termination proved after "
+ << unwind << " unwinding(s)" << messaget::eom;
+ report_statistics();
+ return result;
+ }
+ else if(result==property_checkert::FAIL)
+ {
+ status() << "Nonterminating program execution proved after "
+ << unwind << " unwinding(s)" << messaget::eom;
+ report_statistics();
+ return result;
+ }
+ }
+ result=summary_checker_baset::check_properties();
+ if(result==property_checkert::PASS)
+ {
+ status() << "Termination proved after "
+ << unwind << " unwinding(s)" << messaget::eom;
+ break;
+ }
+ else if(result==property_checkert::FAIL)
+ {
+ status() << "Nonterminating program execution proved after "
+ << unwind << " unwinding(s)" << messaget::eom;
+ break;
+ }
+ }
+
+ report_statistics();
+ return result;
+}
+
+/*******************************************************************\
+
+Function: summary_checker_baset::check_properties
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: checks the property loop instead of assertion
+
+\*******************************************************************/
+
+void summary_checker_nontermt::check_properties(
+ const ssa_dbt::functionst::const_iterator f_it)
+{
+ unwindable_local_SSAt &SSA=*f_it->second;
+
+ ssa_local_unwindert &ssa_local_unwinder=ssa_unwinder.get(f_it->first);
+
+#if 0
+ SSA.output_verbose(std::cout);
+#endif
+
+ // solver
+ incremental_solvert &solver=ssa_db.get_solver(f_it->first);
+ solver.set_message_handler(get_message_handler());
+
+ // give SSA to solver
+ solver << SSA;
+ SSA.mark_nodes();
+
+ solver.new_context();
+
+ // freeze loop head selects
+ exprt::operandst loophead_selects=
+ get_loophead_selects(f_it->first, SSA, *solver.solver);
+
+ exprt enabling_expr=SSA.get_enabling_exprs();
+ solver << enabling_expr;
+
+ cover_goals_extt cover_goals(
+ SSA,
+ solver,
+ loophead_selects,
+ property_map,
+ false,
+ false,
+ options.get_bool_option("show-trace") ||
+ options.get_option("graphml-witness")!="" ||
+ options.get_option("json-cex")!="");
+
+ property_map.clear();
+
+ exprt::operandst ls_guards;
+
+ for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
+ n_it!=SSA.nodes.end(); n_it++)
+ {
+ if(n_it->loophead!=SSA.nodes.end()) // we've found a loop
+ {
+ irep_idt property_id=
+ irep_idt(n_it->loophead->location->location_number, 0);
+
+ exprt lsguard=
+ SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(lsguard), *n_it, true);
+
+ const ssa_domaint::phi_nodest &phi_nodes=
+ SSA.ssa_analysis[n_it->loophead->location].phi_nodes;
+
+ long store_unwinding=SSA.current_unwinding;
+ exprt::operandst loop_check_operands;
+
+ symbol_exprt lhguard=SSA.guard_symbol(n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(lhguard, *n_it, false);
+
+ for(SSA.current_unwinding=1;
+ SSA.current_unwinding<=store_unwinding;
+ SSA.current_unwinding++)
+ {
+ exprt::operandst loop_vars;
+ loop_vars.push_back(lhguard);
+
+ for(local_SSAt::objectst::const_iterator
+ o_it=SSA.ssa_objects.objects.begin();
+ o_it!=SSA.ssa_objects.objects.end();
+ o_it++)
+ {
+ ssa_domaint::phi_nodest::const_iterator p_it=
+ phi_nodes.find(o_it->get_identifier());
+ if(p_it==phi_nodes.end())
+ continue; // object not modified in this loop
+
+ symbol_exprt post_var=
+ SSA.name(*o_it, local_SSAt::PHI, n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(post_var, *n_it->loophead, false);
+
+ symbol_exprt phi_var;
+ phi_var=SSA.name(*o_it, local_SSAt::PHI, n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(phi_var, *n_it->loophead, true);
+ loop_vars.push_back(equal_exprt(post_var, phi_var));
+ }
+
+ loop_check_operands.push_back(conjunction(loop_vars));
+ }
+ SSA.current_unwinding=store_unwinding;
+
+ property_map[property_id].location=n_it->loophead->location;
+ property_map[property_id].result=UNKNOWN;
+ cover_goals.goal_map[property_id].conjuncts.push_back(
+ disjunction(loop_check_operands));
+ ls_guards.push_back(not_exprt(lsguard));
+ }
+ }
+
+ solver << conjunction(ls_guards);
+
+ for(cover_goals_extt::goal_mapt::const_iterator
+ it=cover_goals.goal_map.begin();
+ it!=cover_goals.goal_map.end();
+ it++)
+ {
+ literalt p=solver.convert(disjunction(it->second.conjuncts));
+ cover_goals.add(p);
+ }
+
+ status() << "Running " << solver.solver->decision_procedure_text() << eom;
+
+ cover_goals();
+
+ solver.pop_context();
+
+ std::cout << "** " << cover_goals.number_covered()
+ << " of " << cover_goals.size() << " failed ("
+ << cover_goals.iterations() << " iterations)" << eom;
+}
+
+/*******************************************************************\
+
+Function: summary_checker_baset::check_properties_linear
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: searching for periodical recurrence set
+
+\*******************************************************************/
+
+void summary_checker_nontermt::check_properties_linear(
+ const ssa_dbt::functionst::const_iterator f_it)
+{
+ unwindable_local_SSAt &SSA=*f_it->second;
+
+ ssa_local_unwindert &ssa_local_unwinder=ssa_unwinder.get(f_it->first);
+
+ // solver
+ incremental_solvert &solver=ssa_db.get_solver(f_it->first);
+ solver.set_message_handler(get_message_handler());
+
+ // give SSA to solver
+ solver << SSA;
+ SSA.mark_nodes();
+
+ solver.new_context();
+
+ // freeze loop head selects
+ exprt::operandst loophead_selects=
+ get_loophead_selects(f_it->first, SSA, *solver.solver);
+
+ exprt enabling_expr=SSA.get_enabling_exprs();
+ solver << enabling_expr;
+
+ property_map.clear();
+
+ exprt::operandst ls_guards;
+ for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
+ n_it!=SSA.nodes.end(); n_it++)
+ {
+ if(n_it->loophead!=SSA.nodes.end()) // we've found a loop
+ {
+ exprt lsguard=
+ SSA.name(SSA.guard_symbol(), local_SSAt::LOOP_SELECT, n_it->location);
+ ssa_local_unwinder.unwinder_rename(to_symbol_expr(lsguard), *n_it, true);
+ ls_guards.push_back(lsguard);
+ }
+ }
+
+ unsigned loop_counter=std::numeric_limits::max();
+ for(local_SSAt::nodest::const_iterator n_it=SSA.nodes.begin();
+ n_it!=SSA.nodes.end(); n_it++)
+ {
+ if(n_it->loophead!=SSA.nodes.end()) // we've found a loop
+ {
+ // we use continues further, therefore we put incrementation here
+ loop_counter++;
+
+ irep_idt property_id=
+ irep_idt(n_it->loophead->location->location_number, 0);
+
+ const ssa_domaint::phi_nodest &phi_nodes=
+ SSA.ssa_analysis[n_it->loophead->location].phi_nodes;
+
+ SSA.current_unwinding-=1;
+ symbol_exprt lhguard_second=SSA.guard_symbol(n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(lhguard_second, *n_it, true);
+ SSA.current_unwinding+=1;
+
+ symbol_exprt lhguard=SSA.guard_symbol(n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(lhguard, *n_it, true);
+
+ exprt::operandst first_linearity_check;
+ exprt::operandst second_linearity_check;
+ exprt::operandst constants_computation;
+ exprt::operandst constants;
+ exprt::operandst loopback_vars;
+ exprt::operandst loop_exit_cond;
+ exprt::operandst neg_loop_exit_cond;
+
+ property_map[property_id].location=n_it->loophead->location;
+ property_map[property_id].result=UNKNOWN;
+
+ unsigned const_number=0;
+ for(local_SSAt::objectst::const_iterator
+ o_it=SSA.ssa_objects.objects.begin();
+ o_it!=SSA.ssa_objects.objects.end();
+ o_it++)
+ {
+ ssa_domaint::phi_nodest::const_iterator p_it=
+ phi_nodes.find(o_it->get_identifier());
+ if(p_it==phi_nodes.end())
+ continue; // object not modified in this loop
+
+ // first linearity check data preparation
+
+ SSA.current_unwinding-=1;
+ symbol_exprt phi_var1;
+ phi_var1=SSA.name(*o_it, local_SSAt::PHI, n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(phi_var1, *n_it->loophead, true);
+ SSA.current_unwinding+=1;
+ symbol_exprt phi_var2;
+ phi_var2=SSA.name(*o_it, local_SSAt::PHI, n_it->loophead->location);
+ ssa_local_unwinder.unwinder_rename(phi_var2, *n_it->loophead, true);
+
+ // works only for bitvectors
+
+ if((phi_var2.type().id()!=ID_unsignedbv) &&
+ (phi_var2.type().id()!=ID_signedbv))
+ {
+ first_linearity_check.clear();
+ break;
+ }
+
+ // x_k = x_0 + C*k, const$k - k, const$i - C
+ symbol_exprt constk("const$k", phi_var2.type());
+ symbol_exprt const1(
+ "const$"+std::to_string(const_number++), phi_var2.type());
+
+ first_linearity_check.push_back(
+ equal_exprt(
+ phi_var1,
+ plus_exprt(
+ phi_var2,
+ const1)));
+
+ // get constants data preparation
+
+ constants_computation.push_back(
+ equal_exprt(
+ minus_exprt(phi_var1, phi_var2),
+ const1));
+ constants.push_back(const1);
+
+ // loopback vars data preparation
+
+ exprt init_expr;
+ exprt lb_var;
+ for(local_SSAt::nodet::equalitiest::const_iterator e_it=
+ n_it->loophead->equalities.begin();
+ e_it!=n_it->loophead->equalities.end(); e_it++)
+ {
+ if(e_it->rhs().id()==ID_if &&
+ to_symbol_expr(e_it->lhs()).get_identifier()==
+ phi_var2.get_identifier())
+ {
+ const if_exprt &if_expr=to_if_expr(e_it->rhs());
+ init_expr=if_expr.false_case();
+ lb_var=if_expr.true_case();
+ // should already be renamed for inner loops
+ break;
+ }
+ }
+
+ loopback_vars.push_back(lb_var);
+ loopback_vars.push_back(init_expr);
+ loopback_vars.push_back(constk);
+ }
+
+ if(first_linearity_check.empty()) // nothing to be checked
+ continue;
+
+ neg_loop_exit_cond.push_back(lhguard);
+ neg_loop_exit_cond.push_back(not_exprt(lhguard_second));
+ loop_exit_cond.push_back(lhguard);
+
+ solver.new_context();
+ solver << conjunction(first_linearity_check);
+ switch(solver())
+ {
+ case decision_proceduret::D_UNSATISFIABLE:
+ solver.pop_context();
+ continue;
+
+ case decision_proceduret::D_SATISFIABLE:
+ for(exprt::operandst::iterator it=first_linearity_check.begin();
+ it!=first_linearity_check.end();
+ ++it)
+ {
+ exprt ex=solver.get(it->op1().op1());
+ second_linearity_check.push_back(
+ and_exprt(
+ *it,
+ not_exprt(equal_exprt(to_constant_expr(ex), it->op1().op1()))));
+ }
+
+ solver.pop_context();
+ break;
+
+ default:
+ error() << "decision procedure has failed" << eom;
+ solver.pop_context();
+ solver.pop_context();
+ return;
+ }
+
+ solver.new_context();
+ solver << disjunction(second_linearity_check);
+ switch(solver())
+ {
+ case decision_proceduret::D_UNSATISFIABLE:
+ solver.pop_context();
+ break;
+
+ case decision_proceduret::D_SATISFIABLE:
+ solver.pop_context();
+ continue;
+
+ default:
+ error() << "decision procedure has failed" << eom;
+ solver.pop_context();
+ solver.pop_context();
+ return;
+ }
+
+ // constants extraction
+ exprt::operandst solver_consts;
+
+ solver.new_context();
+ solver << conjunction(constants_computation);
+ switch(solver())
+ {
+ case decision_proceduret::D_UNSATISFIABLE: // should never happen
+ solver.pop_context();
+ solver.pop_context();
+ return;
+
+ case decision_proceduret::D_SATISFIABLE:
+ for(auto constant : constants)
+ {
+ exprt ex=solver.solver->get(constant);
+ if(ex.type().id()==ID_unsignedbv)
+ {
+ // if (constant>UINT_MAX/2)?0-constant:constant
+ constant_exprt cex=to_constant_expr(ex);
+ constant_exprt zero=constant_exprt("0", ex.type());
+ constant_exprt cex2=
+ to_constant_expr(simplify_expr(minus_exprt(zero, cex), SSA.ns));
+ if_exprt ifex=if_exprt(
+ binary_relation_exprt(cex, ID_gt, cex2),
+ cex2,
+ cex,
+ ex.type());
+ ex=simplify_expr(ifex, SSA.ns);
+ }
+ solver_consts.push_back(to_constant_expr((ex)));
+ }
+ solver.pop_context();
+ break;
+
+ default:
+ error() << "decision procedure has failed" << eom;
+ solver.pop_context();
+ solver.pop_context();
+ return;
+ }
+
+ // loop exit conditions satisfiable check
+
+ solver.new_context();
+
+ for(unsigned i=0; iget(*(lbv_it+1));
+
+ // TODO: make this in different way
+ if(!from_expr(SSA.ns, "", *slvc_it).compare("0"))
+ {
+ eq_expr=equal_exprt(
+ *(lbv_it+1),
+ to_constant_expr(
+ simplify_expr(
+ old_xinit,
+ SSA.ns)));
+ }
+ else
+ {
+ // Exists xinit % const != old_xinit % const
+ eq_expr=equal_exprt(
+ mod_exprt(*(lbv_it+1), *slvc_it),
+ mod_exprt(
+ to_constant_expr(simplify_expr(old_xinit, SSA.ns)),
+ *slvc_it));
+ }
+ local_constraints.push_back(eq_expr);
+ ++slvc_it;
+ lbv_it+=3;
+ }
+ constraints.push_back(not_exprt(conjunction(local_constraints)));
+ solver << not_exprt(conjunction(local_constraints));
+ break;
+
+ default:
+ error() << "decision procedure has failed" << eom;
+ solver.pop_context();
+ solver.pop_context();
+ solver.pop_context();
+ return;
+ }
+ }
+ while(result!=decision_proceduret::D_UNSATISFIABLE);
+
+ solver.pop_context();
+
+ solver << conjunction(loop_exit_cond);
+ solver << conjunction(constraints);
+
+ switch(solver())
+ {
+ case decision_proceduret::D_UNSATISFIABLE:
+ solver.pop_context();
+ break;
+
+ case decision_proceduret::D_SATISFIABLE:
+ // found nontermination
+ property_map[property_id].result=FAIL;
+ solver.pop_context();
+ solver.pop_context();
+ return;
+
+ default:
+ error() << "decision procedure has failed" << eom;
+ solver.pop_context();
+ solver.pop_context();
+ return;
+ }
+ }
+ }
+ solver.pop_context();
+}
+
+/*******************************************************************\
+
+Function: summary_checker_nontermt::check_nonterm_linear
+
+ Inputs:
+
+ Outputs:
+
+ Purpose:
+
+\*******************************************************************/
+
+summary_checker_baset::resultt summary_checker_nontermt::check_nonterm_linear()
+{
+ // analyze all the functions
+ for(ssa_dbt::functionst::const_iterator f_it=ssa_db.functions().begin();
+ f_it!=ssa_db.functions().end(); f_it++)
+ {
+ status() << "Checking properties of " << f_it->first << messaget::eom;
+
+ check_properties_linear(f_it);
+ }
+
+ summary_checker_baset::resultt result=property_checkert::PASS;
+ for(property_mapt::const_iterator
+ p_it=property_map.begin(); p_it!=property_map.end(); p_it++)
+ {
+ if(p_it->second.result==FAIL)
+ return property_checkert::FAIL;
+ if(p_it->second.result==UNKNOWN)
+ result=property_checkert::UNKNOWN;
+ }
+
+ return result;
+}
diff --git a/src/2ls/summary_checker_nonterm.h b/src/2ls/summary_checker_nonterm.h
new file mode 100644
index 000000000..18992b169
--- /dev/null
+++ b/src/2ls/summary_checker_nonterm.h
@@ -0,0 +1,34 @@
+/*******************************************************************\
+
+Module: Summarizer for Nontermination Bit-level analysis
+
+Author: Stefan Marticek
+
+\*******************************************************************/
+
+#ifndef CPROVER_2LS_2LS_SUMMARY_CHECKER_NONTERM_H
+#define CPROVER_2LS_2LS_SUMMARY_CHECKER_NONTERM_H
+
+#include "summary_checker_base.h"
+
+class summary_checker_nontermt:public summary_checker_baset
+{
+public:
+ explicit summary_checker_nontermt(optionst &_options):
+ summary_checker_baset(_options)
+ {
+ }
+
+ virtual resultt operator()(const goto_modelt &);
+
+ void check_properties(
+ const ssa_dbt::functionst::const_iterator f_it);
+
+ void check_properties_linear(
+ const ssa_dbt::functionst::const_iterator f_it);
+
+protected:
+ summary_checker_baset::resultt check_nonterm_linear();
+};
+
+#endif // CPROVER_2LS_2LS_SUMMARY_CHECKER_NONTERM_H
diff --git a/src/ssa/ssa_build_goto_trace.cpp b/src/ssa/ssa_build_goto_trace.cpp
index 22891beff..2a24e33c6 100644
--- a/src/ssa/ssa_build_goto_trace.cpp
+++ b/src/ssa/ssa_build_goto_trace.cpp
@@ -336,7 +336,8 @@ void ssa_build_goto_tracet::operator()(
std::cout << "loop-head : " << current_pc->location_number << std::endl;
std::cout << "unwindings: "
<< unwindable_local_SSA.odometer_to_string(
- unwindable_local_SSA.current_unwindings, 100)
+ unwindable_local_SSA.current_unwindings,
+ 100)
<< std::endl;
#endif
}
@@ -365,13 +366,17 @@ void ssa_build_goto_tracet::operator()(
#endif
if(current_pc->is_backwards_goto())
{
+ if(unwindable_local_SSA.current_unwindings.back()==0)
+ break;
+
// we de-(!)-crement the unwinding counter
unwindable_local_SSA.decrement_unwindings(0);
#if 0
std::cout << "loop-end : " << current_pc->location_number << std::endl;
std::cout << "unwindings: "
<< unwindable_local_SSA.odometer_to_string(
- unwindable_local_SSA.current_unwindings, 100)
+ unwindable_local_SSA.current_unwindings,
+ 100)
<< std::endl;
#endif
#if TERM_CEX
From e6ed0c4b7e60f094bd7005917f2e361f39c920f5 Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sat, 4 Nov 2017 13:44:45 +0000
Subject: [PATCH 009/322] Regression tests for nontermination
Author: Stefan Marticek
---
regression/Makefile | 2 +-
regression/nontermination/Makefile | 20 ++++
regression/nontermination/break_loop1/main.c | 11 ++
.../nontermination/break_loop1/test.desc | 6 +
regression/nontermination/break_loop2/main.c | 11 ++
.../nontermination/break_loop2/test.desc | 6 +
regression/nontermination/break_loop3/main.c | 105 ++++++++++++++++++
.../nontermination/break_loop3/test.desc | 6 +
.../nontermination/continue_loop1/main.c | 12 ++
.../nontermination/continue_loop1/test.desc | 6 +
regression/nontermination/loop1/main.c | 14 +++
regression/nontermination/loop1/test.desc | 6 +
regression/nontermination/loop_seq1/main.c | 8 ++
regression/nontermination/loop_seq1/test.desc | 6 +
regression/nontermination/loop_seq2/main.c | 10 ++
regression/nontermination/loop_seq2/test.desc | 6 +
.../nontermination/loop_seq_break1/main.c | 9 ++
.../nontermination/loop_seq_break1/test.desc | 6 +
regression/nontermination/malloc1/main.c | 6 +
regression/nontermination/malloc1/test.desc | 6 +
regression/nontermination/many_loops1/main.c | 15 +++
.../nontermination/many_loops1/test.desc | 6 +
regression/nontermination/mem_alloc1/main.c | 14 +++
.../nontermination/mem_alloc1/test.desc | 6 +
regression/nontermination/mto_loop1/main.c | 7 ++
regression/nontermination/mto_loop1/test.desc | 6 +
.../nontermination/nested_loops1/main.c | 23 ++++
.../nontermination/nested_loops1/test.desc | 6 +
.../nontermination/nested_loops2/main.c | 27 +++++
.../nontermination/nested_loops2/test.desc | 6 +
.../nontermination/nested_loops3/main.c | 17 +++
.../nontermination/nested_loops3/test.desc | 6 +
.../nontermination/nested_loops3b/main.c | 15 +++
.../nontermination/nested_loops3b/test.desc | 6 +
.../nontermination/nested_loops4/main.c | 16 +++
.../nontermination/nested_loops4/test.desc | 6 +
.../nontermination/nested_loops5/main.c | 17 +++
.../nontermination/nested_loops5/test.desc | 6 +
.../nontermination/nested_loops6/main.c | 18 +++
.../nontermination/nested_loops6/test.desc | 6 +
.../nontermination/nested_loops7/main.c | 18 +++
.../nontermination/nested_loops7/test.desc | 6 +
.../nontermination/nested_loops8/main.c | 17 +++
.../nontermination/nested_loops8/test.desc | 6 +
regression/nontermination/nonterm1/main.c | 21 ++++
regression/nontermination/nonterm1/test.desc | 6 +
.../nontermination/nontermination1/main.c | 15 +++
.../nontermination/nontermination1/test.desc | 6 +
.../nontermination/possible_bug1/main.c | 12 ++
.../nontermination/possible_bug1/test.desc | 6 +
regression/nontermination/sloop2/main.c | 11 ++
regression/nontermination/sloop2/test.desc | 6 +
regression/nontermination/sloop3/main.c | 8 ++
regression/nontermination/sloop3/test.desc | 6 +
regression/nontermination/sloop4/main.c | 9 ++
regression/nontermination/sloop4/test.desc | 6 +
regression/nontermination/sloop5/main.c | 13 +++
regression/nontermination/sloop5/test.desc | 6 +
regression/nontermination/sloop6/main.c | 14 +++
regression/nontermination/sloop6/test.desc | 6 +
regression/nontermination/sloop7/main.c | 13 +++
regression/nontermination/sloop7/test.desc | 6 +
regression/nontermination/sloop8/main.c | 10 ++
regression/nontermination/sloop8/test.desc | 6 +
regression/nontermination/sloop9/main.c | 10 ++
regression/nontermination/sloop9/test.desc | 6 +
.../term_fail_break_loop1/main.c | 11 ++
.../term_fail_break_loop1/test.desc | 6 +
.../precond_contextsensitive1/test.desc | 2 +-
69 files changed, 757 insertions(+), 2 deletions(-)
create mode 100644 regression/nontermination/Makefile
create mode 100644 regression/nontermination/break_loop1/main.c
create mode 100644 regression/nontermination/break_loop1/test.desc
create mode 100644 regression/nontermination/break_loop2/main.c
create mode 100644 regression/nontermination/break_loop2/test.desc
create mode 100644 regression/nontermination/break_loop3/main.c
create mode 100644 regression/nontermination/break_loop3/test.desc
create mode 100644 regression/nontermination/continue_loop1/main.c
create mode 100644 regression/nontermination/continue_loop1/test.desc
create mode 100644 regression/nontermination/loop1/main.c
create mode 100644 regression/nontermination/loop1/test.desc
create mode 100644 regression/nontermination/loop_seq1/main.c
create mode 100644 regression/nontermination/loop_seq1/test.desc
create mode 100644 regression/nontermination/loop_seq2/main.c
create mode 100644 regression/nontermination/loop_seq2/test.desc
create mode 100644 regression/nontermination/loop_seq_break1/main.c
create mode 100644 regression/nontermination/loop_seq_break1/test.desc
create mode 100644 regression/nontermination/malloc1/main.c
create mode 100644 regression/nontermination/malloc1/test.desc
create mode 100644 regression/nontermination/many_loops1/main.c
create mode 100644 regression/nontermination/many_loops1/test.desc
create mode 100644 regression/nontermination/mem_alloc1/main.c
create mode 100644 regression/nontermination/mem_alloc1/test.desc
create mode 100644 regression/nontermination/mto_loop1/main.c
create mode 100644 regression/nontermination/mto_loop1/test.desc
create mode 100644 regression/nontermination/nested_loops1/main.c
create mode 100644 regression/nontermination/nested_loops1/test.desc
create mode 100644 regression/nontermination/nested_loops2/main.c
create mode 100644 regression/nontermination/nested_loops2/test.desc
create mode 100644 regression/nontermination/nested_loops3/main.c
create mode 100644 regression/nontermination/nested_loops3/test.desc
create mode 100644 regression/nontermination/nested_loops3b/main.c
create mode 100644 regression/nontermination/nested_loops3b/test.desc
create mode 100644 regression/nontermination/nested_loops4/main.c
create mode 100644 regression/nontermination/nested_loops4/test.desc
create mode 100644 regression/nontermination/nested_loops5/main.c
create mode 100644 regression/nontermination/nested_loops5/test.desc
create mode 100644 regression/nontermination/nested_loops6/main.c
create mode 100644 regression/nontermination/nested_loops6/test.desc
create mode 100644 regression/nontermination/nested_loops7/main.c
create mode 100644 regression/nontermination/nested_loops7/test.desc
create mode 100644 regression/nontermination/nested_loops8/main.c
create mode 100644 regression/nontermination/nested_loops8/test.desc
create mode 100644 regression/nontermination/nonterm1/main.c
create mode 100644 regression/nontermination/nonterm1/test.desc
create mode 100644 regression/nontermination/nontermination1/main.c
create mode 100644 regression/nontermination/nontermination1/test.desc
create mode 100644 regression/nontermination/possible_bug1/main.c
create mode 100644 regression/nontermination/possible_bug1/test.desc
create mode 100644 regression/nontermination/sloop2/main.c
create mode 100644 regression/nontermination/sloop2/test.desc
create mode 100644 regression/nontermination/sloop3/main.c
create mode 100644 regression/nontermination/sloop3/test.desc
create mode 100644 regression/nontermination/sloop4/main.c
create mode 100644 regression/nontermination/sloop4/test.desc
create mode 100644 regression/nontermination/sloop5/main.c
create mode 100644 regression/nontermination/sloop5/test.desc
create mode 100644 regression/nontermination/sloop6/main.c
create mode 100644 regression/nontermination/sloop6/test.desc
create mode 100644 regression/nontermination/sloop7/main.c
create mode 100644 regression/nontermination/sloop7/test.desc
create mode 100644 regression/nontermination/sloop8/main.c
create mode 100644 regression/nontermination/sloop8/test.desc
create mode 100644 regression/nontermination/sloop9/main.c
create mode 100644 regression/nontermination/sloop9/test.desc
create mode 100644 regression/nontermination/term_fail_break_loop1/main.c
create mode 100644 regression/nontermination/term_fail_break_loop1/test.desc
diff --git a/regression/Makefile b/regression/Makefile
index 22aec995c..b22a878c1 100644
--- a/regression/Makefile
+++ b/regression/Makefile
@@ -1,4 +1,4 @@
-DIRS = termination kiki preconditions interprocedural invariants
+DIRS = nontermination termination kiki preconditions interprocedural invariants
test:
$(foreach var,$(DIRS), make -C $(var) test;)
diff --git a/regression/nontermination/Makefile b/regression/nontermination/Makefile
new file mode 100644
index 000000000..cbda9642d
--- /dev/null
+++ b/regression/nontermination/Makefile
@@ -0,0 +1,20 @@
+default: tests.log
+
+FLAGS = --verbosity 10 --nontermination
+
+test:
+ @../test.pl -c "../../../src/2ls/2ls $(FLAGS)"
+
+tests.log: ../test.pl
+ @../test.pl -c "../../../src/2ls/2ls $(FLAGS)"
+
+show:
+ @for dir in *; do \
+ if [ -d "$$dir" ]; then \
+ vim -o "$$dir/*.c" "$$dir/*.out"; \
+ fi; \
+ done;
+
+clean:
+ @rm -f *.log
+ @for dir in *; do rm -f $$dir/*.out; done;
diff --git a/regression/nontermination/break_loop1/main.c b/regression/nontermination/break_loop1/main.c
new file mode 100644
index 000000000..cfb20065d
--- /dev/null
+++ b/regression/nontermination/break_loop1/main.c
@@ -0,0 +1,11 @@
+int main (void)
+{
+ int k = 0;
+
+ while (k < 10)
+ {
+ if (k == 0) break;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/break_loop1/test.desc b/regression/nontermination/break_loop1/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/break_loop1/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/break_loop2/main.c b/regression/nontermination/break_loop2/main.c
new file mode 100644
index 000000000..bf2fbb1da
--- /dev/null
+++ b/regression/nontermination/break_loop2/main.c
@@ -0,0 +1,11 @@
+int main (void)
+{
+ int k = 0;
+
+ while (k < 10)
+ {
+ if (k == 1) break;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/break_loop2/test.desc b/regression/nontermination/break_loop2/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/break_loop2/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/break_loop3/main.c b/regression/nontermination/break_loop3/main.c
new file mode 100644
index 000000000..9f51a8177
--- /dev/null
+++ b/regression/nontermination/break_loop3/main.c
@@ -0,0 +1,105 @@
+#include
+int main(void) {
+ int i___0;
+ int d = 0;
+ int currentFloorID = 3;
+ int floorButtons_0;
+ int floorButtons_1;
+ int floorButtons_2;
+ int floorButtons_3;
+ int floorButtons_4 = 0;
+ int retValue_acc;
+ if (d == 0) {
+ i___0 = 0;
+ i___0 = currentFloorID - 1;
+ {
+ while (1) {
+ currentFloorID=currentFloorID;
+ floorButtons_4=floorButtons_4;
+ while_6_continue: /* CIL Label */ ;
+ if (i___0 >= 0) {
+
+ } else {
+ goto while_6_break;
+ }
+ i___0 = currentFloorID + 1;
+ {
+ while (1) {
+ while_7_continue: /* CIL Label */ ;
+ if (i___0 < 5) {
+
+ } else {
+ goto while_7_break;
+ }
+ if (i___0 == 0) {
+ if (floorButtons_0) {
+ retValue_acc = 1;
+ return (retValue_acc);
+ } else {
+ goto _L___6;
+ }
+ } else {
+ _L___6: /* CIL Label */
+ if (i___0 == 1) {
+ if (floorButtons_1) {
+ retValue_acc = 1;
+ return (retValue_acc);
+ } else {
+ goto _L___5;
+ }
+ } else {
+ _L___5: /* CIL Label */
+ if (i___0 == 2) {
+ if (floorButtons_2) {
+ retValue_acc = 1;
+ return (retValue_acc);
+ } else {
+ goto _L___4;
+ }
+ } else {
+ _L___4: /* CIL Label */
+ if (i___0 == 3) {
+ if (floorButtons_3) {
+ retValue_acc = 1;
+ return (retValue_acc);
+ } else {
+ goto _L___3;
+ }
+ } else {
+ _L___3: /* CIL Label */
+ if (i___0 == 4) {
+ if (floorButtons_4) {
+ retValue_acc = 1;
+ return (retValue_acc);
+ } else {
+
+ }
+ } else {
+
+ }
+ }
+ }
+ }
+ }
+ i___0 = i___0 + 1;
+ printf("%d %d %d %d %d %d %d %d %d\n", i___0,
+ d,
+ currentFloorID,
+ floorButtons_0,
+ floorButtons_1,
+ floorButtons_2,
+ floorButtons_3,
+ floorButtons_4,
+ retValue_acc);
+ }
+ while_7_break: /* CIL Label */ ;
+ }
+ i___0 = i___0 - 1;
+ }
+ while_6_break: /* CIL Label */ ;
+ }
+ } else {
+
+ }
+ return 0;
+}
diff --git a/regression/nontermination/break_loop3/test.desc b/regression/nontermination/break_loop3/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/break_loop3/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/continue_loop1/main.c b/regression/nontermination/continue_loop1/main.c
new file mode 100644
index 000000000..993228df6
--- /dev/null
+++ b/regression/nontermination/continue_loop1/main.c
@@ -0,0 +1,12 @@
+int main (void)
+{
+ int k = 0;
+
+ while (k < 10)
+ {
+ if (k == 0) continue;
+ k++;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/continue_loop1/test.desc b/regression/nontermination/continue_loop1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/continue_loop1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/loop1/main.c b/regression/nontermination/loop1/main.c
new file mode 100644
index 000000000..4db3a12ca
--- /dev/null
+++ b/regression/nontermination/loop1/main.c
@@ -0,0 +1,14 @@
+int main(void)
+{
+ int i;
+ while(1) {
+ if (i++) break;
+ if (--i) break;
+ while(1) {
+ if (i) break;
+ if (i) break;
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/loop1/test.desc b/regression/nontermination/loop1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/loop1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/loop_seq1/main.c b/regression/nontermination/loop_seq1/main.c
new file mode 100644
index 000000000..c37b25bfa
--- /dev/null
+++ b/regression/nontermination/loop_seq1/main.c
@@ -0,0 +1,8 @@
+int main(void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10) i++;
+ while (j < 10) j++;
+ while (k < 10);
+ return 0;
+}
diff --git a/regression/nontermination/loop_seq1/test.desc b/regression/nontermination/loop_seq1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/loop_seq1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/loop_seq2/main.c b/regression/nontermination/loop_seq2/main.c
new file mode 100644
index 000000000..9d7a6f994
--- /dev/null
+++ b/regression/nontermination/loop_seq2/main.c
@@ -0,0 +1,10 @@
+int main(void)
+{
+ int k = 0;
+ while (k < 10) if (k < 10) break;
+
+ do {
+ } while (k < 10);
+
+ return 0;
+}
diff --git a/regression/nontermination/loop_seq2/test.desc b/regression/nontermination/loop_seq2/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/loop_seq2/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/loop_seq_break1/main.c b/regression/nontermination/loop_seq_break1/main.c
new file mode 100644
index 000000000..3d8eb9612
--- /dev/null
+++ b/regression/nontermination/loop_seq_break1/main.c
@@ -0,0 +1,9 @@
+int main(void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10) { i++; }
+ while (i < 15) { i++; }
+ while (k < 10) { if (k < 10) break; }
+
+ return 0;
+}
diff --git a/regression/nontermination/loop_seq_break1/test.desc b/regression/nontermination/loop_seq_break1/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/loop_seq_break1/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/malloc1/main.c b/regression/nontermination/malloc1/main.c
new file mode 100644
index 000000000..b968b3003
--- /dev/null
+++ b/regression/nontermination/malloc1/main.c
@@ -0,0 +1,6 @@
+int main (void)
+{
+ while (malloc(1));
+
+ return 0;
+}
diff --git a/regression/nontermination/malloc1/test.desc b/regression/nontermination/malloc1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/malloc1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/many_loops1/main.c b/regression/nontermination/many_loops1/main.c
new file mode 100644
index 000000000..26da22f15
--- /dev/null
+++ b/regression/nontermination/many_loops1/main.c
@@ -0,0 +1,15 @@
+int main(void)
+{
+ int i = 2;
+ int j = 2;
+
+ for (int k = 0; k < 10; k++);
+
+ while (i > 1) {
+ if (i > 2)
+ i--;
+ if (j > 2)
+ j--;
+ }
+ return i;
+}
diff --git a/regression/nontermination/many_loops1/test.desc b/regression/nontermination/many_loops1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/many_loops1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/mem_alloc1/main.c b/regression/nontermination/mem_alloc1/main.c
new file mode 100644
index 000000000..5b95dc851
--- /dev/null
+++ b/regression/nontermination/mem_alloc1/main.c
@@ -0,0 +1,14 @@
+int main(void)
+{
+ int i = 0;
+ while (1) {
+ i++;
+ int *a, *b;
+ if (malloc(110)) {
+ a = malloc(sizeof(malloc(10)))+1;
+ b = malloc(20);
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/mem_alloc1/test.desc b/regression/nontermination/mem_alloc1/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/mem_alloc1/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/mto_loop1/main.c b/regression/nontermination/mto_loop1/main.c
new file mode 100644
index 000000000..58e216f47
--- /dev/null
+++ b/regression/nontermination/mto_loop1/main.c
@@ -0,0 +1,7 @@
+int main(void)
+{
+ int i;
+ for ( int k = 0; k < 10; k++);
+ while ( i > 0);
+ return 0;
+}
diff --git a/regression/nontermination/mto_loop1/test.desc b/regression/nontermination/mto_loop1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/mto_loop1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops1/main.c b/regression/nontermination/nested_loops1/main.c
new file mode 100644
index 000000000..5399c127d
--- /dev/null
+++ b/regression/nontermination/nested_loops1/main.c
@@ -0,0 +1,23 @@
+int main(void)
+{
+ int i = 1, j = 2, k = 3;
+ while (i!=j && j!=k)
+ {
+ j = k - i;
+ k = j + i;
+ i = k - j;
+ while (i!=k && j!=k)
+ {
+ j = k - i;
+ k = j + i;
+ i = k - j;
+ while (i!=j && j!=k)
+ {
+ j = k - i;
+ k = j + i;
+ i = k - j;
+ }
+
+ }
+ }
+}
diff --git a/regression/nontermination/nested_loops1/test.desc b/regression/nontermination/nested_loops1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops2/main.c b/regression/nontermination/nested_loops2/main.c
new file mode 100644
index 000000000..97292a63d
--- /dev/null
+++ b/regression/nontermination/nested_loops2/main.c
@@ -0,0 +1,27 @@
+#include
+
+int main(void)
+{ //few permutations - 4th is the same 3 times unwind to prove nontermination
+ int i = 1, j = 2, k = 3;
+ int counter = 1;
+ while (1)
+ {
+ printf("%d %d %d\n", i, j, k);
+ if (counter % 2 ==0)
+ {
+ i = j + i;
+ j = i - j;
+ i = i - j;
+ counter--;
+ }
+ else
+ {
+ counter++;
+ }
+ //swap j and k
+ j = j + k;
+ k = j - k;
+ j = j - k;
+ //swap i and j
+ }
+}
diff --git a/regression/nontermination/nested_loops2/test.desc b/regression/nontermination/nested_loops2/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops2/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops3/main.c b/regression/nontermination/nested_loops3/main.c
new file mode 100644
index 000000000..24021b6b5
--- /dev/null
+++ b/regression/nontermination/nested_loops3/main.c
@@ -0,0 +1,17 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ i >>= 1;
+ j >>= 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops3/test.desc b/regression/nontermination/nested_loops3/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops3/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops3b/main.c b/regression/nontermination/nested_loops3b/main.c
new file mode 100644
index 000000000..50476ae00
--- /dev/null
+++ b/regression/nontermination/nested_loops3b/main.c
@@ -0,0 +1,15 @@
+int main (void)
+{
+ int i = 4, j = 4, k = 4;
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ if (!i) break;
+ i >>= 1;
+ j >>= 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops3b/test.desc b/regression/nontermination/nested_loops3b/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops3b/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops4/main.c b/regression/nontermination/nested_loops4/main.c
new file mode 100644
index 000000000..9aec0b597
--- /dev/null
+++ b/regression/nontermination/nested_loops4/main.c
@@ -0,0 +1,16 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ for ( int x = 0; x < 100; x++);
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops4/test.desc b/regression/nontermination/nested_loops4/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/nested_loops4/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops5/main.c b/regression/nontermination/nested_loops5/main.c
new file mode 100644
index 000000000..473d5578a
--- /dev/null
+++ b/regression/nontermination/nested_loops5/main.c
@@ -0,0 +1,17 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ if (k == 0) break;
+ }
+ if (j == 0) break;
+ }
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops5/test.desc b/regression/nontermination/nested_loops5/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops5/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops6/main.c b/regression/nontermination/nested_loops6/main.c
new file mode 100644
index 000000000..a6c9486df
--- /dev/null
+++ b/regression/nontermination/nested_loops6/main.c
@@ -0,0 +1,18 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ if (k == 0) break;
+ }
+ if (j == 0) break;
+ }
+ if (i == 0) break;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops6/test.desc b/regression/nontermination/nested_loops6/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/nested_loops6/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops7/main.c b/regression/nontermination/nested_loops7/main.c
new file mode 100644
index 000000000..63bf53e75
--- /dev/null
+++ b/regression/nontermination/nested_loops7/main.c
@@ -0,0 +1,18 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ k = j - i;
+ }
+ j++;
+ }
+ i++;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops7/test.desc b/regression/nontermination/nested_loops7/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops7/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nested_loops8/main.c b/regression/nontermination/nested_loops8/main.c
new file mode 100644
index 000000000..57819ffa9
--- /dev/null
+++ b/regression/nontermination/nested_loops8/main.c
@@ -0,0 +1,17 @@
+int main (void)
+{
+ int i = 0, j = 0, k = 0;
+ while (i < 10)
+ {
+ while (j < 10)
+ {
+ while (k < 10)
+ {
+ k++;
+ }
+ }
+ i++;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nested_loops8/test.desc b/regression/nontermination/nested_loops8/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nested_loops8/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nonterm1/main.c b/regression/nontermination/nonterm1/main.c
new file mode 100644
index 000000000..6e47986c7
--- /dev/null
+++ b/regression/nontermination/nonterm1/main.c
@@ -0,0 +1,21 @@
+/*
+ * Date: 06/07/2015
+ * Created by: Ton Chanh Le (chanhle@comp.nus.edu.sg)
+ * Adapted from Cairo_true-termination.c
+ */
+
+typedef enum {false, true} bool;
+
+extern int __VERIFIER_nondet_int(void);
+
+int main()
+{
+ int x, y;
+ if (x > 0) {
+ while ((x != 0) && (y % 2 == 0)) {
+ x = x + 2;
+ y=y+2;
+ }
+ }
+ return 0;
+}
diff --git a/regression/nontermination/nonterm1/test.desc b/regression/nontermination/nonterm1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nonterm1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/nontermination1/main.c b/regression/nontermination/nontermination1/main.c
new file mode 100644
index 000000000..c9e776b1b
--- /dev/null
+++ b/regression/nontermination/nontermination1/main.c
@@ -0,0 +1,15 @@
+int main (void)
+{
+ int i = 4, j = 4, k;
+ __CPROVER_assume(3<=k && k<=4);
+ while (j < 10)
+ {
+ do
+ {
+ i >>= 1;
+ j >>= 1;
+ } while ((k < 10));
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/nontermination1/test.desc b/regression/nontermination/nontermination1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/nontermination1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/possible_bug1/main.c b/regression/nontermination/possible_bug1/main.c
new file mode 100644
index 000000000..f8eab91e9
--- /dev/null
+++ b/regression/nontermination/possible_bug1/main.c
@@ -0,0 +1,12 @@
+int main(void)
+{
+ int i, counter = 1;
+ for (i=1; i< 10;)
+ {
+ if (counter % 3 == 0) i++;
+ counter++;
+ }
+ while (i) i=i;
+
+ return 0;
+}
diff --git a/regression/nontermination/possible_bug1/test.desc b/regression/nontermination/possible_bug1/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/possible_bug1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop2/main.c b/regression/nontermination/sloop2/main.c
new file mode 100644
index 000000000..3d252e48d
--- /dev/null
+++ b/regression/nontermination/sloop2/main.c
@@ -0,0 +1,11 @@
+#include
+
+int main()
+{
+ int i = 4;
+ while (i > 1) {
+ if (i > 2)
+ i--;
+ }
+ return i;
+}
diff --git a/regression/nontermination/sloop2/test.desc b/regression/nontermination/sloop2/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/sloop2/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop3/main.c b/regression/nontermination/sloop3/main.c
new file mode 100644
index 000000000..88f50133f
--- /dev/null
+++ b/regression/nontermination/sloop3/main.c
@@ -0,0 +1,8 @@
+#include
+
+int main()
+{
+ int i = 2;
+ while (i > 1);
+ return i;
+}
diff --git a/regression/nontermination/sloop3/test.desc b/regression/nontermination/sloop3/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/sloop3/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop4/main.c b/regression/nontermination/sloop4/main.c
new file mode 100644
index 000000000..2341e3391
--- /dev/null
+++ b/regression/nontermination/sloop4/main.c
@@ -0,0 +1,9 @@
+#include
+
+int main()
+{
+ int i = 2;
+ while (i > 1) i--;
+ assert(i==0);
+ return i;
+}
diff --git a/regression/nontermination/sloop4/test.desc b/regression/nontermination/sloop4/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/sloop4/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop5/main.c b/regression/nontermination/sloop5/main.c
new file mode 100644
index 000000000..ddcf95e49
--- /dev/null
+++ b/regression/nontermination/sloop5/main.c
@@ -0,0 +1,13 @@
+#include
+
+int main()
+{
+ int i = 4;
+ int j = 4;
+ while (i > 1) {
+ if (i > 2)
+ i--;
+ j--;
+ }
+ return i;
+}
diff --git a/regression/nontermination/sloop5/test.desc b/regression/nontermination/sloop5/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/sloop5/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop6/main.c b/regression/nontermination/sloop6/main.c
new file mode 100644
index 000000000..0e33516b0
--- /dev/null
+++ b/regression/nontermination/sloop6/main.c
@@ -0,0 +1,14 @@
+#include
+
+int main()
+{
+ int i = 5;
+ int j = 4;
+ while (i > 1) {
+ if (i > 2)
+ i--;
+ if (j > 2)
+ j--;
+ }
+ return i;
+}
diff --git a/regression/nontermination/sloop6/test.desc b/regression/nontermination/sloop6/test.desc
new file mode 100644
index 000000000..b69d21c78
--- /dev/null
+++ b/regression/nontermination/sloop6/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop7/main.c b/regression/nontermination/sloop7/main.c
new file mode 100644
index 000000000..406a6469d
--- /dev/null
+++ b/regression/nontermination/sloop7/main.c
@@ -0,0 +1,13 @@
+#include
+
+int main()
+{
+ int i = 4;
+ int j = 4;
+ while ( 1) {
+ if (i > 2)
+ i--;
+ j--;
+ }
+ return i;
+}
diff --git a/regression/nontermination/sloop7/test.desc b/regression/nontermination/sloop7/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/sloop7/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop8/main.c b/regression/nontermination/sloop8/main.c
new file mode 100644
index 000000000..a9b1d16ab
--- /dev/null
+++ b/regression/nontermination/sloop8/main.c
@@ -0,0 +1,10 @@
+int main(void)
+{
+ int x=2;
+ int i=1;
+ while(x<10) {
+ if(i%2==0) x++;
+ i++;
+ }
+ return 0;
+}
diff --git a/regression/nontermination/sloop8/test.desc b/regression/nontermination/sloop8/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/sloop8/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/sloop9/main.c b/regression/nontermination/sloop9/main.c
new file mode 100644
index 000000000..e9e5e36f5
--- /dev/null
+++ b/regression/nontermination/sloop9/main.c
@@ -0,0 +1,10 @@
+int main(void)
+{
+ int x=9;
+ int i=1;
+ while(x<10) {
+ if(i%2==0) x++;
+ i++;
+ }
+ return 0;
+}
diff --git a/regression/nontermination/sloop9/test.desc b/regression/nontermination/sloop9/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/sloop9/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/nontermination/term_fail_break_loop1/main.c b/regression/nontermination/term_fail_break_loop1/main.c
new file mode 100644
index 000000000..cfb20065d
--- /dev/null
+++ b/regression/nontermination/term_fail_break_loop1/main.c
@@ -0,0 +1,11 @@
+int main (void)
+{
+ int k = 0;
+
+ while (k < 10)
+ {
+ if (k == 0) break;
+ }
+
+ return 0;
+}
diff --git a/regression/nontermination/term_fail_break_loop1/test.desc b/regression/nontermination/term_fail_break_loop1/test.desc
new file mode 100644
index 000000000..a99c31502
--- /dev/null
+++ b/regression/nontermination/term_fail_break_loop1/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+
+^EXIT=10$
+^SIGNAL=0$
+^VERIFICATION FAILED$
diff --git a/regression/preconditions/precond_contextsensitive1/test.desc b/regression/preconditions/precond_contextsensitive1/test.desc
index 76a98d95f..1da5cbf57 100644
--- a/regression/preconditions/precond_contextsensitive1/test.desc
+++ b/regression/preconditions/precond_contextsensitive1/test.desc
@@ -3,4 +3,4 @@ main.c
--context-sensitive --preconditions
^EXIT=5$
^SIGNAL=0$
-^\[sign\]: sign#return_value#phi19 <= 0 && -((signed __CPROVER_bitvector\[33\])sign#return_value#phi19) <= 0 ==> x <= 0 && -((signed __CPROVER_bitvector\[33\])x) <= 0$
+^\[sign\]: sign#return_value#phi17 <= 0 && -((signed __CPROVER_bitvector\[33\])sign#return_value#phi17) <= 0 ==> x <= 0 && -((signed __CPROVER_bitvector\[33\])x) <= 0$
From 6b7764b77b5044e5b967eaed0e10ef13fcf1856d Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sat, 4 Nov 2017 21:44:40 +0000
Subject: [PATCH 010/322] Version 0.5.2
---
src/2ls/version.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/2ls/version.h b/src/2ls/version.h
index 132ef4309..ec3fd48d6 100644
--- a/src/2ls/version.h
+++ b/src/2ls/version.h
@@ -9,6 +9,6 @@ Author: Peter Schrammel
#ifndef CPROVER_2LS_2LS_VERSION_H
#define CPROVER_2LS_2LS_VERSION_H
-#define TWOLS_VERSION "0.5.1"
+#define TWOLS_VERSION "0.5.2"
#endif
From c42930e15f42a4046cb124b07f9246d33f8697da Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Wed, 10 Aug 2016 09:52:47 +0100
Subject: [PATCH 011/322] Handling pointer parameters of functions. Pointed
object is passed as global.
---
src/ssa/ssa_dereference.cpp | 6 ++++
src/ssa/ssa_inliner.cpp | 58 +++++++++++++++++++++++++++++++++++--
src/ssa/ssa_inliner.h | 10 +++++--
src/ssa/ssa_object.cpp | 1 +
4 files changed, 70 insertions(+), 5 deletions(-)
diff --git a/src/ssa/ssa_dereference.cpp b/src/ssa/ssa_dereference.cpp
index 0425e7d54..3bc60c5c8 100644
--- a/src/ssa/ssa_dereference.cpp
+++ b/src/ssa/ssa_dereference.cpp
@@ -341,6 +341,12 @@ exprt dereference_rec(
result=if_exprt(guard, value, result);
}
+ if (values.empty()) {
+ // We use the identifier of pointed object
+ irep_idt identifier = id2string(to_symbol_expr(pointer).get_identifier())+"'obj";
+ result=symbol_exprt(identifier, src.type());
+ }
+
return result;
}
else if(src.id()==ID_member)
diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp
index 2f68901a0..18a34b042 100644
--- a/src/ssa/ssa_inliner.cpp
+++ b/src/ssa/ssa_inliner.cpp
@@ -10,6 +10,7 @@ Author: Peter Schrammel
#include
#include "ssa_inliner.h"
+#include "ssa_dereference.h"
/*******************************************************************\
@@ -63,7 +64,13 @@ void ssa_inlinert::get_summary(
#endif
// equalities for arguments
- bindings.push_back(get_replace_params(summary.params, *f_it));
+ bindings.push_back(get_replace_params(
+ summary.params,
+ *f_it,
+ summary.globals_in,
+ summary.globals_out,
+ SSA,
+ loc));
// equalities for globals_in
if(forward)
@@ -489,7 +496,11 @@ Function: ssa_inlinert::get_replace_params
exprt ssa_inlinert::get_replace_params(
const local_SSAt::var_listt ¶ms,
- const function_application_exprt &funapp_expr)
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::var_sett &globals_in,
+ const local_SSAt::var_sett &globals_out,
+ const local_SSAt &SSA,
+ const local_SSAt::locationt &loc)
{
// equalities for arguments
exprt::operandst c;
@@ -508,6 +519,49 @@ exprt ssa_inlinert::get_replace_params(
exprt lhs=*p_it; // copy
rename(lhs);
c.push_back(equal_exprt(lhs, *it));
+
+ // For pointer parameters create equalities between pointed object passed as global and
+ // corresponding object in caller
+ if (p_it->type().id() == ID_pointer) {
+ // Find corresponding objects in caller's objects (separately for entry and exit)
+ exprt pointed_ssa_sym_in;
+ exprt pointed_ssa_sym_out;
+ for (equal_exprt equal : SSA.find_node(loc)->equalities)
+ { // search through equalities with argument value
+ if (equal.rhs().id() == ID_symbol &&
+ to_symbol_expr(equal.rhs()).get_identifier() == to_symbol_expr(*it).get_identifier())
+ {
+ exprt arg_pointed = dereference(equal.lhs(), SSA.ssa_value_ai[loc], "", SSA.ns);
+ if (arg_pointed.id() == ID_address_of)
+ {
+ arg_pointed = to_address_of_expr(arg_pointed).object();
+ }
+ ssa_objectt pointed_ssa_obj(arg_pointed, SSA.ns);
+ // get correct SSA symbol for function call entry
+ pointed_ssa_sym_in = SSA.name(pointed_ssa_obj, local_SSAt::OUT,
+ SSA.get_def_loc(to_symbol_expr(arg_pointed), loc));
+ // get correct SSA symbol for function call exit
+ pointed_ssa_sym_out = SSA.name(pointed_ssa_obj, local_SSAt::OUT, loc);
+ }
+ }
+
+ // Find globals containing pointed object and create equalities
+ irep_idt global_id = id2string(to_symbol_expr(*p_it).get_identifier())+"'obj";
+ symbol_exprt expr_to_find(global_id, p_it->type().subtype());
+
+ // Entry global
+ symbol_exprt global_in;
+ if(find_corresponding_symbol(expr_to_find,globals_in,global_in)) {
+ rename(global_in);
+ c.push_back(equal_exprt(global_in,pointed_ssa_sym_in));
+ }
+ // Exit global
+ symbol_exprt global_out;
+ if(find_corresponding_symbol(expr_to_find,globals_out,global_out)) {
+ rename(global_out);
+ c.push_back(equal_exprt(global_out, pointed_ssa_sym_out));
+ }
+ }
}
return conjunction(c);
}
diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h
index 7cf8d0730..d36ee5960 100644
--- a/src/ssa/ssa_inliner.h
+++ b/src/ssa/ssa_inliner.h
@@ -125,14 +125,18 @@ class ssa_inlinert:public messaget
const local_SSAt::var_sett &cs_globals_out);
exprt get_replace_globals_in(
- const local_SSAt::var_sett &globals_in,
+ const local_SSAt::var_sett &globals_in,
const local_SSAt::var_sett &globals);
exprt get_replace_params(
const local_SSAt::var_listt ¶ms,
- const function_application_exprt &funapp_expr);
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::var_sett &globals_in,
+ const local_SSAt::var_sett &globals_out,
+ const local_SSAt &SSA,
+ const local_SSAt::locationt &loc);
exprt get_replace_globals_out(
const local_SSAt::var_sett &globals_out,
- const local_SSAt::var_sett &cs_globals_in,
+ const local_SSAt::var_sett &cs_globals_in,
const local_SSAt::var_sett &cs_globals_out);
void rename(exprt &expr);
diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp
index d3aa56993..72440df3a 100644
--- a/src/ssa/ssa_object.cpp
+++ b/src/ssa/ssa_object.cpp
@@ -282,6 +282,7 @@ void ssa_objectst::categorize_objects(
{
if(is_ptr_object(root_object))
{
+ globals.insert(*o_it);
}
else
{
From eaa069501b04f56bdcda83dcadabe8e99c08d938 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 12 Aug 2016 17:12:50 +0100
Subject: [PATCH 012/322] Simple heap domain - can check if pointers are NULL.
---
src/2ls/2ls_parse_options.cpp | 7 ++
src/2ls/2ls_parse_options.h | 2 +-
src/domains/Makefile | 5 +-
src/domains/heap_domain.cpp | 134 ++++++++++++++++++++++++
src/domains/heap_domain.h | 89 ++++++++++++++++
src/domains/ssa_analyzer.cpp | 7 ++
src/domains/strategy_solver_heap.cpp | 44 ++++++++
src/domains/strategy_solver_heap.h | 30 ++++++
src/domains/template_generator_base.cpp | 17 +++
src/domains/template_generator_base.h | 1 +
10 files changed, 333 insertions(+), 3 deletions(-)
create mode 100644 src/domains/heap_domain.cpp
create mode 100644 src/domains/heap_domain.h
create mode 100644 src/domains/strategy_solver_heap.cpp
create mode 100644 src/domains/strategy_solver_heap.h
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index 95900d778..6551755c4 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -193,6 +193,10 @@ void twols_parse_optionst::get_command_line_options(optionst &options)
options.set_option("equalities", true);
options.set_option("std-invariants", true);
}
+ else if (cmdline.isset("heap"))
+ {
+ options.set_option("heap", true);
+ }
else
{
if(cmdline.isset("zones"))
@@ -480,6 +484,8 @@ int twols_parse_optionst::doit()
status() << "Havocking loops and function calls" << eom;
else if(options.get_bool_option("equalities"))
status() << "Using (dis)equalities domain" << eom;
+ else if (options.get_bool_option("heap"))
+ status() << "Using heap domain" << eom;
else
{
if(options.get_bool_option("intervals"))
@@ -1618,6 +1624,7 @@ void twols_parse_optionst::help()
" --havoc havoc loops and function calls\n"
" --intervals use interval domain\n"
" --equalities use equalities and disequalities domain\n"
+ " --heap use heap domain\n"
" --zones use zone domain\n"
" --octagons use octagon domain\n"
" --enum-solver use solver based on model enumeration\n"
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index 342b79c21..ddbc61c3e 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -36,7 +36,7 @@ class optionst;
"(version)" \
"(i386-linux)(i386-macos)(i386-win32)(win32)(winx64)(gcc)" \
"(ppc-macos)(unsigned-char)" \
- "(havoc)(intervals)(zones)(octagons)(equalities)"\
+ "(havoc)(intervals)(zones)(octagons)(equalities)(heap)"\
"(enum-solver)(binsearch-solver)(arrays)"\
"(string-abstraction)(no-arch)(arch):(floatbv)(fixedbv)" \
"(round-to-nearest)(round-to-plus-inf)(round-to-minus-inf)(round-to-zero)" \
diff --git a/src/domains/Makefile b/src/domains/Makefile
index 82b6a23b8..d780aba0c 100644
--- a/src/domains/Makefile
+++ b/src/domains/Makefile
@@ -1,4 +1,5 @@
-SRC = tpolyhedra_domain.cpp equality_domain.cpp domain.cpp predabs_domain.cpp\
+SRC = tpolyhedra_domain.cpp equality_domain.cpp domain.cpp \
+ predabs_domain.cpp heap_domain.cpp \
ssa_analyzer.cpp util.cpp incremental_solver.cpp \
strategy_solver_base.cpp strategy_solver_equality.cpp \
linrank_domain.cpp lexlinrank_domain.cpp\
@@ -7,7 +8,7 @@ SRC = tpolyhedra_domain.cpp equality_domain.cpp domain.cpp predabs_domain.cpp\
template_generator_base.cpp template_generator_summary.cpp \
template_generator_callingcontext.cpp template_generator_ranking.cpp \
strategy_solver_binsearch2.cpp strategy_solver_binsearch3.cpp \
- strategy_solver_predabs.cpp
+ strategy_solver_predabs.cpp strategy_solver_heap.cpp
#solver_enumeration.cpp
include ../config.inc
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
new file mode 100644
index 000000000..39f29982c
--- /dev/null
+++ b/src/domains/heap_domain.cpp
@@ -0,0 +1,134 @@
+/**
+ * Viktor Malik, 12.8.2016 (c).
+ */
+
+#include "heap_domain.h"
+
+void heap_domaint::initialize(domaint::valuet &value)
+{
+ heap_valuet &val = static_cast(value);
+ val.paths.clear();
+ val.nulls.clear();
+}
+
+void heap_domaint::make_template(const domaint::var_specst &var_specs, const namespacet &ns)
+{
+ unsigned long size = var_specs.size();
+ templ.clear();
+ templ.reserve(size);
+
+ for (auto v1 = var_specs.begin(); v1 != var_specs.end(); ++v1)
+ {
+ // Template for variable - for NULL pointer and dangling checks
+ templ.push_back(template_rowt());
+ template_rowt &templ_row = templ.back();
+ templ_row.expr = v1->var;
+ templ_row.pre_guard = v1->pre_guard;
+ templ_row.post_guard = v1->post_guard;
+ templ_row.aux_expr = v1->post_guard;
+ templ_row.kind = v1->kind;
+ }
+}
+
+exprt heap_domaint::get_pre_null_constraint(unsigned index)
+{
+ assert(index < templ.size());
+ const template_rowt &templ_row = templ[index];
+ if (templ_row.kind == OUT || templ_row.kind == OUTL) return true_exprt();
+ const vart &var = templ_row.expr;
+ return implies_exprt(templ_row.pre_guard,
+ equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type()))));
+}
+
+exprt heap_domaint::get_post_not_null_constraint(unsigned index)
+{
+ assert(index < templ.size());
+ const template_rowt &templ_row = templ[index];
+ if (templ_row.kind == IN) return true_exprt();
+ const vart &var = templ_row.expr;
+ exprt c = and_exprt(templ_row.aux_expr,
+ not_exprt(implies_exprt(templ_row.post_guard,
+ equal_exprt(var, null_pointer_exprt(
+ to_pointer_type(var.type()))))));
+ rename(c);
+ return c;
+}
+
+void heap_domaint::set_null(unsigned index, heap_valuet &value)
+{
+ assert(index < templ.size());
+ value.nulls.insert(index);
+}
+
+void heap_domaint::get_index_set(std::set &indices)
+{
+ for (unsigned i = 0; i < templ.size(); i++) indices.insert(i);
+}
+
+void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
+ const namespacet &ns) const
+{
+ const heap_valuet &_val = static_cast(value);
+ heap_valuet val = _val;
+
+ for (unsigned i = 0; i < templ.size(); ++i)
+ {
+ if (val.nulls.find(i) != val.nulls.end())
+ {
+ out << from_expr(ns, "", templ[i].expr) << "== NULL" << std::endl;
+ }
+ }
+}
+
+void heap_domaint::output_domain(std::ostream &out, const namespacet &ns) const
+{
+ for (unsigned i = 0; i < templ.size(); ++i)
+ {
+ const template_rowt &templ_row = templ[i];
+ switch (templ_row.kind)
+ {
+ case LOOP:
+ out << "(LOOP) [ " << from_expr(ns, "", templ_row.pre_guard) << " | ";
+ out << from_expr(ns, "", templ_row.post_guard) << " | ";
+ out << from_expr(ns, "", templ_row.aux_expr)
+ << " ] ===> " << std::endl << " ";
+ break;
+ case IN:
+ out << "(IN) ";
+ out << from_expr(ns, "", templ_row.pre_guard) << " ===> "
+ << std::endl << " ";
+ break;
+ case OUT:
+ case OUTL:
+ out << "(OUT) ";
+ out << from_expr(ns, "", templ_row.post_guard) << " ===> "
+ << std::endl << " ";
+ break;
+ default:
+ assert(false);
+ }
+ const vart var = templ_row.expr;
+ out << from_expr(ns, "", var) << " =!= NULL" << std::endl;
+ }
+}
+
+void heap_domaint::project_on_vars(domaint::valuet &value,
+ const domaint::var_sett &vars, exprt &result)
+{
+ heap_valuet &val = static_cast(value);
+
+ exprt::operandst c;
+ for (auto it = val.nulls.begin(); it != val.nulls.end(); ++it)
+ {
+ const vart &var = templ[*it].expr;
+
+ if (vars.find(var) == vars.end()) continue;
+
+ if (templ[*it].kind == LOOP)
+ c.push_back(implies_exprt(templ[*it].pre_guard,
+ equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type())))));
+ else
+ c.push_back(equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type()))));
+ }
+ result = conjunction(c);
+}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
new file mode 100644
index 000000000..adccdd70d
--- /dev/null
+++ b/src/domains/heap_domain.h
@@ -0,0 +1,89 @@
+/**
+ * Viktor Malik, 12.8.2016 (c).
+ */
+#ifndef CPROVER_HEAP_DOMAIN_H
+#define CPROVER_HEAP_DOMAIN_H
+
+#include "domain.h"
+
+class heap_domaint : public domaint
+{
+ public:
+
+ class pathst
+ {
+ public:
+ inline void insert_path(vart _from, vart _to, member_exprt _field)
+ {
+ paths.push_back(patht());
+ patht path = paths.back();
+ path.from = _from;
+ path.to = _to;
+ path.field = _field;
+ }
+
+ inline void clear() { paths.clear(); }
+
+ struct patht
+ {
+ vart from;
+ vart to;
+ member_exprt field;
+ };
+ protected:
+ std::list paths;
+ };
+
+ typedef std::set index_sett;
+
+ heap_domaint(unsigned int _domain_number, replace_mapt &_renaming_map,
+ const var_specst &var_specs,
+ const namespacet &ns)
+ : domaint(_domain_number, _renaming_map)
+ {
+ make_template(var_specs, ns);
+ }
+
+ class heap_valuet : public valuet
+ {
+ public:
+ pathst paths;
+ index_sett nulls;
+ };
+
+ struct template_rowt
+ {
+ guardt pre_guard;
+ guardt post_guard;
+ exprt expr;
+ exprt aux_expr;
+ kindt kind;
+ };
+
+ typedef std::vector templatet;
+
+ virtual void initialize(valuet &value) override;
+
+ exprt get_pre_null_constraint(unsigned index);
+
+ exprt get_post_not_null_constraint(unsigned index);
+
+ virtual void output_value(std::ostream &out, const valuet &value,
+ const namespacet &ns) const override;
+
+ virtual void output_domain(std::ostream &out, const namespacet &ns) const override;
+
+ virtual void project_on_vars(valuet &value, const var_sett &vars, exprt &result) override;
+
+ void set_null(unsigned index, heap_valuet &value);
+
+ void get_index_set(std::set &indices);
+
+ protected:
+ templatet templ;
+
+ void make_template(const var_specst &var_specs, const namespacet &ns);
+};
+
+
+#endif //CPROVER_HEAP_DOMAIN_H
diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp
index 993ba4eea..d01654888 100644
--- a/src/domains/ssa_analyzer.cpp
+++ b/src/domains/ssa_analyzer.cpp
@@ -31,6 +31,7 @@ Author: Peter Schrammel
#include "template_generator_ranking.h"
#include "strategy_solver_predabs.h"
#include "ssa_analyzer.h"
+#include "strategy_solver_heap.h"
#define BINSEARCH_SOLVER strategy_solver_binsearcht(\
*static_cast(domain), solver, SSA.ns)
@@ -103,6 +104,12 @@ void ssa_analyzert::operator()(
*static_cast(domain), solver, SSA.ns);
result=new equality_domaint::equ_valuet();
}
+ else if(template_generator.options.get_bool_option("heap"))
+ {
+ strategy_solver=new strategy_solver_heapt(
+ *static_cast(domain), solver, SSA.ns);
+ result=new heap_domaint::heap_valuet();
+ }
else
{
if(template_generator.options.get_bool_option("enum-solver"))
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
new file mode 100644
index 000000000..88a4b78f8
--- /dev/null
+++ b/src/domains/strategy_solver_heap.cpp
@@ -0,0 +1,44 @@
+/**
+ * Viktor Malik, 12.8.2016 (c).
+ */
+
+#include "strategy_solver_heap.h"
+
+bool strategy_solver_heapt::iterate(invariantt &_inv)
+{
+ heap_domaint::heap_valuet &inv = static_cast(_inv);
+
+ auto n_it = todo_nulls.begin();
+ if (n_it != todo_nulls.end()) // check NULL pointers
+ {
+ solver.new_context();
+
+ exprt pre_expr = heap_domain.get_pre_null_constraint(*n_it);
+
+ solver << pre_expr;
+
+ exprt post_expr = heap_domain.get_post_not_null_constraint(*n_it);
+ literalt cond_literal = solver.convert(post_expr);
+
+ solver << literal_exprt(cond_literal);
+
+ if (solver() == decision_proceduret::D_SATISFIABLE)
+ {
+ }
+ else // equality holds
+ {
+ heap_domain.set_null(*n_it, inv);
+
+ solver << pre_expr; // make permanent
+ }
+
+ solver.pop_context();
+
+ todo_nulls.erase(n_it);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
new file mode 100644
index 000000000..38eccdd9e
--- /dev/null
+++ b/src/domains/strategy_solver_heap.h
@@ -0,0 +1,30 @@
+/**
+ * Viktor Malik, 12.8.2016 (c).
+ */
+#ifndef CPROVER_STRATEGY_SOLVER_HEAP_H
+#define CPROVER_STRATEGY_SOLVER_HEAP_H
+
+#include "strategy_solver_base.h"
+#include "heap_domain.h"
+
+class strategy_solver_heapt : public strategy_solver_baset
+{
+ public:
+ explicit strategy_solver_heapt(heap_domaint &_heap_domain, incremental_solvert &_solver,
+ const namespacet &_ns)
+ : strategy_solver_baset(_solver, _ns), heap_domain(_heap_domain)
+ {
+ heap_domain.get_index_set(todo_nulls);
+ }
+
+ virtual bool iterate(invariantt &_inv) override;
+
+ protected:
+ heap_domaint &heap_domain;
+
+ typedef std::set worklistt;
+ worklistt todo_nulls;
+};
+
+
+#endif //CPROVER_STRATEGY_SOLVER_HEAP_H
diff --git a/src/domains/template_generator_base.cpp b/src/domains/template_generator_base.cpp
index e62fa1649..05326a71a 100644
--- a/src/domains/template_generator_base.cpp
+++ b/src/domains/template_generator_base.cpp
@@ -16,6 +16,7 @@ Author: Peter Schrammel
#include "equality_domain.h"
#include "tpolyhedra_domain.h"
#include "predabs_domain.h"
+#include "heap_domain.h"
#ifdef DEBUG
#include
@@ -263,6 +264,17 @@ void template_generator_baset::filter_equality_domain()
}
}
+void template_generator_baset::filter_heap_domain()
+{
+ domaint::var_specst new_var_specs(var_specs);
+ var_specs.clear();
+ for (auto var=new_var_specs.begin(); var!=new_var_specs.end(); ++var)
+ {
+ if (var->var.type().id()==ID_pointer)
+ var_specs.push_back(*var);
+ }
+}
+
/*******************************************************************\
Function: template_generator_baset::add_var
@@ -678,6 +690,11 @@ void template_generator_baset::instantiate_standard_domains(
domain_ptr=
new equality_domaint(domain_number, renaming_map, var_specs, SSA.ns);
}
+ else if(options.get_bool_option("heap"))
+ {
+ filter_heap_domain();
+ domain_ptr = new heap_domaint(domain_number, renaming_map, var_specs, SSA.ns);
+ }
else if(options.get_bool_option("intervals"))
{
domain_ptr=
diff --git a/src/domains/template_generator_base.h b/src/domains/template_generator_base.h
index 1c9428da2..757d342fc 100644
--- a/src/domains/template_generator_base.h
+++ b/src/domains/template_generator_base.h
@@ -73,6 +73,7 @@ class template_generator_baset:public messaget
void filter_template_domain();
void filter_equality_domain();
+ void filter_heap_domain();
void add_var(
const domaint::vart &var_to_add,
From 8ee1b4f9bfcca72c59afb02587163c59527a4375 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 12 Aug 2016 17:14:34 +0100
Subject: [PATCH 013/322] Basic regression tests for pointer properties
(collected from other test directories).
---
regression/heap/Makefile | 20 ++++++++++++++++++++
regression/heap/pointer1/main.c | 12 ++++++++++++
regression/heap/pointer1/test.desc | 6 ++++++
regression/heap/pointer2/main.c | 14 ++++++++++++++
regression/heap/pointer2/test.desc | 6 ++++++
regression/heap/pointer3/main.c | 12 ++++++++++++
regression/heap/pointer3/test.desc | 6 ++++++
regression/heap/pointer4/main.c | 15 +++++++++++++++
regression/heap/pointer4/test.desc | 6 ++++++
regression/heap/pointer5/main.c | 15 +++++++++++++++
regression/heap/pointer5/test.desc | 6 ++++++
regression/heap/pointer6/main.c | 16 ++++++++++++++++
regression/heap/pointer6/test.desc | 6 ++++++
regression/heap/pointer7/main.c | 10 ++++++++++
regression/heap/pointer7/test.desc | 6 ++++++
15 files changed, 156 insertions(+)
create mode 100644 regression/heap/Makefile
create mode 100644 regression/heap/pointer1/main.c
create mode 100644 regression/heap/pointer1/test.desc
create mode 100644 regression/heap/pointer2/main.c
create mode 100644 regression/heap/pointer2/test.desc
create mode 100644 regression/heap/pointer3/main.c
create mode 100644 regression/heap/pointer3/test.desc
create mode 100644 regression/heap/pointer4/main.c
create mode 100644 regression/heap/pointer4/test.desc
create mode 100644 regression/heap/pointer5/main.c
create mode 100644 regression/heap/pointer5/test.desc
create mode 100644 regression/heap/pointer6/main.c
create mode 100644 regression/heap/pointer6/test.desc
create mode 100644 regression/heap/pointer7/main.c
create mode 100644 regression/heap/pointer7/test.desc
diff --git a/regression/heap/Makefile b/regression/heap/Makefile
new file mode 100644
index 000000000..d2ff74910
--- /dev/null
+++ b/regression/heap/Makefile
@@ -0,0 +1,20 @@
+default: tests.log
+
+FLAGS = --verbosity 10
+
+test:
+ @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)"
+
+tests.log: ../test.pl
+ @../test.pl -c "../../../src/summarizer/2ls $(FLAGS)"
+
+show:
+ @for dir in *; do \
+ if [ -d "$$dir" ]; then \
+ vim -o "$$dir/*.c" "$$dir/*.out"; \
+ fi; \
+ done;
+
+clean:
+ @rm -f *.log
+ @for dir in *; do rm -f $$dir/*.out; done;
diff --git a/regression/heap/pointer1/main.c b/regression/heap/pointer1/main.c
new file mode 100644
index 000000000..34c87bb31
--- /dev/null
+++ b/regression/heap/pointer1/main.c
@@ -0,0 +1,12 @@
+void foo(int *x)
+{
+ *x = 10;
+}
+
+void main()
+{
+ int x;
+ foo(&x);
+ assert(x==10);
+}
+
diff --git a/regression/heap/pointer1/test.desc b/regression/heap/pointer1/test.desc
new file mode 100644
index 000000000..9ebb38e34
--- /dev/null
+++ b/regression/heap/pointer1/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer2/main.c b/regression/heap/pointer2/main.c
new file mode 100644
index 000000000..02f54b869
--- /dev/null
+++ b/regression/heap/pointer2/main.c
@@ -0,0 +1,14 @@
+void foo(int *x)
+{
+ x++;
+ *x = 10;
+}
+
+void main()
+{
+ int x[2];
+ foo(&x);
+ int y = x[1];
+ assert(y==10);
+}
+
diff --git a/regression/heap/pointer2/test.desc b/regression/heap/pointer2/test.desc
new file mode 100644
index 000000000..c90269dfc
--- /dev/null
+++ b/regression/heap/pointer2/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer3/main.c b/regression/heap/pointer3/main.c
new file mode 100644
index 000000000..098f61866
--- /dev/null
+++ b/regression/heap/pointer3/main.c
@@ -0,0 +1,12 @@
+#include
+
+void main()
+{
+ int x = 0;
+ int *p = &x;
+ int *y = p;
+ for(int i=0;i<10;i++) y = p;
+ assert(p!=NULL);
+ assert(y!=NULL);
+ *y = *p;
+}
diff --git a/regression/heap/pointer3/test.desc b/regression/heap/pointer3/test.desc
new file mode 100644
index 000000000..c90269dfc
--- /dev/null
+++ b/regression/heap/pointer3/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer4/main.c b/regression/heap/pointer4/main.c
new file mode 100644
index 000000000..0119e4601
--- /dev/null
+++ b/regression/heap/pointer4/main.c
@@ -0,0 +1,15 @@
+#include
+
+int *foo()
+{
+ return NULL;
+}
+
+void main()
+{
+ int x = 0;
+ int *p = &x;
+ int *y = p;
+ for(int i=0;i<10;i++) y = foo();
+ assert(y==NULL);
+}
diff --git a/regression/heap/pointer4/test.desc b/regression/heap/pointer4/test.desc
new file mode 100644
index 000000000..c90269dfc
--- /dev/null
+++ b/regression/heap/pointer4/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer5/main.c b/regression/heap/pointer5/main.c
new file mode 100644
index 000000000..6dc5d56aa
--- /dev/null
+++ b/regression/heap/pointer5/main.c
@@ -0,0 +1,15 @@
+#include
+
+void foo(int **x)
+{
+ x = NULL;
+}
+
+void main()
+{
+ int x = 0;
+ int *p = &x;
+ int *y = p;
+ for(int i=0;i<10;i++) foo(y);
+ assert(y==NULL);
+}
diff --git a/regression/heap/pointer5/test.desc b/regression/heap/pointer5/test.desc
new file mode 100644
index 000000000..c90269dfc
--- /dev/null
+++ b/regression/heap/pointer5/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer6/main.c b/regression/heap/pointer6/main.c
new file mode 100644
index 000000000..676c04b24
--- /dev/null
+++ b/regression/heap/pointer6/main.c
@@ -0,0 +1,16 @@
+#include
+
+int *foo(int *x)
+{
+ return x;
+}
+
+void main()
+{
+ int x = 0;
+ int *y;
+
+ y = foo(&x);
+
+ assert(y!=NULL);
+}
diff --git a/regression/heap/pointer6/test.desc b/regression/heap/pointer6/test.desc
new file mode 100644
index 000000000..c90269dfc
--- /dev/null
+++ b/regression/heap/pointer6/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/pointer7/main.c b/regression/heap/pointer7/main.c
new file mode 100644
index 000000000..28c9e0ab5
--- /dev/null
+++ b/regression/heap/pointer7/main.c
@@ -0,0 +1,10 @@
+#include
+
+void main()
+{
+ int x[10];
+ int *end = &x[9];
+ int *p = x;
+ for(; p!=end; p++);
+ assert(p==end);
+}
diff --git a/regression/heap/pointer7/test.desc b/regression/heap/pointer7/test.desc
new file mode 100644
index 000000000..38318bb3b
--- /dev/null
+++ b/regression/heap/pointer7/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+--heap
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
From c62fc0d1c69909b931f5e1597ab971f26a3165be Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Wed, 17 Aug 2016 17:50:27 +0100
Subject: [PATCH 014/322] Heap domain: completely redo the domain. Now, the
domain can find invariants for paths between pointer variables.
---
src/domains/heap_domain.cpp | 228 +++++++++++++++++++++------
src/domains/heap_domain.h | 104 +++++++-----
src/domains/strategy_solver_heap.cpp | 57 ++++---
src/domains/strategy_solver_heap.h | 5 +-
4 files changed, 279 insertions(+), 115 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 39f29982c..65260f45e 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -3,14 +3,27 @@
*/
#include "heap_domain.h"
+#include "util.h"
+/**
+ * Initialize value.
+ * Clears each pointer destinations.
+ * @param value
+ */
void heap_domaint::initialize(domaint::valuet &value)
{
heap_valuet &val = static_cast(value);
- val.paths.clear();
- val.nulls.clear();
+ val.resize(templ.size());
+ for (unsigned row = 0; row < templ.size(); ++row)
+ val[row].dests.clear();
}
+/**
+ * Create domain template for given set of variables.
+ * Template contains only pointers to structures containing field 'next'.
+ * @param var_specs Set of program variables.
+ * @param ns Namespace
+ */
void heap_domaint::make_template(const domaint::var_specst &var_specs, const namespacet &ns)
{
unsigned long size = var_specs.size();
@@ -19,64 +32,157 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
for (auto v1 = var_specs.begin(); v1 != var_specs.end(); ++v1)
{
- // Template for variable - for NULL pointer and dangling checks
- templ.push_back(template_rowt());
- template_rowt &templ_row = templ.back();
- templ_row.expr = v1->var;
- templ_row.pre_guard = v1->pre_guard;
- templ_row.post_guard = v1->post_guard;
- templ_row.aux_expr = v1->post_guard;
- templ_row.kind = v1->kind;
+ // Check if v1 is struct and has 'next' field
+ bool has_next = false;
+ const vart &var1 = v1->var;
+ if (var1.type().id() == ID_pointer)
+ {
+ const typet &pointed_type = ns.follow(var1.type().subtype());
+ if (pointed_type.id() == ID_struct)
+ {
+ for (auto &component : to_struct_type(pointed_type).components())
+ {
+ if (component.get_name() == "next")
+ has_next = true;
+ }
+ }
+ }
+
+ if (has_next)
+ { // Create template
+ templ.push_back(template_rowt());
+ template_rowt &templ_row = templ.back();
+ templ_row.expr = v1->var;
+ templ_row.pre_guard = v1->pre_guard;
+ templ_row.post_guard = v1->post_guard;
+ templ_row.aux_expr = v1->post_guard;
+ templ_row.kind = v1->kind;
+ }
}
}
-exprt heap_domaint::get_pre_null_constraint(unsigned index)
+/**
+ * Create entry constraints expression for a value.
+ * @param value Value
+ * @return Conjuction of entry expressions for each template row
+ */
+exprt heap_domaint::to_pre_constraints(const heap_domaint::heap_valuet &value) const
{
- assert(index < templ.size());
- const template_rowt &templ_row = templ[index];
- if (templ_row.kind == OUT || templ_row.kind == OUTL) return true_exprt();
- const vart &var = templ_row.expr;
- return implies_exprt(templ_row.pre_guard,
- equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type()))));
+ assert(value.size() == templ.size());
+ exprt::operandst c;
+ for (rowt row = 0; row < templ.size(); ++row)
+ {
+ c.push_back(get_row_pre_constraint(row, value[row]));
+ }
+ return conjunction(c);
}
-exprt heap_domaint::get_post_not_null_constraint(unsigned index)
+/**
+ * Create exit constraint expression for each row.
+ * Each expression is negation of row expression (for solving exists forall problem).
+ * @param value Value
+ * @param cond_exprs Constraint expressions
+ * @param value_exprs Template expressions (variables)
+ */
+void heap_domaint::make_not_post_constraints(const heap_domaint::heap_valuet &value,
+ exprt::operandst &cond_exprs,
+ exprt::operandst &value_exprs)
{
- assert(index < templ.size());
- const template_rowt &templ_row = templ[index];
- if (templ_row.kind == IN) return true_exprt();
- const vart &var = templ_row.expr;
- exprt c = and_exprt(templ_row.aux_expr,
- not_exprt(implies_exprt(templ_row.post_guard,
- equal_exprt(var, null_pointer_exprt(
- to_pointer_type(var.type()))))));
- rename(c);
- return c;
+ assert(value.size() == templ.size());
+ cond_exprs.resize(templ.size());
+ value_exprs.resize(templ.size());
+
+ for (rowt row = 0; row < templ.size(); ++row)
+ {
+ value_exprs[row] = templ[row].expr;
+ rename(value_exprs[row]);
+ cond_exprs[row] = and_exprt(templ[row].aux_expr,
+ not_exprt(get_row_post_constraint(row, value[row])));
+ }
+}
+
+/**
+ * Create entry constraint expression for a row.
+ * @param row Row number
+ * @param row_value Row value
+ * @return Entry constraint expression.
+ */
+exprt heap_domaint::get_row_pre_constraint(const rowt &row, const row_valuet &row_value) const
+{
+ assert(row < templ.size());
+ const template_rowt &templ_row = templ[row];
+ kindt k = templ_row.kind;
+ // For exit variables the result is true
+ if (k == OUT || k == OUTL) return true_exprt();
+ if (row_value.dests.empty())
+ // Bottom is false
+ return implies_exprt(templ_row.pre_guard, false_exprt());
+ return implies_exprt(templ_row.pre_guard, row_value.get_row_expr(templ_row.expr, ns));
}
-void heap_domaint::set_null(unsigned index, heap_valuet &value)
+/**
+ * Create exit constraint expression for a row.
+ * @param row Row number
+ * @param row_value Row value
+ * @return Exit constraint expression.
+ */
+exprt heap_domaint::get_row_post_constraint(const rowt &row, const row_valuet &row_value)
{
- assert(index < templ.size());
- value.nulls.insert(index);
+ assert(row < templ.size());
+ const template_rowt &templ_row = templ[row];
+ // For entry variables the result is true
+ if (templ_row.kind == IN) return true_exprt();
+ if (row_value.dests.empty())
+ // Bottom is false
+ return implies_exprt(templ_row.post_guard, false_exprt());
+ exprt c = implies_exprt(templ_row.post_guard, row_value.get_row_expr(templ_row.expr, ns));
+ if (templ_row.kind == LOOP) rename(c);
+ return c;
}
-void heap_domaint::get_index_set(std::set &indices)
+/**
+ * Add new destination for a row
+ * @param row Row number
+ * @param value Value
+ * @param dest New destination to add
+ * @return True if insertion took place (dest did not exist in the row value)
+ */
+bool heap_domaint::add_row_dest(const heap_domaint::rowt &row,
+ heap_domaint::heap_valuet &value,
+ const exprt &dest)
{
- for (unsigned i = 0; i < templ.size(); i++) indices.insert(i);
+ assert(row < value.size());
+ assert(value.size() == templ.size());
+ auto new_dest = value[row].dests.insert(dest);
+ return new_dest.second;
}
void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
const namespacet &ns) const
{
- const heap_valuet &_val = static_cast(value);
- heap_valuet val = _val;
-
- for (unsigned i = 0; i < templ.size(); ++i)
+ const heap_valuet &val = static_cast(value);
+ for (rowt row = 0; row < templ.size(); ++row)
{
- if (val.nulls.find(i) != val.nulls.end())
+ const template_rowt &templ_row = templ[row];
+ switch (templ_row.kind)
{
- out << from_expr(ns, "", templ[i].expr) << "== NULL" << std::endl;
+ case LOOP:
+ out << "(LOOP) [ " << from_expr(ns, "", templ_row.pre_guard) << " | ";
+ out << from_expr(ns, "", templ_row.post_guard) << " | ";
+ out << from_expr(ns, "", templ_row.aux_expr) << " ] ===> " << std::endl << " ";
+ break;
+ case IN:
+ out << "(IN) ";
+ break;
+ case OUT:
+ case OUTL:
+ out << "(OUT) ";
+ break;
+ default:
+ assert(false);
}
+ out << "( " << from_expr(ns, "", templ_row.expr) << " == "
+ << from_expr(ns, "", val[row].get_row_expr(templ_row.expr, ns)) << " )" << std::endl;
}
}
@@ -107,28 +213,52 @@ void heap_domaint::output_domain(std::ostream &out, const namespacet &ns) const
default:
assert(false);
}
- const vart var = templ_row.expr;
- out << from_expr(ns, "", var) << " =!= NULL" << std::endl;
+ const vart &var = templ_row.expr;
+ out << "?path(" << from_expr(ns, "", var) << ", DESTINATIONS)" << std::endl;
}
}
void heap_domaint::project_on_vars(domaint::valuet &value,
const domaint::var_sett &vars, exprt &result)
{
- heap_valuet &val = static_cast(value);
+ const heap_valuet &val = static_cast(value);
+ assert(val.size() == templ.size());
exprt::operandst c;
- for (auto it = val.nulls.begin(); it != val.nulls.end(); ++it)
+ for (rowt row = 0; row < templ.size(); ++row)
{
- const vart &var = templ[*it].expr;
+ const template_rowt &templ_row = templ[row];
- if (vars.find(var) == vars.end()) continue;
+ if (vars.find(templ_row.expr) == vars.end()) continue;
- if (templ[*it].kind == LOOP)
- c.push_back(implies_exprt(templ[*it].pre_guard,
- equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type())))));
+ const row_valuet &row_val = val[row];
+ if (templ_row.kind == LOOP)
+ {
+ if (row_val.dests.empty())
+ c.push_back(implies_exprt(templ_row.pre_guard, false_exprt()));
+ else
+ c.push_back(implies_exprt(templ_row.pre_guard, row_val.get_row_expr(templ_row.expr, ns)));
+ }
else
- c.push_back(equal_exprt(var, null_pointer_exprt(to_pointer_type(var.type()))));
+ {
+ if (row_val.dests.empty())
+ c.push_back(false_exprt());
+ else
+ c.push_back(row_val.get_row_expr(templ_row.expr, ns));
+ }
}
result = conjunction(c);
}
+
+/**
+ * Converts constant returned from solver to corresponding expression.
+ * @param expr Solver expression
+ * @return
+ */
+exprt heap_domaint::value_to_ptr_exprt(const exprt &expr)
+{
+ if (expr.id() == ID_constant)
+ return expr.op0();
+
+ return expr;
+}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index adccdd70d..098ec3509 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -1,86 +1,112 @@
/**
+ * Abstract domain for representing heap.
+ *
* Viktor Malik, 12.8.2016 (c).
*/
#ifndef CPROVER_HEAP_DOMAIN_H
#define CPROVER_HEAP_DOMAIN_H
+#include
#include "domain.h"
class heap_domaint : public domaint
{
public:
-
- class pathst
- {
- public:
- inline void insert_path(vart _from, vart _to, member_exprt _field)
- {
- paths.push_back(patht());
- patht path = paths.back();
- path.from = _from;
- path.to = _to;
- path.field = _field;
- }
-
- inline void clear() { paths.clear(); }
-
- struct patht
- {
- vart from;
- vart to;
- member_exprt field;
- };
- protected:
- std::list paths;
- };
-
- typedef std::set index_sett;
+ typedef unsigned rowt;
heap_domaint(unsigned int _domain_number, replace_mapt &_renaming_map,
const var_specst &var_specs,
- const namespacet &ns)
- : domaint(_domain_number, _renaming_map)
+ const namespacet &ns_)
+ : domaint(_domain_number, _renaming_map), ns(ns_)
{
make_template(var_specs, ns);
}
- class heap_valuet : public valuet
+ /**
+ * Value of a row is set of addresses reachable from pointer (corresponding to template row) via
+ * field 'next'.
+ */
+ struct row_valuet
+ {
+ std::set dests;
+
+ /**
+ * Get expression for the row value. The expression has form of disjuncion of equalities.
+ * Equality can be:
+ * (templ_expr == NULL) when pointer is NULL
+ * (templ_expr->next == dest) when pointer points to dest via 'next' field
+ * @param templ_expr Pointer variable of the template row
+ * @param ns Namespace
+ * @return Expression corresponding to value - disjunction of equalities.
+ */
+ exprt get_row_expr(const vart &templ_expr, const namespacet &ns) const
+ {
+ exprt::operandst dis;
+ for (auto dest : dests)
+ {
+ if (dest.id() == ID_constant && to_constant_expr(dest).get_value() == ID_NULL)
+ dis.push_back(equal_exprt(templ_expr, dest));
+ else
+ {
+ assert(templ_expr.type().id() == ID_pointer);
+ const typet &struct_type = templ_expr.type().subtype();
+ dis.push_back(
+ equal_exprt(member_exprt(dereference_exprt(templ_expr, struct_type),
+ "next",
+ dest.type()),
+ dest));
+ }
+ }
+ return disjunction(dis);
+ }
+ };
+
+ class heap_valuet : public valuet, public std::vector
{
- public:
- pathst paths;
- index_sett nulls;
};
struct template_rowt
{
guardt pre_guard;
guardt post_guard;
- exprt expr;
+ vart expr;
exprt aux_expr;
kindt kind;
};
-
typedef std::vector templatet;
+ // Initialize value
virtual void initialize(valuet &value) override;
- exprt get_pre_null_constraint(unsigned index);
+ // Value -> constraints
+ exprt to_pre_constraints(const heap_valuet &value) const;
- exprt get_post_not_null_constraint(unsigned index);
+ void make_not_post_constraints(const heap_valuet &value, exprt::operandst &cond_exprs,
+ exprt::operandst &value_exprs);
+ // Row -> constraints
+ exprt get_row_pre_constraint(const rowt &row, const row_valuet &row_value) const;
+
+ exprt get_row_post_constraint(const rowt &row, const row_valuet &row_value);
+
+ // Add new destination to a row
+ bool add_row_dest(const rowt &row, heap_valuet &value, const exprt &dest);
+
+ // Printing
virtual void output_value(std::ostream &out, const valuet &value,
const namespacet &ns) const override;
virtual void output_domain(std::ostream &out, const namespacet &ns) const override;
+ // Projection
virtual void project_on_vars(valuet &value, const var_sett &vars, exprt &result) override;
- void set_null(unsigned index, heap_valuet &value);
-
- void get_index_set(std::set &indices);
+ // Conversion of solver value to expression
+ static exprt value_to_ptr_exprt(const exprt &expr);
protected:
templatet templ;
+ namespacet ns;
void make_template(const var_specst &var_specs, const namespacet &ns);
};
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 88a4b78f8..cac61907b 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -8,37 +8,48 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
{
heap_domaint::heap_valuet &inv = static_cast(_inv);
- auto n_it = todo_nulls.begin();
- if (n_it != todo_nulls.end()) // check NULL pointers
- {
- solver.new_context();
+ bool improved = false;
- exprt pre_expr = heap_domain.get_pre_null_constraint(*n_it);
+ solver.new_context();
- solver << pre_expr;
+ // Entry value constraints
+ exprt pre_expr = heap_domain.to_pre_constraints(inv);
+ solver << pre_expr;
- exprt post_expr = heap_domain.get_post_not_null_constraint(*n_it);
- literalt cond_literal = solver.convert(post_expr);
+ // Exit value constraints
+ exprt::operandst strategy_cond_exprs;
+ heap_domain.make_not_post_constraints(inv, strategy_cond_exprs, strategy_value_exprs);
- solver << literal_exprt(cond_literal);
+ strategy_cond_literals.resize(strategy_cond_exprs.size());
- if (solver() == decision_proceduret::D_SATISFIABLE)
- {
- }
- else // equality holds
+ for (unsigned i = 0; i < strategy_cond_exprs.size(); ++i)
+ {
+ strategy_cond_literals[i] = solver.convert(strategy_cond_exprs[i]);
+ strategy_cond_exprs[i] = literal_exprt(strategy_cond_literals[i]);
+ }
+ solver << disjunction(strategy_cond_exprs);
+
+ if (solver() == decision_proceduret::D_SATISFIABLE) // improvement check
+ {
+ for (unsigned row = 0; row < strategy_cond_literals.size(); ++row)
{
- heap_domain.set_null(*n_it, inv);
+ if (solver.l_get(strategy_cond_literals[row]).is_true())
+ {
+ debug() << "updating row: " << row << eom;
- solver << pre_expr; // make permanent
- }
+ exprt value = solver.get(strategy_value_exprs[row]);
+ // Value from solver must be converted into expression
+ exprt dest = heap_domain.value_to_ptr_exprt(value);
- solver.pop_context();
+ debug() << "destination: " << from_expr(ns, "", dest) << eom;
- todo_nulls.erase(n_it);
- return true;
- }
- else
- {
- return false;
+ if (heap_domain.add_row_dest(row, inv, dest))
+ improved = true;
+ }
+ }
}
+ solver.pop_context();
+
+ return improved;
+
}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index 38eccdd9e..2de00e769 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -1,4 +1,5 @@
/**
+ * Strategy solver for heap verification.
* Viktor Malik, 12.8.2016 (c).
*/
#ifndef CPROVER_STRATEGY_SOLVER_HEAP_H
@@ -14,16 +15,12 @@ class strategy_solver_heapt : public strategy_solver_baset
const namespacet &_ns)
: strategy_solver_baset(_solver, _ns), heap_domain(_heap_domain)
{
- heap_domain.get_index_set(todo_nulls);
}
virtual bool iterate(invariantt &_inv) override;
protected:
heap_domaint &heap_domain;
-
- typedef std::set worklistt;
- worklistt todo_nulls;
};
From 4d56989dc9aa88be6f0ac020ba9559cd4f15bece Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Wed, 17 Aug 2016 17:53:15 +0100
Subject: [PATCH 015/322] Programs using malloc don't need to be fully inlined.
Inlines only malloc and free functions.
---
src/2ls/2ls_parse_options.cpp | 21 +++++++++++++++++++--
src/ssa/malloc_ssa.cpp | 4 +++-
2 files changed, 22 insertions(+), 3 deletions(-)
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index 6551755c4..5ef232136 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -1112,8 +1112,25 @@ bool twols_parse_optionst::process_goto_program(
#endif
#if 1
- // TODO: find a better place for that
- replace_malloc(goto_model, "");
+ // Find, inline and remove malloc function
+ //TODO: find a better place for that
+ Forall_goto_functions(it, goto_model.goto_functions)
+ {
+ if (it->first == "malloc" || it->first == "free")
+ it->second.type.set(ID_C_inlined, true);
+ }
+ goto_partial_inline(goto_model, ui_message_handler, 0);
+ Forall_goto_functions(it, goto_model.goto_functions)
+ {
+ if (it->first == "malloc" || it->first == "free")
+ it->second.body.clear();
+ }
+ // Replace malloc
+ replace_malloc(goto_model,"");
+#endif
+
+#if REMOVE_MULTIPLE_DEREFERENCES
+ remove_multiple_dereferences(goto_model);
#endif
// recalculate numbers, etc.
diff --git a/src/ssa/malloc_ssa.cpp b/src/ssa/malloc_ssa.cpp
index fd5246b4e..9e2263f9b 100644
--- a/src/ssa/malloc_ssa.cpp
+++ b/src/ssa/malloc_ssa.cpp
@@ -15,6 +15,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include
#include
+#include
+#include
#include "malloc_ssa.h"
@@ -222,7 +224,7 @@ void replace_malloc(
exprt malloc_size=nil_exprt();
Forall_goto_program_instructions(i_it, f_it->second.body)
{
- if(i_it->is_assign())
+ if (i_it->is_assign())
{
code_assignt &code_assign=to_code_assign(i_it->code);
if(code_assign.lhs().id()==ID_symbol)
From 17fc7d48460fa1d8f09696f6deb49f302d42e680 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 18 Aug 2016 11:18:41 +0100
Subject: [PATCH 016/322] Heap domain: printing solver debug information
---
src/domains/heap_domain.h | 2 +
src/domains/strategy_solver_heap.cpp | 59 ++++++++++++++++++++++++++++
2 files changed, 61 insertions(+)
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 098ec3509..47e4e8083 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -109,6 +109,8 @@ class heap_domaint : public domaint
namespacet ns;
void make_template(const var_specst &var_specs, const namespacet &ns);
+
+ friend class strategy_solver_heapt;
};
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index cac61907b..030a7c92d 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -14,6 +14,9 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
// Entry value constraints
exprt pre_expr = heap_domain.to_pre_constraints(inv);
+#ifdef DEBUG_OUTPUT
+ debug() << "pre-inv: " << from_expr(ns,"",pre_expr) << eom;
+#endif
solver << pre_expr;
// Exit value constraints
@@ -22,15 +25,55 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
strategy_cond_literals.resize(strategy_cond_exprs.size());
+#ifdef DEBUG_OUTPUT
+ debug() << "post-inv: ";
+#endif
for (unsigned i = 0; i < strategy_cond_exprs.size(); ++i)
{
+#ifdef DEBUG_OUTPUT
+ debug() << (i>0 ? " || " : "") << from_expr(ns,"",strategy_cond_exprs[i]) ;
+#endif
strategy_cond_literals[i] = solver.convert(strategy_cond_exprs[i]);
strategy_cond_exprs[i] = literal_exprt(strategy_cond_literals[i]);
}
+#ifdef DEBUG_OUTPUT
+ debug() << eom;
+#endif
solver << disjunction(strategy_cond_exprs);
+ #ifdef DEBUG_OUTPUT
+ debug() << "solve(): ";
+#endif
+
if (solver() == decision_proceduret::D_SATISFIABLE) // improvement check
{
+#ifdef DEBUG_OUTPUT
+ debug() << "SAT" << eom;
+#endif
+
+#ifdef DEBUG_OUTPUT
+ for(unsigned i=0; iis_in_conflict(solver.formula[i]))
+ debug() << "is_in_conflict: " << solver.formula[i] << eom;
+ else
+ debug() << "not_in_conflict: " << solver.formula[i] << eom;
+ }
+#endif
+ }
solver.pop_context();
return improved;
From 500bd9d5610033964a8cddf86e35b95b22a68bb2 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 26 Aug 2016 12:35:58 +0100
Subject: [PATCH 017/322] Heap domain: improve inference of 'path' predicates.
Not working for loops with nondeterministic number of iterations.
---
src/domains/heap_domain.cpp | 148 ++++++++++++++++++++++-----
src/domains/heap_domain.h | 115 ++++++++++++++++-----
src/domains/strategy_solver_heap.cpp | 128 +++++++++++++++++++----
src/domains/strategy_solver_heap.h | 2 +
4 files changed, 321 insertions(+), 72 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 65260f45e..ee5eed64a 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -4,10 +4,12 @@
#include "heap_domain.h"
#include "util.h"
+#include
+#include
/**
* Initialize value.
- * Clears each pointer destinations.
+ * Clears each pointer paths and points_to predicates.
* @param value
*/
void heap_domaint::initialize(domaint::valuet &value)
@@ -15,7 +17,10 @@ void heap_domaint::initialize(domaint::valuet &value)
heap_valuet &val = static_cast(value);
val.resize(templ.size());
for (unsigned row = 0; row < templ.size(); ++row)
- val[row].dests.clear();
+ {
+ val[row].paths.clear();
+ val[row].points_to.clear();
+ }
}
/**
@@ -57,6 +62,9 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
templ_row.post_guard = v1->post_guard;
templ_row.aux_expr = v1->post_guard;
templ_row.kind = v1->kind;
+ // Check if the pointer itself is field of a dynamic object
+ const std::string identifier = id2string(to_symbol_expr(v1->var).get_identifier());
+ templ_row.dynamic = identifier.find("dynamic_object$") != std::string::npos;
}
}
}
@@ -81,11 +89,10 @@ exprt heap_domaint::to_pre_constraints(const heap_domaint::heap_valuet &value) c
* Create exit constraint expression for each row.
* Each expression is negation of row expression (for solving exists forall problem).
* @param value Value
- * @param cond_exprs Constraint expressions
- * @param value_exprs Template expressions (variables)
+ * @param cond_exprs Output - constraint expressions
+ * @param value_exprs Output - template expressions (row variables)
*/
-void heap_domaint::make_not_post_constraints(const heap_domaint::heap_valuet &value,
- exprt::operandst &cond_exprs,
+void heap_domaint::make_not_post_constraints(const heap_valuet &value, exprt::operandst &cond_exprs,
exprt::operandst &value_exprs)
{
assert(value.size() == templ.size());
@@ -114,10 +121,8 @@ exprt heap_domaint::get_row_pre_constraint(const rowt &row, const row_valuet &ro
kindt k = templ_row.kind;
// For exit variables the result is true
if (k == OUT || k == OUTL) return true_exprt();
- if (row_value.dests.empty())
- // Bottom is false
- return implies_exprt(templ_row.pre_guard, false_exprt());
- return implies_exprt(templ_row.pre_guard, row_value.get_row_expr(templ_row.expr, ns));
+
+ return implies_exprt(templ_row.pre_guard, row_value.get_row_expr(templ_row.expr));
}
/**
@@ -132,10 +137,8 @@ exprt heap_domaint::get_row_post_constraint(const rowt &row, const row_valuet &r
const template_rowt &templ_row = templ[row];
// For entry variables the result is true
if (templ_row.kind == IN) return true_exprt();
- if (row_value.dests.empty())
- // Bottom is false
- return implies_exprt(templ_row.post_guard, false_exprt());
- exprt c = implies_exprt(templ_row.post_guard, row_value.get_row_expr(templ_row.expr, ns));
+
+ exprt c = implies_exprt(templ_row.post_guard, row_value.get_row_expr(templ_row.expr));
if (templ_row.kind == LOOP) rename(c);
return c;
}
@@ -145,16 +148,78 @@ exprt heap_domaint::get_row_post_constraint(const rowt &row, const row_valuet &r
* @param row Row number
* @param value Value
* @param dest New destination to add
+ * @param dyn_obj Dynamic object for that the path passes through (is nil if path can have zero
+ * length).
* @return True if insertion took place (dest did not exist in the row value)
*/
-bool heap_domaint::add_row_dest(const heap_domaint::rowt &row,
- heap_domaint::heap_valuet &value,
- const exprt &dest)
+bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt &dest,
+ const dyn_objt &dyn_obj)
{
assert(row < value.size());
assert(value.size() == templ.size());
- auto new_dest = value[row].dests.insert(dest);
- return new_dest.second;
+
+ auto &path_set = value[row].paths;
+
+ if (path_set.find(dest) == path_set.end())
+ {
+ // Path does not exist yet
+ std::set dyn_obj_set;
+ bool zero_path = true;
+ if (dyn_obj.first.id() != ID_nil)
+ { // Path doesn't have zero length
+ dyn_obj_set.insert(dyn_obj);
+ zero_path = false;
+ }
+ path_set.emplace(dest, dyn_obj_set, zero_path);
+ return true;
+ }
+ else
+ {
+ // Path exists already
+ if (dyn_obj.first.id() == ID_nil) return false;
+ // Try to insert new dynamic object belonging to the path
+ return path_set.find(dest)->dyn_objects.insert(dyn_obj).second;
+ }
+}
+
+/**
+ * Add all paths of one pointer as the destinations of another pointer.
+ * @param to Row to add new paths to
+ * @param from Row to add paths from
+ * @param value Heap value
+ * @param dyn_obj Dynamic object that all the paths pass through (it belongs to path segment from
+ * one pointer to another.
+ * @return True if any path was added or changed, otherwise false.
+ */
+bool heap_domaint::add_all_paths(const rowt &to, const rowt &from, heap_valuet &value,
+ const dyn_objt &dyn_obj)
+{
+ bool result = false;
+ for (auto &path : value[from].paths)
+ {
+ // Add the path with new dynamic object
+ if (add_row_path(to, value, path.destination, dyn_obj))
+ result = true;
+ for (auto &o : path.dyn_objects)
+ { // Add all dynamic objects of the original path
+ if (add_row_path(to, value, path.destination, o))
+ result = true;
+ }
+ }
+ return result;
+}
+
+/**
+ * Add new points to address to a row.
+ * @param row Value row
+ * @param value Heap value
+ * @param dyn_obj New dynamic object that the row variable can point to.
+ * @return True if the object was really added.
+ */
+bool heap_domaint::add_points_to(const rowt &row, heap_valuet &value, const dyn_objt &dyn_obj)
+{
+ auto new_pt = value[row].points_to.insert(dyn_obj);
+ return new_pt.second;
}
void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
@@ -182,7 +247,8 @@ void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
assert(false);
}
out << "( " << from_expr(ns, "", templ_row.expr) << " == "
- << from_expr(ns, "", val[row].get_row_expr(templ_row.expr, ns)) << " )" << std::endl;
+ << from_expr(ns, "", val[row].get_row_expr(templ_row.expr)) << " )"
+ << std::endl;
}
}
@@ -234,17 +300,18 @@ void heap_domaint::project_on_vars(domaint::valuet &value,
const row_valuet &row_val = val[row];
if (templ_row.kind == LOOP)
{
- if (row_val.dests.empty())
+ if (row_val.paths.empty())
c.push_back(implies_exprt(templ_row.pre_guard, false_exprt()));
else
- c.push_back(implies_exprt(templ_row.pre_guard, row_val.get_row_expr(templ_row.expr, ns)));
+ c.push_back(implies_exprt(templ_row.pre_guard,
+ row_val.get_row_expr(templ_row.expr)));
}
else
{
- if (row_val.dests.empty())
+ if (row_val.paths.empty())
c.push_back(false_exprt());
else
- c.push_back(row_val.get_row_expr(templ_row.expr, ns));
+ c.push_back(row_val.get_row_expr(templ_row.expr));
}
}
result = conjunction(c);
@@ -262,3 +329,36 @@ exprt heap_domaint::value_to_ptr_exprt(const exprt &expr)
return expr;
}
+
+/**
+ * Join two abstract heap values. Join of each row is union of the two corresponding sets.
+ * @param value1 First value and result of join
+ * @param value2 Second value
+ */
+void heap_domaint::join(domaint::valuet &value1, const domaint::valuet &value2)
+{
+ heap_valuet &val1 = static_cast(value1);
+ const heap_valuet &val2 = static_cast(value2);
+ assert(val1.size() == templ.size());
+ assert(val2.size() == val1.size());
+ for (rowt row = 0; row < templ.size(); ++row)
+ { // Insert all elements of second set to first
+ val1[row].paths.insert(val2[row].paths.begin(), val2[row].paths.end());
+ }
+}
+
+/**
+ * Check whether expression is NULL pointer.
+ * @param expr Expression to check
+ * @return True if expr is NULL pointer
+ */
+bool heap_domaint::is_null_ptr(const exprt &expr)
+{
+ if (expr.id() == ID_constant && to_constant_expr(expr).get_value() == ID_NULL)
+ return true;
+ if (expr.id() == ID_plus)
+ return is_null_ptr(expr.op0()) || is_null_ptr(expr.op1());
+ if (expr.id() == ID_typecast)
+ return is_null_ptr(to_typecast_expr(expr).op());
+ return false;
+}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 47e4e8083..55a08cd83 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -13,6 +13,8 @@ class heap_domaint : public domaint
{
public:
typedef unsigned rowt;
+ typedef vart next_fieldt;
+ typedef std::pair dyn_objt;
heap_domaint(unsigned int _domain_number, replace_mapt &_renaming_map,
const var_specst &var_specs,
@@ -23,41 +25,91 @@ class heap_domaint : public domaint
}
/**
- * Value of a row is set of addresses reachable from pointer (corresponding to template row) via
- * field 'next'.
+ * Value of a row is set of paths in the heap leading from row variable
*/
struct row_valuet
{
- std::set dests;
+ /**
+ * Path in a heap. Contains:
+ * - destination object
+ * - set of dynamic objects - this is the set of ssa objects that the path is composed of
+ * - boolean value expressing whether path can have zero length
+ * Paths are ordered by destination only as it is unique within a value row.
+ */
+ struct patht
+ {
+ exprt destination;
+ mutable std::set dyn_objects;
+ mutable bool zero_length;
+
+ patht(const exprt &dest_) : destination(dest_) {}
+
+ patht(const exprt &dest_, const std::set &dyn_objs_, const bool zero_l_)
+ : destination(dest_), dyn_objects(dyn_objs_), zero_length(zero_l_) {}
+
+ bool operator<(const patht &rhs) const
+ {
+ return destination < rhs.destination;
+ }
+
+ bool operator==(const patht &rhs) const
+ {
+ return destination == rhs.destination;
+ }
+ };
+
+ std::set paths; /**< Set of paths leading from the row variable */
+ std::set points_to; /**< Set of objects the row variable can point to */
/**
- * Get expression for the row value. The expression has form of disjuncion of equalities.
- * Equality can be:
- * (templ_expr == NULL) when pointer is NULL
- * (templ_expr->next == dest) when pointer points to dest via 'next' field
+ * Get expression for the row value. It is a conjunction of path expressions.
+ * Expression of path leading from variable 'p' to destination 'd' via set of objects 'O'
+ * has form:
+ * p = d || if path can have zero length
+ * p = &o && (o.next = d || o.next = o') where o,o' belong to O and p can point to &o
* @param templ_expr Pointer variable of the template row
- * @param ns Namespace
- * @return Expression corresponding to value - disjunction of equalities.
+ * @return Row value expression in the described form
*/
- exprt get_row_expr(const vart &templ_expr, const namespacet &ns) const
+ exprt get_row_expr(const vart &templ_expr) const
{
- exprt::operandst dis;
- for (auto dest : dests)
- {
- if (dest.id() == ID_constant && to_constant_expr(dest).get_value() == ID_NULL)
- dis.push_back(equal_exprt(templ_expr, dest));
- else
+ if (paths.empty()) return false_exprt();
+ exprt::operandst result;
+
+ for (auto &path : paths)
+ { // path(p, d)[O]
+ const exprt &dest = path.destination;
+ exprt::operandst path_expr;
+
+ if (path.zero_length)
{
- assert(templ_expr.type().id() == ID_pointer);
- const typet &struct_type = templ_expr.type().subtype();
- dis.push_back(
- equal_exprt(member_exprt(dereference_exprt(templ_expr, struct_type),
- "next",
- dest.type()),
- dest));
+ // p = d
+ path_expr.push_back(equal_exprt(templ_expr, dest));
}
+ for (const dyn_objt &obj1 : path.dyn_objects)
+ {
+ if (points_to.find(obj1) != points_to.end())
+ {
+ // p = &o
+ exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
+
+ exprt::operandst step_expr;
+ exprt next_expr = obj1.second;
+ // o.next = d
+ step_expr.push_back(equal_exprt(next_expr, dest));
+
+ for (auto &obj2 : path.dyn_objects)
+ { // o.next = o'
+ step_expr.push_back(equal_exprt(next_expr, address_of_exprt(obj2.first)));
+ }
+
+ path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
+ }
+ }
+
+ result.push_back(disjunction(path_expr));
}
- return disjunction(dis);
+
+ return conjunction(result);
}
};
@@ -72,6 +124,7 @@ class heap_domaint : public domaint
vart expr;
exprt aux_expr;
kindt kind;
+ bool dynamic;
};
typedef std::vector templatet;
@@ -89,8 +142,13 @@ class heap_domaint : public domaint
exprt get_row_post_constraint(const rowt &row, const row_valuet &row_value);
- // Add new destination to a row
- bool add_row_dest(const rowt &row, heap_valuet &value, const exprt &dest);
+ // Add new predicates to a row value (path, or points_to)
+ bool add_row_path(const rowt &row, heap_valuet &value, const exprt &dest,
+ const dyn_objt &dyn_obj);
+
+ bool add_all_paths(const rowt &to, const rowt &from, heap_valuet &value, const dyn_objt &dyn_obj);
+
+ bool add_points_to(const rowt &row, heap_valuet &value, const dyn_objt &dyn_obj);
// Printing
virtual void output_value(std::ostream &out, const valuet &value,
@@ -104,6 +162,11 @@ class heap_domaint : public domaint
// Conversion of solver value to expression
static exprt value_to_ptr_exprt(const exprt &expr);
+ // Join of values
+ virtual void join(valuet &value1, const valuet &value2) override;
+
+ static bool is_null_ptr(const exprt &expr);
+
protected:
templatet templ;
namespacet ns;
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 030a7c92d..ef3d6dba0 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -2,6 +2,8 @@
* Viktor Malik, 12.8.2016 (c).
*/
+//#define DEBUG_OUTPUT
+
#include "strategy_solver_heap.h"
bool strategy_solver_heapt::iterate(invariantt &_inv)
@@ -15,7 +17,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
// Entry value constraints
exprt pre_expr = heap_domain.to_pre_constraints(inv);
#ifdef DEBUG_OUTPUT
- debug() << "pre-inv: " << from_expr(ns,"",pre_expr) << eom;
+ debug() << "pre-inv: " << from_expr(ns, "", pre_expr) << eom;
#endif
solver << pre_expr;
@@ -31,7 +33,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
for (unsigned i = 0; i < strategy_cond_exprs.size(); ++i)
{
#ifdef DEBUG_OUTPUT
- debug() << (i>0 ? " || " : "") << from_expr(ns,"",strategy_cond_exprs[i]) ;
+ debug() << (i > 0 ? " || " : "") << from_expr(ns, "", strategy_cond_exprs[i]);
#endif
strategy_cond_literals[i] = solver.convert(strategy_cond_exprs[i]);
strategy_cond_exprs[i] = literal_exprt(strategy_cond_literals[i]);
@@ -41,7 +43,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
#endif
solver << disjunction(strategy_cond_exprs);
- #ifdef DEBUG_OUTPUT
+#ifdef DEBUG_OUTPUT
debug() << "solve(): ";
#endif
@@ -52,25 +54,28 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
#endif
#ifdef DEBUG_OUTPUT
- for(unsigned i=0; i= 0);
+ exprt next_val_expr = heap_domain.templ[next_val_index].expr;
+
+ // Add all paths from obj.next to p
+ if (heap_domain.add_all_paths(row, (unsigned) next_val_index, inv,
+ std::make_pair(obj, next_val_expr)))
+ improved = true;
+ debug() << "add all paths: " << from_expr(ns, "", next_val_expr) << ", through: "
+ << from_expr(ns, "", obj) << eom;
+
+ if (obj.type().get_bool("#dynamic"))
+ { // Add points to information
+ assert(obj.id() == ID_symbol);
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, next_val_expr)))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+ }
+ }
+
+ if (heap_domain.templ[row].dynamic)
+ { // Recursively check all expressions and update those that point to the dynamic object
+ // that this row variable belongs to.
+ for (unsigned j = 0; j < heap_domain.templ.size(); ++j)
+ {
+ for (auto &pt : inv[j].points_to)
+ {
+ exprt pre_pointer = heap_domain.templ[row].expr;
+ if (pre_pointer == pt.second)
+ {
+ if (heap_domain.add_all_paths(j, row, inv, pt))
+ improved = true;
+ debug() << "recursively updating row: " << j << eom;
+ debug() << "add all paths: " << from_expr(ns, "", pre_pointer) << ", through: "
+ << from_expr(ns, "", pt.first) << eom;
+ }
+ }
+ }
+ }
}
}
}
+
else
{
#ifdef DEBUG_OUTPUT
@@ -98,17 +155,44 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
#endif
#ifdef DEBUG_OUTPUT
- for(unsigned i=0; iis_in_conflict(solver.formula[i]))
+ if (solver.solver->is_in_conflict(solver.formula[i]))
debug() << "is_in_conflict: " << solver.formula[i] << eom;
else
debug() << "not_in_conflict: " << solver.formula[i] << eom;
- }
+ }
#endif
}
solver.pop_context();
return improved;
+}
+
+/**
+ * Find the template row that contains next field of given object as row variable.
+ * @param obj
+ * @return Template row of obj.next
+ */
+int strategy_solver_heapt::next_field_row(const exprt &obj) const
+{
+ // Create "next" member expression
+ exprt next_expr = member_exprt(obj, "next", pointer_typet(obj.type()));
+ std::string next_expr_id = from_expr(ns, "", next_expr);
+
+ int result = -1;
+ for (unsigned i = 0; i < strategy_value_exprs.size(); ++i)
+ { // Find the corresponding strategy value expression
+ exprt val_expr = strategy_value_exprs[i];
+ assert(val_expr.id() == ID_symbol);
+ std::string val_expr_id = id2string(to_symbol_expr(val_expr).get_identifier());
+ // Compare identifiers of row expression and "next" member expresssion
+ if (val_expr_id.find(next_expr_id) != std::string::npos)
+ {
+ result = i;
+ break;
+ }
+ }
+ return result;
}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index 2de00e769..09f000b98 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -21,6 +21,8 @@ class strategy_solver_heapt : public strategy_solver_baset
protected:
heap_domaint &heap_domain;
+
+ int next_field_row(const exprt &obj) const;
};
From d9976b1b33fb23acef0cc6084fa3c62b54281d47 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 26 Aug 2016 12:41:00 +0100
Subject: [PATCH 018/322] Regression tests for single linked lists.
---
regression/heap/sll1_simple/main.c | 69 +++++++++++
regression/heap/sll1_simple/test.desc | 6 +
regression/heap/sll2_nondet_loops/main.c | 66 ++++++++++
regression/heap/sll2_nondet_loops/test.desc | 6 +
regression/heap/sll_to_dll1_reverse/main.c | 114 ++++++++++++++++++
regression/heap/sll_to_dll1_reverse/test.desc | 6 +
6 files changed, 267 insertions(+)
create mode 100644 regression/heap/sll1_simple/main.c
create mode 100644 regression/heap/sll1_simple/test.desc
create mode 100644 regression/heap/sll2_nondet_loops/main.c
create mode 100644 regression/heap/sll2_nondet_loops/test.desc
create mode 100644 regression/heap/sll_to_dll1_reverse/main.c
create mode 100644 regression/heap/sll_to_dll1_reverse/test.desc
diff --git a/regression/heap/sll1_simple/main.c b/regression/heap/sll1_simple/main.c
new file mode 100644
index 000000000..ef5784cb8
--- /dev/null
+++ b/regression/heap/sll1_simple/main.c
@@ -0,0 +1,69 @@
+#include
+
+extern int __VERIFIER_nondet_int(void);
+
+struct node {
+ struct node *next;
+};
+
+static struct node* alloc_node(void)
+{
+ struct node *ptr = malloc(sizeof *ptr);
+ if (!ptr)
+ abort();
+
+ ptr->next = NULL;
+ return ptr;
+}
+
+static void chain_node(struct node **ppnode)
+{
+ struct node *node = alloc_node();
+ node->next = *ppnode;
+ *ppnode = node;
+}
+
+static struct node* create_sll(const struct node **pp1, const struct node **pp2)
+{
+ *pp2 = NULL;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ chain_node(pp2);
+ }
+
+ *pp1 = *pp2;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ chain_node(pp1);
+ }
+
+ struct node *list = *pp1;
+
+ for (int i = 0; i < 2; ++i)
+ {
+ chain_node(&list);
+ }
+
+ return list;
+}
+
+void check_seq_next(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->next; end != beg; beg = beg->next)
+ assert(beg != NULL);
+}
+
+void main()
+{
+ const struct node *p1, *p2;
+
+ struct node *list = create_sll(&p1, &p2);
+ check_seq_next(list, p1);
+ check_seq_next(p1, p2);
+
+}
+
diff --git a/regression/heap/sll1_simple/test.desc b/regression/heap/sll1_simple/test.desc
new file mode 100644
index 000000000..ed14b476a
--- /dev/null
+++ b/regression/heap/sll1_simple/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap --inline --no-propagation
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/sll2_nondet_loops/main.c b/regression/heap/sll2_nondet_loops/main.c
new file mode 100644
index 000000000..5f44c5a68
--- /dev/null
+++ b/regression/heap/sll2_nondet_loops/main.c
@@ -0,0 +1,66 @@
+#include
+
+extern int __VERIFIER_nondet_int(void);
+
+struct node {
+ struct node *next;
+};
+
+static struct node* alloc_node(void)
+{
+ struct node *ptr = malloc(sizeof *ptr);
+ if (!ptr)
+ abort();
+
+ ptr->next = NULL;
+ return ptr;
+}
+
+static void chain_node(struct node **ppnode)
+{
+ struct node *node = alloc_node();
+ node->next = *ppnode;
+ *ppnode = node;
+}
+
+static struct node* create_sll(const struct node **pp1, const struct node **pp2)
+{
+ *pp2 = NULL;
+
+ do
+ chain_node(pp2);
+ while (__VERIFIER_nondet_int());
+
+ *pp1 = *pp2;
+
+ do
+ chain_node(pp1);
+ while (__VERIFIER_nondet_int());
+
+ struct node *list = *pp1;
+
+ do
+ chain_node(&list);
+ while (__VERIFIER_nondet_int());
+
+ return list;
+}
+
+void check_seq_next(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->next; end != beg; beg = beg->next)
+ assert(beg != NULL);
+}
+
+void main()
+{
+ const struct node *p1, *p2;
+
+ struct node *list = create_sll(&p1, &p2);
+ check_seq_next(list, p1);
+ check_seq_next(p1, p2);
+
+}
+
diff --git a/regression/heap/sll2_nondet_loops/test.desc b/regression/heap/sll2_nondet_loops/test.desc
new file mode 100644
index 000000000..ed14b476a
--- /dev/null
+++ b/regression/heap/sll2_nondet_loops/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap --inline --no-propagation
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/regression/heap/sll_to_dll1_reverse/main.c b/regression/heap/sll_to_dll1_reverse/main.c
new file mode 100644
index 000000000..e8d0d1829
--- /dev/null
+++ b/regression/heap/sll_to_dll1_reverse/main.c
@@ -0,0 +1,114 @@
+#include
+
+extern int __VERIFIER_nondet_int(void);
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+static struct node* alloc_node(void)
+{
+ struct node *ptr = malloc(sizeof *ptr);
+ if (!ptr)
+ abort();
+
+ ptr->next = NULL;
+ ptr->prev = NULL;
+ return ptr;
+}
+
+static void chain_node(struct node **ppnode)
+{
+ struct node *node = alloc_node();
+ node->next = *ppnode;
+ *ppnode = node;
+}
+
+static struct node* create_sll(const struct node **pp1, const struct node **pp2)
+{
+ *pp2 = NULL;
+
+ do
+ chain_node(pp2);
+ while (__VERIFIER_nondet_int());
+
+ *pp1 = *pp2;
+
+ while (__VERIFIER_nondet_int())
+ chain_node(pp1);
+
+ struct node *list = *pp1;
+
+ do
+ chain_node(&list);
+ while (__VERIFIER_nondet_int());
+
+ return list;
+}
+
+void init_back_link(struct node *list) {
+ for (;;) {
+ struct node *next = list->next;
+ if (!next)
+ return;
+
+ next->prev = list;
+ list = next;
+ }
+}
+
+void reverse_dll(struct node *list) {
+ while (list) {
+ struct node *next = list->next;
+ list->next = list->prev;
+ list->prev = next;
+ list = next;
+ }
+}
+
+void remove_fw_link(struct node *list) {
+ while (list) {
+ struct node *next = list->next;
+ list->next = NULL;
+ list = next;
+ }
+}
+
+void check_seq_next(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->next; end != beg; beg = beg->next)
+ assert(beg != NULL);
+}
+
+void check_seq_prev(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->prev; end != beg; beg = beg->prev)
+ assert(beg != NULL);
+}
+
+void main()
+{
+ const struct node *p1, *p2;
+
+ struct node *list = create_sll(&p1, &p2);
+ check_seq_next(p1, p2);
+ assert(p1->prev == NULL);
+ assert(p2->prev == NULL);
+
+ init_back_link(list);
+ check_seq_next(p1, p2);
+ check_seq_prev(p2, p1);
+
+ reverse_dll(list);
+ check_seq_prev(p1, p2);
+ check_seq_next(p2, p1);
+
+ remove_fw_link(list);
+ check_seq_prev(p1, p2);
+}
+
diff --git a/regression/heap/sll_to_dll1_reverse/test.desc b/regression/heap/sll_to_dll1_reverse/test.desc
new file mode 100644
index 000000000..92784083a
--- /dev/null
+++ b/regression/heap/sll_to_dll1_reverse/test.desc
@@ -0,0 +1,6 @@
+KNOWNBUG
+main.c
+--heap --inline --no-propagation
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
From 8ae53e5539541acca1a2925f22820b6156fdae15 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 26 Aug 2016 14:29:47 +0100
Subject: [PATCH 019/322] Heap domain: add points_to information to invariant.
Now works also for loops with nondeterministic number of iterations.
---
src/domains/heap_domain.h | 21 ++++++++++++++++++---
src/domains/strategy_solver_heap.cpp | 8 ++++++--
2 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 55a08cd83..62d5901b0 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -59,10 +59,13 @@ class heap_domaint : public domaint
};
std::set paths; /**< Set of paths leading from the row variable */
- std::set points_to; /**< Set of objects the row variable can point to */
+ std::set points_to; /**< Set of objects (or NULL) the row variable can point to */
/**
- * Get expression for the row value. It is a conjunction of path expressions.
+ * Get expression for the row value. It is a conjunction of points to expression and path
+ * expressions.
+ * Points to expression is disjunction of equalities:
+ * p = &o (NULL) for each object 'o' (or NULL) from points_to set
* Expression of path leading from variable 'p' to destination 'd' via set of objects 'O'
* has form:
* p = d || if path can have zero length
@@ -72,9 +75,21 @@ class heap_domaint : public domaint
*/
exprt get_row_expr(const vart &templ_expr) const
{
- if (paths.empty()) return false_exprt();
+ if (paths.empty() && points_to.empty()) return false_exprt();
exprt::operandst result;
+ if (!points_to.empty())
+ { // Points to expression
+ exprt::operandst pt_expr;
+ for (auto &pt : points_to)
+ {
+ pt_expr.push_back(equal_exprt(templ_expr,
+ is_null_ptr(pt.first) ?
+ pt.first : address_of_exprt(pt.first)));
+ }
+ result.push_back(disjunction(pt_expr));
+ }
+
for (auto &path : paths)
{ // path(p, d)[O]
const exprt &dest = path.destination;
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index ef3d6dba0..3263dcc27 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -92,11 +92,15 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (heap_domain.is_null_ptr(ptr_value))
{
- if (heap_domain.add_row_path(row, inv,
- null_pointer_exprt(to_pointer_type(ptr_value.type())),
+ exprt null_expr = null_pointer_exprt(to_pointer_type(ptr_value.type()));
+ if (heap_domain.add_row_path(row, inv, null_expr,
std::make_pair(nil_exprt(), nil_exprt())))
improved = true;
debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
+
+ if (heap_domain.add_points_to(row, inv, std::make_pair(null_expr, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", ptr_value) << eom;
}
else
{
From a58b6ba15ff021f3ddcc7d5714410be892b9cfca Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Tue, 13 Sep 2016 16:55:37 +0100
Subject: [PATCH 020/322] Heap domain: handle simple doubly-linked list. See
regression/heap/dll1_simple.
---
regression/heap/dll1_simple/main.c | 107 +++++++++++++++++++++++
regression/heap/dll1_simple/test.desc | 6 ++
src/domains/heap_domain.cpp | 101 +++++++++++++++-------
src/domains/heap_domain.h | 40 +++++----
src/domains/strategy_solver_heap.cpp | 110 +++++++++++++++---------
src/domains/strategy_solver_heap.h | 2 +-
src/domains/template_generator_base.cpp | 2 +-
7 files changed, 279 insertions(+), 89 deletions(-)
create mode 100644 regression/heap/dll1_simple/main.c
create mode 100644 regression/heap/dll1_simple/test.desc
diff --git a/regression/heap/dll1_simple/main.c b/regression/heap/dll1_simple/main.c
new file mode 100644
index 000000000..0dae16a0d
--- /dev/null
+++ b/regression/heap/dll1_simple/main.c
@@ -0,0 +1,107 @@
+extern void __VERIFIER_error() __attribute__ ((__noreturn__));
+
+#include
+
+extern int __VERIFIER_nondet_int(void);
+
+static void fail(void) {
+ERROR: __VERIFIER_error();
+}
+
+#define ___SL_ASSERT(cond) do { \
+ if (!(cond)) \
+ fail(); \
+ assert(cond); \
+} while (0)
+
+struct node {
+ struct node *next;
+ struct node *prev;
+};
+
+static struct node* alloc_node(void)
+{
+ struct node *ptr = malloc(sizeof *ptr);
+
+ ptr->next = NULL;
+ ptr->prev = NULL;
+ return ptr;
+}
+
+static void chain_node(struct node **ppnode)
+{
+ struct node *node = alloc_node();
+ node->next = *ppnode;
+ *ppnode = node;
+}
+
+static struct node* create_sll(const struct node **pp1, const struct node **pp2)
+{
+ struct node *list = NULL;
+
+ do
+ chain_node(&list);
+ while (__VERIFIER_nondet_int());
+
+ return list;
+}
+
+void init_back_link(struct node *list) {
+ while (list) {
+ struct node *next = list->next;
+ // if (!next)
+ // return;
+
+ next->prev = list;
+ list = next;
+ }
+}
+
+void reverse_dll(struct node *list) {
+ while (list) {
+ struct node *next = list->next;
+ list->next = list->prev;
+ list->prev = next;
+ list = next;
+ }
+}
+
+void remove_fw_link(struct node *list) {
+ while (list) {
+ struct node *next = list->next;
+ list->next = NULL;
+ list = next;
+ }
+}
+
+void check_seq_next(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->next; end != beg; beg = beg->next)
+ assert(beg != NULL);
+}
+
+void check_seq_prev(const struct node *beg, const struct node *const end) {
+ assert(beg != NULL);
+ assert(end != NULL);
+
+ for (beg = beg->prev; end != beg; beg = beg->prev)
+ assert(beg != NULL);
+}
+
+void main()
+{
+ const struct node *p1, *p2;
+
+ struct node *list = create_sll(&p1, &p2);
+
+ init_back_link(list);
+
+ // reverse_dll(list);
+ // check_seq_prev(p1, p2);
+ // check_seq_next(p2, p1);
+
+ remove_fw_link(list);
+}
+
diff --git a/regression/heap/dll1_simple/test.desc b/regression/heap/dll1_simple/test.desc
new file mode 100644
index 000000000..ed14b476a
--- /dev/null
+++ b/regression/heap/dll1_simple/test.desc
@@ -0,0 +1,6 @@
+CORE
+main.c
+--heap --inline --no-propagation
+^EXIT=0$
+^SIGNAL=0$
+^VERIFICATION SUCCESSFUL$
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index ee5eed64a..c4daa5062 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -25,7 +25,8 @@ void heap_domaint::initialize(domaint::valuet &value)
/**
* Create domain template for given set of variables.
- * Template contains only pointers to structures containing field 'next'.
+ * Template contains row for each member of each variable being pointer to struct,
+ * and a row for each flattened member of a struct.
* @param var_specs Set of program variables.
* @param ns Namespace
*/
@@ -37,35 +38,46 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
for (auto v1 = var_specs.begin(); v1 != var_specs.end(); ++v1)
{
- // Check if v1 is struct and has 'next' field
- bool has_next = false;
+ // Create template for each pointer to struct
const vart &var1 = v1->var;
if (var1.type().id() == ID_pointer)
{
const typet &pointed_type = ns.follow(var1.type().subtype());
if (pointed_type.id() == ID_struct)
{
+ // Check if var1 is member field of dynamic object
+ const std::string identifier = id2string(to_symbol_expr(v1->var).get_identifier());
+ bool dynamic = identifier.find("dynamic_object$") != std::string::npos;
+
for (auto &component : to_struct_type(pointed_type).components())
{
- if (component.get_name() == "next")
- has_next = true;
+ if (!dynamic ||
+ identifier.find("." + id2string(component.get_name())) != std::string::npos)
+ {
+ templ.push_back(template_rowt());
+ template_rowt &templ_row = templ.back();
+ templ_row.expr = v1->var;
+ templ_row.member = component.get_name();
+ templ_row.pre_guard = v1->pre_guard;
+ templ_row.post_guard = v1->post_guard;
+ templ_row.aux_expr = v1->post_guard;
+ templ_row.kind = v1->kind;
+ templ_row.dynamic = dynamic;
+ if (dynamic)
+ {
+ int loc_num = get_symbol_loc(var1);
+ std::string var1_id = id2string(to_symbol_expr(var1).get_identifier());
+ std::string do_base_id = var1_id.substr(0, var1_id.find_last_of('.'));
+ // TODO just add the whole suffix
+ irep_idt do_id = do_base_id + "#lb" + std::to_string(loc_num);
+ templ_row.dyn_obj = symbol_exprt(do_id, var1.type().subtype());
+ }
+ else
+ templ_row.dyn_obj = nil_exprt();
+ }
}
}
}
-
- if (has_next)
- { // Create template
- templ.push_back(template_rowt());
- template_rowt &templ_row = templ.back();
- templ_row.expr = v1->var;
- templ_row.pre_guard = v1->pre_guard;
- templ_row.post_guard = v1->post_guard;
- templ_row.aux_expr = v1->post_guard;
- templ_row.kind = v1->kind;
- // Check if the pointer itself is field of a dynamic object
- const std::string identifier = id2string(to_symbol_expr(v1->var).get_identifier());
- templ_row.dynamic = identifier.find("dynamic_object$") != std::string::npos;
- }
}
}
@@ -176,7 +188,12 @@ bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt
else
{
// Path exists already
- if (dyn_obj.first.id() == ID_nil) return false;
+ if (dyn_obj.first.id() == ID_nil)
+ {
+ bool result = path_set.find(dest)->zero_length;
+ path_set.find(dest)->zero_length = true;
+ return !result;
+ }
// Try to insert new dynamic object belonging to the path
return path_set.find(dest)->dyn_objects.insert(dyn_obj).second;
}
@@ -280,7 +297,9 @@ void heap_domaint::output_domain(std::ostream &out, const namespacet &ns) const
assert(false);
}
const vart &var = templ_row.expr;
- out << "?path(" << from_expr(ns, "", var) << ", DESTINATIONS)" << std::endl;
+ const irep_idt &member = templ_row.member;
+ out << i << ": ?path(" << from_expr(ns, "", var) << ", " << member << ", DESTINATIONS)"
+ << std::endl;
}
}
@@ -300,18 +319,12 @@ void heap_domaint::project_on_vars(domaint::valuet &value,
const row_valuet &row_val = val[row];
if (templ_row.kind == LOOP)
{
- if (row_val.paths.empty())
- c.push_back(implies_exprt(templ_row.pre_guard, false_exprt()));
- else
- c.push_back(implies_exprt(templ_row.pre_guard,
- row_val.get_row_expr(templ_row.expr)));
+ c.push_back(implies_exprt(templ_row.pre_guard,
+ row_val.get_row_expr(templ_row.expr)));
}
else
{
- if (row_val.paths.empty())
- c.push_back(false_exprt());
- else
- c.push_back(row_val.get_row_expr(templ_row.expr));
+ c.push_back(row_val.get_row_expr(templ_row.expr));
}
}
result = conjunction(c);
@@ -362,3 +375,31 @@ bool heap_domaint::is_null_ptr(const exprt &expr)
return is_null_ptr(to_typecast_expr(expr).op());
return false;
}
+
+/**
+ * Get location number of a given symbol.
+ * @param expr Symbol expression.
+ * @return Number of location, or -1 if symbol is input.
+ */
+int heap_domaint::get_symbol_loc(const exprt &expr)
+{
+ assert(expr.id() == ID_symbol);
+ std::string expr_id = id2string(to_symbol_expr(expr).get_identifier());
+ if (expr_id.find('#') == std::string::npos) return -1;
+ std::string loc_str = expr_id.substr(expr_id.find_last_not_of("0123456789") + 1);
+ assert(!loc_str.empty());
+ return std::stoi(loc_str);
+}
+
+/**
+ * Get base name of a symbol.
+ * @param expr Symbol expression.
+ * @return Base name of a symbol (without suffix with location number).
+ */
+std::string heap_domaint::get_base_name(const exprt &expr)
+{
+ assert(expr.id() == ID_symbol);
+ std::string result = id2string(to_symbol_expr(expr).get_identifier());
+ result = result.substr(0, result.find_last_of('#'));
+ return result;
+}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 62d5901b0..d602ee17a 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -13,8 +13,8 @@ class heap_domaint : public domaint
{
public:
typedef unsigned rowt;
- typedef vart next_fieldt;
- typedef std::pair dyn_objt;
+ typedef vart member_fieldt;
+ typedef std::pair dyn_objt;
heap_domaint(unsigned int _domain_number, replace_mapt &_renaming_map,
const var_specst &var_specs,
@@ -66,10 +66,10 @@ class heap_domaint : public domaint
* expressions.
* Points to expression is disjunction of equalities:
* p = &o (NULL) for each object 'o' (or NULL) from points_to set
- * Expression of path leading from variable 'p' to destination 'd' via set of objects 'O'
- * has form:
- * p = d || if path can have zero length
- * p = &o && (o.next = d || o.next = o') where o,o' belong to O and p can point to &o
+ * Expression of path leading from variable 'p' to destination 'd' via field 'm' and
+ * passing through set of objects 'O' has form:
+ * p = d || if path can have zero length
+ * p = &o && (o.m = d || o.m = o') where o,o' belong to O and p can point to &o
* @param templ_expr Pointer variable of the template row
* @return Row value expression in the described form
*/
@@ -83,6 +83,7 @@ class heap_domaint : public domaint
exprt::operandst pt_expr;
for (auto &pt : points_to)
{
+ exprt lhs = templ_expr;
pt_expr.push_back(equal_exprt(templ_expr,
is_null_ptr(pt.first) ?
pt.first : address_of_exprt(pt.first)));
@@ -91,7 +92,7 @@ class heap_domaint : public domaint
}
for (auto &path : paths)
- { // path(p, d)[O]
+ { // path(p, m, d)[O]
const exprt &dest = path.destination;
exprt::operandst path_expr;
@@ -102,23 +103,20 @@ class heap_domaint : public domaint
}
for (const dyn_objt &obj1 : path.dyn_objects)
{
- if (points_to.find(obj1) != points_to.end())
- {
// p = &o
exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
exprt::operandst step_expr;
- exprt next_expr = obj1.second;
- // o.next = d
- step_expr.push_back(equal_exprt(next_expr, dest));
+ exprt member_expr = obj1.second;
+ // o.m = d
+ step_expr.push_back(equal_exprt(member_expr, dest));
for (auto &obj2 : path.dyn_objects)
- { // o.next = o'
- step_expr.push_back(equal_exprt(next_expr, address_of_exprt(obj2.first)));
+ { // o.m = o'
+ step_expr.push_back(equal_exprt(member_expr, address_of_exprt(obj2.first)));
}
path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
- }
}
result.push_back(disjunction(path_expr));
@@ -126,6 +124,11 @@ class heap_domaint : public domaint
return conjunction(result);
}
+
+ inline bool empty() const
+ {
+ return paths.empty() && points_to.empty();
+ }
};
class heap_valuet : public valuet, public std::vector
@@ -137,8 +140,10 @@ class heap_domaint : public domaint
guardt pre_guard;
guardt post_guard;
vart expr;
+ irep_idt member;
exprt aux_expr;
kindt kind;
+ exprt dyn_obj;
bool dynamic;
};
typedef std::vector templatet;
@@ -188,6 +193,11 @@ class heap_domaint : public domaint
void make_template(const var_specst &var_specs, const namespacet &ns);
+ // Utility functions
+ static int get_symbol_loc(const exprt &expr);
+
+ static std::string get_base_name(const exprt &expr);
+
friend class strategy_solver_heapt;
};
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 3263dcc27..2051dbc95 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -66,7 +66,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
}
for (unsigned i = 0; i < heap_domain.templ.size(); i++)
{
- exprt c = heap_domain.get_row_pre_constraint(i, inv[i]);
+ exprt c = heap_domain.get_row_pre_constraint(i, inv[i]).op1();
debug() << "cond: " << from_expr(ns, "", c) << " " <<
from_expr(ns, "", solver.get(c)) << eom;
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].pre_guard) <<
@@ -84,8 +84,10 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (solver.l_get(strategy_cond_literals[row]).is_true())
{
debug() << "updating row: " << row << eom;
- exprt pointer = strategy_value_exprs[row];
+ int actual_loc = heap_domain.get_symbol_loc(heap_domain.templ[row].expr);
+
+ exprt pointer = strategy_value_exprs[row];
exprt value = solver.get(pointer);
// Value from solver must be converted into expression
exprt ptr_value = heap_domain.value_to_ptr_exprt(value);
@@ -105,25 +107,37 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
else
{
// pointer points to the heap (p = &obj)
+ debug() << from_expr(ns, "", ptr_value) << eom;
assert(ptr_value.id() == ID_address_of);
- exprt obj = to_address_of_expr(ptr_value).object();
-
- // Find row with next field of pointed object (obj.next)
- int next_val_index = next_field_row(obj);
- assert(next_val_index >= 0);
- exprt next_val_expr = heap_domain.templ[next_val_index].expr;
-
- // Add all paths from obj.next to p
- if (heap_domain.add_all_paths(row, (unsigned) next_val_index, inv,
- std::make_pair(obj, next_val_expr)))
- improved = true;
- debug() << "add all paths: " << from_expr(ns, "", next_val_expr) << ", through: "
- << from_expr(ns, "", obj) << eom;
+ assert(to_address_of_expr(ptr_value).object().id() == ID_symbol);
+ symbol_exprt obj = to_symbol_expr(to_address_of_expr(ptr_value).object());
if (obj.type().get_bool("#dynamic"))
- { // Add points to information
- assert(obj.id() == ID_symbol);
- if (heap_domain.add_points_to(row, inv, std::make_pair(obj, next_val_expr)))
+ {
+ // Find row with corresponding member field of pointed object (obj.member)
+ if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
+ heap_domain.get_base_name(obj) ==
+ heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
+ {
+ --actual_loc;
+ }
+ int member_val_index = find_member_row(obj, heap_domain.templ[row].member,
+ actual_loc);
+ assert(member_val_index >= 0);
+ exprt member_expr = heap_domain.templ[member_val_index].expr;
+ exprt do_expr = heap_domain.templ[member_val_index].dyn_obj;
+
+ // Add all paths from obj.next to p
+ if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
+ std::make_pair(obj, member_expr)))
+ improved = true;
+ debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
+ << from_expr(ns, "", obj) << eom;
+
+ assert(do_expr.id() != ID_nil);
+ // Add points to information
+ assert(do_expr.id() == ID_symbol);
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
improved = true;
debug() << "add points to: " << from_expr(ns, "", obj) << eom;
}
@@ -134,16 +148,19 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
// that this row variable belongs to.
for (unsigned j = 0; j < heap_domain.templ.size(); ++j)
{
- for (auto &pt : inv[j].points_to)
+ if (heap_domain.templ[row].member == heap_domain.templ[j].member)
{
- exprt pre_pointer = heap_domain.templ[row].expr;
- if (pre_pointer == pt.second)
+ for (auto &pt : inv[j].points_to)
{
- if (heap_domain.add_all_paths(j, row, inv, pt))
- improved = true;
- debug() << "recursively updating row: " << j << eom;
- debug() << "add all paths: " << from_expr(ns, "", pre_pointer) << ", through: "
- << from_expr(ns, "", pt.first) << eom;
+ exprt pre_pointer = heap_domain.templ[row].expr;
+ if (pre_pointer == pt.second)
+ {
+ if (heap_domain.add_all_paths(j, row, inv, pt))
+ improved = true;
+ debug() << "recursively updating row: " << j << eom;
+ debug() << "add all paths: " << from_expr(ns, "", pre_pointer) << ", through: "
+ << from_expr(ns, "", pt.first) << eom;
+ }
}
}
}
@@ -154,9 +171,11 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
else
{
+#define DEBUG_OUTPUT
#ifdef DEBUG_OUTPUT
debug() << "UNSAT" << eom;
#endif
+#undef DEBUG_OUTPUT
#ifdef DEBUG_OUTPUT
for (unsigned i = 0; i < solver.formula.size(); i++)
@@ -174,29 +193,36 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
}
/**
- * Find the template row that contains next field of given object as row variable.
+ * Find the template row that contains specified member field of a dynamic object at given location.
+ * Finds obj.member#loc with maximal loc less than actual_loc.
* @param obj
- * @return Template row of obj.next
+ * @param member Member field to find
+ * @param actual_loc Actual location number
+ * @return Template row of obj.member
*/
-int strategy_solver_heapt::next_field_row(const exprt &obj) const
+int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &member, int actual_loc)
{
- // Create "next" member expression
- exprt next_expr = member_exprt(obj, "next", pointer_typet(obj.type()));
- std::string next_expr_id = from_expr(ns, "", next_expr);
+ assert(obj.id() == ID_symbol);
+ std::string obj_id = heap_domain.get_base_name(obj);
int result = -1;
- for (unsigned i = 0; i < strategy_value_exprs.size(); ++i)
- { // Find the corresponding strategy value expression
- exprt val_expr = strategy_value_exprs[i];
- assert(val_expr.id() == ID_symbol);
- std::string val_expr_id = id2string(to_symbol_expr(val_expr).get_identifier());
- // Compare identifiers of row expression and "next" member expresssion
- if (val_expr_id.find(next_expr_id) != std::string::npos)
+ int max_loc = -1;
+ for (unsigned i = 0; i < heap_domain.templ.size(); ++i)
+ {
+ heap_domaint::template_rowt &templ_row = heap_domain.templ[i];
+ if (templ_row.member == member && templ_row.dyn_obj.id() != ID_nil)
{
- result = i;
- break;
+ std::string id = id2string(to_symbol_expr(templ_row.expr).get_identifier());
+ if (id.find(obj_id) != std::string::npos)
+ {
+ int loc = heap_domain.get_symbol_loc(templ_row.expr);
+ if (loc <= actual_loc && loc > max_loc)
+ {
+ max_loc = loc;
+ result = i;
+ }
+ }
}
}
-
return result;
}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index 09f000b98..edb63c9a4 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -22,7 +22,7 @@ class strategy_solver_heapt : public strategy_solver_baset
protected:
heap_domaint &heap_domain;
- int next_field_row(const exprt &obj) const;
+ int find_member_row(const exprt &obj, const irep_idt &member, int actual_loc);
};
diff --git a/src/domains/template_generator_base.cpp b/src/domains/template_generator_base.cpp
index 05326a71a..8815d658a 100644
--- a/src/domains/template_generator_base.cpp
+++ b/src/domains/template_generator_base.cpp
@@ -270,7 +270,7 @@ void template_generator_baset::filter_heap_domain()
var_specs.clear();
for (auto var=new_var_specs.begin(); var!=new_var_specs.end(); ++var)
{
- if (var->var.type().id()==ID_pointer)
+ if (var->var.type().id()==ID_pointer || var->var.type().get_bool("#dynamic"))
var_specs.push_back(*var);
}
}
From e6830681c4fc076931e49a334488a9c257ce3d32 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Wed, 21 Sep 2016 18:12:09 +0100
Subject: [PATCH 021/322] Heap domain: Fix bug with aux_expr. Small changes to
path expression passed to solver. Now works for regression test
heap/sll_to_dll1_reverse.
---
regression/heap/path-format.py | 6 +
regression/heap/sll1_simple/main.out.old | 1120 +++++++++++++++++
regression/heap/sll_to_dll1_reverse/main.c | 25 +-
regression/heap/sll_to_dll1_reverse/test.desc | 2 +-
src/domains/heap_domain.cpp | 3 +-
src/domains/heap_domain.h | 13 +-
src/domains/strategy_solver_heap.cpp | 22 +-
7 files changed, 1172 insertions(+), 19 deletions(-)
create mode 100644 regression/heap/path-format.py
create mode 100644 regression/heap/sll1_simple/main.out.old
diff --git a/regression/heap/path-format.py b/regression/heap/path-format.py
new file mode 100644
index 000000000..a18b0fe13
--- /dev/null
+++ b/regression/heap/path-format.py
@@ -0,0 +1,6 @@
+from lepl import Any, Delayed, Node, Space
+
+expr = Delayed()
+expr += '{' / (Any() | expr[1:, Space()[:]]) / '}' > Node
+
+print expr.parse("{{a}{b}{{{c}}}}")[0]
diff --git a/regression/heap/sll1_simple/main.out.old b/regression/heap/sll1_simple/main.out.old
new file mode 100644
index 000000000..af5a78516
--- /dev/null
+++ b/regression/heap/sll1_simple/main.out.old
@@ -0,0 +1,1120 @@
+2LS version 0.3.4 (based on CBMC 5.4)
+Parsing main.c
+Converting
+Type-checking main
+file main.c line 53 function check_seq_next: function `assert' is not declared
+Generating GOTO Program
+Adding CPROVER library
+Generic Property Instrumentation
+Function Pointer Removal
+Performing full inlining
+Using heap domain
+Computing SSA of _start
+Simplifying
+(E) $guard#0 == TRUE
+
+(E) __CPROVER_dead_object#2 == NULL
+
+(E) __CPROVER_deallocated#3 == NULL
+
+(E) __CPROVER_malloc_is_new_array#4 == FALSE
+
+(E) __CPROVER_malloc_object#5 == NULL
+
+(E) __CPROVER_malloc_size#6 == 0ul
+
+(E) __CPROVER_memory_leak#7 == NULL
+
+(E) __CPROVER_next_thread_id#8 == 0ul
+
+(E) __CPROVER_pipe_count#9 == 0u
+
+(E) __CPROVER_rounding_mode#10 == 0
+
+(E) __CPROVER_thread_id#11 == 0ul
+
+(E) __CPROVER_threads_exited#12 == ARRAY_OF(FALSE)
+
+(E) p1#16 == nondet_symbol(ssa::nondet16.1)
+
+(E) p2#18 == nondet_symbol(ssa::nondet18.1)
+
+(E) list#20 == nondet_symbol(ssa::nondet20.1)
+
+(E) pp1#23 == nondet_symbol(ssa::nondet23.1)
+
+(E) pp1#24 == &p1
+
+(E) pp2#26 == nondet_symbol(ssa::nondet26.1)
+
+(E) pp2#27 == &p2
+
+(E) p2#28 == ((struct node *)NULL)
+
+(E) i#30 == nondet_symbol(ssa::nondet30.1)
+
+(E) i#31 == 0
+
+(E) __CPROVER_deallocated#phi32 == ($guard#ls101 ? __CPROVER_deallocated#lb101 : __CPROVER_deallocated#3)
+(E) __CPROVER_malloc_object#phi32 == ($guard#ls101 ? __CPROVER_malloc_object#lb101 : __CPROVER_malloc_object#5)
+(E) __CPROVER_malloc_size#phi32 == ($guard#ls101 ? __CPROVER_malloc_size#lb101 : __CPROVER_malloc_size#6)
+(E) __CPROVER_malloc_is_new_array#phi32 == ($guard#ls101 ? __CPROVER_malloc_is_new_array#lb101 : __CPROVER_malloc_is_new_array#4)
+(E) __CPROVER_memory_leak#phi32 == ($guard#ls101 ? __CPROVER_memory_leak#lb101 : __CPROVER_memory_leak#7)
+(E) i#phi32 == ($guard#ls101 ? i#lb101 : i#31)
+(E) p2#phi32 == ($guard#ls101 ? p2#lb101 : p2#28)
+(E) dynamic_object$0.next#phi32 == ($guard#ls101 ? dynamic_object$0.next#lb101 : dynamic_object$0.next)
+(E) $cond#32 == i#phi32 >= 2
+(E) $guard#32 == $guard#0
+
+(E) $guard#33 == (!$cond#32 && $guard#32)
+
+(E) ppnode#35 == nondet_symbol(ssa::nondet35.1)
+
+(E) ppnode#36 == pp2#27
+
+(E) node#38 == nondet_symbol(ssa::nondet38.1)
+
+(E) ptr#41 == nondet_symbol(ssa::nondet41.1)
+
+(E) return_value_malloc$1#43 == nondet_symbol(ssa::nondet43.1)
+
+(E) malloc_size#46 == nondet_symbol(ssa::nondet46.1)
+
+(E) malloc_size#47 == sizeof(struct node) /*8ul*/
+
+(E) malloc_res#50 == nondet_symbol(ssa::nondet50.1)
+
+(E) malloc_value$1#52 == nondet_symbol(ssa::nondet52.1)
+
+(E) malloc_value$1#53 == (void *)&dynamic_object$0
+
+(E) malloc_res#54 == malloc_value$1#53
+
+(E) __CPROVER_deallocated#56 == (malloc_res#54 == __CPROVER_deallocated#phi32 ? NULL : __CPROVER_deallocated#phi32)
+
+(E) record_malloc#58 == nondet_symbol(ssa::nondet58.1)
+
+(E) __CPROVER_malloc_object#59 == (record_malloc#58 ? malloc_res#54 : __CPROVER_malloc_object#phi32)
+
+(E) __CPROVER_malloc_size#60 == (record_malloc#58 ? malloc_size#47 : __CPROVER_malloc_size#phi32)
+
+(E) __CPROVER_malloc_is_new_array#61 == (!record_malloc#58 && __CPROVER_malloc_is_new_array#phi32)
+
+(E) record_may_leak#63 == nondet_symbol(ssa::nondet63.1)
+
+(E) __CPROVER_memory_leak#64 == (record_may_leak#63 ? malloc_res#54 : __CPROVER_memory_leak#phi32)
+
+(E) malloc#return_value#65 == malloc_res#54
+
+(E) $cond#70 == TRUE
+
+(E) $guard#71 == FALSE
+
+(E) $guard#75 == ($cond#70 && $guard#33 || $guard#71)
+
+(E) return_value_malloc$1#77 == malloc#return_value#65
+
+(E) ptr#79 == (struct node *)return_value_malloc$1#77
+
+(E) $cond#81 == !(ptr#79 == ((struct node *)NULL))
+
+(E) $guard#82 == (!$cond#81 && $guard#75)
+
+(E) $cond#83 == FALSE
+
+(E) $guard#84 == ($cond#83 && $guard#82)
+
+(E) dynamic_object$0.next#85 == ((struct node *)NULL)
+(E) $guard#85 == ($cond#81 && $guard#75 || $guard#84)
+
+(E) alloc_node#return_value#86 == ptr#79
+
+(E) $cond#89 == TRUE
+
+(E) $guard#90 == FALSE
+
+(E) $guard#92 == ($cond#89 && $guard#85 || $guard#90)
+
+(E) node#93 == alloc_node#return_value#86
+
+(E) dynamic_object$0.next#95 == (ppnode#36 == &p2 ? p2#phi32 : deref#95)
+
+(E) p2#96 == node#93
+
+(E) i#100 == 1 + i#phi32
+
+(E) $cond#101 == TRUE
+
+(E) $guard#102 == ($cond#32 && $guard#32)
+
+(E) p1#103 == (pp2#27 == &p2 ? p2#phi32 : deref#103)
+
+(E) i#105 == nondet_symbol(ssa::nondet105.1)
+
+(E) i#106 == 0
+
+(E) __CPROVER_deallocated#phi107 == ($guard#ls176 ? __CPROVER_deallocated#lb176 : __CPROVER_deallocated#phi32)
+(E) __CPROVER_malloc_object#phi107 == ($guard#ls176 ? __CPROVER_malloc_object#lb176 : __CPROVER_malloc_object#phi32)
+(E) __CPROVER_malloc_size#phi107 == ($guard#ls176 ? __CPROVER_malloc_size#lb176 : __CPROVER_malloc_size#phi32)
+(E) __CPROVER_malloc_is_new_array#phi107 == ($guard#ls176 ? __CPROVER_malloc_is_new_array#lb176 : __CPROVER_malloc_is_new_array#phi32)
+(E) __CPROVER_memory_leak#phi107 == ($guard#ls176 ? __CPROVER_memory_leak#lb176 : __CPROVER_memory_leak#phi32)
+(E) i#phi107 == ($guard#ls176 ? i#lb176 : i#106)
+(E) p1#phi107 == ($guard#ls176 ? p1#lb176 : p1#103)
+(E) dynamic_object$1.next#phi107 == ($guard#ls176 ? dynamic_object$1.next#lb176 : dynamic_object$1.next)
+(E) $cond#107 == i#phi107 >= 2
+(E) $guard#107 == $guard#102
+
+(E) $guard#108 == (!$cond#107 && $guard#107)
+
+(E) ppnode#110 == nondet_symbol(ssa::nondet110.1)
+
+(E) ppnode#111 == pp1#24
+
+(E) node#113 == nondet_symbol(ssa::nondet113.1)
+
+(E) ptr#116 == nondet_symbol(ssa::nondet116.1)
+
+(E) return_value_malloc$1#118 == nondet_symbol(ssa::nondet118.1)
+
+(E) malloc_size#121 == nondet_symbol(ssa::nondet121.1)
+
+(E) malloc_size#122 == sizeof(struct node) /*8ul*/
+
+(E) malloc_res#125 == nondet_symbol(ssa::nondet125.1)
+
+(E) malloc_value$1#127 == nondet_symbol(ssa::nondet127.1)
+
+(E) malloc_value$1#128 == (void *)&dynamic_object$1
+
+(E) malloc_res#129 == malloc_value$1#128
+
+(E) __CPROVER_deallocated#131 == (malloc_res#129 == __CPROVER_deallocated#phi107 ? NULL : __CPROVER_deallocated#phi107)
+
+(E) record_malloc#133 == nondet_symbol(ssa::nondet133.1)
+
+(E) __CPROVER_malloc_object#134 == (record_malloc#133 ? malloc_res#129 : __CPROVER_malloc_object#phi107)
+
+(E) __CPROVER_malloc_size#135 == (record_malloc#133 ? malloc_size#122 : __CPROVER_malloc_size#phi107)
+
+(E) __CPROVER_malloc_is_new_array#136 == (!record_malloc#133 && __CPROVER_malloc_is_new_array#phi107)
+
+(E) record_may_leak#138 == nondet_symbol(ssa::nondet138.1)
+
+(E) __CPROVER_memory_leak#139 == (record_may_leak#138 ? malloc_res#129 : __CPROVER_memory_leak#phi107)
+
+(E) malloc#return_value#140 == malloc_res#129
+
+(E) $cond#145 == TRUE
+
+(E) $guard#146 == FALSE
+
+(E) $guard#150 == ($cond#145 && $guard#108 || $guard#146)
+
+(E) return_value_malloc$1#152 == malloc#return_value#140
+
+(E) ptr#154 == (struct node *)return_value_malloc$1#152
+
+(E) $cond#156 == !(ptr#154 == ((struct node *)NULL))
+
+(E) $guard#157 == (!$cond#156 && $guard#150)
+
+(E) $cond#158 == FALSE
+
+(E) $guard#159 == ($cond#158 && $guard#157)
+
+(E) dynamic_object$1.next#160 == ((struct node *)NULL)
+(E) $guard#160 == ($cond#156 && $guard#150 || $guard#159)
+
+(E) alloc_node#return_value#161 == ptr#154
+
+(E) $cond#164 == TRUE
+
+(E) $guard#165 == FALSE
+
+(E) $guard#167 == ($cond#164 && $guard#160 || $guard#165)
+
+(E) node#168 == alloc_node#return_value#161
+
+(E) dynamic_object$1.next#170 == (ppnode#111 == &p1 ? p1#phi107 : deref#170)
+
+(E) p1#171 == node#168
+
+(E) i#175 == 1 + i#phi107
+
+(E) $cond#176 == TRUE
+
+(E) $guard#177 == ($cond#107 && $guard#107)
+
+(E) list#179 == nondet_symbol(ssa::nondet179.1)
+
+(E) list#180 == (pp1#24 == &p1 ? p1#phi107 : deref#180)
+
+(E) i#182 == nondet_symbol(ssa::nondet182.1)
+
+(E) i#183 == 0
+
+(E) __CPROVER_deallocated#phi184 == ($guard#ls253 ? __CPROVER_deallocated#lb253 : __CPROVER_deallocated#phi107)
+(E) __CPROVER_malloc_object#phi184 == ($guard#ls253 ? __CPROVER_malloc_object#lb253 : __CPROVER_malloc_object#phi107)
+(E) __CPROVER_malloc_size#phi184 == ($guard#ls253 ? __CPROVER_malloc_size#lb253 : __CPROVER_malloc_size#phi107)
+(E) __CPROVER_malloc_is_new_array#phi184 == ($guard#ls253 ? __CPROVER_malloc_is_new_array#lb253 : __CPROVER_malloc_is_new_array#phi107)
+(E) __CPROVER_memory_leak#phi184 == ($guard#ls253 ? __CPROVER_memory_leak#lb253 : __CPROVER_memory_leak#phi107)
+(E) list#phi184 == ($guard#ls253 ? list#lb253 : list#180)
+(E) i#phi184 == ($guard#ls253 ? i#lb253 : i#183)
+(E) dynamic_object$2.next#phi184 == ($guard#ls253 ? dynamic_object$2.next#lb253 : dynamic_object$2.next)
+(E) $cond#184 == i#phi184 >= 2
+(E) $guard#184 == $guard#177
+
+(E) $guard#185 == (!$cond#184 && $guard#184)
+
+(E) ppnode#187 == nondet_symbol(ssa::nondet187.1)
+
+(E) ppnode#188 == &list
+
+(E) node#190 == nondet_symbol(ssa::nondet190.1)
+
+(E) ptr#193 == nondet_symbol(ssa::nondet193.1)
+
+(E) return_value_malloc$1#195 == nondet_symbol(ssa::nondet195.1)
+
+(E) malloc_size#198 == nondet_symbol(ssa::nondet198.1)
+
+(E) malloc_size#199 == sizeof(struct node) /*8ul*/
+
+(E) malloc_res#202 == nondet_symbol(ssa::nondet202.1)
+
+(E) malloc_value$1#204 == nondet_symbol(ssa::nondet204.1)
+
+(E) malloc_value$1#205 == (void *)&dynamic_object$2
+
+(E) malloc_res#206 == malloc_value$1#205
+
+(E) __CPROVER_deallocated#208 == (malloc_res#206 == __CPROVER_deallocated#phi184 ? NULL : __CPROVER_deallocated#phi184)
+
+(E) record_malloc#210 == nondet_symbol(ssa::nondet210.1)
+
+(E) __CPROVER_malloc_object#211 == (record_malloc#210 ? malloc_res#206 : __CPROVER_malloc_object#phi184)
+
+(E) __CPROVER_malloc_size#212 == (record_malloc#210 ? malloc_size#199 : __CPROVER_malloc_size#phi184)
+
+(E) __CPROVER_malloc_is_new_array#213 == (!record_malloc#210 && __CPROVER_malloc_is_new_array#phi184)
+
+(E) record_may_leak#215 == nondet_symbol(ssa::nondet215.1)
+
+(E) __CPROVER_memory_leak#216 == (record_may_leak#215 ? malloc_res#206 : __CPROVER_memory_leak#phi184)
+
+(E) malloc#return_value#217 == malloc_res#206
+
+(E) $cond#222 == TRUE
+
+(E) $guard#223 == FALSE
+
+(E) $guard#227 == ($cond#222 && $guard#185 || $guard#223)
+
+(E) return_value_malloc$1#229 == malloc#return_value#217
+
+(E) ptr#231 == (struct node *)return_value_malloc$1#229
+
+(E) $cond#233 == !(ptr#231 == ((struct node *)NULL))
+
+(E) $guard#234 == (!$cond#233 && $guard#227)
+
+(E) $cond#235 == FALSE
+
+(E) $guard#236 == ($cond#235 && $guard#234)
+
+(E) dynamic_object$2.next#237 == ((struct node *)NULL)
+(E) $guard#237 == ($cond#233 && $guard#227 || $guard#236)
+
+(E) alloc_node#return_value#238 == ptr#231
+
+(E) $cond#241 == TRUE
+
+(E) $guard#242 == FALSE
+
+(E) $guard#244 == ($cond#241 && $guard#237 || $guard#242)
+
+(E) node#245 == alloc_node#return_value#238
+
+(E) dynamic_object$2.next#247 == (ppnode#188 == &list ? list#phi184 : deref#247)
+
+(E) list#248 == node#245
+
+(E) i#252 == 1 + i#phi184
+
+(E) $cond#253 == TRUE
+
+(E) $guard#254 == ($cond#184 && $guard#184)
+
+(E) create_sll#return_value#255 == list#phi184
+
+(E) $cond#257 == TRUE
+
+(E) $guard#258 == FALSE
+
+(E) $guard#259 == ($cond#257 && $guard#254 || $guard#258)
+
+(E) list#262 == create_sll#return_value#255
+
+(E) beg#266 == nondet_symbol(ssa::nondet266.1)
+
+(E) beg#267 == list#262
+
+(E) end#269 == nondet_symbol(ssa::nondet269.1)
+
+(E) end#270 == p1#phi107
+
+(A) !(beg#267 == ((struct node *)NULL)) || !$guard#259
+
+(A) !(end#270 == ((struct node *)NULL)) || !$guard#259
+
+(E) beg#273 == (beg#267 == &dynamic_object$2 ? dynamic_object$2.next#phi184 : (beg#267 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#267 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#273.next)))
+
+(E) beg#phi274 == ($guard#ls277 ? beg#lb277 : beg#273)
+(E) $cond#274 == (end#270 == beg#phi274)
+(E) $guard#274 == $guard#259
+
+(E) $guard#275 == (!$cond#274 && $guard#274)
+(A) !(beg#phi274 == ((struct node *)NULL)) || !$guard#275
+
+(E) beg#276 == (beg#phi274 == &dynamic_object$2 ? dynamic_object$2.next#phi184 : (beg#phi274 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#phi274 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#276.next)))
+
+(E) $cond#277 == TRUE
+
+(E) $guard#278 == ($cond#274 && $guard#274)
+
+(E) beg#283 == nondet_symbol(ssa::nondet283.1)
+
+(E) beg#284 == p1#phi107
+
+(E) end#286 == nondet_symbol(ssa::nondet286.1)
+
+(E) end#287 == p2#phi32
+
+(A) !(beg#284 == ((struct node *)NULL)) || !$guard#278
+
+(A) !(end#287 == ((struct node *)NULL)) || !$guard#278
+
+(E) beg#290 == (beg#284 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#284 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#290.next))
+
+(E) beg#phi291 == ($guard#ls294 ? beg#lb294 : beg#290)
+(E) $cond#291 == (end#287 == beg#phi291)
+(E) $guard#291 == $guard#278
+
+(E) $guard#292 == (!$cond#291 && $guard#291)
+(A) !(beg#phi291 == ((struct node *)NULL)) || !$guard#292
+
+(E) beg#293 == (beg#phi291 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#phi291 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#293.next))
+
+(E) $cond#294 == TRUE
+
+(E) $guard#295 == ($cond#291 && $guard#291)
+
+
+
+Summarizing function _start
+Analyzing function _start
+Computing summary
+Template:
+(LOOP) [ $guard#32 && $guard#ls101 | $guard#92 && $cond#101 | $guard#92 && $cond#101 ] ===>
+ ?path(p2#lb101, DESTINATIONS)
+(LOOP) [ $guard#32 && $guard#ls101 | $guard#92 && $cond#101 | $guard#92 && $cond#101 ] ===>
+ ?path(dynamic_object$0.next#lb101, DESTINATIONS)
+(LOOP) [ $guard#107 && $guard#ls176 | $guard#167 && $cond#176 | $guard#167 && $cond#176 ] ===>
+ ?path(p1#lb176, DESTINATIONS)
+(LOOP) [ $guard#107 && $guard#ls176 | $guard#167 && $cond#176 | $guard#167 && $cond#176 ] ===>
+ ?path(dynamic_object$1.next#lb176, DESTINATIONS)
+(LOOP) [ $guard#184 && $guard#ls253 | $guard#244 && $cond#253 | $guard#244 && $cond#253 ] ===>
+ ?path(list#lb253, DESTINATIONS)
+(LOOP) [ $guard#184 && $guard#ls253 | $guard#244 && $cond#253 | $guard#244 && $cond#253 ] ===>
+ ?path(dynamic_object$2.next#lb253, DESTINATIONS)
+(LOOP) [ $guard#274 && $guard#ls277 | $guard#275 && $cond#277 | $guard#275 && $cond#277 ] ===>
+ ?path(beg#lb277, DESTINATIONS)
+(LOOP) [ $guard#291 && $guard#ls294 | $guard#292 && $cond#294 | $guard#292 && $cond#294 ] ===>
+ ?path(beg#lb294, DESTINATIONS)
+
+updating row: 0
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+add points to: dynamic_object$0
+updating row: 1
+add destination: ((struct node *)NULL)
+recursively updating row: 0
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+updating row: 2
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+add points to: dynamic_object$1
+updating row: 3
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+add points to: dynamic_object$0
+recursively updating row: 2
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+updating row: 3
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+add points to: dynamic_object$1
+recursively updating row: 2
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+recursively updating row: 3
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+updating row: 4
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+add points to: dynamic_object$2
+updating row: 5
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+add points to: dynamic_object$1
+recursively updating row: 4
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+updating row: 5
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+add points to: dynamic_object$2
+recursively updating row: 4
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+recursively updating row: 5
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+updating row: 7
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+add points to: dynamic_object$1
+updating row: 7
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+add points to: dynamic_object$0
+updating row: 6
+add all paths: dynamic_object$2.next#lb253, through: dynamic_object$2
+add points to: dynamic_object$2
+updating row: 6
+add all paths: dynamic_object$1.next#lb176, through: dynamic_object$1
+add points to: dynamic_object$1
+updating row: 1
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+add points to: dynamic_object$0
+recursively updating row: 0
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+recursively updating row: 1
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+recursively updating row: 3
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+recursively updating row: 7
+add all paths: dynamic_object$0.next#lb101, through: dynamic_object$0
+
+Summary for function _start
+params:
+globals_in: __CPROVER_threads_exited __CPROVER_malloc_is_new_array __CPROVER_dead_object __CPROVER_deallocated __CPROVER_malloc_object __CPROVER_memory_leak ppnode'obj beg'obj.next end'obj.next pp1'obj pp2'obj __CPROVER_rounding_mode __CPROVER_pipe_count __CPROVER_malloc_size __CPROVER_next_thread_id __CPROVER_thread_id
+globals_out: __CPROVER_threads_exited#12 __CPROVER_malloc_is_new_array#phi184 __CPROVER_dead_object#2 __CPROVER_deallocated#phi184 __CPROVER_malloc_object#phi184 __CPROVER_memory_leak#phi184 ppnode'obj beg'obj.next end'obj.next pp1'obj pp2'obj __CPROVER_rounding_mode#10 __CPROVER_pipe_count#9 __CPROVER_malloc_size#phi184 __CPROVER_next_thread_id#8 __CPROVER_thread_id#11
+forward precondition: TRUE
+forward transformer: TRUE
+forward invariant: ($guard#32 && $guard#ls101 ==> p2#lb101 == &dynamic_object$0 && (dynamic_object$0.next#lb101 == ((struct node *)NULL) || dynamic_object$0.next#lb101 == &dynamic_object$0)) && ($guard#32 && $guard#ls101 ==> dynamic_object$0.next#lb101 == ((struct node *)NULL) || dynamic_object$0.next#lb101 == &dynamic_object$0 && (dynamic_object$0.next#lb101 == ((struct node *)NULL) || dynamic_object$0.next#lb101 == &dynamic_object$0)) && ($guard#107 && $guard#ls176 ==> p1#lb176 == &dynamic_object$1 && (dynamic_object$1.next#lb176 == ((struct node *)NULL) || dynamic_object$1.next#lb176 == &dynamic_object$0 || dynamic_object$1.next#lb176 == &dynamic_object$1)) && ($guard#107 && $guard#ls176 ==> dynamic_object$1.next#lb176 == &dynamic_object$0 && (dynamic_object$0.next#lb101 == ((struct node *)NULL) || dynamic_object$0.next#lb101 == &dynamic_object$0 || dynamic_object$0.next#lb101 == &dynamic_object$1) || dynamic_object$1.next#lb176 == &dynamic_object$1 && (dynamic_object$1.next#lb176 == ((struct node *)NULL) || dynamic_object$1.next#lb176 == &dynamic_object$0 || dynamic_object$1.next#lb176 == &dynamic_object$1)) && ($guard#184 && $guard#ls253 ==> list#lb253 == &dynamic_object$2 && (dynamic_object$2.next#lb253 == ((struct node *)NULL) || dynamic_object$2.next#lb253 == &dynamic_object$0 || dynamic_object$2.next#lb253 == &dynamic_object$1 || dynamic_object$2.next#lb253 == &dynamic_object$2)) && ($guard#184 && $guard#ls253 ==> dynamic_object$2.next#lb253 == &dynamic_object$1 && (dynamic_object$1.next#lb176 == ((struct node *)NULL) || dynamic_object$1.next#lb176 == &dynamic_object$0 || dynamic_object$1.next#lb176 == &dynamic_object$1 || dynamic_object$1.next#lb176 == &dynamic_object$2) || dynamic_object$2.next#lb253 == &dynamic_object$2 && (dynamic_object$2.next#lb253 == ((struct node *)NULL) || dynamic_object$2.next#lb253 == &dynamic_object$0 || dynamic_object$2.next#lb253 == &dynamic_object$1 || dynamic_object$2.next#lb253 == &dynamic_object$2)) && ($guard#274 && $guard#ls277 ==> beg#lb277 == &dynamic_object$1 && (dynamic_object$1.next#lb176 == ((struct node *)NULL) || dynamic_object$1.next#lb176 == &dynamic_object$0 || dynamic_object$1.next#lb176 == &dynamic_object$1 || dynamic_object$1.next#lb176 == &dynamic_object$2) || beg#lb277 == &dynamic_object$2 && (dynamic_object$2.next#lb253 == ((struct node *)NULL) || dynamic_object$2.next#lb253 == &dynamic_object$0 || dynamic_object$2.next#lb253 == &dynamic_object$1 || dynamic_object$2.next#lb253 == &dynamic_object$2)) && ($guard#291 && $guard#ls294 ==> beg#lb294 == &dynamic_object$0 && (dynamic_object$0.next#lb101 == ((struct node *)NULL) || dynamic_object$0.next#lb101 == &dynamic_object$0 || dynamic_object$0.next#lb101 == &dynamic_object$1) || beg#lb294 == &dynamic_object$1 && (dynamic_object$1.next#lb176 == ((struct node *)NULL) || dynamic_object$1.next#lb176 == &dynamic_object$0 || dynamic_object$1.next#lb176 == &dynamic_object$1))
+backward precondition: not computed
+backward postcondition: not computed
+backward transformer: not computed
+backward invariant: not computed
+termination argument: not computed
+terminates: unknown
+
+Checking properties of _start
+*** 0
+(E) $guard#0 == TRUE
+
+*** 2 file line 39
+(E) __CPROVER_dead_object#2 == NULL
+
+*** 3 file line 38
+(E) __CPROVER_deallocated#3 == NULL
+
+*** 4 file line 42
+(E) __CPROVER_malloc_is_new_array#4 == FALSE
+
+*** 5 file line 40
+(E) __CPROVER_malloc_object#5 == NULL
+
+*** 6 file line 41
+(E) __CPROVER_malloc_size#6 == 0ul
+
+*** 7 file line 43
+(E) __CPROVER_memory_leak#7 == NULL
+
+*** 8 file line 31
+(E) __CPROVER_next_thread_id#8 == 0ul
+
+*** 9 file line 87
+(E) __CPROVER_pipe_count#9 == 0u
+
+*** 10 file line 65
+(E) __CPROVER_rounding_mode#10 == 0
+
+*** 11 file line 29
+(E) __CPROVER_thread_id#11 == 0ul
+
+*** 12 file line 30
+(E) __CPROVER_threads_exited#12 == ARRAY_OF(FALSE)
+
+*** 16 file main.c line 62 function main
+(E) p1#16 == nondet_symbol(ssa::nondet16.1)
+
+*** 18 file main.c line 62 function main
+(E) p2#18 == nondet_symbol(ssa::nondet18.1)
+
+*** 20 file main.c line 64 function main
+(E) list#20 == nondet_symbol(ssa::nondet20.1)
+
+*** 23 file main.c line 64 function main
+(E) pp1#23 == nondet_symbol(ssa::nondet23.1)
+
+*** 24 file main.c line 64 function main
+(E) pp1#24 == &p1
+
+*** 26 file main.c line 64 function main
+(E) pp2#26 == nondet_symbol(ssa::nondet26.1)
+
+*** 27 file main.c line 64 function main
+(E) pp2#27 == &p2
+
+*** 28 file main.c line 28 function create_sll
+(E) p2#28 == ((struct node *)NULL)
+
+*** 30 file main.c line 30 function create_sll
+(E) i#30 == nondet_symbol(ssa::nondet30.1)
+
+*** 31 file main.c line 30 function create_sll
+(E) i#31 == 0
+
+*** 32 file main.c line 30 function create_sll
+(E) __CPROVER_deallocated#phi32 == ($guard#ls101 ? __CPROVER_deallocated#lb101 : __CPROVER_deallocated#3)
+(E) __CPROVER_malloc_object#phi32 == ($guard#ls101 ? __CPROVER_malloc_object#lb101 : __CPROVER_malloc_object#5)
+(E) __CPROVER_malloc_size#phi32 == ($guard#ls101 ? __CPROVER_malloc_size#lb101 : __CPROVER_malloc_size#6)
+(E) __CPROVER_malloc_is_new_array#phi32 == ($guard#ls101 ? __CPROVER_malloc_is_new_array#lb101 : __CPROVER_malloc_is_new_array#4)
+(E) __CPROVER_memory_leak#phi32 == ($guard#ls101 ? __CPROVER_memory_leak#lb101 : __CPROVER_memory_leak#7)
+(E) i#phi32 == ($guard#ls101 ? i#lb101 : i#31)
+(E) p2#phi32 == ($guard#ls101 ? p2#lb101 : p2#28)
+(E) dynamic_object$0.next#phi32 == ($guard#ls101 ? dynamic_object$0.next#lb101 : dynamic_object$0.next)
+(E) $cond#32 == i#phi32 >= 2
+(E) $guard#32 == $guard#0
+
+*** 33 file main.c line 32 function create_sll
+(E) $guard#33 == (!$cond#32 && $guard#32)
+
+*** 35 file main.c line 32 function create_sll
+(E) ppnode#35 == nondet_symbol(ssa::nondet35.1)
+
+*** 36 file main.c line 32 function create_sll
+(E) ppnode#36 == pp2#27
+
+*** 38 file main.c line 21 function chain_node
+(E) node#38 == nondet_symbol(ssa::nondet38.1)
+
+*** 41 file main.c line 11 function alloc_node
+(E) ptr#41 == nondet_symbol(ssa::nondet41.1)
+
+*** 43 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#43 == nondet_symbol(ssa::nondet43.1)
+
+*** 46 file main.c line 11 function alloc_node
+(E) malloc_size#46 == nondet_symbol(ssa::nondet46.1)
+
+*** 47 file main.c line 11 function alloc_node
+(E) malloc_size#47 == sizeof(struct node) /*8ul*/
+
+*** 50 file main.c line 11 function alloc_node
+(E) malloc_res#50 == nondet_symbol(ssa::nondet50.1)
+
+*** 52 file main.c line 11 function alloc_node
+(E) malloc_value$1#52 == nondet_symbol(ssa::nondet52.1)
+
+*** 53 file main.c line 11 function alloc_node
+(E) malloc_value$1#53 == (void *)&dynamic_object$0
+
+*** 54 file main.c line 11 function alloc_node
+(E) malloc_res#54 == malloc_value$1#53
+
+*** 56 file main.c line 11 function alloc_node
+(E) __CPROVER_deallocated#56 == (malloc_res#54 == __CPROVER_deallocated#phi32 ? NULL : __CPROVER_deallocated#phi32)
+
+*** 58 file main.c line 11 function alloc_node
+(E) record_malloc#58 == nondet_symbol(ssa::nondet58.1)
+
+*** 59 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_object#59 == (record_malloc#58 ? malloc_res#54 : __CPROVER_malloc_object#phi32)
+
+*** 60 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_size#60 == (record_malloc#58 ? malloc_size#47 : __CPROVER_malloc_size#phi32)
+
+*** 61 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_is_new_array#61 == (!record_malloc#58 && __CPROVER_malloc_is_new_array#phi32)
+
+*** 63 file main.c line 11 function alloc_node
+(E) record_may_leak#63 == nondet_symbol(ssa::nondet63.1)
+
+*** 64 file main.c line 11 function alloc_node
+(E) __CPROVER_memory_leak#64 == (record_may_leak#63 ? malloc_res#54 : __CPROVER_memory_leak#phi32)
+
+*** 65 file main.c line 11 function alloc_node
+(E) malloc#return_value#65 == malloc_res#54
+
+*** 70 file main.c line 11 function alloc_node
+(E) $cond#70 == TRUE
+
+*** 71 file main.c line 11 function alloc_node
+(E) $guard#71 == FALSE
+
+*** 75 file main.c line 11 function alloc_node
+(E) $guard#75 == ($cond#70 && $guard#33 || $guard#71)
+
+*** 77 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#77 == malloc#return_value#65
+
+*** 79 file main.c line 11 function alloc_node
+(E) ptr#79 == (struct node *)return_value_malloc$1#77
+
+*** 81 file main.c line 12 function alloc_node
+(E) $cond#81 == !(ptr#79 == ((struct node *)NULL))
+
+*** 82 file main.c line 13 function alloc_node
+(E) $guard#82 == (!$cond#81 && $guard#75)
+
+*** 83 file line 6 function abort
+(E) $cond#83 == FALSE
+
+*** 84 file line 7 function abort
+(E) $guard#84 == ($cond#83 && $guard#82)
+
+*** 85 file main.c line 15 function alloc_node
+(E) dynamic_object$0.next#85 == ((struct node *)NULL)
+(E) $guard#85 == ($cond#81 && $guard#75 || $guard#84)
+
+*** 86 file main.c line 16 function alloc_node
+(E) alloc_node#return_value#86 == ptr#79
+
+*** 89 file main.c line 16 function alloc_node
+(E) $cond#89 == TRUE
+
+*** 90 file main.c line 17 function alloc_node
+(E) $guard#90 == FALSE
+
+*** 92 file main.c line 17 function alloc_node
+(E) $guard#92 == ($cond#89 && $guard#85 || $guard#90)
+
+*** 93 file main.c line 21 function chain_node
+(E) node#93 == alloc_node#return_value#86
+
+*** 95 file main.c line 22 function chain_node
+(E) dynamic_object$0.next#95 == (ppnode#36 == &p2 ? p2#phi32 : deref#95)
+
+*** 96 file main.c line 23 function chain_node
+(E) p2#96 == node#93
+
+*** 100 file main.c line 30 function create_sll
+(E) i#100 == 1 + i#phi32
+
+*** 101 file main.c line 30 function create_sll
+(E) $cond#101 == TRUE
+loop back to location 32
+
+*** 102 file main.c line 33 function create_sll
+(E) $guard#102 == ($cond#32 && $guard#32)
+
+*** 103 file main.c line 35 function create_sll
+(E) p1#103 == (pp2#27 == &p2 ? p2#phi32 : deref#103)
+
+*** 105 file main.c line 37 function create_sll
+(E) i#105 == nondet_symbol(ssa::nondet105.1)
+
+*** 106 file main.c line 37 function create_sll
+(E) i#106 == 0
+
+*** 107 file main.c line 37 function create_sll
+(E) __CPROVER_deallocated#phi107 == ($guard#ls176 ? __CPROVER_deallocated#lb176 : __CPROVER_deallocated#phi32)
+(E) __CPROVER_malloc_object#phi107 == ($guard#ls176 ? __CPROVER_malloc_object#lb176 : __CPROVER_malloc_object#phi32)
+(E) __CPROVER_malloc_size#phi107 == ($guard#ls176 ? __CPROVER_malloc_size#lb176 : __CPROVER_malloc_size#phi32)
+(E) __CPROVER_malloc_is_new_array#phi107 == ($guard#ls176 ? __CPROVER_malloc_is_new_array#lb176 : __CPROVER_malloc_is_new_array#phi32)
+(E) __CPROVER_memory_leak#phi107 == ($guard#ls176 ? __CPROVER_memory_leak#lb176 : __CPROVER_memory_leak#phi32)
+(E) i#phi107 == ($guard#ls176 ? i#lb176 : i#106)
+(E) p1#phi107 == ($guard#ls176 ? p1#lb176 : p1#103)
+(E) dynamic_object$1.next#phi107 == ($guard#ls176 ? dynamic_object$1.next#lb176 : dynamic_object$1.next)
+(E) $cond#107 == i#phi107 >= 2
+(E) $guard#107 == $guard#102
+
+*** 108 file main.c line 39 function create_sll
+(E) $guard#108 == (!$cond#107 && $guard#107)
+
+*** 110 file main.c line 39 function create_sll
+(E) ppnode#110 == nondet_symbol(ssa::nondet110.1)
+
+*** 111 file main.c line 39 function create_sll
+(E) ppnode#111 == pp1#24
+
+*** 113 file main.c line 21 function chain_node
+(E) node#113 == nondet_symbol(ssa::nondet113.1)
+
+*** 116 file main.c line 11 function alloc_node
+(E) ptr#116 == nondet_symbol(ssa::nondet116.1)
+
+*** 118 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#118 == nondet_symbol(ssa::nondet118.1)
+
+*** 121 file main.c line 11 function alloc_node
+(E) malloc_size#121 == nondet_symbol(ssa::nondet121.1)
+
+*** 122 file main.c line 11 function alloc_node
+(E) malloc_size#122 == sizeof(struct node) /*8ul*/
+
+*** 125 file main.c line 11 function alloc_node
+(E) malloc_res#125 == nondet_symbol(ssa::nondet125.1)
+
+*** 127 file main.c line 11 function alloc_node
+(E) malloc_value$1#127 == nondet_symbol(ssa::nondet127.1)
+
+*** 128 file main.c line 11 function alloc_node
+(E) malloc_value$1#128 == (void *)&dynamic_object$1
+
+*** 129 file main.c line 11 function alloc_node
+(E) malloc_res#129 == malloc_value$1#128
+
+*** 131 file main.c line 11 function alloc_node
+(E) __CPROVER_deallocated#131 == (malloc_res#129 == __CPROVER_deallocated#phi107 ? NULL : __CPROVER_deallocated#phi107)
+
+*** 133 file main.c line 11 function alloc_node
+(E) record_malloc#133 == nondet_symbol(ssa::nondet133.1)
+
+*** 134 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_object#134 == (record_malloc#133 ? malloc_res#129 : __CPROVER_malloc_object#phi107)
+
+*** 135 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_size#135 == (record_malloc#133 ? malloc_size#122 : __CPROVER_malloc_size#phi107)
+
+*** 136 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_is_new_array#136 == (!record_malloc#133 && __CPROVER_malloc_is_new_array#phi107)
+
+*** 138 file main.c line 11 function alloc_node
+(E) record_may_leak#138 == nondet_symbol(ssa::nondet138.1)
+
+*** 139 file main.c line 11 function alloc_node
+(E) __CPROVER_memory_leak#139 == (record_may_leak#138 ? malloc_res#129 : __CPROVER_memory_leak#phi107)
+
+*** 140 file main.c line 11 function alloc_node
+(E) malloc#return_value#140 == malloc_res#129
+
+*** 145 file main.c line 11 function alloc_node
+(E) $cond#145 == TRUE
+
+*** 146 file main.c line 11 function alloc_node
+(E) $guard#146 == FALSE
+
+*** 150 file main.c line 11 function alloc_node
+(E) $guard#150 == ($cond#145 && $guard#108 || $guard#146)
+
+*** 152 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#152 == malloc#return_value#140
+
+*** 154 file main.c line 11 function alloc_node
+(E) ptr#154 == (struct node *)return_value_malloc$1#152
+
+*** 156 file main.c line 12 function alloc_node
+(E) $cond#156 == !(ptr#154 == ((struct node *)NULL))
+
+*** 157 file main.c line 13 function alloc_node
+(E) $guard#157 == (!$cond#156 && $guard#150)
+
+*** 158 file line 6 function abort
+(E) $cond#158 == FALSE
+
+*** 159 file line 7 function abort
+(E) $guard#159 == ($cond#158 && $guard#157)
+
+*** 160 file main.c line 15 function alloc_node
+(E) dynamic_object$1.next#160 == ((struct node *)NULL)
+(E) $guard#160 == ($cond#156 && $guard#150 || $guard#159)
+
+*** 161 file main.c line 16 function alloc_node
+(E) alloc_node#return_value#161 == ptr#154
+
+*** 164 file main.c line 16 function alloc_node
+(E) $cond#164 == TRUE
+
+*** 165 file main.c line 17 function alloc_node
+(E) $guard#165 == FALSE
+
+*** 167 file main.c line 17 function alloc_node
+(E) $guard#167 == ($cond#164 && $guard#160 || $guard#165)
+
+*** 168 file main.c line 21 function chain_node
+(E) node#168 == alloc_node#return_value#161
+
+*** 170 file main.c line 22 function chain_node
+(E) dynamic_object$1.next#170 == (ppnode#111 == &p1 ? p1#phi107 : deref#170)
+
+*** 171 file main.c line 23 function chain_node
+(E) p1#171 == node#168
+
+*** 175 file main.c line 37 function create_sll
+(E) i#175 == 1 + i#phi107
+
+*** 176 file main.c line 37 function create_sll
+(E) $cond#176 == TRUE
+loop back to location 107
+
+*** 177 file main.c line 40 function create_sll
+(E) $guard#177 == ($cond#107 && $guard#107)
+
+*** 179 file main.c line 42 function create_sll
+(E) list#179 == nondet_symbol(ssa::nondet179.1)
+
+*** 180 file main.c line 42 function create_sll
+(E) list#180 == (pp1#24 == &p1 ? p1#phi107 : deref#180)
+
+*** 182 file main.c line 44 function create_sll
+(E) i#182 == nondet_symbol(ssa::nondet182.1)
+
+*** 183 file main.c line 44 function create_sll
+(E) i#183 == 0
+
+*** 184 file main.c line 44 function create_sll
+(E) __CPROVER_deallocated#phi184 == ($guard#ls253 ? __CPROVER_deallocated#lb253 : __CPROVER_deallocated#phi107)
+(E) __CPROVER_malloc_object#phi184 == ($guard#ls253 ? __CPROVER_malloc_object#lb253 : __CPROVER_malloc_object#phi107)
+(E) __CPROVER_malloc_size#phi184 == ($guard#ls253 ? __CPROVER_malloc_size#lb253 : __CPROVER_malloc_size#phi107)
+(E) __CPROVER_malloc_is_new_array#phi184 == ($guard#ls253 ? __CPROVER_malloc_is_new_array#lb253 : __CPROVER_malloc_is_new_array#phi107)
+(E) __CPROVER_memory_leak#phi184 == ($guard#ls253 ? __CPROVER_memory_leak#lb253 : __CPROVER_memory_leak#phi107)
+(E) list#phi184 == ($guard#ls253 ? list#lb253 : list#180)
+(E) i#phi184 == ($guard#ls253 ? i#lb253 : i#183)
+(E) dynamic_object$2.next#phi184 == ($guard#ls253 ? dynamic_object$2.next#lb253 : dynamic_object$2.next)
+(E) $cond#184 == i#phi184 >= 2
+(E) $guard#184 == $guard#177
+
+*** 185 file main.c line 46 function create_sll
+(E) $guard#185 == (!$cond#184 && $guard#184)
+
+*** 187 file main.c line 46 function create_sll
+(E) ppnode#187 == nondet_symbol(ssa::nondet187.1)
+
+*** 188 file main.c line 46 function create_sll
+(E) ppnode#188 == &list
+
+*** 190 file main.c line 21 function chain_node
+(E) node#190 == nondet_symbol(ssa::nondet190.1)
+
+*** 193 file main.c line 11 function alloc_node
+(E) ptr#193 == nondet_symbol(ssa::nondet193.1)
+
+*** 195 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#195 == nondet_symbol(ssa::nondet195.1)
+
+*** 198 file main.c line 11 function alloc_node
+(E) malloc_size#198 == nondet_symbol(ssa::nondet198.1)
+
+*** 199 file main.c line 11 function alloc_node
+(E) malloc_size#199 == sizeof(struct node) /*8ul*/
+
+*** 202 file main.c line 11 function alloc_node
+(E) malloc_res#202 == nondet_symbol(ssa::nondet202.1)
+
+*** 204 file main.c line 11 function alloc_node
+(E) malloc_value$1#204 == nondet_symbol(ssa::nondet204.1)
+
+*** 205 file main.c line 11 function alloc_node
+(E) malloc_value$1#205 == (void *)&dynamic_object$2
+
+*** 206 file main.c line 11 function alloc_node
+(E) malloc_res#206 == malloc_value$1#205
+
+*** 208 file main.c line 11 function alloc_node
+(E) __CPROVER_deallocated#208 == (malloc_res#206 == __CPROVER_deallocated#phi184 ? NULL : __CPROVER_deallocated#phi184)
+
+*** 210 file main.c line 11 function alloc_node
+(E) record_malloc#210 == nondet_symbol(ssa::nondet210.1)
+
+*** 211 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_object#211 == (record_malloc#210 ? malloc_res#206 : __CPROVER_malloc_object#phi184)
+
+*** 212 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_size#212 == (record_malloc#210 ? malloc_size#199 : __CPROVER_malloc_size#phi184)
+
+*** 213 file main.c line 11 function alloc_node
+(E) __CPROVER_malloc_is_new_array#213 == (!record_malloc#210 && __CPROVER_malloc_is_new_array#phi184)
+
+*** 215 file main.c line 11 function alloc_node
+(E) record_may_leak#215 == nondet_symbol(ssa::nondet215.1)
+
+*** 216 file main.c line 11 function alloc_node
+(E) __CPROVER_memory_leak#216 == (record_may_leak#215 ? malloc_res#206 : __CPROVER_memory_leak#phi184)
+
+*** 217 file main.c line 11 function alloc_node
+(E) malloc#return_value#217 == malloc_res#206
+
+*** 222 file main.c line 11 function alloc_node
+(E) $cond#222 == TRUE
+
+*** 223 file main.c line 11 function alloc_node
+(E) $guard#223 == FALSE
+
+*** 227 file main.c line 11 function alloc_node
+(E) $guard#227 == ($cond#222 && $guard#185 || $guard#223)
+
+*** 229 file main.c line 11 function alloc_node
+(E) return_value_malloc$1#229 == malloc#return_value#217
+
+*** 231 file main.c line 11 function alloc_node
+(E) ptr#231 == (struct node *)return_value_malloc$1#229
+
+*** 233 file main.c line 12 function alloc_node
+(E) $cond#233 == !(ptr#231 == ((struct node *)NULL))
+
+*** 234 file main.c line 13 function alloc_node
+(E) $guard#234 == (!$cond#233 && $guard#227)
+
+*** 235 file line 6 function abort
+(E) $cond#235 == FALSE
+
+*** 236 file line 7 function abort
+(E) $guard#236 == ($cond#235 && $guard#234)
+
+*** 237 file main.c line 15 function alloc_node
+(E) dynamic_object$2.next#237 == ((struct node *)NULL)
+(E) $guard#237 == ($cond#233 && $guard#227 || $guard#236)
+
+*** 238 file main.c line 16 function alloc_node
+(E) alloc_node#return_value#238 == ptr#231
+
+*** 241 file main.c line 16 function alloc_node
+(E) $cond#241 == TRUE
+
+*** 242 file main.c line 17 function alloc_node
+(E) $guard#242 == FALSE
+
+*** 244 file main.c line 17 function alloc_node
+(E) $guard#244 == ($cond#241 && $guard#237 || $guard#242)
+
+*** 245 file main.c line 21 function chain_node
+(E) node#245 == alloc_node#return_value#238
+
+*** 247 file main.c line 22 function chain_node
+(E) dynamic_object$2.next#247 == (ppnode#188 == &list ? list#phi184 : deref#247)
+
+*** 248 file main.c line 23 function chain_node
+(E) list#248 == node#245
+
+*** 252 file main.c line 44 function create_sll
+(E) i#252 == 1 + i#phi184
+
+*** 253 file main.c line 44 function create_sll
+(E) $cond#253 == TRUE
+loop back to location 184
+
+*** 254 file main.c line 47 function create_sll
+(E) $guard#254 == ($cond#184 && $guard#184)
+
+*** 255 file main.c line 49 function create_sll
+(E) create_sll#return_value#255 == list#phi184
+
+*** 257 file main.c line 49 function create_sll
+(E) $cond#257 == TRUE
+
+*** 258 file main.c line 50 function create_sll
+(E) $guard#258 == FALSE
+
+*** 259 file main.c line 50 function create_sll
+(E) $guard#259 == ($cond#257 && $guard#254 || $guard#258)
+
+*** 262 file main.c line 64 function main
+(E) list#262 == create_sll#return_value#255
+
+*** 266 file main.c line 65 function main
+(E) beg#266 == nondet_symbol(ssa::nondet266.1)
+
+*** 267 file main.c line 65 function main
+(E) beg#267 == list#262
+
+*** 269 file main.c line 65 function main
+(E) end#269 == nondet_symbol(ssa::nondet269.1)
+
+*** 270 file main.c line 65 function main
+(E) end#270 == p1#phi107
+
+*** 271 file main.c line 53 function check_seq_next
+(A) !(beg#267 == ((struct node *)NULL)) || !$guard#259
+
+*** 272 file main.c line 54 function check_seq_next
+(A) !(end#270 == ((struct node *)NULL)) || !$guard#259
+
+*** 273 file main.c line 56 function check_seq_next
+(E) beg#273 == (beg#267 == &dynamic_object$2 ? dynamic_object$2.next#phi184 : (beg#267 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#267 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#273.next)))
+
+*** 274 file main.c line 56 function check_seq_next
+(E) beg#phi274 == ($guard#ls277 ? beg#lb277 : beg#273)
+(E) $cond#274 == (end#270 == beg#phi274)
+(E) $guard#274 == $guard#259
+
+*** 275 file main.c line 57 function check_seq_next
+(E) $guard#275 == (!$cond#274 && $guard#274)
+(A) !(beg#phi274 == ((struct node *)NULL)) || !$guard#275
+
+*** 276 file main.c line 56 function check_seq_next
+(E) beg#276 == (beg#phi274 == &dynamic_object$2 ? dynamic_object$2.next#phi184 : (beg#phi274 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#phi274 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#276.next)))
+
+*** 277 file main.c line 56 function check_seq_next
+(E) $cond#277 == TRUE
+loop back to location 274
+
+*** 278 file main.c line 58 function check_seq_next
+(E) $guard#278 == ($cond#274 && $guard#274)
+
+*** 283 file main.c line 66 function main
+(E) beg#283 == nondet_symbol(ssa::nondet283.1)
+
+*** 284 file main.c line 66 function main
+(E) beg#284 == p1#phi107
+
+*** 286 file main.c line 66 function main
+(E) end#286 == nondet_symbol(ssa::nondet286.1)
+
+*** 287 file main.c line 66 function main
+(E) end#287 == p2#phi32
+
+*** 288 file main.c line 53 function check_seq_next
+(A) !(beg#284 == ((struct node *)NULL)) || !$guard#278
+
+*** 289 file main.c line 54 function check_seq_next
+(A) !(end#287 == ((struct node *)NULL)) || !$guard#278
+
+*** 290 file main.c line 56 function check_seq_next
+(E) beg#290 == (beg#284 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#284 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#290.next))
+
+*** 291 file main.c line 56 function check_seq_next
+(E) beg#phi291 == ($guard#ls294 ? beg#lb294 : beg#290)
+(E) $cond#291 == (end#287 == beg#phi291)
+(E) $guard#291 == $guard#278
+
+*** 292 file main.c line 57 function check_seq_next
+(E) $guard#292 == (!$cond#291 && $guard#291)
+(A) !(beg#phi291 == ((struct node *)NULL)) || !$guard#292
+
+*** 293 file main.c line 56 function check_seq_next
+(E) beg#293 == (beg#phi291 == &dynamic_object$1 ? dynamic_object$1.next#phi107 : (beg#phi291 == &dynamic_object$0 ? dynamic_object$0.next#phi32 : deref#293.next))
+
+*** 294 file main.c line 56 function check_seq_next
+(E) $cond#294 == TRUE
+loop back to location 291
+
+*** 295 file main.c line 58 function check_seq_next
+(E) $guard#295 == ($cond#291 && $guard#291)
+
+(enable) TRUE
+
+
+Callee summaries:
+Callee bindings:
+
+Loops not fully unwound
+Running refinement loop with MiniSAT 2.2.1 with simplifier
+** 0 of 6 failed (1 iterations)
+** statistics:
+ number of solver instances: 1
+ number of solver calls: 14
+ number of summaries used: 0
+
+[check_seq_next.assertion.1] assertion beg != (struct node *)(void *)0: OK
+[check_seq_next.assertion.2] assertion end != (struct node *)(void *)0: OK
+[check_seq_next.assertion.3] assertion beg != (struct node *)(void *)0: OK
+[check_seq_next.assertion.4] assertion beg != (struct node *)(void *)0: OK
+[check_seq_next.assertion.5] assertion end != (struct node *)(void *)0: OK
+[check_seq_next.assertion.6] assertion beg != (struct node *)(void *)0: OK
+
+** 0 of 6 unknown
+** 0 of 6 failed
+VERIFICATION SUCCESSFUL
+EXIT=0
+SIGNAL=0
diff --git a/regression/heap/sll_to_dll1_reverse/main.c b/regression/heap/sll_to_dll1_reverse/main.c
index e8d0d1829..f25d00f7e 100644
--- a/regression/heap/sll_to_dll1_reverse/main.c
+++ b/regression/heap/sll_to_dll1_reverse/main.c
@@ -1,3 +1,5 @@
+extern void __VERIFIER_error() __attribute__ ((__noreturn__));
+
#include
extern int __VERIFIER_nondet_int(void);
@@ -10,8 +12,8 @@ struct node {
static struct node* alloc_node(void)
{
struct node *ptr = malloc(sizeof *ptr);
- if (!ptr)
- abort();
+ // if (!ptr)
+ // abort();
ptr->next = NULL;
ptr->prev = NULL;
@@ -35,8 +37,9 @@ static struct node* create_sll(const struct node **pp1, const struct node **pp2)
*pp1 = *pp2;
- while (__VERIFIER_nondet_int())
+ do
chain_node(pp1);
+ while (__VERIFIER_nondet_int());
struct node *list = *pp1;
@@ -48,10 +51,10 @@ static struct node* create_sll(const struct node **pp1, const struct node **pp2)
}
void init_back_link(struct node *list) {
- for (;;) {
+ while (list) {
struct node *next = list->next;
- if (!next)
- return;
+ // if (!next)
+ // return;
next->prev = list;
list = next;
@@ -96,19 +99,19 @@ void main()
const struct node *p1, *p2;
struct node *list = create_sll(&p1, &p2);
- check_seq_next(p1, p2);
assert(p1->prev == NULL);
assert(p2->prev == NULL);
+ check_seq_next(p1, p2);
init_back_link(list);
check_seq_next(p1, p2);
check_seq_prev(p2, p1);
- reverse_dll(list);
- check_seq_prev(p1, p2);
- check_seq_next(p2, p1);
+ // reverse_dll(list);
+ // check_seq_prev(p1, p2);
+ // check_seq_next(p2, p1);
remove_fw_link(list);
- check_seq_prev(p1, p2);
+ check_seq_prev(p2, p1);
}
diff --git a/regression/heap/sll_to_dll1_reverse/test.desc b/regression/heap/sll_to_dll1_reverse/test.desc
index 92784083a..ed14b476a 100644
--- a/regression/heap/sll_to_dll1_reverse/test.desc
+++ b/regression/heap/sll_to_dll1_reverse/test.desc
@@ -1,4 +1,4 @@
-KNOWNBUG
+CORE
main.c
--heap --inline --no-propagation
^EXIT=0$
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index c4daa5062..3af05b446 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -4,6 +4,7 @@
#include "heap_domain.h"
#include "util.h"
+#include "domain.h"
#include
#include
@@ -60,7 +61,7 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
templ_row.member = component.get_name();
templ_row.pre_guard = v1->pre_guard;
templ_row.post_guard = v1->post_guard;
- templ_row.aux_expr = v1->post_guard;
+ templ_row.aux_expr = v1->aux_expr;
templ_row.kind = v1->kind;
templ_row.dynamic = dynamic;
if (dynamic)
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index d602ee17a..68a129f2f 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -101,8 +101,10 @@ class heap_domaint : public domaint
// p = d
path_expr.push_back(equal_exprt(templ_expr, dest));
}
- for (const dyn_objt &obj1 : path.dyn_objects)
+ for (const dyn_objt &obj1 : points_to)
{
+ if (path.dyn_objects.find(obj1) != path.dyn_objects.end())
+ {
// p = &o
exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
@@ -117,6 +119,13 @@ class heap_domaint : public domaint
}
path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
+ }
+ else
+ {
+ path_expr.push_back(equal_exprt(templ_expr,
+ is_null_ptr(obj1.first) ?
+ obj1.first : address_of_exprt(obj1.first)));
+ }
}
result.push_back(disjunction(path_expr));
@@ -127,7 +136,7 @@ class heap_domaint : public domaint
inline bool empty() const
{
- return paths.empty() && points_to.empty();
+ return paths.empty();
}
};
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 2051dbc95..0291f02fc 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -69,6 +69,10 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
exprt c = heap_domain.get_row_pre_constraint(i, inv[i]).op1();
debug() << "cond: " << from_expr(ns, "", c) << " " <<
from_expr(ns, "", solver.get(c)) << eom;
+ forall_operands(it, c)
+ {
+ debug() << from_expr(ns, "", *it) << " " << from_expr(ns, "", solver.get(*it)) << eom;
+ }
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].pre_guard) <<
" " << from_expr(ns, "", solver.get(heap_domain.templ[i].pre_guard)) << eom;
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].post_guard) << " "
@@ -76,6 +80,10 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
exprt post = heap_domain.get_row_post_constraint(i, inv[i]).op1();
debug() << "post-cond: " << from_expr(ns, "", post) << " "
<< from_expr(ns, "", solver.get(post)) << eom;
+ forall_operands(it, post)
+ {
+ debug() << from_expr(ns, "", *it) << " " << from_expr(ns, "", solver.get(*it)) << eom;
+ }
}
#endif
@@ -104,7 +112,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
improved = true;
debug() << "add points to: " << from_expr(ns, "", ptr_value) << eom;
}
- else
+ else if (ptr_value.id() == ID_address_of)
{
// pointer points to the heap (p = &obj)
debug() << from_expr(ns, "", ptr_value) << eom;
@@ -115,14 +123,20 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (obj.type().get_bool("#dynamic"))
{
// Find row with corresponding member field of pointed object (obj.member)
+ int member_val_index;
if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
heap_domain.get_base_name(obj) ==
heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
{
- --actual_loc;
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member, --actual_loc);
+ if (member_val_index < 0)
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member,
+ ++actual_loc);
+ }
+ else
+ {
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member, actual_loc);
}
- int member_val_index = find_member_row(obj, heap_domain.templ[row].member,
- actual_loc);
assert(member_val_index >= 0);
exprt member_expr = heap_domain.templ[member_val_index].expr;
exprt do_expr = heap_domain.templ[member_val_index].dyn_obj;
From 0a659066b69c80b9aaa0c324581593b53029a7c0 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 22 Sep 2016 14:26:51 +0100
Subject: [PATCH 022/322] Heap domain: recursive updating values of template
rows when a dependent row is changed.
---
src/domains/heap_domain.cpp | 17 ++++++--
src/domains/heap_domain.h | 7 +++-
src/domains/strategy_solver_heap.cpp | 62 +++++++++++++++-------------
src/domains/strategy_solver_heap.h | 3 ++
4 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 3af05b446..84c04f9cc 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -21,6 +21,7 @@ void heap_domaint::initialize(domaint::valuet &value)
{
val[row].paths.clear();
val[row].points_to.clear();
+ val[row].pointed_by.clear();
}
}
@@ -66,11 +67,8 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
templ_row.dynamic = dynamic;
if (dynamic)
{
- int loc_num = get_symbol_loc(var1);
std::string var1_id = id2string(to_symbol_expr(var1).get_identifier());
- std::string do_base_id = var1_id.substr(0, var1_id.find_last_of('.'));
- // TODO just add the whole suffix
- irep_idt do_id = do_base_id + "#lb" + std::to_string(loc_num);
+ std::string do_id = var1_id.substr(0, var1_id.find_last_of('.'));
templ_row.dyn_obj = symbol_exprt(do_id, var1.type().subtype());
}
else
@@ -240,6 +238,17 @@ bool heap_domaint::add_points_to(const rowt &row, heap_valuet &value, const dyn_
return new_pt.second;
}
+/**
+ * Add new dependent row (pb_row points to row)
+ * @param row Pointed row
+ * @param pb_row Pointer row
+ * @param value Hepa value
+ */
+void heap_domaint::add_pointed_by_row(const rowt &row, const rowt &pb_row, heap_valuet &value)
+{
+ value[row].pointed_by.insert(pb_row);
+}
+
void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
const namespacet &ns) const
{
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 68a129f2f..e3bb1ca47 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -58,8 +58,9 @@ class heap_domaint : public domaint
}
};
- std::set paths; /**< Set of paths leading from the row variable */
- std::set points_to; /**< Set of objects (or NULL) the row variable can point to */
+ std::set paths; /**< Set of paths leading from the row variable */
+ std::set points_to; /**< Set of objects (or NULL) the row variable can point to */
+ std::set pointed_by; /**< Set of rows whose variables point to this row */
/**
* Get expression for the row value. It is a conjunction of points to expression and path
@@ -179,6 +180,8 @@ class heap_domaint : public domaint
bool add_points_to(const rowt &row, heap_valuet &value, const dyn_objt &dyn_obj);
+ void add_pointed_by_row(const rowt &row, const rowt &pb_row, heap_valuet &value);
+
// Printing
virtual void output_value(std::ostream &out, const valuet &value,
const namespacet &ns) const override;
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 0291f02fc..b332c86d7 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -69,10 +69,6 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
exprt c = heap_domain.get_row_pre_constraint(i, inv[i]).op1();
debug() << "cond: " << from_expr(ns, "", c) << " " <<
from_expr(ns, "", solver.get(c)) << eom;
- forall_operands(it, c)
- {
- debug() << from_expr(ns, "", *it) << " " << from_expr(ns, "", solver.get(*it)) << eom;
- }
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].pre_guard) <<
" " << from_expr(ns, "", solver.get(heap_domain.templ[i].pre_guard)) << eom;
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].post_guard) << " "
@@ -80,10 +76,6 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
exprt post = heap_domain.get_row_post_constraint(i, inv[i]).op1();
debug() << "post-cond: " << from_expr(ns, "", post) << " "
<< from_expr(ns, "", solver.get(post)) << eom;
- forall_operands(it, post)
- {
- debug() << from_expr(ns, "", *it) << " " << from_expr(ns, "", solver.get(*it)) << eom;
- }
}
#endif
@@ -154,30 +146,15 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
improved = true;
debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+
+ heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
}
}
if (heap_domain.templ[row].dynamic)
- { // Recursively check all expressions and update those that point to the dynamic object
- // that this row variable belongs to.
- for (unsigned j = 0; j < heap_domain.templ.size(); ++j)
- {
- if (heap_domain.templ[row].member == heap_domain.templ[j].member)
- {
- for (auto &pt : inv[j].points_to)
- {
- exprt pre_pointer = heap_domain.templ[row].expr;
- if (pre_pointer == pt.second)
- {
- if (heap_domain.add_all_paths(j, row, inv, pt))
- improved = true;
- debug() << "recursively updating row: " << j << eom;
- debug() << "add all paths: " << from_expr(ns, "", pre_pointer) << ", through: "
- << from_expr(ns, "", pt.first) << eom;
- }
- }
- }
- }
+ { // Recursively update all rows that are dependent on this row
+ updated_rows.clear();
+ update_rows_rec(row, inv);
}
}
}
@@ -224,7 +201,7 @@ int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &mem
for (unsigned i = 0; i < heap_domain.templ.size(); ++i)
{
heap_domaint::template_rowt &templ_row = heap_domain.templ[i];
- if (templ_row.member == member && templ_row.dyn_obj.id() != ID_nil)
+ if (templ_row.member == member && templ_row.dynamic)
{
std::string id = id2string(to_symbol_expr(templ_row.expr).get_identifier());
if (id.find(obj_id) != std::string::npos)
@@ -240,3 +217,30 @@ int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &mem
}
return result;
}
+
+/**
+ * Recursively update rows that point to given row.
+ * @param row Pointed row
+ * @param value Heap value
+ * @return True if any change occured
+ */
+bool strategy_solver_heapt::update_rows_rec(const heap_domaint::rowt &row,
+ heap_domaint::heap_valuet &value)
+{
+ updated_rows.insert(row);
+ bool result = false;
+ heap_domaint::template_rowt &templ_row = heap_domain.templ[row];
+ for (auto &ptr : value[row].pointed_by)
+ {
+ if (heap_domain.add_all_paths(ptr, row, value,
+ std::make_pair(templ_row.dyn_obj, templ_row.expr)))
+ result = true;
+ debug() << "recursively updating row: " << ptr << eom;
+ debug() << "add all paths: " << from_expr(ns, "", templ_row.expr) << ", through: "
+ << from_expr(ns, "", templ_row.dyn_obj) << eom;
+ // Recursive update is called for each row only once
+ if (updated_rows.find(ptr) == updated_rows.end())
+ result = update_rows_rec(ptr, value) || result;
+ }
+ return result;
+}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index edb63c9a4..5b22acf4e 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -21,8 +21,11 @@ class strategy_solver_heapt : public strategy_solver_baset
protected:
heap_domaint &heap_domain;
+ std::set updated_rows;
int find_member_row(const exprt &obj, const irep_idt &member, int actual_loc);
+
+ bool update_rows_rec(const heap_domaint::rowt &row, heap_domaint::heap_valuet &value);
};
From fd2290f73555acec567fab0c125606b08813647c Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 23 Sep 2016 17:32:20 +0100
Subject: [PATCH 023/322] Heap domain: remove zero_length field from path.
---
src/domains/heap_domain.cpp | 14 ++++----------
src/domains/heap_domain.h | 10 ++--------
2 files changed, 6 insertions(+), 18 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 84c04f9cc..9fca9faf5 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -175,24 +175,18 @@ bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt
{
// Path does not exist yet
std::set dyn_obj_set;
- bool zero_path = true;
if (dyn_obj.first.id() != ID_nil)
{ // Path doesn't have zero length
dyn_obj_set.insert(dyn_obj);
- zero_path = false;
}
- path_set.emplace(dest, dyn_obj_set, zero_path);
+ path_set.emplace(dest, dyn_obj_set);
return true;
}
else
{
// Path exists already
- if (dyn_obj.first.id() == ID_nil)
- {
- bool result = path_set.find(dest)->zero_length;
- path_set.find(dest)->zero_length = true;
- return !result;
- }
+ if (dyn_obj.first.id() == ID_nil) return false;
+
// Try to insert new dynamic object belonging to the path
return path_set.find(dest)->dyn_objects.insert(dyn_obj).second;
}
@@ -242,7 +236,7 @@ bool heap_domaint::add_points_to(const rowt &row, heap_valuet &value, const dyn_
* Add new dependent row (pb_row points to row)
* @param row Pointed row
* @param pb_row Pointer row
- * @param value Hepa value
+ * @param value Heap value
*/
void heap_domaint::add_pointed_by_row(const rowt &row, const rowt &pb_row, heap_valuet &value)
{
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index e3bb1ca47..8f75a37dd 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -40,12 +40,11 @@ class heap_domaint : public domaint
{
exprt destination;
mutable std::set dyn_objects;
- mutable bool zero_length;
patht(const exprt &dest_) : destination(dest_) {}
- patht(const exprt &dest_, const std::set &dyn_objs_, const bool zero_l_)
- : destination(dest_), dyn_objects(dyn_objs_), zero_length(zero_l_) {}
+ patht(const exprt &dest_, const std::set &dyn_objs_)
+ : destination(dest_), dyn_objects(dyn_objs_) {}
bool operator<(const patht &rhs) const
{
@@ -97,11 +96,6 @@ class heap_domaint : public domaint
const exprt &dest = path.destination;
exprt::operandst path_expr;
- if (path.zero_length)
- {
- // p = d
- path_expr.push_back(equal_exprt(templ_expr, dest));
- }
for (const dyn_objt &obj1 : points_to)
{
if (path.dyn_objects.find(obj1) != path.dyn_objects.end())
From 78032354574805722bde7592619a091fe0f56c0e Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 23 Sep 2016 17:56:26 +0100
Subject: [PATCH 024/322] SSA dereference: replace "deref" for pointers to
objects by real "unknown" objects.
---
src/domains/strategy_solver_heap.cpp | 68 ++++++++++++----------
src/ssa/assignments.cpp | 2 +-
src/ssa/local_ssa.cpp | 84 +++++++++++++++++++++++++++-
src/ssa/local_ssa.h | 11 +++-
src/ssa/malloc_ssa.cpp | 2 +
src/ssa/ssa_dereference.cpp | 16 +++++-
src/ssa/ssa_object.h | 6 ++
7 files changed, 155 insertions(+), 34 deletions(-)
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index b332c86d7..68ee5ace2 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -114,40 +114,50 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (obj.type().get_bool("#dynamic"))
{
- // Find row with corresponding member field of pointed object (obj.member)
- int member_val_index;
- if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
- heap_domain.get_base_name(obj) ==
- heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
+ if (id2string(obj.get_identifier()).find("$unknown") != std::string::npos)
{
- member_val_index = find_member_row(obj, heap_domain.templ[row].member, --actual_loc);
- if (member_val_index < 0)
- member_val_index = find_member_row(obj, heap_domain.templ[row].member,
- ++actual_loc);
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
}
else
{
- member_val_index = find_member_row(obj, heap_domain.templ[row].member, actual_loc);
+ // Find row with corresponding member field of pointed object (obj.member)
+ int member_val_index;
+ if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
+ heap_domain.get_base_name(obj) ==
+ heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
+ {
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member,
+ --actual_loc);
+ if (member_val_index < 0)
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member,
+ ++actual_loc);
+ }
+ else
+ {
+ member_val_index = find_member_row(obj, heap_domain.templ[row].member, actual_loc);
+ }
+ assert(member_val_index >= 0);
+ exprt member_expr = heap_domain.templ[member_val_index].expr;
+ exprt do_expr = heap_domain.templ[member_val_index].dyn_obj;
+
+ // Add all paths from obj.next to p
+ if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
+ std::make_pair(obj, member_expr)))
+ improved = true;
+ debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
+ << from_expr(ns, "", obj) << eom;
+
+ assert(do_expr.id() != ID_nil);
+ // Add points to information
+ assert(do_expr.id() == ID_symbol);
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+
+ heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
}
- assert(member_val_index >= 0);
- exprt member_expr = heap_domain.templ[member_val_index].expr;
- exprt do_expr = heap_domain.templ[member_val_index].dyn_obj;
-
- // Add all paths from obj.next to p
- if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
- std::make_pair(obj, member_expr)))
- improved = true;
- debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
- << from_expr(ns, "", obj) << eom;
-
- assert(do_expr.id() != ID_nil);
- // Add points to information
- assert(do_expr.id() == ID_symbol);
- if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
- improved = true;
- debug() << "add points to: " << from_expr(ns, "", obj) << eom;
-
- heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
}
}
diff --git a/src/ssa/assignments.cpp b/src/ssa/assignments.cpp
index 2a5bc1c6b..5c977cb6b 100644
--- a/src/ssa/assignments.cpp
+++ b/src/ssa/assignments.cpp
@@ -121,7 +121,7 @@ void assignmentst::assign(
// object?
ssa_objectt ssa_object(lhs, ns);
- if(ssa_object)
+ if(ssa_object && !ssa_object.is_unknown_obj()) // unknown objects are just placeholders
{
assign(ssa_object, loc, ns);
}
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index f86fbb092..d9a941cc5 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -58,6 +58,7 @@ void local_SSAt::build_SSA()
build_guard(i_it);
build_assertions(i_it);
build_function_call(i_it);
+ build_unknown_objs(i_it);
}
// collect custom templates in loop heads
@@ -1344,7 +1345,10 @@ void local_SSAt::assign_rec(
else if(lhs.id()==ID_if)
{
const if_exprt &if_expr=to_if_expr(lhs);
- assign_rec(if_expr.true_case(), rhs, and_exprt(guard, if_expr.cond()), loc);
+
+ exprt new_rhs = if_exprt(if_expr.cond(), rhs, if_expr.true_case());
+ assign_rec(if_expr.true_case(), new_rhs, and_exprt(guard, if_expr.cond()), loc);
+
assign_rec(
if_expr.false_case(),
rhs,
@@ -1559,6 +1563,18 @@ std::list &operator<<(
{
dest.push_back(*c_it);
}
+
+ for (auto &obj : src.unknown_objs)
+ {
+ const typet &obj_type = src.ns.follow(obj.type());
+ if (obj_type.id() == ID_struct)
+ {
+ for (auto &component : to_struct_type(obj_type).components())
+ {
+ dest.push_back(src.unknown_obj_eq(obj, component));
+ }
+ }
+ }
}
#endif
@@ -1609,6 +1625,18 @@ decision_proceduret &operator<<(
dest << *c_it;
}
}
+
+ for (auto &obj : src.unknown_objs)
+ {
+ const typet &obj_type = src.ns.follow(obj.type());
+ if (obj_type.id() == ID_struct)
+ {
+ for (auto &component : to_struct_type(obj_type).components())
+ {
+ dest << src.unknown_obj_eq(obj, component);
+ }
+ }
+ }
#endif
return dest;
}
@@ -1677,6 +1705,18 @@ incremental_solvert &operator<<(
dest << *c_it;
}
}
+
+ for (auto &obj : src.unknown_objs)
+ {
+ const typet &obj_type = src.ns.follow(obj.type());
+ if (obj_type.id() == ID_struct)
+ {
+ for (auto &component : to_struct_type(obj_type).components())
+ {
+ dest << src.unknown_obj_eq(obj, component);
+ }
+ }
+ }
#endif
return dest;
}
@@ -1736,3 +1776,45 @@ bool local_SSAt::has_function_calls() const
return found;
}
+/**
+ * If a location is malloc call, create "unknown object" for return type. This is later used
+ * as a placeholder for invalid of unknown dereference of an object of that type.
+ * @param loc Location
+ */
+void local_SSAt::build_unknown_objs(locationt loc)
+{
+ if (loc->is_assign())
+ {
+ const code_assignt &code_assign = to_code_assign(loc->code);
+ const exprt &rhs = code_assign.rhs();
+ if (rhs.get_bool("#malloc_result"))
+ {
+ const exprt &addr_of_do = rhs.id() == ID_typecast ? to_typecast_expr(rhs).op() : rhs;
+ const exprt &dyn_obj = to_address_of_expr(addr_of_do).object();
+ const typet &dyn_type = ns.follow(dyn_obj.type());
+
+ std::string dyn_type_name = dyn_type.id_string();
+ if (dyn_type.id() == ID_struct)
+ dyn_type_name += "_" + id2string(to_struct_type(dyn_type).get_tag());
+ irep_idt identifier = "ssa::" + dyn_type_name + "_obj$unknown";
+
+ symbol_exprt unknown_obj(identifier, dyn_obj.type());
+ unknown_objs.insert(unknown_obj);
+ }
+ }
+}
+
+/**
+ * Create equality obj.component = &obj, which creates self-loop on "unknown" objects.
+ * @param obj "Unknown" object
+ * @param component Object's component
+ * @return Equality obj.component = &obj
+ */
+exprt local_SSAt::unknown_obj_eq(const symbol_exprt &obj,
+ const struct_typet::componentt &component) const
+{
+ const irep_idt identifier =
+ id2string(obj.get_identifier()) + "." + id2string(component.get_name());
+ const symbol_exprt member(identifier, component.type());
+ return equal_exprt(member, address_of_exprt(obj));
+}
diff --git a/src/ssa/local_ssa.h b/src/ssa/local_ssa.h
index 0f8fcc477..38914d95a 100644
--- a/src/ssa/local_ssa.h
+++ b/src/ssa/local_ssa.h
@@ -13,7 +13,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include
-#include "../domains/incremental_solver.h"
+#include
+
#include "ssa_domain.h"
#include "guard_map.h"
#include "ssa_object.h"
@@ -123,9 +124,12 @@ class local_SSAt
// function entry and exit variables
typedef std::list var_listt;
typedef std::set var_sett;
- var_listt params;
+ var_listt params;
var_sett globals_in, globals_out;
+ // unknown heap objects
+ var_sett unknown_objs;
+
bool has_function_calls() const;
const namespacet &ns;
@@ -162,6 +166,8 @@ class local_SSAt
void assign_rec(
const exprt &lhs, const exprt &rhs, const exprt &guard, locationt loc);
+ exprt unknown_obj_eq(const symbol_exprt &obj, const struct_typet::componentt &component) const;
+
void get_entry_exit_vars();
bool has_static_lifetime(const ssa_objectt &) const;
@@ -212,6 +218,7 @@ class local_SSAt
void build_guard(locationt loc);
void build_function_call(locationt loc);
void build_assertions(locationt loc);
+ void build_unknown_objs(locationt loc);
// custom templates
void collect_custom_templates();
diff --git a/src/ssa/malloc_ssa.cpp b/src/ssa/malloc_ssa.cpp
index 9e2263f9b..9a51ba3f9 100644
--- a/src/ssa/malloc_ssa.cpp
+++ b/src/ssa/malloc_ssa.cpp
@@ -165,6 +165,8 @@ exprt malloc_ssa(
if(result.type()!=code.type())
result=typecast_exprt(result, code.type());
+ result.set("#malloc_result", true);
+
return result;
}
diff --git a/src/ssa/ssa_dereference.cpp b/src/ssa/ssa_dereference.cpp
index 3bc60c5c8..f6be56299 100644
--- a/src/ssa/ssa_dereference.cpp
+++ b/src/ssa/ssa_dereference.cpp
@@ -325,7 +325,21 @@ exprt dereference_rec(
// We use the identifier produced by
// local_SSAt::replace_side_effects_rec
- exprt result=symbol_exprt(nondet_prefix, src.type());
+ exprt result;
+ const typet &pointed_type = pointer.type().subtype();
+ if (pointed_type.id() == ID_pointer)
+ result = symbol_exprt(nondet_prefix, src.type());
+ else
+ {
+ const typet &obj_type = ns.follow(pointed_type);
+ std::string dyn_type_name = obj_type.id_string();
+ if (obj_type.id() == ID_struct)
+ dyn_type_name += "_" + id2string(to_struct_type(obj_type).get_tag());
+ irep_idt identifier = "ssa::" + dyn_type_name + "_obj$unknown";
+
+ result = symbol_exprt(identifier, src.type());
+ }
+
// query the value sets
const ssa_value_domaint::valuest values=
diff --git a/src/ssa/ssa_object.h b/src/ssa/ssa_object.h
index 37f4b8c8e..1cb21ec1d 100644
--- a/src/ssa/ssa_object.h
+++ b/src/ssa/ssa_object.h
@@ -84,6 +84,12 @@ class ssa_objectt
return get_root_object_rec(expr);
}
+ inline bool is_unknown_obj()
+ {
+ std::string id_str = id2string(identifier);
+ return id_str.find("$unknown") != std::string::npos;
+ }
+
protected:
exprt expr;
identifiert identifier;
From 8d6eba70d978136024d2a31a6ceefa34c809977f Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 30 Sep 2016 10:31:28 +0100
Subject: [PATCH 025/322] SSA: add pointed object into globals only if it is
assigned in the function, or the original pointer is parameter.
---
src/ssa/local_ssa.cpp | 29 +++++++++++++++--------------
src/ssa/ssa_object.cpp | 6 ++----
2 files changed, 17 insertions(+), 18 deletions(-)
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index d9a941cc5..43031bad9 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -150,6 +150,21 @@ void local_SSAt::get_globals(
id2string(returns_for_function)+"#return_value")==std::string::npos)
continue;
+ const exprt &root_obj=it->get_root_object();
+ if(is_ptr_object(root_obj))
+ {
+ const symbolt *symbol;
+ if(ns.lookup(root_obj.get(ID_ptr_object), symbol)) continue;
+ if(!symbol->is_parameter)
+ {
+ const ssa_domaint &ssa_domain=ssa_analysis[loc];
+ // Filter out non-assigned symbols
+ const auto &def=ssa_domain.def_map.find(it->get_identifier());
+ if(def->second.def.is_input())
+ continue;
+ }
+ }
+
if(rhs_value)
{
const exprt &expr=read_rhs(it->get_expr(), loc);
@@ -1678,20 +1693,6 @@ incremental_solvert &operator<<(
dest << implies_exprt(n_it->enabling_expr, *e_it);
else
dest << *e_it;
-
-#if 0
- // freeze cond variables
- if(e_it->op0().id()==ID_symbol &&
- e_it->op0().type().id()==ID_bool)
- {
- const symbol_exprt &symbol=to_symbol_expr(e_it->op0());
- if(id2string(symbol.get_identifier()).find("ssa::$cond")!=
- std::string::npos)
- {
- dest.solver->set_frozen(dest.solver->convert(symbol));
- }
- }
-#endif
}
for(local_SSAt::nodet::constraintst::const_iterator
diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp
index 72440df3a..55f3e185f 100644
--- a/src/ssa/ssa_object.cpp
+++ b/src/ssa/ssa_object.cpp
@@ -231,9 +231,7 @@ void ssa_objectst::add_ptr_objects(
{
if(o_it->type().id()==ID_pointer)
{
- const symbolt &symbol=ns.lookup(root_object);
- if(symbol.is_parameter)
- tmp.insert(*o_it);
+ tmp.insert(*o_it);
}
}
}
@@ -280,7 +278,7 @@ void ssa_objectst::categorize_objects(
if(root_object.id()==ID_symbol)
{
- if(is_ptr_object(root_object))
+ if(is_ptr_object(root_object) || root_object.type().get_bool("#dynamic"))
{
globals.insert(*o_it);
}
From 20d3745894df3b3ae397e812a7faf26dcb7aa3c1 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 13 Oct 2016 14:35:19 +0100
Subject: [PATCH 026/322] Improve heap objects passing between functions.
Objects pointed by parameters are passed to function as global. Handle heap
objects pointed by return value of called function.
---
src/ssa/assignments.cpp | 8 +++++-
src/ssa/local_ssa.cpp | 56 ++++++++++++++++++++++++++++---------
src/ssa/ssa_dereference.cpp | 2 +-
src/ssa/ssa_object.cpp | 19 +++++++++----
src/ssa/ssa_value_set.cpp | 13 +++++++++
5 files changed, 77 insertions(+), 21 deletions(-)
diff --git a/src/ssa/assignments.cpp b/src/ssa/assignments.cpp
index 5c977cb6b..7c4d99e46 100644
--- a/src/ssa/assignments.cpp
+++ b/src/ssa/assignments.cpp
@@ -61,7 +61,13 @@ void assignmentst::build_assignment_map(
for(objectst::const_iterator
o_it=ssa_objects.globals.begin();
o_it!=ssa_objects.globals.end(); o_it++)
- assign(*o_it, it, ns);
+ {
+ const exprt &function = code_function_call.function();
+ if (function.id() == ID_symbol &&
+ id2string(o_it->get_identifier()).find(
+ id2string(to_symbol_expr(function).get_identifier())) != std::string::npos)
+ assign(*o_it, it, ns);
+ }
// the call might come with an assignment
if(code_function_call.lhs().is_not_nil())
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index 43031bad9..dbf9bb8d0 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -95,13 +95,32 @@ void local_SSAt::get_entry_exit_vars()
if(ns.lookup(identifier, symbol))
continue;
- params.push_back(symbol->symbol_expr());
+ const symbol_exprt ¶m=symbol->symbol_expr();
+ params.push_back(param);
+
+ if(param.type().id()==ID_pointer)
+ {
+ const typet &pointed_type=ns.follow(param.type().subtype());
+ const symbol_exprt pointed_obj(id2string(param.get_identifier()) + "'obj", pointed_type);
+ nodes.begin()->equalities.push_back(equal_exprt(param, address_of_exprt(pointed_obj)));
+ }
}
// get globals in
goto_programt::const_targett first=goto_function.body.instructions.begin();
get_globals(first, globals_in, true, false); // filters out #return_value
+ for(auto &global_in : globals_in)
+ {
+ if(global_in.type().id()==ID_pointer &&
+ id2string(global_in.get_identifier()).find('.') == std::string::npos)
+ {
+ const typet &pointed_type=ns.follow(global_in.type().subtype());
+ const symbol_exprt pointed_obj(id2string(global_in.get_identifier()) + "'obj", pointed_type);
+ nodes.begin()->equalities.push_back(equal_exprt(global_in, address_of_exprt(pointed_obj)));
+ }
+ }
+
// get globals out (includes return value)
goto_programt::const_targett
last=goto_function.body.instructions.end(); last--;
@@ -142,21 +161,26 @@ void local_SSAt::get_globals(
"#return_value")!=std::string::npos)
continue;
- // filter out return values of other functions
+ //filter out return values of other functions
if(with_returns && returns_for_function!="" &&
- id2string(it->get_identifier()).find(
- "#return_value")!=std::string::npos &&
+ id2string(it->get_identifier()).find("#return_value")==
+ id2string(it->get_identifier()).size()-std::string("#return_value").size() &&
id2string(it->get_identifier()).find(
id2string(returns_for_function)+"#return_value")==std::string::npos)
continue;
const exprt &root_obj=it->get_root_object();
+ if(root_obj.type().get_bool("#dynamic") && !with_returns)
+ continue;
if(is_ptr_object(root_obj))
{
const symbolt *symbol;
if(ns.lookup(root_obj.get(ID_ptr_object), symbol)) continue;
if(!symbol->is_parameter)
{
+ if(!with_returns ||
+ id2string(it->get_identifier()).find("'obj")==std::string::npos)
+ continue;
const ssa_domaint &ssa_domain=ssa_analysis[loc];
// Filter out non-assigned symbols
const auto &def=ssa_domain.def_map.find(it->get_identifier());
@@ -1361,8 +1385,13 @@ void local_SSAt::assign_rec(
{
const if_exprt &if_expr=to_if_expr(lhs);
- exprt new_rhs = if_exprt(if_expr.cond(), rhs, if_expr.true_case());
- assign_rec(if_expr.true_case(), new_rhs, and_exprt(guard, if_expr.cond()), loc);
+ if (if_expr.false_case().id() == ID_if)
+ {
+ exprt new_rhs = if_exprt(if_expr.cond(), rhs, if_expr.true_case());
+ assign_rec(if_expr.true_case(), new_rhs, and_exprt(guard, if_expr.cond()), loc);
+ }
+ else
+ assign_rec(if_expr.true_case(), rhs, and_exprt(guard, if_expr.cond()), loc);
assign_rec(
if_expr.false_case(),
@@ -1579,15 +1608,16 @@ std::list &operator<<(
dest.push_back(*c_it);
}
- for (auto &obj : src.unknown_objs)
+ }
+
+ for (auto &obj : src.unknown_objs)
+ {
+ const typet &obj_type = src.ns.follow(obj.type());
+ if (obj_type.id() == ID_struct)
{
- const typet &obj_type = src.ns.follow(obj.type());
- if (obj_type.id() == ID_struct)
+ for (auto &component : to_struct_type(obj_type).components())
{
- for (auto &component : to_struct_type(obj_type).components())
- {
- dest.push_back(src.unknown_obj_eq(obj, component));
- }
+ dest.push_back(src.unknown_obj_eq(obj, component));
}
}
}
diff --git a/src/ssa/ssa_dereference.cpp b/src/ssa/ssa_dereference.cpp
index f6be56299..08c33e166 100644
--- a/src/ssa/ssa_dereference.cpp
+++ b/src/ssa/ssa_dereference.cpp
@@ -358,7 +358,7 @@ exprt dereference_rec(
if (values.empty()) {
// We use the identifier of pointed object
irep_idt identifier = id2string(to_symbol_expr(pointer).get_identifier())+"'obj";
- result=symbol_exprt(identifier, src.type());
+ result = symbol_exprt(identifier, ns.follow(pointed_type));
}
return result;
diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp
index 55f3e185f..cf5e047c9 100644
--- a/src/ssa/ssa_object.cpp
+++ b/src/ssa/ssa_object.cpp
@@ -229,7 +229,9 @@ void ssa_objectst::add_ptr_objects(
exprt root_object=o_it->get_root_object();
if(root_object.id()==ID_symbol)
{
- if(o_it->type().id()==ID_pointer)
+ const symbolt &symbol = ns.lookup(root_object);
+ if(o_it->type().id()==ID_pointer &&
+ (symbol.is_parameter || !symbol.is_procedure_local()))
{
tmp.insert(*o_it);
}
@@ -240,11 +242,16 @@ void ssa_objectst::add_ptr_objects(
o_it!=tmp.end();
o_it++)
{
- typet type=o_it->type().subtype();
- irep_idt identifier=id2string(o_it->get_identifier())+"'obj";
- symbol_exprt ptr_object(identifier, type);
- ptr_object.set(ID_ptr_object, o_it->get_identifier());
- collect_objects_rec(ptr_object, ns, objects, literals);
+ typet type = o_it->type();
+ irep_idt identifier = o_it->get_identifier();
+ do
+ {
+ type = type.subtype();
+ identifier = id2string(identifier) + "'obj";
+ symbol_exprt ptr_object(identifier, type);
+ ptr_object.set(ID_ptr_object, o_it->get_identifier());
+ collect_objects_rec(ptr_object, ns, objects, literals);
+ } while (ns.follow(type).id() == ID_pointer);
}
}
diff --git a/src/ssa/ssa_value_set.cpp b/src/ssa/ssa_value_set.cpp
index aa362160e..e9b73940c 100644
--- a/src/ssa/ssa_value_set.cpp
+++ b/src/ssa/ssa_value_set.cpp
@@ -294,6 +294,19 @@ void ssa_value_domaint::assign_rhs_rec(
tmp_values.alignment=merge_alignment(tmp_values.alignment, alignment);
dest.merge(tmp_values);
}
+ else if(ssa_object.type().id()==ID_pointer &&
+ id2string(ssa_object.get_identifier())
+ .find("#return_value")!=std::string::npos &&
+ id2string(ssa_object.get_identifier())!="malloc#return_value")
+ {
+ // Pointer typed return value of some function points to some dynamic object
+ const typet &pointed_type=ns.follow(ssa_object.type().subtype());
+ const symbol_exprt &pointed_obj=symbol_exprt(
+ id2string(ssa_object.get_identifier())+"'obj", pointed_type);
+ dest.value_set.insert(ssa_objectt(pointed_obj, ns));
+ if(offset)
+ dest.offset=true;
+ }
}
else
{
From 6d861c17487db254acabf8db840baa10e7e58954 Mon Sep 17 00:00:00 2001
From: Peter Schrammel
Date: Sat, 4 Nov 2017 22:51:15 +0000
Subject: [PATCH 027/322] Fixes to heap domain
---
src/domains/heap_domain.h | 22 +++----
src/solver/summary.h | 5 +-
src/ssa/ssa_inliner.cpp | 135 +++++++++++++++++++++++++++++++++-----
src/ssa/ssa_inliner.h | 14 +++-
4 files changed, 144 insertions(+), 32 deletions(-)
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 8f75a37dd..748805c66 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -3,25 +3,26 @@
*
* Viktor Malik, 12.8.2016 (c).
*/
-#ifndef CPROVER_HEAP_DOMAIN_H
-#define CPROVER_HEAP_DOMAIN_H
+#ifndef CPROVER_2LS_DOMAINS_HEAP_DOMAIN_H
+#define CPROVER_2LS_DOMAINS_HEAP_DOMAIN_H
-#include
#include "domain.h"
-class heap_domaint : public domaint
+class heap_domaint:public domaint
{
public:
typedef unsigned rowt;
typedef vart member_fieldt;
typedef std::pair dyn_objt;
- heap_domaint(unsigned int _domain_number, replace_mapt &_renaming_map,
- const var_specst &var_specs,
- const namespacet &ns_)
- : domaint(_domain_number, _renaming_map), ns(ns_)
+ heap_domaint(
+ unsigned int _domain_number,
+ replace_mapt &_renaming_map,
+ const var_specst &var_specs,
+ const namespacet &ns_):
+ domaint(_domain_number, _renaming_map, ns_)
{
- make_template(var_specs, ns);
+ make_template(var_specs, ns_);
}
/**
@@ -195,7 +196,6 @@ class heap_domaint : public domaint
protected:
templatet templ;
- namespacet ns;
void make_template(const var_specst &var_specs, const namespacet &ns);
@@ -208,4 +208,4 @@ class heap_domaint : public domaint
};
-#endif //CPROVER_HEAP_DOMAIN_H
+#endif // CPROVER_2LS_DOMAINS_HEAP_DOMAIN_H
diff --git a/src/solver/summary.h b/src/solver/summary.h
index 840a42230..0141d4bd4 100644
--- a/src/solver/summary.h
+++ b/src/solver/summary.h
@@ -13,6 +13,7 @@ Author: Daniel Kroening, kroening@kroening.com
#include
#include
+#include
typedef enum {YES, NO, UNKNOWN} threevalt;
@@ -38,7 +39,7 @@ class summaryt
var_listt params;
var_sett globals_in, globals_out;
-
+ ssa_value_domaint value_domain;
predicatet fw_precondition; // accumulated calling contexts (over-approx)
// predicatet fw_postcondition; // we are not projecting that out currently
predicatet fw_transformer; // forward summary (over-approx)
@@ -58,6 +59,8 @@ class summaryt
void join(const summaryt &new_summary);
+ void set_value_domain(const local_SSAt &SSA);
+
protected:
void combine_or(exprt &olde, const exprt &newe);
void combine_and(exprt &olde, const exprt &newe);
diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp
index 18a34b042..3a72fbfa4 100644
--- a/src/ssa/ssa_inliner.cpp
+++ b/src/ssa/ssa_inliner.cpp
@@ -96,17 +96,11 @@ void ssa_inlinert::get_summary(
// equalities for globals out (including unmodified globals)
if(forward)
- bindings.push_back(
- get_replace_globals_out(
- summary.globals_out,
- cs_globals_in,
- cs_globals_out));
+ bindings.push_back(get_replace_globals_out(
+ cs_globals_in, cs_globals_out, summary, SSA.ns));
else
- bindings.push_back(
- get_replace_globals_out(
- summary.globals_in,
- cs_globals_out,
- cs_globals_in));
+ bindings.push_back(get_replace_globals_out(
+ cs_globals_out, cs_globals_in, summary, SSA.ns));
}
/*******************************************************************\
@@ -614,22 +608,76 @@ Function: ssa_inlinert::get_replace_globals_out
\*******************************************************************/
exprt ssa_inlinert::get_replace_globals_out(
- const local_SSAt::var_sett &globals_out,
const local_SSAt::var_sett &cs_globals_in,
- const local_SSAt::var_sett &cs_globals_out)
+ const local_SSAt::var_sett &cs_globals_out,
+ const summaryt &summary,
+ const namespacet &ns)
{
// equalities for globals_out
exprt::operandst c;
for(summaryt::var_sett::const_iterator it=cs_globals_out.begin();
it!=cs_globals_out.end(); it++)
{
- symbol_exprt rhs=*it; // copy
symbol_exprt lhs;
- if(find_corresponding_symbol(*it, globals_out, lhs))
- rename(lhs);
+ exprt rhs;
+
+ if(id2string(it->get_identifier()).find("'obj")!=std::string::npos &&
+ it->get_identifier()!=get_original_identifier(*it))
+ {
+ // variable is heap object (contains 'obj) and is assigned by the call
+ const irep_idt &id=get_original_identifier(*it);
+ if(is_struct_member(id))
+ {
+ // variable is member of dynamic struct
+ const std::string member=id2string(id).substr(id2string(id).find_last_of("."));
+ const irep_idt &root_id=id2string(id).substr(0, id2string(id).find_last_of("."));
+ // find root object (must be in global variables)
+ symbol_exprt root_object;
+ for(auto &global : cs_globals_out)
+ {
+ if(get_original_identifier(global)==root_id)
+ root_object=global;
+ }
+
+ // find corresponding dynamic object in called function
+ symbol_exprt dynamic_object;
+ assert(find_corresponding_dyn_obj(root_object, summary, ns, dynamic_object));
+
+ // restore member expression
+ dynamic_object.set_identifier(id2string(dynamic_object.get_identifier()) + member);
+ dynamic_object.type()=it->type();
+
+ assert(find_corresponding_symbol(dynamic_object, summary.globals_out, lhs));
+ rename(lhs);
+
+ rhs=*it; // copy
+ }
+ else
+ { // variable is dynamic object
+ // find corresponding dynamic object in called function
+ symbol_exprt dynamic_object;
+ assert(find_corresponding_dyn_obj(*it, summary, ns, dynamic_object));
+
+ // equality is between addresses of corresponding dynamic objects
+ exprt addr=address_of_exprt(dynamic_object);
+ rename(addr);
+ assert(addr.id()==ID_symbol);
+
+ lhs=to_symbol_expr(addr);
+
+ symbol_exprt orig_obj(id, dynamic_object.type());
+ rhs=address_of_exprt(orig_obj);
+ }
+ }
else
- assert(find_corresponding_symbol(*it, cs_globals_in, lhs));
- c.push_back(equal_exprt(lhs, rhs));
+ {
+ rhs=*it; // copy
+ if (find_corresponding_symbol(*it, summary.globals_out, lhs))
+ rename(lhs);
+ else
+ assert(find_corresponding_symbol(*it, cs_globals_in, lhs));
+ }
+ c.push_back(equal_exprt(lhs,rhs));
}
return conjunction (c);
}
@@ -705,6 +753,17 @@ void ssa_inlinert::rename(exprt &expr)
irep_idt id=id2string(sexpr.get_identifier())+"@"+i2string(counter);
sexpr.set_identifier(id);
}
+ else if (expr.id() == ID_address_of)
+ {
+ irep_idt id;
+ const exprt &obj = to_address_of_expr(expr).object();
+ if (obj.id() == ID_symbol)
+ {
+ id = id2string(to_symbol_expr(obj).get_identifier()) + "'addr" + "@" + i2string(counter);
+ }
+ symbol_exprt addr_symbol(id, expr.type());
+ expr = addr_symbol;
+ }
Forall_operands(op, expr)
rename(*op);
}
@@ -965,6 +1024,7 @@ irep_idt ssa_inlinert::get_original_identifier(const symbol_exprt &s)
{
if(!(c=='#' || c=='@' || c=='%' || c=='!' || c=='$') &&
!(c=='p' || c=='h' || c=='i') &&
+ !(c=='l' || c=='b') &&
!('0'<=c && c<='9'))
pos=std::string::npos;
}
@@ -974,3 +1034,44 @@ irep_idt ssa_inlinert::get_original_identifier(const symbol_exprt &s)
return id;
}
+/**
+ * Test if variable is member of struct.
+ * @param identifier Id of variable
+ * @return
+ */
+bool ssa_inlinert::is_struct_member(const irep_idt &identifier)
+{
+ const std::string id = id2string(identifier);
+ return id.find(".") != std::string::npos &&
+ id.find_first_of("#$@'%!", id.find_last_of(".")) == std::string::npos;
+}
+
+/**
+ * Find corresponding dynamic object in called function.
+ * Takes pointer to s (by stripping away 'obj suffix) and querys called function value set (stored
+ * in summary of that function).
+ * @param s Call site dynamic object
+ * @param summary Called function summary
+ * @param ns Namespace
+ * @param found Found symbol
+ * @return True if an object was found, otherwise false.
+ */
+bool ssa_inlinert::find_corresponding_dyn_obj(const symbol_exprt &s,
+ const summaryt &summary,
+ const namespacet &ns,
+ symbol_exprt &found)
+{
+ irep_idt id = get_original_identifier(s);
+ const std::string &id_str = id2string(s.get_identifier());
+ id = id_str.substr(0, id_str.rfind("'obj"));
+
+ auto &values = summary.value_domain(symbol_exprt(id, pointer_typet(s.type())), ns);
+ if (values.value_set.size() == 1)
+ {
+ found = values.value_set.begin()->symbol_expr();
+ return true;
+ }
+
+ return false;
+}
+
diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h
index d36ee5960..dea9c7f9b 100644
--- a/src/ssa/ssa_inliner.h
+++ b/src/ssa/ssa_inliner.h
@@ -103,8 +103,15 @@ class ssa_inlinert:public messaget
const local_SSAt::var_sett &globals,
symbol_exprt &s_found);
+ static bool find_corresponding_dyn_obj(const symbol_exprt &s,
+ const summaryt &summary,
+ const namespacet &ns,
+ symbol_exprt &found);
+
static irep_idt get_original_identifier(const symbol_exprt &s);
+ static bool is_struct_member(const irep_idt &identifier);
+
protected:
unsigned counter;
summary_dbt &summary_db;
@@ -135,9 +142,10 @@ class ssa_inlinert:public messaget
const local_SSAt &SSA,
const local_SSAt::locationt &loc);
exprt get_replace_globals_out(
- const local_SSAt::var_sett &globals_out,
- const local_SSAt::var_sett &cs_globals_in,
- const local_SSAt::var_sett &cs_globals_out);
+ const local_SSAt::var_sett &cs_globals_in,
+ const local_SSAt::var_sett &cs_globals_out,
+ const summaryt &summary,
+ const namespacet &ns);
void rename(exprt &expr);
void rename(local_SSAt::nodet &node);
From 221a0fc5d358e9648ac2debbdf4ef6789c2588e4 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 13 Oct 2016 14:41:09 +0100
Subject: [PATCH 028/322] Heap domain: create summaries (transformers) for
functions. Does not work for passing heap objects by pointer parameters
between functions.
---
src/domains/heap_domain.cpp | 21 +++++++++++---
src/domains/heap_domain.h | 5 ++--
src/domains/strategy_solver_heap.cpp | 38 +++++++++++++++++++------
src/domains/template_generator_base.cpp | 12 ++++++--
src/ssa/address_canonizer.cpp | 30 +++++++++++--------
5 files changed, 76 insertions(+), 30 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 9fca9faf5..1e5425822 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -40,6 +40,8 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
for (auto v1 = var_specs.begin(); v1 != var_specs.end(); ++v1)
{
+ if (v1->kind == IN) continue;
+
// Create template for each pointer to struct
const vart &var1 = v1->var;
if (var1.type().id() == ID_pointer)
@@ -49,7 +51,12 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
{
// Check if var1 is member field of dynamic object
const std::string identifier = id2string(to_symbol_expr(v1->var).get_identifier());
- bool dynamic = identifier.find("dynamic_object$") != std::string::npos;
+ bool dynamic = false;
+ for (auto &component : to_struct_type(pointed_type).components())
+ {
+ if (identifier.find("." + id2string(component.get_name())) != std::string::npos)
+ dynamic = true;
+ }
for (auto &component : to_struct_type(pointed_type).components())
{
@@ -175,18 +182,24 @@ bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt
{
// Path does not exist yet
std::set dyn_obj_set;
+ bool zero_path = true;
if (dyn_obj.first.id() != ID_nil)
{ // Path doesn't have zero length
dyn_obj_set.insert(dyn_obj);
+ zero_path = false;
}
- path_set.emplace(dest, dyn_obj_set);
+ path_set.emplace(dest, dyn_obj_set, zero_path);
return true;
}
else
{
// Path exists already
- if (dyn_obj.first.id() == ID_nil) return false;
-
+ if (dyn_obj.first.id() == ID_nil)
+ {
+ bool result = path_set.find(dest)->zero_length;
+ path_set.find(dest)->zero_length = true;
+ return !result;
+ }
// Try to insert new dynamic object belonging to the path
return path_set.find(dest)->dyn_objects.insert(dyn_obj).second;
}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 748805c66..efe023b86 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -41,11 +41,12 @@ class heap_domaint:public domaint
{
exprt destination;
mutable std::set dyn_objects;
+ mutable bool zero_length;
patht(const exprt &dest_) : destination(dest_) {}
- patht(const exprt &dest_, const std::set &dyn_objs_)
- : destination(dest_), dyn_objects(dyn_objs_) {}
+ patht(const exprt &dest_, const std::set &dyn_objs_, const bool zero_l_)
+ : destination(dest_), dyn_objects(dyn_objs_), zero_length(zero_l_) {}
bool operator<(const patht &rhs) const
{
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index 68ee5ace2..b6ad92e6a 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -5,6 +5,7 @@
//#define DEBUG_OUTPUT
#include "strategy_solver_heap.h"
+#include "../ssa/address_canonizer.h"
bool strategy_solver_heapt::iterate(invariantt &_inv)
{
@@ -66,14 +67,14 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
}
for (unsigned i = 0; i < heap_domain.templ.size(); i++)
{
- exprt c = heap_domain.get_row_pre_constraint(i, inv[i]).op1();
+ exprt c = heap_domain.get_row_pre_constraint(i, inv[i]);
debug() << "cond: " << from_expr(ns, "", c) << " " <<
from_expr(ns, "", solver.get(c)) << eom;
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].pre_guard) <<
" " << from_expr(ns, "", solver.get(heap_domain.templ[i].pre_guard)) << eom;
debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].post_guard) << " "
<< from_expr(ns, "", solver.get(heap_domain.templ[i].post_guard)) << eom;
- exprt post = heap_domain.get_row_post_constraint(i, inv[i]).op1();
+ exprt post = heap_domain.get_row_post_constraint(i, inv[i]);
debug() << "post-cond: " << from_expr(ns, "", post) << " "
<< from_expr(ns, "", solver.get(post)) << eom;
}
@@ -95,11 +96,14 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (heap_domain.is_null_ptr(ptr_value))
{
exprt null_expr = null_pointer_exprt(to_pointer_type(ptr_value.type()));
+
+ // Add path to NULL
if (heap_domain.add_row_path(row, inv, null_expr,
std::make_pair(nil_exprt(), nil_exprt())))
improved = true;
debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
+ // Add points to information
if (heap_domain.add_points_to(row, inv, std::make_pair(null_expr, nil_exprt())))
improved = true;
debug() << "add points to: " << from_expr(ns, "", ptr_value) << eom;
@@ -109,13 +113,18 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
// pointer points to the heap (p = &obj)
debug() << from_expr(ns, "", ptr_value) << eom;
assert(ptr_value.id() == ID_address_of);
- assert(to_address_of_expr(ptr_value).object().id() == ID_symbol);
- symbol_exprt obj = to_symbol_expr(to_address_of_expr(ptr_value).object());
+ // Canonize address
+ const exprt address = address_canonizer(ptr_value, ns);
+ assert(to_address_of_expr(address).object().id() == ID_symbol);
+
+ symbol_exprt obj = to_symbol_expr(to_address_of_expr(address).object());
if (obj.type().get_bool("#dynamic"))
{
+ // obj is dynamic object accessed inside the function
+
if (id2string(obj.get_identifier()).find("$unknown") != std::string::npos)
- {
+ { // handle unknown object
if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
improved = true;
debug() << "add points to: " << from_expr(ns, "", obj) << eom;
@@ -127,7 +136,8 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
heap_domain.get_base_name(obj) ==
heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
- {
+ { // for the same object find previous instance
+ // (used for multiple loops in one function)
member_val_index = find_member_row(obj, heap_domain.templ[row].member,
--actual_loc);
if (member_val_index < 0)
@@ -140,7 +150,6 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
}
assert(member_val_index >= 0);
exprt member_expr = heap_domain.templ[member_val_index].expr;
- exprt do_expr = heap_domain.templ[member_val_index].dyn_obj;
// Add all paths from obj.next to p
if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
@@ -149,9 +158,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
<< from_expr(ns, "", obj) << eom;
- assert(do_expr.id() != ID_nil);
// Add points to information
- assert(do_expr.id() == ID_symbol);
if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
improved = true;
debug() << "add points to: " << from_expr(ns, "", obj) << eom;
@@ -159,6 +166,19 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
}
}
+ else
+ {
+ // Add points to information
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+
+ // Add path to &(obj)
+ if (heap_domain.add_row_path(row, inv, address_of_exprt(obj),
+ std::make_pair(nil_exprt(), nil_exprt())))
+ improved = true;
+ debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
+ }
}
if (heap_domain.templ[row].dynamic)
diff --git a/src/domains/template_generator_base.cpp b/src/domains/template_generator_base.cpp
index 8815d658a..7aa2e1ed9 100644
--- a/src/domains/template_generator_base.cpp
+++ b/src/domains/template_generator_base.cpp
@@ -17,6 +17,7 @@ Author: Peter Schrammel
#include "tpolyhedra_domain.h"
#include "predabs_domain.h"
#include "heap_domain.h"
+#include
#ifdef DEBUG
#include
@@ -268,10 +269,15 @@ void template_generator_baset::filter_heap_domain()
{
domaint::var_specst new_var_specs(var_specs);
var_specs.clear();
- for (auto var=new_var_specs.begin(); var!=new_var_specs.end(); ++var)
+ for(auto var=new_var_specs.begin(); var!=new_var_specs.end(); ++var)
{
- if (var->var.type().id()==ID_pointer || var->var.type().get_bool("#dynamic"))
- var_specs.push_back(*var);
+ if(var->var.id()==ID_symbol && var->var.type().id()==ID_pointer)
+ {
+ // Filter out non-assigned variables
+ if(ssa_inlinert::get_original_identifier(to_symbol_expr(var->var)) !=
+ to_symbol_expr(var->var).get_identifier())
+ var_specs.push_back(*var);
+ }
}
}
diff --git a/src/ssa/address_canonizer.cpp b/src/ssa/address_canonizer.cpp
index 2ffab3ff1..f6e6b9cb2 100644
--- a/src/ssa/address_canonizer.cpp
+++ b/src/ssa/address_canonizer.cpp
@@ -47,18 +47,24 @@ exprt address_canonizer(
// get offset
exprt offset=member_offset_expr(to_member_expr(object), ns);
- // &x.m ---> (&x)+offset
-
- address_of_exprt address_of_expr(to_member_expr(object).struct_op());
- exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call
-
- pointer_typet byte_pointer(unsigned_char_type());
- typecast_exprt typecast_expr(rec_result, byte_pointer);
- plus_exprt sum(typecast_expr, offset);
- if(sum.type()!=address.type())
- sum.make_typecast(address.type());
-
- return sum;
+ if (offset.id()==ID_constant && to_constant_expr(offset).is_zero())
+ {
+ return address_of_exprt(to_member_expr(object).struct_op());
+ }
+ else
+ {
+ // &x.m ---> (&x)+offset
+
+ address_of_exprt address_of_expr(to_member_expr(object).struct_op());
+ exprt rec_result=address_canonizer(address_of_expr, ns); // rec. call
+
+ pointer_typet byte_pointer(unsigned_char_type());
+ typecast_exprt typecast_expr(rec_result, byte_pointer);
+ plus_exprt sum(typecast_expr, offset);
+ if (sum.type()!=address.type()) sum.make_typecast(address.type());
+
+ return sum;
+ }
}
else if(object.id()==ID_index)
{
From 22d6decae5332982a7a90be097231d927b6a378d Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 13 Oct 2016 18:33:18 +0100
Subject: [PATCH 029/322] Better collection of pointed objects. Only objects
pointed by parameters and any called function returns, or arguments are
collected.
---
src/ssa/local_ssa.cpp | 17 +++-------
src/ssa/ssa_object.cpp | 76 +++++++++++++++++++++++++++++++++++-------
src/ssa/ssa_object.h | 4 +--
3 files changed, 71 insertions(+), 26 deletions(-)
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index dbf9bb8d0..eb9d17aa7 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -175,18 +175,11 @@ void local_SSAt::get_globals(
if(is_ptr_object(root_obj))
{
const symbolt *symbol;
- if(ns.lookup(root_obj.get(ID_ptr_object), symbol)) continue;
- if(!symbol->is_parameter)
- {
- if(!with_returns ||
- id2string(it->get_identifier()).find("'obj")==std::string::npos)
- continue;
- const ssa_domaint &ssa_domain=ssa_analysis[loc];
- // Filter out non-assigned symbols
- const auto &def=ssa_domain.def_map.find(it->get_identifier());
- if(def->second.def.is_input())
- continue;
- }
+ irep_idt ptr_obj_id=root_obj.get(ID_ptr_object);
+ if(ns.lookup(ptr_obj_id, symbol))
+ continue;
+ if(!symbol->is_parameter && !with_returns)
+ continue;
}
if(rhs_value)
diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp
index cf5e047c9..0996c9b3c 100644
--- a/src/ssa/ssa_object.cpp
+++ b/src/ssa/ssa_object.cpp
@@ -37,15 +37,9 @@ bool is_ptr_object(const exprt &src)
src.get(ID_ptr_object)!=irep_idt();
}
-void collect_objects_rec(
- const exprt &src,
- const namespacet &ns,
- std::set &objects,
- std::set &literals);
-
/*******************************************************************\
-Function: collect_objects_address_of_rec
+Function: collect_objects_rec
Inputs:
@@ -55,6 +49,44 @@ Function: collect_objects_address_of_rec
\*******************************************************************/
+void collect_objects_rec(
+ const exprt &src,
+ const namespacet &ns,
+ std::set &objects,
+ std::set &literals);
+
+void collect_ptr_objects(
+ const exprt &expr,
+ const namespacet &ns,
+ std::set &objects,
+ std::set &literals)
+{
+ if(expr.id()==ID_symbol)
+ {
+ const symbol_exprt &src=to_symbol_expr(expr);
+ const typet &type=ns.follow(src.type());
+ if(type.id()==ID_pointer)
+ {
+ const irep_idt &identifier=id2string(src.get_identifier()) + "'obj";
+ const typet &pointed_type=src.type().subtype();
+ symbol_exprt ptr_object(identifier, pointed_type);
+
+ if(is_ptr_object(src))
+ ptr_object.set(ID_ptr_object, src.get(ID_ptr_object));
+ else
+ ptr_object.set(ID_ptr_object, src.get_identifier());
+
+ collect_objects_rec(ptr_object, ns, objects, literals);
+ collect_ptr_objects(ptr_object, ns, objects, literals);
+ }
+ }
+ else
+ {
+ forall_operands(it, expr)
+ collect_ptr_objects(*it, ns, objects, literals);
+ }
+}
+
void collect_objects_address_of_rec(
const exprt &src,
const namespacet &ns,
@@ -120,6 +152,15 @@ void collect_objects_rec(
{
forall_operands(it, src)
collect_objects_rec(*it, ns, objects, literals);
+
+ const codet &code=to_code(src);
+ if (code.get_statement()==ID_function_call)
+ {
+ const code_function_callt &function_call=to_code_function_call(code);
+ for (auto &arg : function_call.arguments())
+ collect_ptr_objects(arg, ns, objects, literals);
+ }
+
return;
}
else if(src.id()==ID_address_of)
@@ -141,6 +182,10 @@ void collect_objects_rec(
{
if(type.id()==ID_struct)
{
+ std::string id=id2string(ssa_object.get_identifier());
+ if (src.type().get_bool("#dynamic") || id.find("'obj")==id.size()-4)
+ objects.insert(ssa_object);
+
// need to split up
const struct_typet &struct_type=to_struct_type(type);
@@ -162,6 +207,14 @@ void collect_objects_rec(
#endif
objects.insert(ssa_object);
+
+ const exprt &root_object=ssa_object.get_root_object();
+ const symbolt *symbol;
+ if(ssa_object.type().get_bool("#dynamic") ||
+ (root_object.id()==ID_symbol &&
+ !ns.lookup(to_symbol_expr(root_object).get_identifier(), symbol) &&
+ (symbol->is_parameter || !symbol->is_procedure_local())))
+ collect_ptr_objects(ssa_object.symbol_expr(), ns, objects, literals);
}
}
else
@@ -195,6 +248,7 @@ void ssa_objectst::collect_objects(
{
symbol_exprt symbol=ns.lookup(*it).symbol_expr();
collect_objects_rec(symbol, ns, objects, literals);
+ collect_ptr_objects(symbol, ns, objects, literals);
}
// Rummage through body.
@@ -218,6 +272,7 @@ Function: ssa_objectst::add_ptr_objects
\*******************************************************************/
void ssa_objectst::add_ptr_objects(
+ const goto_functionst::goto_functiont &goto_function,
const namespacet &ns)
{
objectst tmp;
@@ -230,8 +285,9 @@ void ssa_objectst::add_ptr_objects(
if(root_object.id()==ID_symbol)
{
const symbolt &symbol = ns.lookup(root_object);
+ dirtyt dirty(goto_function);
if(o_it->type().id()==ID_pointer &&
- (symbol.is_parameter || !symbol.is_procedure_local()))
+ (symbol.is_parameter || !symbol.is_procedure_local() || dirty(symbol.name)))
{
tmp.insert(*o_it);
}
@@ -385,10 +441,6 @@ ssa_objectt::identifiert ssa_objectt::object_id_rec(
{
return identifiert();
}
- else if(src.id()==ID_ptr_object)
- {
- return identifiert(id2string(src.get(ID_identifier))+"'obj");
- }
else
return identifiert();
}
diff --git a/src/ssa/ssa_object.h b/src/ssa/ssa_object.h
index 1cb21ec1d..5a16bcd6b 100644
--- a/src/ssa/ssa_object.h
+++ b/src/ssa/ssa_object.h
@@ -114,7 +114,6 @@ class ssa_objectst
const namespacet &ns)
{
collect_objects(goto_function, ns);
- add_ptr_objects(ns);
categorize_objects(goto_function, ns);
}
@@ -128,7 +127,8 @@ class ssa_objectst
const namespacet &);
void add_ptr_objects(
- const namespacet &);
+ const goto_functionst::goto_functiont &,
+ const namespacet &);
};
bool is_ptr_object(const exprt &);
From 7468625ff11977cf27e844fe09c4717daf87ba2c Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Tue, 18 Oct 2016 11:15:28 +0100
Subject: [PATCH 030/322] Assignments and value domain for objects pointed by
function call arguments.
---
src/ssa/assignments.cpp | 32 ++++++++++++++++++++---
src/ssa/ssa_value_set.cpp | 54 +++++++++++++++++++++++++++++----------
2 files changed, 69 insertions(+), 17 deletions(-)
diff --git a/src/ssa/assignments.cpp b/src/ssa/assignments.cpp
index 7c4d99e46..4b5703444 100644
--- a/src/ssa/assignments.cpp
+++ b/src/ssa/assignments.cpp
@@ -62,10 +62,34 @@ void assignmentst::build_assignment_map(
o_it=ssa_objects.globals.begin();
o_it!=ssa_objects.globals.end(); o_it++)
{
- const exprt &function = code_function_call.function();
- if (function.id() == ID_symbol &&
- id2string(o_it->get_identifier()).find(
- id2string(to_symbol_expr(function).get_identifier())) != std::string::npos)
+ bool assigned = false;
+ const exprt &root_obj = o_it->get_root_object();
+ if (is_ptr_object(root_obj))
+ { // assign objects pointed by arguments and return value of the function
+ const exprt &function = code_function_call.function();
+ if (function.id() == ID_symbol &&
+ id2string(o_it->get_identifier()).find(
+ id2string(to_symbol_expr(function).get_identifier())) !=
+ std::string::npos)
+ assigned = true;
+
+ for (auto &arg : code_function_call.arguments())
+ {
+ exprt arg_symbol = arg;
+ if (arg.id() == ID_address_of)
+ arg_symbol = to_address_of_expr(arg_symbol).object();
+ if (arg_symbol.id() == ID_symbol && id2string(o_it->get_identifier()).find(
+ id2string(to_symbol_expr(arg_symbol).get_identifier())) != std::string::npos)
+ assigned = true;
+ }
+ }
+ else
+ { // assign return value of the function
+ if (id2string(o_it->get_identifier()).find("#return_value") == std::string::npos)
+ assigned = true;
+ }
+
+ if (assigned)
assign(*o_it, it, ns);
}
diff --git a/src/ssa/ssa_value_set.cpp b/src/ssa/ssa_value_set.cpp
index e9b73940c..c57ea8023 100644
--- a/src/ssa/ssa_value_set.cpp
+++ b/src/ssa/ssa_value_set.cpp
@@ -74,6 +74,30 @@ void ssa_value_domaint::transform(
assign(*o_it, it, ns);
#endif
+ for (auto &argument : code_function_call.arguments())
+ {
+ exprt arg = argument;
+ while (arg.type().id() == ID_pointer)
+ {
+ if (arg.id() == ID_symbol)
+ {
+ const typet &pointed_type = ns.follow(arg.type().subtype());
+ symbol_exprt pointed_obj = symbol_exprt(
+ id2string(to_symbol_expr(arg).get_identifier()) + "'obj",
+ pointed_type);
+ pointed_obj.type().set("#dynamic", true);
+
+ assign_lhs_rec(arg, address_of_exprt(pointed_obj), ns);
+
+ arg = pointed_obj;
+ }
+ else if (arg.id() == ID_address_of)
+ {
+ arg = to_address_of_expr(arg).object();
+ }
+ }
+ }
+
// the call might come with an assignment
if(code_function_call.lhs().is_not_nil())
{
@@ -137,6 +161,23 @@ void ssa_value_domaint::assign_lhs_rec(
return; // done
}
+ // if rhs is a return value of pointer type, it points to a dynamic object
+ if(rhs.id()==ID_symbol &&
+ rhs.type().id()==ID_pointer &&
+ id2string(to_symbol_expr(rhs).get_identifier()).find("#return_value")!=
+ std::string::npos &&
+ id2string(to_symbol_expr(rhs).get_identifier())!="malloc#return_value")
+ {
+ // Pointer typed return value of some function points to some dynamic object
+ const typet &pointed_type=ns.follow(rhs.type().subtype());
+ symbol_exprt pointed_obj=symbol_exprt(
+ id2string(to_symbol_expr(rhs).get_identifier())+"'obj",
+ pointed_type);
+ pointed_obj.type().set("#dynamic", true);
+
+ assign_lhs_rec(rhs, address_of_exprt(pointed_obj), ns);
+ }
+
// object?
ssa_objectt ssa_object(lhs, ns);
@@ -294,19 +335,6 @@ void ssa_value_domaint::assign_rhs_rec(
tmp_values.alignment=merge_alignment(tmp_values.alignment, alignment);
dest.merge(tmp_values);
}
- else if(ssa_object.type().id()==ID_pointer &&
- id2string(ssa_object.get_identifier())
- .find("#return_value")!=std::string::npos &&
- id2string(ssa_object.get_identifier())!="malloc#return_value")
- {
- // Pointer typed return value of some function points to some dynamic object
- const typet &pointed_type=ns.follow(ssa_object.type().subtype());
- const symbol_exprt &pointed_obj=symbol_exprt(
- id2string(ssa_object.get_identifier())+"'obj", pointed_type);
- dest.value_set.insert(ssa_objectt(pointed_obj, ns));
- if(offset)
- dest.offset=true;
- }
}
else
{
From 0c1377cf915d2820f3e1d591359a13b2afce462a Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Tue, 18 Oct 2016 11:16:47 +0100
Subject: [PATCH 031/322] Bindings for objects pointed by arguments when
inlining called function summaries.
---
src/ssa/ssa_inliner.cpp | 102 +++++++++++++++++++++++++++++++++++-----
src/ssa/ssa_inliner.h | 12 +++--
2 files changed, 99 insertions(+), 15 deletions(-)
diff --git a/src/ssa/ssa_inliner.cpp b/src/ssa/ssa_inliner.cpp
index 3a72fbfa4..3c47ab741 100644
--- a/src/ssa/ssa_inliner.cpp
+++ b/src/ssa/ssa_inliner.cpp
@@ -97,10 +97,10 @@ void ssa_inlinert::get_summary(
// equalities for globals out (including unmodified globals)
if(forward)
bindings.push_back(get_replace_globals_out(
- cs_globals_in, cs_globals_out, summary, SSA.ns));
+ cs_globals_in, cs_globals_out, summary, *f_it, *n_it, SSA.ns));
else
bindings.push_back(get_replace_globals_out(
- cs_globals_out, cs_globals_in, summary, SSA.ns));
+ cs_globals_out, cs_globals_in, summary, *f_it, *n_it, SSA.ns));
}
/*******************************************************************\
@@ -532,8 +532,7 @@ exprt ssa_inlinert::get_replace_params(
}
ssa_objectt pointed_ssa_obj(arg_pointed, SSA.ns);
// get correct SSA symbol for function call entry
- pointed_ssa_sym_in = SSA.name(pointed_ssa_obj, local_SSAt::OUT,
- SSA.get_def_loc(to_symbol_expr(arg_pointed), loc));
+ pointed_ssa_sym_in = SSA.read_rhs(pointed_ssa_obj, loc);
// get correct SSA symbol for function call exit
pointed_ssa_sym_out = SSA.name(pointed_ssa_obj, local_SSAt::OUT, loc);
}
@@ -611,6 +610,8 @@ exprt ssa_inlinert::get_replace_globals_out(
const local_SSAt::var_sett &cs_globals_in,
const local_SSAt::var_sett &cs_globals_out,
const summaryt &summary,
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::nodet &ssa_node,
const namespacet &ns)
{
// equalities for globals_out
@@ -641,7 +642,14 @@ exprt ssa_inlinert::get_replace_globals_out(
// find corresponding dynamic object in called function
symbol_exprt dynamic_object;
- assert(find_corresponding_dyn_obj(root_object, summary, ns, dynamic_object));
+ if (!find_corresponding_dyn_obj(root_object, summary, funapp_expr, ssa_node, ns,
+ dynamic_object))
+ { // if corresponding dynamic object does not exist, the global is not changed
+ rhs = *it; // copy
+ assert(find_corresponding_symbol(*it, cs_globals_in, lhs));
+ c.push_back(equal_exprt(lhs, rhs));
+ continue;
+ }
// restore member expression
dynamic_object.set_identifier(id2string(dynamic_object.get_identifier()) + member);
@@ -656,7 +664,13 @@ exprt ssa_inlinert::get_replace_globals_out(
{ // variable is dynamic object
// find corresponding dynamic object in called function
symbol_exprt dynamic_object;
- assert(find_corresponding_dyn_obj(*it, summary, ns, dynamic_object));
+ if (!find_corresponding_dyn_obj(*it, summary, funapp_expr, ssa_node, ns, dynamic_object))
+ { // if corresponding dynamic object does not exist, the global is not changed
+ rhs = *it; // copy
+ assert(find_corresponding_symbol(*it, cs_globals_in, lhs));
+ c.push_back(equal_exprt(lhs, rhs));
+ continue;
+ }
// equality is between addresses of corresponding dynamic objects
exprt addr=address_of_exprt(dynamic_object);
@@ -665,7 +679,9 @@ exprt ssa_inlinert::get_replace_globals_out(
lhs=to_symbol_expr(addr);
- symbol_exprt orig_obj(id, dynamic_object.type());
+ typet orig_type = it->type();
+ orig_type.set("#dynamic", dynamic_object.type().get_bool("#dynamic"));
+ symbol_exprt orig_obj(id, orig_type);
rhs=address_of_exprt(orig_obj);
}
}
@@ -759,7 +775,13 @@ void ssa_inlinert::rename(exprt &expr)
const exprt &obj = to_address_of_expr(expr).object();
if (obj.id() == ID_symbol)
{
- id = id2string(to_symbol_expr(obj).get_identifier()) + "'addr" + "@" + i2string(counter);
+ const std::string &obj_id = id2string(to_symbol_expr(obj).get_identifier());
+ if (obj_id.compare(obj_id.length() - 4, 4, "'obj") == 0)
+ id = obj_id.substr(0, obj_id.find_last_of("'"));
+ else
+ id = id2string(obj_id) + "'addr";
+
+ id = id2string(id) + "@" + i2string(counter);
}
symbol_exprt addr_symbol(id, expr.type());
expr = addr_symbol;
@@ -1053,22 +1075,80 @@ bool ssa_inlinert::is_struct_member(const irep_idt &identifier)
* @param s Call site dynamic object
* @param summary Called function summary
* @param ns Namespace
- * @param found Found symbol
+ * @param found_sym Found symbol
* @return True if an object was found, otherwise false.
*/
bool ssa_inlinert::find_corresponding_dyn_obj(const symbol_exprt &s,
const summaryt &summary,
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::nodet &ssa_node,
const namespacet &ns,
- symbol_exprt &found)
+ symbol_exprt &found_sym)
{
irep_idt id = get_original_identifier(s);
const std::string &id_str = id2string(s.get_identifier());
id = id_str.substr(0, id_str.rfind("'obj"));
+ if (id2string(id).find("#return_value") == std::string::npos)
+ {
+ auto p_it = summary.params.begin();
+ bool found = false;
+ for (auto arg_it = funapp_expr.arguments().begin(); arg_it != funapp_expr.arguments().end();
+ ++arg_it, ++p_it)
+ {
+ exprt arg = nil_exprt();
+ for (auto &eq : ssa_node.equalities)
+ {
+ if (eq.rhs() == *arg_it)
+ arg = eq.lhs();
+ }
+ assert(arg.is_not_nil());
+
+ symbol_exprt param = *p_it;
+ while (arg.type().id() == ID_pointer)
+ {
+ if (arg.id() == ID_symbol)
+ {
+ if (to_symbol_expr(arg).get_identifier() == id)
+ {
+ found = true;
+ break;
+ }
+ else
+ {
+ // arg --> arg'obj
+ symbol_exprt &arg_sym = to_symbol_expr(arg);
+ arg_sym.set_identifier(id2string(arg_sym.get_identifier()) + "'obj");
+ arg_sym.type() = arg_sym.type().subtype();
+
+ // param --> param'obj
+ assert(param.type().id() == ID_pointer);
+ param.set_identifier(id2string(param.get_identifier()) + "'obj");
+ param.type() = param.type().subtype();
+
+ }
+ }
+ else if (arg.id() == ID_address_of)
+ {
+ // &arg --> arg
+ arg = to_address_of_expr(arg).object();
+
+ // param --> param'obj
+ assert(param.type().id() == ID_pointer);
+ param.set_identifier(id2string(param.get_identifier()) + "'obj");
+ param.type() = param.type().subtype();
+ }
+ }
+ if (found)
+ id = param.get_identifier();
+ }
+ assert(found);
+ }
+
auto &values = summary.value_domain(symbol_exprt(id, pointer_typet(s.type())), ns);
if (values.value_set.size() == 1)
{
- found = values.value_set.begin()->symbol_expr();
+ found_sym = values.value_set.begin()->symbol_expr();
return true;
}
diff --git a/src/ssa/ssa_inliner.h b/src/ssa/ssa_inliner.h
index dea9c7f9b..9a2a9d4f9 100644
--- a/src/ssa/ssa_inliner.h
+++ b/src/ssa/ssa_inliner.h
@@ -103,10 +103,12 @@ class ssa_inlinert:public messaget
const local_SSAt::var_sett &globals,
symbol_exprt &s_found);
- static bool find_corresponding_dyn_obj(const symbol_exprt &s,
- const summaryt &summary,
- const namespacet &ns,
- symbol_exprt &found);
+ static bool find_corresponding_dyn_obj(const symbol_exprt &s,
+ const summaryt &summary,
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::nodet &ssa_node,
+ const namespacet &ns,
+ symbol_exprt &found_sym);
static irep_idt get_original_identifier(const symbol_exprt &s);
@@ -145,6 +147,8 @@ class ssa_inlinert:public messaget
const local_SSAt::var_sett &cs_globals_in,
const local_SSAt::var_sett &cs_globals_out,
const summaryt &summary,
+ const function_application_exprt &funapp_expr,
+ const local_SSAt::nodet &ssa_node,
const namespacet &ns);
void rename(exprt &expr);
From d0db87252687c11d58f373f7a3c36c72f8a0f1e6 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Thu, 20 Oct 2016 10:11:16 +0100
Subject: [PATCH 032/322] Improve dereferencing.
---
src/ssa/local_ssa.cpp | 9 ++----
src/ssa/ssa_dereference.cpp | 62 ++++++++++++++++++-------------------
2 files changed, 32 insertions(+), 39 deletions(-)
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index eb9d17aa7..964abb41c 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -1378,13 +1378,8 @@ void local_SSAt::assign_rec(
{
const if_exprt &if_expr=to_if_expr(lhs);
- if (if_expr.false_case().id() == ID_if)
- {
- exprt new_rhs = if_exprt(if_expr.cond(), rhs, if_expr.true_case());
- assign_rec(if_expr.true_case(), new_rhs, and_exprt(guard, if_expr.cond()), loc);
- }
- else
- assign_rec(if_expr.true_case(), rhs, and_exprt(guard, if_expr.cond()), loc);
+ exprt new_rhs = if_exprt(if_expr.cond(), rhs, if_expr.true_case());
+ assign_rec(if_expr.true_case(), new_rhs, and_exprt(guard, if_expr.cond()), loc);
assign_rec(
if_expr.false_case(),
diff --git a/src/ssa/ssa_dereference.cpp b/src/ssa/ssa_dereference.cpp
index 08c33e166..95ae0f425 100644
--- a/src/ssa/ssa_dereference.cpp
+++ b/src/ssa/ssa_dereference.cpp
@@ -323,42 +323,40 @@ exprt dereference_rec(
exprt pointer_deref=
dereference(pointer, ssa_value_domain, nondet_prefix, ns);
- // We use the identifier produced by
- // local_SSAt::replace_side_effects_rec
- exprt result;
- const typet &pointed_type = pointer.type().subtype();
- if (pointed_type.id() == ID_pointer)
- result = symbol_exprt(nondet_prefix, src.type());
- else
- {
- const typet &obj_type = ns.follow(pointed_type);
- std::string dyn_type_name = obj_type.id_string();
- if (obj_type.id() == ID_struct)
- dyn_type_name += "_" + id2string(to_struct_type(obj_type).get_tag());
- irep_idt identifier = "ssa::" + dyn_type_name + "_obj$unknown";
-
- result = symbol_exprt(identifier, src.type());
- }
+ const typet &pointed_type=ns.follow(pointer.type().subtype());
+ const ssa_value_domaint::valuest values=ssa_value_domain(pointer, ns);
- // query the value sets
- const ssa_value_domaint::valuest values=
- ssa_value_domain(pointer, ns);
-
- for(ssa_value_domaint::valuest::value_sett::const_iterator
- it=values.value_set.begin();
- it!=values.value_set.end();
- it++)
+ exprt result;
+ if (values.value_set.empty())
{
- exprt guard=ssa_alias_guard(src, it->get_expr(), ns);
- exprt value=ssa_alias_value(src, it->get_expr(), ns);
- result=if_exprt(guard, value, result);
+ irep_idt identifier=id2string(to_symbol_expr(pointer).get_identifier())+"'obj";
+ result=symbol_exprt(identifier, pointed_type);
}
-
- if (values.empty()) {
- // We use the identifier of pointed object
- irep_idt identifier = id2string(to_symbol_expr(pointer).get_identifier())+"'obj";
- result = symbol_exprt(identifier, ns.follow(pointed_type));
+ else
+ {
+ auto it=values.value_set.begin();
+
+ if(values.null || values.unknown)
+ {
+ std::string dyn_type_name=pointed_type.id_string();
+ if(pointed_type.id()==ID_struct)
+ dyn_type_name+= "_"+id2string(to_struct_type(pointed_type).get_tag());
+ irep_idt identifier="ssa::"+dyn_type_name+"_obj$unknown";
+
+ result=symbol_exprt(identifier, src.type());
+ }
+ else
+ {
+ result=ssa_alias_value(src, (it++)->get_expr(), ns);
+ }
+
+ for (; it!=values.value_set.end(); ++it)
+ {
+ exprt guard=ssa_alias_guard(src, it->get_expr(), ns);
+ exprt value=ssa_alias_value(src, it->get_expr(), ns);
+ result=if_exprt(guard, value, result);
+ }
}
return result;
From fca0f0e0148f56ebd2be1dd1c818d1710d543128 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 9 Dec 2016 10:55:05 +0100
Subject: [PATCH 033/322] Repair collection of dynamic objects
---
src/ssa/ssa_object.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/ssa/ssa_object.cpp b/src/ssa/ssa_object.cpp
index 0996c9b3c..0db5acd5d 100644
--- a/src/ssa/ssa_object.cpp
+++ b/src/ssa/ssa_object.cpp
@@ -183,7 +183,7 @@ void collect_objects_rec(
if(type.id()==ID_struct)
{
std::string id=id2string(ssa_object.get_identifier());
- if (src.type().get_bool("#dynamic") || id.find("'obj")==id.size()-4)
+ if (src.type().get_bool("#dynamic") || id.rfind("'obj")==id.size()-4)
objects.insert(ssa_object);
// need to split up
From 35a163f56018c72d689694ec7b2b63b88e8ee87a Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 9 Dec 2016 11:23:41 +0100
Subject: [PATCH 034/322] Remove replacement of arguments by symbols. Now
actual arguments are used in function call. Also remove equalities between
parameter and its pointed object (will be solved in next commits).
---
src/ssa/assignments.cpp | 28 +++++++++++--------
src/ssa/local_ssa.cpp | 60 ++++++++++++++++++-----------------------
2 files changed, 43 insertions(+), 45 deletions(-)
diff --git a/src/ssa/assignments.cpp b/src/ssa/assignments.cpp
index 4b5703444..7ff61824f 100644
--- a/src/ssa/assignments.cpp
+++ b/src/ssa/assignments.cpp
@@ -65,23 +65,13 @@ void assignmentst::build_assignment_map(
bool assigned = false;
const exprt &root_obj = o_it->get_root_object();
if (is_ptr_object(root_obj))
- { // assign objects pointed by arguments and return value of the function
+ { // assign objects pointed by return value of the function
const exprt &function = code_function_call.function();
if (function.id() == ID_symbol &&
id2string(o_it->get_identifier()).find(
id2string(to_symbol_expr(function).get_identifier())) !=
std::string::npos)
assigned = true;
-
- for (auto &arg : code_function_call.arguments())
- {
- exprt arg_symbol = arg;
- if (arg.id() == ID_address_of)
- arg_symbol = to_address_of_expr(arg_symbol).object();
- if (arg_symbol.id() == ID_symbol && id2string(o_it->get_identifier()).find(
- id2string(to_symbol_expr(arg_symbol).get_identifier())) != std::string::npos)
- assigned = true;
- }
}
else
{ // assign return value of the function
@@ -93,6 +83,22 @@ void assignmentst::build_assignment_map(
assign(*o_it, it, ns);
}
+ // assign objects pointed by arguments of the function
+ for (auto &arg : code_function_call.arguments())
+ {
+ if (arg.type().id() == ID_pointer)
+ {
+ exprt arg_ptr = arg;
+ do
+ {
+ arg_ptr = dereference(dereference_exprt(arg_ptr, arg_ptr.type().subtype()),
+ ssa_value_ai[it], "", ns);
+ assign(arg_ptr, it, ns);
+ }
+ while (arg_ptr.type().id() == ID_pointer);
+ }
+ }
+
// the call might come with an assignment
if(code_function_call.lhs().is_not_nil())
{
diff --git a/src/ssa/local_ssa.cpp b/src/ssa/local_ssa.cpp
index 964abb41c..45af83a02 100644
--- a/src/ssa/local_ssa.cpp
+++ b/src/ssa/local_ssa.cpp
@@ -97,34 +97,16 @@ void local_SSAt::get_entry_exit_vars()
const symbol_exprt ¶m=symbol->symbol_expr();
params.push_back(param);
-
- if(param.type().id()==ID_pointer)
- {
- const typet &pointed_type=ns.follow(param.type().subtype());
- const symbol_exprt pointed_obj(id2string(param.get_identifier()) + "'obj", pointed_type);
- nodes.begin()->equalities.push_back(equal_exprt(param, address_of_exprt(pointed_obj)));
- }
}
// get globals in
goto_programt::const_targett first=goto_function.body.instructions.begin();
get_globals(first, globals_in, true, false); // filters out #return_value
- for(auto &global_in : globals_in)
- {
- if(global_in.type().id()==ID_pointer &&
- id2string(global_in.get_identifier()).find('.') == std::string::npos)
- {
- const typet &pointed_type=ns.follow(global_in.type().subtype());
- const symbol_exprt pointed_obj(id2string(global_in.get_identifier()) + "'obj", pointed_type);
- nodes.begin()->equalities.push_back(equal_exprt(global_in, address_of_exprt(pointed_obj)));
- }
- }
-
- // get globals out (includes return value)
- goto_programt::const_targett
+ //get globals out (includes return value)
+ goto_programt::const_targett
last=goto_function.body.instructions.end(); last--;
- get_globals(last, globals_out, true, true, last->function);
+ get_globals(last,globals_out,true,true,last->function);
}
/*******************************************************************\
@@ -561,20 +543,9 @@ void local_SSAt::build_function_call(locationt loc)
return;
}
- f=to_function_application_expr(read_rhs(f, loc));
- assert(f.function().id()==ID_symbol); // no function pointers
- irep_idt fname=to_symbol_expr(f.function()).get_identifier();
- // add equalities for arguments
- unsigned i=0;
- for(exprt::operandst::iterator it=f.arguments().begin();
- it!=f.arguments().end(); ++it, ++i)
- {
- symbol_exprt arg(id2string(fname)+"#"+i2string(loc->location_number)+
- "#arg"+i2string(i), it->type());
- n_it->equalities.push_back(equal_exprt(*it, arg));
- *it=arg;
- }
+ assert(f.function().id()==ID_symbol); //no function pointers
+ f = to_function_application_expr(read_rhs(f, loc));
n_it->function_calls.push_back(
to_function_application_expr(f));
}
@@ -1417,6 +1388,27 @@ Function: local_SSAt::output
void local_SSAt::output(std::ostream &out) const
{
+ out << "params:";
+ for (auto ¶m : params)
+ {
+ out << " " << from_expr(param);
+ }
+ out << '\n';
+
+ out << "globals in:";
+ for (auto &glob : globals_in)
+ {
+ out << " " << from_expr(glob);
+ }
+ out << '\n';
+
+ out << "globals out:";
+ for (auto &glob : globals_out)
+ {
+ out << " " << from_expr(glob);
+ }
+ out << "\n\n";
+
for(nodest::const_iterator
n_it=nodes.begin();
n_it!=nodes.end(); n_it++)
From a26bd5800b058b3aa869109a04612e166d701d1f Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 9 Dec 2016 11:27:01 +0100
Subject: [PATCH 035/322] New preprocessings of GOTO program. Remove loop heads
in the entry of a function. Add symbols for objects pointed by function
parameters into symbol table.
---
src/2ls/2ls_parse_options.cpp | 6 ++
src/2ls/2ls_parse_options.h | 3 +
src/2ls/preprocessing_util.cpp | 107 ++++++++++++++++++++++++++++++++-
3 files changed, 115 insertions(+), 1 deletion(-)
diff --git a/src/2ls/2ls_parse_options.cpp b/src/2ls/2ls_parse_options.cpp
index 5ef232136..cd8e78fa6 100644
--- a/src/2ls/2ls_parse_options.cpp
+++ b/src/2ls/2ls_parse_options.cpp
@@ -1129,6 +1129,9 @@ bool twols_parse_optionst::process_goto_program(
replace_malloc(goto_model,"");
#endif
+ // create symbols for objects pointed by parameters
+ create_dynamic_objects(goto_model);
+
#if REMOVE_MULTIPLE_DEREFERENCES
remove_multiple_dereferences(goto_model);
#endif
@@ -1139,6 +1142,9 @@ bool twols_parse_optionst::process_goto_program(
// add loop ids
goto_model.goto_functions.compute_loop_numbers();
+ // remove loop heads from function entries
+ remove_loops_in_entry(goto_model);
+
// inline __CPROVER_initialize and main
if(cmdline.isset("inline-main"))
{
diff --git a/src/2ls/2ls_parse_options.h b/src/2ls/2ls_parse_options.h
index ddbc61c3e..68dea5b5b 100644
--- a/src/2ls/2ls_parse_options.h
+++ b/src/2ls/2ls_parse_options.h
@@ -174,6 +174,9 @@ class twols_parse_optionst:
void add_assumptions_after_assertions(goto_modelt &goto_model);
void filter_assertions(goto_modelt &goto_model);
void split_loopheads(goto_modelt &goto_model);
+ void remove_loops_in_entry(goto_modelt &goto_model);
+ void create_dynamic_objects(goto_modelt &goto_model);
+ void add_dynamic_object_rec(exprt &expr, symbol_tablet &symbol_table);
};
#endif
diff --git a/src/2ls/preprocessing_util.cpp b/src/2ls/preprocessing_util.cpp
index 590827693..dff5120e9 100644
--- a/src/2ls/preprocessing_util.cpp
+++ b/src/2ls/preprocessing_util.cpp
@@ -15,7 +15,6 @@ Author: Peter Schrammel
#include "2ls_parse_options.h"
-
/*******************************************************************\
Function: twols_parse_optionst::inline_main
@@ -466,3 +465,109 @@ void twols_parse_optionst::split_loopheads(goto_modelt &goto_model)
}
}
}
+
+/*******************************************************************\
+
+Function: twols_parse_optionst::remove_loops_in_entry
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: Remove loop head from entry instruction of a function -
+ causes problems with input variables naming. If first
+ instruction is target of back-jump, insert SKIP instruction
+ before.
+
+\*******************************************************************/
+
+void twols_parse_optionst::remove_loops_in_entry(goto_modelt &goto_model)
+{
+ Forall_goto_functions(f_it, goto_model.goto_functions)
+ {
+ if (f_it->second.body_available() &&
+ f_it->second.body.instructions.begin()->is_target())
+ {
+ auto new_entry=
+ f_it->second.body.insert_before(f_it->second.body.instructions.begin());
+ new_entry->make_skip();
+ }
+ }
+}
+
+/*******************************************************************\
+
+Function: twols_parse_optionst::create_dynamic_objects
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: Create symbols for objects pointed by parameters of a function.
+
+\*******************************************************************/
+
+void twols_parse_optionst::create_dynamic_objects(goto_modelt &goto_model)
+{
+ Forall_goto_functions(f_it, goto_model.goto_functions)
+ {
+ Forall_goto_program_instructions(i_it, f_it->second.body)
+ {
+ if (i_it->is_assign())
+ {
+ code_assignt &code_assign = to_code_assign(i_it->code);
+ add_dynamic_object_rec(code_assign.lhs(), goto_model.symbol_table);
+ add_dynamic_object_rec(code_assign.rhs(), goto_model.symbol_table);
+ }
+ }
+ }
+}
+
+/*******************************************************************\
+
+Function: twols_parse_optionst::add_dynamic_object_rec
+
+ Inputs:
+
+ Outputs:
+
+ Purpose: For each pointer-typed symbol in an expression which is a parameter,
+ create symbol for pointed object in the symbol table.
+
+\*******************************************************************/
+
+void twols_parse_optionst::add_dynamic_object_rec(
+ exprt &expr, symbol_tablet &symbol_table)
+{
+ if (expr.id() == ID_symbol)
+ {
+ const symbolt &symbol=
+ symbol_table.lookup(to_symbol_expr(expr).get_identifier());
+ if (symbol.is_parameter && symbol.type.id() == ID_pointer)
+ {
+ // New symbol
+ symbolt object_symbol;
+
+ object_symbol.base_name = id2string(symbol.base_name) + "'obj";
+ object_symbol.name = id2string(symbol.name) + "'obj";
+ const typet &pointed_type = symbol.type.subtype();
+ // Follow pointed type
+ if (pointed_type.id() == ID_symbol)
+ {
+ const symbolt type_symbol = symbol_table.lookup(
+ to_symbol_type(pointed_type).get_identifier());
+ object_symbol.type = type_symbol.type;
+ }
+ else
+ object_symbol.type = pointed_type;
+ object_symbol.mode = ID_C;
+
+ symbol_table.add(object_symbol);
+ }
+ }
+ else
+ {
+ Forall_operands(it, expr)
+ add_dynamic_object_rec(*it, symbol_table);
+ }
+}
From d982c708248df7bf1dba2970597d07bbda958f89 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Fri, 9 Dec 2016 12:45:53 +0100
Subject: [PATCH 036/322] Heap domain changes - solve problem with calling
context for functions called in loop. Introduce nondet value for template row
- expression is TRUE. Initialize heap strategy solver - create precondition
for pointer-typed parameters that don't have it.
---
src/domains/heap_domain.cpp | 77 +++++++-
src/domains/heap_domain.h | 69 +------
src/domains/ssa_analyzer.cpp | 2 +-
src/domains/strategy_solver_heap.cpp | 228 +++++++++++++++++-------
src/domains/strategy_solver_heap.h | 15 +-
src/domains/template_generator_base.cpp | 5 +-
src/ssa/address_canonizer.cpp | 2 +-
7 files changed, 263 insertions(+), 135 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 1e5425822..20fc9cb14 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -27,7 +27,7 @@ void heap_domaint::initialize(domaint::valuet &value)
/**
* Create domain template for given set of variables.
- * Template contains row for each member of each variable being pointer to struct,
+ * Template contains a row for each member of each variable being pointer to struct,
* and a row for each flattened member of a struct.
* @param var_specs Set of program variables.
* @param ns Namespace
@@ -420,3 +420,78 @@ std::string heap_domaint::get_base_name(const exprt &expr)
result = result.substr(0, result.find_last_of('#'));
return result;
}
+
+/**
+ * Get expression for the row value. It is a conjunction of points to expression and path
+ * expressions.
+ * Points to expression is disjunction of equalities:
+ * p = &o (NULL) for each object 'o' (or NULL) from points_to set
+ * Expression of path leading from variable 'p' to destination 'd' via field 'm' and
+ * passing through set of objects 'O' has form:
+ * p = d || if path can have zero length
+ * p = &o && (o.m = d || o.m = o') where o,o' belong to O and p can point to &o
+ * @param templ_expr Pointer variable of the template row
+ * @return Row value expression in the described form
+ */
+exprt heap_domaint::row_valuet::get_row_expr(const vart &templ_expr) const
+{
+ if (nondet) return true_exprt();
+
+ if (paths.empty() && points_to.empty()) return false_exprt();
+
+ exprt::operandst result;
+
+ exprt::operandst pt_expr;
+ if (!points_to.empty())
+ { // Points to expression
+ for (auto &pt : points_to)
+ {
+ pt_expr.push_back(equal_exprt(templ_expr,
+ templ_expr.type() == pt.first.type() ?
+ pt.first : address_of_exprt(pt.first)));
+ }
+ result.push_back(disjunction(pt_expr));
+ }
+
+ exprt::operandst paths_expr;
+ if (!paths.empty())
+ {
+ for (auto &path : paths)
+ { // path(p, m, d)[O]
+ const exprt &dest = path.destination;
+ exprt::operandst path_expr;
+
+ for (const dyn_objt &obj1 : points_to)
+ {
+ if (path.dyn_objects.find(obj1) != path.dyn_objects.end())
+ {
+ // p = &o
+ exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
+
+ exprt::operandst step_expr;
+ exprt member_expr = obj1.second;
+ // o.m = d
+ step_expr.push_back(equal_exprt(member_expr, dest));
+
+ for (auto &obj2 : path.dyn_objects)
+ { // o.m = o'
+ step_expr.push_back(equal_exprt(member_expr, address_of_exprt(obj2.first)));
+ }
+
+ path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
+ }
+ else
+ {
+ path_expr.push_back(equal_exprt(templ_expr,
+ templ_expr.type() == obj1.first.type() ?
+ obj1.first : address_of_exprt(obj1.first)));
+ }
+ }
+
+ paths_expr.push_back(disjunction(path_expr));
+ }
+ result.push_back(disjunction(paths_expr));
+ }
+
+ return conjunction(result);
+}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index efe023b86..2f0b51dd1 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -62,74 +62,9 @@ class heap_domaint:public domaint
std::set paths; /**< Set of paths leading from the row variable */
std::set points_to; /**< Set of objects (or NULL) the row variable can point to */
std::set pointed_by; /**< Set of rows whose variables point to this row */
+ bool nondet = false; /**< Row is nondeterministic - expression is TRUE */
- /**
- * Get expression for the row value. It is a conjunction of points to expression and path
- * expressions.
- * Points to expression is disjunction of equalities:
- * p = &o (NULL) for each object 'o' (or NULL) from points_to set
- * Expression of path leading from variable 'p' to destination 'd' via field 'm' and
- * passing through set of objects 'O' has form:
- * p = d || if path can have zero length
- * p = &o && (o.m = d || o.m = o') where o,o' belong to O and p can point to &o
- * @param templ_expr Pointer variable of the template row
- * @return Row value expression in the described form
- */
- exprt get_row_expr(const vart &templ_expr) const
- {
- if (paths.empty() && points_to.empty()) return false_exprt();
- exprt::operandst result;
-
- if (!points_to.empty())
- { // Points to expression
- exprt::operandst pt_expr;
- for (auto &pt : points_to)
- {
- exprt lhs = templ_expr;
- pt_expr.push_back(equal_exprt(templ_expr,
- is_null_ptr(pt.first) ?
- pt.first : address_of_exprt(pt.first)));
- }
- result.push_back(disjunction(pt_expr));
- }
-
- for (auto &path : paths)
- { // path(p, m, d)[O]
- const exprt &dest = path.destination;
- exprt::operandst path_expr;
-
- for (const dyn_objt &obj1 : points_to)
- {
- if (path.dyn_objects.find(obj1) != path.dyn_objects.end())
- {
- // p = &o
- exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
-
- exprt::operandst step_expr;
- exprt member_expr = obj1.second;
- // o.m = d
- step_expr.push_back(equal_exprt(member_expr, dest));
-
- for (auto &obj2 : path.dyn_objects)
- { // o.m = o'
- step_expr.push_back(equal_exprt(member_expr, address_of_exprt(obj2.first)));
- }
-
- path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
- }
- else
- {
- path_expr.push_back(equal_exprt(templ_expr,
- is_null_ptr(obj1.first) ?
- obj1.first : address_of_exprt(obj1.first)));
- }
- }
-
- result.push_back(disjunction(path_expr));
- }
-
- return conjunction(result);
- }
+ exprt get_row_expr(const vart &templ_expr) const;
inline bool empty() const
{
diff --git a/src/domains/ssa_analyzer.cpp b/src/domains/ssa_analyzer.cpp
index d01654888..68d178e62 100644
--- a/src/domains/ssa_analyzer.cpp
+++ b/src/domains/ssa_analyzer.cpp
@@ -107,7 +107,7 @@ void ssa_analyzert::operator()(
else if(template_generator.options.get_bool_option("heap"))
{
strategy_solver=new strategy_solver_heapt(
- *static_cast(domain), solver, SSA.ns);
+ *static_cast(domain), solver, SSA, precondition);
result=new heap_domaint::heap_valuet();
}
else
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index b6ad92e6a..fc171428f 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -77,6 +77,8 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
exprt post = heap_domain.get_row_post_constraint(i, inv[i]);
debug() << "post-cond: " << from_expr(ns, "", post) << " "
<< from_expr(ns, "", solver.get(post)) << eom;
+ print_solver_expr(c);
+ print_solver_expr(post);
}
#endif
@@ -86,25 +88,25 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
{
debug() << "updating row: " << row << eom;
- int actual_loc = heap_domain.get_symbol_loc(heap_domain.templ[row].expr);
+ const heap_domaint::template_rowt &templ_row = heap_domain.templ[row];
+
+ int actual_loc = heap_domain.get_symbol_loc(templ_row.expr);
exprt pointer = strategy_value_exprs[row];
exprt value = solver.get(pointer);
// Value from solver must be converted into expression
exprt ptr_value = heap_domain.value_to_ptr_exprt(value);
- if (heap_domain.is_null_ptr(ptr_value))
+ if (ptr_value.id() == ID_constant && to_constant_expr(ptr_value).get_value() == ID_NULL)
{
- exprt null_expr = null_pointer_exprt(to_pointer_type(ptr_value.type()));
-
- // Add path to NULL
- if (heap_domain.add_row_path(row, inv, null_expr,
+ // Add path to constant
+ if (heap_domain.add_row_path(row, inv, ptr_value,
std::make_pair(nil_exprt(), nil_exprt())))
improved = true;
debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
// Add points to information
- if (heap_domain.add_points_to(row, inv, std::make_pair(null_expr, nil_exprt())))
+ if (heap_domain.add_points_to(row, inv, std::make_pair(ptr_value, nil_exprt())))
improved = true;
debug() << "add points to: " << from_expr(ns, "", ptr_value) << eom;
}
@@ -119,69 +121,100 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
symbol_exprt obj = to_symbol_expr(to_address_of_expr(address).object());
- if (obj.type().get_bool("#dynamic"))
+ if (obj.type() == pointer.type())
{
- // obj is dynamic object accessed inside the function
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
- if (id2string(obj.get_identifier()).find("$unknown") != std::string::npos)
- { // handle unknown object
- if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
- improved = true;
- debug() << "add points to: " << from_expr(ns, "", obj) << eom;
- }
- else
+ if (heap_domain.add_row_path(row, inv, obj,
+ std::make_pair(nil_exprt(), nil_exprt())));
+ }
+ else
+ {
+
+ if (obj.type().get_bool("#dynamic"))
{
- // Find row with corresponding member field of pointed object (obj.member)
- int member_val_index;
- if (inv[row].empty() && heap_domain.templ[row].dyn_obj.id() != ID_nil &&
- heap_domain.get_base_name(obj) ==
- heap_domain.get_base_name(heap_domain.templ[row].dyn_obj))
- { // for the same object find previous instance
- // (used for multiple loops in one function)
- member_val_index = find_member_row(obj, heap_domain.templ[row].member,
- --actual_loc);
- if (member_val_index < 0)
- member_val_index = find_member_row(obj, heap_domain.templ[row].member,
- ++actual_loc);
+ // obj is dynamic object accessed inside the function
+
+ if (id2string(obj.get_identifier()).find("$unknown") != std::string::npos)
+ { // handle unknown object
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
}
else
{
- member_val_index = find_member_row(obj, heap_domain.templ[row].member, actual_loc);
+ // Find row with corresponding member field of pointed object (obj.member)
+ int member_val_index;
+ if (inv[row].empty() && templ_row.dyn_obj.id() != ID_nil &&
+ heap_domain.get_base_name(obj) ==
+ heap_domain.get_base_name(templ_row.dyn_obj))
+ { // for the same object find previous instance
+ // (used for multiple loops in one function)
+ member_val_index = find_member_row(obj, templ_row.member, --actual_loc,
+ templ_row.kind);
+ if (member_val_index < 0)
+ member_val_index = find_member_row(obj, templ_row.member, ++actual_loc,
+ templ_row.kind);
+ }
+ else
+ {
+ member_val_index = find_member_row(obj, templ_row.member, actual_loc,
+ templ_row.kind);
+ }
+ assert(member_val_index >= 0);
+ exprt member_expr = heap_domain.templ[member_val_index].expr;
+
+ // Add all paths from obj.next to p
+ if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
+ std::make_pair(obj, member_expr)))
+ improved = true;
+ debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
+ << from_expr(ns, "", obj) << eom;
+
+ // Add points to information
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+
+ heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
}
- assert(member_val_index >= 0);
- exprt member_expr = heap_domain.templ[member_val_index].expr;
-
- // Add all paths from obj.next to p
- if (heap_domain.add_all_paths(row, (unsigned) member_val_index, inv,
- std::make_pair(obj, member_expr)))
- improved = true;
- debug() << "add all paths: " << from_expr(ns, "", member_expr) << ", through: "
- << from_expr(ns, "", obj) << eom;
-
+ }
+ else
+ {
// Add points to information
- if (heap_domain.add_points_to(row, inv, std::make_pair(obj, member_expr)))
+ if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
improved = true;
debug() << "add points to: " << from_expr(ns, "", obj) << eom;
- heap_domain.add_pointed_by_row((unsigned) member_val_index, row, inv);
+ // Add path to &(obj)
+ if (heap_domain.add_row_path(row, inv, address_of_exprt(obj),
+ std::make_pair(nil_exprt(), nil_exprt())))
+ improved = true;
+ debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
}
}
- else
- {
- // Add points to information
- if (heap_domain.add_points_to(row, inv, std::make_pair(obj, nil_exprt())))
- improved = true;
- debug() << "add points to: " << from_expr(ns, "", obj) << eom;
+ }
+ else if (ptr_value.id() == ID_symbol)
+ {
+ if (heap_domain.add_points_to(row, inv, std::make_pair(ptr_value, nil_exprt())))
+ improved = true;
+ debug() << "add points to: " << from_expr(ns, "", ptr_value) << eom;
- // Add path to &(obj)
- if (heap_domain.add_row_path(row, inv, address_of_exprt(obj),
- std::make_pair(nil_exprt(), nil_exprt())))
- improved = true;
- debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
- }
+ if (heap_domain.add_row_path(row, inv, ptr_value,
+ std::make_pair(nil_exprt(), nil_exprt())))
+ improved = true;
+ debug() << "add destination: " << from_expr(ns, "", ptr_value) << eom;
+ }
+ else
+ {
+ improved = !inv[row].nondet;
+ inv[row].nondet = true;
+ debug() << "set nondet" << eom;
}
- if (heap_domain.templ[row].dynamic)
+ if (templ_row.dynamic)
{ // Recursively update all rows that are dependent on this row
updated_rows.clear();
update_rows_rec(row, inv);
@@ -192,11 +225,7 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
else
{
-#define DEBUG_OUTPUT
-#ifdef DEBUG_OUTPUT
debug() << "UNSAT" << eom;
-#endif
-#undef DEBUG_OUTPUT
#ifdef DEBUG_OUTPUT
for (unsigned i = 0; i < solver.formula.size(); i++)
@@ -206,6 +235,20 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
else
debug() << "not_in_conflict: " << solver.formula[i] << eom;
}
+
+ for (unsigned i = 0; i < heap_domain.templ.size(); i++)
+ {
+ exprt c = heap_domain.get_row_pre_constraint(i, inv[i]);
+ debug() << "cond: " << from_expr(ns, "", c) << " " <<
+ from_expr(ns, "", solver.get(c)) << eom;
+ debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].pre_guard) <<
+ " " << from_expr(ns, "", solver.get(heap_domain.templ[i].pre_guard)) << eom;
+ debug() << "guards: " << from_expr(ns, "", heap_domain.templ[i].post_guard) << " "
+ << from_expr(ns, "", solver.get(heap_domain.templ[i].post_guard)) << eom;
+ exprt post = heap_domain.get_row_post_constraint(i, inv[i]);
+ debug() << "post-cond: " << from_expr(ns, "", post) << " "
+ << from_expr(ns, "", solver.get(post)) << eom;
+ }
#endif
}
solver.pop_context();
@@ -221,7 +264,8 @@ bool strategy_solver_heapt::iterate(invariantt &_inv)
* @param actual_loc Actual location number
* @return Template row of obj.member
*/
-int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &member, int actual_loc)
+int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &member, int actual_loc,
+ const domaint::kindt &kind)
{
assert(obj.id() == ID_symbol);
std::string obj_id = heap_domain.get_base_name(obj);
@@ -231,7 +275,7 @@ int strategy_solver_heapt::find_member_row(const exprt &obj, const irep_idt &mem
for (unsigned i = 0; i < heap_domain.templ.size(); ++i)
{
heap_domaint::template_rowt &templ_row = heap_domain.templ[i];
- if (templ_row.member == member && templ_row.dynamic)
+ if (templ_row.kind == kind && templ_row.member == member && templ_row.dynamic)
{
std::string id = id2string(to_symbol_expr(templ_row.expr).get_identifier());
if (id.find(obj_id) != std::string::npos)
@@ -274,3 +318,67 @@ bool strategy_solver_heapt::update_rows_rec(const heap_domaint::rowt &row,
}
return result;
}
+
+void strategy_solver_heapt::print_solver_expr(const exprt &expr)
+{
+ debug() << from_expr(ns, "", expr) << ": " << from_expr(ns, "", solver.get(expr)) << eom;
+ forall_operands(it, expr)
+ print_solver_expr(*it);
+}
+
+void strategy_solver_heapt::initialize(const local_SSAt &SSA, const exprt &precondition)
+{
+ exprt::operandst equs;
+ for (auto ¶m : SSA.params)
+ {
+ if (param.type().id() == ID_pointer &&
+ id2string(param.get_identifier()).find('.') == std::string::npos)
+ {
+ if (!has_precondition_rec(param, precondition))
+ {
+ debug() << "Creating precondition for pointer parameters" << eom;
+ const symbolt *symbol;
+ if (ns.lookup(id2string(param.get_identifier()), symbol)) continue;
+
+ address_of_exprt init_value(symbol->symbol_expr());
+ init_value.type() = symbol->type;
+ equs.push_back(equal_exprt(param, init_value));
+ }
+ }
+ }
+ for (auto &global_in : SSA.globals_in)
+ {
+ if (global_in.type().id() == ID_pointer &&
+ id2string(global_in.get_identifier()).find('.') == std::string::npos)
+ {
+ if (!has_precondition_rec(global_in, precondition))
+ {
+ debug() << "Creating precondition for pointer parameters" << eom;
+ const symbolt *symbol;
+ if (ns.lookup(id2string(global_in.get_identifier()), symbol)) continue;
+
+ address_of_exprt init_value(symbol->symbol_expr());
+ init_value.type() = symbol->type;
+ equs.push_back(equal_exprt(global_in, init_value));
+ }
+ }
+ }
+
+ solver << conjunction(equs);
+}
+
+bool strategy_solver_heapt::has_precondition_rec(const exprt &expr, const exprt &precondition)
+{
+ if (precondition.id() == ID_equal)
+ {
+ const equal_exprt &eq = to_equal_expr(precondition);
+ return (eq.lhs() == expr && eq.rhs() != expr);
+ }
+ else
+ {
+ bool result = false;
+ forall_operands(it, precondition)
+ result = result || has_precondition_rec(expr, *it);
+ return result;
+ }
+}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index 5b22acf4e..0d80fc10f 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -5,6 +5,7 @@
#ifndef CPROVER_STRATEGY_SOLVER_HEAP_H
#define CPROVER_STRATEGY_SOLVER_HEAP_H
+#include "../ssa/local_ssa.h"
#include "strategy_solver_base.h"
#include "heap_domain.h"
@@ -12,20 +13,28 @@ class strategy_solver_heapt : public strategy_solver_baset
{
public:
explicit strategy_solver_heapt(heap_domaint &_heap_domain, incremental_solvert &_solver,
- const namespacet &_ns)
- : strategy_solver_baset(_solver, _ns), heap_domain(_heap_domain)
+ const local_SSAt &SSA, const exprt &precondition)
+ : strategy_solver_baset(_solver, SSA.ns), heap_domain(_heap_domain)
{
+ initialize(SSA, precondition);
}
virtual bool iterate(invariantt &_inv) override;
+ void initialize(const local_SSAt &SSA, const exprt &precondition);
+
protected:
heap_domaint &heap_domain;
std::set updated_rows;
- int find_member_row(const exprt &obj, const irep_idt &member, int actual_loc);
+ int find_member_row(const exprt &obj, const irep_idt &member, int actual_loc,
+ const domaint::kindt &kind);
bool update_rows_rec(const heap_domaint::rowt &row, heap_domaint::heap_valuet &value);
+
+ void print_solver_expr(const exprt &expr);
+
+ bool has_precondition_rec(const exprt &expr, const exprt &precondition);
};
diff --git a/src/domains/template_generator_base.cpp b/src/domains/template_generator_base.cpp
index 7aa2e1ed9..45249b0e5 100644
--- a/src/domains/template_generator_base.cpp
+++ b/src/domains/template_generator_base.cpp
@@ -273,8 +273,9 @@ void template_generator_baset::filter_heap_domain()
{
if(var->var.id()==ID_symbol && var->var.type().id()==ID_pointer)
{
- // Filter out non-assigned variables
- if(ssa_inlinert::get_original_identifier(to_symbol_expr(var->var)) !=
+ // Filter out non-assigned OUT variables
+ if(var->kind!=domaint::OUT ||
+ ssa_inlinert::get_original_identifier(to_symbol_expr(var->var))!=
to_symbol_expr(var->var).get_identifier())
var_specs.push_back(*var);
}
diff --git a/src/ssa/address_canonizer.cpp b/src/ssa/address_canonizer.cpp
index f6e6b9cb2..466139299 100644
--- a/src/ssa/address_canonizer.cpp
+++ b/src/ssa/address_canonizer.cpp
@@ -49,7 +49,7 @@ exprt address_canonizer(
if (offset.id()==ID_constant && to_constant_expr(offset).is_zero())
{
- return address_of_exprt(to_member_expr(object).struct_op());
+ return address_of_exprt(to_member_expr(object).compound());
}
else
{
From 1cb1881021e297be4c613451ef459555f90658b8 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Tue, 17 Jan 2017 10:55:07 +0100
Subject: [PATCH 037/322] Strategy solver heap: move creating precondition to
separate function
---
src/domains/strategy_solver_heap.cpp | 56 ++++++++++++----------------
src/domains/strategy_solver_heap.h | 3 ++
2 files changed, 26 insertions(+), 33 deletions(-)
diff --git a/src/domains/strategy_solver_heap.cpp b/src/domains/strategy_solver_heap.cpp
index fc171428f..6b9bc6c91 100644
--- a/src/domains/strategy_solver_heap.cpp
+++ b/src/domains/strategy_solver_heap.cpp
@@ -328,41 +328,12 @@ void strategy_solver_heapt::print_solver_expr(const exprt &expr)
void strategy_solver_heapt::initialize(const local_SSAt &SSA, const exprt &precondition)
{
+ // Create preconditions for input variables if not exist
exprt::operandst equs;
for (auto ¶m : SSA.params)
- {
- if (param.type().id() == ID_pointer &&
- id2string(param.get_identifier()).find('.') == std::string::npos)
- {
- if (!has_precondition_rec(param, precondition))
- {
- debug() << "Creating precondition for pointer parameters" << eom;
- const symbolt *symbol;
- if (ns.lookup(id2string(param.get_identifier()), symbol)) continue;
-
- address_of_exprt init_value(symbol->symbol_expr());
- init_value.type() = symbol->type;
- equs.push_back(equal_exprt(param, init_value));
- }
- }
- }
+ create_precondition(param, precondition, equs);
for (auto &global_in : SSA.globals_in)
- {
- if (global_in.type().id() == ID_pointer &&
- id2string(global_in.get_identifier()).find('.') == std::string::npos)
- {
- if (!has_precondition_rec(global_in, precondition))
- {
- debug() << "Creating precondition for pointer parameters" << eom;
- const symbolt *symbol;
- if (ns.lookup(id2string(global_in.get_identifier()), symbol)) continue;
-
- address_of_exprt init_value(symbol->symbol_expr());
- init_value.type() = symbol->type;
- equs.push_back(equal_exprt(global_in, init_value));
- }
- }
- }
+ create_precondition(global_in, precondition, equs);
solver << conjunction(equs);
}
@@ -378,7 +349,26 @@ bool strategy_solver_heapt::has_precondition_rec(const exprt &expr, const exprt
{
bool result = false;
forall_operands(it, precondition)
- result = result || has_precondition_rec(expr, *it);
+ result = result || has_precondition_rec(expr, *it);
return result;
}
}
+
+void strategy_solver_heapt::create_precondition(const symbol_exprt &var, const exprt &precondition,
+ exprt::operandst &equs)
+{
+ if (var.type().id() == ID_pointer &&
+ id2string(var.get_identifier()).find('.') == std::string::npos)
+ {
+ if (!has_precondition_rec(var, precondition))
+ {
+ debug() << "Creating precondition for pointer parameters" << eom;
+ const symbolt *symbol;
+ if (ns.lookup(id2string(var.get_identifier()), symbol)) return;
+
+ address_of_exprt init_value(symbol->symbol_expr());
+ init_value.type() = symbol->type;
+ equs.push_back(equal_exprt(var, init_value));
+ }
+ }
+}
diff --git a/src/domains/strategy_solver_heap.h b/src/domains/strategy_solver_heap.h
index 0d80fc10f..c048dda04 100644
--- a/src/domains/strategy_solver_heap.h
+++ b/src/domains/strategy_solver_heap.h
@@ -34,6 +34,9 @@ class strategy_solver_heapt : public strategy_solver_baset
void print_solver_expr(const exprt &expr);
+ void create_precondition(const symbol_exprt &var, const exprt &precondition,
+ exprt::operandst &equs);
+
bool has_precondition_rec(const exprt &expr, const exprt &precondition);
};
From 0b8a3c835aa2e5160c99a31494989f699f8c29f0 Mon Sep 17 00:00:00 2001
From: Viktor Malik
Date: Tue, 17 Jan 2017 11:02:30 +0100
Subject: [PATCH 038/322] Heap domain: split template into STACK and HEAP part.
Stack part contains rows for pointers and a value is set of pointed objects.
Heap part contains rows for struct objects and a value is set of access
paths.
---
src/domains/heap_domain.cpp | 360 +++++++++++++--------------
src/domains/heap_domain.h | 79 ++++--
src/domains/strategy_solver_heap.cpp | 232 +++++++++--------
3 files changed, 339 insertions(+), 332 deletions(-)
diff --git a/src/domains/heap_domain.cpp b/src/domains/heap_domain.cpp
index 20fc9cb14..6431059cb 100644
--- a/src/domains/heap_domain.cpp
+++ b/src/domains/heap_domain.cpp
@@ -16,12 +16,15 @@
void heap_domaint::initialize(domaint::valuet &value)
{
heap_valuet &val = static_cast(value);
- val.resize(templ.size());
- for (unsigned row = 0; row < templ.size(); ++row)
+
+ for (auto &templ_row : templ)
{
- val[row].paths.clear();
- val[row].points_to.clear();
- val[row].pointed_by.clear();
+ if (templ_row.mem_kind == STACK)
+ val.emplace_back(new stack_row_valuet());
+ else if (templ_row.mem_kind == HEAP)
+ val.emplace_back(new heap_row_valuet());
+ else
+ assert(false);
}
}
@@ -38,55 +41,52 @@ void heap_domaint::make_template(const domaint::var_specst &var_specs, const nam
templ.clear();
templ.reserve(size);
- for (auto v1 = var_specs.begin(); v1 != var_specs.end(); ++v1)
+ for (auto v = var_specs.begin(); v != var_specs.end(); ++v)
{
- if (v1->kind == IN) continue;
+ if (v->kind == IN) continue;
// Create template for each pointer to struct
- const vart &var1 = v1->var;
- if (var1.type().id() == ID_pointer)
+ const vart &var = v->var;
+ if (var.type().id() == ID_pointer)
{
- const typet &pointed_type = ns.follow(var1.type().subtype());
+ const typet &pointed_type = ns.follow(var.type().subtype());
if (pointed_type.id() == ID_struct)
{
- // Check if var1 is member field of dynamic object
- const std::string identifier = id2string(to_symbol_expr(v1->var).get_identifier());
- bool dynamic = false;
- for (auto &component : to_struct_type(pointed_type).components())
- {
- if (identifier.find("." + id2string(component.get_name())) != std::string::npos)
- dynamic = true;
- }
-
- for (auto &component : to_struct_type(pointed_type).components())
- {
- if (!dynamic ||
- identifier.find("." + id2string(component.get_name())) != std::string::npos)
- {
- templ.push_back(template_rowt());
- template_rowt &templ_row = templ.back();
- templ_row.expr = v1->var;
- templ_row.member = component.get_name();
- templ_row.pre_guard = v1->pre_guard;
- templ_row.post_guard = v1->post_guard;
- templ_row.aux_expr = v1->aux_expr;
- templ_row.kind = v1->kind;
- templ_row.dynamic = dynamic;
- if (dynamic)
- {
- std::string var1_id = id2string(to_symbol_expr(var1).get_identifier());
- std::string do_id = var1_id.substr(0, var1_id.find_last_of('.'));
- templ_row.dyn_obj = symbol_exprt(do_id, var1.type().subtype());
- }
- else
- templ_row.dyn_obj = nil_exprt();
- }
- }
+ add_template_row(*v, pointed_type);
}
}
}
}
+void heap_domaint::add_template_row(const var_spect &var_spec, const typet &pointed_type)
+{
+ const vart &var = var_spec.var;
+
+ templ.push_back(template_rowt());
+ template_rowt &templ_row = templ.back();
+ templ_row.expr = var;
+ templ_row.pre_guard = var_spec.pre_guard;
+ templ_row.post_guard = var_spec.post_guard;
+ templ_row.aux_expr = var_spec.aux_expr;
+ templ_row.kind = var_spec.kind;
+
+ templ_row.mem_kind = STACK;
+ // Check if var is member field of heap object
+ const std::string identifier = id2string(to_symbol_expr(var_spec.var).get_identifier());
+ for (auto &component : to_struct_type(pointed_type).components())
+ {
+ if (identifier.find("." + id2string(component.get_name())) != std::string::npos)
+ {
+ templ_row.mem_kind = HEAP;
+ templ_row.member = component.get_name();
+
+ std::string var_id = id2string(to_symbol_expr(var).get_identifier());
+ std::string do_id = var_id.substr(0, var_id.find_last_of('.'));
+ templ_row.dyn_obj = symbol_exprt(do_id, var.type().subtype());
+ }
+ }
+}
+
/**
* Create entry constraints expression for a value.
* @param value Value
@@ -161,50 +161,6 @@ exprt heap_domaint::get_row_post_constraint(const rowt &row, const row_valuet &r
return c;
}
-/**
- * Add new destination for a row
- * @param row Row number
- * @param value Value
- * @param dest New destination to add
- * @param dyn_obj Dynamic object for that the path passes through (is nil if path can have zero
- * length).
- * @return True if insertion took place (dest did not exist in the row value)
- */
-bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt &dest,
- const dyn_objt &dyn_obj)
-{
- assert(row < value.size());
- assert(value.size() == templ.size());
-
- auto &path_set = value[row].paths;
-
- if (path_set.find(dest) == path_set.end())
- {
- // Path does not exist yet
- std::set dyn_obj_set;
- bool zero_path = true;
- if (dyn_obj.first.id() != ID_nil)
- { // Path doesn't have zero length
- dyn_obj_set.insert(dyn_obj);
- zero_path = false;
- }
- path_set.emplace(dest, dyn_obj_set, zero_path);
- return true;
- }
- else
- {
- // Path exists already
- if (dyn_obj.first.id() == ID_nil)
- {
- bool result = path_set.find(dest)->zero_length;
- path_set.find(dest)->zero_length = true;
- return !result;
- }
- // Try to insert new dynamic object belonging to the path
- return path_set.find(dest)->dyn_objects.insert(dyn_obj).second;
- }
-}
-
/**
* Add all paths of one pointer as the destinations of another pointer.
* @param to Row to add new paths to
@@ -214,46 +170,43 @@ bool heap_domaint::add_row_path(const rowt &row, heap_valuet &value, const exprt
* one pointer to another.
* @return True if any path was added or changed, otherwise false.
*/
-bool heap_domaint::add_all_paths(const rowt &to, const rowt &from, heap_valuet &value,
- const dyn_objt &dyn_obj)
+bool heap_domaint::add_transitivity(const rowt &from, const rowt &to, heap_valuet &value)
{
+ assert(from < value.size() && to < value.size());
+ assert(templ[to].mem_kind == HEAP && templ[from].mem_kind == HEAP);
+
+ heap_row_valuet &heap_val_from = static_cast(value[from]);
+ heap_row_valuet &heap_val_to = static_cast(value[to]);
+
bool result = false;
- for (auto &path : value[from].paths)
+ if (heap_val_from.add_all_paths(heap_val_to, std::make_pair(templ[to].dyn_obj, templ[to].expr)))
+ result = true;
+ if (from != to)
{
- // Add the path with new dynamic object
- if (add_row_path(to, value, path.destination, dyn_obj))
+ if (heap_val_to.add_pointed_by(from))
result = true;
- for (auto &o : path.dyn_objects)
- { // Add all dynamic objects of the original path
- if (add_row_path(to, value, path.destination, o))
- result = true;
- }
}
+
return result;
}
-/**
- * Add new points to address to a row.
- * @param row Value row
- * @param value Heap value
- * @param dyn_obj New dynamic object that the row variable can point to.
- * @return True if the object was really added.
- */
-bool heap_domaint::add_points_to(const rowt &row, heap_valuet &value, const dyn_objt &dyn_obj)
+bool heap_domaint::add_points_to(const heap_domaint::rowt &row, heap_domaint::heap_valuet &value,
+ const exprt &dest)
{
- auto new_pt = value[row].points_to.insert(dyn_obj);
- return new_pt.second;
+ assert(row < value.size());
+
+ if (templ[row].dyn_obj == dest) return false;
+
+ return value[row].add_points_to(dest);
}
-/**
- * Add new dependent row (pb_row points to row)
- * @param row Pointed row
- * @param pb_row Pointer row
- * @param value Heap value
- */
-void heap_domaint::add_pointed_by_row(const rowt &row, const rowt &pb_row, heap_valuet &value)
+bool heap_domaint::set_nondet(const rowt &row, heap_valuet &value)
{
- value[row].pointed_by.insert(pb_row);
+ assert(row < value.size());
+
+ bool result = !value[row].nondet;
+ value[row].nondet = true;
+ return result;
}
void heap_domaint::output_value(std::ostream &out, const domaint::valuet &value,
@@ -314,8 +267,10 @@ void heap_domaint::output_domain(std::ostream &out, const namespacet &ns) const
assert(false);
}
const vart &var = templ_row.expr;
- const irep_idt &member = templ_row.member;
- out << i << ": ?path(" << from_expr(ns, "", var) << ", " << member << ", DESTINATIONS)"
+
+ out << i << ": " << from_expr(ns, "", var)
+ << (templ_row.mem_kind == STACK ? " --points_to--> Locations"
+ : " --paths--> Destinations")
<< std::endl;
}
}
@@ -371,26 +326,6 @@ void heap_domaint::join(domaint::valuet &value1, const domaint::valuet &value2)
const heap_valuet &val2 = static_cast(value2);
assert(val1.size() == templ.size());
assert(val2.size() == val1.size());
- for (rowt row = 0; row < templ.size(); ++row)
- { // Insert all elements of second set to first
- val1[row].paths.insert(val2[row].paths.begin(), val2[row].paths.end());
- }
-}
-
-/**
- * Check whether expression is NULL pointer.
- * @param expr Expression to check
- * @return True if expr is NULL pointer
- */
-bool heap_domaint::is_null_ptr(const exprt &expr)
-{
- if (expr.id() == ID_constant && to_constant_expr(expr).get_value() == ID_NULL)
- return true;
- if (expr.id() == ID_plus)
- return is_null_ptr(expr.op0()) || is_null_ptr(expr.op1());
- if (expr.id() == ID_typecast)
- return is_null_ptr(to_typecast_expr(expr).op());
- return false;
}
/**
@@ -421,77 +356,122 @@ std::string heap_domaint::get_base_name(const exprt &expr)
return result;
}
-/**
- * Get expression for the row value. It is a conjunction of points to expression and path
- * expressions.
- * Points to expression is disjunction of equalities:
- * p = &o (NULL) for each object 'o' (or NULL) from points_to set
- * Expression of path leading from variable 'p' to destination 'd' via field 'm' and
- * passing through set of objects 'O' has form:
- * p = d || if path can have zero length
- * p = &o && (o.m = d || o.m = o') where o,o' belong to O and p can point to &o
- * @param templ_expr Pointer variable of the template row
- * @return Row value expression in the described form
- */
-exprt heap_domaint::row_valuet::get_row_expr(const vart &templ_expr) const
+exprt heap_domaint::stack_row_valuet::get_row_expr(const domaint::vart &templ_expr) const
{
if (nondet) return true_exprt();
- if (paths.empty() && points_to.empty()) return false_exprt();
-
- exprt::operandst result;
-
- exprt::operandst pt_expr;
- if (!points_to.empty())
+ if (empty())
+ return false_exprt();
+ else
{ // Points to expression
+ exprt::operandst result;
for (auto &pt : points_to)
{
- pt_expr.push_back(equal_exprt(templ_expr,
- templ_expr.type() == pt.first.type() ?
- pt.first : address_of_exprt(pt.first)));
+ result.push_back(equal_exprt(templ_expr, templ_expr.type() == pt.type() ?
+ pt : address_of_exprt(pt)));
}
- result.push_back(disjunction(pt_expr));
+ return disjunction(result);
}
+}
- exprt::operandst paths_expr;
- if (!paths.empty())
+bool heap_domaint::stack_row_valuet::add_points_to(const exprt &expr)
+{
+ auto new_pt = points_to.insert(expr);
+ return new_pt.second;
+}
+
+exprt heap_domaint::heap_row_valuet::get_row_expr(const domaint::vart &templ_expr) const
+{
+ if (nondet) return true_exprt();
+
+ if (empty())
+ return false_exprt();
+ else
{
+ exprt::operandst result;
for (auto &path : paths)
- { // path(p, m, d)[O]
- const exprt &dest = path.destination;
+ { // path(o.m, d)[O]
+ const exprt &dest = templ_expr.type() == path.destination.type() ?
+ path.destination : address_of_exprt(path.destination);
exprt::operandst path_expr;
- for (const dyn_objt &obj1 : points_to)
+ // o.m = d
+ path_expr.push_back(equal_exprt(templ_expr, dest));
+
+ for (const dyn_objt &obj1 : path.dyn_objects)
{
- if (path.dyn_objects.find(obj1) != path.dyn_objects.end())
- {
- // p = &o
- exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
-
- exprt::operandst step_expr;
- exprt member_expr = obj1.second;
- // o.m = d
- step_expr.push_back(equal_exprt(member_expr, dest));
-
- for (auto &obj2 : path.dyn_objects)
- { // o.m = o'
- step_expr.push_back(equal_exprt(member_expr, address_of_exprt(obj2.first)));
- }
-
- path_expr.push_back(and_exprt(equ_exprt, disjunction(step_expr)));
- }
- else
- {
- path_expr.push_back(equal_exprt(templ_expr,
- templ_expr.type() == obj1.first.type() ?
- obj1.first : address_of_exprt(obj1.first)));
+ // o.m = &o'
+ exprt equ_exprt = equal_exprt(templ_expr, address_of_exprt(obj1.first));
+
+ exprt::operandst steps_expr;
+ exprt member_expr = obj1.second;
+ // o'.m = d
+ steps_expr.push_back(equal_exprt(member_expr, dest));
+
+ for (auto &obj2 : path.dyn_objects)
+ { // o'.m = o''
+ steps_expr.push_back(equal_exprt(member_expr, address_of_exprt(obj2.first)));
}
+
+ path_expr.push_back(and_exprt(equ_exprt, disjunction(steps_expr)));
}
- paths_expr.push_back(disjunction(path_expr));
+ result.push_back(disjunction(path_expr));
+ }
+ return conjunction(result);
+ }
+}
+
+bool heap_domaint::heap_row_valuet::add_points_to(const exprt &dest)
+{
+ return add_path(dest, std::make_pair(nil_exprt(), nil_exprt()));
+}
+
+bool heap_domaint::heap_row_valuet::add_path(const exprt &dest,
+ const heap_domaint::dyn_objt &dyn_obj)
+{
+ if (paths.find(dest) == paths.end())
+ {
+ // Path does not exist yet
+ std::set dyn_obj_set;
+ if (dyn_obj.first.id() != ID_nil)
+ { // Path doesn't have zero length
+ dyn_obj_set.insert(dyn_obj);
}
- result.push_back(disjunction(paths_expr));
+ paths.emplace(dest, dyn_obj_set);
+ return true;
+ }
+ else
+ {
+ // Path exists already
+ if (dyn_obj.first.id() != ID_nil)
+ // Try to insert new dynamic object on the path
+ return paths.find(dest)->dyn_objects.insert(dyn_obj).second;
+ else
+ return false;
}
+}
- return conjunction(result);
+bool heap_domaint::heap_row_valuet::add_all_paths(const heap_domaint::heap_row_valuet &other_val,
+ const heap_domaint::dyn_objt &dyn_obj)
+{
+ bool result = false;
+ for (auto &path : other_val.paths)
+ {
+ // Add the path with new dynamic object
+ if (add_path(path.destination, dyn_obj))
+ result = true;
+ for (auto &o : path.dyn_objects)
+ { // Add all dynamic objects of the original path
+ if (add_path(path.destination, o))
+ result = true;
+ }
+ }
+ return result;
+}
+
+bool heap_domaint::heap_row_valuet::add_pointed_by(const rowt &row)
+{
+ auto new_pb = pointed_by.insert(row);
+ return new_pb.second;
}
diff --git a/src/domains/heap_domain.h b/src/domains/heap_domain.h
index 2f0b51dd1..ca6474ca0 100644
--- a/src/domains/heap_domain.h
+++ b/src/domains/heap_domain.h
@@ -6,6 +6,8 @@
#ifndef CPROVER_2LS_DOMAINS_HEAP_DOMAIN_H
#define CPROVER_2LS_DOMAINS_HEAP_DOMAIN_H
+#include
+#include
#include "domain.h"
class heap_domaint:public domaint
@@ -15,6 +17,8 @@ class heap_domaint:public domaint
typedef vart member_fieldt;
typedef std::pair dyn_objt;
+ typedef enum { STACK, HEAP } mem_kindt;
+
heap_domaint(
unsigned int _domain_number,
replace_mapt &_renaming_map,
@@ -29,6 +33,31 @@ class heap_domaint:public domaint
* Value of a row is set of paths in the heap leading from row variable
*/
struct row_valuet
+ {
+ bool nondet = false; /**< Row is nondeterministic - expression is TRUE */
+
+ virtual exprt get_row_expr(const vart &templ_expr) const = 0;
+
+ virtual bool empty() const = 0;
+
+ virtual bool add_points_to(const exprt &dest) = 0;
+ };
+
+ struct stack_row_valuet : public row_valuet
+ {
+ std::set points_to; /**< Set of objects (or NULL) the row variable can point to */
+
+ virtual exprt get_row_expr(const vart &templ_expr) const override;
+
+ virtual bool add_points_to(const exprt &expr) override;
+
+ virtual bool empty() const override
+ {
+ return points_to.empty();
+ }
+ };
+
+ struct heap_row_valuet : public row_valuet
{
/**
* Path in a heap. Contains:
@@ -41,12 +70,11 @@ class heap_domaint:public domaint
{
exprt destination;
mutable std::set dyn_objects;
- mutable bool zero_length;
patht(const exprt &dest_) : destination(dest_) {}
- patht(const exprt &dest_, const std::set