-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Coverage] Fix mapping for do-while loops with terminating statements #139777
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
The current region mapping for do-while loops that contain statements such as break or continue results in inaccurate line coverage reports for the line following the loop. This change handles terminating statements the same way that other loop constructs do, correcting the region mapping for accurate reports. It also fixes a fragile test relying on exact line numbers. Fixes llvm#139122
@llvm/pr-subscribers-clang-codegen @llvm/pr-subscribers-pgo Author: Justin Cady (justincady) ChangesThe current region mapping for do-while loops that contain statements This change handles terminating statements the same way that other loop Fixes #139122 Full diff: https://github.com/llvm/llvm-project/pull/139777.diff 3 Files Affected:
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..6170dc7f59107 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1703,14 +1703,13 @@ struct CounterCoverageMappingBuilder
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
}
// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
-
- if (BodyHasTerminateStmt)
- HasTerminateStmt = true;
}
void VisitForStmt(const ForStmt *S) {
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp b/clang/test/CoverageMapping/terminate-statements.cpp
index ef6b6fd82687d..93d655794ccf5 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -348,10 +348,20 @@ int elsecondnoret(void) {
// CHECK-LABEL: _Z18statementexprnoretb:
int statementexprnoret(bool crash) {
- int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = (#0 - #1)
+ int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, [[@LINE]]:35 -> [[@LINE+1]]:12 = (#0 - #1)
return rc; // CHECK-NOT: Gap
}
+// CHECK-LABEL: _Z13do_with_breaki:
+int do_with_break(int n) {
+ do {
+ if (n == 87) {
+ break;
+ } // CHECK: File 0, [[@LINE-2]]:18 -> [[@LINE]]:6 = #2
+ } while (0); // CHECK: File 0, [[@LINE]]:12 -> [[@LINE]]:13 = ((#0 + #1) - #2)
+ return 0; // CHECK-NOT: Gap,File 0, [[@LINE-1]]:15
+}
+
int main() {
foo(0);
foo(1);
@@ -375,5 +385,6 @@ int main() {
abstractcondnoret();
elsecondnoret();
statementexprnoret(false);
+ do_with_break(0);
return 0;
}
diff --git a/compiler-rt/test/profile/Linux/coverage-do-while.c b/compiler-rt/test/profile/Linux/coverage-do-while.c
new file mode 100644
index 0000000000000..9e112cbc4c6a3
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-do-while.c
@@ -0,0 +1,21 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+// clang-format off
+int main(int argc, char **argv) { // CHECK: [[@LINE]]| 1|int main(
+ do { // CHECK: [[@LINE]]| 1| do {
+ if (argc == 87) { // CHECK: [[@LINE]]| 1| if (argc
+ break; // CHECK: [[@LINE]]| 0| break
+ } // CHECK: [[@LINE]]| 0| }
+ } while (0); // CHECK: [[@LINE]]| 1| } while
+ printf("coverage after do is present\n"); // CHECK: [[@LINE]]| 1| printf(
+ return 0; // CHECK: [[@LINE]]| 1| return
+} // CHECK: [[@LINE]]| 1|}
+// clang-format on
|
@llvm/pr-subscribers-clang Author: Justin Cady (justincady) ChangesThe current region mapping for do-while loops that contain statements This change handles terminating statements the same way that other loop Fixes #139122 Full diff: https://github.com/llvm/llvm-project/pull/139777.diff 3 Files Affected:
diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 73811d15979d5..6170dc7f59107 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -1703,14 +1703,13 @@ struct CounterCoverageMappingBuilder
if (!IsCounterEqual(OutCount, ParentCount)) {
pushRegion(OutCount);
GapRegionCounter = OutCount;
+ if (BodyHasTerminateStmt)
+ HasTerminateStmt = true;
}
// Create Branch Region around condition.
if (!llvm::EnableSingleByteCoverage)
createBranchRegion(S->getCond(), BodyCount, BranchCount.Skipped);
-
- if (BodyHasTerminateStmt)
- HasTerminateStmt = true;
}
void VisitForStmt(const ForStmt *S) {
diff --git a/clang/test/CoverageMapping/terminate-statements.cpp b/clang/test/CoverageMapping/terminate-statements.cpp
index ef6b6fd82687d..93d655794ccf5 100644
--- a/clang/test/CoverageMapping/terminate-statements.cpp
+++ b/clang/test/CoverageMapping/terminate-statements.cpp
@@ -348,10 +348,20 @@ int elsecondnoret(void) {
// CHECK-LABEL: _Z18statementexprnoretb:
int statementexprnoret(bool crash) {
- int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, 351:35 -> 352:12 = (#0 - #1)
+ int rc = ({ if (crash) abort(); 0; }); // CHECK: File 0, [[@LINE]]:35 -> [[@LINE+1]]:12 = (#0 - #1)
return rc; // CHECK-NOT: Gap
}
+// CHECK-LABEL: _Z13do_with_breaki:
+int do_with_break(int n) {
+ do {
+ if (n == 87) {
+ break;
+ } // CHECK: File 0, [[@LINE-2]]:18 -> [[@LINE]]:6 = #2
+ } while (0); // CHECK: File 0, [[@LINE]]:12 -> [[@LINE]]:13 = ((#0 + #1) - #2)
+ return 0; // CHECK-NOT: Gap,File 0, [[@LINE-1]]:15
+}
+
int main() {
foo(0);
foo(1);
@@ -375,5 +385,6 @@ int main() {
abstractcondnoret();
elsecondnoret();
statementexprnoret(false);
+ do_with_break(0);
return 0;
}
diff --git a/compiler-rt/test/profile/Linux/coverage-do-while.c b/compiler-rt/test/profile/Linux/coverage-do-while.c
new file mode 100644
index 0000000000000..9e112cbc4c6a3
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/coverage-do-while.c
@@ -0,0 +1,21 @@
+// REQUIRES: lld-available
+// XFAIL: powerpc64-target-arch
+
+// RUN: %clangxx_profgen -fuse-ld=lld -fcoverage-mapping -o %t %s
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t
+// RUN: llvm-profdata merge -o %t.profdata %t.profraw
+// RUN: llvm-cov show %t -instr-profile=%t.profdata 2>&1 | FileCheck %s
+
+#include <stdio.h>
+
+// clang-format off
+int main(int argc, char **argv) { // CHECK: [[@LINE]]| 1|int main(
+ do { // CHECK: [[@LINE]]| 1| do {
+ if (argc == 87) { // CHECK: [[@LINE]]| 1| if (argc
+ break; // CHECK: [[@LINE]]| 0| break
+ } // CHECK: [[@LINE]]| 0| }
+ } while (0); // CHECK: [[@LINE]]| 1| } while
+ printf("coverage after do is present\n"); // CHECK: [[@LINE]]| 1| printf(
+ return 0; // CHECK: [[@LINE]]| 1| return
+} // CHECK: [[@LINE]]| 1|}
+// clang-format on
|
Thank you for looking at this! |
The current region mapping for do-while loops that contain statements
such as break or continue results in inaccurate line coverage reports
for the line following the loop.
This change handles terminating statements the same way that other loop
constructs do, correcting the region mapping for accurate reports. It
also fixes a fragile test relying on exact line numbers.
Fixes #139122