@@ -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,52 @@ 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))
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)
182201 {
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));
258205 }
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);
259214 }
260215
261216protected:
262217 void generate_function_body_impl (
263218 goto_functiont &function,
264- const symbol_tablet &symbol_table,
219+ symbol_tablet &symbol_table,
265220 const irep_idt &function_name) const override
266221 {
267222 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -277,18 +232,29 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
277232 {
278233 if (
279234 parameter.type ().id () == ID_pointer &&
235+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
280236 std::regex_match (
281237 id2string (parameter.get_base_name ()), parameters_to_havoc))
282238 {
283- // if (param != nullptr) { *param = nondet(); }
284239 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;
285249 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,
251+ 1 ,
252+ function_symbol.location ,
253+ symbol_table,
254+ dest);
255+
256+ function.body .destructive_append (dest);
257+
292258 auto label_instruction = add_instruction ();
293259 goto_instruction->make_goto (
294260 label_instruction,
@@ -302,12 +268,19 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
302268 for (auto const &global_id : globals_to_havoc)
303269 {
304270 auto const &global_sym = symbol_table.lookup_ref (global_id);
271+
272+ goto_programt dest;
273+
305274 havoc_expr_rec (
306275 symbol_exprt (global_sym.name , global_sym.type ),
307- ns,
308- add_instruction,
309- function_name);
276+ 0 ,
277+ function_symbol.location ,
278+ symbol_table,
279+ dest);
280+
281+ function.body .destructive_append (dest);
310282 }
283+
311284 if (function.type .return_type () != void_typet ())
312285 {
313286 auto return_instruction = add_instruction ();
0 commit comments