Skip to content

Commit a0be06a

Browse files
committed
Add recursive nondet struct initialization
1 parent e8d9a16 commit a0be06a

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
public:
3539
symbol_factoryt(
3640
std::vector<const symbolt *> &_symbols_created,
@@ -52,7 +56,11 @@ class symbol_factoryt
5256
const typet &allocate_type,
5357
const bool static_lifetime);
5458

55-
void gen_nondet_init(code_blockt &assignments, const exprt &expr);
59+
void gen_nondet_init(
60+
code_blockt &assignments,
61+
const exprt &expr,
62+
const std::size_t depth = 0,
63+
recursion_sett recursion_set = recursion_sett());
5664
};
5765

5866
/// Create a symbol for a pointer to point to
@@ -103,9 +111,13 @@ exprt symbol_factoryt::allocate_object(
103111
/// \param assignments: The code block to add code to
104112
/// \param expr: The expression which we are generating a non-determinate value
105113
/// for
114+
/// \param depth number of pointers followed so far during initialisation
115+
/// \param recursion_set names of structs seen so far on current pointer chain
106116
void symbol_factoryt::gen_nondet_init(
107117
code_blockt &assignments,
108-
const exprt &expr)
118+
const exprt &expr,
119+
const std::size_t depth,
120+
recursion_sett recursion_set)
109121
{
110122
const typet &type=ns.follow(expr.type());
111123

@@ -115,6 +127,22 @@ void symbol_factoryt::gen_nondet_init(
115127
const pointer_typet &pointer_type=to_pointer_type(type);
116128
const typet &subtype=ns.follow(pointer_type.subtype());
117129

130+
if(subtype.id() == ID_struct)
131+
{
132+
const struct_typet &struct_type = to_struct_type(subtype);
133+
const irep_idt struct_tag = struct_type.get_tag();
134+
135+
if(
136+
recursion_set.find(struct_tag) != recursion_set.end() &&
137+
depth >= object_factory_params.max_nondet_tree_depth)
138+
{
139+
code_assignt c(expr, null_pointer_exprt(pointer_type));
140+
assignments.move(c);
141+
142+
return;
143+
}
144+
}
145+
118146
code_blockt non_null_inst;
119147

120148
exprt allocated=allocate_object(non_null_inst, expr, subtype, false);
@@ -128,7 +156,7 @@ void symbol_factoryt::gen_nondet_init(
128156
{
129157
init_expr=dereference_exprt(allocated, allocated.type().subtype());
130158
}
131-
gen_nondet_init(non_null_inst, init_expr);
159+
gen_nondet_init(non_null_inst, init_expr, depth + 1, recursion_set);
132160

133161
if(assume_non_null)
134162
{
@@ -157,7 +185,25 @@ void symbol_factoryt::gen_nondet_init(
157185
assignments.move(null_check);
158186
}
159187
}
160-
// TODO(OJones): Add support for structs and arrays
188+
else if(type.id() == ID_struct)
189+
{
190+
const struct_typet &struct_type = to_struct_type(type);
191+
192+
const irep_idt struct_tag = struct_type.get_tag();
193+
194+
recursion_set.insert(struct_tag);
195+
196+
for(const auto &component : struct_type.components())
197+
{
198+
const typet &component_type = component.type();
199+
const irep_idt name = component.get_name();
200+
201+
member_exprt me(expr, name, component_type);
202+
me.add_source_location() = loc;
203+
204+
gen_nondet_init(assignments, me, depth, recursion_set);
205+
}
206+
}
161207
else
162208
{
163209
// If type is a ID_c_bool then add the following code to assignments:
@@ -189,7 +235,6 @@ exprt c_nondet_symbol_factory(
189235
const irep_idt base_name,
190236
const typet &type,
191237
const source_locationt &loc,
192-
bool allow_null,
193238
const c_object_factory_parameterst &object_factory_parameters)
194239
{
195240
irep_idt identifier=id2string(goto_functionst::entry_point())+
@@ -212,6 +257,8 @@ exprt c_nondet_symbol_factory(
212257
std::vector<const symbolt *> symbols_created;
213258
symbols_created.push_back(main_symbol_ptr);
214259

260+
const bool allow_null = (object_factory_parameters.min_null_tree_depth == 0);
261+
215262
symbol_factoryt state(
216263
symbols_created, symbol_table, loc, !allow_null, object_factory_parameters);
217264
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)