Skip to content

Commit 6c7c824

Browse files
committed
coverage: Make MCDC take in account last RHS of condition-coverage
Condition coverage extends branch coverage to treat the specific case of last operands of boolean decisions not involved in control flow. This is ultimately made for MCDC to be exhaustive on all boolean expressions. This patch adds a call to `visit_branch_coverage_operation` to track the top-level operand of the said decisions, and changes `visit_coverage_standalone_condition` so MCDC branch registration is called when enabled on these _last RHS_ cases.
1 parent acd6e4c commit 6c7c824

File tree

2 files changed

+48
-23
lines changed

2 files changed

+48
-23
lines changed

compiler/rustc_mir_build/src/build/coverageinfo.rs

+45-23
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,35 @@ impl BranchInfoBuilder {
118118
}
119119
}
120120

121-
fn add_two_way_branch<'tcx>(
121+
fn register_two_way_branch<'tcx>(
122122
&mut self,
123+
tcx: TyCtxt<'tcx>,
123124
cfg: &mut CFG<'tcx>,
124125
source_info: SourceInfo,
125126
true_block: BasicBlock,
126127
false_block: BasicBlock,
127128
) {
128-
let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block);
129-
let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block);
130-
131-
self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker });
129+
// Separate path for handling branches when MC/DC is enabled.
130+
if let Some(mcdc_info) = self.mcdc_info.as_mut() {
131+
let inject_block_marker =
132+
|source_info, block| self.markers.inject_block_marker(cfg, source_info, block);
133+
mcdc_info.visit_evaluated_condition(
134+
tcx,
135+
source_info,
136+
true_block,
137+
false_block,
138+
inject_block_marker,
139+
);
140+
} else {
141+
let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block);
142+
let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block);
143+
144+
self.branch_spans.push(BranchSpan {
145+
span: source_info.span,
146+
true_marker,
147+
false_marker,
148+
});
149+
}
132150
}
133151

134152
pub(crate) fn into_done(self) -> Option<Box<mir::coverage::BranchInfo>> {
@@ -205,7 +223,14 @@ impl<'tcx> Builder<'_, 'tcx> {
205223
mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block),
206224
);
207225

208-
branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block);
226+
// Separate path for handling branches when MC/DC is enabled.
227+
branch_info.register_two_way_branch(
228+
self.tcx,
229+
&mut self.cfg,
230+
source_info,
231+
true_block,
232+
false_block,
233+
);
209234

210235
let join_block = self.cfg.start_new_block();
211236
self.cfg.goto(true_block, source_info, join_block);
@@ -236,22 +261,13 @@ impl<'tcx> Builder<'_, 'tcx> {
236261

237262
let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope };
238263

239-
// Separate path for handling branches when MC/DC is enabled.
240-
if let Some(mcdc_info) = branch_info.mcdc_info.as_mut() {
241-
let inject_block_marker = |source_info, block| {
242-
branch_info.markers.inject_block_marker(&mut self.cfg, source_info, block)
243-
};
244-
mcdc_info.visit_evaluated_condition(
245-
self.tcx,
246-
source_info,
247-
then_block,
248-
else_block,
249-
inject_block_marker,
250-
);
251-
return;
252-
}
253-
254-
branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block);
264+
branch_info.register_two_way_branch(
265+
self.tcx,
266+
&mut self.cfg,
267+
source_info,
268+
then_block,
269+
else_block,
270+
);
255271
}
256272

257273
/// If branch coverage is enabled, inject marker statements into `true_block`
@@ -270,6 +286,12 @@ impl<'tcx> Builder<'_, 'tcx> {
270286
// FIXME(#124144) This may need special handling when MC/DC is enabled.
271287

272288
let source_info = SourceInfo { span: pattern.span, scope: self.source_scope };
273-
branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block);
289+
branch_info.register_two_way_branch(
290+
self.tcx,
291+
&mut self.cfg,
292+
source_info,
293+
true_block,
294+
false_block,
295+
);
274296
}
275297
}

compiler/rustc_mir_build/src/build/expr/into.rs

+3
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
150150
ExprKind::LogicalOp { op, lhs, rhs } => {
151151
let condition_scope = this.local_scope();
152152
let source_info = this.source_info(expr.span);
153+
154+
this.visit_coverage_branch_operation(op, expr.span);
155+
153156
// We first evaluate the left-hand side of the predicate ...
154157
let (then_block, else_block) =
155158
this.in_if_then_scope(condition_scope, expr.span, |this| {

0 commit comments

Comments
 (0)