@@ -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>
@@ -27,21 +29,20 @@ class symbol_factoryt
27
29
std::vector<const symbolt *> &symbols_created;
28
30
symbol_tablet &symbol_table;
29
31
const source_locationt &loc;
30
- const bool assume_non_null;
31
32
namespacet ns;
32
33
const c_object_factory_parameterst &object_factory_params;
33
34
35
+ typedef std::set<irep_idt> recursion_sett;
36
+
34
37
public:
35
38
symbol_factoryt (
36
39
std::vector<const symbolt *> &_symbols_created,
37
40
symbol_tablet &_symbol_table,
38
41
const source_locationt &loc,
39
- const bool _assume_non_null,
40
42
const c_object_factory_parameterst &object_factory_params)
41
43
: symbols_created(_symbols_created),
42
44
symbol_table (_symbol_table),
43
45
loc(loc),
44
- assume_non_null(_assume_non_null),
45
46
ns(_symbol_table),
46
47
object_factory_params(object_factory_params)
47
48
{}
@@ -52,7 +53,11 @@ class symbol_factoryt
52
53
const typet &allocate_type,
53
54
const bool static_lifetime);
54
55
55
- void gen_nondet_init (code_blockt &assignments, const exprt &expr);
56
+ void gen_nondet_init (
57
+ code_blockt &assignments,
58
+ const exprt &expr,
59
+ const std::size_t depth = 0 ,
60
+ recursion_sett recursion_set = recursion_sett());
56
61
};
57
62
58
63
// / Create a symbol for a pointer to point to
@@ -103,9 +108,13 @@ exprt symbol_factoryt::allocate_object(
103
108
// / \param assignments: The code block to add code to
104
109
// / \param expr: The expression which we are generating a non-determinate value
105
110
// / for
111
+ // / \param depth number of pointers followed so far during initialisation
112
+ // / \param recursion_set names of structs seen so far on current pointer chain
106
113
void symbol_factoryt::gen_nondet_init (
107
114
code_blockt &assignments,
108
- const exprt &expr)
115
+ const exprt &expr,
116
+ const std::size_t depth,
117
+ recursion_sett recursion_set)
109
118
{
110
119
const typet &type=ns.follow (expr.type ());
111
120
@@ -115,6 +124,22 @@ void symbol_factoryt::gen_nondet_init(
115
124
const pointer_typet &pointer_type=to_pointer_type (type);
116
125
const typet &subtype=ns.follow (pointer_type.subtype ());
117
126
127
+ if (subtype.id () == ID_struct)
128
+ {
129
+ const struct_typet &struct_type = to_struct_type (subtype);
130
+ const irep_idt struct_tag = struct_type.get_tag ();
131
+
132
+ if (
133
+ recursion_set.find (struct_tag) != recursion_set.end () &&
134
+ depth >= object_factory_params.max_nondet_tree_depth )
135
+ {
136
+ code_assignt c (expr, null_pointer_exprt (pointer_type));
137
+ assignments.add (std::move (c));
138
+
139
+ return ;
140
+ }
141
+ }
142
+
118
143
code_blockt non_null_inst;
119
144
120
145
exprt allocated=allocate_object (non_null_inst, expr, subtype, false );
@@ -128,9 +153,9 @@ void symbol_factoryt::gen_nondet_init(
128
153
{
129
154
init_expr=dereference_exprt (allocated, allocated.type ().subtype ());
130
155
}
131
- gen_nondet_init (non_null_inst, init_expr);
156
+ gen_nondet_init (non_null_inst, init_expr, depth + 1 , recursion_set );
132
157
133
- if (assume_non_null )
158
+ if (depth < object_factory_params. min_null_tree_depth )
134
159
{
135
160
// Add the following code to assignments:
136
161
// <expr> = <aoe>;
@@ -157,7 +182,25 @@ void symbol_factoryt::gen_nondet_init(
157
182
assignments.add (std::move (null_check));
158
183
}
159
184
}
160
- // TODO(OJones): Add support for structs and arrays
185
+ else if (type.id () == ID_struct)
186
+ {
187
+ const struct_typet &struct_type = to_struct_type (type);
188
+
189
+ const irep_idt struct_tag = struct_type.get_tag ();
190
+
191
+ recursion_set.insert (struct_tag);
192
+
193
+ for (const auto &component : struct_type.components ())
194
+ {
195
+ const typet &component_type = component.type ();
196
+ const irep_idt name = component.get_name ();
197
+
198
+ member_exprt me (expr, name, component_type);
199
+ me.add_source_location () = loc;
200
+
201
+ gen_nondet_init (assignments, me, depth, recursion_set);
202
+ }
203
+ }
161
204
else
162
205
{
163
206
// If type is a ID_c_bool then add the following code to assignments:
@@ -181,7 +224,6 @@ void symbol_factoryt::gen_nondet_init(
181
224
// / \param base_name: The name to use for the symbol created
182
225
// / \param type: The type for the symbol created
183
226
// / \param loc: The location to assign to generated code
184
- // / \param allow_null: Whether to allow a null value when type is a pointer
185
227
// / \param object_factory_parameters configuration parameters for the object
186
228
// / factory
187
229
// / \return Returns the symbol_exprt for the symbol created
@@ -191,7 +233,6 @@ symbol_exprt c_nondet_symbol_factory(
191
233
const irep_idt base_name,
192
234
const typet &type,
193
235
const source_locationt &loc,
194
- bool allow_null,
195
236
const c_object_factory_parameterst &object_factory_parameters)
196
237
{
197
238
irep_idt identifier=id2string (goto_functionst::entry_point ())+
@@ -215,7 +256,7 @@ symbol_exprt c_nondet_symbol_factory(
215
256
symbols_created.push_back (main_symbol_ptr);
216
257
217
258
symbol_factoryt state (
218
- symbols_created, symbol_table, loc, !allow_null, object_factory_parameters);
259
+ symbols_created, symbol_table, loc, object_factory_parameters);
219
260
code_blockt assignments;
220
261
state.gen_nondet_init (assignments, main_symbol_expr);
221
262
0 commit comments