[clang] [Coverage] Skip coverage mapping for consteval member functions (PR #190870)

Paweł Bylica via cfe-commits cfe-commits at lists.llvm.org
Tue Apr 7 16:11:25 PDT 2026


https://github.com/chfast created https://github.com/llvm/llvm-project/pull/190870

Static consteval member functions were incorrectly getting a coverage mapping with zero count, making them appear as uncovered lines. Free consteval functions were already correctly excluded because EmitTopLevelDecl returns early for immediate functions.

The fix adds an isImmediateFunction() check in HandleInlineMemberFunction before adding deferred coverage mappings, consistent with the top-level check.

Fixes #164448.

>From a66bb02fcc09e2d6b1e7c9f3645d1d036b30cf40 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Bylica?= <pawel at hepcolgum.band>
Date: Wed, 8 Apr 2026 00:59:25 +0200
Subject: [PATCH] [Coverage] Skip coverage mapping for consteval member
 functions

Static consteval member functions were incorrectly getting a coverage
mapping with zero count, making them appear as uncovered lines.
Free consteval functions were already correctly excluded because
EmitTopLevelDecl returns early for immediate functions.

The fix adds an isImmediateFunction() check in HandleInlineMemberFunction
before adding deferred coverage mappings, consistent with the top-level
check.

Fixes #164448.
---
 clang/lib/CodeGen/ModuleBuilder.cpp      |  5 +++--
 clang/test/CoverageMapping/consteval.cpp | 21 +++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CoverageMapping/consteval.cpp

diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp
index dd6b3c904d03d..1888de4521abd 100644
--- a/clang/lib/CodeGen/ModuleBuilder.cpp
+++ b/clang/lib/CodeGen/ModuleBuilder.cpp
@@ -228,8 +228,9 @@ namespace {
 
       // Provide some coverage mapping even for methods that aren't emitted.
       // Don't do this for templated classes though, as they may not be
-      // instantiable.
-      if (!D->getLexicalDeclContext()->isDependentContext())
+      // instantiable. Also skip consteval methods as they are never emitted.
+      if (!D->getLexicalDeclContext()->isDependentContext() &&
+          !D->getAsFunction()->isImmediateFunction())
         Builder->AddDeferredUnusedCoverageMapping(D);
     }
 
diff --git a/clang/test/CoverageMapping/consteval.cpp b/clang/test/CoverageMapping/consteval.cpp
new file mode 100644
index 0000000000000..3540d52011955
--- /dev/null
+++ b/clang/test/CoverageMapping/consteval.cpp
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -mllvm -emptyline-comment-coverage=false -fprofile-instrument=clang -fcoverage-mapping -dump-coverage-mapping -emit-llvm-only -std=c++20 -triple %itanium_abi_triple -main-file-name consteval.cpp %s | FileCheck %s
+
+// Consteval functions should not have coverage mappings, as they are evaluated
+// entirely at compile time and produce no runtime code.
+// See https://github.com/llvm/llvm-project/issues/164448.
+
+// CHECK-NOT: _Z1gv:
+consteval int g() { return 0; }
+
+struct S {
+  // CHECK-NOT: _ZN1S1sEv:
+  static consteval int s() { return 1; }
+};
+
+// CHECK-LABEL: main:
+// CHECK-NEXT: File 0, [[@LINE+1]]:12 -> [[@LINE+5]]:2 = #0
+int main() {
+  [[maybe_unused]] auto i = g();
+  [[maybe_unused]] auto j = S::s();
+  return 0;
+}



More information about the cfe-commits mailing list