@@ -11,6 +11,8 @@ Author: Diffblue Ltd.
11
11
12
12
#include " c_nondet_symbol_factory.h"
13
13
14
+ #include < ansi-c/c_object_factory_parameters.h>
15
+
14
16
#include < util/arith_tools.h>
15
17
#include < util/c_types.h>
16
18
#include < util/fresh_symbol.h>
@@ -31,6 +33,8 @@ class symbol_factoryt
31
33
namespacet ns;
32
34
const c_object_factory_parameterst &object_factory_params;
33
35
36
+ typedef std::set<irep_idt> recursion_sett;
37
+
34
38
const symbolt &c_new_tmp_symbol (
35
39
// symbol_tablet &symbol_table,
36
40
// const source_locationt &loc,
@@ -59,7 +63,11 @@ class symbol_factoryt
59
63
const typet &allocate_type,
60
64
const bool static_lifetime);
61
65
62
- void gen_nondet_init (code_blockt &assignments, const exprt &expr);
66
+ void gen_nondet_init (
67
+ code_blockt &assignments,
68
+ const exprt &expr,
69
+ const std::size_t depth = 0 ,
70
+ recursion_sett recursion_set = recursion_sett());
63
71
};
64
72
65
73
// / Create a new temporary static symbol
@@ -129,7 +137,9 @@ exprt symbol_factoryt::allocate_object(
129
137
// / for
130
138
void symbol_factoryt::gen_nondet_init (
131
139
code_blockt &assignments,
132
- const exprt &expr)
140
+ const exprt &expr,
141
+ const std::size_t depth,
142
+ recursion_sett recursion_set)
133
143
{
134
144
const typet &type=ns.follow (expr.type ());
135
145
@@ -139,6 +149,22 @@ void symbol_factoryt::gen_nondet_init(
139
149
const pointer_typet &pointer_type=to_pointer_type (type);
140
150
const typet &subtype=ns.follow (pointer_type.subtype ());
141
151
152
+ if (subtype.id () == ID_struct)
153
+ {
154
+ const struct_typet &struct_type = to_struct_type (subtype);
155
+ const irep_idt struct_tag = struct_type.get_tag ();
156
+
157
+ if (
158
+ recursion_set.find (struct_tag) != recursion_set.end () &&
159
+ depth >= object_factory_params.max_nondet_tree_depth )
160
+ {
161
+ code_assignt c (expr, null_pointer_exprt (pointer_type));
162
+ assignments.move (c);
163
+
164
+ return ;
165
+ }
166
+ }
167
+
142
168
code_blockt non_null_inst;
143
169
144
170
exprt allocated=allocate_object (non_null_inst, expr, subtype, false );
@@ -152,7 +178,7 @@ void symbol_factoryt::gen_nondet_init(
152
178
{
153
179
init_expr=dereference_exprt (allocated, allocated.type ().subtype ());
154
180
}
155
- gen_nondet_init (non_null_inst, init_expr);
181
+ gen_nondet_init (non_null_inst, init_expr, depth + 1 , recursion_set );
156
182
157
183
if (assume_non_null)
158
184
{
@@ -181,7 +207,25 @@ void symbol_factoryt::gen_nondet_init(
181
207
assignments.move (null_check);
182
208
}
183
209
}
184
- // TODO(OJones): Add support for structs and arrays
210
+ else if (type.id () == ID_struct)
211
+ {
212
+ const struct_typet &struct_type = to_struct_type (type);
213
+
214
+ const irep_idt struct_tag = struct_type.get_tag ();
215
+
216
+ recursion_set.insert (struct_tag);
217
+
218
+ for (const auto &component : struct_type.components ())
219
+ {
220
+ const typet &component_type = component.type ();
221
+ const irep_idt name = component.get_name ();
222
+
223
+ member_exprt me (expr, name, component_type);
224
+ me.add_source_location () = loc;
225
+
226
+ gen_nondet_init (assignments, me, depth, recursion_set);
227
+ }
228
+ }
185
229
else
186
230
{
187
231
// If type is a ID_c_bool then add the following code to assignments:
@@ -213,7 +257,6 @@ exprt c_nondet_symbol_factory(
213
257
const irep_idt base_name,
214
258
const typet &type,
215
259
const source_locationt &loc,
216
- bool allow_null,
217
260
const c_object_factory_parameterst &object_factory_parameters)
218
261
{
219
262
irep_idt identifier=id2string (goto_functionst::entry_point ())+
@@ -236,6 +279,8 @@ exprt c_nondet_symbol_factory(
236
279
std::vector<const symbolt *> symbols_created;
237
280
symbols_created.push_back (main_symbol_ptr);
238
281
282
+ const bool allow_null = (object_factory_parameters.min_null_tree_depth == 0 );
283
+
239
284
symbol_factoryt state (
240
285
symbols_created, symbol_table, loc, !allow_null, object_factory_parameters);
241
286
code_blockt assignments;
0 commit comments