1
Fork 0

Only generate dummy assign when instrumenting coverage

And make the LocalDecl internal, to avoid needing to declare storage.
(For multiple `continue` stateuemtns, it must also be mutable.)
This commit is contained in:
Rich Kadel 2021-04-18 11:51:42 -07:00
parent 448e52d97c
commit d1d7fb1ae5
2 changed files with 15 additions and 14 deletions

View file

@ -618,16 +618,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
} else {
assert!(value.is_none(), "`return` and `break` should have a destination");
// `continue` statements generate no MIR statement with the `continue` statement's Span,
// and the `InstrumentCoverage` statement will have no way to generate a coverage
// code region for the `continue` statement, unless we add a dummy `Assign` here:
let mut local_decl = LocalDecl::new(self.tcx.mk_unit(), span);
local_decl = local_decl.immutable();
let temp = self.local_decls.push(local_decl);
let temp_place = Place::from(temp);
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageDead(temp) });
if self.tcx.sess.instrument_coverage() {
// Unlike `break` and `return`, which push an `Assign` statement to MIR, from which
// a Coverage code region can be generated, `continue` needs no `Assign`; but
// without one, the `InstrumentCoverage` MIR pass cannot generate a code region for
// `continue`. Coverage will be missing unless we add a dummy `Assign` to MIR.
self.add_dummy_assignment(&span, block, source_info);
}
}
let region_scope = self.scopes.breakable_scopes[break_index].region_scope;
@ -653,6 +650,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.start_new_block().unit()
}
// Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
// statement.
fn add_dummy_assignment(&mut self, span: &Span, block: BasicBlock, source_info: SourceInfo) {
let local_decl = LocalDecl::new(self.tcx.mk_unit(), *span).internal();
let temp_place = Place::from(self.local_decls.push(local_decl));
self.cfg.push_assign_unit(block, source_info, temp_place, self.tcx);
}
crate fn exit_top_scope(
&mut self,
mut block: BasicBlock,