@@ -7,13 +7,13 @@ use rustc_middle::mir::coverage::{
77 BlockMarkerId , BranchSpan , ConditionId , ConditionInfo , CoverageKind , MCDCBranchSpan ,
88 MCDCDecisionSpan ,
99} ;
10- use rustc_middle:: mir:: { self , BasicBlock , UnOp } ;
10+ use rustc_middle:: mir:: { self , BasicBlock , SourceInfo , UnOp } ;
1111use rustc_middle:: thir:: { ExprId , ExprKind , LogicalOp , Thir } ;
1212use rustc_middle:: ty:: TyCtxt ;
1313use rustc_span:: def_id:: LocalDefId ;
1414use rustc_span:: Span ;
1515
16- use crate :: build:: Builder ;
16+ use crate :: build:: { Builder , CFG } ;
1717use crate :: errors:: MCDCExceedsConditionNumLimit ;
1818
1919pub ( crate ) struct BranchInfoBuilder {
@@ -22,6 +22,7 @@ pub(crate) struct BranchInfoBuilder {
2222
2323 num_block_markers : usize ,
2424 branch_spans : Vec < BranchSpan > ,
25+
2526 mcdc_branch_spans : Vec < MCDCBranchSpan > ,
2627 mcdc_decision_spans : Vec < MCDCDecisionSpan > ,
2728 mcdc_state : Option < MCDCState > ,
@@ -95,13 +96,7 @@ impl BranchInfoBuilder {
9596 }
9697 }
9798
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 (
105100 & mut self ,
106101 tcx : TyCtxt < ' _ > ,
107102 true_marker : BlockMarkerId ,
@@ -121,14 +116,9 @@ impl BranchInfoBuilder {
121116 _ => {
122117 // Do not generate mcdc mappings and statements for decisions with too many conditions.
123118 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+ }
132122
133123 // ConditionInfo of this branch shall also be reset.
134124 condition_info = None ;
@@ -144,20 +134,50 @@ impl BranchInfoBuilder {
144134 condition_info
145135 }
146136
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+
147150 fn next_block_marker_id ( & mut self ) -> BlockMarkerId {
148151 let id = BlockMarkerId :: from_usize ( self . num_block_markers ) ;
149152 self . num_block_markers += 1 ;
150153 id
151154 }
152155
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+
153173 pub ( crate ) fn into_done ( self ) -> Option < Box < mir:: coverage:: BranchInfo > > {
154174 let Self {
155175 nots : _,
156176 num_block_markers,
157177 branch_spans,
158178 mcdc_branch_spans,
159179 mcdc_decision_spans,
160- ..
180+ mcdc_state : _ ,
161181 } = self ;
162182
163183 if num_block_markers == 0 {
@@ -325,7 +345,7 @@ impl Builder<'_, '_> {
325345 mut else_block : BasicBlock ,
326346 ) {
327347 // 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 } ;
329349
330350 // If this condition expression is nested within one or more `!` expressions,
331351 // replace it with the enclosing `!` collected by `visit_unary_not`.
@@ -335,47 +355,34 @@ impl Builder<'_, '_> {
335355 std:: mem:: swap ( & mut then_block, & mut else_block) ;
336356 }
337357 }
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) ;
351358
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 } ;
357360
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) ;
361369 branch_info. mcdc_branch_spans . push ( MCDCBranchSpan {
362370 span : source_info. span ,
363371 condition_info,
364372 true_marker,
365373 false_marker,
366374 } ) ;
367- } else {
368- branch_info. branch_spans . push ( BranchSpan {
369- span : source_info. span ,
370- true_marker,
371- false_marker,
372- } ) ;
375+ return ;
373376 }
377+
378+ branch_info. add_two_way_branch ( & mut self . cfg , source_info, then_block, else_block) ;
374379 }
375380
376381 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) ;
379386 }
380387 }
381388}
0 commit comments