[clang] [Coverage] Add a new flag to split region after every call. (PR #90031)

via cfe-commits cfe-commits at lists.llvm.org
Thu Apr 25 01:04:26 PDT 2024


https://github.com/c01db33f created https://github.com/llvm/llvm-project/pull/90031

This helps with displaying more precise coverage when a function causes the program to exit, crashes, or similar. For example, using this flag should address the case listed in the documentation under "Drawbacks and limitations":

```
int f() {
  may_throw();
  return 0;
}
```

If the call to `may_throw` propagates an exception into `f`, the `return` statement should not be marked as executed.

This change adds a significant number of basic blocks, so likely has a performance and size overhead, so I've not made it the default behaviour.

>From d534e1b04d7b2d9faf8fb10f4f6e44b99b3cbb45 Mon Sep 17 00:00:00 2001
From: Mark Brand <markbrand at google.com>
Date: Wed, 24 Apr 2024 17:44:34 +0200
Subject: [PATCH] [Coverage] Add a new flag to split region after every call.

This helps with displaying more precise coverage when a function
causes the program to exit, crashes, or similar. For example,
using this flag should address the case listed in the documentation
under "Drawbacks and limitations":

```
int f() {
  may_throw();
  return 0;
}
```

If the call to `may_throw` propagates an exception into `f`, the
`return` statement should not be marked as executed.

This change adds a significant number of basic blocks, so likely
has a performance and size overhead, so I've not made it the
default behaviour.
---
 clang/lib/CodeGen/CoverageMappingGen.cpp     |  7 ++++-
 clang/test/CoverageMapping/branch-return.cpp | 31 ++++++++++++++++++++
 2 files changed, 37 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/CoverageMapping/branch-return.cpp

diff --git a/clang/lib/CodeGen/CoverageMappingGen.cpp b/clang/lib/CodeGen/CoverageMappingGen.cpp
index 733686d4946b3c..32fdfb0d35063b 100644
--- a/clang/lib/CodeGen/CoverageMappingGen.cpp
+++ b/clang/lib/CodeGen/CoverageMappingGen.cpp
@@ -45,6 +45,11 @@ static llvm::cl::opt<bool> EmptyLineCommentCoverage(
                    "disable it on test)"),
     llvm::cl::init(true), llvm::cl::Hidden);
 
+static llvm::cl::opt<bool> CallsEndCoverageRegion(
+    "calls-end-coverage-region",
+    llvm::cl::desc("Force a coverage region end after every call expression"),
+    llvm::cl::init(false), llvm::cl::Hidden);
+
 llvm::cl::opt<bool> SystemHeadersCoverage(
     "system-headers-coverage",
     llvm::cl::desc("Enable collecting coverage from system headers"),
@@ -1484,7 +1489,7 @@ struct CounterCoverageMappingBuilder
     // Terminate the region when we hit a noreturn function.
     // (This is helpful dealing with switch statements.)
     QualType CalleeType = E->getCallee()->getType();
-    if (getFunctionExtInfo(*CalleeType).getNoReturn())
+    if (CallsEndCoverageRegion || getFunctionExtInfo(*CalleeType).getNoReturn())
       terminateRegion(E);
   }
 
diff --git a/clang/test/CoverageMapping/branch-return.cpp b/clang/test/CoverageMapping/branch-return.cpp
new file mode 100644
index 00000000000000..16c1b88607d590
--- /dev/null
+++ b/clang/test/CoverageMapping/branch-return.cpp
@@ -0,0 +1,31 @@
+// Test that branch regions are generated for return paths when calls-end-coverage-region is set.
+
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -main-file-name branch-return.cpp %s | FileCheck %s -check-prefix=WITHOUT
+// RUN: %clang_cc1 -triple %itanium_abi_triple -std=c++11 -fprofile-instrument=clang -fcoverage-mapping -mllvm -calls-end-coverage-region -dump-coverage-mapping -emit-llvm-only -main-file-name branch-return.cpp %s | FileCheck %s -check-prefix=WITH
+
+// CHECK-LABEL: _Z5func1ii:
+// WITHOUT: File 0, [[@LINE+2]]:26 -> [[@LINE+4]]:2 = #0
+// WITH: File 0, [[@LINE+1]]:26 -> [[@LINE+3]]:2 = #0
+bool func1(int a, int b) {
+  return (a | b) < 100;
+}
+
+// CHECK-LABEL: _Z5func2ii:
+// WITHOUT: File 0, [[@LINE+2]]:26 -> [[@LINE+4]]:2 = #0
+// WITH: File 0, [[@LINE+1]]:26 -> [[@LINE+3]]:2 = #0
+bool func2(int a, int b) {
+  return (a ^ b) > 10;
+}
+
+// CHECK-LABEL: _Z5func3ii:
+// WITHOUT: File 0, [[@LINE+6]]:26 -> [[@LINE+10]]:2 = #0
+// WITH: File 0, [[@LINE+5]]:26 -> [[@LINE+9]]:2 = #0
+// WITH: Gap,File 0, [[@LINE+5]]:27 -> [[@LINE+6]]:3 = 0
+// WITH: File 0, [[@LINE+5]]:3 -> [[@LINE+5]]:26 = 0
+// WITH: Gap,File 0, [[@LINE+4]]:27 -> [[@LINE+5]]:3 = 0
+// WITH: File 0, [[@LINE+4]]:3 -> [[@LINE+4]]:22 = 0
+bool func3(int a, int b) {
+  bool val1 = func1(a, b);
+  bool val2 = func2(a, b);
+  return val1 || val2;
+}



More information about the cfe-commits mailing list