@@ -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,51 @@ 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
+ symbol_tablet &symbol_table ,
176
+ goto_programt &dest ) const
177
177
{
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))
178
+ std::vector<const symbolt *> symbols_created;
179
+
180
+ symbol_factoryt symbol_factory (
181
+ symbols_created,
182
+ symbol_table,
183
+ source_locationt (),
184
+ object_factory_parameters,
185
+ allocation_typet::DYNAMIC);
186
+
187
+ code_blockt assignments;
188
+
189
+ symbol_factory.gen_nondet_init (
190
+ assignments,
191
+ lhs,
192
+ initial_depth, // depth 1 since we pass the dereferenced pointer
193
+ symbol_factoryt::recursion_sett (),
194
+ false ); // do not initialize const objects at the top level
195
+
196
+ code_blockt init_code;
197
+
198
+ // declare added symbols
199
+ for (const symbolt *const symbol_ptr : symbols_created)
182
200
{
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
- }
201
+ code_declt decl (symbol_ptr->symbol_expr ());
202
+ decl.add_source_location () = source_locationt ();
203
+ init_code.add (std::move (decl));
258
204
}
205
+
206
+ init_code.append (assignments);
207
+
208
+ null_message_handlert nmh;
209
+ goto_programt tmp_dest;
210
+ goto_convert (init_code, symbol_table, tmp_dest, nmh, ID_C);
211
+
212
+ dest.destructive_append (tmp_dest);
259
213
}
260
214
261
215
protected:
262
216
void generate_function_body_impl (
263
217
goto_functiont &function,
264
- const symbol_tablet &symbol_table,
218
+ symbol_tablet &symbol_table,
265
219
const irep_idt &function_name) const override
266
220
{
267
221
auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -277,18 +231,24 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
277
231
{
278
232
if (
279
233
parameter.type ().id () == ID_pointer &&
234
+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
280
235
std::regex_match (
281
236
id2string (parameter.get_base_name ()), parameters_to_havoc))
282
237
{
283
- // if (param != nullptr) { *param = nondet(); }
284
238
auto goto_instruction = add_instruction ();
285
- 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);
239
+
240
+ const irep_idt base_name = parameter.get_base_name ();
241
+ CHECK_RETURN (!base_name.empty ());
242
+
243
+ dereference_exprt dereference_expr (
244
+ symbol_exprt (parameter.get_identifier (), parameter.type ()),
245
+ parameter.type ().subtype ());
246
+
247
+ goto_programt dest;
248
+ havoc_expr_rec (dereference_expr, 1 , symbol_table, dest);
249
+
250
+ function.body .destructive_append (dest);
251
+
292
252
auto label_instruction = add_instruction ();
293
253
goto_instruction->make_goto (
294
254
label_instruction,
@@ -302,12 +262,15 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
302
262
for (auto const &global_id : globals_to_havoc)
303
263
{
304
264
auto const &global_sym = symbol_table.lookup_ref (global_id);
265
+
266
+ goto_programt dest;
267
+
305
268
havoc_expr_rec (
306
- symbol_exprt (global_sym.name , global_sym.type ),
307
- ns,
308
- add_instruction,
309
- function_name);
269
+ symbol_exprt (global_sym.name , global_sym.type ), 0 , symbol_table, dest);
270
+
271
+ function.body .destructive_append (dest);
310
272
}
273
+
311
274
if (function.type .return_type () != void_typet ())
312
275
{
313
276
auto return_instruction = add_instruction ();
0 commit comments