Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 2263a41

Browse files
author
zhuyunxing
committedApr 23, 2024·
coverage. Implement branch coverage in mcdc for pattern match
1 parent 9cf10bc commit 2263a41

File tree

8 files changed

+283
-16
lines changed

8 files changed

+283
-16
lines changed
 

‎compiler/rustc_middle/src/mir/coverage.rs

+11
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,7 @@ pub struct BranchInfo {
281281
pub num_block_markers: usize,
282282
pub branch_spans: Vec<BranchSpan>,
283283
pub mcdc_branch_spans: Vec<MCDCBranchSpan>,
284+
pub mcdc_match_branch_spans: Vec<MCDCMatchBranchSpan>,
284285
pub mcdc_decision_spans: Vec<MCDCDecisionSpan>,
285286
}
286287

@@ -321,6 +322,16 @@ pub struct MCDCBranchSpan {
321322
pub false_marker: BlockMarkerId,
322323
}
323324

325+
#[derive(Clone, Debug)]
326+
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
327+
pub struct MCDCMatchBranchSpan {
328+
pub span: Span,
329+
pub condition_info: Option<ConditionInfo>,
330+
pub test_markers: Vec<BlockMarkerId>,
331+
pub true_markers: Vec<BlockMarkerId>,
332+
pub substract_markers: Vec<BlockMarkerId>,
333+
}
334+
324335
#[derive(Copy, Clone, Debug)]
325336
#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)]
326337
pub struct DecisionInfo {

‎compiler/rustc_middle/src/mir/pretty.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -485,12 +485,16 @@ fn write_coverage_branch_info(
485485
)?;
486486
}
487487

488-
for coverage::MCDCBranchSpan { span, condition_info, true_marker, false_marker } in
489-
mcdc_branch_spans
488+
for coverage::MCDCBranchSpan {
489+
span,
490+
condition_info,
491+
true_marker: true_markers,
492+
false_marker: false_markers,
493+
} in mcdc_branch_spans
490494
{
491495
writeln!(
492496
w,
493-
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_marker:?}, false: {false_marker:?} }} => {span:?}",
497+
"{INDENT}coverage mcdc branch {{ condition_id: {:?}, true: {true_markers:?}, false: {false_markers:?} }} => {span:?}",
494498
condition_info.map(|info| info.condition_id)
495499
)?;
496500
}

‎compiler/rustc_mir_build/src/build/coverageinfo.rs

+92-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::assert_matches::assert_matches;
22
use std::collections::hash_map::Entry;
3-
use std::collections::VecDeque;
3+
use std::collections::{BTreeMap, VecDeque};
44

