@@ -888,6 +888,12 @@ void code_contractst::apply_loop_contract(
888
888
889
889
std::list<size_t > to_check_contracts_on_children;
890
890
891
+ std::map<
892
+ goto_programt::targett,
893
+ std::pair<goto_programt::targett, natural_loops_mutablet::loopt>,
894
+ goto_programt::target_less_than>
895
+ loop_head_ends;
896
+
891
897
for (const auto &loop_head_and_content : natural_loops.loop_map)
892
898
{
893
899
const auto &loop_content = loop_head_and_content.second ;
@@ -914,6 +920,42 @@ void code_contractst::apply_loop_contract(
914
920
throw 0 ;
915
921
}
916
922
923
+ // By definition the `loop_content` is a set of instructions computed
924
+ // by `natural_loops` based on the CFG.
925
+ // Since we perform assigns clause instrumentation by sequentially
926
+ // traversing instructions from `loop_head` to `loop_end`,
927
+ // here we ensure that all instructions in `loop_content` belong within
928
+ // the [loop_head, loop_end] target range
929
+
930
+ // Check 1. (i \in loop_content) ==> loop_head <= i <= loop_end
931
+ for (const auto &i : loop_content)
932
+ {
933
+ if (
934
+ loop_head->location_number > i->location_number ||
935
+ i->location_number > loop_end->location_number )
936
+ {
937
+ log .conditional_output (
938
+ log .error (), [&i, &loop_head](messaget::mstreamt &mstream) {
939
+ mstream << " Computed loop at " << loop_head->source_location ()
940
+ << " contains an instruction beyond [loop_head, loop_end]:"
941
+ << messaget::eom;
942
+ i->output (mstream);
943
+ mstream << messaget::eom;
944
+ });
945
+ throw 0 ;
946
+ }
947
+ }
948
+
949
+ if (!loop_head_ends
950
+ .emplace (loop_head, std::make_pair (loop_end, loop_content))
951
+ .second )
952
+ UNREACHABLE;
953
+ }
954
+
955
+ for (auto &loop_head_end : loop_head_ends)
956
+ {
957
+ auto loop_head = loop_head_end.first ;
958
+ auto loop_end = loop_head_end.second .first ;
917
959
// After loop-contract instrumentation, jumps to the `loop_head` will skip
918
960
// some instrumented instructions. So we want to make sure that there is
919
961
// only one jump targeting `loop_head` from `loop_end` before loop-contract
@@ -961,7 +1003,7 @@ void code_contractst::apply_loop_contract(
961
1003
}
962
1004
963
1005
const auto idx = loop_nesting_graph.add_node (
964
- loop_content ,
1006
+ loop_head_end. second . second ,
965
1007
loop_head,
966
1008
loop_end,
967
1009
assigns_clause,
@@ -974,30 +1016,6 @@ void code_contractst::apply_loop_contract(
974
1016
continue ;
975
1017
976
1018
to_check_contracts_on_children.push_back (idx);
977
-
978
- // By definition the `loop_content` is a set of instructions computed
979
- // by `natural_loops` based on the CFG.
980
- // Since we perform assigns clause instrumentation by sequentially
981
- // traversing instructions from `loop_head` to `loop_end`,
982
- // here we ensure that all instructions in `loop_content` belong within
983
- // the [loop_head, loop_end] target range
984
-
985
- // Check 1. (i \in loop_content) ==> loop_head <= i <= loop_end
986
- for (const auto &i : loop_content)
987
- {
988
- if (std::distance (loop_head, i) < 0 || std::distance (i, loop_end) < 0 )
989
- {
990
- log .conditional_output (
991
- log .error (), [&i, &loop_head](messaget::mstreamt &mstream) {
992
- mstream << " Computed loop at " << loop_head->source_location ()
993
- << " contains an instruction beyond [loop_head, loop_end]:"
994
- << messaget::eom;
995
- i->output (mstream);
996
- mstream << messaget::eom;
997
- });
998
- throw 0 ;
999
- }
1000
- }
1001
1019
}
1002
1020
1003
1021
for (size_t outer = 0 ; outer < loop_nesting_graph.size(); ++outer)
0 commit comments