Skip to content

Commit 3e4701a

Browse files
committed
Adapt c nondet symbol factory for use in function body generation
We essentially make two changes to the c nondet symbol factory: - A parameter assign_const is added to gen_nondet_init(). When false, an object of const type is not nondet assigned. This will be used in the function body generation feature to not havoc const arguments (e.g., the targets of pointers to const int) - A parameter lifetime (an enum of type lifetimet) is added to the constructor of symbol_factoryt. It indicates whether it uses lifetimet::AUTOMATIC_LOCAL, lifetimet::STATIC_GLOBAL, or lifetimet::DYNAMIC when allocating new objects with allocate_object(). Previously this was hardcoded to behave like lifetime::AUTOMATIC_LOCAL. However, in the function body generation we need to add code to a function to allocate dynamic objects. This is because the function may be called multiple times, hence using local or global variables does not work.
1 parent 6cf7982 commit 3e4701a

File tree

3 files changed

+99
-69
lines changed

3 files changed

+99
-69
lines changed

src/ansi-c/ansi_c_entry_point.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ exprt::operandst build_function_environment(
4242
base_name,
4343
p.type(),
4444
p.source_location(),
45-
object_factory_parameters);
45+
object_factory_parameters,
46+
lifetimet::AUTOMATIC_LOCAL);
4647
}
4748

4849
return main_arguments;

src/ansi-c/c_nondet_symbol_factory.cpp

Lines changed: 27 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -25,79 +25,29 @@ Author: Diffblue Ltd.
2525

2626
#include <goto-programs/goto_functions.h>
2727

