Skip to content

Commit c7985bd

Browse files
Merge pull request #5833 from thomasspriggs/tas/format_initialisation
Bug fix using `format` function on `code_declt` containing initialization
2 parents ddad3ee + dae3eca commit c7985bd

File tree

8 files changed

+78
-16
lines changed

8 files changed

+78
-16
lines changed

src/goto-instrument/dump_c.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff 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

src/goto-instrument/goto_program2code.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff 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
{

src/goto-programs/goto_program.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff 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

src/goto-programs/wp.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff 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());

src/util/format_expr.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff 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
{

src/util/std_code.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff 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)

unit/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff 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 \

unit/util/format.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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+
}

0 commit comments

Comments
 (0)