@@ -103,9 +103,12 @@ impl BranchInfoBuilder {
103
103
false_marker : BlockMarkerId ,
104
104
) -> Option < ( u16 , ConditionInfo ) > {
105
105
let mcdc_state = self . mcdc_state . as_mut ( ) ?;
106
- let decision_depth = mcdc_state. decision_depth ;
106
+ let decision_depth = mcdc_state. decision_depth ( ) ;
107
107
let ( mut condition_info, decision_result) =
108
108
mcdc_state. take_condition ( true_marker, false_marker) ;
109
+ // take_condition() returns Some for decision_result when the decision stack
110
+ // is empty, i.e. when all the conditions of the decision were instrumented,
111
+ // and the decision is "complete".
109
112
if let Some ( decision) = decision_result {
110
113
match decision. conditions_num {
111
114
0 => {
@@ -200,20 +203,27 @@ impl BranchInfoBuilder {
200
203
/// This limit may be relaxed if the [upstream change](https://github.com/llvm/llvm-project/pull/82448) is merged.
201
204
const MAX_CONDITIONS_NUM_IN_DECISION : usize = 6 ;
202
205
203
- struct MCDCState {
206
+ #[ derive( Default ) ]
207
+ struct MCDCDecisionCtx {
204
208
/// To construct condition evaluation tree.
205
209
decision_stack : VecDeque < ConditionInfo > ,
206
210
processing_decision : Option < MCDCDecisionSpan > ,
207
- decision_depth : u16 ,
211
+ }
212
+
213
+ struct MCDCState {
214
+ decision_ctx_stack : Vec < MCDCDecisionCtx > ,
208
215
}
209
216
210
217
impl MCDCState {
211
218
fn new_if_enabled ( tcx : TyCtxt < ' _ > ) -> Option < Self > {
212
- tcx. sess . instrument_coverage_mcdc ( ) . then ( || Self {
213
- decision_stack : VecDeque :: new ( ) ,
214
- processing_decision : None ,
215
- decision_depth : 0 ,
216
- } )
219
+ tcx. sess
220
+ . instrument_coverage_mcdc ( )
221
+ . then ( || Self { decision_ctx_stack : vec ! [ MCDCDecisionCtx :: default ( ) ] } )
222
+ }
223
+
224
+ #[ inline]
225
+ fn decision_depth ( & self ) -> u16 {
226
+ ( self . decision_ctx_stack . len ( ) - 1 ) as u16
217
227
}
218
228
219
229
// At first we assign ConditionIds for each sub expression.
@@ -257,20 +267,23 @@ impl MCDCState {
257
267
// - If the op is AND, the "false_next" of LHS and RHS should be the parent's "false_next". While "true_next" of the LHS is the RHS, the "true next" of RHS is the parent's "true_next".
258
268
// - If the op is OR, the "true_next" of LHS and RHS should be the parent's "true_next". While "false_next" of the LHS is the RHS, the "false next" of RHS is the parent's "false_next".
259
269
fn record_conditions ( & mut self , op : LogicalOp , span : Span ) {
260
- let decision = match self . processing_decision . as_mut ( ) {
270
+ let decision_depth = self . decision_depth ( ) ;
271
+ let decision_ctx =
272
+ self . decision_ctx_stack . last_mut ( ) . expect ( "Unexpected empty decision_ctx_stack" ) ;
273
+ let decision = match decision_ctx. processing_decision . as_mut ( ) {
261
274
Some ( decision) => {
262
275
decision. span = decision. span . to ( span) ;
263
276
decision
264
277
}
265
- None => self . processing_decision . insert ( MCDCDecisionSpan {
278
+ None => decision_ctx . processing_decision . insert ( MCDCDecisionSpan {
266
279
span,
267
280
conditions_num : 0 ,
268
281
end_markers : vec ! [ ] ,
269
- decision_depth : 0 ,
282
+ decision_depth : decision_depth ,
270
283
} ) ,
271
284
} ;
272
285
273
- let parent_condition = self . decision_stack . pop_back ( ) . unwrap_or_default ( ) ;
286
+ let parent_condition = decision_ctx . decision_stack . pop_back ( ) . unwrap_or_default ( ) ;
274
287
let lhs_id = if parent_condition. condition_id == ConditionId :: NONE {
275
288
decision. conditions_num += 1 ;
276
289
ConditionId :: from ( decision. conditions_num )
@@ -310,19 +323,21 @@ impl MCDCState {
310
323
}
311
324
} ;
312
325
// We visit expressions tree in pre-order, so place the left-hand side on the top.
313
- self . decision_stack . push_back ( rhs) ;
314
- self . decision_stack . push_back ( lhs) ;
326
+ decision_ctx . decision_stack . push_back ( rhs) ;
327
+ decision_ctx . decision_stack . push_back ( lhs) ;
315
328
}
316
329
317
330
fn take_condition (
318
331
& mut self ,
319
332
true_marker : BlockMarkerId ,
320
333
false_marker : BlockMarkerId ,
321
334
) -> ( Option < ConditionInfo > , Option < MCDCDecisionSpan > ) {
322
- let Some ( condition_info) = self . decision_stack . pop_back ( ) else {
335
+ let decision_ctx =
336
+ self . decision_ctx_stack . last_mut ( ) . expect ( "Unexpected empty decision_ctx_stack" ) ;
337
+ let Some ( condition_info) = decision_ctx. decision_stack . pop_back ( ) else {
323
338
return ( None , None ) ;
324
339
} ;
325
- let Some ( decision) = self . processing_decision . as_mut ( ) else {
340
+ let Some ( decision) = decision_ctx . processing_decision . as_mut ( ) else {
326
341
bug ! ( "Processing decision should have been created before any conditions are taken" ) ;
327
342
} ;
328
343
if condition_info. true_next_id == ConditionId :: NONE {
@@ -332,8 +347,8 @@ impl MCDCState {
332
347
decision. end_markers . push ( false_marker) ;
333
348
}
334
349
335
- if self . decision_stack . is_empty ( ) {
336
- ( Some ( condition_info) , self . processing_decision . take ( ) )
350
+ if decision_ctx . decision_stack . is_empty ( ) {
351
+ ( Some ( condition_info) , decision_ctx . processing_decision . take ( ) )
337
352
} else {
338
353
( Some ( condition_info) , None )
339
354
}
@@ -399,15 +414,20 @@ impl Builder<'_, '_> {
399
414
if let Some ( branch_info) = self . coverage_branch_info . as_mut ( )
400
415
&& let Some ( mcdc_state) = branch_info. mcdc_state . as_mut ( )
401
416
{
402
- mcdc_state. decision_depth += 1 ;
417
+ mcdc_state. decision_ctx_stack . push ( MCDCDecisionCtx :: default ( ) ) ;
403
418
} ;
404
419
}
405
420
406
421
pub ( crate ) fn mcdc_decrement_depth_if_enabled ( & mut self ) {
407
422
if let Some ( branch_info) = self . coverage_branch_info . as_mut ( )
408
423
&& let Some ( mcdc_state) = branch_info. mcdc_state . as_mut ( )
409
424
{
410
- mcdc_state. decision_depth -= 1 ;
425
+ #[ allow( unused) ]
426
+ let Some ( MCDCDecisionCtx { decision_stack, processing_decision } ) =
427
+ mcdc_state. decision_ctx_stack . pop ( )
428
+ else {
429
+ bug ! ( "Unexpected empty Decision stack" ) ;
430
+ } ;
411
431
} ;
412
432
}
413
433
}
0 commit comments