@@ -1005,12 +1005,12 @@ void goto_convertt::convert_assume(
1005
1005
void goto_convertt::convert_loop_contracts (
1006
1006
const codet &code,
1007
1007
goto_programt::targett loop,
1008
- const irep_idt &mode )
1008
+ bool check_side_effect )
1009
1009
{
1010
1010
auto assigns = static_cast <const unary_exprt &>(code.find (ID_C_spec_assigns));
1011
1011
if (assigns.is_not_nil ())
1012
1012
{
1013
- PRECONDITION (loop->is_goto ());
1013
+ PRECONDITION (loop->is_goto () || loop-> is_incomplete_goto () );
1014
1014
loop->condition_nonconst ().add (ID_C_spec_assigns).swap (assigns.op ());
1015
1015
}
1016
1016
@@ -1020,11 +1020,20 @@ void goto_convertt::convert_loop_contracts(
1020
1020
{
1021
1021
if (has_subexpr (invariant, ID_side_effect))
1022
1022
{
1023
- throw incorrect_goto_program_exceptiont (
1024
- " Loop invariant is not side-effect free." , code.find_source_location ());
1023
+ if (check_side_effect)
1024
+ {
1025
+ throw incorrect_goto_program_exceptiont (
1026
+ " Loop invariant is not side-effect free." ,
1027
+ code.find_source_location ());
1028
+ }
1029
+ else
1030
+ {
1031
+ warning ().source_location = code.find_source_location ();
1032
+ warning () << " Loop invariants is not side-effect-free." << eom;
1033
+ }
1025
1034
}
1026
1035
1027
- PRECONDITION (loop->is_goto ());
1036
+ PRECONDITION (loop->is_goto () || loop-> is_incomplete_goto () );
1028
1037
loop->condition_nonconst ().add (ID_C_spec_loop_invariant).swap (invariant);
1029
1038
}
1030
1039
@@ -1034,12 +1043,20 @@ void goto_convertt::convert_loop_contracts(
1034
1043
{
1035
1044
if (has_subexpr (decreases_clause, ID_side_effect))
1036
1045
{
1037
- throw incorrect_goto_program_exceptiont (
1038
- " Decreases clause is not side-effect free." ,
1039
- code.find_source_location ());
1046
+ if (check_side_effect)
1047
+ {
1048
+ throw incorrect_goto_program_exceptiont (
1049
+ " Decreases clause is not side-effect free." ,
1050
+ code.find_source_location ());
1051
+ }
1052
+ else
1053
+ {
1054
+ warning ().source_location = code.find_source_location ();
1055
+ warning () << " Decreases clause is not side-effect-free." << eom;
1056
+ }
1040
1057
}
1041
1058
1042
- PRECONDITION (loop->is_goto ());
1059
+ PRECONDITION (loop->is_goto () || loop-> is_incomplete_goto () );
1043
1060
loop->condition_nonconst ().add (ID_C_spec_decreases).swap (decreases_clause);
1044
1061
}
1045
1062
}
@@ -1123,7 +1140,7 @@ void goto_convertt::convert_for(
1123
1140
goto_programt::make_goto (u, true_exprt (), code.source_location ()));
1124
1141
1125
1142
// assigns clause, loop invariant and decreases clause
1126
- convert_loop_contracts (code, y, mode );
1143
+ convert_loop_contracts (code, y);
1127
1144
1128
1145
dest.destructive_append (sideeffects);
1129
1146
dest.destructive_append (tmp_v);
@@ -1181,7 +1198,7 @@ void goto_convertt::convert_while(
1181
1198
convert (code.body (), tmp_x, mode);
1182
1199
1183
1200
// assigns clause, loop invariant and decreases clause
1184
- convert_loop_contracts (code, y, mode );
1201
+ convert_loop_contracts (code, y);
1185
1202
1186
1203
dest.destructive_append (tmp_branch);
1187
1204
dest.destructive_append (tmp_x);
@@ -1250,7 +1267,7 @@ void goto_convertt::convert_dowhile(
1250
1267
y->complete_goto (w);
1251
1268
1252
1269
// assigns_clause, loop invariant and decreases clause
1253
- convert_loop_contracts (code, y, mode );
1270
+ convert_loop_contracts (code, y);
1254
1271
1255
1272
dest.destructive_append (tmp_w);
1256
1273
dest.destructive_append (sideeffects);
@@ -1512,6 +1529,9 @@ void goto_convertt::convert_goto(const code_gotot &code, goto_programt &dest)
1512
1529
goto_programt::targett t =
1513
1530
dest.add (goto_programt::make_incomplete_goto (code, code.source_location ()));
1514
1531
1532
+ // Loop contracts annotated in GOTO
1533
+ convert_loop_contracts (code, t, false );
1534
+
1515
1535
// remember it to do the target later
1516
1536
targets.gotos .emplace_back (t, targets.scope_stack .get_current_node ());
1517
1537
}
0 commit comments