Skip to content

Commit 628c3d0

Browse files
author
zhuyunxing
committed
coverage. Warn about too much decision depth
1 parent 3d24cf9 commit 628c3d0

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

compiler/rustc_mir_build/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,8 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
103103
104104
mir_build_exceeds_mcdc_condition_limit = number of conditions in decision ({$num_conditions}) exceeds limit ({$max_conditions}), so MC/DC analysis will not count this expression
105105
106+
mir_build_exceeds_mcdc_decision_depth = number of decisions evaluated simultaneously exceeds limit ({$max_decision_depth}). MCDC analysis will not count this expression
107+
106108
mir_build_extern_static_requires_unsafe =
107109
use of extern static is unsafe and requires unsafe block
108110
.note = extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior

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

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,16 @@ use rustc_middle::ty::TyCtxt;
1010
use rustc_span::Span;
1111

1212
use crate::build::Builder;
13-
use crate::errors::MCDCExceedsConditionLimit;
13+
use crate::errors::{MCDCExceedsConditionLimit, MCDCExceedsDecisionDepth};
1414

1515
/// LLVM uses `i16` to represent condition id. Hence `i16::MAX` is the hard limit for number of
1616
/// conditions in a decision.
1717
const MAX_CONDITIONS_IN_DECISION: usize = i16::MAX as usize;
1818

19+
/// MCDC allocates an i32 variable on stack for each depth. Ignore decisions nested too much to prevent it
20+
/// consuming excessive memory.
21+
const MAX_DECISION_DEPTH: u16 = 0x3FFF;
22+
1923
#[derive(Default)]
2024
struct MCDCDecisionCtx {
2125
/// To construct condition evaluation tree.
@@ -236,25 +240,34 @@ impl MCDCInfoBuilder {
236240
&mut self.degraded_spans,
237241
) {
238242
let num_conditions = conditions.len();
243+
let depth = decision.decision_depth;
239244
assert_eq!(
240245
num_conditions, decision.num_conditions,
241246
"final number of conditions is not correct"
242247
);
243-
match num_conditions {
244-
0 => {
248+
match (num_conditions, depth) {
249+
(0, _) => {
245250
unreachable!("Decision with no condition is not expected");
246251
}
247-
1..=MAX_CONDITIONS_IN_DECISION => {
252+
(1..=MAX_CONDITIONS_IN_DECISION, 0..=MAX_DECISION_DEPTH) => {
248253
self.mcdc_spans.push((decision, conditions));
249254
}
250255
_ => {
251256
self.degraded_spans.extend(conditions);
252257

253-
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
254-
span: decision.span,
255-
num_conditions,
256-
max_conditions: MAX_CONDITIONS_IN_DECISION,
257-
});
258+
if num_conditions > MAX_CONDITIONS_IN_DECISION {
259+
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
260+
span: decision.span,
261+
num_conditions,
262+
max_conditions: MAX_CONDITIONS_IN_DECISION,
263+
});
264+
}
265+
if depth > MAX_DECISION_DEPTH {
266+
tcx.dcx().emit_warn(MCDCExceedsDecisionDepth {
267+
span: decision.span,
268+
max_decision_depth: MAX_DECISION_DEPTH as usize,
269+
});
270+
}
258271
}
259272
}
260273
}

compiler/rustc_mir_build/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,14 @@ pub(crate) struct MCDCExceedsConditionLimit {
883883
pub(crate) max_conditions: usize,
884884
}
885885

886+
#[derive(Diagnostic)]
887+
#[diag(mir_build_exceeds_mcdc_decision_depth)]
888+
pub(crate) struct MCDCExceedsDecisionDepth {
889+
#[primary_span]
890+
pub span: Span,
891+
pub max_decision_depth: usize,
892+
}
893+
886894
#[derive(Diagnostic)]
887895
#[diag(mir_build_pattern_not_covered, code = E0005)]
888896
pub(crate) struct PatternNotCovered<'s, 'tcx> {

0 commit comments

Comments
 (0)