Skip to content

Commit eb1c4b9

Browse files
authored
Merge pull request #3 from xbauch/cleanup_goto_convert
Cleanup goto convert
2 parents 9a60cdb + 6f721cc commit eb1c4b9

File tree

15 files changed

+161
-59
lines changed

15 files changed

+161
-59
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int main()
2+
{
3+
break;
4+
return 0;
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
int main()
2+
{
3+
continue;
4+
return 0;
5+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int main()
2+
{
3+
goto x;
4+
5+
// x:
6+
7+
return 0;
8+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE gcc-only
2+
main.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int main()
2+
{
3+
int x;
4+
int n = 5;
5+
switch(x)
6+
{
7+
case 0 ... n:
8+
break;
9+
default:
10+
break;
11+
}
12+
return 0;
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^CONVERSION ERROR$
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
int main()
2+
{
3+
int x;
4+
switch(x)
5+
{
6+
case 10 ... 0:
7+
break;
8+
default:
9+
break;
10+
}
11+
return 0;
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=134$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^Invariant check failed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
int main()
2+
{
3+
int x;
4+
switch(x)
5+
{
6+
case 0 ... 10 20:
7+
break;
8+
default:
9+
break;
10+
}
11+
return 0;
12+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
--
7+
^warning: ignoring
8+
^PARSING ERROR$

src/cbmc/cbmc_parse_options.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Author: Daniel Kroening, [email protected]
1717
#include <memory>
1818

1919
#include <util/config.h>
20+
#include <util/exception_utils.h>
2021
#include <util/exit_codes.h>
2122
#include <util/invariant.h>
2223
#include <util/unicode.h>
@@ -611,6 +612,12 @@ int cbmc_parse_optionst::get_goto_program(
611612
log.status() << config.object_bits_info() << log.eom;
612613
}
613614

615+
catch(incorrect_goto_program_exceptiont &e)
616+
{
617+
log.error() << e.what() << log.eom;
618+
return CPROVER_EXIT_EXCEPTION;
619+
}
620+
614621
catch(const char *e)
615622
{
616623
log.error() << e << log.eom;

src/goto-programs/goto_convert.cpp

Lines changed: 48 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,9 @@ Author: Daniel Kroening, [email protected]
1111

1212
#include "goto_convert.h"
1313

14-
#include <cassert>
15-
1614
#include <util/arith_tools.h>
1715
#include <util/cprover_prefix.h>
16+
#include <util/exception_utils.h>
1817
#include <util/expr_util.h>
1918
#include <util/fresh_symbol.h>
2019
#include <util/prefix.h>
@@ -116,10 +115,12 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
116115
labelst::const_iterator l_it=
117116
targets.labels.find(goto_label);
118117

119-
DATA_INVARIANT(
120-
l_it != targets.labels.end(),
121-
i.code.find_source_location().as_string() + ": goto label '" +
122-
id2string(goto_label) + "' not found");
118+
if(l_it == targets.labels.end())
119+
{
120+
throw incorrect_goto_program_exceptiont(
121+
"goto label \'" + id2string(goto_label) + "\' not found",
122+
i.code.find_source_location());
123+
}
123124

124125
i.targets.push_back(l_it->second.first);
125126
}
@@ -129,10 +130,12 @@ void goto_convertt::finish_gotos(goto_programt &dest, const irep_idt &mode)
129130

130131
labelst::const_iterator l_it=targets.labels.find(goto_label);
131132

132-
DATA_INVARIANT(
133-
l_it != targets.labels.end(),
134-
i.code.find_source_location().as_string() + ": goto label '" +
135-
id2string(goto_label) + "' not found");
133+
if(l_it == targets.labels.end())
134+
{
135+
throw incorrect_goto_program_exceptiont(
136+
"goto label \'" + id2string(goto_label) + "\' not found",
137+
i.code.find_source_location());
138+
}
136139

137140
i.complete_goto(l_it->second.first);
138141

@@ -192,13 +195,8 @@ void goto_convertt::finish_computed_gotos(goto_programt &goto_program)
192195
for(auto &g_it : targets.computed_gotos)
193196
{
194197
goto_programt::instructiont &i=*g_it;
195-
exprt destination=i.code.op0();
196-
197-
DATA_INVARIANT(
198-
destination.id() == ID_dereference, "dereference ID not allowed here");
199-
DATA_INVARIANT(destination.operands().size() == 1, "expected 1 argument");
200-
201-
exprt pointer=destination.op0();
198+
dereference_exprt destination = to_dereference_expr(i.code.op0());
199+
exprt pointer = destination.op();
202200

203201
// remember the expression for later checks
204202
i.type=OTHER;
@@ -516,7 +514,7 @@ void goto_convertt::convert(
516514
assertion.make_typecast(bool_typet());
517515
simplify(assertion, ns);
518516
INVARIANT(
519-
assertion.is_false(),
517+
!assertion.is_false(),
520518
code.op0().find_source_location().as_string() + ": static assertion " +
521519
id2string(get_string_constant(code.op1())));
522520
}
@@ -580,12 +578,7 @@ void goto_convertt::convert_expression(
580578
goto_programt &dest,
581579
const irep_idt &mode)
582580
{
583-
INVARIANT(
584-
code.operands().size() == 1,
585-
code.find_source_location().as_string() +
586-
": expression statement takes one operand");
587-
588-
exprt expr=code.op0();
581+
exprt expr = code.expression();
589582

590583
if(expr.id()==ID_if)
591584
{
@@ -622,14 +615,7 @@ void goto_convertt::convert_decl(
622615
goto_programt &dest,
623616
const irep_idt &mode)
624617
{
625-
const exprt &op = code.symbol();
626-
627-
INVARIANT(
628-
op.id() == ID_symbol,
629-
op.find_source_location().as_string() +
630-
": decl statement expects symbol as operand");
631-
632-
const irep_idt &identifier = to_symbol_expr(op).get_identifier();
618+
const irep_idt &identifier = to_symbol_expr(code.symbol()).get_identifier();
633619

634620
const symbolt &symbol = ns.lookup(identifier);
635621

@@ -774,11 +760,8 @@ void goto_convertt::convert_assign(
774760

775761
if(lhs.id()==ID_typecast)
776762
{
777-
INVARIANT(lhs.operands().size() == 1, "typecast takes one operand");
778-
779763
// add a typecast to the rhs
780-
exprt new_rhs=rhs;
781-
rhs.make_typecast(lhs.op0().type());
764+
rhs.make_typecast(to_typecast_expr(lhs).op().type());
782765

783766
// remove typecast from lhs
784767
exprt tmp=lhs.op0();
@@ -1170,27 +1153,28 @@ exprt goto_convertt::case_guard(
11701153
const exprt &value,
11711154
const exprt::operandst &case_op)
11721155
{
1173-
exprt dest=exprt(ID_or, bool_typet());
1174-
dest.reserve_operands(case_op.size());
1156+
PRECONDITION(!case_op.empty());
11751157

1176-
forall_expr(it, case_op)
1158+
if(case_op.size() == 1)
1159+
return equal_exprt(value, case_op.at(0));
1160+
else
11771161
{
1178-
equal_exprt eq_expr;
1179-
eq_expr.lhs()=value;
1180-
eq_expr.rhs()=*it;
1181-
dest.move_to_operands(eq_expr);
1182-
}
1162+
exprt dest = exprt(ID_or, bool_typet());
1163+
dest.reserve_operands(case_op.size());
11831164

1184-
CHECK_RETURN(!dest.operands().empty());
1165+
forall_expr(it, case_op)
1166+
{
1167+
equal_exprt eq_expr;
1168+
eq_expr.lhs() = value;
1169+
eq_expr.rhs() = *it;
1170+
dest.move_to_operands(eq_expr);
1171+
}
1172+
INVARIANT(
1173+
case_op.size() == dest.operands().size(),
1174+
"case guard conversion should preserve the number of cases");
11851175

1186-
if(dest.operands().size()==1)
1187-
{
1188-
exprt tmp;
1189-
tmp.swap(dest.op0());
1190-
dest.swap(tmp);
1176+
return dest;
11911177
}
1192-
1193-
return dest;
11941178
}
11951179

11961180
void goto_convertt::convert_switch(
@@ -1269,7 +1253,9 @@ void goto_convertt::convert_switch(
12691253
{
12701254
const caset &case_ops=case_pair.second;
12711255

1272-
assert(!case_ops.empty());
1256+
if(case_ops.empty())
1257+
throw incorrect_goto_program_exceptiont(
1258+
"switch case range cannot be empty", code.find_source_location());
12731259

12741260
exprt guard_expr=case_guard(argument, case_ops);
12751261

@@ -1325,9 +1311,8 @@ void goto_convertt::convert_return(
13251311
{
13261312
if(!targets.return_set)
13271313
{
1328-
error().source_location=code.find_source_location();
1329-
error() << "return without target" << eom;
1330-
throw 0;
1314+
throw incorrect_goto_program_exceptiont(
1315+
"return without target", code.find_source_location());
13311316
}
13321317

13331318
DATA_INVARIANT(
@@ -1763,10 +1748,14 @@ void goto_convertt::generate_conditional_branch(
17631748
{
17641749
if(guard.id()==ID_not)
17651750
{
1766-
PRECONDITION(guard.operands().size() == 1);
17671751
// simply swap targets
17681752
generate_conditional_branch(
1769-
guard.op0(), target_false, target_true, source_location, dest, mode);
1753+
to_not_expr(guard).op(),
1754+
target_false,
1755+
target_true,
1756+
source_location,
1757+
dest,
1758+
mode);
17701759
return;
17711760
}
17721761

@@ -1877,7 +1866,7 @@ irep_idt goto_convertt::get_string_constant(const exprt &expr)
18771866
irep_idt result;
18781867

18791868
bool res = get_string_constant(expr, result);
1880-
INVARIANT(
1869+
INVARIANT_WITH_DIAGNOSTICS(
18811870
!res,
18821871
expr.find_source_location().as_string() + ": expected string constant",
18831872
expr.pretty());

src/util/std_code.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,9 @@ inline const code_declt &to_code_decl(const codet &code)
315315
// will be size()==1 in the future
316316
DATA_INVARIANT(
317317
code.operands().size() >= 1, "decls must have one or more operands");
318+
DATA_INVARIANT(
319+
code.op0().id() == ID_symbol, "decls symbols must be a \"symbol\"");
320+
318321
return static_cast<const code_declt &>(code);
319322
}
320323

0 commit comments

Comments
 (0)