@@ -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`.
@@ -1081,11 +1082,9 @@ void code_contractst::apply_loop_contract(
10811082 // By definition the `loop_content` is a set of instructions computed
10821083 // by `natural_loops` based on the CFG.
10831084 // Since we perform assigns clause instrumentation by sequentially
1084- // traversing instructions from `loop_head` to `loop_end`, here check that:
1085- // 1. All instructions in `loop_content` are contained within the
1086- // [loop_head, loop_end] iterator range
1087- // 2. All instructions in the [loop_head, loop_end] range are contained
1088- // in the `loop_content` set, except for the exceptions explained below.
1085+ // traversing instructions from `loop_head` to `loop_end`,
1086+ // here we ensure that all instructions in `loop_content` belong within
1087+ // the [loop_head, loop_end] target range
10891088
10901089 // Check 1. (i \in loop_content) ==> loop_head <= i <= loop_end
10911090 for (const auto &i : loop_content)
@@ -1100,49 +1099,6 @@ void code_contractst::apply_loop_contract(
11001099 throw 0 ;
11011100 }
11021101 }
1103-
1104- // Check 2. (loop_head <= i <= loop_end) ==> (i \in loop_content)
1105- //
1106- // We allow the following exceptions in this check:
1107- // - `SKIP` or `LOCATION` instructions which are no-op
1108- // - `ASSUME(false)` instructions which are introduced by function pointer
1109- // or nested loop transformations, and have no successor instructions
1110- // - `SET_RETURN_VALUE` instructions followed by an uninterrupted sequence
1111- // of `DEAD` instructions and a `GOTO` jump out of the loop,
1112- // which model C `return` statements.
1113- // - `GOTO` jumps out of the loops, which model C `break` statements.
1114- // These instructions are allowed to be missing from `loop_content`,
1115- // and may be safely ignored for the purpose of our instrumentation.
1116- for (auto i = loop_head; i != loop_end; ++i)
1117- {
1118- if (loop_content.contains (i))
1119- continue ;
1120-
1121- if (i->is_skip () || i->is_location ())
1122- continue ;
1123-
1124- if (i->is_goto () && !loop_content.contains (i->get_target ()))
1125- continue ;
1126-
1127- if (i->is_assume () && i->get_condition ().is_false ())
1128- continue ;
1129-
1130- if (i->is_set_return_value ())
1131- {
1132- do
1133- i++;
1134- while (i != loop_end && i->is_dead ());
1135-
1136- // because we increment `i` in the outer `for` loop
1137- i--;
1138- continue ;
1139- }
1140-
1141- log.error () << " Computed loop at: " << loop_head->source_location ()
1142- << " is missing an instruction:" << messaget::eom;
1143- goto_function.body .output_instruction (ns, function_name, log.error (), *i);
1144- throw 0 ;
1145- }
11461102 }
11471103
11481104 for (size_t outer = 0 ; outer < loop_nesting_graph.size(); ++outer)
@@ -1205,13 +1161,22 @@ void code_contractst::apply_loop_contract(
12051161 loop_node.decreases_clause .is_nil ())
12061162 continue ;
12071163
1164+ // Computed loop "contents" needs to be refreshed to include any newly
1165+ // introduced instrumentation, e.g. havoc instructions for assigns clause,
1166+ // on inner loops in to the outer loop's contents.
1167+ // Else, during the outer loop instrumentation these instructions will be
1168+ // "masked" just as any other instruction not within its "contents."
1169+
1170+ goto_functions.update ();
1171+ natural_loops_mutablet updated_loops (goto_function.body );
1172+
12081173 check_apply_loop_contracts (
12091174 function_name,
12101175 goto_function,
12111176 local_may_alias,
12121177 loop_node.head_target ,
12131178 loop_node.end_target ,
1214- loop_node.content ,
1179+ updated_loops. loop_map [ loop_node.head_target ] ,
12151180 loop_node.assigns_clause ,
12161181 loop_node.invariant ,
12171182 loop_node.decreases_clause ,
0 commit comments