Skip to content

Commit 6f39e6f

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 27f2db6 commit 6f39e6f

File tree

2 files changed

+51
-23
lines changed

2 files changed

+51
-23
lines changed

compiler/rustc_mir_build/src/build/coverageinfo.rs

+46-22
Original file line numberDiff line numberDiff line change
@@ -118,17 +118,37 @@ 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);
129+
let this = self;
130130

131-
self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker });
131+
// Separate path for handling branches when MC/DC is enabled.
132+
if let Some(mcdc_info) = this.mcdc_info.as_mut() {
133+
let inject_block_marker =
134+
|source_info, block| this.markers.inject_block_marker(cfg, source_info, block);
135+
mcdc_info.visit_evaluated_condition(
136+
tcx,
137+
source_info,
138+
true_block,
139+
false_block,
140+
inject_block_marker,
141+
);
142+
} else {
143+
let true_marker = this.markers.inject_block_marker(cfg, source_info, true_block);
144+
let false_marker = this.markers.inject_block_marker(cfg, source_info, false_block);
145+
146+
this.branch_spans.push(BranchSpan {
147+
span: source_info.span,
148+
true_marker,
149+
false_marker,
150+
});
151+
}
132152
}
133153

134154
pub(crate) fn into_done(self) -> Option<Box<mir::coverage::BranchInfo>> {
@@ -205,7 +225,14 @@ impl<'tcx> Builder<'_, 'tcx> {
205225
mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block),
206226
);
207227

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

210237
let join_block = self.cfg.start_new_block();
211238
self.cfg.goto(true_block, source_info, join_block);
@@ -236,22 +263,13 @@ impl<'tcx> Builder<'_, 'tcx> {
236263

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

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);
266+
branch_info.register_two_way_branch(
267+
self.tcx,
268+
&mut self.cfg,
269+
source_info,
270+
then_block,
271+
else_block,
272+
);
255273
}
256274

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

272290
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);
291+
branch_info.register_two_way_branch(
292+
self.tcx,
293+
&mut self.cfg,
294+
source_info,
295+
true_block,
296+
false_block,
297+
);
274298
}
275299
}

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

+5-1
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
149149
}
150150
ExprKind::LogicalOp { op, lhs, rhs } => {
151151
let condition_scope = this.local_scope();
152-
let source_info = this.source_info(expr.span);
152+
let expr_span = expr.span;
153+
let source_info = this.source_info(expr_span);
154+
155+
this.visit_coverage_branch_operation(op, expr_span);
156+
153157
// We first evaluate the left-hand side of the predicate ...
154158
let (then_block, else_block) =
155159
this.in_if_then_scope(condition_scope, expr.span, |this| {

0 commit comments

Comments
 (0)