Skip to content

Commit 695a360

Browse files
authored
Merge pull request #5409 from hannes-steffenhagen-diffblue/fix/do_not_use_side_effect_expr_nondett_in_goto_harness
Do not use side_effect_expr_nondett in recursive_initialization
2 parents 9e0c78e + 430ab00 commit 695a360

File tree

8 files changed

+87
-48
lines changed

8 files changed

+87
-48
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <assert.h>
2+
3+
void test_function(int test)
4+
{
5+
assert(test != 42);
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
test.c
3+
--function test_function --harness-type call-function
4+
\[test_function\.assertion\.1\] line \d+ assertion test != 42
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
nondet_signed_int
9+
--
10+
If we use side_effect_expr_nondett then dump_c will generation function calls
11+
to functions with names like nondet_signed_int without declaration.
12+
This can cause problems around usability.
13+
14+
To fix this, we changed goto-harness to just not use side_effect_expr_nondett
15+
at all.
16+
17+
This test tests for the absence the use for these things.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct linked_list
2+
{
3+
struct linked_list *next;
4+
};
5+
6+
void test(struct linked_list *list)
7+
{
8+
assert(list);
9+
assert(list->next);
10+
assert(!list->next);
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
test.c
3+
--function test --harness-type call-function
4+
\[test.assertion.1\] line \d+ assertion list: SUCCESS
5+
\[test.assertion.2\] line \d+ assertion list->next: FAILURE
6+
\[test.assertion.3\] line \d+ assertion !\(list->next != \(\(struct linked_list \*\).*\)\): FAILURE
7+
should_recurse_nondet
8+
^EXIT=10$
9+
^SIGNAL=0$
10+
--
11+
__CPROVER_nondet_bool
12+
--
13+
This is to check that we use the new mechanism to decide whether we should recurse
14+
non-deterministically (i.e. without using side_effect_expr_nondett).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
void test(int *x, int *y)
2+
{
3+
assert(x);
4+
assert(y);
5+
assert(x == y);
6+
assert(x != y);
7+
assert(*x == *y);
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
CORE
2+
test.c
3+
--function test --harness-type call-function --treat-pointers-equal x,y --treat-pointers-equal-maybe
4+
should_make_equal
5+
\[test.assertion.1\] line 3 assertion x: SUCCESS
6+
\[test.assertion.2\] line 4 assertion y: SUCCESS
7+
\[test.assertion.3\] line 5 assertion x == y: FAILURE
8+
\[test.assertion.4\] line 6 assertion x != y: FAILURE
9+
\[test.assertion.5\] line 7 assertion \*x == \*y: FAILURE
10+
^EXIT=10$
11+
^SIGNAL=0$
12+
--
13+
__CPROVER_nondet_bool
14+
--
15+
We are no longer using side_effect_expr_nondett for nondet primitives,
16+
specifically this is testing that we are using a variable called some variation
17+
of “should_make_equal” (plus some optional postfix) as the condition variable
18+
that assigns the same destination to pointers.

src/goto-harness/recursive_initialization.cpp

+13-43
Original file line numberDiff line numberDiff line change
@@ -169,11 +169,11 @@ void recursive_initializationt::initialize(
169169
goto_model.symbol_table.lookup_ref(fun_name);
170170
const auto proper_init_case = code_function_callt{
171171
fun_symbol.symbol_expr(), {depth, address_of_exprt{lhs}}};
172-
172+
const auto should_make_equal =
173+
get_fresh_local_typed_symexpr("should_make_equal", bool_typet{});
174+
body.add(code_declt{should_make_equal});
173175
body.add(code_ifthenelset{
174-
side_effect_expr_nondett{bool_typet{}, source_locationt{}},
175-
set_equal_case,
176-
proper_init_case});
176+
should_make_equal, set_equal_case, proper_init_case});
177177
}
178178
else
179179
{
@@ -265,9 +265,7 @@ code_blockt recursive_initializationt::build_constructor_body(
265265
}
266266
if(lhs_name.has_value())
267267
{
268-
if(should_be_treated_as_cstring(*lhs_name) && type == char_type())
269-
return build_array_string_constructor(result_symbol);
270-
else if(should_be_treated_as_array(*lhs_name))
268+
if(should_be_treated_as_array(*lhs_name))
271269
{
272270
CHECK_RETURN(size_symbol.has_value());
273271
return build_dynamic_array_constructor(
@@ -693,9 +691,12 @@ code_blockt recursive_initializationt::build_pointer_constructor(
693691
code_blockt null_and_return{{assign_null, code_returnt{}}};
694692
body.add(code_ifthenelset{conjunction(should_not_recurse), null_and_return});
695693

694+
const auto should_recurse_nondet =
695+
get_fresh_local_typed_symexpr("should_recurse_nondet", bool_typet{});
696+
body.add(code_declt{should_recurse_nondet});
696697
exprt::operandst should_recurse_ops{
697698
binary_predicate_exprt{depth, ID_lt, get_symbol_expr(min_depth_var_name)},
698-
side_effect_expr_nondett{bool_typet{}, source_locationt{}}};
699+
should_recurse_nondet};
699700
code_blockt then_case{};
700701

701702
code_assignt seen_assign_prev{};
@@ -737,34 +738,6 @@ code_blockt recursive_initializationt::build_pointer_constructor(
737738
return body;
738739
}
739740

740-
code_blockt recursive_initializationt::build_array_string_constructor(
741-
const symbol_exprt &result) const
742-
{
743-
PRECONDITION(result.type().id() == ID_pointer);
744-
const typet &type = result.type().subtype();
745-
PRECONDITION(type.id() == ID_array);
746-
PRECONDITION(type.subtype() == char_type());
747-
const array_typet &array_type = to_array_type(type);
748-
const auto array_size =
749-
numeric_cast_v<std::size_t>(to_constant_expr(array_type.size()));
750-
code_blockt body{};
751-
752-
for(std::size_t index = 0; index < array_size - 1; index++)
753-
{
754-
index_exprt index_expr{dereference_exprt{result},
755-
from_integer(index, size_type())};
756-
body.add(code_assignt{
757-
index_expr, side_effect_expr_nondett{char_type(), source_locationt{}}});
758-
body.add(code_assumet{
759-
notequal_exprt{index_expr, from_integer(0, array_type.subtype())}});
760-
}
761-
body.add(code_assignt{index_exprt{dereference_exprt{result},
762-
from_integer(array_size - 1, size_type())},
763-
from_integer(0, array_type.subtype())});
764-
765-
return body;
766-
}
767-
768741
code_blockt recursive_initializationt::build_array_constructor(
769742
const exprt &depth,
770743
const symbol_exprt &result)
@@ -830,9 +803,10 @@ code_blockt recursive_initializationt::build_nondet_constructor(
830803
{
831804
PRECONDITION(result.type().id() == ID_pointer);
832805
code_blockt body{};
833-
body.add(code_assignt{
834-
dereference_exprt{result},
835-
side_effect_expr_nondett{result.type().subtype(), source_locationt{}}});
806+
auto const nondet_symbol =
807+
get_fresh_local_typed_symexpr("nondet", result.type().subtype());
808+
body.add(code_declt{nondet_symbol});
809+
body.add(code_assignt{dereference_exprt{result}, nondet_symbol});
836810
return body;
837811
}
838812

@@ -1029,10 +1003,6 @@ code_blockt recursive_initializationt::build_function_pointer_constructor(
10291003
const auto function_pointer_selector =
10301004
get_fresh_local_symexpr("function_pointer_selector");
10311005
body.add(code_declt{function_pointer_selector});
1032-
body.add(
1033-
code_assignt{function_pointer_selector,
1034-
side_effect_expr_nondett{function_pointer_selector.type(),
1035-
source_locationt{}}});
10361006
auto function_pointer_index = std::size_t{0};
10371007

10381008
for(const auto &target : targets)

src/goto-harness/recursive_initialization.h

-5
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,6 @@ class recursive_initializationt
262262
const exprt &size,
263263
const optionalt<irep_idt> &lhs_name);
264264

265-
/// Constructor for strings: as array but the last element is zero.
266-
/// \param result: symbol of the result parameter
267-
/// \return the body of the constructor
268-
code_blockt build_array_string_constructor(const symbol_exprt &result) const;
269-
270265
/// Select the specified struct-member to be non-deterministically
271266
/// initialized.
272267
/// \param lhs: symbol expression of the top structure

0 commit comments

Comments
 (0)