Author: Justin Cady Date: 2025-05-19T15:49:26-04:00 New Revision: 025639bc396f1e0d2ead279c5f345cb381733f16
URL: https://github.com/llvm/llvm-project/commit/025639bc396f1e0d2ead279c5f345cb381733f16 DIFF: https://github.com/llvm/llvm-project/commit/025639bc396f1e0d2ead279c5f345cb381733f16.diff LOG: [Coverage] Fix mapping for do-while loops with terminating statements (#139777) 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 Added: compiler-rt/test/profile/Linux/coverage-do-while.c Modified: clang/lib/CodeGen/CoverageMappingGen.cpp clang/test/CoverageMapping/terminate-statements.cpp Removed: ################################################################################ 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits