Skip to content

Commit 6378dec

Browse files
authored
Merge pull request #989 from diffblue/smv-typecheck-expr-boolean
SMV: error reporting for Boolean expressions
2 parents 11158c9 + 359d42c commit 6378dec

File tree

7 files changed

+100
-33
lines changed

7 files changed

+100
-33
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
boolean_expected1.smv
33

4-
^file boolean_expected1\.smv line 3: expected 0 or 1 here, but got 10$
4+
^file boolean_expected1\.smv line 3: Expected expression of type `boolean', but got expression `10', which is of type `10..10'$
55
^EXIT=2$
66
^SIGNAL=0$
77
--
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
boolean_expected2.smv
33

4-
^file boolean_expected2\.smv line 5: expected 0 or 1 here, but got 5$
4+
^file boolean_expected2\.smv line 5: Expected expression of type `boolean', but got expression `5', which is of type `5..5'$
55
^EXIT=2$
66
^SIGNAL=0$
77
--
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
boolean_expected3.smv
33

4-
^file boolean_expected3\.smv line 3: expected 0 or 1 here, but got 3$
4+
^file boolean_expected3\.smv line 3: Expected expression of type `boolean', but got expression `3', which is of type `3..3'$
55
^EXIT=2$
66
^SIGNAL=0$
77
--
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
CORE
22
boolean_expected4.smv
33

4-
^file boolean_expected4\.smv line 6: expected 0 or 1 here, but got 5$
4+
^file boolean_expected4\.smv line 6: Expected expression of type `boolean', but got expression `5', which is of type `5..5'$
55
^EXIT=2$
66
^SIGNAL=0$
77
--
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
boolean_expected5.smv
3+
4+
^file boolean_expected5\.smv line 5: Expected expression of type `boolean', but got expression `a', which is of type `\{ \}'$
5+
^EXIT=2$
6+
^SIGNAL=0$
7+
--
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
MODULE main
2+
3+
VAR e : { a, b, c };
4+
5+
SPEC a

src/smvlang/smv_typecheck.cpp

Lines changed: 84 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class smv_typecheckt:public typecheckt
6464
void convert(exprt &, expr_modet);
6565

6666
void typecheck(exprt &, const typet &, modet);
67+
void typecheck(exprt &, modet);
6768
void typecheck_op(exprt &, const typet &, modet);
6869

6970
void typecheck() override;
@@ -84,6 +85,7 @@ class smv_typecheckt:public typecheckt
8485
void convert(smv_parse_treet::modulet::itemt &);
8586
void typecheck(smv_parse_treet::modulet::itemt &);
8687
void typecheck_expr_rec(exprt &, const typet &, modet);
88+
void typecheck_expr_rec(exprt &, modet);
8789
void convert_expr_to(exprt &, const typet &dest);
8890

8991
smv_parse_treet::modulet *modulep;
@@ -592,6 +594,40 @@ void smv_typecheckt::typecheck(
592594

593595
/*******************************************************************\
594596
597+
Function: smv_typecheckt::typecheck
598+
599+
Inputs:
600+
601+
Outputs:
602+
603+
Purpose:
604+
605+
\*******************************************************************/
606+
607+
void smv_typecheckt::typecheck(exprt &expr, modet mode)
608+
{
609+
typecheck_expr_rec(expr, static_cast<const typet &>(get_nil_irep()), mode);
610+
}
611+
612+
/*******************************************************************\
613+
614+
Function: smv_typecheckt::typecheck_expr_rec
615+
616+
Inputs:
617+
618+
Outputs:
619+
620+
Purpose:
621+
622+
\*******************************************************************/
623+
624+
void smv_typecheckt::typecheck_expr_rec(exprt &expr, modet mode)
625+
{
626+
typecheck_expr_rec(expr, static_cast<const typet &>(get_nil_irep()), mode);
627+
}
628+
629+
/*******************************************************************\
630+
595631
Function: smv_typecheckt::typecheck_expr_rec
596632
597633
Inputs:
@@ -642,13 +678,26 @@ void smv_typecheckt::typecheck_expr_rec(
642678
}
643679
else if(
644680
expr.id() == ID_and || expr.id() == ID_or || expr.id() == ID_xor ||
645-
expr.id() == ID_not)
681+
expr.id() == ID_not || expr.id() == ID_implies)
646682
{
647-
typecheck_op(expr, bool_typet(), mode);
683+
for(auto &op : expr.operands())
684+
typecheck_expr_rec(op, mode);
685+
686+
expr.type() = bool_typet{};
687+
688+
for(auto &op : expr.operands())
689+
convert_expr_to(op, expr.type());
648690
}
649691
else if(expr.id() == ID_smv_iff)
650692
{
651-
typecheck_op(expr, bool_typet(), mode);
693+
for(auto &op : expr.operands())
694+
typecheck_expr_rec(op, mode);
695+
696+
expr.type() = bool_typet{};
697+
698+
for(auto &op : expr.operands())
699+
convert_expr_to(op, expr.type());
700+
652701
expr.set(ID_C_smv_iff, true);
653702
expr.id(ID_equal);
654703
}
@@ -670,30 +719,20 @@ void smv_typecheckt::typecheck_expr_rec(
670719

671720
expr.type()=op_type;
672721
}
673-
else if(expr.id()==ID_implies)
674-
{
675-
if(expr.operands().size()!=2)
676-
{
677-
throw errort().with_location(expr.find_source_location())
678-
<< "Expected two operands for -> operator";
679-
}
680-
681-
typecheck_op(expr, bool_typet(), mode);
682-
}
683722
else if(expr.id()==ID_equal || expr.id()==ID_notequal ||
684723
expr.id()==ID_lt || expr.id()==ID_le ||
685724
expr.id()==ID_gt || expr.id()==ID_ge)
686725
{
687726
for(auto &op : expr.operands())
688-
typecheck_expr_rec(op, static_cast<const typet &>(get_nil_irep()), mode);
727+
typecheck_expr_rec(op, mode);
689728

690729
if(expr.operands().size()!=2)
691730
{
692731
throw errort().with_location(expr.find_source_location())
693732
<< "Expected two operands for " << expr.id();
694733
}
695734

696-
expr.type()=bool_typet();
735+
expr.type() = bool_typet{};
697736

698737
exprt &op0 = to_binary_expr(expr).op0(), &op1 = to_binary_expr(expr).op1();
699738

@@ -719,7 +758,8 @@ void smv_typecheckt::typecheck_expr_rec(
719758
auto &if_expr = to_if_expr(expr);
720759
auto &true_case = if_expr.true_case();
721760
auto &false_case = if_expr.false_case();
722-
typecheck_expr_rec(if_expr.cond(), bool_typet{}, mode);
761+
typecheck_expr_rec(if_expr.cond(), mode);
762+
convert_expr_to(if_expr.cond(), bool_typet{});
723763
typecheck_expr_rec(true_case, dest_type, mode);
724764
typecheck_expr_rec(false_case, dest_type, mode);
725765
expr.type() = dest_type;
@@ -880,7 +920,10 @@ void smv_typecheckt::typecheck_expr_rec(
880920
for(auto &op : expr.operands())
881921
{
882922
if(condition)
883-
typecheck_expr_rec(op, bool_typet(), mode);
923+
{
924+
typecheck_expr_rec(op, mode);
925+
convert_expr_to(op, bool_typet{});
926+
}
884927
else
885928
{
886929
typecheck_expr_rec(
@@ -900,7 +943,10 @@ void smv_typecheckt::typecheck_expr_rec(
900943
for(auto &op : expr.operands())
901944
{
902945
if(condition)
903-
typecheck_expr_rec(op, bool_typet(), mode);
946+
{
947+
typecheck_expr_rec(op, mode);
948+
convert_expr_to(op, bool_typet{});
949+
}
904950
else
905951
typecheck_expr_rec(op, expr.type(), mode);
906952

@@ -916,15 +962,19 @@ void smv_typecheckt::typecheck_expr_rec(
916962
throw errort().with_location(expr.source_location())
917963
<< "CTL operator not permitted here";
918964
expr.type() = bool_typet();
919-
typecheck_expr_rec(to_unary_expr(expr).op(), expr.type(), mode);
965+
auto &op = to_unary_expr(expr).op();
966+
typecheck_expr_rec(op, mode);
967+
convert_expr_to(op, expr.type());
920968
}
921969
else if(expr.id() == ID_X || expr.id() == ID_F || expr.id() == ID_G)
922970
{
923971
if(mode != LTL)
924972
throw errort().with_location(expr.source_location())
925973
<< "LTL operator not permitted here";
926-
expr.type() = bool_typet();
927-
typecheck_expr_rec(to_unary_expr(expr).op(), expr.type(), mode);
974+
expr.type() = bool_typet{};
975+
auto &op = to_unary_expr(expr).op();
976+
typecheck_expr_rec(op, mode);
977+
convert_expr_to(op, expr.type());
928978
}
929979
else if(
930980
expr.id() == ID_EU || expr.id() == ID_ER || expr.id() == ID_AU ||
@@ -934,19 +984,23 @@ void smv_typecheckt::typecheck_expr_rec(
934984
throw errort().with_location(expr.source_location())
935985
<< "CTL operator not permitted here";
936986
auto &binary_expr = to_binary_expr(expr);
937-
expr.type() = bool_typet();
938-
typecheck_expr_rec(binary_expr.lhs(), expr.type(), mode);
939-
typecheck_expr_rec(binary_expr.rhs(), expr.type(), mode);
987+
expr.type() = bool_typet{};
988+
typecheck_expr_rec(binary_expr.lhs(), mode);
989+
typecheck_expr_rec(binary_expr.rhs(), mode);
990+
convert_expr_to(binary_expr.lhs(), expr.type());
991+
convert_expr_to(binary_expr.rhs(), expr.type());
940992
}
941993
else if(expr.id() == ID_U || expr.id() == ID_R)
942994
{
943995
if(mode != LTL)
944996
throw errort().with_location(expr.source_location())
945997
<< "LTL operator not permitted here";
946998
auto &binary_expr = to_binary_expr(expr);
947-
expr.type() = bool_typet();
948-
typecheck_expr_rec(binary_expr.lhs(), expr.type(), mode);
949-
typecheck_expr_rec(binary_expr.rhs(), expr.type(), mode);
999+
expr.type() = bool_typet{};
1000+
typecheck_expr_rec(binary_expr.lhs(), mode);
1001+
typecheck_expr_rec(binary_expr.rhs(), mode);
1002+
convert_expr_to(binary_expr.lhs(), expr.type());
1003+
convert_expr_to(binary_expr.rhs(), expr.type());
9501004
}
9511005
else if(expr.id()==ID_typecast)
9521006
{
@@ -990,7 +1044,7 @@ void smv_typecheckt::convert_expr_to(exprt &expr, const typet &type)
9901044
smv_ranget e=convert_type(expr.type());
9911045
smv_ranget t=convert_type(type);
9921046

993-
if(e.is_contained_in(t))
1047+
if(e.is_contained_in(t) && expr.type().id() != ID_enumeration)
9941048
{
9951049
if(e.is_singleton())
9961050
{
@@ -1222,7 +1276,8 @@ void smv_typecheckt::typecheck(
12221276
mode=OTHER;
12231277
}
12241278

1225-
typecheck(item.expr, bool_typet(), mode);
1279+
typecheck(item.expr, mode);
1280+
convert_expr_to(item.expr, bool_typet{});
12261281
}
12271282

12281283
/*******************************************************************\

0 commit comments

Comments
 (0)