55
use rustc_data_structures::fx::FxHashMap;
66
use rustc_middle::mir::coverage::{
77
BlockMarkerId, BranchSpan, ConditionId, ConditionInfo, CoverageKind, MCDCBranchSpan,
8-
MCDCDecisionSpan,
8+
MCDCDecisionSpan, MCDCMatchBranchSpan,
99
};
10-
use rustc_middle::mir::{self, BasicBlock, SourceInfo, UnOp};
10+
use rustc_middle::mir::{self, BasicBlock, SourceInfo, StatementKind, UnOp};
1111
use rustc_middle::thir::{ExprId, ExprKind, LogicalOp, Thir};
1212
use rustc_middle::ty::TyCtxt;
1313
use rustc_span::def_id::LocalDefId;
@@ -22,7 +22,8 @@ pub(crate) struct BranchInfoBuilder {
2222

2323
num_block_markers: usize,
2424
branch_spans: Vec<BranchSpan>,
25-
25+
pattern_match_branch_records: BTreeMap<Span, MCDCMatchBranchSpan>,
26+
markers_map: BTreeMap<usize, BasicBlock>,
2627
mcdc_branch_spans: Vec<MCDCBranchSpan>,
2728
mcdc_decision_spans: Vec<MCDCDecisionSpan>,
2829
mcdc_state: Option<MCDCState>,
@@ -47,6 +48,8 @@ impl BranchInfoBuilder {
4748
nots: FxHashMap::default(),
4849
num_block_markers: 0,
4950
branch_spans: vec![],
51+
pattern_match_branch_records: BTreeMap::new(),
52+
markers_map: Default::default(),
5053
mcdc_branch_spans: vec![],
5154
mcdc_decision_spans: vec![],
5255
mcdc_state: MCDCState::new_if_enabled(tcx),
@@ -175,6 +178,8 @@ impl BranchInfoBuilder {
175178
nots: _,
176179
num_block_markers,
177180
branch_spans,
181+
pattern_match_branch_records,
182+
markers_map: _,
178183
mcdc_branch_spans,
179184
mcdc_decision_spans,
180185
mcdc_state: _,
@@ -184,11 +189,24 @@ impl BranchInfoBuilder {
184189
assert!(branch_spans.is_empty());
185190
return None;
186191
}
192+
let mut mcdc_match_branch_spans =
193+
pattern_match_branch_records.into_values().collect::<Vec<_>>();
194+
mcdc_match_branch_spans.sort_by(|a, b| {
195+
if a.span.contains(b.span) { std::cmp::Ordering::Less } else { a.span.cmp(&b.span) }
196+
});
197+
for idx in 0..(mcdc_match_branch_spans.len() - 1) {
198+
if mcdc_match_branch_spans[idx].span.contains(mcdc_match_branch_spans[idx + 1].span) {
199+
let refined_span =
200+
mcdc_match_branch_spans[idx].span.until(mcdc_match_branch_spans[idx + 1].span);
201+
mcdc_match_branch_spans[idx].span = refined_span;
202+
}
203+
}
187204

188205
Some(Box::new(mir::coverage::BranchInfo {
189206
num_block_markers,
190207
branch_spans,
191208
mcdc_branch_spans,
209+
mcdc_match_branch_spans,
192210
mcdc_decision_spans,
193211
}))
194212
}
@@ -385,4 +403,74 @@ impl Builder<'_, '_> {
385403
mcdc_state.record_conditions(logical_op, span);
386404
}
387405
}
406+
407+
pub(crate) fn visit_coverage_mcdc_match_arms(
408+
&mut self,
409+
test_block: BasicBlock,
410+
targets: impl Iterator<Item = (Span, BasicBlock)>,
411+
) {
412+
if self.tcx.sess.instrument_coverage_mcdc() {
413+
return;
414+
}
415+
let mut markers_map = BTreeMap::<usize, BasicBlock>::new();
416+
let mut get_marker_id = |span, block| {
417+
self.cfg
418+
.block_data_mut(block)
419+
.statements
420+
.iter()
421+
.find_map(|statement| match statement.kind {
422+
StatementKind::Coverage(CoverageKind::BlockMarker { id }) => Some(id),
423+
_ => None,
424+
})
425+
.unwrap_or_else(|| {
426+
let source_info = self.source_info(span);
427+
let id = self
428+
.coverage_branch_info
429+
.as_mut()
430+
.expect("Checked at entry of the function")
431+
.next_block_marker_id();
432+
433+
let marker_statement = mir::Statement {
434+
source_info,
435+
kind: mir::StatementKind::Coverage(CoverageKind::BlockMarker { id }),
436+
};
437+
markers_map.insert(id.as_usize(), block);
438+
self.cfg.push(block, marker_statement);
439+
id
440+
})
441+
};
442+
let test_block_id = get_marker_id(Span::default(), test_block);
443+
444+
let mut targets = targets
445+
.map(|(span, block)| {
446+
let marker_id = get_marker_id(span, block);
447+
(span, marker_id)
448+
})
449+
.collect::<Vec<_>>();
450+
451+
let branch_records = self
452+
.coverage_branch_info
453+
.as_mut()
454+
.map(|branch_info| {
455+
branch_info.markers_map.extend(markers_map);
456+
&mut branch_info.pattern_match_branch_records
457+
})
458+
.expect("Checked at entry of the function");
459+
460+
while let Some((span, matched_block)) = targets.pop() {
461+
// By here we do not know the span of the target yet, so just record the
462+
// basic blocks and insert BlockMarkerId later.
463+
let record = branch_records.entry(span).or_insert_with(|| MCDCMatchBranchSpan {
464+
span,
465+
condition_info: None,
466+
test_markers: vec![],
467+
true_markers: vec![],
468+
substract_markers: vec![],
469+
});
470+
record.test_markers.push(test_block_id);
471+
record.true_markers.push(matched_block);
472+
473+
record.substract_markers.extend(targets.iter().map(|(_, blk)| *blk));
474+
}
475+
}
388476
}

‎compiler/rustc_mir_build/src/build/matches/mod.rs

+28
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18571857
// Extract the match-pair from the highest priority candidate and build a test from it.
18581858
let (match_place, test) = self.pick_test(candidates);
18591859

1860+
// Patterns like `Some(A) | Some(B)` need spans for their target branches separately.
1861+
// Keep it in original order so that true arms of the laters won't be counted as false arms of the formers.
1862+
let mut coverage_targets: Vec<_> = candidates
1863+
.iter()
1864+
.filter_map(|candidate| {
1865+
candidate.match_pairs.first().map(|matched_pair| {
1866+
(candidate.extra_data.span, (matched_pair.pattern.span, None))
1867+
})
1868+
})
1869+
.collect();
1870+
1871+
let mut set_coverage_matched_blk = |pattern_span: Span, blk: BasicBlock| {
1872+
*coverage_targets
1873+
.iter_mut()
1874+
.find_map(|(span, (_, blk_opt))| (*span == pattern_span).then_some(blk_opt))
1875+
.expect("target_candidates only are part of candidates") = Some(blk);
1876+
};
1877+
18601878
// For each of the N possible test outcomes, build the vector of candidates that applies if
18611879
// the test has that particular outcome.
18621880
let (remaining_candidates, target_candidates) =
@@ -1883,6 +1901,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18831901
.into_iter()
18841902
.map(|(branch, mut candidates)| {
18851903
let candidate_start = self.cfg.start_new_block();
1904+
set_coverage_matched_blk(
1905+
candidates.first().expect("candidates must be not empty").extra_data.span,
1906+
candidate_start,
1907+
);
18861908
self.match_candidates(
18871909
span,
18881910
scrutinee_span,
@@ -1894,6 +1916,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
18941916
})
18951917
.collect();
18961918

1919+
self.visit_coverage_mcdc_match_arms(
1920+
start_block,
1921+
coverage_targets.into_iter().filter_map(|(_, (span, matched_target_block))| {
1922+
matched_target_block.map(|blk| (span, blk))
1923+
}),
1924+
);
18971925
// Perform the test, branching to one of N blocks.
18981926
self.perform_test(
18991927
span,

‎compiler/rustc_mir_transform/src/coverage/counters.rs

+23-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use std::fmt::{self, Debug};
1+
use std::{
2+
collections::BTreeMap,
3+
fmt::{self, Debug},
4+
};
25

36
use rustc_data_structures::captures::Captures;
47
use rustc_data_structures::fx::FxHashMap;
@@ -58,6 +61,8 @@ pub(super) struct CoverageCounters {
5861
/// Table of expression data, associating each expression ID with its
5962
/// corresponding operator (+ or -) and its LHS/RHS operands.
6063
expressions: IndexVec<ExpressionId, Expression>,
64+
65+
branch_sum_expressions: BTreeMap<BasicCoverageBlock, Vec<ExpressionId>>,
6166
}
6267

6368
impl CoverageCounters {
@@ -75,6 +80,7 @@ impl CoverageCounters {
7580
bcb_counters: IndexVec::from_elem_n(None, num_bcbs),
7681
bcb_edge_counters: FxHashMap::default(),
7782
expressions: IndexVec::new(),
83+
branch_sum_expressions: BTreeMap::new(),
7884
};
7985

8086
MakeBcbCounters::new(&mut this, basic_coverage_blocks)
@@ -88,7 +94,7 @@ impl CoverageCounters {
8894
BcbCounter::Counter { id }
8995
}
9096

91-
fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
97+
pub fn make_expression(&mut self, lhs: BcbCounter, op: Op, rhs: BcbCounter) -> BcbCounter {
9298
let expression = Expression { lhs: lhs.as_term(), op, rhs: rhs.as_term() };
9399
let id = self.expressions.push(expression);
94100
BcbCounter::Expression { id }
@@ -97,7 +103,11 @@ impl CoverageCounters {
97103
/// Variant of `make_expression` that makes `lhs` optional and assumes [`Op::Add`].
98104
///
99105
/// This is useful when using [`Iterator::fold`] to build an arbitrary-length sum.
100-
fn make_sum_expression(&mut self, lhs: Option<BcbCounter>, rhs: BcbCounter) -> BcbCounter {
106+
pub(super) fn make_sum_expression(
107+
&mut self,
108+
lhs: Option<BcbCounter>,
109+
rhs: BcbCounter,
110+
) -> BcbCounter {
101111
let Some(lhs) = lhs else { return rhs };
102112
self.make_expression(lhs, Op::Add, rhs)
103113
}
@@ -138,6 +148,10 @@ impl CoverageCounters {
138148
}
139149
}
140150

151+
pub(super) fn set_bcb_branch_sum_expr(&mut self, bcb: BasicCoverageBlock, expr: ExpressionId) {
152+
self.branch_sum_expressions.entry(bcb).or_default().push(expr);
153+
}
154+
141155
pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
142156
self.bcb_counters[bcb]
143157
}
@@ -164,6 +178,12 @@ impl CoverageCounters {
164178
})
165179
}
166180

181+
pub(super) fn bcb_nodes_with_branch_sum_expressions(
182+
&self,
183+
) -> impl Iterator<Item = (BasicCoverageBlock, &[ExpressionId])> {
184+
self.branch_sum_expressions.iter().map(|(bcb, exprs)| (*bcb, exprs.as_slice()))
185+
}
186+
167187
pub(super) fn into_expressions(self) -> IndexVec<ExpressionId, Expression> {
168188
self.expressions
169189
}

‎compiler/rustc_mir_transform/src/coverage/mod.rs

+71-3
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use self::counters::{CounterIncrementSite, CoverageCounters};
1111
use self::graph::{BasicCoverageBlock, CoverageGraph};
1212
use self::spans::{BcbBranchPair, BcbMapping, BcbMappingKind, CoverageSpans};
1313

14+
use crate::coverage::counters::BcbCounter;
1415
use crate::MirPass;
1516

1617
use rustc_middle::mir::coverage::*;
@@ -83,10 +84,10 @@ fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>, mir_body: &mut mir:
8384
// and all `Expression` dependencies (operands) are also generated, for any other
8485
// `BasicCoverageBlock`s not already associated with a coverage span.
8586
let bcb_has_coverage_spans = |bcb| coverage_spans.bcb_has_coverage_spans(bcb);
86-
let coverage_counters =
87+
let mut coverage_counters =
8788
CoverageCounters::make_bcb_counters(&basic_coverage_blocks, bcb_has_coverage_spans);
8889

89-
let mappings = create_mappings(tcx, &hir_info, &coverage_spans, &coverage_counters);
90+
let mappings = create_mappings(tcx, &hir_info, &coverage_spans, &mut coverage_counters);
9091
if mappings.is_empty() {
9192
// No spans could be converted into valid mappings, so skip this function.
9293
debug!("no spans could be converted into valid mappings; skipping");
@@ -120,7 +121,7 @@ fn create_mappings<'tcx>(
120121
tcx: TyCtxt<'tcx>,
121122
hir_info: &ExtractedHirInfo,
122123
coverage_spans: &CoverageSpans,
123-
coverage_counters: &CoverageCounters,
124+
coverage_counters: &mut CoverageCounters,
124125
) -> Vec<Mapping> {
125126
let source_map = tcx.sess.source_map();
126127
let body_span = hir_info.body_span;
@@ -160,6 +161,9 @@ fn create_mappings<'tcx>(
160161
false_term: term_for_bcb(false_bcb),
161162
mcdc_params,
162163
},
164+
BcbMappingKind::MCDCMatchBranch { .. } => {
165+
return None;
166+
}
163167
BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
164168
MappingKind::MCDCDecision(DecisionInfo { bitmap_idx, conditions_num })
165169
}
@@ -179,9 +183,63 @@ fn create_mappings<'tcx>(
179183
},
180184
));
181185

186+
mappings.extend(create_mcdc_match_mappings(coverage_spans, coverage_counters, |span| {
187+
make_code_region(source_map, file_name, span, body_span)
188+
}));
189+
182190
mappings
183191
}
184192

193+
fn create_mcdc_match_mappings(
194+
coverage_spans: &CoverageSpans,
195+
coverage_counters: &mut CoverageCounters,
196+
get_code_region: impl Fn(Span) -> Option<CodeRegion>,
197+
) -> Vec<Mapping> {
198+
coverage_spans
199+
.mappings
200+
.iter()
201+
.filter_map(|mapping| match mapping.kind {
202+
BcbMappingKind::MCDCMatchBranch {
203+
ref true_bcbs,
204+
ref test_bcbs,
205+
prebinding_bcbs: ref prebingding_bcbs,
206+
..
207+
} => {
208+
let used_block = true_bcbs[0];
209+
let mut calc_exprs = |bcbs: &[BasicCoverageBlock]| {
210+
bcbs.iter()
211+
.map(|bcb| coverage_counters.bcb_counter(*bcb))
212+
.collect::<Option<Vec<_>>>()
213+
.and_then(|counters| {
214+
counters.into_iter().fold(None, |acc, counter| {
215+
Some(coverage_counters.make_sum_expression(acc, counter))
216+
})
217+
})
218+
};
219+
let true_expr = calc_exprs(true_bcbs).expect("true blocks must not be empty");
220+
let test_expr = calc_exprs(test_bcbs).expect("test blocks must not be empty");
221+
let prebinding_expr = calc_exprs(prebingding_bcbs);
222+
let true_term = true_expr.as_term();
223+
let exclude_expr =
224+
coverage_counters.make_sum_expression(prebinding_expr, true_expr);
225+
let false_expr =
226+
coverage_counters.make_expression(test_expr, Op::Subtract, exclude_expr);
227+
let false_term = false_expr.as_term();
228+
if let BcbCounter::Expression { id } = true_expr {
229+
coverage_counters.set_bcb_branch_sum_expr(used_block, id);
230+
}
231+
if let BcbCounter::Expression { id } = false_expr {
232+
coverage_counters.set_bcb_branch_sum_expr(used_block, id);
233+
}
234+
235+
let kind = MappingKind::Branch { true_term, false_term };
236+
get_code_region(mapping.span).map(|code_region| Mapping { kind, code_region })
237+
}
238+
_ => None,
239+
})
240+
.collect()
241+
}
242+
185243
/// For each BCB node or BCB edge that has an associated coverage counter,
186244
/// inject any necessary coverage statements into MIR.
187245
fn inject_coverage_statements<'tcx>(
@@ -232,6 +290,16 @@ fn inject_coverage_statements<'tcx>(
232290
basic_coverage_blocks[bcb].leader_bb(),
233291
);
234292
}
293+
294+
for (bcb, expressions) in coverage_counters.bcb_nodes_with_branch_sum_expressions() {
295+
expressions.into_iter().for_each(|&id| {
296+
inject_statement(
297+
mir_body,
298+
CoverageKind::ExpressionUsed { id },
299+
basic_coverage_blocks[bcb].leader_bb(),
300+
);
301+
});
302+
}
235303
}
236304

