about summary refs log tree commit diff
diff options
context:
space:
mode:
authorZalathar <Zalathar@users.noreply.github.com>2023-09-28 15:08:11 +1000
committerZalathar <Zalathar@users.noreply.github.com>2023-10-01 14:44:27 +1100
commit3de082497e4581cb8ba977511dfacc848cffef37 (patch)
tree0bc00f442a091662e150952b6cf1df20f595f2dc
parentb11431edc141295682783e1eaf19633aa2fab6b9 (diff)
downloadrust-3de082497e4581cb8ba977511dfacc848cffef37.tar.gz
rust-3de082497e4581cb8ba977511dfacc848cffef37.zip
coverage: Regression test for functions with unreachable bodies
-rw-r--r--tests/coverage-map/unreachable.cov-map24
-rw-r--r--tests/coverage-map/unreachable.rs37
-rw-r--r--tests/run-coverage/unreachable.coverage38
-rw-r--r--tests/run-coverage/unreachable.rs37
4 files changed, 136 insertions, 0 deletions
diff --git a/tests/coverage-map/unreachable.cov-map b/tests/coverage-map/unreachable.cov-map
new file mode 100644
index 00000000000..495419820c1
--- /dev/null
+++ b/tests/coverage-map/unreachable.cov-map
@@ -0,0 +1,24 @@
+Function name: unreachable::UNREACHABLE_CLOSURE::{closure#0}
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 0f, 27, 00, 49]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 15, 39) to (start + 0, 73)
+
+Function name: unreachable::unreachable_function
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 11, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 17, 1) to (start + 2, 2)
+
+Function name: unreachable::unreachable_intrinsic
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 16, 01, 02, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 22, 1) to (start + 2, 2)
+
diff --git a/tests/coverage-map/unreachable.rs b/tests/coverage-map/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/coverage-map/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}
diff --git a/tests/run-coverage/unreachable.coverage b/tests/run-coverage/unreachable.coverage
new file mode 100644
index 00000000000..fa0ac9ccfa1
--- /dev/null
+++ b/tests/run-coverage/unreachable.coverage
@@ -0,0 +1,38 @@
+   LL|       |#![feature(core_intrinsics)]
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// compile-flags: --edition=2021
+   LL|       |
+   LL|       |// <https://github.com/rust-lang/rust/issues/116171>
+   LL|       |// If we instrument a function for coverage, but all of its counter-increment
+   LL|       |// statements are removed by MIR optimizations, LLVM will think it isn't
+   LL|       |// instrumented and it will disappear from coverage maps and coverage reports.
+   LL|       |// Most MIR opts won't cause this because they tend not to remove statements
+   LL|       |// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+   LL|       |// with `TerminatorKind::Unreachable`.
+   LL|       |
+   LL|       |use std::hint::{black_box, unreachable_unchecked};
+   LL|       |
+   LL|      0|static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+   LL|       |
+   LL|      0|fn unreachable_function() {
+   LL|      0|    unsafe { unreachable_unchecked() }
+   LL|      0|}
+   LL|       |
+   LL|       |// Use an intrinsic to more reliably trigger unreachable-propagation.
+   LL|      0|fn unreachable_intrinsic() {
+   LL|      0|    unsafe { std::intrinsics::unreachable() }
+   LL|      0|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    if black_box(false) {
+   LL|       |        UNREACHABLE_CLOSURE();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_function();
+   LL|       |    }
+   LL|       |    if black_box(false) {
+   LL|       |        unreachable_intrinsic();
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/run-coverage/unreachable.rs b/tests/run-coverage/unreachable.rs
new file mode 100644
index 00000000000..6385bfa160d
--- /dev/null
+++ b/tests/run-coverage/unreachable.rs
@@ -0,0 +1,37 @@
+#![feature(core_intrinsics)]
+#![feature(coverage_attribute)]
+// compile-flags: --edition=2021
+
+// <https://github.com/rust-lang/rust/issues/116171>
+// If we instrument a function for coverage, but all of its counter-increment
+// statements are removed by MIR optimizations, LLVM will think it isn't
+// instrumented and it will disappear from coverage maps and coverage reports.
+// Most MIR opts won't cause this because they tend not to remove statements
+// from bb0, but `UnreachablePropagation` can do so if it sees that bb0 ends
+// with `TerminatorKind::Unreachable`.
+
+use std::hint::{black_box, unreachable_unchecked};
+
+static UNREACHABLE_CLOSURE: fn() = || unsafe { unreachable_unchecked() };
+
+fn unreachable_function() {
+    unsafe { unreachable_unchecked() }
+}
+
+// Use an intrinsic to more reliably trigger unreachable-propagation.
+fn unreachable_intrinsic() {
+    unsafe { std::intrinsics::unreachable() }
+}
+
+#[coverage(off)]
+fn main() {
+    if black_box(false) {
+        UNREACHABLE_CLOSURE();
+    }
+    if black_box(false) {
+        unreachable_function();
+    }
+    if black_box(false) {
+        unreachable_intrinsic();
+    }
+}