File tree Expand file tree Collapse file tree 8 files changed +78
-16
lines changed
Expand file tree Collapse file tree 8 files changed +78
-16
lines changed Original file line number Diff line number Diff line change @@ -650,19 +650,14 @@ void dump_ct::cleanup_decl(
650650 std::list<irep_idt> &local_static,
651651 std::list<irep_idt> &local_type_decls)
652652{
653- exprt value=nil_exprt ();
654-
655- if (decl.operands ().size ()==2 )
656- {
657- value=decl.op1 ();
658- decl.operands ().resize (1 );
659- }
660-
661653 goto_programt tmp;
662654 tmp.add (goto_programt::make_decl (decl.symbol ()));
663655
664- if (value.is_not_nil ())
665- tmp.add (goto_programt::make_assignment (decl.symbol (), value));
656+ if (optionalt<exprt> value = decl.initial_value ())
657+ {
658+ decl.set_initial_value ({});
659+ tmp.add (goto_programt::make_assignment (decl.symbol (), std::move (*value)));
660+ }
666661
667662 tmp.add (goto_programt::make_end_function ());
668663
Original file line number Diff line number Diff line change @@ -477,7 +477,7 @@ goto_programt::const_targett goto_program2codet::convert_decl(
477477 {
478478 if (next->is_assign ())
479479 {
480- d.copy_to_operands ( next->get_assign ().rhs ());
480+ d.set_initial_value ({ next->get_assign ().rhs ()} );
481481 }
482482 else
483483 {
Original file line number Diff line number Diff line change @@ -199,13 +199,21 @@ class goto_programt
199199 const code_declt &get_decl () const
200200 {
201201 PRECONDITION (is_decl ());
202- return to_code_decl (code);
202+ const auto &decl = expr_checked_cast<code_declt>(code);
203+ INVARIANT (
204+ !decl.initial_value (),
205+ " code_declt in goto program may not contain initialization." );
206+ return decl;
203207 }
204208
205209 // / Set the declaration for DECL
206210 void set_decl (code_declt c)
207211 {
208212 PRECONDITION (is_decl ());
213+ INVARIANT (
214+ !c.initial_value (),
215+ " Initialization must be separated from code_declt before adding to "
216+ " goto_instructiont." );
209217 code = std::move (c);
210218 }
211219
Original file line number Diff line number Diff line change @@ -226,6 +226,7 @@ exprt wp_decl(
226226 const exprt &post ,
227227 const namespacet &ns)
228228{
229+ PRECONDITION (!code.initial_value ());
229230 // Model decl(var) as var = nondet()
230231 const exprt &var = code.symbol ();
231232 side_effect_expr_nondett nondet (var.type (), source_locationt ());
Original file line number Diff line number Diff line change @@ -422,11 +422,14 @@ void format_expr_configt::setup()
422422 {
423423 return os << " dead " << format (to_code_dead (code).symbol ()) << " ;" ;
424424 }
425- else if (statement == ID_decl )
425+ else if (const auto decl = expr_try_dynamic_cast<code_declt>(code) )
426426 {
427- const auto &declaration_symb = to_code_decl (code).symbol ();
428- return os << " decl " << format (declaration_symb.type ()) << " "
429- << format (declaration_symb) << " ;" ;
427+ const auto &declaration_symb = decl->symbol ();
428+ os << " decl " << format (declaration_symb.type ()) << " "
429+ << format (declaration_symb);
430+ if (const optionalt<exprt> initial_value = decl->initial_value ())
431+ os << " = " << format (*initial_value);
432+ return os << " ;" ;
430433 }
431434 else if (statement == ID_function_call)
432435 {
Original file line number Diff line number Diff line change @@ -420,6 +420,38 @@ class code_declt:public codet
420420 return symbol ().get_identifier ();
421421 }
422422
423+ // / Returns the initial value to which the declared variable is initialized,
424+ // / or empty in the case where no initialisation is included.
425+ // / \note: Initial values may be present in the front end but they must be
426+ // / separated into a separate assignment when used in a `goto_instructiont`.
427+ optionalt<exprt> initial_value () const
428+ {
429+ if (operands ().size () < 2 )
430+ return {};
431+ return {op1 ()};
432+ }
433+
434+ // / Sets the value to which this declaration initializes the declared
435+ // / variable. Empty optional maybe passed to remove existing initialisation.
436+ // / \note: Initial values may be present in the front end but they must be
437+ // / separated into a separate assignment when used in a `goto_instructiont`.
438+ void set_initial_value (optionalt<exprt> initial_value)
439+ {
440+ if (!initial_value)
441+ {
442+ operands ().resize (1 );
443+ }
444+ else if (operands ().size () < 2 )
445+ {
446+ PRECONDITION (operands ().size () == 1 );
447+ add_to_operands (std::move (*initial_value));
448+ }
449+ else
450+ {
451+ op1 () = std::move (*initial_value);
452+ }
453+ }
454+
423455 static void check (
424456 const codet &code,
425457 const validation_modet vm = validation_modet::INVARIANT)
Original file line number Diff line number Diff line change @@ -90,6 +90,7 @@ SRC += analyses/ai/ai.cpp \
9090 util/expr.cpp \
9191 util/expr_iterator.cpp \
9292 util/file_util.cpp \
93+ util/format.cpp \
9394 util/format_number_range.cpp \
9495 util/get_base_name.cpp \
9596 util/graph.cpp \
Original file line number Diff line number Diff line change 1+ /* ******************************************************************\
2+
3+ Module: Unit tests for `format` function.
4+
5+ Author: DiffBlue Limited.
6+
7+ \*******************************************************************/
8+
9+ #include < util/format.h>
10+ #include < util/format_expr.h>
11+ #include < util/std_code.h>
12+
13+ #include < testing-utils/use_catch.h>
14+
15+ TEST_CASE (" Format a declaration statement." , " [core][util][format]" )
16+ {
17+ const signedbv_typet int_type{32 };
18+ code_declt declaration{symbol_exprt{" foo" , int_type}};
19+ REQUIRE (format_to_string (declaration) == " decl signedbv[32] foo;" );
20+ declaration.set_initial_value ({int_type.zero_expr ()});
21+ REQUIRE (format_to_string (declaration) == " decl signedbv[32] foo = 0;" );
22+ }
You can’t perform that action at this time.
0 commit comments