Skip to content

Commit f0fd538

Browse files
committed
Add recursive nondet struct initialization
1 parent 7126e7c commit f0fd538

File tree

3 files changed

+52
-13
lines changed

3 files changed

+52
-13
lines changed

src/ansi-c/ansi_c_entry_point.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ exprt::operandst build_function_environment(
4242
base_name,
4343
p.type(),
4444
p.source_location(),
45-
true,
4645
object_factory_parameters);
4746
}
4847

src/ansi-c/c_nondet_symbol_factory.cpp

Lines changed: 52 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Author: Diffblue Ltd.
1111

1212
#include "c_nondet_symbol_factory.h"
1313

14+
#include <ansi-c/c_object_factory_parameters.h>
15+
1416
#include <util/arith_tools.h>
1517
#include <util/c_types.h>
1618
#include <util/fresh_symbol.h>
@@ -27,21 +29,20 @@ class symbol_factoryt
2729
std::vector<const symbolt *> &symbols_created;
2830
symbol_tablet &symbol_table;
2931
const source_locationt &loc;
30-
const bool assume_non_null;
3132
namespacet ns;
3233
const c_object_factory_parameterst &object_factory_params;
3334

35+
typedef std::set<irep_idt> recursion_sett;
36+
3437
public:
3538
symbol_factoryt(
3639
std::vector<const symbolt *> &_symbols_created,
3740
symbol_tablet &_symbol_table,
3841
const source_locationt &loc,
39-
const bool _assume_non_null,
4042
const c_object_factory_parameterst &object_factory_params)
4143
: symbols_created(_symbols_created),
4244
symbol_table(_symbol_table),
4345
loc(loc),
44-
assume_non_null(_assume_non_null),
4546
ns(_symbol_table),
4647
object_factory_params(object_factory_params)
4748
{}
@@ -52,7 +53,11 @@ class symbol_factoryt
5253
const typet &allocate_type,
5354
const bool static_lifetime);
5455

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());
5661
};
5762

5863
/// Create a symbol for a pointer to point to
@@ -103,9 +108,13 @@ exprt symbol_factoryt::allocate_object(
103108
/// \param assignments: The code block to add code to
104109
/// \param expr: The expression which we are generating a non-determinate value
105110
/// 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
106113
void symbol_factoryt::gen_nondet_init(
107114
code_blockt &assignments,
108-
const exprt &expr)
115+
const exprt &expr,
116+
const std::size_t depth,
117+
recursion_sett recursion_set)
109118
{
110119
const typet &type=ns.follow(expr.type());
111120

@@ -115,6 +124,22 @@ void symbol_factoryt::gen_nondet_init(
115124
const pointer_typet &pointer_type=to_pointer_type(type);
116125
const typet &subtype=ns.follow(pointer_type.subtype());
117126

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+
118143
code_blockt non_null_inst;
119144

120145
exprt allocated=allocate_object(non_null_inst, expr, subtype, false);
@@ -128,9 +153,9 @@ void symbol_factoryt::gen_nondet_init(
128153
{
129154
init_expr=dereference_exprt(allocated, allocated.type().subtype());
130155
}
131-
gen_nondet_init(non_null_inst, init_expr);
156+
gen_nondet_init(non_null_inst, init_expr, depth + 1, recursion_set);
132157

133-
if(assume_non_null)
158+
if(depth < object_factory_params.min_null_tree_depth)
134159
{
135160
// Add the following code to assignments:
136161
// <expr> = <aoe>;
@@ -157,7 +182,25 @@ void symbol_factoryt::gen_nondet_init(
157182
assignments.add(std::move(null_check));
158183
}
159184
}
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+
}
161204
else
162205
{
163206
// If type is a ID_c_bool then add the following code to assignments:
@@ -181,7 +224,6 @@ void symbol_factoryt::gen_nondet_init(
181224
/// \param base_name: The name to use for the symbol created
182225
/// \param type: The type for the symbol created
183226
/// \param loc: The location to assign to generated code
184-
/// \param allow_null: Whether to allow a null value when type is a pointer
185227
/// \param object_factory_parameters configuration parameters for the object
186228
/// factory
187229
/// \return Returns the symbol_exprt for the symbol created
@@ -191,7 +233,6 @@ symbol_exprt c_nondet_symbol_factory(
191233
const irep_idt base_name,
192234
const typet &type,
193235
const source_locationt &loc,
194-
bool allow_null,
195236
const c_object_factory_parameterst &object_factory_parameters)
196237
{
197238
irep_idt identifier=id2string(goto_functionst::entry_point())+
@@ -215,7 +256,7 @@ symbol_exprt c_nondet_symbol_factory(
215256
symbols_created.push_back(main_symbol_ptr);
216257

217258
symbol_factoryt state(
218-
symbols_created, symbol_table, loc, !allow_null, object_factory_parameters);
259+
symbols_created, symbol_table, loc, object_factory_parameters);
219260
code_blockt assignments;
220261
state.gen_nondet_init(assignments, main_symbol_expr);
221262

src/ansi-c/c_nondet_symbol_factory.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ symbol_exprt c_nondet_symbol_factory(
2323
const irep_idt base_name,
2424
const typet &type,
2525
const source_locationt &,
26-
bool allow_null,
2726
const c_object_factory_parameterst &object_factory_parameters);
2827

2928
#endif // CPROVER_ANSI_C_C_NONDET_SYMBOL_FACTORY_H

0 commit comments

Comments
 (0)