@@ -68,7 +68,7 @@ class assume_false_generate_function_bodiest : public generate_function_bodiest
68
68
protected:
69
69
void generate_function_body_impl (
70
70
goto_functiont &function,
71
- const symbol_tablet &symbol_table,
71
+ symbol_tablet &symbol_table,
72
72
const irep_idt &function_name) const override
73
73
{
74
74
auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -91,7 +91,7 @@ class assert_false_generate_function_bodiest : public generate_function_bodiest
91
91
protected:
92
92
void generate_function_body_impl (
93
93
goto_functiont &function,
94
- const symbol_tablet &symbol_table,
94
+ symbol_tablet &symbol_table,
95
95
const irep_idt &function_name) const override
96
96
{
97
97
auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -122,7 +122,7 @@ class assert_false_then_assume_false_generate_function_bodiest
122
122
protected:
123
123
void generate_function_body_impl (
124
124
goto_functiont &function,
125
- const symbol_tablet &symbol_table,
125
+ symbol_tablet &symbol_table,
126
126
const irep_idt &function_name) const override
127
127
{
128
128
auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -150,8 +150,7 @@ class assert_false_then_assume_false_generate_function_bodiest
150
150
}
151
151
};
152
152
153
- class havoc_generate_function_bodiest : public generate_function_bodiest ,
154
- private messaget
153
+ class havoc_generate_function_bodiest : public generate_function_bodiest
155
154
{
156
155
public:
157
156
havoc_generate_function_bodiest (
@@ -160,107 +159,52 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
160
159
const c_object_factory_parameterst &object_factory_parameters,
161
160
message_handlert &message_handler)
162
161
: generate_function_bodiest(),
163
- messaget (message_handler),
164
162
globals_to_havoc (std::move(globals_to_havoc)),
165
163
parameters_to_havoc(std::move(parameters_to_havoc)),
166
- object_factory_parameters(object_factory_parameters)
164
+ object_factory_parameters(object_factory_parameters),
165
+ message(message_handler)
167
166
{
168
167
}
169
168
170
169
private:
171
170
void havoc_expr_rec (
172
171
const exprt &lhs,
173
- const namespacet &ns,
174
- const std::function<goto_programt::targett(void )> &add_instruction,
175
- const irep_idt &function_name) const
172
+ const std::size_t initial_depth,
173
+ const source_locationt &source_location,
174
+ symbol_tablet &symbol_table,
175
+ goto_programt &dest) const
176
176
{
177
- // resolve type symbols
178
- auto const lhs_type = ns.follow (lhs.type ());
179
- // skip constants
180
- if (!lhs_type.get_bool (ID_C_constant))
181
- {
182
- // expand arrays, structs and union, everything else gets
183
- // assigned nondet
184
- if (lhs_type.id () == ID_struct || lhs_type.id () == ID_union)
185
- {
186
- // Note: In the case of unions it's often enough to assign
187
- // just one member; However consider a case like
188
- // union { struct { const int x; int y; } a;
189
- // struct { int x; const int y; } b;};
190
- // in this case both a.y and b.x must be assigned
191
- // otherwise these parts stay constant even though
192
- // they could've changed (note that type punning through
193
- // unions is allowed in the C standard but forbidden in C++)
194
- // so we're assigning all members even in the case of
195
- // unions just to be safe
196
- auto const lhs_struct_type = to_struct_union_type (lhs_type);
197
- for (auto const &component : lhs_struct_type.components ())
198
- {
199
- havoc_expr_rec (
200
- member_exprt (lhs, component.get_name (), component.type ()),
201
- ns,
202
- add_instruction,
203
- function_name);
204
- }
205
- }
206
- else if (lhs_type.id () == ID_array)
207
- {
208
- auto const lhs_array_type = to_array_type (lhs_type);
209
- if (!lhs_array_type.subtype ().get_bool (ID_C_constant))
210
- {
211
- bool constant_known_array_size = lhs_array_type.size ().is_constant ();
212
- if (!constant_known_array_size)
213
- {
214
- warning () << " Cannot havoc non-const array " << format (lhs)
215
- << " in function " << function_name
216
- << " : Unknown array size" << eom;
217
- }
218
- else
219
- {
220
- auto const array_size =
221
- numeric_cast<mp_integer>(lhs_array_type.size ());
222
- INVARIANT (
223
- array_size.has_value (),
224
- " Array size should be known constant integer" );
225
- if (array_size.value () == 0 )
226
- {
227
- // Pretty much the same thing as a unknown size array
228
- // Technically not allowed by the C standard, but we model
229
- // unknown size arrays in structs this way
230
- warning () << " Cannot havoc non-const array " << format (lhs)
231
- << " in function " << function_name << " : Array size 0"
232
- << eom;
233
- }
234
- else
235
- {
236
- for (mp_integer i = 0 ; i < array_size.value (); ++i)
237
- {
238
- auto const index =
239
- from_integer (i, lhs_array_type.size ().type ());
240
- havoc_expr_rec (
241
- index_exprt (lhs, index , lhs_array_type.subtype ()),
242
- ns,
243
- add_instruction,
244
- function_name);
245
- }
246
- }
247
- }
248
- }
249
- }
250
- else
251
- {
252
- auto assign_instruction = add_instruction ();
253
- assign_instruction->make_assignment (
254
- code_assignt (
255
- lhs, side_effect_expr_nondett (lhs_type, lhs.source_location ())));
256
- }
257
- }
177
+ symbol_factoryt symbol_factory (
178
+ symbol_table,
179
+ source_location,
180
+ object_factory_parameters,
181
+ lifetimet::DYNAMIC);
182
+
183
+ code_blockt assignments;
184
+
185
+ symbol_factory.gen_nondet_init (
186
+ assignments,
187
+ lhs,
188
+ initial_depth,
189
+ symbol_factoryt::recursion_sett (),
190
+ false ); // do not initialize const objects at the top level
191
+
192
+ code_blockt init_code;
193
+
194
+ symbol_factory.declare_created_symbols (init_code);
195
+ init_code.append (assignments);
196
+
197
+ goto_programt tmp_dest;
198
+ goto_convert (
199
+ init_code, symbol_table, tmp_dest, message.get_message_handler (), ID_C);
200
+
201
+ dest.destructive_append (tmp_dest);
258
202
}
259
203
260
204
protected:
261
205
void generate_function_body_impl (
262
206
goto_functiont &function,
263
- const symbol_tablet &symbol_table,
207
+ symbol_tablet &symbol_table,
264
208
const irep_idt &function_name) const override
265
209
{
266
210
auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -276,18 +220,29 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
276
220
{
277
221
if (
278
222
parameter.type ().id () == ID_pointer &&
223
+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
279
224
std::regex_match (
280
225
id2string (parameter.get_base_name ()), parameters_to_havoc))
281
226
{
282
- // if (param != nullptr) { *param = nondet(); }
283
227
auto goto_instruction = add_instruction ();
228
+
229
+ const irep_idt base_name = parameter.get_base_name ();
230
+ CHECK_RETURN (!base_name.empty ());
231
+
232
+ dereference_exprt dereference_expr (
233
+ symbol_exprt (parameter.get_identifier (), parameter.type ()),
234
+ parameter.type ().subtype ());
235
+
236
+ goto_programt dest;
284
237
havoc_expr_rec (
285
- dereference_exprt (
286
- symbol_exprt (parameter.get_identifier (), parameter.type ()),
287
- parameter.type ().subtype ()),
288
- ns,
289
- add_instruction,
290
- function_name);
238
+ dereference_expr,
239
+ 1 , // depth 1 since we pass the dereferenced pointer
240
+ function_symbol.location ,
241
+ symbol_table,
242
+ dest);
243
+
244
+ function.body .destructive_append (dest);
245
+
291
246
auto label_instruction = add_instruction ();
292
247
goto_instruction->make_goto (
293
248
label_instruction,
@@ -301,12 +256,19 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
301
256
for (auto const &global_id : globals_to_havoc)
302
257
{
303
258
auto const &global_sym = symbol_table.lookup_ref (global_id);
259
+
260
+ goto_programt dest;
261
+
304
262
havoc_expr_rec (
305
263
symbol_exprt (global_sym.name , global_sym.type ),
306
- ns,
307
- add_instruction,
308
- function_name);
264
+ 0 ,
265
+ function_symbol.location ,
266
+ symbol_table,
267
+ dest);
268
+
269
+ function.body .destructive_append (dest);
309
270
}
271
+
310
272
if (function.type .return_type () != void_typet ())
311
273
{
312
274
auto return_instruction = add_instruction ();
@@ -324,6 +286,7 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
324
286
const std::vector<irep_idt> globals_to_havoc;
325
287
std::regex parameters_to_havoc;
326
288
const c_object_factory_parameterst &object_factory_parameters;
289
+ mutable messaget message;
327
290
};
328
291
329
292
class generate_function_bodies_errort : public std ::runtime_error
0 commit comments