@@ -286,7 +286,7 @@ fn make_code_region(
286286 start_line = source_map. doctest_offset_line ( & file. name , start_line) ;
287287 end_line = source_map. doctest_offset_line ( & file. name , end_line) ;
288288 }
289- Some ( CodeRegion {
289+ check_code_region ( CodeRegion {
290290 file_name,
291291 start_line : start_line as u32 ,
292292 start_col : start_col as u32 ,
@@ -295,6 +295,37 @@ fn make_code_region(
295295 } )
296296}
297297
298+ /// If `llvm-cov` sees a code region that is improperly ordered (end < start),
299+ /// it will immediately exit with a fatal error. To prevent that from happening,
300+ /// discard regions that are improperly ordered, or might be interpreted in a
301+ /// way that makes them improperly ordered.
302+ fn check_code_region ( code_region : CodeRegion ) -> Option < CodeRegion > {
303+ let CodeRegion { file_name : _, start_line, start_col, end_line, end_col } = code_region;
304+
305+ // Line/column coordinates are supposed to be 1-based. If we ever emit
306+ // coordinates of 0, `llvm-cov` might misinterpret them.
307+ let all_nonzero = [ start_line, start_col, end_line, end_col] . into_iter ( ) . all ( |x| x != 0 ) ;
308+ // Coverage mappings use the high bit of `end_col` to indicate that a
309+ // region is actually a "gap" region, so make sure it's unset.
310+ let end_col_has_high_bit_unset = ( end_col & ( 1 << 31 ) ) == 0 ;
311+ // If a region is improperly ordered (end < start), `llvm-cov` will exit
312+ // with a fatal error, which is inconvenient for users and hard to debug.
313+ let is_ordered = ( start_line, start_col) <= ( end_line, end_col) ;
314+
315+ if all_nonzero && end_col_has_high_bit_unset && is_ordered {
316+ Some ( code_region)
317+ } else {
318+ debug ! (
319+ ?code_region,
320+ ?all_nonzero,
321+ ?end_col_has_high_bit_unset,
322+ ?is_ordered,
323+ "Skipping code region that would be misinterpreted or rejected by LLVM"
324+ ) ;
325+ None
326+ }
327+ }
328+
298329fn is_eligible_for_coverage ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> bool {
299330 // Only instrument functions, methods, and closures (not constants since they are evaluated
300331 // at compile time by Miri).
0 commit comments