Skip to content

Commit b5b5850

Browse files
committed
Add recursive nondet struct initialization
1 parent a159a67 commit b5b5850

File tree

3 files changed

+52
-7
lines changed

3 files changed

+52
-7
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 & 5 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>
@@ -31,6 +33,8 @@ class symbol_factoryt
3133
namespacet ns;
3234
const c_object_factory_parameterst &object_factory_params;
3335

36+
typedef std::set<irep_idt> recursion_sett;
37+
3438
const symbolt &c_new_tmp_symbol(
3539
const typet &type,
3640
const bool static_lifetime,
@@ -57,7 +61,11 @@ class symbol_factoryt
5761
const typet &allocate_type,
5862
const bool static_lifetime);
5963

60-
void gen_nondet_init(code_blockt &assignments, const exprt &expr);
64+
void gen_nondet_init(
65+
code_blockt &assignments,
66+
const exprt &expr,
67+
const std::size_t depth = 0,
68+
recursion_sett recursion_set = recursion_sett());
6169
};
6270

6371
/// Create a new temporary static symbol
@@ -121,9 +129,13 @@ exprt symbol_factoryt::allocate_object(
121129
/// \param assignments: The code block to add code to
122130
/// \param expr: The expression which we are generating a non-determinate value
123131
/// for
132+
/// \param depth number of pointers followed so far during initialisation
133+
/// \param recursion_set names of structs seen so far on current pointer chain
124134
void symbol_factoryt::gen_nondet_init(
125135
code_blockt &assignments,
126-
const exprt &expr)
136+
const exprt &expr,
137+
const std::size_t depth,
138+
recursion_sett recursion_set)
127139
{
128140
const typet &type=ns.follow(expr.type());
129141

@@ -133,6 +145,22 @@ void symbol_factoryt::gen_nondet_init(
133145
const pointer_typet &pointer_type=to_pointer_type(type);
134146
const typet &subtype=ns.follow(pointer_type.subtype());
135147

148+
if(subtype.id() == ID_struct)
149+
{
150+
const struct_typet &struct_type = to_struct_type(subtype);
151+
const irep_idt struct_tag = struct_type.get_tag();
152+
153+
if(
154+
recursion_set.find(struct_tag) != recursion_set.end() &&
155+
depth >= object_factory_params.max_nondet_tree_depth)
156+
{
157+
code_assignt c(expr, null_pointer_exprt(pointer_type));
158+
assignments.move(c);
159+
160+
return;
161+
}
162+
}
163+
136164
code_blockt non_null_inst;
137165

138166
exprt allocated=allocate_object(non_null_inst, expr, subtype, false);
@@ -146,7 +174,7 @@ void symbol_factoryt::gen_nondet_init(
146174
{
147175
init_expr=dereference_exprt(allocated, allocated.type().subtype());
148176
}
149-
gen_nondet_init(non_null_inst, init_expr);
177+
gen_nondet_init(non_null_inst, init_expr, depth + 1, recursion_set);
150178

151179
if(assume_non_null)
152180
{
@@ -175,7 +203,25 @@ void symbol_factoryt::gen_nondet_init(
175203
assignments.move(null_check);
176204
}
177205
}
178-
// TODO(OJones): Add support for structs and arrays
206+
else if(type.id() == ID_struct)
207+
{
208+
const struct_typet &struct_type = to_struct_type(type);
209+
210+
const irep_idt struct_tag = struct_type.get_tag();
211+
212+
recursion_set.insert(struct_tag);
213+
214+
for(const auto &component : struct_type.components())
215+
{
216+
const typet &component_type = component.type();
217+
const irep_idt name = component.get_name();
218+
219+
member_exprt me(expr, name, component_type);
220+
me.add_source_location() = loc;
221+
222+
gen_nondet_init(assignments, me, depth, recursion_set);
223+
}
224+
}
179225
else
180226
{
181227
// If type is a ID_c_bool then add the following code to assignments:
@@ -207,7 +253,6 @@ exprt c_nondet_symbol_factory(
207253
const irep_idt base_name,
208254
const typet &type,
209255
const source_locationt &loc,
210-
bool allow_null,
211256
const c_object_factory_parameterst &object_factory_parameters)
212257
{
213258
irep_idt identifier=id2string(goto_functionst::entry_point())+
@@ -230,6 +275,8 @@ exprt c_nondet_symbol_factory(
230275
std::vector<const symbolt *> symbols_created;
231276
symbols_created.push_back(main_symbol_ptr);
232277

278+
const bool allow_null = (object_factory_parameters.min_null_tree_depth == 0);
279+
233280
symbol_factoryt state(
234281
symbols_created, symbol_table, loc, !allow_null, object_factory_parameters);
235282
code_blockt assignments;

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 @@ 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)