@@ -69,7 +69,7 @@ class assume_false_generate_function_bodiest : public generate_function_bodiest
6969protected:
7070 void generate_function_body_impl (
7171 goto_functiont &function,
72- const symbol_tablet &symbol_table,
72+ symbol_tablet &symbol_table,
7373 const irep_idt &function_name) const override
7474 {
7575 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -92,7 +92,7 @@ class assert_false_generate_function_bodiest : public generate_function_bodiest
9292protected:
9393 void generate_function_body_impl (
9494 goto_functiont &function,
95- const symbol_tablet &symbol_table,
95+ symbol_tablet &symbol_table,
9696 const irep_idt &function_name) const override
9797 {
9898 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -123,7 +123,7 @@ class assert_false_then_assume_false_generate_function_bodiest
123123protected:
124124 void generate_function_body_impl (
125125 goto_functiont &function,
126- const symbol_tablet &symbol_table,
126+ symbol_tablet &symbol_table,
127127 const irep_idt &function_name) const override
128128 {
129129 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -171,97 +171,42 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
171171private:
172172 void havoc_expr_rec (
173173 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
177178 {
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))
182- {
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- }
258- }
179+ symbol_factoryt symbol_factory (
180+ symbol_table,
181+ source_location,
182+ object_factory_parameters,
183+ lifetimet::DYNAMIC);
184+
185+ code_blockt assignments;
186+
187+ symbol_factory.gen_nondet_init (
188+ assignments,
189+ lhs,
190+ initial_depth, // depth 1 since we pass the dereferenced pointer
191+ symbol_factoryt::recursion_sett (),
192+ false ); // do not initialize const objects at the top level
193+
194+ code_blockt init_code;
195+
196+ symbol_factory.declare_created_symbols (init_code);
197+ init_code.append (assignments);
198+
199+ null_message_handlert nmh;
200+ goto_programt tmp_dest;
201+ goto_convert (init_code, symbol_table, tmp_dest, nmh, ID_C);
202+
203+ dest.destructive_append (tmp_dest);
259204 }
260205
261206protected:
262207 void generate_function_body_impl (
263208 goto_functiont &function,
264- const symbol_tablet &symbol_table,
209+ symbol_tablet &symbol_table,
265210 const irep_idt &function_name) const override
266211 {
267212 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -277,18 +222,25 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
277222 {
278223 if (
279224 parameter.type ().id () == ID_pointer &&
225+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
280226 std::regex_match (
281227 id2string (parameter.get_base_name ()), parameters_to_havoc))
282228 {
283- // if (param != nullptr) { *param = nondet(); }
284229 auto goto_instruction = add_instruction ();
230+
231+ const irep_idt base_name = parameter.get_base_name ();
232+ CHECK_RETURN (!base_name.empty ());
233+
234+ dereference_exprt dereference_expr (
235+ symbol_exprt (parameter.get_identifier (), parameter.type ()),
236+ parameter.type ().subtype ());
237+
238+ goto_programt dest;
285239 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);
240+ dereference_expr, 1 , function_symbol.location , symbol_table, dest);
241+
242+ function.body .destructive_append (dest);
243+
292244 auto label_instruction = add_instruction ();
293245 goto_instruction->make_goto (
294246 label_instruction,
@@ -302,19 +254,25 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
302254 for (auto const &global_id : globals_to_havoc)
303255 {
304256 auto const &global_sym = symbol_table.lookup_ref (global_id);
257+
258+ goto_programt dest;
259+
305260 havoc_expr_rec (
306261 symbol_exprt (global_sym.name , global_sym.type ),
307- ns,
308- add_instruction,
309- function_name);
262+ 0 ,
263+ function_symbol.location ,
264+ symbol_table,
265+ dest);
266+
267+ function.body .destructive_append (dest);
310268 }
269+
311270 if (function.type .return_type () != void_typet ())
312271 {
313272 auto return_instruction = add_instruction ();
314273 return_instruction->make_return ();
315- return_instruction->code = code_returnt (
316- side_effect_expr_nondett (
317- function.type .return_type (), function_symbol.location ));
274+ return_instruction->code = code_returnt (side_effect_expr_nondett (
275+ function.type .return_type (), function_symbol.location ));
318276 }
319277 auto end_function_instruction = add_instruction ();
320278 end_function_instruction->make_end_function ();
0 commit comments