coverage: Discard code regions that might cause fatal errors in llvm-cov
This commit is contained in:
parent
190f4c9611
commit
b152de29c5
@ -330,7 +330,7 @@ fn make_code_region(
|
|||||||
start_line = source_map.doctest_offset_line(&file.name, start_line);
|
start_line = source_map.doctest_offset_line(&file.name, start_line);
|
||||||
end_line = source_map.doctest_offset_line(&file.name, end_line);
|
end_line = source_map.doctest_offset_line(&file.name, end_line);
|
||||||
|
|
||||||
Some(CodeRegion {
|
check_code_region(CodeRegion {
|
||||||
file_name,
|
file_name,
|
||||||
start_line: start_line as u32,
|
start_line: start_line as u32,
|
||||||
start_col: start_col as u32,
|
start_col: start_col as u32,
|
||||||
@ -339,6 +339,41 @@ fn make_code_region(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If `llvm-cov` sees a code region that is improperly ordered (end < start),
|
||||||
|
/// it will immediately exit with a fatal error. To prevent that from happening,
|
||||||
|
/// discard regions that are improperly ordered, or might be interpreted in a
|
||||||
|
/// way that makes them improperly ordered.
|
||||||
|
fn check_code_region(code_region: CodeRegion) -> Option<CodeRegion> {
|
||||||
|
let CodeRegion { file_name: _, start_line, start_col, end_line, end_col } = code_region;
|
||||||
|
|
||||||
|
// Line/column coordinates are supposed to be 1-based. If we ever emit
|
||||||
|
// coordinates of 0, `llvm-cov` might misinterpret them.
|
||||||
|
let all_nonzero = [start_line, start_col, end_line, end_col].into_iter().all(|x| x != 0);
|
||||||
|
// Coverage mappings use the high bit of `end_col` to indicate that a
|
||||||
|
// region is actually a "gap" region, so make sure it's unset.
|
||||||
|
let end_col_has_high_bit_unset = (end_col & (1 << 31)) == 0;
|
||||||
|
// If a region is improperly ordered (end < start), `llvm-cov` will exit
|
||||||
|
// with a fatal error, which is inconvenient for users and hard to debug.
|
||||||
|
let is_ordered = (start_line, start_col) <= (end_line, end_col);
|
||||||
|
|
||||||
|
if all_nonzero && end_col_has_high_bit_unset && is_ordered {
|
||||||
|
Some(code_region)
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
?code_region,
|
||||||
|
?all_nonzero,
|
||||||
|
?end_col_has_high_bit_unset,
|
||||||
|
?is_ordered,
|
||||||
|
"Skipping code region that would be misinterpreted or rejected by LLVM"
|
||||||
|
);
|
||||||
|
if cfg!(debug_assertions) {
|
||||||
|
// If this happens in a debug build, ICE to make it easier to notice.
|
||||||
|
bug!("Improper code region: {code_region:?}");
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||||
// Only instrument functions, methods, and closures (not constants since they are evaluated
|
// Only instrument functions, methods, and closures (not constants since they are evaluated
|
||||||
// at compile time by Miri).
|
// at compile time by Miri).
|
||||||
|
Loading…
Reference in New Issue
Block a user