@@ -68,7 +68,7 @@ class assume_false_generate_function_bodiest : public generate_function_bodiest
6868protected:
6969 void generate_function_body_impl (
7070 goto_functiont &function,
71- const symbol_tablet &symbol_table,
71+ symbol_tablet &symbol_table,
7272 const irep_idt &function_name) const override
7373 {
7474 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -91,7 +91,7 @@ class assert_false_generate_function_bodiest : public generate_function_bodiest
9191protected:
9292 void generate_function_body_impl (
9393 goto_functiont &function,
94- const symbol_tablet &symbol_table,
94+ symbol_tablet &symbol_table,
9595 const irep_idt &function_name) const override
9696 {
9797 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -122,7 +122,7 @@ class assert_false_then_assume_false_generate_function_bodiest
122122protected:
123123 void generate_function_body_impl (
124124 goto_functiont &function,
125- const symbol_tablet &symbol_table,
125+ symbol_tablet &symbol_table,
126126 const irep_idt &function_name) const override
127127 {
128128 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -150,8 +150,7 @@ class assert_false_then_assume_false_generate_function_bodiest
150150 }
151151};
152152
153- class havoc_generate_function_bodiest : public generate_function_bodiest ,
154- private messaget
153+ class havoc_generate_function_bodiest : public generate_function_bodiest
155154{
156155public:
157156 havoc_generate_function_bodiest (
@@ -160,107 +159,52 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
160159 const c_object_factory_parameterst &object_factory_parameters,
161160 message_handlert &message_handler)
162161 : generate_function_bodiest(),
163- messaget (message_handler),
164162 globals_to_havoc (std::move(globals_to_havoc)),
165163 parameters_to_havoc(std::move(parameters_to_havoc)),
166- object_factory_parameters(object_factory_parameters)
164+ object_factory_parameters(object_factory_parameters),
165+ message(message_handler)
167166 {
168167 }
169168
170169private:
171170 void havoc_expr_rec (
172171 const exprt &lhs,
173- const namespacet &ns,
174- const std::function<goto_programt::targett(void )> &add_instruction,
175- const irep_idt &function_name) const
172+ const std::size_t initial_depth,
173+ const source_locationt &source_location,
174+ symbol_tablet &symbol_table,
175+ goto_programt &dest) const
176176 {
177- // resolve type symbols
178- auto const lhs_type = ns.follow (lhs.type ());
179- // skip constants
180- if (!lhs_type.get_bool (ID_C_constant))
181- {
182- // expand arrays, structs and union, everything else gets
183- // assigned nondet
184- if (lhs_type.id () == ID_struct || lhs_type.id () == ID_union)
185- {
186- // Note: In the case of unions it's often enough to assign
187- // just one member; However consider a case like
188- // union { struct { const int x; int y; } a;
189- // struct { int x; const int y; } b;};
190- // in this case both a.y and b.x must be assigned
191- // otherwise these parts stay constant even though
192- // they could've changed (note that type punning through
193- // unions is allowed in the C standard but forbidden in C++)
194- // so we're assigning all members even in the case of
195- // unions just to be safe
196- auto const lhs_struct_type = to_struct_union_type (lhs_type);
197- for (auto const &component : lhs_struct_type.components ())
198- {
199- havoc_expr_rec (
200- member_exprt (lhs, component.get_name (), component.type ()),
201- ns,
202- add_instruction,
203- function_name);
204- }
205- }
206- else if (lhs_type.id () == ID_array)
207- {
208- auto const lhs_array_type = to_array_type (lhs_type);
209- if (!lhs_array_type.subtype ().get_bool (ID_C_constant))
210- {
211- bool constant_known_array_size = lhs_array_type.size ().is_constant ();
212- if (!constant_known_array_size)
213- {
214- warning () << " Cannot havoc non-const array " << format (lhs)
215- << " in function " << function_name
216- << " : Unknown array size" << eom;
217- }
218- else
219- {
220- auto const array_size =
221- numeric_cast<mp_integer>(lhs_array_type.size ());
222- INVARIANT (
223- array_size.has_value (),
224- " Array size should be known constant integer" );
225- if (array_size.value () == 0 )
226- {
227- // Pretty much the same thing as a unknown size array
228- // Technically not allowed by the C standard, but we model
229- // unknown size arrays in structs this way
230- warning () << " Cannot havoc non-const array " << format (lhs)
231- << " in function " << function_name << " : Array size 0"
232- << eom;
233- }
234- else
235- {
236- for (mp_integer i = 0 ; i < array_size.value (); ++i)
237- {
238- auto const index =
239- from_integer (i, lhs_array_type.size ().type ());
240- havoc_expr_rec (
241- index_exprt (lhs, index, lhs_array_type.subtype ()),
242- ns,
243- add_instruction,
244- function_name);
245- }
246- }
247- }
248- }
249- }
250- else
251- {
252- auto assign_instruction = add_instruction ();
253- assign_instruction->make_assignment (
254- code_assignt (
255- lhs, side_effect_expr_nondett (lhs_type, lhs.source_location ())));
256- }
257- }
177+ symbol_factoryt symbol_factory (
178+ symbol_table,
179+ source_location,
180+ object_factory_parameters,
181+ lifetimet::DYNAMIC);
182+
183+ code_blockt assignments;
184+
185+ symbol_factory.gen_nondet_init (
186+ assignments,
187+ lhs,
188+ initial_depth,
189+ symbol_factoryt::recursion_sett (),
190+ false ); // do not initialize const objects at the top level
191+
192+ code_blockt init_code;
193+
194+ symbol_factory.declare_created_symbols (init_code);
195+ init_code.append (assignments);
196+
197+ goto_programt tmp_dest;
198+ goto_convert (
199+ init_code, symbol_table, tmp_dest, message.get_message_handler (), ID_C);
200+
201+ dest.destructive_append (tmp_dest);
258202 }
259203
260204protected:
261205 void generate_function_body_impl (
262206 goto_functiont &function,
263- const symbol_tablet &symbol_table,
207+ symbol_tablet &symbol_table,
264208 const irep_idt &function_name) const override
265209 {
266210 auto const &function_symbol = symbol_table.lookup_ref (function_name);
@@ -276,18 +220,29 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
276220 {
277221 if (
278222 parameter.type ().id () == ID_pointer &&
223+ !parameter.type ().subtype ().get_bool (ID_C_constant) &&
279224 std::regex_match (
280225 id2string (parameter.get_base_name ()), parameters_to_havoc))
281226 {
282- // if (param != nullptr) { *param = nondet(); }
283227 auto goto_instruction = add_instruction ();
228+
229+ const irep_idt base_name = parameter.get_base_name ();
230+ CHECK_RETURN (!base_name.empty ());
231+
232+ dereference_exprt dereference_expr (
233+ symbol_exprt (parameter.get_identifier (), parameter.type ()),
234+ parameter.type ().subtype ());
235+
236+ goto_programt dest;
284237 havoc_expr_rec (
285- dereference_exprt (
286- symbol_exprt (parameter.get_identifier (), parameter.type ()),
287- parameter.type ().subtype ()),
288- ns,
289- add_instruction,
290- function_name);
238+ dereference_expr,
239+ 1 , // depth 1 since we pass the dereferenced pointer
240+ function_symbol.location ,
241+ symbol_table,
242+ dest);
243+
244+ function.body .destructive_append (dest);
245+
291246 auto label_instruction = add_instruction ();
292247 goto_instruction->make_goto (
293248 label_instruction,
@@ -301,12 +256,19 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
301256 for (auto const &global_id : globals_to_havoc)
302257 {
303258 auto const &global_sym = symbol_table.lookup_ref (global_id);
259+
260+ goto_programt dest;
261+
304262 havoc_expr_rec (
305263 symbol_exprt (global_sym.name , global_sym.type ),
306- ns,
307- add_instruction,
308- function_name);
264+ 0 ,
265+ function_symbol.location ,
266+ symbol_table,
267+ dest);
268+
269+ function.body .destructive_append (dest);
309270 }
271+
310272 if (function.type .return_type () != void_typet ())
311273 {
312274 auto return_instruction = add_instruction ();
@@ -325,6 +287,7 @@ class havoc_generate_function_bodiest : public generate_function_bodiest,
325287 const std::vector<irep_idt> globals_to_havoc;
326288 std::regex parameters_to_havoc;
327289 const c_object_factory_parameterst &object_factory_parameters;
290+ mutable messaget message;
328291};
329292
330293class generate_function_bodies_errort : public std ::runtime_error
0 commit comments