Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[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

Open
wants to merge 1 commit into
base: main
Choose a base branch
Loading
from

Conversation

justincady
Copy link
Contributor

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

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
@justincady justincady marked this pull request as ready for review May 13, 2025 19:19
@llvmbot llvmbot added clang Clang issues not falling into any other category compiler-rt clang:codegen IR generation bugs: mangling, exceptions, etc. PGO Profile Guided Optimizations labels May 13, 2025
@justincady justincady requested a review from MaskRay May 13, 2025 19:20
@llvmbot
Copy link
Member

llvmbot commented May 13, 2025

@llvm/pr-subscribers-clang-codegen

@llvm/pr-subscribers-pgo

Author: Justin Cady (justincady)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/139777.diff

3 Files Affected:

  • (modified) clang/lib/CodeGen/CoverageMappingGen.cpp (+2-3)
  • (modified) clang/test/CoverageMapping/terminate-statements.cpp (+12-1)
  • (added) compiler-rt/test/profile/Linux/coverage-do-while.c (+21)
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

@llvmbot
Copy link
Member

llvmbot commented May 13, 2025

@llvm/pr-subscribers-clang

Author: Justin Cady (justincady)

Changes

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


Full diff: https://github.com/llvm/llvm-project/pull/139777.diff

3 Files Affected:

  • (modified) clang/lib/CodeGen/CoverageMappingGen.cpp (+2-3)
  • (modified) clang/test/CoverageMapping/terminate-statements.cpp (+12-1)
  • (added) compiler-rt/test/profile/Linux/coverage-do-while.c (+21)
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

@justincady justincady requested review from ZequanWu and chapuni May 13, 2025 19:20
@evodius96
Copy link
Contributor

Thank you for looking at this!

@justincady justincady requested a review from evodius96 May 14, 2025 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category compiler-rt PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[coverage] incorrect coverage when a do-while contains break or continue statements
3 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.