237305
/// For each conditions inject statements to update condition bitmap after it has been evaluated.

‎compiler/rustc_mir_transform/src/coverage/spans.rs

+20
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ pub(super) enum BcbMappingKind {
2727
/// for code that was too complex for MC/DC.
2828
condition_info: Option<ConditionInfo>,
2929
},
30+
MCDCMatchBranch {
31+
true_bcbs: Vec<BasicCoverageBlock>,
32+
test_bcbs: Vec<BasicCoverageBlock>,
33+
prebinding_bcbs: Vec<BasicCoverageBlock>,
34+
#[allow(unused)]
35+
condition_info: Option<ConditionInfo>,
36+
},
3037
/// Associates a mcdc decision with its join BCB.
3138
MCDCDecision { end_bcbs: BTreeSet<BasicCoverageBlock>, bitmap_idx: u32, conditions_num: u16 },
3239
}
@@ -126,6 +133,19 @@ pub(super) fn generate_coverage_spans(
126133
insert(true_bcb);
127134
insert(false_bcb);
128135
}
136+
BcbMappingKind::MCDCMatchBranch {
137+
ref true_bcbs,
138+
ref test_bcbs,
139+
prebinding_bcbs: ref prebingding_bcbs,
140+
..
141+
} => {
142+
true_bcbs
143+
.iter()
144+
.chain(test_bcbs.iter())
145+
.chain(prebingding_bcbs)
146+
.copied()
147+
.for_each(&mut insert);
148+
}
129149
BcbMappingKind::MCDCDecision { bitmap_idx, conditions_num, .. } => {
130150
// `bcb_has_mappings` is used for inject coverage counters
131151
// but they are not needed for decision BCBs.

‎compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_data_structures::captures::Captures;
22
use rustc_data_structures::fx::FxHashSet;
33
use rustc_index::IndexVec;
44
use rustc_middle::mir::coverage::{
5-
BlockMarkerId, BranchSpan, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan,
5+
BlockMarkerId, BranchSpan, CoverageKind, MCDCBranchSpan, MCDCDecisionSpan, MCDCMatchBranchSpan,
66
};
77
use rustc_middle::mir::{
88
self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
@@ -462,6 +462,31 @@ pub(super) fn extract_mcdc_mappings(
462462
},
463463
)
464464
};
465+
let mcdc_match_branch_filter_map = |&MCDCMatchBranchSpan {
466+
span: raw_span,
467+
ref test_markers,
468+
ref true_markers,
469+
ref substract_markers,
470+
condition_info,
471+
}| {
472+
if !raw_span.ctxt().outer_expn_data().is_root() {
473+
return None;
474+
}
475+
let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?;
476+
let test_bcbs = test_markers.iter().copied().map(bcb_from_marker).collect::<Option<_>>()?;
477+
let true_bcbs = true_markers.iter().copied().map(bcb_from_marker).collect::<Option<_>>()?;
478+
let prebinding_bcbs =
479+
substract_markers.iter().copied().map(bcb_from_marker).collect::<Option<_>>()?;
480+
Some(BcbMapping {
481+
kind: BcbMappingKind::MCDCMatchBranch {
482+
test_bcbs,
483+
true_bcbs,
484+
prebinding_bcbs,
485+
condition_info,
486+
},
487+
span,
488+
})
489+
};
465490

466491
let mut next_bitmap_idx = 0;
467492

@@ -471,8 +496,10 @@ pub(super) fn extract_mcdc_mappings(
471496
let end_bcbs = decision
472497
.end_markers
473498
.iter()
474-
.map(|&marker| bcb_from_marker(marker))
475-
.collect::<Option<_>>()?;
499+
.copied()
500+
.map(bcb_from_marker)
501+
.collect::<Option<_>>()
502+
.expect("all markers must be located in a bcb");
476503

477504
let bitmap_idx = next_bitmap_idx;
478505
next_bitmap_idx += (1_u32 << decision.conditions_num).div_ceil(8);
@@ -489,6 +516,7 @@ pub(super) fn extract_mcdc_mappings(
489516

490517
std::iter::empty()
491518
.chain(branch_info.mcdc_branch_spans.iter().filter_map(mcdc_branch_filter_map))
519+
.chain(branch_info.mcdc_match_branch_spans.iter().filter_map(mcdc_match_branch_filter_map))
492520
.chain(branch_info.mcdc_decision_spans.iter().filter_map(decision_filter_map))
493521
.collect::<Vec<_>>()
494522
}

0 commit comments

Comments
 (0)
Please sign in to comment.