Skip to content

Commit 4388a69

Browse files
Merge pull request #3472 from hannes-steffenhagen-diffblue/feature-nondet-array-init
Add nondet initialisation for statically sized arrays
2 parents 6e085d2 + 8b305e0 commit 4388a69

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include <assert.h>
2+
#include <stdlib.h>
3+
4+
typedef struct list_nodet list_nodet;
5+
6+
struct list_nodet
7+
{
8+
int val;
9+
struct list_nodet *next;
10+
};
11+
12+
struct Test
13+
{
14+
list_nodet *lists[4];
15+
};
16+
17+
void test(struct Test Test)
18+
{
19+
// array elements are nondet initialised (min-null-tree-depth is respected)
20+
assert(Test.lists[0]->next);
21+
assert(Test.lists[1]->next);
22+
assert(Test.lists[2]->next);
23+
assert(Test.lists[3]->next);
24+
25+
// array elements are nondet initialised (max-nondet-tree-depth is respected)
26+
assert(!Test.lists[0]->next->next);
27+
assert(!Test.lists[1]->next->next);
28+
assert(!Test.lists[2]->next->next);
29+
assert(!Test.lists[3]->next->next);
30+
31+
// array elements are not all initialised to the same size
32+
assert(Test.lists[0] != Test.lists[1]);
33+
assert(Test.lists[1] != Test.lists[2]);
34+
assert(Test.lists[2] != Test.lists[3]);
35+
36+
assert(!Test.lists[4]);
37+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CORE
2+
test.c
3+
--function test --min-null-tree-depth 2 --max-nondet-tree-depth 2 --bounds-check
4+
\[test.assertion.1\] line \d+ assertion Test.lists\[0\]->next: SUCCESS
5+
\[test.assertion.2\] line \d+ assertion Test.lists\[1\]->next: SUCCESS
6+
\[test.assertion.3\] line \d+ assertion Test.lists\[2\]->next: SUCCESS
7+
\[test.assertion.4\] line \d+ assertion Test.lists\[3\]->next: SUCCESS
8+
\[test.assertion.5\] line \d+ assertion !Test.lists\[0\]->next->next: SUCCESS
9+
\[test.assertion.6\] line \d+ assertion !Test.lists\[1\]->next->next: SUCCESS
10+
\[test.assertion.7\] line \d+ assertion !Test.lists\[2\]->next->next: SUCCESS
11+
\[test.assertion.8\] line \d+ assertion !Test.lists\[3\]->next->next: SUCCESS
12+
\[test.assertion.9\] line \d+ assertion Test.lists\[0\] != Test.lists\[1\]: SUCCESS
13+
\[test.assertion.10\] line \d+ assertion Test.lists\[1\] != Test.lists\[2\]: SUCCESS
14+
\[test.assertion.11\] line \d+ assertion Test.lists\[2\] != Test.lists\[3\]: SUCCESS
15+
\[test.array_bounds.1\] line \d+ array `Test'.lists upper bound in Test.lists\[\(signed long int\)4\]: FAILURE
16+
\[test.assertion.12\] line \d+ assertion !Test.lists\[4\]: FAILURE
17+
--

scripts/delete_failing_smt2_solver_tests

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ rm Typecast1/test.desc
7171
rm Union_Initialization1/test.desc
7272
rm address_space_size_limit1/test.desc
7373
rm address_space_size_limit3/test.desc
74+
rm argv1/test.desc
75+
rm argv1/test.desc
76+
rm array-function-parameters/test.desc
7477
rm array-tests/test.desc
7578
rm bounds_check1/test.desc
7679
rm byte_update2/test.desc

src/ansi-c/c_nondet_symbol_factory.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ class symbol_factoryt
5858
const exprt &expr,
5959
const std::size_t depth = 0,
6060
recursion_sett recursion_set = recursion_sett());
61+
62+
private:
63+
/// Generate initialisation code for each array element
64+
/// \param assignments: The code block to add code to
65+
/// \param expr: An expression of array type
66+
/// \param depth: The struct recursion depth
67+
/// \param recursion_set: The struct recursion set
68+
/// \see gen_nondet_init For the meaning of the last 2 parameters
69+
void gen_nondet_array_init(
70+
code_blockt &assignments,
71+
const exprt &expr,
72+
std::size_t depth,
73+
const recursion_sett &recursion_set);
6174
};
6275

6376
/// Create a symbol for a pointer to point to
@@ -201,6 +214,10 @@ void symbol_factoryt::gen_nondet_init(
201214
gen_nondet_init(assignments, me, depth, recursion_set);
202215
}
203216
}
217+
else if(type.id() == ID_array)
218+
{
219+
gen_nondet_array_init(assignments, expr, depth, recursion_set);
220+
}
204221
else
205222
{
206223
// If type is a ID_c_bool then add the following code to assignments:
@@ -216,6 +233,25 @@ void symbol_factoryt::gen_nondet_init(
216233
}
217234
}
218235

236+
void symbol_factoryt::gen_nondet_array_init(
237+
code_blockt &assignments,
238+
const exprt &expr,
239+
std::size_t depth,
240+
const recursion_sett &recursion_set)
241+
{
242+
auto const &array_type = to_array_type(expr.type());
243+
auto const array_size = numeric_cast_v<size_t>(array_type.size());
244+
DATA_INVARIANT(array_size > 0, "Arrays should have positive size");
245+
for(size_t index = 0; index < array_size; ++index)
246+
{
247+
gen_nondet_init(
248+
assignments,
249+
index_exprt(expr, from_integer(index, size_type())),
250+
depth,
251+
recursion_set);
252+
}
253+
}
254+
219255
/// Creates a symbol and generates code so that it can vary over all possible
220256
/// values for its type. For pointers this involves allocating symbols which it
221257
/// can point to.

0 commit comments

Comments
 (0)