@@ -7,13 +7,13 @@ use rustc_middle::mir::coverage::{
7
7
BlockMarkerId , BranchSpan , ConditionId , ConditionInfo , CoverageKind , MCDCBranchSpan ,
8
8
MCDCDecisionSpan ,
9
9
} ;
10
- use rustc_middle:: mir:: { self , BasicBlock , UnOp } ;
10
+ use rustc_middle:: mir:: { self , BasicBlock , SourceInfo , UnOp } ;
11
11
use rustc_middle:: thir:: { ExprId , ExprKind , LogicalOp , Thir } ;
12
12
use rustc_middle:: ty:: TyCtxt ;
13
13
use rustc_span:: def_id:: LocalDefId ;
14
14
use rustc_span:: Span ;
15
15
16
- use crate :: build:: Builder ;
16
+ use crate :: build:: { Builder , CFG } ;
17
17
use crate :: errors:: MCDCExceedsConditionNumLimit ;
18
18
19
19
pub ( crate ) struct BranchInfoBuilder {
@@ -22,6 +22,7 @@ pub(crate) struct BranchInfoBuilder {
22
22
23
23
num_block_markers : usize ,
24
24
branch_spans : Vec < BranchSpan > ,
25
+
25
26
mcdc_branch_spans : Vec < MCDCBranchSpan > ,
26
27
mcdc_decision_spans : Vec < MCDCDecisionSpan > ,
27
28
mcdc_state : Option < MCDCState > ,
@@ -95,13 +96,7 @@ impl BranchInfoBuilder {
95
96
}
96
97
}
97
98
98
- fn record_conditions_operation ( & mut self , logical_op : LogicalOp , span : Span ) {
99
- if let Some ( mcdc_state) = self . mcdc_state . as_mut ( ) {
100
- mcdc_state. record_conditions ( logical_op, span) ;
101
- }
102
- }
103
-
104
- fn fetch_condition_info (
99
+ fn fetch_mcdc_condition_info (
105
100
& mut self ,
106
101
tcx : TyCtxt < ' _ > ,
107
102
true_marker : BlockMarkerId ,
@@ -121,14 +116,9 @@ impl BranchInfoBuilder {
121
116
_ => {
122
117
// Do not generate mcdc mappings and statements for decisions with too many conditions.
123
118
let rebase_idx = self . mcdc_branch_spans . len ( ) - decision. conditions_num + 1 ;
124
- let to_normal_branches = self . mcdc_branch_spans . split_off ( rebase_idx) ;
125
- self . branch_spans . extend ( to_normal_branches. into_iter ( ) . map (
126
- |MCDCBranchSpan { span, true_marker, false_marker, .. } | BranchSpan {
127
- span,
128
- true_marker,
129
- false_marker,
130
- } ,
131
- ) ) ;
119
+ for branch in & mut self . mcdc_branch_spans [ rebase_idx..] {
120
+ branch. condition_info = None ;
121
+ }
132
122
133
123
// ConditionInfo of this branch shall also be reset.
134
124
condition_info = None ;
@@ -144,20 +134,50 @@ impl BranchInfoBuilder {
144
134
condition_info
145
135
}
146
136
137
+ fn add_two_way_branch < ' tcx > (
138
+ & mut self ,
139
+ cfg : & mut CFG < ' tcx > ,
140
+ source_info : SourceInfo ,
141
+ true_block : BasicBlock ,
142
+ false_block : BasicBlock ,
143
+ ) {
144
+ let true_marker = self . inject_block_marker ( cfg, source_info, true_block) ;
145
+ let false_marker = self . inject_block_marker ( cfg, source_info, false_block) ;
146
+
147
+ self . branch_spans . push ( BranchSpan { span : source_info. span , true_marker, false_marker } ) ;
148
+ }
149
+
147
150
fn next_block_marker_id ( & mut self ) -> BlockMarkerId {
148
151
let id = BlockMarkerId :: from_usize ( self . num_block_markers ) ;
149
152
self . num_block_markers += 1 ;
150
153
id
151
154
}
152
155
156
+ fn inject_block_marker (
157
+ & mut self ,
158
+ cfg : & mut CFG < ' _ > ,
159
+ source_info : SourceInfo ,
160
+ block : BasicBlock ,
161
+ ) -> BlockMarkerId {
162
+ let id = self . next_block_marker_id ( ) ;
163
+
164
+ let marker_statement = mir:: Statement {
165
+ source_info,
166
+ kind : mir:: StatementKind :: Coverage ( CoverageKind :: BlockMarker { id } ) ,
167
+ } ;
168
+ cfg. push ( block, marker_statement) ;
169
+
170
+ id
171
+ }
172
+
153
173
pub ( crate ) fn into_done ( self ) -> Option < Box < mir:: coverage:: BranchInfo > > {
154
174
let Self {
155
175
nots : _,
156
176
num_block_markers,
157
177
branch_spans,
158
178
mcdc_branch_spans,
159
179
mcdc_decision_spans,
160
- ..
180
+ mcdc_state : _ ,
161
181
} = self ;
162
182
163
183
if num_block_markers == 0 {
@@ -325,7 +345,7 @@ impl Builder<'_, '_> {
325
345
mut else_block : BasicBlock ,
326
346
) {
327
347
// Bail out if branch coverage is not enabled for this function.
328
- let Some ( branch_info) = self . coverage_branch_info . as_ref ( ) else { return } ;
348
+ let Some ( branch_info) = self . coverage_branch_info . as_mut ( ) else { return } ;
329
349
330
350
// If this condition expression is nested within one or more `!` expressions,
331
351
// replace it with the enclosing `!` collected by `visit_unary_not`.
@@ -335,47 +355,34 @@ impl Builder<'_, '_> {
335
355
std:: mem:: swap ( & mut then_block, & mut else_block) ;
336
356
}
337
357
}
338
- let source_info = self . source_info ( self . thir [ expr_id] . span ) ;
339
-
340
- // Now that we have `source_info`, we can upgrade to a &mut reference.
341
- let branch_info = self . coverage_branch_info . as_mut ( ) . expect ( "upgrading & to &mut" ) ;
342
-
343
- let mut inject_branch_marker = |block : BasicBlock | {
344
- let id = branch_info. next_block_marker_id ( ) ;
345
-
346
- let marker_statement = mir:: Statement {
347
- source_info,
348
- kind : mir:: StatementKind :: Coverage ( CoverageKind :: BlockMarker { id } ) ,
349
- } ;
350
- self . cfg . push ( block, marker_statement) ;
351
358
352
- id
353
- } ;
354
-
355
- let true_marker = inject_branch_marker ( then_block) ;
356
- let false_marker = inject_branch_marker ( else_block) ;
359
+ let source_info = SourceInfo { span : self . thir [ expr_id] . span , scope : self . source_scope } ;
357
360
358
- if let Some ( condition_info) =
359
- branch_info. fetch_condition_info ( self . tcx , true_marker, false_marker)
360
- {
361
+ // Separate path for handling branches when MC/DC is enabled.
362
+ if branch_info. mcdc_state . is_some ( ) {
363
+ let mut inject_block_marker =
364
+ |block| branch_info. inject_block_marker ( & mut self . cfg , source_info, block) ;
365
+ let true_marker = inject_block_marker ( then_block) ;
366
+ let false_marker = inject_block_marker ( else_block) ;
367
+ let condition_info =
368
+ branch_info. fetch_mcdc_condition_info ( self . tcx , true_marker, false_marker) ;
361
369
branch_info. mcdc_branch_spans . push ( MCDCBranchSpan {
362
370
span : source_info. span ,
363
371
condition_info,
364
372
true_marker,
365
373
false_marker,
366
374
} ) ;
367
- } else {
368
- branch_info. branch_spans . push ( BranchSpan {
369
- span : source_info. span ,
370
- true_marker,
371
- false_marker,
372
- } ) ;
375
+ return ;
373
376
}
377
+
378
+ branch_info. add_two_way_branch ( & mut self . cfg , source_info, then_block, else_block) ;
374
379
}
375
380
376
381
pub ( crate ) fn visit_coverage_branch_operation ( & mut self , logical_op : LogicalOp , span : Span ) {
377
- if let Some ( branch_info) = self . coverage_branch_info . as_mut ( ) {
378
- branch_info. record_conditions_operation ( logical_op, span) ;
382
+ if let Some ( branch_info) = self . coverage_branch_info . as_mut ( )
383
+ && let Some ( mcdc_state) = branch_info. mcdc_state . as_mut ( )
384
+ {
385
+ mcdc_state. record_conditions ( logical_op, span) ;
379
386
}
380
387
}
381
388
}
0 commit comments