28-
class symbol_factoryt
29-
{
30-
symbol_tablet &symbol_table;
31-
const source_locationt &loc;
32-
namespacet ns;
33-
const c_object_factory_parameterst &object_factory_params;
34-
35-
allocate_objectst allocate_objects;
36-
37-
typedef std::set<irep_idt> recursion_sett;
38-
39-
public:
40-
symbol_factoryt(
41-
symbol_tablet &_symbol_table,
42-
const source_locationt &loc,
43-
const c_object_factory_parameterst &object_factory_params)
44-
: symbol_table(_symbol_table),
45-
loc(loc),
46-
ns(_symbol_table),
47-
object_factory_params(object_factory_params),
48-
allocate_objects(ID_C, loc, loc.get_function(), symbol_table)
49-
{}
50-
51-
void gen_nondet_init(
52-
code_blockt &assignments,
53-
const exprt &expr,
54-
const std::size_t depth = 0,
55-
recursion_sett recursion_set = recursion_sett());
56-
57-
void add_created_symbol(const symbolt *symbol_ptr)
58-
{
59-
allocate_objects.add_created_symbol(symbol_ptr);
60-
}
61-
62-
void declare_created_symbols(code_blockt &init_code)
63-
{
64-
allocate_objects.declare_created_symbols(init_code);
65-
}
66-
67-
void mark_created_symbols_as_input(code_blockt &init_code)
68-
{
69-
allocate_objects.mark_created_symbols_as_input(init_code);
70-
}
71-
72-
private:
73-
/// Generate initialisation code for each array element
74-
/// \param assignments: The code block to add code to
75-
/// \param expr: An expression of array type
76-
/// \param depth: The struct recursion depth
77-
/// \param recursion_set: The struct recursion set
78-
/// \see gen_nondet_init For the meaning of the last 2 parameters
79-
void gen_nondet_array_init(
80-
code_blockt &assignments,
81-
const exprt &expr,
82-
std::size_t depth,
83-
const recursion_sett &recursion_set);
84-
};
85-
8628
/// Creates a nondet for expr, including calling itself recursively to make
8729
/// appropriate symbols to point to if expr is a pointer.
8830
/// \param assignments: The code block to add code to
8931
/// \param expr: The expression which we are generating a non-determinate value
9032
/// for
91-
/// \param depth: number of pointers followed so far during initialisation
92-
/// \param recursion_set: names of structs seen so far on current pointer chain
33+
/// \param depth number of pointers followed so far during initialisation
34+
/// \param recursion_set names of structs seen so far on current pointer chain
35+
/// \param assign_const Indicates whether const objects should be nondet
36+
/// initialized
9337
void symbol_factoryt::gen_nondet_init(
9438
code_blockt &assignments,
9539
const exprt &expr,
9640
const std::size_t depth,
97-
recursion_sett recursion_set)
41+
recursion_sett recursion_set,
42+
const bool assign_const)
9843
{
9944
const typet &type = expr.type();
10045

46+
if(!assign_const && expr.type().get_bool(ID_C_constant))
47+
{
48+
return;
49+
}
50+
10151
if(type.id()==ID_pointer)
10252
{
10353
// dereferenced type
@@ -120,10 +70,10 @@ void symbol_factoryt::gen_nondet_init(
12070

12171
code_blockt non_null_inst;
12272

123-
exprt init_expr = allocate_objects.allocate_automatic_local_object(
124-
non_null_inst, expr, subtype);
73+
exprt init_expr =
74+
allocate_objects.allocate_object(non_null_inst, expr, subtype, lifetime);
12575

126-
gen_nondet_init(non_null_inst, init_expr, depth + 1, recursion_set);
76+
gen_nondet_init(non_null_inst, init_expr, depth + 1, recursion_set, true);
12777

12878
if(depth < object_factory_params.min_null_tree_depth)
12979
{
@@ -165,12 +115,18 @@ void symbol_factoryt::gen_nondet_init(
165115
for(const auto &component : struct_type.components())
166116
{
167117
const typet &component_type = component.type();
118+
119+
if(!assign_const && component_type.get_bool(ID_C_constant))
120+
{
121+
continue;
122+
}
123+
168124
const irep_idt name = component.get_name();
169125

170126
member_exprt me(expr, name, component_type);
171127
me.add_source_location() = loc;
172128

173-
gen_nondet_init(assignments, me, depth, recursion_set);
129+
gen_nondet_init(assignments, me, depth, recursion_set, assign_const);
174130
}
175131
}
176132
else if(type.id() == ID_array)
@@ -221,14 +177,17 @@ void symbol_factoryt::gen_nondet_array_init(
221177
/// \param loc: The location to assign to generated code
222178
/// \param object_factory_parameters: configuration parameters for the object
223179
/// factory
180+
/// \param lifetime: Lifetime of the allocated object (AUTOMATIC_LOCAL,
181+
/// STATIC_GLOBAL, or DYNAMIC)
224182
/// \return Returns the symbol_exprt for the symbol created
225183
symbol_exprt c_nondet_symbol_factory(
226184
code_blockt &init_code,
227185
symbol_tablet &symbol_table,
228186
const irep_idt base_name,
229187
const typet &type,
230188
const source_locationt &loc,
231-
const c_object_factory_parameterst &object_factory_parameters)
189+
const c_object_factory_parameterst &object_factory_parameters,
190+
const lifetimet lifetime)
232191
{
233192
irep_idt identifier=id2string(goto_functionst::entry_point())+
234193
"::"+id2string(base_name);
@@ -247,7 +206,8 @@ symbol_exprt c_nondet_symbol_factory(
247206
bool moving_symbol_failed=symbol_table.move(main_symbol, main_symbol_ptr);
248207
CHECK_RETURN(!moving_symbol_failed);
249208

250-
symbol_factoryt state(symbol_table, loc, object_factory_parameters);
209+
symbol_factoryt state(symbol_table, loc, object_factory_parameters, lifetime);
210+
251211
code_blockt assignments;
252212
state.gen_nondet_init(assignments, main_symbol_expr);
253213

src/ansi-c/c_nondet_symbol_factory.h

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,84 @@ Author: Diffblue Ltd.
1414

1515
#include "c_object_factory_parameters.h"
1616

17+
#include <set>
18+
#include <vector>
19+
20+
#include <util/allocate_objects.h>
1721
#include <util/std_code.h>
1822
#include <util/symbol_table.h>
1923

24+
class symbol_factoryt
25+
{
26+
symbol_tablet &symbol_table;
27+
const source_locationt &loc;
28+
namespacet ns;
29+
const c_object_factory_parameterst &object_factory_params;
30+
31+
allocate_objectst allocate_objects;
32+
33+
const lifetimet lifetime;
34+
35+
public:
36+
typedef std::set<irep_idt> recursion_sett;
37+
38+
symbol_factoryt(
39+
symbol_tablet &_symbol_table,
40+
const source_locationt &loc,
41+
const c_object_factory_parameterst &object_factory_params,
42+
const lifetimet lifetime)
43+
: symbol_table(_symbol_table),
44+
loc(loc),
45+
ns(_symbol_table),
46+
object_factory_params(object_factory_params),
47+
allocate_objects(ID_C, loc, loc.get_function(), symbol_table),
48+
lifetime(lifetime)
49+
{
50+
}
51+
52+
void gen_nondet_init(
53+
code_blockt &assignments,
54+
const exprt &expr,
55+
const std::size_t depth = 0,
56+
recursion_sett recursion_set = recursion_sett(),
57+
const bool assign_const = true);
58+
59+
void add_created_symbol(const symbolt *symbol_ptr)
60+
{
61+
allocate_objects.add_created_symbol(symbol_ptr);
62+
}
63+
64+
void declare_created_symbols(code_blockt &init_code)
65+
{
66+
allocate_objects.declare_created_symbols(init_code);
67+
}
68+
69+
void mark_created_symbols_as_input(code_blockt &init_code)
70+
{
71+
allocate_objects.mark_created_symbols_as_input(init_code);
72+
}
73+
74+
private:
75+
/// Generate initialisation code for each array element
76+
/// \param assignments: The code block to add code to
77+
/// \param expr: An expression of array type
78+
/// \param depth: The struct recursion depth
79+
/// \param recursion_set: The struct recursion set
80+
/// \see gen_nondet_init For the meaning of the last 2 parameters
81+
void gen_nondet_array_init(
82+
code_blockt &assignments,
83+
const exprt &expr,
84+
std::size_t depth,
85+
const recursion_sett &recursion_set);
86+
};
87+
2088
symbol_exprt c_nondet_symbol_factory(
2189
code_blockt &init_code,
2290
symbol_tablet &symbol_table,
2391
const irep_idt base_name,
2492
const typet &type,
2593
const source_locationt &,
26-
const c_object_factory_parameterst &object_factory_parameters);
94+
const c_object_factory_parameterst &object_factory_parameters,
95+
const lifetimet lifetime);
2796

2897
#endif // CPROVER_ANSI_C_C_NONDET_SYMBOL_FACTORY_H

0 commit comments

Comments
 (0)