Skip to content

Commit 0b26d8a

Browse files
zhuyunxingLambdaris
zhuyunxing
authored andcommitted
coverage. Warn about too much decision depth
1 parent a9e7b30 commit 0b26d8a

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

compiler/rustc_mir_build/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
108108
109109
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
110110
111+
mir_build_exceeds_mcdc_decision_depth = number of decisions evaluated simultaneously exceeds limit ({$max_decision_depth}). MCDC analysis will not count this expression
112+
111113
mir_build_extern_static_requires_unsafe =
112114
use of extern static is unsafe and requires unsafe block
113115
.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/builder/coverageinfo/mcdc.rs

+22-9
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::builder::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

+8
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,14 @@ pub(crate) struct MCDCExceedsConditionLimit {
989989
pub(crate) max_conditions: usize,
990990
}
991991

992+
#[derive(Diagnostic)]
993+
#[diag(mir_build_exceeds_mcdc_decision_depth)]
994+
pub(crate) struct MCDCExceedsDecisionDepth {
995+
#[primary_span]
996+
pub span: Span,
997+
pub max_decision_depth: usize,
998+
}
999+
9921000
#[derive(Diagnostic)]
9931001
#[diag(mir_build_pattern_not_covered, code = E0005)]
9941002
pub(crate) struct PatternNotCovered<'s, 'tcx> {

0 commit comments

Comments
 (0)