@@ -449,7 +449,8 @@ void code_contractst::check_apply_loop_contracts(
449449 loop_end,
450450 skip_function_paramst::NO,
451451 // do not use CFG info for now
452- cfg_empty_info);
452+ cfg_empty_info,
453+ [&loop](const goto_programt::targett &t) { return loop.contains (t); });
453454
454455 // Now we begin instrumenting at the loop_end.
455456 // `pre_loop_end_instrs` are to be inserted before `loop_end`.
@@ -1070,11 +1071,9 @@ void code_contractst::apply_loop_contract(
10701071 // By definition the `loop_content` is a set of instructions computed
10711072 // by `natural_loops` based on the CFG.
10721073 // Since we perform assigns clause instrumentation by sequentially
1073- // traversing instructions from `loop_head` to `loop_end`, here check that:
1074- // 1. All instructions in `loop_content` are contained within the
1075- // [loop_head, loop_end] iterator range
1076- // 2. All instructions in the [loop_head, loop_end] range are contained
1077- // in the `loop_content` set, except for the exceptions explained below.
1074+ // traversing instructions from `loop_head` to `loop_end`,
1075+ // here we ensure that all instructions in `loop_content` belong within
1076+ // the [loop_head, loop_end] target range
10781077
10791078 // Check 1. (i \in loop_content) ==> loop_head <= i <= loop_end
10801079 for (const auto &i : loop_content)
@@ -1089,49 +1088,6 @@ void code_contractst::apply_loop_contract(
10891088 throw 0 ;
10901089 }
10911090 }
1092-
1093- // Check 2. (loop_head <= i <= loop_end) ==> (i \in loop_content)
1094- //
1095- // We allow the following exceptions in this check:
1096- // - `SKIP` or `LOCATION` instructions which are no-op
1097- // - `ASSUME(false)` instructions which are introduced by function pointer
1098- // or nested loop transformations, and have no successor instructions
1099- // - `SET_RETURN_VALUE` instructions followed by an uninterrupted sequence
1100- // of `DEAD` instructions and a `GOTO` jump out of the loop,
1101- // which model C `return` statements.
1102- // - `GOTO` jumps out of the loops, which model C `break` statements.
1103- // These instructions are allowed to be missing from `loop_content`,
1104- // and may be safely ignored for the purpose of our instrumentation.
1105- for (auto i = loop_head; i != loop_end; ++i)
1106- {
1107- if (loop_content.contains (i))
1108- continue ;
1109-
1110- if (i->is_skip () || i->is_location ())
1111- continue ;
1112-
1113- if (i->is_goto () && !loop_content.contains (i->get_target ()))
1114- continue ;
1115-
1116- if (i->is_assume () && i->get_condition ().is_false ())
1117- continue ;
1118-
1119- if (i->is_set_return_value ())
1120- {
1121- do
1122- i++;
1123- while (i != loop_end && i->is_dead ());
1124-
1125- // because we increment `i` in the outer `for` loop
1126- i--;
1127- continue ;
1128- }
1129-
1130- log.error () << " Computed loop at: " << loop_head->source_location ()
1131- << " is missing an instruction:" << messaget::eom;
1132- goto_function.body .output_instruction (ns, function_name, log.error (), *i);
1133- throw 0 ;
1134- }
11351091 }
11361092
11371093 for (size_t outer = 0 ; outer < loop_nesting_graph.size(); ++outer)
@@ -1194,13 +1150,22 @@ void code_contractst::apply_loop_contract(
11941150 loop_node.decreases_clause .is_nil ())
11951151 continue ;
11961152
1153+ // Computed loop "contents" needs to be refreshed to include any newly
1154+ // introduced instrumentation, e.g. havoc instructions for assigns clause,
1155+ // on inner loops in to the outer loop's contents.
1156+ // Else, during the outer loop instrumentation these instructions will be
1157+ // "masked" just as any other instruction not within its "contents."
1158+
1159+ goto_functions.update ();
1160+ natural_loops_mutablet updated_loops (goto_function.body );
1161+
11971162 check_apply_loop_contracts (
11981163 function_name,
11991164 goto_function,
12001165 local_may_alias,
12011166 loop_node.head_target ,
12021167 loop_node.end_target ,
1203- loop_node.content ,
1168+ updated_loops. loop_map [ loop_node.head_target ] ,
12041169 loop_node.assigns_clause ,
12051170 loop_node.invariant ,
12061171 loop_node.decreases_clause ,
0 commit comments