Skip to content

Commit 881b0b4

Browse files
author
zhuyunxing
committed
coverage. Warn about too much decision depth
1 parent 24d2ac0 commit 881b0b4

File tree

3 files changed

+32
-11
lines changed

3 files changed

+32
-11
lines changed

compiler/rustc_mir_build/messages.ftl

+2
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,8 @@ mir_build_deref_raw_pointer_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
105105
106106
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
107107
108+
mir_build_exceeds_mcdc_decision_depth = number of decisions evaluated simultaneously exceeds limit ({$max_decision_depth}). MCDC analysis will not count this expression
109+
108110
mir_build_extern_static_requires_unsafe =
109111
use of extern static is unsafe and requires unsafe block
110112
.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

+22-11
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,17 @@ 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
/// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen,
1616
/// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge.
1717
/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
1818
const MAX_CONDITIONS_IN_DECISION: usize = 6;
1919

20+
/// MCDC allocates an i32 variable on stack for each depth. Ignore decisions nested too much to prevent it
21+
/// consuming excessive memory.
22+
const MAX_DECISION_DEPTH: u16 = 0x3FFF;
23+
2024
#[derive(Default)]
2125
struct MCDCDecisionCtx {
2226
/// To construct condition evaluation tree.
@@ -208,14 +212,14 @@ impl MCDCInfoBuilder {
208212
// is empty, i.e. when all the conditions of the decision were instrumented,
209213
// and the decision is "complete".
210214
if let Some(decision) = decision_result {
211-
match decision.num_conditions {
212-
0 => {
215+
match (decision.num_conditions, decision_depth) {
216+
(0, _) => {
213217
unreachable!("Decision with no condition is not expected");
214218
}
215-
1..=MAX_CONDITIONS_IN_DECISION => {
219+
(1..=MAX_CONDITIONS_IN_DECISION, 0..=MAX_DECISION_DEPTH) => {
216220
self.decision_spans.push(decision);
217221
}
218-
_ => {
222+
(_, _) => {
219223
// Do not generate mcdc mappings and statements for decisions with too many conditions.
220224
// Therefore, first erase the condition info of the (N-1) previous branch spans.
221225
let rebase_idx = self.branch_spans.len() - (decision.num_conditions - 1);
@@ -225,12 +229,19 @@ impl MCDCInfoBuilder {
225229

226230
// Then, erase this last branch span's info too, for a total of N.
227231
condition_info = None;
228-
229-
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
230-
span: decision.span,
231-
num_conditions: decision.num_conditions,
232-
max_conditions: MAX_CONDITIONS_IN_DECISION,
233-
});
232+
if decision.num_conditions > MAX_CONDITIONS_IN_DECISION {
233+
tcx.dcx().emit_warn(MCDCExceedsConditionLimit {
234+
span: decision.span,
235+
num_conditions: decision.num_conditions,
236+
max_conditions: MAX_CONDITIONS_IN_DECISION,
237+
});
238+
}
239+
if decision_depth > MAX_DECISION_DEPTH {
240+
tcx.dcx().emit_warn(MCDCExceedsDecisionDepth {
241+
span: decision.span,
242+
max_decision_depth: MAX_DECISION_DEPTH.into(),
243+
});
244+
}
234245
}
235246
}
236247
}

compiler/rustc_mir_build/src/errors.rs

+8
Original file line numberDiff line numberDiff line change
@@ -844,6 +844,14 @@ pub(crate) struct MCDCExceedsConditionLimit {
844844
pub(crate) max_conditions: usize,
845845
}
846846

847+
#[derive(Diagnostic)]
848+
#[diag(mir_build_exceeds_mcdc_decision_depth)]
849+
pub(crate) struct MCDCExceedsDecisionDepth {
850+
#[primary_span]
851+
pub span: Span,
852+
pub max_decision_depth: usize,
853+
}
854+
847855
#[derive(Diagnostic)]
848856
#[diag(mir_build_pattern_not_covered, code = E0005)]
849857
pub(crate) struct PatternNotCovered<'s, 'tcx> {

0 commit comments

Comments
 (0)