@@ -330,7 +330,7 @@ fn make_code_region(
330330 start_line = source_map. doctest_offset_line ( & file. name , start_line) ;
331331 end_line = source_map. doctest_offset_line ( & file. name , end_line) ;
332332
333- Some ( CodeRegion {
333+ check_code_region ( CodeRegion {
334334 file_name,
335335 start_line : start_line as u32 ,
336336 start_col : start_col as u32 ,
@@ -339,6 +339,37 @@ fn make_code_region(
339339 } )
340340}
341341
342+ /// If `llvm-cov` sees a code region that is improperly ordered (end < start),
343+ /// it will immediately exit with a fatal error. To prevent that from happening,
344+ /// discard regions that are improperly ordered, or might be interpreted in a
345+ /// way that makes them improperly ordered.
346+ fn check_code_region ( code_region : CodeRegion ) -> Option < CodeRegion > {
347+ let CodeRegion { file_name : _, start_line, start_col, end_line, end_col } = code_region;
348+
349+ // Line/column coordinates are supposed to be 1-based. If we ever emit
350+ // coordinates of 0, `llvm-cov` might misinterpret them.
351+ let all_nonzero = [ start_line, start_col, end_line, end_col] . into_iter ( ) . all ( |x| x != 0 ) ;
352+ // Coverage mappings use the high bit of `end_col` to indicate that a
353+ // region is actually a "gap" region, so make sure it's unset.
354+ let end_col_has_high_bit_unset = ( end_col & ( 1 << 31 ) ) == 0 ;
355+ // If a region is improperly ordered (end < start), `llvm-cov` will exit
356+ // with a fatal error, which is inconvenient for users and hard to debug.
357+ let is_ordered = ( start_line, start_col) <= ( end_line, end_col) ;
358+
359+ if all_nonzero && end_col_has_high_bit_unset && is_ordered {
360+ Some ( code_region)
361+ } else {
362+ debug ! (
363+ ?code_region,
364+ ?all_nonzero,
365+ ?end_col_has_high_bit_unset,
366+ ?is_ordered,
367+ "Skipping code region that would be misinterpreted or rejected by LLVM"
368+ ) ;
369+ None
370+ }
371+ }
372+
342373fn is_eligible_for_coverage ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> bool {
343374 // Only instrument functions, methods, and closures (not constants since they are evaluated
344375 // at compile time by Miri).
0 commit comments