@@ -15,11 +15,6 @@ use rustc_span::Span;
15
15
use crate :: build:: Builder ;
16
16
use crate :: errors:: { MCDCExceedsConditionLimit , MCDCExceedsDecisionDepth } ;
17
17
18
- /// The MCDC bitmap scales exponentially (2^n) based on the number of conditions seen,
19
- /// So llvm sets a maximum value prevents the bitmap footprint from growing too large without the user's knowledge.
20
- /// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
21
- const MAX_CONDITIONS_IN_DECISION : usize = 6 ;
22
-
23
18
/// MCDC allocates an i32 variable on stack for each depth. Ignore decisions nested too much to prevent it
24
19
/// consuming excessive memory.
25
20
const MAX_DECISION_DEPTH : u16 = 0x3FFF ;
@@ -356,6 +351,7 @@ pub(crate) struct MCDCInfoBuilder {
356
351
mcdc_targets : FxIndexMap < DecisionId , MCDCTargetInfo > ,
357
352
state : MCDCState ,
358
353
decision_id_gen : DecisionIdGen ,
354
+ required_num_test_vectors : usize ,
359
355
}
360
356
361
357
impl MCDCInfoBuilder {
@@ -365,6 +361,7 @@ impl MCDCInfoBuilder {
365
361
mcdc_targets : FxIndexMap :: default ( ) ,
366
362
state : MCDCState :: new ( ) ,
367
363
decision_id_gen : DecisionIdGen :: default ( ) ,
364
+ required_num_test_vectors : 0 ,
368
365
}
369
366
}
370
367
@@ -396,27 +393,30 @@ impl MCDCInfoBuilder {
396
393
conditions : Vec < MCDCBranchSpan > ,
397
394
) -> Option < & mut MCDCTargetInfo > {
398
395
let num_conditions = conditions. len ( ) ;
399
- match num_conditions {
400
- 0 => {
401
- unreachable ! ( "Decision with no condition is not expected" ) ;
402
- }
403
- // Ignore decisions with only one condition given that mcdc for them is completely equivalent to branch coverage.
404
- 2 ..=MAX_CONDITIONS_IN_DECISION => {
405
- let info = MCDCTargetInfo :: new ( decision, conditions) ;
406
- Some ( self . mcdc_targets . entry ( id) . or_insert ( info) )
407
- }
408
- _ => {
409
- self . append_normal_branches ( conditions) ;
410
- if num_conditions > MAX_CONDITIONS_IN_DECISION {
411
- tcx. dcx ( ) . emit_warn ( MCDCExceedsConditionLimit {
412
- span : decision. span ,
413
- num_conditions,
414
- max_conditions : MAX_CONDITIONS_IN_DECISION ,
415
- } ) ;
416
- }
417
- None
418
- }
396
+ let max_conditions = tcx. sess . coverage_mcdc_max_conditions_per_decision ( ) ;
397
+ let max_test_vectors = tcx. sess . coverage_mcdc_max_test_vectors ( ) ;
398
+ // Ignore decisions with only one condition given that mcdc for them is completely equivalent to branch coverage.
399
+ if num_conditions <= 1 {
400
+ return None ;
401
+ }
402
+ if num_conditions > max_conditions {
403
+ self . append_normal_branches ( conditions) ;
404
+ tcx. dcx ( ) . emit_warn ( MCDCExceedsConditionLimit {
405
+ span : decision. span ,
406
+ num_conditions,
407
+ max_conditions,
408
+ } ) ;
409
+ return None ;
419
410
}
411
+
412
+ let info = MCDCTargetInfo :: new ( decision, conditions) ;
413
+ let expected_num_tv = info. decision . num_test_vectors + self . required_num_test_vectors ;
414
+ if expected_num_tv > max_test_vectors {
415
+ self . append_normal_branches ( info. conditions ) ;
416
+ return None ;
417
+ }
418
+
419
+ Some ( self . mcdc_targets . entry ( id) . or_insert ( info) )
420
420
}
421
421
422
422
fn normalize_depth_from ( & mut self , tcx : TyCtxt < ' _ > , id : DecisionId ) {
@@ -499,8 +499,13 @@ impl MCDCInfoBuilder {
499
499
pub ( crate ) fn into_done (
500
500
self ,
501
501
) -> ( Vec < MCDCBranchSpan > , Vec < ( MCDCDecisionSpan , Vec < MCDCBranchSpan > ) > ) {
502
- let MCDCInfoBuilder { normal_branch_spans, mcdc_targets, state : _, decision_id_gen : _ } =
503
- self ;
502
+ let MCDCInfoBuilder {
503
+ normal_branch_spans,
504
+ mcdc_targets,
505
+ state : _,
506
+ decision_id_gen : _,
507
+ required_num_test_vectors : _,
508
+ } = self ;
504
509
505
510
let mcdc_spans = mcdc_targets
506
511
. into_values ( )
0 commit comments