@@ -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,51 @@ 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+ symbol_tablet &symbol_table ,
176+ goto_programt &dest ) const
177177 {
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)
182200 {
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));
258204 }
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);
259213 }
260214
261215protected:
262216 void generate_function_body_impl (
263217 goto_functiont &function,
264- const symbol_tablet &symbol_table,
218+ symbol_tablet &symbol_table,
265219 const irep_idt &function_name) const override
266220 {
267221 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -277,18 +231,24 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
277231 {
278232 if (
279233 parameter.type ().id () == ID_pointer &&
234+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
280235 std::regex_match (
281236 id2string (parameter.get_base_name ()), parameters_to_havoc))
282237 {
283- // if (param != nullptr) { *param = nondet(); }
284238 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+
292252 auto label_instruction = add_instruction ();
293253 goto_instruction->make_goto (
294254 label_instruction,
@@ -302,12 +262,15 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
302262 for (auto const &global_id : globals_to_havoc)
303263 {
304264 auto const &global_sym = symbol_table.lookup_ref (global_id);
265+
266+ goto_programt dest;
267+
305268 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);
310272 }
273+
311274 if (function.type .return_type () != void_typet ())
312275 {
313276 auto return_instruction = add_instruction ();
0 commit comments