File tree Expand file tree Collapse file tree 22 files changed +362
-1
lines changed Expand file tree Collapse file tree 22 files changed +362
-1
lines changed Original file line number Diff line number Diff line change
1
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_ensures (* x == * x_ + 5 )
2
+ {
3
+ * x = * x + 5 ;
4
+ }
5
+
6
+ int main ()
7
+ {
8
+ int n ;
9
+ foo (& n );
10
+
11
+ return 0 ;
12
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported for variables that are
11
+ being assigned by the function under test. By using the
12
+ --enforce-all-contracts flag, the post-condition (which contains the ghost
13
+ vriable) is asserted. In this case, this assertion should pass.
Original file line number Diff line number Diff line change
1
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_ensures (* x < * x_ + 5 )
2
+ {
3
+ * x = * x + 5 ;
4
+ }
5
+
6
+ int main ()
7
+ {
8
+ int n ;
9
+ foo (& n );
10
+
11
+ return 0 ;
12
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=10$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION FAILED$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported for variables that are
11
+ being assigned by the function under test. By using the
12
+ --enforce-all-contracts flag, the post-condition (which contains the ghost
13
+ vriable) is asserted. In this case, this assertion should fail.
Original file line number Diff line number Diff line change
1
+ void foo (int * x , int * y ) __CPROVER_assigns (* x , * y )
2
+ __CPROVER_ensures (* x == * y_ + 1 && * y == * x_ + 2 )
3
+ {
4
+ int x_initial = * x ;
5
+ * x = * y + 1 ;
6
+ * y = x_initial + 2 ;
7
+ }
8
+
9
+ int main ()
10
+ {
11
+ int x , y ;
12
+ foo (& x , & y );
13
+
14
+ return 0 ;
15
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported in the case where multiple
11
+ variables are being assgned by the function under test. By using the
12
+ --enforce-all-contracts flag, the post-condition (which contains the ghost
13
+ variable) is asserted. In this case, this assertion should pass.
Original file line number Diff line number Diff line change
1
+ void foo (int * x , int * y ) __CPROVER_assigns (* x , * y )
2
+ __CPROVER_ensures (* x == * x_ + 2 || * y == * y_ + 3 )
3
+ {
4
+ * x = * x + 1 ;
5
+ * y = * y + 2 ;
6
+ }
7
+
8
+ int main ()
9
+ {
10
+ int x , y ;
11
+ foo (& x , & y );
12
+
13
+ return 0 ;
14
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=10$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION FAILED$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported in the case where multiple
11
+ variables are being assgned by the function under test. By using the
12
+ --enforce-all-contracts flag, the post-condition (which contains the ghost
13
+ variable) is asserted. In this case, this assertion should fail.
Original file line number Diff line number Diff line change
1
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_requires (* x != 3 )
2
+ __CPROVER_ensures (* x == * x_ + 5 && * x != 8 )
3
+ {
4
+ int * x_ = 3 ;
5
+ * x = * x + 5 ;
6
+ }
7
+
8
+ int main ()
9
+ {
10
+ int n ;
11
+ foo (& n );
12
+
13
+ return 0 ;
14
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks ensures that the declaration of a new variable (in the
11
+ function-under-test) with the same name as the ghost variable does not
12
+ interfere with the ghost variable handling. For this test, we use the
13
+ --enforce-all-contracts flag. As a result, the post-condition is asserted,
14
+ and is expected to pass.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+
3
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_ensures (* x == * x_ + 5 )
4
+ {
5
+ assert (* x_ == * x );
6
+ * x = * x + 5 ;
7
+ }
8
+
9
+ int main ()
10
+ {
11
+ int n ;
12
+ foo (& n );
13
+
14
+ return 0 ;
15
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --enforce-all-contracts
4
+ ^EXIT=1$
5
+ ^SIGNAL=0$
6
+ ^CONVERSION ERROR$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are not supported when referred to from
11
+ a function body. In such a case, the program should not parse and there
12
+ should be a conversion error.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+
3
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_requires (* x > 0 )
4
+ __CPROVER_ensures (* x == * x_ + 2 )
5
+ {
6
+ * x = * x + 2 ;
7
+ }
8
+
9
+ int main ()
10
+ {
11
+ int n ;
12
+ __CPROVER_assume (n > 0 && n < __INT_MAX__ - 2 );
13
+ foo (& n );
14
+
15
+ assert (n > 2 );
16
+
17
+ return 0 ;
18
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --replace-all-calls-with-contracts
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported with the use of the
11
+ --replace-all-calls-with-contracts flag. In this case, the post-condition
12
+ (which contains the ghost variable) becomes an assumption. We then manually
13
+ assert this assumption. For this test, the assertion should succeed.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+
3
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_requires (* x == 0 )
4
+ __CPROVER_ensures (* x > * x_ + 2 )
5
+ {
6
+ * x = * x + 2 ;
7
+ }
8
+
9
+ int main ()
10
+ {
11
+ int n = 0 ;
12
+ foo (& n );
13
+
14
+ assert (n > 2 );
15
+
16
+ return 0 ;
17
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --replace-all-calls-with-contracts
4
+ ^EXIT=0$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION SUCCESSFUL$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables are supported with the use of the
11
+ --replace-all-calls-with-contracts flag. In this case, the post-condition
12
+ (which contains the ghost variable) becomes an assumption. We then manually
13
+ assert this assumption. For this test, the assertion should succeed.
Original file line number Diff line number Diff line change
1
+ #include <assert.h>
2
+
3
+ void foo (int * x ) __CPROVER_assigns (* x ) __CPROVER_requires (* x != * x_ )
4
+ __CPROVER_ensures (* x == * x_ + 2 )
5
+ {
6
+ * x = * x + 2 ;
7
+ }
8
+
9
+ int main ()
10
+ {
11
+ int n = 0 ;
12
+ foo (& n );
13
+
14
+ assert (n == 2 );
15
+
16
+ return 0 ;
17
+ }
Original file line number Diff line number Diff line change
1
+ CORE
2
+ main.c
3
+ --replace-all-calls-with-contracts
4
+ ^EXIT=10$
5
+ ^SIGNAL=0$
6
+ ^VERIFICATION FAILED$
7
+ --
8
+ --
9
+ Verification:
10
+ This test checks that ghost variables may be used as part of the
11
+ pre-condition contract, while keeping their usual semantic meaning.
12
+ For this test, we use the --replace-all-calls-with-contracts flag, which
13
+ asserts the pre-condition. In this case, the assertion is expected to fail.
Original file line number Diff line number Diff line change @@ -142,6 +142,24 @@ void ansi_c_parsert::add_declarator(
142
142
current_scope ().prefix +id2string (base_name);
143
143
new_declarator.set_name (prefixed_name);
144
144
145
+ // For every parameter...
146
+ if (is_parameter)
147
+ {
148
+ // 1. create a new identifier that corresponds to the ghost variable.
149
+ ansi_c_identifiert ghost_identifier = scope.name_map [base_name];
150
+ ghost_identifier.id_class = id_class;
151
+
152
+ irep_idt ghost_prefixed_name =
153
+ current_scope ().prefix + id2string (base_name) + " _" ;
154
+ ghost_identifier.prefixed_name = ghost_prefixed_name;
155
+
156
+ // 2. Add the new ghost variable identifier to the name map
157
+ // Note that the "ghost_base_name" irep corresponds to the
158
+ // ghost variable syntax.
159
+ irep_idt ghost_base_name = id2string (base_name) + " _" ;
160
+ scope.name_map [ghost_base_name] = ghost_identifier;
161
+ }
162
+
145
163
// add to scope
146
164
ansi_c_identifiert &identifier=scope.name_map [base_name];
147
165
identifier.id_class =id_class;
Original file line number Diff line number Diff line change @@ -540,6 +540,23 @@ void c_typecheck_baset::typecheck_function_body(symbolt &symbol)
540
540
541
541
symbolt *new_p_symbol;
542
542
move_symbol (p_symbol, new_p_symbol);
543
+
544
+ // Handling ghost variables...
545
+
546
+ // 1. Produce a symbol for the ghost variable corresponding to the
547
+ // parameter.
548
+ irep_idt identifier_ghost =
549
+ id2string (symbol.name ) + " ::" + id2string (base_name) + " _" ;
550
+
551
+ parameter_symbolt p_symbol_ghost;
552
+ p_symbol_ghost.type = p.type ();
553
+ p_symbol_ghost.name = identifier_ghost;
554
+ p_symbol_ghost.base_name = base_name;
555
+ p_symbol_ghost.location = p.source_location ();
556
+
557
+ // 2. Add the ghost variable symbol to the symbol table.
558
+ symbolt *new_p_symbol_ghost;
559
+ move_symbol (p_symbol_ghost, new_p_symbol_ghost);
543
560
}
544
561
545
562
// typecheck the body code
You can’t perform that action at this time.
0 commit comments