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